[NTGDI][FREETYPE] Add special structure for hashing (#4916)

Add FONT_CACHE_HASHED structure and use it.
CORE-11848
This commit is contained in:
Katayama Hirofumi MZ 2022-11-29 19:41:09 +09:00 committed by GitHub
parent 062a8f20a9
commit 4d0d22aee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 79 deletions

View File

@ -25,42 +25,42 @@ typedef struct _FONT_ENTRY_COLL_MEM
#include <pshpack1.h> /* We don't like padding for these structures for hashing */ #include <pshpack1.h> /* We don't like padding for these structures for hashing */
typedef struct _EMULATION_BOLD_ITALIC
{
BYTE Bold;
BYTE Italic;
} EMULATION_BOLD_ITALIC, *PEMULATION_BOLD_ITALIC;
typedef struct _FONT_ASPECT typedef struct _FONT_ASPECT
{ {
_ANONYMOUS_UNION union { _ANONYMOUS_UNION union {
EMULATION_BOLD_ITALIC Emu;
WORD EmuBoldItalic; WORD EmuBoldItalic;
struct {
BYTE Bold;
BYTE Italic;
} Emu;
} DUMMYUNIONNAME; } DUMMYUNIONNAME;
WORD RenderMode; WORD RenderMode;
} FONT_ASPECT, *PFONT_ASPECT; } FONT_ASPECT, *PFONT_ASPECT;
typedef struct _FONT_CACHE_HASHED
{
INT GlyphIndex;
FT_Face Face;
LONG lfHeight;
_ANONYMOUS_UNION union {
DWORD AspectValue;
FONT_ASPECT Aspect;
} DUMMYUNIONNAME;
FT_Matrix matTransform;
} FONT_CACHE_HASHED, *PFONT_CACHE_HASHED;
#include <poppack.h>
typedef struct _FONT_CACHE_ENTRY typedef struct _FONT_CACHE_ENTRY
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
FT_BitmapGlyph BitmapGlyph; FT_BitmapGlyph BitmapGlyph;
DWORD dwHash; DWORD dwHash;
FONT_CACHE_HASHED Hashed;
/* The following members are hashed */
INT GlyphIndex;
FT_Face Face;
LONG lfHeight;
_ANONYMOUS_UNION union {
FONT_ASPECT Aspect;
DWORD AspectValue;
} DUMMYUNIONNAME;
FT_Matrix matTransform;
} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY; } FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
#include <poppack.h> C_ASSERT(FIELD_OFFSET(FONT_CACHE_ENTRY, Hashed) % sizeof(DWORD) == 0); /* for hashing */
C_ASSERT(sizeof(FONT_CACHE_HASHED) % sizeof(DWORD) == 0); /* for hashing */
C_ASSERT(FIELD_OFFSET(FONT_CACHE_ENTRY, GlyphIndex) % sizeof(DWORD) == 0); /* for hashing */
C_ASSERT(sizeof(FONT_CACHE_ENTRY) % sizeof(DWORD) == 0); /* for hashing */
/* /*
* FONTSUBST_... --- constants for font substitutes * FONTSUBST_... --- constants for font substitutes

View File

@ -280,7 +280,7 @@ RemoveCacheEntries(FT_Face Face)
FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry); FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
NextEntry = CurrentEntry->Flink; NextEntry = CurrentEntry->Flink;
if (FontEntry->Face == Face) if (FontEntry->Hashed.Face == Face)
{ {
RemoveCachedEntry(FontEntry); RemoveCachedEntry(FontEntry);
} }
@ -3142,11 +3142,12 @@ ftGdiGlyphCacheGet(IN const FONT_CACHE_ENTRY *pCache)
{ {
FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry); FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
if (FontEntry->dwHash == dwHash && if (FontEntry->dwHash == dwHash &&
FontEntry->GlyphIndex == pCache->GlyphIndex && FontEntry->Hashed.GlyphIndex == pCache->Hashed.GlyphIndex &&
FontEntry->Face == pCache->Face && FontEntry->Hashed.Face == pCache->Hashed.Face &&
FontEntry->lfHeight == pCache->lfHeight && FontEntry->Hashed.lfHeight == pCache->Hashed.lfHeight &&
FontEntry->AspectValue == pCache->AspectValue && FontEntry->Hashed.AspectValue == pCache->Hashed.AspectValue &&
memcmp(&FontEntry->matTransform, &pCache->matTransform, sizeof(FT_Matrix)) == 0) memcmp(&FontEntry->Hashed.matTransform, &pCache->Hashed.matTransform,
sizeof(FT_Matrix)) == 0)
{ {
break; break;
} }
@ -3226,7 +3227,7 @@ ftGdiGlyphCacheSet(
return NULL; return NULL;
}; };
error = FT_Glyph_To_Bitmap(&GlyphCopy, Cache->Aspect.RenderMode, 0, 1); error = FT_Glyph_To_Bitmap(&GlyphCopy, Cache->Hashed.Aspect.RenderMode, 0, 1);
if (error) if (error)
{ {
FT_Done_Glyph(GlyphCopy); FT_Done_Glyph(GlyphCopy);
@ -3257,8 +3258,8 @@ ftGdiGlyphCacheSet(
BitmapGlyph->bitmap = AlignedBitmap; BitmapGlyph->bitmap = AlignedBitmap;
NewEntry->BitmapGlyph = BitmapGlyph; NewEntry->BitmapGlyph = BitmapGlyph;
RtlCopyMemory(&NewEntry->dwHash, &Cache->dwHash, NewEntry->dwHash = Cache->dwHash;
sizeof(FONT_CACHE_ENTRY) - offsetof(FONT_CACHE_ENTRY, dwHash)); NewEntry->Hashed = Cache->Hashed;
InsertHeadList(&g_FontCacheListHead, &NewEntry->ListEntry); InsertHeadList(&g_FontCacheListHead, &NewEntry->ListEntry);
if (++g_FontCacheNumEntries > MAX_FONT_CACHE) if (++g_FontCacheNumEntries > MAX_FONT_CACHE)
@ -4213,49 +4214,48 @@ ftGdiGetRealGlyph(
INT error; INT error;
FT_GlyphSlot glyph; FT_GlyphSlot glyph;
FT_BitmapGlyph realglyph; FT_BitmapGlyph realglyph;
DWORD cdw;
ASSERT_FREETYPE_LOCK_HELD(); ASSERT_FREETYPE_LOCK_HELD();
if (Cache->Aspect.EmuBoldItalic) if (Cache->Hashed.Aspect.EmuBoldItalic)
{ {
error = FT_Load_Glyph(Cache->Face, Cache->GlyphIndex, FT_LOAD_NO_BITMAP); error = FT_Load_Glyph(Cache->Hashed.Face, Cache->Hashed.GlyphIndex, FT_LOAD_NO_BITMAP);
if (error) if (error)
{ {
DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", Cache->GlyphIndex); DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n",
Cache->Hashed.GlyphIndex);
return NULL; return NULL;
} }
glyph = Cache->Face->glyph; glyph = Cache->Hashed.Face->glyph;
if (Cache->Aspect.Emu.Bold) if (Cache->Hashed.Aspect.Emu.Bold)
FT_GlyphSlot_Embolden(glyph); FT_GlyphSlot_Embolden(glyph);
if (Cache->Aspect.Emu.Italic) if (Cache->Hashed.Aspect.Emu.Italic)
FT_GlyphSlot_Oblique(glyph); FT_GlyphSlot_Oblique(glyph);
realglyph = ftGdiGlyphSet(Cache->Face, glyph, Cache->Aspect.RenderMode); realglyph = ftGdiGlyphSet(Cache->Hashed.Face, glyph, Cache->Hashed.Aspect.RenderMode);
} }
else else
{ {
cdw = (sizeof(FONT_CACHE_ENTRY) - offsetof(FONT_CACHE_ENTRY, GlyphIndex)) / sizeof(DWORD); Cache->dwHash = IntGetHash(&Cache->Hashed, sizeof(Cache->Hashed) / sizeof(DWORD));
Cache->dwHash = IntGetHash(&Cache->GlyphIndex, cdw);
realglyph = ftGdiGlyphCacheGet(Cache); realglyph = ftGdiGlyphCacheGet(Cache);
if (realglyph) if (realglyph)
return realglyph; return realglyph;
error = FT_Load_Glyph(Cache->Face, Cache->GlyphIndex, FT_LOAD_DEFAULT); error = FT_Load_Glyph(Cache->Hashed.Face, Cache->Hashed.GlyphIndex, FT_LOAD_DEFAULT);
if (error) if (error)
{ {
DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", Cache->GlyphIndex); DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
return NULL; return NULL;
} }
glyph = Cache->Face->glyph; glyph = Cache->Hashed.Face->glyph;
realglyph = ftGdiGlyphCacheSet(Cache, glyph); realglyph = ftGdiGlyphCacheSet(Cache, glyph);
} }
if (!realglyph) if (!realglyph)
DPRINT1("Failed to render glyph! [index: %d]\n", Cache->GlyphIndex); DPRINT1("Failed to render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
return realglyph; return realglyph;
} }
@ -4283,7 +4283,7 @@ TextIntGetTextExtentPoint(PDC dc,
FontGDI = ObjToGDI(TextObj->Font, FONT); FontGDI = ObjToGDI(TextObj->Font, FONT);
Cache.Face = FontGDI->SharedFace->Face; Cache.Hashed.Face = FontGDI->SharedFace->Face;
if (NULL != Fit) if (NULL != Fit)
{ {
*Fit = 0; *Fit = 0;
@ -4294,30 +4294,30 @@ TextIntGetTextExtentPoint(PDC dc,
TextIntUpdateSize(dc, TextObj, FontGDI, FALSE); TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont; plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
Cache.lfHeight = plf->lfHeight; Cache.Hashed.lfHeight = plf->lfHeight;
Cache.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight); Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
Cache.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic); Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
if (IntIsFontRenderingEnabled()) if (IntIsFontRenderingEnabled())
Cache.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf); Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
else else
Cache.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO; Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
// NOTE: GetTextExtentPoint32 simply ignores lfEscapement and XFORM. // NOTE: GetTextExtentPoint32 simply ignores lfEscapement and XFORM.
if (FT_IS_SCALABLE(Cache.Face) && plf->lfWidth != 0) if (FT_IS_SCALABLE(Cache.Hashed.Face) && plf->lfWidth != 0)
IntWidthMatrix(Cache.Face, &Cache.matTransform, plf->lfWidth); IntWidthMatrix(Cache.Hashed.Face, &Cache.Hashed.matTransform, plf->lfWidth);
else else
Cache.matTransform = identityMat; Cache.Hashed.matTransform = identityMat;
FT_Set_Transform(Cache.Face, &Cache.matTransform, 0); FT_Set_Transform(Cache.Hashed.Face, &Cache.Hashed.matTransform, 0);
use_kerning = FT_HAS_KERNING(Cache.Face); use_kerning = FT_HAS_KERNING(Cache.Hashed.Face);
previous = 0; previous = 0;
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {
glyph_index = get_glyph_index_flagged(Cache.Face, *String, GTEF_INDICES, fl); glyph_index = get_glyph_index_flagged(Cache.Hashed.Face, *String, GTEF_INDICES, fl);
Cache.GlyphIndex = glyph_index; Cache.Hashed.GlyphIndex = glyph_index;
realglyph = ftGdiGetRealGlyph(&Cache); realglyph = ftGdiGetRealGlyph(&Cache);
if (!realglyph) if (!realglyph)
@ -4327,7 +4327,7 @@ TextIntGetTextExtentPoint(PDC dc,
if (use_kerning && previous && glyph_index) if (use_kerning && previous && glyph_index)
{ {
FT_Vector delta; FT_Vector delta;
FT_Get_Kerning(Cache.Face, previous, glyph_index, 0, &delta); FT_Get_Kerning(Cache.Hashed.Face, previous, glyph_index, 0, &delta);
TotalWidth64 += delta.x; TotalWidth64 += delta.x;
} }
@ -4337,14 +4337,13 @@ TextIntGetTextExtentPoint(PDC dc,
{ {
*Fit = i + 1; *Fit = i + 1;
} }
if (NULL != Dx) if (NULL != Dx)
{ {
Dx[i] = (TotalWidth64 + 32) >> 6; Dx[i] = (TotalWidth64 + 32) >> 6;
} }
/* Bold and italic do not use the cache */ /* Bold and italic do not use the cache */
if (Cache.Aspect.EmuBoldItalic) if (Cache.Hashed.Aspect.EmuBoldItalic)
{ {
FT_Done_Glyph((FT_Glyph)realglyph); FT_Done_Glyph((FT_Glyph)realglyph);
} }
@ -5874,7 +5873,7 @@ ftGdiGetTextWidth(
LONGLONG TextLeft64 = 0; LONGLONG TextLeft64 = 0;
INT glyph_index; INT glyph_index;
FT_BitmapGlyph realglyph; FT_BitmapGlyph realglyph;
FT_Face face = Cache->Face; FT_Face face = Cache->Hashed.Face;
BOOL use_kerning = FT_HAS_KERNING(face); BOOL use_kerning = FT_HAS_KERNING(face);
ULONG previous = 0; ULONG previous = 0;
FT_Vector delta; FT_Vector delta;
@ -5884,7 +5883,7 @@ ftGdiGetTextWidth(
while (Count-- > 0) while (Count-- > 0)
{ {
glyph_index = get_glyph_index_flagged(face, *String, ETO_GLYPH_INDEX, fuOptions); glyph_index = get_glyph_index_flagged(face, *String, ETO_GLYPH_INDEX, fuOptions);
Cache->GlyphIndex = glyph_index; Cache->Hashed.GlyphIndex = glyph_index;
realglyph = ftGdiGetRealGlyph(Cache); realglyph = ftGdiGetRealGlyph(Cache);
if (!realglyph) if (!realglyph)
@ -5899,7 +5898,7 @@ ftGdiGetTextWidth(
TextLeft64 += realglyph->root.advance.x >> 10; TextLeft64 += realglyph->root.advance.x >> 10;
if (Cache->Aspect.EmuBoldItalic) if (Cache->Hashed.Aspect.EmuBoldItalic)
FT_Done_Glyph((FT_Glyph)realglyph); FT_Done_Glyph((FT_Glyph)realglyph);
previous = glyph_index; previous = glyph_index;
@ -6070,18 +6069,17 @@ IntExtTextOutW(
ASSERT(FontGDI); ASSERT(FontGDI);
IntLockFreeType(); IntLockFreeType();
Cache.Face = face = FontGDI->SharedFace->Face; Cache.Hashed.Face = face = FontGDI->SharedFace->Face;
plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont; plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
Cache.lfHeight = plf->lfHeight; Cache.Hashed.lfHeight = plf->lfHeight;
Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
Cache.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight); Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
Cache.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
if (IntIsFontRenderingEnabled()) if (IntIsFontRenderingEnabled())
Cache.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf); Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
else else
Cache.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO; Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
if (!TextIntUpdateSize(dc, TextObj, FontGDI, FALSE)) if (!TextIntUpdateSize(dc, TextObj, FontGDI, FALSE))
{ {
@ -6094,8 +6092,8 @@ IntExtTextOutW(
if (pdcattr->iGraphicsMode == GM_ADVANCED) if (pdcattr->iGraphicsMode == GM_ADVANCED)
{ {
pmxWorldToDevice = DC_pmxWorldToDevice(dc); pmxWorldToDevice = DC_pmxWorldToDevice(dc);
FtMatrixFromMx(&Cache.matTransform, pmxWorldToDevice); FtMatrixFromMx(&Cache.Hashed.matTransform, pmxWorldToDevice);
FT_Set_Transform(face, &Cache.matTransform, 0); FT_Set_Transform(face, &Cache.Hashed.matTransform, 0);
fixAscender = ScaleLong(FontGDI->tmAscent, &pmxWorldToDevice->efM22) << 6; fixAscender = ScaleLong(FontGDI->tmAscent, &pmxWorldToDevice->efM22) << 6;
fixDescender = ScaleLong(FontGDI->tmDescent, &pmxWorldToDevice->efM22) << 6; fixDescender = ScaleLong(FontGDI->tmDescent, &pmxWorldToDevice->efM22) << 6;
@ -6103,8 +6101,8 @@ IntExtTextOutW(
else else
{ {
pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault; pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
FtMatrixFromMx(&Cache.matTransform, pmxWorldToDevice); FtMatrixFromMx(&Cache.Hashed.matTransform, pmxWorldToDevice);
FT_Set_Transform(face, &Cache.matTransform, 0); FT_Set_Transform(face, &Cache.Hashed.matTransform, 0);
fixAscender = FontGDI->tmAscent << 6; fixAscender = FontGDI->tmAscent << 6;
fixDescender = FontGDI->tmDescent << 6; fixDescender = FontGDI->tmDescent << 6;
@ -6197,7 +6195,7 @@ IntExtTextOutW(
for (i = 0; i < Count; ++i) for (i = 0; i < Count; ++i)
{ {
glyph_index = get_glyph_index_flagged(face, *String++, ETO_GLYPH_INDEX, fuOptions); glyph_index = get_glyph_index_flagged(face, *String++, ETO_GLYPH_INDEX, fuOptions);
Cache.GlyphIndex = glyph_index; Cache.Hashed.GlyphIndex = glyph_index;
realglyph = ftGdiGetRealGlyph(&Cache); realglyph = ftGdiGetRealGlyph(&Cache);
if (!realglyph) if (!realglyph)
@ -6243,7 +6241,7 @@ IntExtTextOutW(
{ {
DPRINT1("WARNING: EngCreateBitmap() failed!\n"); DPRINT1("WARNING: EngCreateBitmap() failed!\n");
bResult = FALSE; bResult = FALSE;
if (Cache.Aspect.EmuBoldItalic) if (Cache.Hashed.Aspect.EmuBoldItalic)
FT_Done_Glyph((FT_Glyph)realglyph); FT_Done_Glyph((FT_Glyph)realglyph);
break; break;
} }
@ -6254,7 +6252,7 @@ IntExtTextOutW(
EngDeleteSurface((HSURF)HSourceGlyph); EngDeleteSurface((HSURF)HSourceGlyph);
DPRINT1("WARNING: EngLockSurface() failed!\n"); DPRINT1("WARNING: EngLockSurface() failed!\n");
bResult = FALSE; bResult = FALSE;
if (Cache.Aspect.EmuBoldItalic) if (Cache.Hashed.Aspect.EmuBoldItalic)
FT_Done_Glyph((FT_Glyph)realglyph); FT_Done_Glyph((FT_Glyph)realglyph);
break; break;
} }
@ -6305,7 +6303,7 @@ IntExtTextOutW(
if (DoBreak) if (DoBreak)
{ {
if (Cache.Aspect.EmuBoldItalic) if (Cache.Hashed.Aspect.EmuBoldItalic)
FT_Done_Glyph((FT_Glyph)realglyph); FT_Done_Glyph((FT_Glyph)realglyph);
break; break;
} }
@ -6335,7 +6333,7 @@ IntExtTextOutW(
previous = glyph_index; previous = glyph_index;
if (Cache.Aspect.EmuBoldItalic) if (Cache.Hashed.Aspect.EmuBoldItalic)
{ {
FT_Done_Glyph((FT_Glyph)realglyph); FT_Done_Glyph((FT_Glyph)realglyph);
} }