📄 text.c
字号:
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;
}
IntUnLockFreeType;
/* 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 + (sizeof(WCHAR) << 1);
}
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;
FONTGDI *FontGDI;
Entry = Head->Flink;
while (Entry != Head)
{
CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
FontGDI = CurrentEntry->Font;
ASSERT(FontGDI);
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 = PsGetCurrentProcessWin32Process();
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;
RtlZeroMemory(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->lfItalic = TM->tmItalic;
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;
FONTGDI *FontGDI;
Entry = Head->Flink;
while (Entry != Head)
{
CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
FontGDI = CurrentEntry->Font;
ASSERT(FontGDI);
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] = {{0}};
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -