📄 font.c
字号:
/* $Id: font.c 26542 2007-04-27 15:26:21Z jimtabor $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/gdi32/object/font.c
* PURPOSE:
* PROGRAMMER:
*
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
#define INITIAL_FAMILY_COUNT 64
/***********************************************************************
* TEXTMETRIC conversion functions.
*/
static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
{
ptmA->tmHeight = ptmW->tmHeight;
ptmA->tmAscent = ptmW->tmAscent;
ptmA->tmDescent = ptmW->tmDescent;
ptmA->tmInternalLeading = ptmW->tmInternalLeading;
ptmA->tmExternalLeading = ptmW->tmExternalLeading;
ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
ptmA->tmWeight = ptmW->tmWeight;
ptmA->tmOverhang = ptmW->tmOverhang;
ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
ptmA->tmItalic = ptmW->tmItalic;
ptmA->tmUnderlined = ptmW->tmUnderlined;
ptmA->tmStruckOut = ptmW->tmStruckOut;
ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
ptmA->tmCharSet = ptmW->tmCharSet;
}
/***********************************************************************
* FONT_mbtowc
*
* Returns a Unicode translation of str. If count is -1 then str is
* assumed to be '\0' terminated, otherwise it contains the number of
* bytes to convert. If plenW is non-NULL, on return it will point to
* the number of WCHARs that have been written. The caller should free
* the returned LPWSTR from the process heap itself.
*/
static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW)
{
UINT cp = CP_ACP;
INT lenW;
LPWSTR strW;
if(count == -1) count = strlen(str);
lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
MultiByteToWideChar(cp, 0, str, count, strW, lenW);
DPRINT1("mapped %s -> %s \n", str, strW);
if(plenW) *plenW = lenW;
return strW;
}
static BOOL FASTCALL
MetricsCharConvert(WCHAR w, UCHAR *b)
{
UNICODE_STRING WString;
WCHAR WBuf[2];
ANSI_STRING AString;
CHAR ABuf[2];
NTSTATUS Status;
if (L'\0' == w)
{
*b = '\0';
}
else
{
WBuf[0] = w;
WBuf[1] = L'\0';
RtlInitUnicodeString(&WString, WBuf);
ABuf[0] = '*';
ABuf[1] = L'\0';
RtlInitAnsiString(&AString, ABuf);
Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
if (! NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
*b = ABuf[0];
}
return TRUE;
}
BOOL FASTCALL
TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw)
{
UNICODE_STRING WString;
WCHAR WBuf[256];
ANSI_STRING AString;
CHAR ABuf[256];
UINT Letter;
NTSTATUS Status;
tma->tmHeight = tmw->tmHeight;
tma->tmAscent = tmw->tmAscent;
tma->tmDescent = tmw->tmDescent;
tma->tmInternalLeading = tmw->tmInternalLeading;
tma->tmExternalLeading = tmw->tmExternalLeading;
tma->tmAveCharWidth = tmw->tmAveCharWidth;
tma->tmMaxCharWidth = tmw->tmMaxCharWidth;
tma->tmWeight = tmw->tmWeight;
tma->tmOverhang = tmw->tmOverhang;
tma->tmDigitizedAspectX = tmw->tmDigitizedAspectX;
tma->tmDigitizedAspectY = tmw->tmDigitizedAspectY;
/* The Unicode FirstChar/LastChar need not correspond to the ANSI
FirstChar/LastChar. For example, if the font contains glyphs for
letters A-Z and an accented version of the letter e, the Unicode
FirstChar would be A and the Unicode LastChar would be the accented
e. If you just translate those to ANSI, the range would become
letters A-E instead of A-Z.
We translate all possible ANSI chars to Unicode and find the first
and last translated character which fall into the Unicode FirstChar/
LastChar range and return the corresponding ANSI char. */
/* Setup an Ansi string containing all possible letters (note: skip '\0' at
the beginning since that would be interpreted as end-of-string, handle
'\0' special later */
for (Letter = 1; Letter < 256; Letter++)
{
ABuf[Letter - 1] = (CHAR) Letter;
WBuf[Letter - 1] = L' ';
}
ABuf[255] = '\0';
WBuf[255] = L'\0';
RtlInitAnsiString(&AString, ABuf);
RtlInitUnicodeString(&WString, WBuf);
/* Find the corresponding Unicode characters */
Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
if (! NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
/* Scan for the first ANSI character which maps to an Unicode character
in the range */
tma->tmFirstChar = '\0';
if (L'\0' != tmw->tmFirstChar)
{
for (Letter = 1; Letter < 256; Letter++)
{
if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
WBuf[Letter - 1] <= tmw->tmLastChar)
{
tma->tmFirstChar = (CHAR) Letter;
break;
}
}
}
/* Scan for the last ANSI character which maps to an Unicode character
in the range */
tma->tmLastChar = '\0';
if (L'\0' != tmw->tmLastChar)
{
for (Letter = 255; 0 < Letter; Letter--)
{
if (tmw->tmFirstChar <= WBuf[Letter - 1] &&
WBuf[Letter - 1] <= tmw->tmLastChar)
{
tma->tmLastChar = (CHAR) Letter;
break;
}
}
}
if (! MetricsCharConvert(tmw->tmDefaultChar, &tma->tmDefaultChar) ||
! MetricsCharConvert(tmw->tmBreakChar, &tma->tmBreakChar))
{
return FALSE;
}
tma->tmItalic = tmw->tmItalic;
tma->tmUnderlined = tmw->tmUnderlined;
tma->tmStruckOut = tmw->tmStruckOut;
tma->tmPitchAndFamily = tmw->tmPitchAndFamily;
tma->tmCharSet = tmw->tmCharSet;
return TRUE;
}
BOOL FASTCALL
NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
{
if (! TextMetricW2A((TEXTMETRICA *) tma, (TEXTMETRICW *) tmw))
{
return FALSE;
}
tma->ntmFlags = tmw->ntmFlags;
tma->ntmSizeEM = tmw->ntmSizeEM;
tma->ntmCellHeight = tmw->ntmCellHeight;
tma->ntmAvgWidth = tmw->ntmAvgWidth;
return TRUE;
}
BOOL FASTCALL
NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
{
if (! NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm))
{
return FALSE;
}
tma->ntmFontSig = tmw->ntmFontSig;
return TRUE;
}
static int FASTCALL
IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
BOOL Unicode)
{
int FontFamilyCount;
int FontFamilySize;
PFONTFAMILYINFO Info;
int Ret = 0;
int i;
ENUMLOGFONTEXA EnumLogFontExA;
NEWTEXTMETRICEXA NewTextMetricExA;
Info = RtlAllocateHeap(GetProcessHeap(), 0,
INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
if (NULL == Info)
{
return 0;
}
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
if (FontFamilyCount < 0)
{
RtlFreeHeap(GetProcessHeap(), 0, Info);
return 0;
}
if (INITIAL_FAMILY_COUNT < FontFamilyCount)
{
FontFamilySize = FontFamilyCount;
RtlFreeHeap(GetProcessHeap(), 0, Info);
Info = RtlAllocateHeap(GetProcessHeap(), 0,
FontFamilyCount * sizeof(FONTFAMILYINFO));
if (NULL == Info)
{
return 0;
}
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
{
RtlFreeHeap(GetProcessHeap(), 0, Info);
return 0;
}
}
for (i = 0; i < FontFamilyCount; i++)
{
if (Unicode)
{
Ret = ((FONTENUMPROCW) EnumProc)(
&Info[i].EnumLogFontEx,
&Info[i].NewTextMetricEx,
Info[i].FontType, lParam);
}
else
{ // Could use EnumLogFontExW2A here?
LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
(LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
(LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
(LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
NewTextMetricExW2A(&NewTextMetricExA,
&Info[i].NewTextMetricEx);
Ret = ((FONTENUMPROCA) EnumProc)(
&EnumLogFontExA,
&NewTextMetricExA,
Info[i].FontType, lParam);
}
}
RtlFreeHeap(GetProcessHeap(), 0, Info);
return Ret;
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
LPARAM lParam, DWORD dwFlags)
{
return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
LPARAM lParam)
{
LOGFONTW LogFont;
ZeroMemory(&LogFont, sizeof(LOGFONTW));
LogFont.lfCharSet = DEFAULT_CHARSET;
if (NULL != lpszFamily)
{
lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
}
return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
LPARAM lParam, DWORD dwFlags)
{
LOGFONTW LogFontW;
LogFontA2W(&LogFontW, lpLogfont);
/* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
return IntEnumFontFamilies(hdc, &LogFontW, lpEnumFontFamExProc, lParam, FALSE);
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
LPARAM lParam)
{
LOGFONTW LogFont;
ZeroMemory(&LogFont, sizeof(LOGFONTW));
LogFont.lfCharSet = DEFAULT_CHARSET;
if (NULL != lpszFamily)
{
MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
}
return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
}
/*
* @implemented
*/
BOOL
STDCALL
GetCharWidthA (
HDC hdc,
UINT iFirstChar,
UINT iLastChar,
LPINT lpBuffer
)
{
DPRINT1("GCWA iFirstChar %x\n",iFirstChar);
return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer );
}
/*
* @implemented
*/
BOOL
STDCALL
GetCharWidth32A(
HDC hdc,
UINT iFirstChar,
UINT iLastChar,
LPINT lpBuffer
)
{
INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
LPSTR str;
LPWSTR wstr;
BOOL ret = TRUE;
DPRINT1("GCW32A iFirstChar %x\n",iFirstChar);
if(count <= 0) return FALSE;
str = HeapAlloc(GetProcessHeap(), 0, count);
for(i = 0; i < count; i++)
str[i] = (BYTE)(iFirstChar + i);
wstr = FONT_mbtowc(str, count, &wlen);
for(i = 0; i < wlen; i++)
{
/* FIXME should be NtGdiGetCharWidthW */
if(!NtGdiGetCharWidth32 (hdc, wstr[i], wstr[i], lpBuffer))
{
ret = FALSE;
break;
}
lpBuffer++;
}
HeapFree(GetProcessHeap(), 0, str);
HeapFree(GetProcessHeap(), 0, wstr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -