mirror of
https://github.com/reactos/reactos.git
synced 2025-07-30 17:32:32 +00:00
[0.4.7][USP10] Significantly speed up the text rendering
-fixes CORE-14192 Notepad text rendering performance improves dramatically -fixes 50% of CORE-13631 GSView Setup, dramatic speedup, but only partially solved because the jumping does persist -fixes CORE-14002 "It takes 8seconds to open up about dlg of DevCPP 5.11" reduces to 2seconds -fixes "about-dlg of DoubleCommander takes long to open" [USP10] Re-use script caches for the same font. CORE-14192 This significantly speeds up WM_SETTEXT in multiline edit controls. by porting back the fix from 0.4.8-dev-779-gcd992d022f
----------------------------------------------------------- but since that commit on its own would introduce the regression CORE-14226 I have to additionally port back 0.4.12-dev-151-gc086edf366
That 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 ------------------------------------------------------------- and I have to sync the modules\rostests\winetests\usp10\usp10.c to the state of 0.4.8-release-30-gfb23ed8
This commit is contained in:
parent
8632b23f79
commit
b4f3d7a575
3 changed files with 392 additions and 98 deletions
|
@ -664,6 +664,16 @@ static const SCRIPT_PROPERTIES *script_props[] =
|
|||
&scriptInformation[80].props, &scriptInformation[81].props
|
||||
};
|
||||
|
||||
static CRITICAL_SECTION cs_script_cache;
|
||||
static CRITICAL_SECTION_DEBUG cs_script_cache_dbg =
|
||||
{
|
||||
0, 0, &cs_script_cache,
|
||||
{ &cs_script_cache_dbg.ProcessLocksList, &cs_script_cache_dbg.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": script_cache") }
|
||||
};
|
||||
static CRITICAL_SECTION cs_script_cache = { &cs_script_cache_dbg, -1, 0, 0, 0, 0 };
|
||||
static struct list script_cache_list = LIST_INIT(script_cache_list);
|
||||
|
||||
typedef struct {
|
||||
ScriptCache *sc;
|
||||
int numGlyphs;
|
||||
|
@ -838,12 +848,34 @@ static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *ab
|
|||
static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc)
|
||||
{
|
||||
ScriptCache *sc;
|
||||
int size;
|
||||
unsigned size;
|
||||
LOGFONTW lf;
|
||||
|
||||
if (!psc) return E_INVALIDARG;
|
||||
if (*psc) return S_OK;
|
||||
if (!hdc) return E_PENDING;
|
||||
|
||||
if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
/* Ensure canonical result by zeroing extra space in lfFaceName */
|
||||
size = strlenW(lf.lfFaceName);
|
||||
memset(lf.lfFaceName + size, 0, sizeof(lf.lfFaceName) - size * sizeof(WCHAR));
|
||||
|
||||
EnterCriticalSection(&cs_script_cache);
|
||||
LIST_FOR_EACH_ENTRY(sc, &script_cache_list, ScriptCache, entry)
|
||||
{
|
||||
if (!memcmp(&sc->lf, &lf, sizeof(lf)))
|
||||
{
|
||||
sc->refcount++;
|
||||
LeaveCriticalSection(&cs_script_cache);
|
||||
*psc = sc;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&cs_script_cache);
|
||||
|
||||
if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY;
|
||||
if (!GetTextMetricsW(hdc, &sc->tm))
|
||||
{
|
||||
|
@ -857,18 +889,32 @@ static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc)
|
|||
sc->otm->otmSize = size;
|
||||
GetOutlineTextMetricsW(hdc, size, sc->otm);
|
||||
}
|
||||
if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf))
|
||||
{
|
||||
heap_free(sc);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
sc->sfnt = (GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, NULL, 0)!=GDI_ERROR);
|
||||
if (!set_cache_font_properties(hdc, sc))
|
||||
{
|
||||
heap_free(sc);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
sc->lf = lf;
|
||||
sc->refcount = 1;
|
||||
*psc = sc;
|
||||
|
||||
EnterCriticalSection(&cs_script_cache);
|
||||
list_add_head(&script_cache_list, &sc->entry);
|
||||
LIST_FOR_EACH_ENTRY(sc, &script_cache_list, ScriptCache, entry)
|
||||
{
|
||||
if (sc != *psc && !memcmp(&sc->lf, &lf, sizeof(lf)))
|
||||
{
|
||||
/* Another thread won the race. Use their cache instead of ours */
|
||||
list_remove(&sc->entry);
|
||||
sc->refcount++;
|
||||
LeaveCriticalSection(&cs_script_cache);
|
||||
heap_free(*psc);
|
||||
*psc = sc;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&cs_script_cache);
|
||||
TRACE("<- %p\n", sc);
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1021,6 +1067,17 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
|
|||
{
|
||||
unsigned int i;
|
||||
INT n;
|
||||
|
||||
EnterCriticalSection(&cs_script_cache);
|
||||
if (--((ScriptCache *)*psc)->refcount > 0)
|
||||
{
|
||||
LeaveCriticalSection(&cs_script_cache);
|
||||
*psc = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
list_remove(&((ScriptCache *)*psc)->entry);
|
||||
LeaveCriticalSection(&cs_script_cache);
|
||||
|
||||
for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++)
|
||||
{
|
||||
heap_free(((ScriptCache *)*psc)->widths[i]);
|
||||
|
@ -3355,35 +3412,41 @@ HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS
|
|||
if (pABC) memset(pABC, 0, sizeof(ABC));
|
||||
for (i = 0; i < cGlyphs; i++)
|
||||
{
|
||||
WORD glyph;
|
||||
ABC abc;
|
||||
|
||||
/* FIXME: set to more reasonable values */
|
||||
pGoffset[i].du = pGoffset[i].dv = 0;
|
||||
|
||||
if (pGlyphProps[i].sva.fZeroWidth)
|
||||
{
|
||||
abc.abcA = abc.abcB = abc.abcC = 0;
|
||||
if (piAdvance) piAdvance[i] = 0;
|
||||
continue;
|
||||
}
|
||||
else if (!get_cache_glyph_widths(psc, pwGlyphs[i], &abc))
|
||||
|
||||
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 (get_cache_pitch_family(psc) & TMPF_TRUETYPE)
|
||||
{
|
||||
if (psa->fNoGlyphIndex)
|
||||
ret = GetCharABCWidthsW(hdc, pwGlyphs[i], pwGlyphs[i], &abc);
|
||||
else
|
||||
ret = GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc);
|
||||
if (!ret) return S_FALSE;
|
||||
if (!GetCharABCWidthsI(hdc, glyph, 1, NULL, &abc)) return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT width;
|
||||
if (psa->fNoGlyphIndex)
|
||||
ret = GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width);
|
||||
else
|
||||
ret = GetCharWidthI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &width);
|
||||
if (!ret) return S_FALSE;
|
||||
if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
|
||||
abc.abcB = width;
|
||||
abc.abcA = abc.abcC = 0;
|
||||
}
|
||||
set_cache_glyph_widths(psc, pwGlyphs[i], &abc);
|
||||
set_cache_glyph_widths(psc, glyph, &abc);
|
||||
}
|
||||
if (pABC)
|
||||
{
|
||||
|
@ -3391,8 +3454,6 @@ HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS
|
|||
pABC->abcB += abc.abcB;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -3648,14 +3709,14 @@ HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, AB
|
|||
if (!get_cache_glyph_widths(psc, glyph, abc))
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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->abcA = abc->abcC = 0;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <wine/debug.h>
|
||||
#include <wine/unicode.h>
|
||||
#include <wine/list.h>
|
||||
|
||||
#define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
|
||||
( ( (ULONG)_x4 << 24 ) | \
|
||||
|
@ -194,6 +195,8 @@ typedef struct {
|
|||
} CacheGlyphPage;
|
||||
|
||||
typedef struct {
|
||||
struct list entry;
|
||||
DWORD refcount;
|
||||
LOGFONTW lf;
|
||||
TEXTMETRICW tm;
|
||||
OUTLINETEXTMETRICW *otm;
|
||||
|
|
|
@ -56,13 +56,16 @@ typedef struct _shapeTest_glyph {
|
|||
SCRIPT_GLYPHPROP GlyphProp;
|
||||
} shapeTest_glyph;
|
||||
|
||||
typedef struct _font_fingerprint {
|
||||
WCHAR check[10];
|
||||
WORD result[10];
|
||||
} font_fingerprint;
|
||||
|
||||
/* Uniscribe 1.6 calls */
|
||||
static HRESULT (WINAPI *pScriptItemizeOpenType)( const WCHAR *pwcInChars, int cInChars, int cMaxItems, const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, ULONG *pScriptTags, int *pcItems);
|
||||
|
||||
static HRESULT (WINAPI *pScriptShapeOpenType)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties, int cRanges, const WCHAR *pwcChars, int cChars, int cMaxGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProps, WORD *pwOutGlyphs, SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs);
|
||||
|
||||
static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
|
||||
|
||||
static HRESULT (WINAPI *pScriptGetFontScriptTags)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags);
|
||||
static HRESULT (WINAPI *pScriptGetFontLanguageTags)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags);
|
||||
static HRESULT (WINAPI *pScriptGetFontFeatureTags)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags);
|
||||
|
@ -601,15 +604,8 @@ static void test_ScriptItemize( void )
|
|||
SCRIPT_CONTROL Control;
|
||||
SCRIPT_STATE State;
|
||||
HRESULT hr;
|
||||
HMODULE usp10;
|
||||
int nItems;
|
||||
|
||||
usp10 = LoadLibraryA("usp10.dll");
|
||||
ok (usp10 != 0,"Unable to LoadLibrary on usp10.dll\n");
|
||||
pScriptItemizeOpenType = (void*)GetProcAddress(usp10, "ScriptItemizeOpenType");
|
||||
pScriptShapeOpenType = (void*)GetProcAddress(usp10, "ScriptShapeOpenType");
|
||||
pGetGlyphIndicesW = (void*)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GetGlyphIndicesW");
|
||||
|
||||
memset(&Control, 0, sizeof(Control));
|
||||
memset(&State, 0, sizeof(State));
|
||||
|
||||
|
@ -995,14 +991,6 @@ static inline void _test_shape_ok(int valid, HDC hdc, LPCWSTR string,
|
|||
winetest_ok(SUCCEEDED(hr), "Failed to get script properties, hr %#x.\n", hr);
|
||||
|
||||
hr = pScriptItemizeOpenType(string, cchString, 15, Control, State, outpItems, tags, &outnItems);
|
||||
if (hr == USP_E_SCRIPT_NOT_IN_FONT)
|
||||
{
|
||||
if (valid > 0)
|
||||
winetest_win_skip("Select font does not support script\n");
|
||||
else
|
||||
winetest_trace("Select font does not support script\n");
|
||||
return;
|
||||
}
|
||||
if (valid > 0)
|
||||
winetest_ok(hr == S_OK, "ScriptItemizeOpenType should return S_OK not %08x\n", hr);
|
||||
else if (hr != S_OK)
|
||||
|
@ -1286,7 +1274,7 @@ static int CALLBACK enumFontProc( const LOGFONTA *lpelfe, const TEXTMETRICA *lpn
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, const WCHAR check, HFONT *hfont, HFONT *origFont)
|
||||
static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, const WCHAR check, HFONT *hfont, HFONT *origFont, const font_fingerprint *fingerprint)
|
||||
{
|
||||
int rc = 0;
|
||||
fontEnumParam lParam;
|
||||
|
@ -1304,7 +1292,26 @@ static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, co
|
|||
if (*hfont)
|
||||
{
|
||||
winetest_trace("using font %s\n",lParam.lf.lfFaceName);
|
||||
rc = 1;
|
||||
*origFont = SelectObject(hdc,*hfont);
|
||||
if (fingerprint)
|
||||
{
|
||||
WORD output[10];
|
||||
int i;
|
||||
if (GetGlyphIndicesW(hdc, fingerprint->check, 10, output, 0) != GDI_ERROR)
|
||||
{
|
||||
for (i=0; i < 10; i++)
|
||||
if (output[i] != fingerprint->result[i])
|
||||
{
|
||||
winetest_trace("found font does not match fingerprint\n");
|
||||
SelectObject(hdc,*origFont);
|
||||
DeleteObject(*hfont);
|
||||
*hfont = NULL;
|
||||
break;
|
||||
}
|
||||
if (i == 10) rc = 1;
|
||||
}
|
||||
}
|
||||
else rc = 1;
|
||||
}
|
||||
}
|
||||
if (!rc)
|
||||
|
@ -1329,7 +1336,7 @@ static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, co
|
|||
WORD glyph = 0;
|
||||
|
||||
*origFont = SelectObject(hdc,*hfont);
|
||||
if (pGetGlyphIndicesW && (pGetGlyphIndicesW(hdc, &check, 1, &glyph, 0) == GDI_ERROR || glyph ==0))
|
||||
if (GetGlyphIndicesW(hdc, &check, 1, &glyph, 0) == GDI_ERROR || glyph == 0)
|
||||
{
|
||||
winetest_trace(" Font fails to contain required glyphs\n");
|
||||
SelectObject(hdc,*origFont);
|
||||
|
@ -1346,7 +1353,7 @@ static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, co
|
|||
return rc;
|
||||
}
|
||||
|
||||
#define find_font_for_range(a,b,c,d,e,f) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _find_font_for_range(a,b,c,d,e,f)
|
||||
#define find_font_for_range(a,b,c,d,e,f,g) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _find_font_for_range(a,b,c,d,e,f,g)
|
||||
|
||||
static void test_ScriptShapeOpenType(HDC hdc)
|
||||
{
|
||||
|
@ -1628,6 +1635,11 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
{1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}},
|
||||
{1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} };
|
||||
|
||||
static const font_fingerprint fingerprint_estrangelo = {
|
||||
{'A','a','B','b','C','c','D','d',0,0},
|
||||
{284,310,285,311,286,312,287,313,0,0}};
|
||||
|
||||
|
||||
if (!pScriptItemizeOpenType || !pScriptShapeOpenType)
|
||||
{
|
||||
win_skip("ScriptShapeOpenType not available on this platform\n");
|
||||
|
@ -1670,7 +1682,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
|
||||
test_shape_ok(hdc, test2, 4, &Control, &State, 1, 4, t2_c, glyph_test);
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Calibri", 0, test3[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Calibri", 0, test3[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test3, 6, &Control, &State, 0, 2, t3_c, t3_g);
|
||||
|
@ -1678,7 +1690,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 11, test_hebrew[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 11, test_hebrew[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_hebrew, 4, &Control, &State, 0, 4, hebrew_c, hebrew_g);
|
||||
|
@ -1686,7 +1698,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 13, test_arabic[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 13, test_arabic[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_arabic, 4, &Control, &State, 0, 3, arabic_c, arabic_g);
|
||||
|
@ -1694,7 +1706,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 24, test_thai[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 24, test_thai[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_thai, 10, &Control, &State, 0, 10, thai_c, thai_g);
|
||||
|
@ -1702,7 +1714,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Estrangelo Edessa", 71, test_syriac[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Estrangelo Edessa", 71, test_syriac[0], &hfont, &hfont_orig, &fingerprint_estrangelo);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_syriac, 8, &Control, &State, 0, 7, syriac_c, syriac_g);
|
||||
|
@ -1710,7 +1722,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "MV Boli", 72, test_thaana[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "MV Boli", 72, test_thaana[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_thaana, 13, &Control, &State, 0, 13, thaana_c, thaana_g);
|
||||
|
@ -1718,7 +1730,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Microsoft PhagsPa", 53, test_phagspa[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Microsoft PhagsPa", 53, test_phagspa[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid_props2(test_valid, hdc, test_phagspa, 11, &Control, &State, 0, 11,
|
||||
|
@ -1727,7 +1739,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "DokChampa", 25, test_lao[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "DokChampa", 25, test_lao[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_lao, 9, &Control, &State, 0, 9, lao_c, lao_g);
|
||||
|
@ -1735,7 +1747,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Himalaya", 70, test_tibetan[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Microsoft Himalaya", 70, test_tibetan[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid_props2(test_valid, hdc, test_tibetan, 17, &Control, &State, 0, 17,
|
||||
|
@ -1744,7 +1756,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Mangal", 15, test_devanagari[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Mangal", 15, test_devanagari[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_devanagari, 8, &Control, &State, 0, 8, devanagari_c, devanagari_g);
|
||||
|
@ -1752,7 +1764,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Vrinda", 16, test_bengali[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Vrinda", 16, test_bengali[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_bengali, 5, &Control, &State, 0, 5, bengali_c, bengali_g);
|
||||
|
@ -1760,7 +1772,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Raavi", 17, test_gurmukhi[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Raavi", 17, test_gurmukhi[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_gurmukhi, 7, &Control, &State, 0, 7, gurmukhi_c, gurmukhi_g);
|
||||
|
@ -1768,7 +1780,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Shruti", 18, test_gujarati[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Shruti", 18, test_gujarati[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_gujarati, 7, &Control, &State, 0, 7, gujarati_c, gujarati_g);
|
||||
|
@ -1776,7 +1788,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Kalinga", 19, test_oriya[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Kalinga", 19, test_oriya[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_oriya, 5, &Control, &State, 0, 4, oriya_c, oriya_g);
|
||||
|
@ -1784,7 +1796,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Latha", 20, test_tamil[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Latha", 20, test_tamil[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_tamil, 5, &Control, &State, 0, 4, tamil_c, tamil_g);
|
||||
|
@ -1792,7 +1804,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Gautami", 21, test_telugu[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Gautami", 21, test_telugu[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_telugu, 6, &Control, &State, 0, 6, telugu_c, telugu_g);
|
||||
|
@ -1800,7 +1812,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Kartika", 23, test_malayalam[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Kartika", 23, test_malayalam[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_malayalam, 6, &Control, &State, 0, 6, malayalam_c, malayalam_g);
|
||||
|
@ -1808,7 +1820,7 @@ static void test_ScriptShapeOpenType(HDC hdc)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
test_valid = find_font_for_range(hdc, "Tunga", 22, test_kannada[0], &hfont, &hfont_orig);
|
||||
test_valid = find_font_for_range(hdc, "Tunga", 22, test_kannada[0], &hfont, &hfont_orig, NULL);
|
||||
if (hfont != NULL)
|
||||
{
|
||||
test_shape_ok_valid(test_valid, hdc, test_kannada, 5, &Control, &State, 0, 4, kannada_c, kannada_g);
|
||||
|
@ -1821,8 +1833,10 @@ static void test_ScriptShape(HDC hdc)
|
|||
{
|
||||
static const WCHAR test1[] = {'w', 'i', 'n', 'e',0};
|
||||
static const WCHAR test2[] = {0x202B, 'i', 'n', 0x202C,0};
|
||||
static const WCHAR test3[] = {0x30b7};
|
||||
HRESULT hr;
|
||||
SCRIPT_CACHE sc = NULL;
|
||||
SCRIPT_CACHE sc2 = NULL;
|
||||
WORD glyphs[4], glyphs2[4], logclust[4], glyphs3[4];
|
||||
SCRIPT_VISATTR attrs[4];
|
||||
SCRIPT_ITEM items[4];
|
||||
|
@ -1852,6 +1866,10 @@ static void test_ScriptShape(HDC hdc)
|
|||
ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr);
|
||||
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
|
||||
|
||||
hr = ScriptShape(hdc, &sc2, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb);
|
||||
ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr);
|
||||
ok(sc2 == sc, "caches %p, %p not identical\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
memset(glyphs,-1,sizeof(glyphs));
|
||||
memset(logclust,-1,sizeof(logclust));
|
||||
|
@ -2052,6 +2070,23 @@ static void test_ScriptShape(HDC hdc)
|
|||
DeleteObject(SelectObject(hdc, oldfont));
|
||||
ScriptFreeCache(&sc);
|
||||
}
|
||||
|
||||
/* Text does not support this range. */
|
||||
memset(items, 0, sizeof(items));
|
||||
nb = 0;
|
||||
hr = ScriptItemize(test3, sizeof(test3)/sizeof(test3[0]), sizeof(items)/sizeof(items[0]), NULL, NULL, items, &nb);
|
||||
ok(hr == S_OK, "ScriptItemize failed, hr %#x.\n", hr);
|
||||
ok(items[0].a.eScript > 0, "Expected script id.\n");
|
||||
ok(nb == 1, "Unexpected number of items.\n");
|
||||
|
||||
memset(glyphs, 0xff, sizeof(glyphs));
|
||||
nb = 0;
|
||||
hr = ScriptShape(hdc, &sc, test3, sizeof(test3)/sizeof(test3[0]), sizeof(glyphs)/sizeof(glyphs[0]), &items[0].a,
|
||||
glyphs, logclust, attrs, &nb);
|
||||
ok(hr == S_OK, "ScriptShape failed, hr %#x.\n", hr);
|
||||
ok(nb == 1, "Unexpected glyph count %u\n", nb);
|
||||
ok(glyphs[0] == 0, "Unexpected glyph id\n");
|
||||
ScriptFreeCache(&sc);
|
||||
}
|
||||
|
||||
static void test_ScriptPlace(HDC hdc)
|
||||
|
@ -2060,6 +2095,7 @@ static void test_ScriptPlace(HDC hdc)
|
|||
BOOL ret;
|
||||
HRESULT hr;
|
||||
SCRIPT_CACHE sc = NULL;
|
||||
SCRIPT_CACHE sc2 = NULL;
|
||||
WORD glyphs[4], logclust[4];
|
||||
SCRIPT_VISATTR attrs[4];
|
||||
SCRIPT_ITEM items[2];
|
||||
|
@ -2097,6 +2133,11 @@ static void test_ScriptPlace(HDC hdc)
|
|||
ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr);
|
||||
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
|
||||
|
||||
hr = ScriptPlace(hdc, &sc2, glyphs, 4, attrs, &items[0].a, widths, offset, NULL);
|
||||
ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr);
|
||||
ok(sc2 == sc, "caches %p, %p not identical\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
if (widths[0] != 0)
|
||||
{
|
||||
int old_width = widths[0];
|
||||
|
@ -2517,6 +2558,7 @@ static void test_ScriptGetFontProperties(HDC hdc)
|
|||
hr = ScriptGetFontProperties(hdc,&psc,&sfp);
|
||||
ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) invalid, expected E_INVALIDARG, got %08x\n", hr);
|
||||
ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
|
||||
ok( sfp.cBytes == sizeof(SCRIPT_FONTPROPERTIES) - 1, "Unexpected cBytes.\n");
|
||||
ScriptFreeCache(&psc);
|
||||
ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
|
||||
|
||||
|
@ -2536,12 +2578,6 @@ static void test_ScriptGetFontProperties(HDC hdc)
|
|||
ScriptFreeCache(&psc);
|
||||
ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
|
||||
|
||||
pGetGlyphIndicesW = (void*)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GetGlyphIndicesW");
|
||||
if (!pGetGlyphIndicesW)
|
||||
{
|
||||
win_skip("Skip on WINNT4\n");
|
||||
return;
|
||||
}
|
||||
memset(&lf, 0, sizeof(lf));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
efnd.total = 0;
|
||||
|
@ -2575,7 +2611,7 @@ static void test_ScriptGetFontProperties(HDC hdc)
|
|||
ret = GetTextMetricsA(hdc, &tmA);
|
||||
ok(ret != 0, "GetTextMetricsA failed!\n");
|
||||
|
||||
ret = pGetGlyphIndicesW(hdc, invalids, 1, gi, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
ret = GetGlyphIndicesW(hdc, invalids, 1, gi, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n");
|
||||
|
||||
ok(sfp.wgBlank == tmA.tmBreakChar || sfp.wgBlank == gi[0], "bitmap font %s wgBlank %04x tmBreakChar %04x Space %04x\n", lf.lfFaceName, sfp.wgBlank, tmA.tmBreakChar, gi[0]);
|
||||
|
@ -2621,13 +2657,13 @@ static void test_ScriptGetFontProperties(HDC hdc)
|
|||
}
|
||||
|
||||
str[0] = 0x0020; /* U+0020: numeric space */
|
||||
ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
|
||||
ret = GetGlyphIndicesW(hdc, str, 1, gi, 0);
|
||||
ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n");
|
||||
ok(sfp.wgBlank == gi[0], "truetype font %s wgBlank %04x gi[0] %04x\n", lf.lfFaceName, sfp.wgBlank, gi[0]);
|
||||
|
||||
ok(sfp.wgDefault == 0 || broken(is_arabic), "truetype font %s wgDefault %04x\n", lf.lfFaceName, sfp.wgDefault);
|
||||
|
||||
ret = pGetGlyphIndicesW(hdc, invalids, 3, gi, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
ret = GetGlyphIndicesW(hdc, invalids, 3, gi, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n");
|
||||
if (gi[2] != 0xFFFF) /* index of default non exist char */
|
||||
ok(sfp.wgInvalid == gi[2], "truetype font %s wgInvalid %04x gi[2] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[2]);
|
||||
|
@ -2639,7 +2675,7 @@ static void test_ScriptGetFontProperties(HDC hdc)
|
|||
ok(sfp.wgInvalid == 0, "truetype font %s wgInvalid %04x expect 0\n", lf.lfFaceName, sfp.wgInvalid);
|
||||
|
||||
str[0] = 0x0640; /* U+0640: kashida */
|
||||
ret = pGetGlyphIndicesW(hdc, str, 1, gi, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
ret = GetGlyphIndicesW(hdc, str, 1, gi, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n");
|
||||
is_arial = !lstrcmpA(lf.lfFaceName, "Arial");
|
||||
is_times_new_roman= !lstrcmpA(lf.lfFaceName, "Times New Roman");
|
||||
|
@ -3128,6 +3164,7 @@ static void test_ScriptXtoX(void)
|
|||
WORD clust = 0;
|
||||
INT advance = 16;
|
||||
hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing);
|
||||
ok(hr == S_OK, "ScriptXtoCP() failed, hr %#x.\n", hr);
|
||||
ok(piCP==0 && piTrailing==1,"%i should return 0(%i) and 1(%i)\n",iX,piCP,piTrailing);
|
||||
}
|
||||
for (iX = 9; iX < 16; iX++)
|
||||
|
@ -3135,6 +3172,7 @@ static void test_ScriptXtoX(void)
|
|||
WORD clust = 0;
|
||||
INT advance = 16;
|
||||
hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing);
|
||||
ok(hr == S_OK, "ScriptXtoCP() failed, hr %#x.\n", hr);
|
||||
ok(piCP==0 && piTrailing==0,"%i should return 0(%i) and 0(%i)\n",iX,piCP,piTrailing);
|
||||
}
|
||||
|
||||
|
@ -3180,7 +3218,7 @@ static void test_ScriptString(HDC hdc)
|
|||
* This set of tests are for the string functions of uniscribe. The ScriptStringAnalyse
|
||||
* function allocates memory pointed to by the SCRIPT_STRING_ANALYSIS ssa pointer. This
|
||||
* memory is freed by ScriptStringFree. There needs to be a valid hdc for this as
|
||||
* ScriptStringAnalyse calls ScriptSItemize, ScriptShape and ScriptPlace which require it.
|
||||
* ScriptStringAnalyse calls ScriptItemize, ScriptShape and ScriptPlace which require it.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -3448,11 +3486,27 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
|||
}
|
||||
}
|
||||
|
||||
static HWND create_test_window(void)
|
||||
{
|
||||
HWND hwnd = CreateWindowExA(0, "Static", "", WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL);
|
||||
ok(hwnd != NULL, "Failed to create test window.\n");
|
||||
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
static void test_ScriptCacheGetHeight(HDC hdc)
|
||||
{
|
||||
HRESULT hr;
|
||||
HFONT hfont, prev_hfont;
|
||||
SCRIPT_CACHE sc = NULL;
|
||||
LONG height;
|
||||
LONG height, height2;
|
||||
TEXTMETRICW tm;
|
||||
LOGFONTA lf;
|
||||
HRESULT hr;
|
||||
HWND hwnd;
|
||||
HDC hdc2;
|
||||
|
||||
hr = ScriptCacheGetHeight(NULL, NULL, NULL);
|
||||
ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
|
||||
|
@ -3463,11 +3517,54 @@ static void test_ScriptCacheGetHeight(HDC hdc)
|
|||
hr = ScriptCacheGetHeight(NULL, &sc, &height);
|
||||
ok(hr == E_PENDING, "expected E_PENDING, got 0x%08x\n", hr);
|
||||
|
||||
height = 0;
|
||||
height = 123;
|
||||
hr = ScriptCacheGetHeight(hdc, NULL, &height);
|
||||
ok(hr == E_INVALIDARG, "Uexpected hr %#x.\n", hr);
|
||||
ok(height == 123, "Unexpected height.\n");
|
||||
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
GetTextMetricsW(hdc, &tm);
|
||||
ok(tm.tmHeight > 0, "Unexpected tmHeight %u.\n", tm.tmHeight);
|
||||
|
||||
height = 0;
|
||||
hr = ScriptCacheGetHeight(hdc, &sc, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(height > 0, "expected height > 0\n");
|
||||
ok(height == tm.tmHeight, "expected height > 0\n");
|
||||
|
||||
/* Try again with NULL dc. */
|
||||
height2 = 0;
|
||||
hr = ScriptCacheGetHeight(NULL, &sc, &height2);
|
||||
ok(hr == S_OK, "Failed to get cached height, hr %#x.\n", hr);
|
||||
ok(height2 == height, "Unexpected height %u.\n", height2);
|
||||
|
||||
hwnd = create_test_window();
|
||||
|
||||
hdc2 = GetDC(hwnd);
|
||||
ok(hdc2 != NULL, "Failed to get window dc.\n");
|
||||
|
||||
memset(&lf, 0, sizeof(LOGFONTA));
|
||||
lstrcpyA(lf.lfFaceName, "Tahoma");
|
||||
lf.lfHeight = -32;
|
||||
|
||||
hfont = CreateFontIndirectA(&lf);
|
||||
ok(hfont != NULL, "Failed to create font.\n");
|
||||
|
||||
prev_hfont = SelectObject(hdc2, hfont);
|
||||
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
GetTextMetricsW(hdc2, &tm);
|
||||
ok(tm.tmHeight > height, "Unexpected tmHeight %u.\n", tm.tmHeight);
|
||||
|
||||
height2 = 0;
|
||||
hr = ScriptCacheGetHeight(hdc2, &sc, &height2);
|
||||
ok(hr == S_OK, "Failed to get cached height, hr %#x.\n", hr);
|
||||
ok(height2 == height, "Unexpected height.\n");
|
||||
|
||||
SelectObject(hdc2, prev_hfont);
|
||||
DeleteObject(hfont);
|
||||
|
||||
ReleaseDC(hwnd, hdc2);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
ScriptFreeCache(&sc);
|
||||
}
|
||||
|
@ -3647,27 +3744,10 @@ static void test_digit_substitution(void)
|
|||
LGRPID_GEORGIAN,
|
||||
LGRPID_ARMENIAN
|
||||
};
|
||||
HMODULE hKernel32;
|
||||
static BOOL (WINAPI * pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROCA,LGRPID,DWORD,LONG_PTR);
|
||||
|
||||
hKernel32 = GetModuleHandleA("kernel32.dll");
|
||||
pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
|
||||
|
||||
if (!pEnumLanguageGroupLocalesA)
|
||||
{
|
||||
win_skip("EnumLanguageGroupLocalesA not available on this platform\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(groups)/sizeof(groups[0]); i++)
|
||||
{
|
||||
ret = pEnumLanguageGroupLocalesA(enum_proc, groups[i], 0, 0);
|
||||
if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
win_skip("EnumLanguageGroupLocalesA not implemented on this platform\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = EnumLanguageGroupLocalesA(enum_proc, groups[i], 0, 0);
|
||||
ok(ret, "EnumLanguageGroupLocalesA failed unexpectedly: %u\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
@ -3788,9 +3868,6 @@ static void test_newlines(void)
|
|||
static void test_ScriptGetFontFunctions(HDC hdc)
|
||||
{
|
||||
HRESULT hr;
|
||||
pScriptGetFontScriptTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontScriptTags");
|
||||
pScriptGetFontLanguageTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontLanguageTags");
|
||||
pScriptGetFontFeatureTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontFeatureTags");
|
||||
if (!pScriptGetFontScriptTags || !pScriptGetFontLanguageTags || !pScriptGetFontFeatureTags)
|
||||
{
|
||||
win_skip("ScriptGetFontScriptTags,ScriptGetFontLanguageTags or ScriptGetFontFeatureTags not available on this platform\n");
|
||||
|
@ -4016,6 +4093,155 @@ static void test_ScriptIsComplex(void)
|
|||
ok(hr == S_FALSE, "got 0x%08x\n", hr);
|
||||
}
|
||||
|
||||
static void test_ScriptString_pSize(HDC hdc)
|
||||
{
|
||||
static const WCHAR textW[] = {'A',0};
|
||||
SCRIPT_STRING_ANALYSIS ssa;
|
||||
const SIZE *size;
|
||||
TEXTMETRICW tm;
|
||||
HRESULT hr;
|
||||
ABC abc;
|
||||
|
||||
hr = ScriptStringAnalyse(hdc, textW, 1, 16, -1, SSA_GLYPHS, 0, NULL, NULL, NULL, NULL, NULL, &ssa);
|
||||
ok(hr == S_OK, "ScriptStringAnalyse failed, hr %#x.\n", hr);
|
||||
|
||||
size = ScriptString_pSize(NULL);
|
||||
ok(size == NULL || broken(size != NULL) /* <win7 */, "Unexpected size pointer.\n");
|
||||
|
||||
GetCharABCWidthsW(hdc, textW[0], textW[0], &abc);
|
||||
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
GetTextMetricsW(hdc, &tm);
|
||||
ok(tm.tmHeight > 0, "Unexpected tmHeight.\n");
|
||||
|
||||
size = ScriptString_pSize(ssa);
|
||||
ok(size != NULL, "Unexpected size pointer.\n");
|
||||
ok(size->cx == abc.abcA + abc.abcB + abc.abcC, "Unexpected cx size %d.\n", size->cx);
|
||||
ok(size->cy == tm.tmHeight, "Unexpected cy size %d.\n", size->cy);
|
||||
|
||||
hr = ScriptStringFree(&ssa);
|
||||
ok(hr == S_OK, "Failed to free ssa, hr %#x.\n", hr);
|
||||
}
|
||||
|
||||
static void test_script_cache_reuse(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
HWND hwnd1, hwnd2;
|
||||
HDC hdc1, hdc2;
|
||||
LOGFONTA lf;
|
||||
HFONT hfont1, hfont2;
|
||||
HFONT prev_hfont1, prev_hfont2;
|
||||
SCRIPT_CACHE sc = NULL;
|
||||
SCRIPT_CACHE sc2;
|
||||
LONG height;
|
||||
|
||||
hwnd1 = create_test_window();
|
||||
hwnd2 = create_test_window();
|
||||
|
||||
hdc1 = GetDC(hwnd1);
|
||||
hdc2 = GetDC(hwnd2);
|
||||
ok(hdc1 != NULL && hdc2 != NULL, "Failed to get window dc.\n");
|
||||
|
||||
memset(&lf, 0, sizeof(LOGFONTA));
|
||||
lstrcpyA(lf.lfFaceName, "Tahoma");
|
||||
|
||||
lf.lfHeight = 10;
|
||||
hfont1 = CreateFontIndirectA(&lf);
|
||||
ok(hfont1 != NULL, "CreateFontIndirectA failed\n");
|
||||
hfont2 = CreateFontIndirectA(&lf);
|
||||
ok(hfont2 != NULL, "CreateFontIndirectA failed\n");
|
||||
ok(hfont1 != hfont2, "Expected fonts %p and %p to differ\n", hfont1, hfont2);
|
||||
|
||||
prev_hfont1 = SelectObject(hdc1, hfont1);
|
||||
ok(prev_hfont1 != NULL, "SelectObject failed: %p\n", prev_hfont1);
|
||||
prev_hfont2 = SelectObject(hdc2, hfont1);
|
||||
ok(prev_hfont2 != NULL, "SelectObject failed: %p\n", prev_hfont2);
|
||||
|
||||
/* Get a script cache */
|
||||
hr = ScriptCacheGetHeight(hdc1, &sc, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc != NULL, "Script cache is NULL\n");
|
||||
|
||||
/* Same font, same DC -> same SCRIPT_CACHE */
|
||||
sc2 = NULL;
|
||||
hr = ScriptCacheGetHeight(hdc1, &sc2, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc2 != NULL, "Script cache is NULL\n");
|
||||
ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
/* Same font in different DC -> same SCRIPT_CACHE */
|
||||
sc2 = NULL;
|
||||
hr = ScriptCacheGetHeight(hdc2, &sc2, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc2 != NULL, "Script cache is NULL\n");
|
||||
ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
/* Same font face & size, but different font handle */
|
||||
ok(SelectObject(hdc1, hfont2) != NULL, "SelectObject failed\n");
|
||||
ok(SelectObject(hdc2, hfont2) != NULL, "SelectObject failed\n");
|
||||
|
||||
sc2 = NULL;
|
||||
hr = ScriptCacheGetHeight(hdc1, &sc2, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc2 != NULL, "Script cache is NULL\n");
|
||||
ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
sc2 = NULL;
|
||||
hr = ScriptCacheGetHeight(hdc2, &sc2, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc2 != NULL, "Script cache is NULL\n");
|
||||
ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
/* Different font size -- now we get a different SCRIPT_CACHE */
|
||||
SelectObject(hdc1, prev_hfont1);
|
||||
SelectObject(hdc2, prev_hfont2);
|
||||
DeleteObject(hfont2);
|
||||
lf.lfHeight = 20;
|
||||
hfont2 = CreateFontIndirectA(&lf);
|
||||
ok(hfont2 != NULL, "CreateFontIndirectA failed\n");
|
||||
ok(SelectObject(hdc1, hfont2) != NULL, "SelectObject failed\n");
|
||||
ok(SelectObject(hdc2, hfont2) != NULL, "SelectObject failed\n");
|
||||
|
||||
sc2 = NULL;
|
||||
hr = ScriptCacheGetHeight(hdc1, &sc2, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc2 != NULL, "Script cache is NULL\n");
|
||||
ok(sc != sc2, "Expected caches %p, %p to be different\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
sc2 = NULL;
|
||||
hr = ScriptCacheGetHeight(hdc2, &sc2, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
ok(sc2 != NULL, "Script cache is NULL\n");
|
||||
ok(sc != sc2, "Expected caches %p, %p to be different\n", sc, sc2);
|
||||
ScriptFreeCache(&sc2);
|
||||
|
||||
ScriptFreeCache(&sc);
|
||||
SelectObject(hdc1, prev_hfont1);
|
||||
SelectObject(hdc2, prev_hfont2);
|
||||
DeleteObject(hfont1);
|
||||
DeleteObject(hfont2);
|
||||
DestroyWindow(hwnd1);
|
||||
DestroyWindow(hwnd2);
|
||||
}
|
||||
|
||||
static void init_tests(void)
|
||||
{
|
||||
HMODULE module = GetModuleHandleA("usp10.dll");
|
||||
|
||||
ok(module != 0, "Expected usp10.dll to be loaded.\n");
|
||||
|
||||
pScriptItemizeOpenType = (void *)GetProcAddress(module, "ScriptItemizeOpenType");
|
||||
pScriptShapeOpenType = (void *)GetProcAddress(module, "ScriptShapeOpenType");
|
||||
pScriptGetFontScriptTags = (void *)GetProcAddress(module, "ScriptGetFontScriptTags");
|
||||
pScriptGetFontLanguageTags = (void *)GetProcAddress(module, "ScriptGetFontLanguageTags");
|
||||
pScriptGetFontFeatureTags = (void *)GetProcAddress(module, "ScriptGetFontFeatureTags");
|
||||
}
|
||||
|
||||
START_TEST(usp10)
|
||||
{
|
||||
HWND hwnd;
|
||||
|
@ -4045,6 +4271,8 @@ START_TEST(usp10)
|
|||
hfont = SelectObject(hdc, CreateFontIndirectA(&lf));
|
||||
ok(hfont != NULL, "SelectObject failed: %p\n", hfont);
|
||||
|
||||
init_tests();
|
||||
|
||||
test_ScriptItemize();
|
||||
test_ScriptItemize_surrogates();
|
||||
test_ScriptItemIzeShapePlace(hdc,pwOutGlyphs);
|
||||
|
@ -4062,6 +4290,7 @@ START_TEST(usp10)
|
|||
test_ScriptXtoX();
|
||||
test_ScriptString(hdc);
|
||||
test_ScriptStringXtoCP_CPtoX(hdc);
|
||||
test_ScriptString_pSize(hdc);
|
||||
|
||||
test_ScriptLayout();
|
||||
test_digit_substitution();
|
||||
|
@ -4073,6 +4302,7 @@ START_TEST(usp10)
|
|||
test_ScriptGetLogicalWidths();
|
||||
|
||||
test_ScriptIsComplex();
|
||||
test_script_cache_reuse();
|
||||
|
||||
ReleaseDC(hwnd, hdc);
|
||||
DestroyWindow(hwnd);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue