mirror of
https://github.com/reactos/reactos.git
synced 2025-03-30 17:10:22 +00:00
Implement EnumFontFamilies(Ex)A/W() and TranslateCharsetInfo()
svn path=/trunk/; revision=8844
This commit is contained in:
parent
4aae876500
commit
c718f507e9
15 changed files with 1335 additions and 318 deletions
|
@ -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","StartGUI",0x00010001,0x00000000
|
||||||
HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Userinit",0x00020000,"%SystemRoot%\system32\userinit.exe"
|
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
|
; EOF
|
||||||
|
|
|
@ -66,8 +66,6 @@ NtGdiEndDoc 1
|
||||||
NtGdiEndPage 1
|
NtGdiEndPage 1
|
||||||
NtGdiEndPath 1
|
NtGdiEndPath 1
|
||||||
NtGdiEnumEnhMetaFile 5
|
NtGdiEnumEnhMetaFile 5
|
||||||
NtGdiEnumFontFamilies 4
|
|
||||||
NtGdiEnumFontFamiliesEx 5
|
|
||||||
NtGdiEnumFonts 4
|
NtGdiEnumFonts 4
|
||||||
NtGdiEnumICMProfiles 3
|
NtGdiEnumICMProfiles 3
|
||||||
NtGdiEnumMetaFile 4
|
NtGdiEnumMetaFile 4
|
||||||
|
@ -126,6 +124,7 @@ NtGdiGetEnhMetaFileDescription 3
|
||||||
NtGdiGetEnhMetaFileHeader 3
|
NtGdiGetEnhMetaFileHeader 3
|
||||||
NtGdiGetEnhMetaFilePaletteEntries 3
|
NtGdiGetEnhMetaFilePaletteEntries 3
|
||||||
NtGdiGetEnhMetaFilePixelFormat 3
|
NtGdiGetEnhMetaFilePixelFormat 3
|
||||||
|
NtGdiGetFontFamilyInfo 4
|
||||||
NtGdiGetFontLanguageInfo 1
|
NtGdiGetFontLanguageInfo 1
|
||||||
#NtGdiGetFontResourceInfo ?
|
#NtGdiGetFontResourceInfo ?
|
||||||
NtGdiGetGlyphOutline 7
|
NtGdiGetGlyphOutline 7
|
||||||
|
|
|
@ -468,10 +468,12 @@ extern "C" {
|
||||||
#define SYMBOL_CHARSET (2)
|
#define SYMBOL_CHARSET (2)
|
||||||
#define SHIFTJIS_CHARSET (128)
|
#define SHIFTJIS_CHARSET (128)
|
||||||
#define HANGEUL_CHARSET (129)
|
#define HANGEUL_CHARSET (129)
|
||||||
|
#define JOHAB_CHARSET (130)
|
||||||
#define GB2312_CHARSET (134)
|
#define GB2312_CHARSET (134)
|
||||||
#define CHINESEBIG5_CHARSET (136)
|
#define CHINESEBIG5_CHARSET (136)
|
||||||
#define GREEK_CHARSET (161)
|
#define GREEK_CHARSET (161)
|
||||||
#define TURKISH_CHARSET (162)
|
#define TURKISH_CHARSET (162)
|
||||||
|
#define VIETNAMESE_CHARSET (163)
|
||||||
#define HEBREW_CHARSET (177)
|
#define HEBREW_CHARSET (177)
|
||||||
#define ARABIC_CHARSET (178)
|
#define ARABIC_CHARSET (178)
|
||||||
#define BALTIC_CHARSET (186)
|
#define BALTIC_CHARSET (186)
|
||||||
|
@ -3276,6 +3278,18 @@ extern "C" {
|
||||||
#define PAN_XHEIGHT_DUCKING_SMALL (5)
|
#define PAN_XHEIGHT_DUCKING_SMALL (5)
|
||||||
#define PAN_XHEIGHT_DUCKING_STD (6)
|
#define PAN_XHEIGHT_DUCKING_STD (6)
|
||||||
#define PAN_XHEIGHT_DUCKING_LARGE (7)
|
#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 */
|
/* PALETTENTRY structure */
|
||||||
#define PC_EXPLICIT (2)
|
#define PC_EXPLICIT (2)
|
||||||
|
@ -4777,6 +4791,11 @@ extern "C" {
|
||||||
#define TMPF_TRUETYPE (0x4)
|
#define TMPF_TRUETYPE (0x4)
|
||||||
#define TMPF_DEVICE (0x8)
|
#define TMPF_DEVICE (0x8)
|
||||||
|
|
||||||
|
/* NEWTEXTMETRIC structure */
|
||||||
|
#define NTM_ITALIC (0x01)
|
||||||
|
#define NTM_BOLD (0x20)
|
||||||
|
#define NTM_REGULAR (0x40)
|
||||||
|
|
||||||
/* CopyFileEx options */
|
/* CopyFileEx options */
|
||||||
#define COPY_FILE_FAIL_IF_EXISTS (1)
|
#define COPY_FILE_FAIL_IF_EXISTS (1)
|
||||||
|
|
||||||
|
|
|
@ -3634,13 +3634,13 @@ typedef struct tagNEWTEXTMETRICW {
|
||||||
typedef_tident(NEWTEXTMETRIC)
|
typedef_tident(NEWTEXTMETRIC)
|
||||||
|
|
||||||
typedef struct tagNEWTEXTMETRICEXA {
|
typedef struct tagNEWTEXTMETRICEXA {
|
||||||
NEWTEXTMETRICA ntmentm;
|
NEWTEXTMETRICA ntmTm;
|
||||||
FONTSIGNATURE ntmeFontSignature;
|
FONTSIGNATURE ntmFontSig;
|
||||||
} NEWTEXTMETRICEXA;
|
} NEWTEXTMETRICEXA;
|
||||||
|
|
||||||
typedef struct tagNEWTEXTMETRICEXW {
|
typedef struct tagNEWTEXTMETRICEXW {
|
||||||
NEWTEXTMETRICW ntmentm;
|
NEWTEXTMETRICW ntmTm;
|
||||||
FONTSIGNATURE ntmeFontSignature;
|
FONTSIGNATURE ntmFontSig;
|
||||||
} NEWTEXTMETRICEXW;
|
} NEWTEXTMETRICEXW;
|
||||||
|
|
||||||
typedef_tident(NEWTEXTMETRICEX)
|
typedef_tident(NEWTEXTMETRICEX)
|
||||||
|
|
26
reactos/include/win32k/font.h
Normal file
26
reactos/include/win32k/font.h
Normal 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 */
|
|
@ -9,6 +9,7 @@
|
||||||
#include <win32k/dc.h>
|
#include <win32k/dc.h>
|
||||||
#include <win32k/debug.h>
|
#include <win32k/debug.h>
|
||||||
#include <win32k/fillshap.h>
|
#include <win32k/fillshap.h>
|
||||||
|
#include <win32k/font.h>
|
||||||
#include <win32k/icm.h>
|
#include <win32k/icm.h>
|
||||||
#include <win32k/line.h>
|
#include <win32k/line.h>
|
||||||
#include <win32k/metafile.h>
|
#include <win32k/metafile.h>
|
||||||
|
|
|
@ -53,21 +53,6 @@ NtGdiCreateScalableFontResource(DWORD Hidden,
|
||||||
LPCWSTR FontFile,
|
LPCWSTR FontFile,
|
||||||
LPCWSTR CurrentPath);
|
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
|
int
|
||||||
STDCALL
|
STDCALL
|
||||||
NtGdiEnumFonts(HDC hDC,
|
NtGdiEnumFonts(HDC hDC,
|
||||||
|
@ -250,11 +235,5 @@ NtGdiTextOut(HDC hDC,
|
||||||
LPCWSTR String,
|
LPCWSTR String,
|
||||||
int Count);
|
int Count);
|
||||||
|
|
||||||
UINT
|
|
||||||
STDCALL
|
|
||||||
NtGdiTranslateCharsetInfo(PDWORD Src,
|
|
||||||
LPCHARSETINFO CSI,
|
|
||||||
DWORD Flags);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
21
reactos/lib/gdi32/include/internal/font.h
Normal file
21
reactos/lib/gdi32/include/internal/font.h
Normal 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
|
||||||
|
|
|
@ -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 = ../..
|
PATH_TO_TOP = ../..
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ OBJECTS_OBJECTS = \
|
||||||
objects/clip.o \
|
objects/clip.o \
|
||||||
objects/dc.o \
|
objects/dc.o \
|
||||||
objects/fillshap.o \
|
objects/fillshap.o \
|
||||||
|
objects/font.o \
|
||||||
objects/line.o \
|
objects/line.o \
|
||||||
objects/linedda.o \
|
objects/linedda.o \
|
||||||
objects/metafile.o \
|
objects/metafile.o \
|
||||||
|
|
|
@ -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
|
* 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
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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
|
* 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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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
|
* 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
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
332
reactos/lib/gdi32/objects/font.c
Normal file
332
reactos/lib/gdi32/objects/font.c
Normal 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);
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <win32k/kapi.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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -124,106 +90,13 @@ GetTextMetricsA(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
TEXTMETRICW tmw;
|
TEXTMETRICW tmw;
|
||||||
UNICODE_STRING WString;
|
|
||||||
WCHAR WBuf[256];
|
|
||||||
ANSI_STRING AString;
|
|
||||||
CHAR ABuf[256];
|
|
||||||
UINT Letter;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
if (! NtGdiGetTextMetrics(hdc, &tmw))
|
if (! NtGdiGetTextMetrics(hdc, &tmw))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tm->tmHeight = tmw.tmHeight;
|
return TextMetricW2A(tm, &tmw);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,7 +110,7 @@ GetTextMetricsW(
|
||||||
LPTEXTMETRICW tm
|
LPTEXTMETRICW tm
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return NtGdiGetTextMetrics(hdc, tm);
|
return NtGdiGetTextMetrics(hdc, tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* ReactOS W32 Subsystem
|
* ReactOS W32 Subsystem
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* Parts based on Wine code
|
||||||
* it under the terms of the GNU General Public License as published by
|
* Copyright 1993 Alexandre Julliard
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* 1997 Alex Korobka
|
||||||
* (at your option) any later version.
|
* 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,
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* it under the terms of the GNU General Public License as published by
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* GNU General Public License for more details.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* This program is distributed in the hope that it will be useful,
|
||||||
* along with this program; if not, write to the Free Software
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
#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 INT FontsLoaded = 0; /* number of all fonts loaded (including private fonts */
|
||||||
static BOOL RenderingEnabled = TRUE;
|
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
|
BOOL FASTCALL
|
||||||
IntIsFontRenderingEnabled(VOID)
|
IntIsFontRenderingEnabled(VOID)
|
||||||
{
|
{
|
||||||
|
@ -546,25 +620,839 @@ NtGdiCreateScalableFontResource(DWORD Hidden,
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/*************************************************************************
|
||||||
STDCALL
|
* TranslateCharsetInfo
|
||||||
NtGdiEnumFontFamilies(HDC hDC,
|
*
|
||||||
LPCWSTR Family,
|
* Fills a CHARSETINFO structure for a character set, code page, or
|
||||||
FONTENUMPROCW EnumFontFamProc,
|
* font. This allows making the correspondance between different labelings
|
||||||
LPARAM lParam)
|
* (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
|
BOOL STDCALL
|
||||||
STDCALL
|
NtGdiTranslateCharsetInfo(PDWORD Src,
|
||||||
NtGdiEnumFontFamiliesEx(HDC hDC,
|
LPCHARSETINFO UnsafeCs,
|
||||||
LPLOGFONTW Logfont,
|
DWORD Flags)
|
||||||
FONTENUMEXPROCW EnumFontFamExProc,
|
|
||||||
LPARAM lParam,
|
|
||||||
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
|
int
|
||||||
|
@ -1689,15 +2577,6 @@ NtGdiTextOut(
|
||||||
return NtGdiExtTextOut(hDC, XStart, YStart, 0, NULL, String, Count, NULL);
|
return NtGdiExtTextOut(hDC, XStart, YStart, 0, NULL, String, Count, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT
|
|
||||||
STDCALL
|
|
||||||
NtGdiTranslateCharsetInfo(PDWORD Src,
|
|
||||||
LPCHARSETINFO CSI,
|
|
||||||
DWORD Flags)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
TextIntRealizeFont(HFONT FontHandle)
|
TextIntRealizeFont(HFONT FontHandle)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue