Commit addcf866 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

usp10: Store glyph mappings and widths in the script cache.

parent fa6a31ab
...@@ -61,13 +61,22 @@ static void test_ScriptShape(HDC hdc) ...@@ -61,13 +61,22 @@ static void test_ScriptShape(HDC hdc)
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, NULL); hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, NULL);
ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr); ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr);
hr = ScriptShape(NULL, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb);
ok(hr == E_PENDING, "ScriptShape should return E_PENDING not %08x\n", hr);
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb); hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb);
ok(!hr, "ScriptShape should return S_OK not %08x\n", hr); ok(!hr, "ScriptShape should return S_OK not %08x\n", hr);
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
hr = ScriptShape(NULL, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb);
ok(!hr, "ScriptShape should return S_OK not %08x\n", hr);
hr = ScriptPlace(hdc, &sc, glyphs, 4, NULL, &items[0].a, widths, NULL, NULL); hr = ScriptPlace(hdc, &sc, glyphs, 4, NULL, &items[0].a, widths, NULL, NULL);
ok(hr == E_INVALIDARG, "ScriptPlace should return E_INVALIDARG not %08x\n", hr); ok(hr == E_INVALIDARG, "ScriptPlace should return E_INVALIDARG not %08x\n", hr);
hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL);
ok(hr == E_PENDING, "ScriptPlace should return E_PENDING not %08x\n", hr);
hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL); hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL);
ok(!hr, "ScriptPlace should return S_OK not %08x\n", hr); ok(!hr, "ScriptPlace should return S_OK not %08x\n", hr);
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
...@@ -1394,7 +1403,7 @@ START_TEST(usp10) ...@@ -1394,7 +1403,7 @@ START_TEST(usp10)
ok( hdc != NULL, "HDC failed to be created %p\n", hdc); ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
memset(&lf, 0, sizeof(LOGFONTA)); memset(&lf, 0, sizeof(LOGFONTA));
lstrcpyA(lf.lfFaceName, "Symbol"); lstrcpyA(lf.lfFaceName, "Tahoma");
lf.lfHeight = 10; lf.lfHeight = 10;
lf.lfWeight = 3; lf.lfWeight = 3;
lf.lfWidth = 10; lf.lfWidth = 10;
......
...@@ -138,10 +138,16 @@ static const SCRIPT_PROPERTIES *script_props[] = ...@@ -138,10 +138,16 @@ static const SCRIPT_PROPERTIES *script_props[] =
&props[73] &props[73]
}; };
#define GLYPH_BLOCK_SHIFT 8
#define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
#define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
#define GLYPH_MAX 65536
typedef struct { typedef struct {
HDC hdc;
LOGFONTW lf; LOGFONTW lf;
TEXTMETRICW tm; TEXTMETRICW tm;
WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE];
ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
} ScriptCache; } ScriptCache;
typedef struct { typedef struct {
...@@ -155,6 +161,7 @@ typedef struct { ...@@ -155,6 +161,7 @@ typedef struct {
} StringGlyphs; } StringGlyphs;
typedef struct { typedef struct {
HDC hdc;
BOOL invalid; BOOL invalid;
int clip_len; int clip_len;
ScriptCache *sc; ScriptCache *sc;
...@@ -187,71 +194,80 @@ static inline BOOL heap_free(LPVOID mem) ...@@ -187,71 +194,80 @@ static inline BOOL heap_free(LPVOID mem)
return HeapFree(GetProcessHeap(), 0, mem); return HeapFree(GetProcessHeap(), 0, mem);
} }
static HDC get_cache_hdc(SCRIPT_CACHE *psc) static inline WCHAR get_cache_default_char(SCRIPT_CACHE *psc)
{
return ((ScriptCache *)*psc)->hdc;
}
static WCHAR get_cache_default_char(SCRIPT_CACHE *psc)
{ {
return ((ScriptCache *)*psc)->tm.tmDefaultChar; return ((ScriptCache *)*psc)->tm.tmDefaultChar;
} }
static LONG get_cache_height(SCRIPT_CACHE *psc) static inline LONG get_cache_height(SCRIPT_CACHE *psc)
{ {
return ((ScriptCache *)*psc)->tm.tmHeight; return ((ScriptCache *)*psc)->tm.tmHeight;
} }
static BYTE get_cache_pitch_family(SCRIPT_CACHE *psc) static inline BYTE get_cache_pitch_family(SCRIPT_CACHE *psc)
{ {
return ((ScriptCache *)*psc)->tm.tmPitchAndFamily; return ((ScriptCache *)*psc)->tm.tmPitchAndFamily;
} }
static HRESULT init_script_cache(const HDC hdc, ScriptCache *sc) static inline WORD get_cache_glyph(SCRIPT_CACHE *psc, WCHAR c)
{ {
if (!GetTextMetricsW(hdc, &sc->tm)) return E_INVALIDARG; WORD *block = ((ScriptCache *)*psc)->glyphs[c >> GLYPH_BLOCK_SHIFT];
if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf)) return E_INVALIDARG;
sc->hdc = hdc; if (!block) return 0;
return S_OK; return block[c & GLYPH_BLOCK_MASK];
} }
static HRESULT get_script_cache(const HDC hdc, SCRIPT_CACHE *psc) static inline WORD set_cache_glyph(SCRIPT_CACHE *psc, WCHAR c, WORD glyph)
{
WORD **block = &((ScriptCache *)*psc)->glyphs[c >> GLYPH_BLOCK_SHIFT];
if (!*block && !(*block = heap_alloc_zero(sizeof(WORD) * GLYPH_BLOCK_SIZE))) return 0;
return ((*block)[c & GLYPH_BLOCK_MASK] = glyph);
}
static inline BOOL get_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
{
static const ABC nil;
ABC *block = ((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil, sizeof(ABC))) return FALSE;
memcpy(abc, &block[glyph & GLYPH_BLOCK_MASK], sizeof(ABC));
return TRUE;
}
static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
{
ABC **block = &((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
if (!*block && !(*block = heap_alloc_zero(sizeof(ABC) * GLYPH_BLOCK_SIZE))) return FALSE;
memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], abc, sizeof(ABC));
return TRUE;
}
static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc)
{ {
if (!psc) return E_INVALIDARG;
if (!*psc)
{
HRESULT ret;
ScriptCache *sc; ScriptCache *sc;
if (!psc) return E_INVALIDARG;
if (*psc) return S_OK;
if (!hdc) return E_PENDING; if (!hdc) return E_PENDING;
if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY; if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY;
ret = init_script_cache(hdc, sc); if (!GetTextMetricsW(hdc, &sc->tm))
if (ret != S_OK)
{ {
heap_free(sc); heap_free(sc);
return ret; return E_INVALIDARG;
} }
*psc = sc; if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf))
{
heap_free(sc);
return E_INVALIDARG;
} }
TRACE("<- %p\n", *psc); *psc = sc;
TRACE("<- %p\n", sc);
return S_OK; return S_OK;
} }
static HFONT select_cached_font(SCRIPT_CACHE *psc)
{
HFONT old_font;
ScriptCache *sc = *psc;
old_font = SelectObject(sc->hdc, CreateFontIndirectW(&sc->lf));
return old_font;
}
static void unselect_cached_font(SCRIPT_CACHE *psc, HFONT old_font)
{
ScriptCache *sc = *psc;
DeleteObject(SelectObject(sc->hdc, old_font));
}
/*********************************************************************** /***********************************************************************
* DllMain * DllMain
* *
...@@ -285,8 +301,14 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) ...@@ -285,8 +301,14 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
{ {
TRACE("%p\n", psc); TRACE("%p\n", psc);
if (psc) if (psc && *psc)
{
unsigned int i;
for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++)
{ {
heap_free(((ScriptCache *)*psc)->glyphs[i]);
heap_free(((ScriptCache *)*psc)->widths[i]);
}
heap_free(*psc); heap_free(*psc);
*psc = NULL; *psc = NULL;
} }
...@@ -338,10 +360,7 @@ HRESULT WINAPI ScriptGetFontProperties(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_FONTPR ...@@ -338,10 +360,7 @@ HRESULT WINAPI ScriptGetFontProperties(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_FONTPR
TRACE("%p,%p,%p\n", hdc, psc, sfp); TRACE("%p,%p,%p\n", hdc, psc, sfp);
if (!sfp) return E_INVALIDARG; if (!sfp) return E_INVALIDARG;
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
hr = get_script_cache(hdc, psc);
if (hr != S_OK)
return hr;
if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES)) if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES))
return E_INVALIDARG; return E_INVALIDARG;
...@@ -613,6 +632,7 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, ...@@ -613,6 +632,7 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString,
/* FIXME: handle clipping */ /* FIXME: handle clipping */
analysis->clip_len = cString; analysis->clip_len = cString;
analysis->hdc = hdc;
hr = ScriptItemize(pString, cString, num_items, psControl, psState, analysis->pItem, hr = ScriptItemize(pString, cString, num_items, psControl, psState, analysis->pItem,
&analysis->numItems); &analysis->numItems);
...@@ -757,7 +777,7 @@ HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, ...@@ -757,7 +777,7 @@ HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa,
cnt += analysis->glyphs[item].numGlyphs; /* point to the end of the copied text */ cnt += analysis->glyphs[item].numGlyphs; /* point to the end of the copied text */
} }
hr = ScriptTextOut(analysis->sc->hdc, (SCRIPT_CACHE *)&analysis->sc, iX, iY, hr = ScriptTextOut(analysis->hdc, (SCRIPT_CACHE *)&analysis->sc, iX, iY,
uOptions, prc, &analysis->pItem->a, NULL, 0, glyphs, cnt, uOptions, prc, &analysis->pItem->a, NULL, 0, glyphs, cnt,
analysis->glyphs->piAdvance, NULL, analysis->glyphs->pGoffset); analysis->glyphs->piAdvance, NULL, analysis->glyphs->pGoffset);
TRACE("ScriptTextOut hr=%08x\n", hr); TRACE("ScriptTextOut hr=%08x\n", hr);
...@@ -1242,9 +1262,8 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, ...@@ -1242,9 +1262,8 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust, SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust,
SCRIPT_VISATTR *psva, int *pcGlyphs) SCRIPT_VISATTR *psva, int *pcGlyphs)
{ {
int cnt;
HRESULT hr; HRESULT hr;
HFONT hfont; unsigned int i;
TRACE("(%p, %p, %p, %d, %d, %p)\n", hdc, psc, pwcChars, cChars, cMaxGlyphs, psa); TRACE("(%p, %p, %p, %d, %d, %p)\n", hdc, psc, pwcChars, cChars, cMaxGlyphs, psa);
if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL, if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL,
...@@ -1253,38 +1272,42 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, ...@@ -1253,38 +1272,42 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
if (!psva || !pcGlyphs) return E_INVALIDARG; if (!psva || !pcGlyphs) return E_INVALIDARG;
if (cChars > cMaxGlyphs) return E_OUTOFMEMORY; if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
hr = get_script_cache(hdc, psc);
if (hr != S_OK) return hr;
*pcGlyphs = cChars; *pcGlyphs = cChars;
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
hfont = select_cached_font(psc);
if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex) if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex)
{ {
GetGlyphIndicesW(get_cache_hdc(psc), pwcChars, cChars, pwOutGlyphs, 0); for (i = 0; i < cChars; i++)
{
if (!(pwOutGlyphs[i] = get_cache_glyph(psc, pwcChars[i])))
{
WORD glyph;
if (!hdc) return E_PENDING;
if (GetGlyphIndicesW(hdc, &pwcChars[i], 1, &glyph, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE;
pwOutGlyphs[i] = set_cache_glyph(psc, pwcChars[i], glyph);
}
}
} }
else else
{ {
TRACE("no glyph translation\n"); TRACE("no glyph translation\n");
for (cnt = 0; cnt < cChars; cnt++) pwOutGlyphs[cnt] = pwcChars[cnt]; for (i = 0; i < cChars; i++) pwOutGlyphs[i] = pwcChars[i];
} }
if (psva) if (psva)
{ {
/* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */ /* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */
for (cnt = 0; cnt < cChars; cnt++) for (i = 0; i < cChars; i++)
{ {
/* FIXME: set to better values */ /* FIXME: set to better values */
psva[cnt].uJustification = 2; psva[i].uJustification = 2;
psva[cnt].fClusterStart = 1; psva[i].fClusterStart = 1;
psva[cnt].fDiacritic = 0; psva[i].fDiacritic = 0;
psva[cnt].fZeroWidth = 0; psva[i].fZeroWidth = 0;
if (pwLogClust) pwLogClust[cnt] = cnt; if (pwLogClust) pwLogClust[i] = i;
} }
} }
unselect_cached_font(psc, hfont);
return S_OK; return S_OK;
} }
...@@ -1313,60 +1336,46 @@ HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, ...@@ -1313,60 +1336,46 @@ HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs,
SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC ) SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC )
{ {
HRESULT hr; HRESULT hr;
LPABC lpABC;
HFONT hfont;
unsigned int i; unsigned int i;
TRACE("(%p, %p, %p, %s, %d, %p, %p, %p)\n", hdc, psc, pwGlyphs, TRACE("(%p, %p, %p, %s, %d, %p, %p, %p)\n", hdc, psc, pwGlyphs,
debugstr_wn(pwGlyphs, cGlyphs), cGlyphs, psva, psa, piAdvance); debugstr_wn(pwGlyphs, cGlyphs), cGlyphs, psva, psa, piAdvance);
if (!psva) return E_INVALIDARG; if (!psva) return E_INVALIDARG;
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
hr = get_script_cache(hdc, psc);
if (hr != S_OK) return hr;
hfont = select_cached_font(psc);
/* Here we need to calculate the width of the run unit. At this point the input string
* has been converted to glyphs and we still need to translate back to the original chars
* to get the correct ABC widths. */
if (!(lpABC = heap_alloc_zero(sizeof(ABC) * cGlyphs))) return E_OUTOFMEMORY;
if (pABC) memset(pABC, 0, sizeof(ABC)); if (pABC) memset(pABC, 0, sizeof(ABC));
for (i = 0; i < cGlyphs; i++)
{
ABC abc;
if (!get_cache_glyph_widths(psc, pwGlyphs[i], &abc))
{
if (!hdc) return E_PENDING;
if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex) if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex)
{ {
GetCharABCWidthsI(get_cache_hdc(psc), 0, cGlyphs, (WORD *)pwGlyphs, lpABC); if (!GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc)) return S_FALSE;
} }
else else
{ {
INT width; INT width;
for (i = 0; i < cGlyphs; i++) if (!GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width)) return S_FALSE;
{ abc.abcB = width;
GetCharWidth32W(get_cache_hdc(psc), pwGlyphs[i], pwGlyphs[i], &width); abc.abcA = abc.abcC = 0;
lpABC[i].abcB = width;
} }
set_cache_glyph_widths(psc, pwGlyphs[i], &abc);
} }
for (i = 0; i < cGlyphs; i++)
{
TRACE(" Glyph=%04x, abcA=%d, abcB=%d, abcC=%d index=%d\n",
pwGlyphs[i], lpABC[i].abcA, lpABC[i].abcB, lpABC[i].abcC, i);
if (pABC) if (pABC)
{ {
pABC->abcA += lpABC[i].abcA; pABC->abcA += abc.abcA;
pABC->abcB += lpABC[i].abcB; pABC->abcB += abc.abcB;
pABC->abcC += lpABC[i].abcC; pABC->abcC += abc.abcC;
} }
/* FIXME: set to more reasonable values */ /* FIXME: set to more reasonable values */
if (pGoffset) pGoffset[i].du = pGoffset[i].dv = 0; if (pGoffset) pGoffset[i].du = pGoffset[i].dv = 0;
if (piAdvance) piAdvance[i] = lpABC[i].abcA + lpABC[i].abcB + lpABC[i].abcC; if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC;
} }
if (pABC) TRACE("Total for run: abcA=%d, abcB=%d, abcC=%d\n", pABC->abcA, pABC->abcB, pABC->abcC);
heap_free(lpABC); if (pABC) TRACE("Total for run: abcA=%d, abcB=%d, abcC=%d\n", pABC->abcA, pABC->abcB, pABC->abcC);
unselect_cached_font(psc, hfont);
return S_OK; return S_OK;
} }
...@@ -1391,20 +1400,32 @@ HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars ...@@ -1391,20 +1400,32 @@ HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars
int cChars, DWORD dwFlags, WORD *pwOutGlyphs) int cChars, DWORD dwFlags, WORD *pwOutGlyphs)
{ {
HRESULT hr; HRESULT hr;
HFONT hfont; unsigned int i;
TRACE("(%p,%p,%s,%d,0x%x,%p)\n", hdc, psc, debugstr_wn(pwcInChars, cChars), TRACE("(%p,%p,%s,%d,0x%x,%p)\n", hdc, psc, debugstr_wn(pwcInChars, cChars),
cChars, dwFlags, pwOutGlyphs); cChars, dwFlags, pwOutGlyphs);
hr = get_script_cache(hdc, psc); if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
if (hr != S_OK) return hr;
hfont = select_cached_font(psc); if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE))
if (GetGlyphIndicesW(get_cache_hdc(psc), pwcInChars, cChars, pwOutGlyphs, 0) == GDI_ERROR) {
hr = S_FALSE; for (i = 0; i < cChars; i++)
{
unselect_cached_font(psc, hfont); if (!(pwOutGlyphs[i] = get_cache_glyph(psc, pwcInChars[i])))
return hr; {
WORD glyph;
if (!hdc) return E_PENDING;
if (GetGlyphIndicesW(hdc, &pwcInChars[i], 1, &glyph, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE;
pwOutGlyphs[i] = set_cache_glyph(psc, pwcInChars[i], glyph);
}
}
}
else
{
TRACE("no glyph translation\n");
for (i = 0; i < cChars; i++) pwOutGlyphs[i] = pwcInChars[i];
}
return S_OK;
} }
/*********************************************************************** /***********************************************************************
...@@ -1456,9 +1477,7 @@ HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, LONG *height) ...@@ -1456,9 +1477,7 @@ HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, LONG *height)
TRACE("(%p, %p, %p)\n", hdc, psc, height); TRACE("(%p, %p, %p)\n", hdc, psc, height);
if (!height) return E_INVALIDARG; if (!height) return E_INVALIDARG;
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
hr = get_script_cache(hdc, psc);
if (hr != S_OK) return hr;
*height = get_cache_height(psc); *height = get_cache_height(psc);
return S_OK; return S_OK;
...@@ -1481,19 +1500,29 @@ HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, LONG *height) ...@@ -1481,19 +1500,29 @@ HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, LONG *height)
*/ */
HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, ABC *abc) HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
{ {
HFONT hfont; HRESULT hr;
HRESULT hr = S_OK;
TRACE("(%p, %p, 0x%04x, %p)\n", hdc, psc, glyph, abc); TRACE("(%p, %p, 0x%04x, %p)\n", hdc, psc, glyph, abc);
hr = get_script_cache(hdc, psc); if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
if (hr != S_OK) return hr;
hfont = select_cached_font(psc); if (!get_cache_glyph_widths(psc, glyph, abc))
if (!GetCharABCWidthsI(get_cache_hdc(psc), 0, 1, &glyph, abc)) hr = E_HANDLE; {
if (!hdc) return E_PENDING;
unselect_cached_font(psc, hfont); if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE))
return hr; {
if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE;
}
else
{
INT width;
if (!GetCharWidth32W(hdc, glyph, glyph, &width)) return S_FALSE;
abc->abcB = width;
abc->abcA = abc->abcC = 0;
}
set_cache_glyph_widths(psc, glyph, abc);
}
return S_OK;
} }
/*********************************************************************** /***********************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment