Implement EnumFontFamilies(Ex)A/W() and TranslateCharsetInfo()

svn path=/trunk/; revision=8844
This commit is contained in:
Gé van Geldorp 2004-03-23 00:18:54 +00:00
parent 4aae876500
commit c718f507e9
15 changed files with 1335 additions and 318 deletions

View file

@ -37,4 +37,10 @@ HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartServices",0x000
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartGUI",0x00010001,0x00000000
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Userinit",0x00020000,"%SystemRoot%\system32\userinit.exe"
; Font substitutes
; SysFontSubstitutes are also returned by EnumFontFamilies, FontSubstitutes aren't
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes","Arial",0x00000000,"Bitstream Vera Sans"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes","Courier New",0x00000000,"Bitstream Vera Sans Mono"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes","Times New Roman",0x00000000,"Bitstream Vera Serif"
; EOF

View file

@ -66,8 +66,6 @@ NtGdiEndDoc 1
NtGdiEndPage 1
NtGdiEndPath 1
NtGdiEnumEnhMetaFile 5
NtGdiEnumFontFamilies 4
NtGdiEnumFontFamiliesEx 5
NtGdiEnumFonts 4
NtGdiEnumICMProfiles 3
NtGdiEnumMetaFile 4
@ -126,6 +124,7 @@ NtGdiGetEnhMetaFileDescription 3
NtGdiGetEnhMetaFileHeader 3
NtGdiGetEnhMetaFilePaletteEntries 3
NtGdiGetEnhMetaFilePixelFormat 3
NtGdiGetFontFamilyInfo 4
NtGdiGetFontLanguageInfo 1
#NtGdiGetFontResourceInfo ?
NtGdiGetGlyphOutline 7

View file

@ -468,10 +468,12 @@ extern "C" {
#define SYMBOL_CHARSET (2)
#define SHIFTJIS_CHARSET (128)
#define HANGEUL_CHARSET (129)
#define JOHAB_CHARSET (130)
#define GB2312_CHARSET (134)
#define CHINESEBIG5_CHARSET (136)
#define GREEK_CHARSET (161)
#define TURKISH_CHARSET (162)
#define VIETNAMESE_CHARSET (163)
#define HEBREW_CHARSET (177)
#define ARABIC_CHARSET (178)
#define BALTIC_CHARSET (186)
@ -3276,6 +3278,18 @@ extern "C" {
#define PAN_XHEIGHT_DUCKING_SMALL (5)
#define PAN_XHEIGHT_DUCKING_STD (6)
#define PAN_XHEIGHT_DUCKING_LARGE (7)
#define PANOSE_COUNT (10)
#define PAN_FAMILYTYPE_INDEX (0)
#define PAN_SERIFSTYLE_INDEX (1)
#define PAN_WEIGTH_INDEX (2)
#define PAN_PROPORTION_INDEX (3)
#define PAN_CONTRAST_INDEX (4)
#define PAN_STROKEVARIATION_INDEX (5)
#define PAN_ARMSTYLE_INDEX (6)
#define PAN_LETTERFORM_INDEX (7)
#define PAN_MIDLINE_INDEX (8)
#define PAN_XHEIGHT_INDEX (9)
#define PAN_CULTURE_LATIN (0)
/* PALETTENTRY structure */
#define PC_EXPLICIT (2)
@ -4777,6 +4791,11 @@ extern "C" {
#define TMPF_TRUETYPE (0x4)
#define TMPF_DEVICE (0x8)
/* NEWTEXTMETRIC structure */
#define NTM_ITALIC (0x01)
#define NTM_BOLD (0x20)
#define NTM_REGULAR (0x40)
/* CopyFileEx options */
#define COPY_FILE_FAIL_IF_EXISTS (1)

View file

@ -3634,13 +3634,13 @@ typedef struct tagNEWTEXTMETRICW {
typedef_tident(NEWTEXTMETRIC)
typedef struct tagNEWTEXTMETRICEXA {
NEWTEXTMETRICA ntmentm;
FONTSIGNATURE ntmeFontSignature;
NEWTEXTMETRICA ntmTm;
FONTSIGNATURE ntmFontSig;
} NEWTEXTMETRICEXA;
typedef struct tagNEWTEXTMETRICEXW {
NEWTEXTMETRICW ntmentm;
FONTSIGNATURE ntmeFontSignature;
NEWTEXTMETRICW ntmTm;
FONTSIGNATURE ntmFontSig;
} NEWTEXTMETRICEXW;
typedef_tident(NEWTEXTMETRICEX)

View file

@ -0,0 +1,26 @@
/* $Id: font.h,v 1.1 2004/03/23 00:18:54 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: include/win32k/font.h
* PURPOSE: GDI32/Win32k font interface
* PROGRAMMER:
*
*/
#ifndef WIN32K_FONT_H_INCLUDED
#define WIN32K_FONT_H_INCLUDED
#include <windows.h>
typedef struct tagFONTFAMILYINFO
{
ENUMLOGFONTEXW EnumLogFontEx;
NEWTEXTMETRICEXW NewTextMetricEx;
DWORD FontType;
} FONTFAMILYINFO, *PFONTFAMILYINFO;
int STDCALL NtGdiGetFontFamilyInfo(HDC Dc, LPLOGFONTW LogFont, PFONTFAMILYINFO Info, DWORD Size);
BOOL STDCALL NtGdiTranslateCharsetInfo(PDWORD Src, LPCHARSETINFO CSI, DWORD Flags);
#endif /* WIN32K_FONT_H_INCLUDED */

View file

@ -9,6 +9,7 @@
#include <win32k/dc.h>
#include <win32k/debug.h>
#include <win32k/fillshap.h>
#include <win32k/font.h>
#include <win32k/icm.h>
#include <win32k/line.h>
#include <win32k/metafile.h>

View file

@ -53,21 +53,6 @@ NtGdiCreateScalableFontResource(DWORD Hidden,
LPCWSTR FontFile,
LPCWSTR CurrentPath);
int
STDCALL
NtGdiEnumFontFamilies(HDC hDC,
LPCWSTR Family,
FONTENUMPROCW EnumFontFamProc,
LPARAM lParam);
int
STDCALL
NtGdiEnumFontFamiliesEx(HDC hDC,
LPLOGFONTW Logfont,
FONTENUMEXPROCW EnumFontFamExProc,
LPARAM lParam,
DWORD Flags);
int
STDCALL
NtGdiEnumFonts(HDC hDC,
@ -250,11 +235,5 @@ NtGdiTextOut(HDC hDC,
LPCWSTR String,
int Count);
UINT
STDCALL
NtGdiTranslateCharsetInfo(PDWORD Src,
LPCHARSETINFO CSI,
DWORD Flags);
#endif

View file

@ -0,0 +1,21 @@
/* $Id: font.h,v 1.1 2004/03/23 00:18:54 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/gdi32/include/internal/font.h
* PURPOSE:
* PROGRAMMER:
*
*/
#ifndef GDI32_FONT_H_INCLUDED
#define GDI32_FONT_H_INCLUDED
#include <windows.h>
BOOL FASTCALL TextMetricW2A(TEXTMETRICA *tma, TEXTMETRICW *tmw);
BOOL FASTCALL NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw);
BOOL FASTCALL NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw);
#endif

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.35 2003/11/16 22:44:39 sedwards Exp $
# $Id: makefile,v 1.36 2004/03/23 00:18:54 gvg Exp $
PATH_TO_TOP = ../..
@ -38,6 +38,7 @@ OBJECTS_OBJECTS = \
objects/clip.o \
objects/dc.o \
objects/fillshap.o \
objects/font.o \
objects/line.o \
objects/linedda.o \
objects/metafile.o \

View file

@ -1,4 +1,4 @@
/* $Id: stubs.c,v 1.49 2004/02/14 00:31:38 sedwards Exp $
/* $Id: stubs.c,v 1.50 2004/03/23 00:18:54 gvg Exp $
*
* reactos/lib/gdi32/misc/stubs.c
*
@ -380,22 +380,6 @@ GetTextCharsetInfo(
}
/*
* @unimplemented
*/
BOOL
STDCALL
TranslateCharsetInfo(
DWORD FAR *lpSrc,
LPCHARSETINFO lpCs,
DWORD dwFlags
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* @unimplemented
*/

View file

@ -1,4 +1,4 @@
/* $Id: stubsa.c,v 1.27 2004/01/24 08:23:12 ekohl Exp $
/* $Id: stubsa.c,v 1.28 2004/03/23 00:18:54 gvg Exp $
*
* reactos/lib/gdi32/misc/stubs.c
*
@ -175,66 +175,6 @@ DeviceCapabilitiesExA(
}
/*
* @unimplemented
*/
int
STDCALL
EnumFontFamiliesExA (
HDC hdc,
LPLOGFONTA lpLogFont,
FONTENUMEXPROCA lpEnumFontFamProc,
LPARAM lParam,
DWORD dwFlags
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
#if 0
LOGFONTW LogFontW;
RosRtlLogFontA2W ( &LogFontW, lpLogFont );
/* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
return NtGdiEnumFontFamiliesEx ( hdc, &LogFontW, lpEnumFontFamProc, lParam, dwFlags );
#endif
}
/*
* @unimplemented
*/
int
STDCALL
EnumFontFamiliesA(
HDC hdc,
LPCSTR lpszFamily,
FONTENUMPROCA lpEnumFontFamProc,
LPARAM lParam
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
#if 0
NTSTATUS Status;
LPWSTR lpszFamilyW;
int rc = 0;
Status = HEAP_strdupA2W ( &lpszFamilyW, lpszFamily );
if (!NT_SUCCESS (Status))
SetLastError (RtlNtStatusToDosError(Status));
else
{
rc = NtGdiEnumFontFamilies ( hdc, lpszFamilyW, lpEnumFontFamProc, lParam );
HEAP_free ( lpszFamilyW );
}
return rc;
#endif
}
/*
* @implemented
*/

View file

@ -1,4 +1,4 @@
/* $Id: stubsw.c,v 1.24 2004/01/24 08:23:12 ekohl Exp $
/* $Id: stubsw.c,v 1.25 2004/03/23 00:18:54 gvg Exp $
*
* reactos/lib/gdi32/misc/stubs.c
*
@ -112,49 +112,6 @@ DeviceCapabilitiesExW(
}
/*
* @unimplemented
*/
int
STDCALL
EnumFontFamiliesExW(
HDC hdc,
LPLOGFONTW lpLogFont,
FONTENUMEXPROCW lpEnumFontFamProc,
LPARAM lParam,
DWORD dwFlags
)
{
#if 0
return NtGdiEnumFontFamiliesEx ( hdc, lpLogFont, lpEnumFontFamProc, lParam, dwFlags );
#else
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
#endif
}
/*
* @unimplemented
*/
int
STDCALL
EnumFontFamiliesW(
HDC hdc,
LPCWSTR lpszFamily,
FONTENUMPROCW lpEnumFontFamProc,
LPARAM lParam
)
{
#if 0
return NtGdiEnumFontFamilies ( hdc, lpszFamily, lpEnumFontFamProc, lParam );
#else
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
#endif
}
/*
* @unimplemented
*/

View file

@ -0,0 +1,332 @@
/* $Id: font.c,v 1.1 2004/03/23 00:18:54 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/gdi32/object/font.c
* PURPOSE:
* PROGRAMMER:
*
*/
#ifdef UNICODE
#undef UNICODE
#endif
#include <windows.h>
#include <rosrtl/logfont.h>
#include <win32k/font.h>
#include <internal/font.h>
#define NDEBUG
#include <debug.h>
#define INITIAL_FAMILY_COUNT 64
static BOOL FASTCALL
MetricsCharConvert(WCHAR w, CHAR *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;
}
/*
* @implemented
*/
BOOL
STDCALL
TranslateCharsetInfo(DWORD *Src, LPCHARSETINFO Cs, DWORD Flags)
{
return NtGdiTranslateCharsetInfo(Src, Cs, Flags);
}
static int FASTCALL
IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
BOOL Unicode)
{
int FontFamilyCount;
unsigned FontFamilySize;
PFONTFAMILYINFO Info;
int Ret;
unsigned 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 = ((FONTENUMEXPROCW) EnumProc)(&Info[i].EnumLogFontEx, &Info[i].NewTextMetricEx,
Info[i].FontType, lParam);
}
else
{
RosRtlLogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
NewTextMetricExW2A(&NewTextMetricExA,
&Info[i].NewTextMetricEx);
Ret = ((FONTENUMEXPROCA) EnumProc)(&EnumLogFontExA, &NewTextMetricExA,
Info[i].FontType, lParam);
}
}
RtlFreeHeap(GetProcessHeap(), 0, Info);
return Ret;
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesExW(HDC Dc, LPLOGFONTW LogFont, FONTENUMEXPROCW EnumFontFamProc,
LPARAM lParam, DWORD Flags)
{
return IntEnumFontFamilies(Dc, LogFont, EnumFontFamProc, lParam, TRUE);
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesW(HDC Dc, LPCWSTR Family, FONTENUMPROCW EnumFontFamProc,
LPARAM lParam)
{
LOGFONTW LogFont;
ZeroMemory(&LogFont, sizeof(LOGFONTW));
LogFont.lfCharSet = DEFAULT_CHARSET;
if (NULL != Family)
{
lstrcpynW(LogFont.lfFaceName, Family, LF_FACESIZE);
}
return IntEnumFontFamilies(Dc, &LogFont, EnumFontFamProc, lParam, TRUE);
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesExA (HDC Dc, LPLOGFONTA LogFont, FONTENUMEXPROCA EnumFontFamProc,
LPARAM lParam, DWORD dwFlags)
{
LOGFONTW LogFontW;
RosRtlLogFontA2W(&LogFontW, LogFont);
/* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
return IntEnumFontFamilies(Dc, &LogFontW, EnumFontFamProc, lParam, FALSE);
}
/*
* @implemented
*/
int STDCALL
EnumFontFamiliesA(HDC Dc, LPCSTR Family, FONTENUMPROCA EnumFontFamProc,
LPARAM lParam)
{
LOGFONTW LogFont;
ZeroMemory(&LogFont, sizeof(LOGFONTW));
LogFont.lfCharSet = DEFAULT_CHARSET;
if (NULL != Family)
{
MultiByteToWideChar(CP_THREAD_ACP, 0, Family, -1, LogFont.lfFaceName, LF_FACESIZE);
}
return IntEnumFontFamilies(Dc, &LogFont, EnumFontFamProc, lParam, FALSE);
}

View file

@ -7,6 +7,7 @@
#include <windows.h>
#include <ddk/ntddk.h>
#include <win32k/kapi.h>
#include <internal/font.h>
/*
@ -78,41 +79,6 @@ SetTextColor(HDC hDC, COLORREF color)
}
static BOOL
MetricsCharConvert(WCHAR w, CHAR *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;
}
/*
* @implemented
*/
@ -124,106 +90,13 @@ GetTextMetricsA(
)
{
TEXTMETRICW tmw;
UNICODE_STRING WString;
WCHAR WBuf[256];
ANSI_STRING AString;
CHAR ABuf[256];
UINT Letter;
NTSTATUS Status;
if (! NtGdiGetTextMetrics(hdc, &tmw))
{
return FALSE;
}
tm->tmHeight = tmw.tmHeight;
tm->tmAscent = tmw.tmAscent;
tm->tmDescent = tmw.tmDescent;
tm->tmInternalLeading = tmw.tmInternalLeading;
tm->tmExternalLeading = tmw.tmExternalLeading;
tm->tmAveCharWidth = tmw.tmAveCharWidth;
tm->tmMaxCharWidth = tmw.tmMaxCharWidth;
tm->tmWeight = tmw.tmWeight;
tm->tmOverhang = tmw.tmOverhang;
tm->tmDigitizedAspectX = tmw.tmDigitizedAspectX;
tm->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 */
tm->tmFirstChar = '\0';
if (L'\0' != tmw.tmFirstChar)
{
for (Letter = 1; Letter < 256; Letter++)
{
if (tmw.tmFirstChar <= WBuf[Letter - 1] &&
WBuf[Letter - 1] <= tmw.tmLastChar)
{
tm->tmFirstChar = (CHAR) Letter;
break;
}
}
}
/* Scan for the last ANSI character which maps to an Unicode character
in the range */
tm->tmLastChar = '\0';
if (L'\0' != tmw.tmLastChar)
{
for (Letter = 255; 0 < Letter; Letter--)
{
if (tmw.tmFirstChar <= WBuf[Letter - 1] &&
WBuf[Letter - 1] <= tmw.tmLastChar)
{
tm->tmLastChar = (CHAR) Letter;
break;
}
}
}
if (! MetricsCharConvert(tmw.tmDefaultChar, &tm->tmDefaultChar) ||
! MetricsCharConvert(tmw.tmBreakChar, &tm->tmBreakChar))
{
return FALSE;
}
tm->tmItalic = tmw.tmItalic;
tm->tmUnderlined = tmw.tmUnderlined;
tm->tmStruckOut = tmw.tmStruckOut;
tm->tmPitchAndFamily = tmw.tmPitchAndFamily;
tm->tmCharSet = tmw.tmCharSet;
return TRUE;
return TextMetricW2A(tm, &tmw);
}
@ -237,7 +110,7 @@ GetTextMetricsW(
LPTEXTMETRICW tm
)
{
return NtGdiGetTextMetrics(hdc, tm);
return NtGdiGetTextMetrics(hdc, tm);
}

View file

@ -1,22 +1,28 @@
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Parts based on Wine code
* Copyright 1993 Alexandre Julliard
* 1997 Alex Korobka
* Copyright 2002,2003 Shachar Shemesh
* Copyright 2001 Huw D M Davies for CodeWeavers.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: text.c,v 1.81 2004/03/18 22:03:40 royce Exp $ */
/* $Id: text.c,v 1.82 2004/03/23 00:18:54 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN
@ -63,6 +69,74 @@ static FAST_MUTEX FontListLock;
static INT FontsLoaded = 0; /* number of all fonts loaded (including private fonts */
static BOOL RenderingEnabled = TRUE;
static PWCHAR ElfScripts[32] = { /* these are in the order of the fsCsb[0] bits */
L"Western", /*00*/
L"Central_European",
L"Cyrillic",
L"Greek",
L"Turkish",
L"Hebrew",
L"Arabic",
L"Baltic",
L"Vietnamese", /*08*/
NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
L"Thai",
L"Japanese",
L"CHINESE_GB2312",
L"Hangul",
L"CHINESE_BIG5",
L"Hangul(Johab)",
NULL, NULL, /*23*/
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
L"Symbol" /*31*/
};
/*
* For NtGdiTranslateCharsetInfo
*/
#define FS(x) {{0,0,0,0},{0x1<<(x),0}}
#define MAXTCIINDEX 32
static CHARSETINFO FontTci[MAXTCIINDEX] = {
/* ANSI */
{ ANSI_CHARSET, 1252, FS(0)},
{ EASTEUROPE_CHARSET, 1250, FS(1)},
{ RUSSIAN_CHARSET, 1251, FS(2)},
{ GREEK_CHARSET, 1253, FS(3)},
{ TURKISH_CHARSET, 1254, FS(4)},
{ HEBREW_CHARSET, 1255, FS(5)},
{ ARABIC_CHARSET, 1256, FS(6)},
{ BALTIC_CHARSET, 1257, FS(7)},
{ VIETNAMESE_CHARSET, 1258, FS(8)},
/* reserved by ANSI */
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
/* ANSI and OEM */
{ THAI_CHARSET, 874, FS(16)},
{ SHIFTJIS_CHARSET, 932, FS(17)},
{ GB2312_CHARSET, 936, FS(18)},
{ HANGEUL_CHARSET, 949, FS(19)},
{ CHINESEBIG5_CHARSET, 950, FS(20)},
{ JOHAB_CHARSET, 1361, FS(21)},
/* reserved for alternate ANSI and OEM */
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
/* reserved for system */
{ DEFAULT_CHARSET, 0, FS(0)},
{ SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
};
BOOL FASTCALL
IntIsFontRenderingEnabled(VOID)
{
@ -546,25 +620,839 @@ NtGdiCreateScalableFontResource(DWORD Hidden,
UNIMPLEMENTED;
}
int
STDCALL
NtGdiEnumFontFamilies(HDC hDC,
LPCWSTR Family,
FONTENUMPROCW EnumFontFamProc,
LPARAM lParam)
/*************************************************************************
* TranslateCharsetInfo
*
* Fills a CHARSETINFO structure for a character set, code page, or
* font. This allows making the correspondance between different labelings
* (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
* of the same encoding.
*
* Only one codepage will be set in Cs->fs. If TCI_SRCFONTSIG is used,
* only one codepage should be set in *Src.
*
* RETURNS
* TRUE on success, FALSE on failure.
*
*/
static BOOLEAN STDCALL
IntTranslateCharsetInfo(PDWORD Src, /* [in]
if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
if flags == TCI_SRCCHARSET: a character set value
if flags == TCI_SRCCODEPAGE: a code page value */
LPCHARSETINFO Cs, /* [out] structure to receive charset information */
DWORD Flags /* [in] determines interpretation of lpSrc */)
{
UNIMPLEMENTED;
int Index = 0;
switch (Flags)
{
case TCI_SRCFONTSIG:
while (0 == (*Src >> Index & 0x0001) && Index < MAXTCIINDEX)
{
Index++;
}
break;
case TCI_SRCCODEPAGE:
while ((UINT) (Src) != FontTci[Index].ciACP && Index < MAXTCIINDEX)
{
Index++;
}
break;
case TCI_SRCCHARSET:
while ((UINT) (Src) != FontTci[Index].ciCharset && Index < MAXTCIINDEX)
{
Index++;
}
break;
default:
return FALSE;
}
if (MAXTCIINDEX <= Index || DEFAULT_CHARSET == FontTci[Index].ciCharset)
{
return FALSE;
}
memcpy(Cs, &FontTci[Index], sizeof(CHARSETINFO));
return TRUE;
}
int
STDCALL
NtGdiEnumFontFamiliesEx(HDC hDC,
LPLOGFONTW Logfont,
FONTENUMEXPROCW EnumFontFamExProc,
LPARAM lParam,
DWORD Flags)
BOOL STDCALL
NtGdiTranslateCharsetInfo(PDWORD Src,
LPCHARSETINFO UnsafeCs,
DWORD Flags)
{
UNIMPLEMENTED;
CHARSETINFO Cs;
BOOLEAN Ret;
NTSTATUS Status;
Ret = IntTranslateCharsetInfo(Src, &Cs, Flags);
if (Ret)
{
Status = MmCopyToCaller(UnsafeCs, &Cs, sizeof(CHARSETINFO));
if (! NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
}
return (BOOL) Ret;
}
/*************************************************************
* IntGetOutlineTextMetrics
*
*/
static unsigned FASTCALL
IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size,
OUTLINETEXTMETRICW *Otm)
{
unsigned Needed;
TT_OS2 *pOS2;
TT_HoriHeader *pHori;
TT_Postscript *pPost;
FT_Fixed XScale, YScale;
ANSI_STRING FamilyNameA, StyleNameA;
UNICODE_STRING FamilyNameW, StyleNameW, Regular;
char *Cp;
int Ascent, Descent;
TEXTMETRICW *TM;
Needed = sizeof(OUTLINETEXTMETRICW);
RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name);
RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name);
RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
/* These names should be read from the TT name table */
/* length of otmpFamilyName */
Needed += FamilyNameW.Length + sizeof(WCHAR);
RtlInitUnicodeString(&Regular, L"regular");
/* length of otmpFaceName */
if (0 == RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE))
{
Needed += FamilyNameW.Length + sizeof(WCHAR); /* just the family name */
}
else
{
Needed += FamilyNameW.Length + StyleNameW.Length + 2 * sizeof(WCHAR); /* family + " " + style */
}
/* length of otmpStyleName */
Needed += StyleNameW.Length + sizeof(WCHAR);
/* length of otmpFullName */
Needed += FamilyNameW.Length + StyleNameW.Length + 2 * sizeof(WCHAR);
if (Size < Needed)
{
RtlFreeUnicodeString(&FamilyNameW);
RtlFreeUnicodeString(&StyleNameW);
return Needed;
}
XScale = FontGDI->face->size->metrics.x_scale;
YScale = FontGDI->face->size->metrics.y_scale;
IntLockFreeType;
pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
if (NULL == pOS2)
{
IntUnLockFreeType;
DPRINT1("Can't find OS/2 table - not TT font?\n");
RtlFreeUnicodeString(&StyleNameW);
RtlFreeUnicodeString(&FamilyNameW);
return 0;
}
pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea);
if (NULL == pHori)
{
IntUnLockFreeType;
DPRINT1("Can't find HHEA table - not TT font?\n");
RtlFreeUnicodeString(&StyleNameW);
RtlFreeUnicodeString(&FamilyNameW);
return 0;
}
pPost = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_post); /* we can live with this failing */
IntUnLockFreeType;
Otm->otmSize = Needed;
if (0 == pOS2->usWinAscent + pOS2->usWinDescent)
{
Ascent = pHori->Ascender;
Descent = -pHori->Descender;
}
else
{
Ascent = pOS2->usWinAscent;
Descent = pOS2->usWinDescent;
}
TM = &Otm->otmTextMetrics;
TM->tmAscent = (FT_MulFix(Ascent, YScale) + 32) >> 6;
TM->tmDescent = (FT_MulFix(Descent, YScale) + 32) >> 6;
TM->tmInternalLeading = (FT_MulFix(Ascent + Descent
- FontGDI->face->units_per_EM, YScale) + 32) >> 6;
TM->tmHeight = TM->tmAscent + TM->tmDescent;
/* MSDN says:
* el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
*/
TM->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap
- ((Ascent + Descent)
- (pHori->Ascender - pHori->Descender)),
YScale) + 32) >> 6);
TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
if (0 == TM->tmAveCharWidth)
{
TM->tmAveCharWidth = 1;
}
TM->tmMaxCharWidth = (FT_MulFix(FontGDI->face->bbox.xMax - FontGDI->face->bbox.xMin,
XScale) + 32) >> 6;
TM->tmWeight = pOS2->usWeightClass;
TM->tmOverhang = 0;
TM->tmDigitizedAspectX = 300;
TM->tmDigitizedAspectY = 300;
TM->tmFirstChar = pOS2->usFirstCharIndex;
TM->tmLastChar = pOS2->usLastCharIndex;
TM->tmDefaultChar = pOS2->usDefaultChar;
TM->tmBreakChar = L'\0' != pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
TM->tmItalic = (FontGDI->face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0;
TM->tmUnderlined = 0; /* entry in OS2 table */
TM->tmStruckOut = 0; /* entry in OS2 table */
/* Yes TPMF_FIXED_PITCH is correct; braindead api */
if (! FT_IS_FIXED_WIDTH(FontGDI->face))
{
TM->tmPitchAndFamily = TMPF_FIXED_PITCH;
}
else
{
TM->tmPitchAndFamily = 0;
}
switch (pOS2->panose[PAN_FAMILYTYPE_INDEX])
{
case PAN_FAMILY_SCRIPT:
TM->tmPitchAndFamily |= FF_SCRIPT;
break;
case PAN_FAMILY_DECORATIVE:
case PAN_FAMILY_PICTORIAL:
TM->tmPitchAndFamily |= FF_DECORATIVE;
break;
case PAN_FAMILY_TEXT_DISPLAY:
if (0 == TM->tmPitchAndFamily) /* fixed */
{
TM->tmPitchAndFamily = FF_MODERN;
}
else
{
switch (pOS2->panose[PAN_SERIFSTYLE_INDEX])
{
case PAN_SERIF_NORMAL_SANS:
case PAN_SERIF_OBTUSE_SANS:
case PAN_SERIF_PERP_SANS:
TM->tmPitchAndFamily |= FF_SWISS;
break;
default:
TM->tmPitchAndFamily |= FF_ROMAN;
break;
}
}
break;
default:
TM->tmPitchAndFamily |= FF_DONTCARE;
}
if (FT_IS_SCALABLE(FontGDI->face))
{
TM->tmPitchAndFamily |= TMPF_VECTOR;
}
if (FT_IS_SFNT(FontGDI->face))
{
TM->tmPitchAndFamily |= TMPF_TRUETYPE;
}
#ifndef TODO
TM->tmCharSet = DEFAULT_CHARSET;
#endif
Otm->otmFiller = 0;
memcpy(&Otm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
Otm->otmfsSelection = pOS2->fsSelection;
Otm->otmfsType = pOS2->fsType;
Otm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
Otm->otmsCharSlopeRun = pHori->caret_Slope_Run;
Otm->otmItalicAngle = 0; /* POST table */
Otm->otmEMSquare = FontGDI->face->units_per_EM;
Otm->otmAscent = (FT_MulFix(pOS2->sTypoAscender, YScale) + 32) >> 6;
Otm->otmDescent = (FT_MulFix(pOS2->sTypoDescender, YScale) + 32) >> 6;
Otm->otmLineGap = (FT_MulFix(pOS2->sTypoLineGap, YScale) + 32) >> 6;
Otm->otmsCapEmHeight = (FT_MulFix(pOS2->sCapHeight, YScale) + 32) >> 6;
Otm->otmsXHeight = (FT_MulFix(pOS2->sxHeight, YScale) + 32) >> 6;
Otm->otmrcFontBox.left = (FT_MulFix(FontGDI->face->bbox.xMin, XScale) + 32) >> 6;
Otm->otmrcFontBox.right = (FT_MulFix(FontGDI->face->bbox.xMax, XScale) + 32) >> 6;
Otm->otmrcFontBox.top = (FT_MulFix(FontGDI->face->bbox.yMax, YScale) + 32) >> 6;
Otm->otmrcFontBox.bottom = (FT_MulFix(FontGDI->face->bbox.yMin, YScale) + 32) >> 6;
Otm->otmMacAscent = 0; /* where do these come from ? */
Otm->otmMacDescent = 0;
Otm->otmMacLineGap = 0;
Otm->otmusMinimumPPEM = 0; /* TT Header */
Otm->otmptSubscriptSize.x = (FT_MulFix(pOS2->ySubscriptXSize, XScale) + 32) >> 6;
Otm->otmptSubscriptSize.y = (FT_MulFix(pOS2->ySubscriptYSize, YScale) + 32) >> 6;
Otm->otmptSubscriptOffset.x = (FT_MulFix(pOS2->ySubscriptXOffset, XScale) + 32) >> 6;
Otm->otmptSubscriptOffset.y = (FT_MulFix(pOS2->ySubscriptYOffset, YScale) + 32) >> 6;
Otm->otmptSuperscriptSize.x = (FT_MulFix(pOS2->ySuperscriptXSize, XScale) + 32) >> 6;
Otm->otmptSuperscriptSize.y = (FT_MulFix(pOS2->ySuperscriptYSize, YScale) + 32) >> 6;
Otm->otmptSuperscriptOffset.x = (FT_MulFix(pOS2->ySuperscriptXOffset, XScale) + 32) >> 6;
Otm->otmptSuperscriptOffset.y = (FT_MulFix(pOS2->ySuperscriptYOffset, YScale) + 32) >> 6;
Otm->otmsStrikeoutSize = (FT_MulFix(pOS2->yStrikeoutSize, YScale) + 32) >> 6;
Otm->otmsStrikeoutPosition = (FT_MulFix(pOS2->yStrikeoutPosition, YScale) + 32) >> 6;
if (NULL == pPost)
{
Otm->otmsUnderscoreSize = 0;
Otm->otmsUnderscorePosition = 0;
}
else
{
Otm->otmsUnderscoreSize = (FT_MulFix(pPost->underlineThickness, YScale) + 32) >> 6;
Otm->otmsUnderscorePosition = (FT_MulFix(pPost->underlinePosition, YScale) + 32) >> 6;
}
/* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
Cp = (char*) Otm + sizeof(OUTLINETEXTMETRICW);
Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm);
wcscpy((WCHAR*) Cp, FamilyNameW.Buffer);
Cp += FamilyNameW.Length + sizeof(WCHAR);
Otm->otmpStyleName = (LPSTR)(Cp - (char*) Otm);
wcscpy((WCHAR*) Cp, StyleNameW.Buffer);
Cp += StyleNameW.Length + sizeof(WCHAR);
Otm->otmpFaceName = (LPSTR)(Cp - (char*) Otm);
wcscpy((WCHAR*) Cp, FamilyNameW.Buffer);
if (0 != RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE))
{
wcscat((WCHAR*) Cp, L" ");
wcscat((WCHAR*) Cp, StyleNameW.Buffer);
Cp += FamilyNameW.Length + StyleNameW.Length + 2 * sizeof(WCHAR);
}
else
{
Cp += FamilyNameW.Length + sizeof(WCHAR);
}
Otm->otmpFullName = (LPSTR)(Cp - (char*) Otm);
wcscpy((WCHAR*) Cp, FamilyNameW.Buffer);
wcscat((WCHAR*) Cp, L" ");
wcscat((WCHAR*) Cp, StyleNameW.Buffer);
RtlFreeUnicodeString(&StyleNameW);
RtlFreeUnicodeString(&FamilyNameW);
return Needed;
}
static PFONTGDI FASTCALL
FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head)
{
PLIST_ENTRY Entry;
PFONT_ENTRY CurrentEntry;
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
PFONTGDI FontGDI;
Entry = Head->Flink;
while (Entry != Head)
{
CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
if (NULL == (FontGDI = AccessInternalObject((ULONG) CurrentEntry->hFont)))
{
Entry = Entry->Flink;
continue;
}
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
}
if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
{
RtlFreeUnicodeString(&EntryFaceNameW);
return FontGDI;
}
RtlFreeUnicodeString(&EntryFaceNameW);
Entry = Entry->Flink;
}
return NULL;
}
static PFONTGDI FASTCALL
FindFaceNameInLists(PUNICODE_STRING FaceName)
{
PW32PROCESS Win32Process;
PFONTGDI Font;
/* Search the process local list */
Win32Process = PsGetWin32Process();
IntLockProcessPrivateFonts(Win32Process);
Font = FindFaceNameInList(FaceName, &Win32Process->PrivateFontListHead);
IntUnLockProcessPrivateFonts(Win32Process);
if (NULL != Font)
{
return Font;
}
/* Search the global list */
IntLockGlobalFonts;
Font = FindFaceNameInList(FaceName, &FontListHead);
IntUnLockGlobalFonts;
return Font;
}
static void FASTCALL
FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI)
{
ANSI_STRING StyleA;
UNICODE_STRING StyleW;
TT_OS2 *pOS2;
FONTSIGNATURE fs;
DWORD fs_fsCsb0;
CHARSETINFO CharSetInfo;
unsigned i, Size;
OUTLINETEXTMETRICW *Otm;
LOGFONTW *Lf;
TEXTMETRICW *TM;
NEWTEXTMETRICW *Ntm;
ZeroMemory(Info, sizeof(FONTFAMILYINFO));
Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
if (NULL == Otm)
{
return;
}
IntGetOutlineTextMetrics(FontGDI, Size, Otm);
Lf = &Info->EnumLogFontEx.elfLogFont;
TM = &Otm->otmTextMetrics;
Lf->lfHeight = TM->tmHeight;
Lf->lfWidth = TM->tmAveCharWidth;
Lf->lfWeight = TM->tmWeight;
Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1;
Lf->lfCharSet = TM->tmCharSet;
Lf->lfOutPrecision = OUT_STROKE_PRECIS;
Lf->lfClipPrecision = CLIP_STROKE_PRECIS;
Lf->lfQuality = DRAFT_QUALITY;
Ntm = &Info->NewTextMetricEx.ntmTm;
Ntm->tmHeight = TM->tmHeight;
Ntm->tmAscent = TM->tmAscent;
Ntm->tmDescent = TM->tmDescent;
Ntm->tmInternalLeading = TM->tmInternalLeading;
Ntm->tmExternalLeading = TM->tmExternalLeading;
Ntm->tmAveCharWidth = TM->tmAveCharWidth;
Ntm->tmMaxCharWidth = TM->tmMaxCharWidth;
Ntm->tmWeight = TM->tmWeight;
Ntm->tmOverhang = TM->tmOverhang;
Ntm->tmDigitizedAspectX = TM->tmDigitizedAspectX;
Ntm->tmDigitizedAspectY = TM->tmDigitizedAspectY;
Ntm->tmFirstChar = TM->tmFirstChar;
Ntm->tmLastChar = TM->tmLastChar;
Ntm->tmDefaultChar = TM->tmDefaultChar;
Ntm->tmBreakChar = TM->tmBreakChar;
Ntm->tmItalic = TM->tmItalic;
Ntm->tmUnderlined = TM->tmUnderlined;
Ntm->tmStruckOut = TM->tmStruckOut;
Ntm->tmPitchAndFamily = TM->tmPitchAndFamily;
Ntm->tmCharSet = TM->tmCharSet;
Ntm->ntmFlags = TM->tmItalic ? NTM_ITALIC : 0;
if (550 < TM->tmWeight)
{
Ntm->ntmFlags |= NTM_BOLD;
}
if (0 == Ntm->ntmFlags)
{
Ntm->ntmFlags = NTM_REGULAR;
}
Ntm->ntmSizeEM = Otm->otmEMSquare;
Ntm->ntmCellHeight = 0;
Ntm->ntmAvgWidth = 0;
Info->FontType = (0 != (TM->tmPitchAndFamily & TMPF_TRUETYPE)
? TRUETYPE_FONTTYPE : 0);
if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR))
{
Info->FontType |= RASTER_FONTTYPE;
}
ExFreePool(Otm);
wcsncpy(Info->EnumLogFontEx.elfLogFont.lfFaceName, FaceName, LF_FACESIZE);
wcsncpy(Info->EnumLogFontEx.elfFullName, FaceName, LF_FULLFACESIZE);
RtlInitAnsiString(&StyleA, FontGDI->face->style_name);
RtlAnsiStringToUnicodeString(&StyleW, &StyleA, TRUE);
wcsncpy(Info->EnumLogFontEx.elfStyle, StyleW.Buffer, LF_FACESIZE);
RtlFreeUnicodeString(&StyleW);
Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET;
Info->EnumLogFontEx.elfScript[0] = L'\0';
IntLockFreeType;
pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
IntUnLockFreeType;
if (NULL != pOS2)
{
Info->NewTextMetricEx.ntmFontSig.fsCsb[0] = pOS2->ulCodePageRange1;
Info->NewTextMetricEx.ntmFontSig.fsCsb[1] = pOS2->ulCodePageRange2;
Info->NewTextMetricEx.ntmFontSig.fsUsb[0] = pOS2->ulUnicodeRange1;
Info->NewTextMetricEx.ntmFontSig.fsUsb[1] = pOS2->ulUnicodeRange2;
Info->NewTextMetricEx.ntmFontSig.fsUsb[2] = pOS2->ulUnicodeRange3;
Info->NewTextMetricEx.ntmFontSig.fsUsb[3] = pOS2->ulUnicodeRange4;
fs_fsCsb0 = pOS2->ulCodePageRange1;
if (0 == pOS2->version)
{
FT_UInt Dummy;
if (FT_Get_First_Char(FontGDI->face, &Dummy) < 0x100)
{
fs_fsCsb0 |= 1;
}
else
{
fs_fsCsb0 |= 1L << 31;
}
}
if (0 == fs_fsCsb0)
{ /* let's see if we can find any interesting cmaps */
for (i = 0; i < FontGDI->face->num_charmaps; i++)
{
switch (FontGDI->face->charmaps[i]->encoding)
{
case ft_encoding_unicode:
case ft_encoding_apple_roman:
fs_fsCsb0 |= 1;
break;
case ft_encoding_symbol:
fs_fsCsb0 |= 1L << 31;
break;
default:
break;
}
}
}
for(i = 0; i < 32; i++)
{
if (0 != (fs_fsCsb0 & (1L << i)))
{
fs.fsCsb[0] = 1L << i;
fs.fsCsb[1] = 0;
if (! IntTranslateCharsetInfo(fs.fsCsb, &CharSetInfo, TCI_SRCFONTSIG))
{
CharSetInfo.ciCharset = DEFAULT_CHARSET;
}
if (31 == i)
{
CharSetInfo.ciCharset = SYMBOL_CHARSET;
}
if (DEFAULT_CHARSET != CharSetInfo.ciCharset)
{
Info->EnumLogFontEx.elfLogFont.lfCharSet = CharSetInfo.ciCharset;
if (NULL != ElfScripts[i])
{
wcscpy(Info->EnumLogFontEx.elfScript, ElfScripts[i]);
}
else
{
DPRINT1("Unknown elfscript for bit %d\n", i);
}
}
}
}
}
}
static int FASTCALL
FindFaceNameInInfo(PUNICODE_STRING FaceName, PFONTFAMILYINFO Info, DWORD InfoEntries)
{
DWORD i;
UNICODE_STRING InfoFaceName;
for (i = 0; i < InfoEntries; i++)
{
RtlInitUnicodeString(&InfoFaceName, Info[i].EnumLogFontEx.elfLogFont.lfFaceName);
if (0 == RtlCompareUnicodeString(&InfoFaceName, FaceName, TRUE))
{
return i;
}
}
return -1;
}
static BOOLEAN FASTCALL
FontFamilyInclude(LPLOGFONTW LogFont, PUNICODE_STRING FaceName,
PFONTFAMILYINFO Info, DWORD InfoEntries)
{
UNICODE_STRING LogFontFaceName;
RtlInitUnicodeString(&LogFontFaceName, LogFont->lfFaceName);
if (0 != LogFontFaceName.Length
&& 0 != RtlCompareUnicodeString(&LogFontFaceName, FaceName, TRUE))
{
return FALSE;
}
return FindFaceNameInInfo(FaceName, Info, InfoEntries) < 0;
}
static BOOLEAN FASTCALL
GetFontFamilyInfoForList(LPLOGFONTW LogFont,
PFONTFAMILYINFO Info,
DWORD *Count,
DWORD Size,
PLIST_ENTRY Head)
{
PLIST_ENTRY Entry;
PFONT_ENTRY CurrentEntry;
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
PFONTGDI FontGDI;
Entry = Head->Flink;
while (Entry != Head)
{
CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
if (NULL == (FontGDI = AccessInternalObject((ULONG) CurrentEntry->hFont)))
{
Entry = Entry->Flink;
continue;
}
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
}
if (FontFamilyInclude(LogFont, &EntryFaceNameW, Info, min(*Count, Size)))
{
if (*Count < Size)
{
FontFamilyFillInfo(Info + *Count, EntryFaceNameW.Buffer, FontGDI);
}
(*Count)++;
}
RtlFreeUnicodeString(&EntryFaceNameW);
Entry = Entry->Flink;
}
return TRUE;
}
typedef struct FontFamilyInfoCallbackContext
{
LPLOGFONTW LogFont;
PFONTFAMILYINFO Info;
DWORD Count;
DWORD Size;
} FONT_FAMILY_INFO_CALLBACK_CONTEXT, *PFONT_FAMILY_INFO_CALLBACK_CONTEXT;
static NTSTATUS STDCALL
FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType,
IN PVOID ValueData, IN ULONG ValueLength,
IN PVOID Context, IN PVOID EntryContext)
{
PFONT_FAMILY_INFO_CALLBACK_CONTEXT InfoContext;
UNICODE_STRING RegistryName, RegistryValue;
int Existing;
PFONTGDI FontGDI;
if (REG_SZ != ValueType)
{
return STATUS_SUCCESS;
}
InfoContext = (PFONT_FAMILY_INFO_CALLBACK_CONTEXT) Context;
RtlInitUnicodeString(&RegistryName, ValueName);
/* Do we need to include this font family? */
if (FontFamilyInclude(InfoContext->LogFont, &RegistryName, InfoContext->Info,
min(InfoContext->Count, InfoContext->Size)))
{
RtlInitUnicodeString(&RegistryValue, (PCWSTR) ValueData);
Existing = FindFaceNameInInfo(&RegistryValue, InfoContext->Info,
min(InfoContext->Count, InfoContext->Size));
if (0 <= Existing)
{
/* We already have the information about the "real" font. Just copy it */
if (InfoContext->Count < InfoContext->Size)
{
InfoContext->Info[InfoContext->Count] = InfoContext->Info[Existing];
wcsncpy(InfoContext->Info[InfoContext->Count].EnumLogFontEx.elfLogFont.lfFaceName,
RegistryName.Buffer, LF_FACESIZE);
}
InfoContext->Count++;
return STATUS_SUCCESS;
}
/* Try to find information about the "real" font */
FontGDI = FindFaceNameInLists(&RegistryValue);
if (NULL == FontGDI)
{
/* "Real" font not found, discard this registry entry */
return STATUS_SUCCESS;
}
/* Return info about the "real" font but with the name of the alias */
if (InfoContext->Count < InfoContext->Size)
{
FontFamilyFillInfo(InfoContext->Info + InfoContext->Count,
RegistryName.Buffer, FontGDI);
}
InfoContext->Count++;
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
static BOOLEAN FASTCALL
GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
PFONTFAMILYINFO Info,
DWORD *Count,
DWORD Size)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
FONT_FAMILY_INFO_CALLBACK_CONTEXT Context;
NTSTATUS Status;
/* Enumerate font families found in HKLM\Software\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes
The real work is done in the registry callback function */
Context.LogFont = LogFont;
Context.Info = Info;
Context.Count = *Count;
Context.Size = Size;
QueryTable[0].QueryRoutine = FontFamilyInfoQueryRegistryCallback;
QueryTable[0].Flags = 0;
QueryTable[0].Name = NULL;
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = REG_NONE;
QueryTable[0].DefaultData = NULL;
QueryTable[0].DefaultLength = 0;
QueryTable[1].QueryRoutine = NULL;
QueryTable[1].Name = NULL;
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
L"SysFontSubstitutes",
QueryTable,
&Context,
NULL);
if (NT_SUCCESS(Status))
{
*Count = Context.Count;
}
return NT_SUCCESS(Status) || STATUS_OBJECT_NAME_NOT_FOUND == Status;
}
int STDCALL
NtGdiGetFontFamilyInfo(HDC Dc,
LPLOGFONTW UnsafeLogFont,
PFONTFAMILYINFO UnsafeInfo,
DWORD Size)
{
NTSTATUS Status;
LOGFONTW LogFont;
PFONTFAMILYINFO Info;
DWORD Count;
PW32PROCESS Win32Process;
/* Make a safe copy */
Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
if (! NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return -1;
}
/* Allocate space for a safe copy */
Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), TAG_GDITEXT);
if (NULL == Info)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return -1;
}
/* Enumerate font families in the global list */
IntLockGlobalFonts;
Count = 0;
if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, &FontListHead) )
{
IntUnLockGlobalFonts;
ExFreePool(Info);
return -1;
}
IntUnLockGlobalFonts;
/* Enumerate font families in the process local list */
Win32Process = PsGetWin32Process();
IntLockProcessPrivateFonts(Win32Process);
if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
&Win32Process->PrivateFontListHead))
{
IntUnLockProcessPrivateFonts(Win32Process);
ExFreePool(Info);
return -1;
}
IntUnLockProcessPrivateFonts(Win32Process);
/* Enumerate font families in the registry */
if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size))
{
ExFreePool(Info);
return -1;
}
/* Return data to caller */
if (0 != Count)
{
Status = MmCopyToCaller(UnsafeInfo, Info,
(Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO));
if (! NT_SUCCESS(Status))
{
ExFreePool(Info);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return -1;
}
}
ExFreePool(Info);
return Count;
}
int
@ -1689,15 +2577,6 @@ NtGdiTextOut(
return NtGdiExtTextOut(hDC, XStart, YStart, 0, NULL, String, Count, NULL);
}
UINT
STDCALL
NtGdiTranslateCharsetInfo(PDWORD Src,
LPCHARSETINFO CSI,
DWORD Flags)
{
UNIMPLEMENTED;
}
NTSTATUS FASTCALL
TextIntRealizeFont(HFONT FontHandle)
{