📄 text.c
字号:
NTSTATUS Status;
int Ret;
/* Copy the UNICODE_STRING structure */
Status = MmCopyFromCaller(&SafeFileName, Filename, sizeof(UNICODE_STRING));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return 0;
}
/* Reserve for prepending '\??\' */
SafeFileName.Length += 4 * sizeof(WCHAR);
SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
src = SafeFileName.Buffer;
SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
if(!SafeFileName.Buffer)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
/* Prepend '\??\' */
RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
if(!NT_SUCCESS(Status))
{
ExFreePool(SafeFileName.Buffer);
SetLastNtError(Status);
return 0;
}
Ret = IntGdiAddFontResource(&SafeFileName, fl);
ExFreePool(SafeFileName.Buffer);
return Ret;
}
NTSTATUS FASTCALL
TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont)
{
PTEXTOBJ TextObj;
NTSTATUS Status = STATUS_SUCCESS;
*NewFont = TEXTOBJ_AllocText();
if (NULL != *NewFont)
{
TextObj = TEXTOBJ_LockText(*NewFont);
if (NULL != TextObj)
{
memcpy(&TextObj->logfont.elfEnumLogfontEx.elfLogFont, lf, sizeof(LOGFONTW));
if (lf->lfEscapement != lf->lfOrientation)
{
/* this should really depend on whether GM_ADVANCED is set */
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
}
TEXTOBJ_UnlockText(TextObj);
}
else
{
/* FIXME */
/* ASSERT(FALSE);*/
Status = STATUS_INVALID_HANDLE;
}
}
else
{
Status = STATUS_NO_MEMORY;
}
return Status;
}
HFONT
STDCALL
NtGdiHfontCreate(
IN PENUMLOGFONTEXDVW pelfw,
IN ULONG cjElfw,
IN LFTYPE lft,
IN FLONG fl,
IN PVOID pvCliData )
{
ENUMLOGFONTEXDVW SafeLogfont;
HFONT NewFont;
PTEXTOBJ TextObj;
NTSTATUS Status = STATUS_SUCCESS;
if (NULL != pelfw)
{
Status = MmCopyFromCaller(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
if (NT_SUCCESS(Status))
{
NewFont = TEXTOBJ_AllocText();
if (NULL != NewFont)
{
TextObj = TEXTOBJ_LockText(NewFont);
if (NULL != TextObj)
{
RtlCopyMemory ( &TextObj->logfont,
&SafeLogfont,
sizeof(ENUMLOGFONTEXDVW));
if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation)
{
/* this should really depend on whether GM_ADVANCED is set */
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
}
TEXTOBJ_UnlockText(TextObj);
}
else
{
/* FIXME */
/* ASSERT(FALSE);*/
Status = STATUS_INVALID_HANDLE;
}
}
}
}
else
{
Status = STATUS_INVALID_PARAMETER;
}
return NT_SUCCESS(Status) ? NewFont : NULL;
}
BOOL
STDCALL
NtGdiCreateScalableFontResource(DWORD Hidden,
LPCWSTR FontRes,
LPCWSTR FontFile,
LPCWSTR CurrentPath)
{
DPRINT1("NtGdiCreateScalableFontResource - is unimplemented, have a nice day and keep going");
return FALSE;
}
/*************************************************************************
* 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 */)
{
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;
}
BOOL STDCALL
NtGdiTranslateCharsetInfo(PDWORD Src,
LPCHARSETINFO UnsafeCs,
DWORD Flags)
{
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;
}
static void FASTCALL
FillTM(TEXTMETRICW *TM, FT_Face Face, TT_OS2 *pOS2, TT_HoriHeader *pHori)
{
FT_Fixed XScale, YScale;
int Ascent, Descent;
XScale = Face->size->metrics.x_scale;
YScale = Face->size->metrics.y_scale;
if (0 == pOS2->usWinAscent + pOS2->usWinDescent)
{
Ascent = pHori->Ascender;
Descent = -pHori->Descender;
}
else
{
Ascent = pOS2->usWinAscent;
Descent = pOS2->usWinDescent;
}
#if 1 /* This (Wine) code doesn't seem to work correctly for us, cmd issue */
TM->tmAscent = (FT_MulFix(Ascent, YScale) + 32) >> 6;
TM->tmDescent = (FT_MulFix(Descent, YScale) + 32) >> 6;
#else /* This (ros) code doesn't seem to work correctly for us for it miss 2-3 pixel draw of the font*/
TM->tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */
TM->tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */
#endif
TM->tmInternalLeading = (FT_MulFix(Ascent + Descent - Face->units_per_EM, YScale) + 32) >> 6;
TM->tmHeight = TM->tmAscent + TM->tmDescent; // we need add 1 height more after scale it right
/* 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;
}
/* Correct forumla to get the maxcharwidth from unicode and ansi font */
TM->tmMaxCharWidth = (FT_MulFix(Face->max_advance_width, 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 = (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(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(Face))
{
TM->tmPitchAndFamily |= TMPF_VECTOR;
}
if (FT_IS_SFNT(Face))
{
TM->tmPitchAndFamily |= TMPF_TRUETYPE;
}
TM->tmCharSet = DEFAULT_CHARSET;
}
/*************************************************************
* 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;
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 + (sizeof(WCHAR) << 1); /* family + " " + style */
}
/* length of otmpStyleName */
Needed += StyleNameW.Length + sizeof(WCHAR);
/* length of otmpFullName */
Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1);
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 */
Otm->otmSize = Needed;
FillTM(&Otm->otmTextMetrics, FontGDI->face, pOS2, pHori);
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -