https://git.reactos.org/?p=reactos.git;a=commitdiff;h=138eb58b955e733d1bb53…
commit 138eb58b955e733d1bb53eb72445641ced65ebf6
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Dec 1 08:54:39 2022 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Dec 1 08:54:39 2022 +0900
[NTGDI][FREETYPE] lfWidth for GetTextMetrics and GetCharWidth (#4919)
- Add lfWidth member into FONTGDI structure.
- Delete IntWidthMatrix function.
- Fix IntRequestFontSize behavior for processing lfWidth value.
- Apply lfWidth in GetTextMetrics and GetCharWidth.
- Ignore the XFORM values in GetTextMetrics and GetCharWidth.
CORE-11848
---
win32ss/gdi/eng/engobjects.h | 1 +
win32ss/gdi/ntgdi/font.h | 1 +
win32ss/gdi/ntgdi/freetype.c | 127 ++++++++++++++++++++-----------------------
3 files changed, 60 insertions(+), 69 deletions(-)
diff --git a/win32ss/gdi/eng/engobjects.h b/win32ss/gdi/eng/engobjects.h
index 81f2b586432..98af01af982 100644
--- a/win32ss/gdi/eng/engobjects.h
+++ b/win32ss/gdi/eng/engobjects.h
@@ -164,6 +164,7 @@ typedef struct _FONTGDI {
LONG tmInternalLeading;
LONG Magic;
LONG lfHeight;
+ LONG lfWidth;
} FONTGDI, *PFONTGDI;
/* The initialized 'Magic' value in FONTGDI */
diff --git a/win32ss/gdi/ntgdi/font.h b/win32ss/gdi/ntgdi/font.h
index 674406281a0..fe54c3b8d8d 100644
--- a/win32ss/gdi/ntgdi/font.h
+++ b/win32ss/gdi/ntgdi/font.h
@@ -42,6 +42,7 @@ typedef struct _FONT_CACHE_HASHED
INT GlyphIndex;
FT_Face Face;
LONG lfHeight;
+ LONG lfWidth;
_ANONYMOUS_UNION union {
DWORD AspectValue;
FONT_ASPECT Aspect;
diff --git a/win32ss/gdi/ntgdi/freetype.c b/win32ss/gdi/ntgdi/freetype.c
index ea4a854bfad..fa60795b70c 100644
--- a/win32ss/gdi/ntgdi/freetype.c
+++ b/win32ss/gdi/ntgdi/freetype.c
@@ -703,37 +703,12 @@ InitFontSupport(VOID)
return TRUE;
}
-static LONG FASTCALL IntWidthMatrix(FT_Face face, FT_Matrix *pmat, LONG lfWidth)
+static LONG IntNormalizeAngle(LONG nTenthsOfDegrees)
{
- LONG tmAveCharWidth;
- TT_OS2 *pOS2;
- FT_Fixed XScale;
-
- *pmat = identityMat;
-
- if (lfWidth == 0)
- return 0;
-
- ASSERT_FREETYPE_LOCK_HELD();
- pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
- if (!pOS2)
- return 0;
-
- XScale = face->size->metrics.x_scale;
- tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
- if (tmAveCharWidth == 0)
- {
- tmAveCharWidth = 1;
- }
-
- if (lfWidth == tmAveCharWidth)
- return 0;
-
- pmat->xx = INT_TO_FIXED(lfWidth) / tmAveCharWidth;
- pmat->xy = 0;
- pmat->yx = 0;
- pmat->yy = INT_TO_FIXED(1);
- return lfWidth;
+ nTenthsOfDegrees %= 360 * 10;
+ if (nTenthsOfDegrees >= 0)
+ return nTenthsOfDegrees;
+ return nTenthsOfDegrees + 360 * 10;
}
VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement)
@@ -2188,12 +2163,13 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI,
- ((Ascent + Descent)
- (pHori->Ascender - pHori->Descender)),
YScale) + 32) >> 6);
+ if (FontGDI->lfWidth != 0)
+ TM->tmAveCharWidth = FontGDI->lfWidth;
+ else
+ TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >>
6;
- TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
if (TM->tmAveCharWidth == 0)
- {
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;
@@ -3145,6 +3121,7 @@ ftGdiGlyphCacheGet(IN const FONT_CACHE_ENTRY *pCache)
FontEntry->Hashed.GlyphIndex == pCache->Hashed.GlyphIndex &&
FontEntry->Hashed.Face == pCache->Hashed.Face &&
FontEntry->Hashed.lfHeight == pCache->Hashed.lfHeight &&
+ FontEntry->Hashed.lfWidth == pCache->Hashed.lfWidth &&
FontEntry->Hashed.AspectValue == pCache->Hashed.AspectValue &&
memcmp(&FontEntry->Hashed.matTransform,
&pCache->Hashed.matTransform,
sizeof(FT_Matrix)) == 0)
@@ -3478,7 +3455,7 @@ IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG
lfHeight)
TT_OS2 *pOS2;
TT_HoriHeader *pHori;
FT_WinFNT_HeaderRec WinFNT;
- LONG Ascent, Descent, Sum, EmHeight;
+ LONG Ascent, Descent, Sum, EmHeight, Width64;
lfWidth = abs(lfWidth);
if (lfHeight == 0)
@@ -3497,8 +3474,12 @@ IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG
lfHeight)
if (lfHeight == -1)
lfHeight = -2;
- if (FontGDI->Magic == FONTGDI_MAGIC && FontGDI->lfHeight == lfHeight)
+ if (FontGDI->Magic == FONTGDI_MAGIC &&
+ FontGDI->lfHeight == lfHeight &&
+ FontGDI->lfWidth == lfWidth)
+ {
return 0; /* Cached */
+ }
ASSERT_FREETYPE_LOCK_HELD();
pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
@@ -3520,6 +3501,7 @@ IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG
lfHeight)
FontGDI->tmInternalLeading = WinFNT.internal_leading;
FontGDI->Magic = FONTGDI_MAGIC;
FontGDI->lfHeight = lfHeight;
+ FontGDI->lfWidth = lfWidth;
return 0;
}
@@ -3574,13 +3556,19 @@ IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG
lfHeight)
FontGDI->Magic = FONTGDI_MAGIC;
FontGDI->lfHeight = lfHeight;
+ FontGDI->lfWidth = lfWidth;
EmHeight = FontGDI->tmHeight - FontGDI->tmInternalLeading;
EmHeight = max(EmHeight, 1);
EmHeight = min(EmHeight, USHORT_MAX);
+ if (pOS2 && lfWidth > 0)
+ Width64 = FT_MulDiv(lfWidth, face->units_per_EM, pOS2->xAvgCharWidth)
<< 6;
+ else
+ Width64 = 0;
+
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
- req.width = 0;
+ req.width = Width64;
req.height = (EmHeight << 6);
req.horiResolution = 0;
req.vertResolution = 0;
@@ -3805,7 +3793,7 @@ ftGdiGetGlyphOutline(
IntLockFreeType();
TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
FtMatrixFromMx(&mat, DC_pmxWorldToDevice(dc));
- FT_Set_Transform(ft_face, &mat, 0);
+ FT_Set_Transform(ft_face, &mat, NULL);
TEXTOBJ_UnlockText(TextObj);
@@ -4274,10 +4262,10 @@ TextIntGetTextExtentPoint(PDC dc,
{
PFONTGDI FontGDI;
FT_BitmapGlyph realglyph;
- INT glyph_index, i, previous;
+ INT glyph_index, i, previous, nTenthsOfDegrees;
ULONGLONG TotalWidth64 = 0;
LOGFONTW *plf;
- BOOL use_kerning;
+ BOOL use_kerning, bVerticalWriting;
LONG ascender, descender;
FONT_CACHE_ENTRY Cache;
@@ -4289,27 +4277,26 @@ TextIntGetTextExtentPoint(PDC dc,
*Fit = 0;
}
- IntLockFreeType();
-
- TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
-
plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
Cache.Hashed.lfHeight = plf->lfHeight;
+ Cache.Hashed.lfWidth = plf->lfWidth;
Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight,
plf->lfWeight);
Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic &&
!FontGDI->OriginalItalic);
+ // Check vertical writing (tategaki)
+ nTenthsOfDegrees = IntNormalizeAngle(plf->lfEscapement - plf->lfOrientation);
+ bVerticalWriting = ((nTenthsOfDegrees == 90 * 10) || (nTenthsOfDegrees == 270 *
10));
+
if (IntIsFontRenderingEnabled())
Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
else
Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
// NOTE: GetTextExtentPoint32 simply ignores lfEscapement and XFORM.
- if (FT_IS_SCALABLE(Cache.Hashed.Face) && plf->lfWidth != 0)
- IntWidthMatrix(Cache.Hashed.Face, &Cache.Hashed.matTransform,
plf->lfWidth);
- else
- Cache.Hashed.matTransform = identityMat;
-
- FT_Set_Transform(Cache.Hashed.Face, &Cache.Hashed.matTransform, 0);
+ IntLockFreeType();
+ TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
+ Cache.Hashed.matTransform = identityMat;
+ FT_Set_Transform(Cache.Hashed.Face, NULL, NULL);
use_kerning = FT_HAS_KERNING(Cache.Hashed.Face);
previous = 0;
@@ -4356,8 +4343,16 @@ TextIntGetTextExtentPoint(PDC dc,
descender = FontGDI->tmDescent; /* Units below baseline */
IntUnLockFreeType();
- Size->cx = (TotalWidth64 + 32) >> 6;
- Size->cy = ascender + descender;
+ if (bVerticalWriting)
+ {
+ Size->cx = ascender + descender;
+ Size->cy = (TotalWidth64 + 32) >> 6;
+ }
+ else
+ {
+ Size->cx = (TotalWidth64 + 32) >> 6;
+ Size->cy = ascender + descender;
+ }
return TRUE;
}
@@ -4561,7 +4556,6 @@ ftGdiGetTextMetricsW(
ULONG Error;
NTSTATUS Status = STATUS_SUCCESS;
LOGFONTW *plf;
- FT_Matrix mat;
if (!ptmwi)
{
@@ -4584,10 +4578,11 @@ ftGdiGetTextMetricsW(
Face = FontGDI->SharedFace->Face;
+ // NOTE: GetTextMetrics simply ignores lfEscapement and XFORM.
IntLockFreeType();
Error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
- FtMatrixFromMx(&mat, DC_pmxWorldToDevice(dc));
- FT_Set_Transform(Face, &mat, 0);
+ FT_Set_Transform(Face, NULL, NULL);
+
IntUnLockFreeType();
if (0 != Error)
@@ -4597,7 +4592,6 @@ ftGdiGetTextMetricsW(
}
else
{
- FT_Face Face = FontGDI->SharedFace->Face;
Status = STATUS_SUCCESS;
IntLockFreeType();
@@ -6073,6 +6067,7 @@ IntExtTextOutW(
plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
Cache.Hashed.lfHeight = plf->lfHeight;
+ Cache.Hashed.lfWidth = plf->lfWidth;
Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight,
plf->lfWeight);
Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic &&
!FontGDI->OriginalItalic);
@@ -6093,7 +6088,7 @@ IntExtTextOutW(
{
pmxWorldToDevice = DC_pmxWorldToDevice(dc);
FtMatrixFromMx(&Cache.Hashed.matTransform, pmxWorldToDevice);
- FT_Set_Transform(face, &Cache.Hashed.matTransform, 0);
+ FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL);
fixAscender = ScaleLong(FontGDI->tmAscent, &pmxWorldToDevice->efM22)
<< 6;
fixDescender = ScaleLong(FontGDI->tmDescent, &pmxWorldToDevice->efM22)
<< 6;
@@ -6102,7 +6097,7 @@ IntExtTextOutW(
{
pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
FtMatrixFromMx(&Cache.Hashed.matTransform, pmxWorldToDevice);
- FT_Set_Transform(face, &Cache.Hashed.matTransform, 0);
+ FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL);
fixAscender = FontGDI->tmAscent << 6;
fixDescender = FontGDI->tmDescent << 6;
@@ -6594,11 +6589,9 @@ NtGdiGetCharABCWidthsW(
PFONTGDI FontGDI;
FT_Face face;
FT_CharMap charmap, found = NULL;
- FT_Matrix mat;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
NTSTATUS Status = STATUS_SUCCESS;
- PMATRIX pmxWorldToDevice;
PWCHAR Safepwch = NULL;
LOGFONTW *plf;
@@ -6668,8 +6661,6 @@ NtGdiGetCharABCWidthsW(
hFont = pdcattr->hlfntNew;
TextObj = RealizeFontInit(hFont);
- /* Get the DC's world-to-device transformation matrix */
- pmxWorldToDevice = DC_pmxWorldToDevice(dc);
DC_UnlockDc(dc);
if (TextObj == NULL)
@@ -6716,10 +6707,11 @@ NtGdiGetCharABCWidthsW(
}
plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
+
+ // NOTE: GetCharABCWidths simply ignores lfEscapement and XFORM.
IntLockFreeType();
IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
- FtMatrixFromMx(&mat, pmxWorldToDevice);
- FT_Set_Transform(face, &mat, 0);
+ FT_Set_Transform(face, NULL, NULL);
for (i = FirstChar; i < FirstChar+Count; i++)
{
@@ -6801,10 +6793,8 @@ NtGdiGetCharWidthW(
PFONTGDI FontGDI;
FT_Face face;
FT_CharMap charmap, found = NULL;
- FT_Matrix mat;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
- PMATRIX pmxWorldToDevice;
PWCHAR Safepwc = NULL;
LOGFONTW *plf;
@@ -6861,8 +6851,6 @@ NtGdiGetCharWidthW(
pdcattr = dc->pdcattr;
hFont = pdcattr->hlfntNew;
TextObj = RealizeFontInit(hFont);
- /* Get the DC's world-to-device transformation matrix */
- pmxWorldToDevice = DC_pmxWorldToDevice(dc);
DC_UnlockDc(dc);
if (TextObj == NULL)
@@ -6908,10 +6896,11 @@ NtGdiGetCharWidthW(
}
plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
+
+ // NOTE: GetCharWidth simply ignores lfEscapement and XFORM.
IntLockFreeType();
IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
- FtMatrixFromMx(&mat, pmxWorldToDevice);
- FT_Set_Transform(face, &mat, 0);
+ FT_Set_Transform(face, NULL, NULL);
for (i = FirstChar; i < FirstChar+Count; i++)
{