[0.4.10][USP10] Slightly tweak our intermediate fix

CORE-14226 was already effectively fixed by
0.4.11-RC-3-g 2fc4683
0.4.10-RC-3-g 71ea3f9
0.4.9-RC-4-g c19ce95
0.4.8-RC-5-g 937c261
and therefore no release ever was affected by it,
but today I undo the intermediate and sync to the final state of this fix
like we did commit it into master after Wine review
by master commit 0.4.12-dev-151-g c086edf366
The final fixes commit message:

[USP10] Don't mix character and glyph index caches. CORE-14226

Import Wine commits by Nikolay Sivov:
* d1e618d31da usp10: Use glyph index consistently in ScriptGetGlyphABCWidth().
* 8d018d8d1da usp10: Make sure metrics cache is used with glyph indices only.
* eda3a3e37da usp10: Remove extra parentheses.

Fixes font display in UltraISO and GOG and many other installers.

See also https://bugs.winehq.org/show_bug.cgi?id=44410
This commit is contained in:
Joachim Henze 2020-11-15 23:11:07 +01:00
parent a6b3d2131d
commit 5dc9c8846b
2 changed files with 27 additions and 28 deletions

View file

@ -842,23 +842,19 @@ static inline WORD set_cache_glyph(SCRIPT_CACHE *psc, WCHAR c, WORD glyph)
return ((*block)[(c % 0x10000) & GLYPH_BLOCK_MASK] = glyph); return ((*block)[(c % 0x10000) & GLYPH_BLOCK_MASK] = glyph);
} }
static inline BOOL get_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc, BOOL no_glyph_index) static inline BOOL get_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
{ {
static const ABC nil; static const ABC nil;
ABC *block = no_glyph_index ? ABC *block = ((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT] :
((ScriptCache *)*psc)->glyph_widths[glyph >> GLYPH_BLOCK_SHIFT];
if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil, sizeof(ABC))) return FALSE; if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil, sizeof(ABC))) return FALSE;
memcpy(abc, &block[glyph & GLYPH_BLOCK_MASK], sizeof(ABC)); memcpy(abc, &block[glyph & GLYPH_BLOCK_MASK], sizeof(ABC));
return TRUE; return TRUE;
} }
static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc, BOOL no_glyph_index) static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
{ {
ABC **block = no_glyph_index ? ABC **block = &((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
&((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT] :
&((ScriptCache *)*psc)->glyph_widths[glyph >> GLYPH_BLOCK_SHIFT];
if (!*block && !(*block = heap_alloc_zero(sizeof(ABC) * GLYPH_BLOCK_SIZE))) return FALSE; if (!*block && !(*block = heap_alloc_zero(sizeof(ABC) * GLYPH_BLOCK_SIZE))) return FALSE;
memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], abc, sizeof(ABC)); memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], abc, sizeof(ABC));
@ -3420,35 +3416,41 @@ HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS
if (pABC) memset(pABC, 0, sizeof(ABC)); if (pABC) memset(pABC, 0, sizeof(ABC));
for (i = 0; i < cGlyphs; i++) for (i = 0; i < cGlyphs; i++)
{ {
WORD glyph;
ABC abc; ABC abc;
/* FIXME: set to more reasonable values */
pGoffset[i].du = pGoffset[i].dv = 0;
if (pGlyphProps[i].sva.fZeroWidth) if (pGlyphProps[i].sva.fZeroWidth)
{ {
abc.abcA = abc.abcB = abc.abcC = 0; abc.abcA = abc.abcB = abc.abcC = 0;
if (piAdvance) piAdvance[i] = 0;
continue;
} }
else if (!get_cache_glyph_widths(psc, pwGlyphs[i], &abc, psa->fNoGlyphIndex))
if (psa->fNoGlyphIndex)
{
if (FAILED(hr = ScriptGetCMap(hdc, psc, &pwGlyphs[i], 1, 0, &glyph))) return hr;
}
else
glyph = pwGlyphs[i];
if (!get_cache_glyph_widths(psc, glyph, &abc))
{ {
BOOL ret;
if (!hdc) return E_PENDING; if (!hdc) return E_PENDING;
if (get_cache_pitch_family(psc) & TMPF_TRUETYPE) if (get_cache_pitch_family(psc) & TMPF_TRUETYPE)
{ {
if (psa->fNoGlyphIndex) if (!GetCharABCWidthsI(hdc, glyph, 1, NULL, &abc)) return S_FALSE;
ret = GetCharABCWidthsW(hdc, pwGlyphs[i], pwGlyphs[i], &abc);
else
ret = GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc);
if (!ret) return S_FALSE;
} }
else else
{ {
INT width; INT width;
if (psa->fNoGlyphIndex) if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
ret = GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width);
else
ret = GetCharWidthI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &width);
if (!ret) return S_FALSE;
abc.abcB = width; abc.abcB = width;
abc.abcA = abc.abcC = 0; abc.abcA = abc.abcC = 0;
} }
set_cache_glyph_widths(psc, pwGlyphs[i], &abc, psa->fNoGlyphIndex); set_cache_glyph_widths(psc, glyph, &abc);
} }
if (pABC) if (pABC)
{ {
@ -3456,8 +3458,6 @@ HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS
pABC->abcB += abc.abcB; pABC->abcB += abc.abcB;
pABC->abcC += abc.abcC; pABC->abcC += abc.abcC;
} }
/* FIXME: set to more reasonable values */
pGoffset[i].du = pGoffset[i].dv = 0;
if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC; if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC;
} }
@ -3709,21 +3709,21 @@ HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, AB
if (!abc) return E_INVALIDARG; if (!abc) return E_INVALIDARG;
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
if (!get_cache_glyph_widths(psc, glyph, abc, FALSE)) if (!get_cache_glyph_widths(psc, glyph, abc))
{ {
if (!hdc) return E_PENDING; if (!hdc) return E_PENDING;
if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE)) if (get_cache_pitch_family(psc) & TMPF_TRUETYPE)
{ {
if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE; if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE;
} }
else else
{ {
INT width; INT width;
if (!GetCharWidth32W(hdc, glyph, glyph, &width)) return S_FALSE; if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
abc->abcB = width; abc->abcB = width;
abc->abcA = abc->abcC = 0; abc->abcA = abc->abcC = 0;
} }
set_cache_glyph_widths(psc, glyph, abc, FALSE); set_cache_glyph_widths(psc, glyph, abc);
} }
return S_OK; return S_OK;
} }

View file

@ -201,7 +201,6 @@ typedef struct {
BOOL sfnt; BOOL sfnt;
CacheGlyphPage *page[NUM_PAGES]; CacheGlyphPage *page[NUM_PAGES];
ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE]; ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
ABC *glyph_widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
void *GSUB_Table; void *GSUB_Table;
void *GDEF_Table; void *GDEF_Table;
void *CMAP_Table; void *CMAP_Table;