diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index c238d09e8f9..7f23296664c 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -3775,3 +3775,63 @@ DWORD CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DW } return 0; } + +static HRESULT GSUB_GetFontScriptTags(LPCVOID table, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags, LPCVOID* script_table) +{ + const GSUB_ScriptList *script; + const GSUB_Header* header = (const GSUB_Header*)table; + int i; + HRESULT rc = S_OK; + + script = (const GSUB_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList)); + + *pcTags = 0; + TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount)); + if (!searchingFor && cMaxTags < GET_BE_WORD(script->ScriptCount)) + rc = E_OUTOFMEMORY; + for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++) + { + if (searchingFor) + { + if (strncmp(script->ScriptRecord[i].ScriptTag, (char*)&searchingFor,4)==0) + { + pScriptTags[0] = MS_MAKE_TAG(script->ScriptRecord[i].ScriptTag[0], script->ScriptRecord[i].ScriptTag[1], script->ScriptRecord[i].ScriptTag[2], script->ScriptRecord[i].ScriptTag[3]); + *pcTags = 1; + if (script_table) + { + int offset = GET_BE_WORD(script->ScriptRecord[i].Script); + *script_table = ((const BYTE*)script + offset); + } + break; + } + } + else if (i < cMaxTags) + { + pScriptTags[i] = MS_MAKE_TAG(script->ScriptRecord[i].ScriptTag[0], script->ScriptRecord[i].ScriptTag[1], script->ScriptRecord[i].ScriptTag[2], script->ScriptRecord[i].ScriptTag[3]); + *pcTags = *pcTags + 1; + } + } + return rc; +} + +HRESULT SHAPE_GetFontScriptTags( HDC hdc, ScriptCache *psc, + SCRIPT_ANALYSIS *psa, int cMaxTags, + OPENTYPE_TAG *pScriptTags, int *pcTags) +{ + HRESULT hr; + OPENTYPE_TAG searching = 0x00000000; + + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + if (psa) + { + if (ShapingData[psa->eScript].otTag[0] != 0) + searching = MS_MAKE_TAG(ShapingData[psa->eScript].otTag[0], ShapingData[psa->eScript].otTag[1], ShapingData[psa->eScript].otTag[2], ShapingData[psa->eScript].otTag[3]); + } + + hr = GSUB_GetFontScriptTags(psc->GSUB_Table, searching, cMaxTags, pScriptTags, pcTags, NULL); + if (FAILED(hr)) + *pcTags = 0; + return hr; +} diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c index 2e05f480197..cdd15105fe0 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -59,6 +59,8 @@ static HRESULT (WINAPI *pScriptShapeOpenType)( HDC hdc, SCRIPT_CACHE *psc, SCRIP 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 inline void _test_items_ok(LPCWSTR string, DWORD cchString, SCRIPT_CONTROL *Control, SCRIPT_STATE *State, DWORD nItems, const itemTest* items, BOOL nItemsToDo, @@ -2865,6 +2867,46 @@ static void test_newlines(void) ok(count == 4, "got %d expected 4\n", count); } +static void test_ScriptGetFontFunctions(HDC hdc) +{ + HRESULT hr; + pScriptGetFontScriptTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontScriptTags"); + if (!pScriptGetFontScriptTags) + { + win_skip("ScriptGetFontScriptTags not available on this platform\n"); + } + else + { + SCRIPT_CACHE sc = NULL; + OPENTYPE_TAG tags[5]; + int count = 0; + + hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, NULL, NULL); + ok(hr == E_INVALIDARG,"Incorrect return code\n"); + ok(sc == NULL, "ScriptCache should remain uninitialized\n"); + hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, NULL, &count); + ok(hr == E_INVALIDARG,"Incorrect return code\n"); + ok(sc == NULL, "ScriptCache should remain uninitialized\n"); + hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 5, tags, NULL); + ok(hr == E_INVALIDARG,"Incorrect return code\n"); + ok(sc == NULL, "ScriptCache should remain uninitialized\n"); + hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, tags, &count); + ok(hr == E_INVALIDARG,"Incorrect return code\n"); + ok(sc == NULL, "ScriptCache should remain uninitialized\n"); + hr = pScriptGetFontScriptTags(NULL, &sc, NULL, 5, tags, &count); + ok(hr == E_PENDING,"Incorrect return code\n"); + ok(sc == NULL, "ScriptCache should remain uninitialized\n"); + hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 5, tags, &count); + ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); + if (hr == S_OK) + ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); + else if (hr == E_OUTOFMEMORY) + ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); + ok(sc != NULL, "ScriptCache should be initialized\n"); + ScriptFreeCache(&sc); + } +} + START_TEST(usp10) { HWND hwnd; @@ -2917,6 +2959,8 @@ START_TEST(usp10) test_ScriptBreak(); test_newlines(); + test_ScriptGetFontFunctions(hdc); + ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); } diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c index 93d7b0f9e78..14674a7bbb2 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -3525,3 +3525,12 @@ HRESULT WINAPI ScriptJustify(const SCRIPT_VISATTR *sva, const int *advance, for (i = 0; i < num_glyphs; i++) justify[i] = advance[i]; return S_OK; } + +HRESULT WINAPI ScriptGetFontScriptTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags) +{ + HRESULT hr; + if (!pScriptTags || !pcTags || cMaxTags == 0) return E_INVALIDARG; + if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; + + return SHAPE_GetFontScriptTags(hdc, (ScriptCache *)*psc, psa, cMaxTags, pScriptTags, pcTags); +} diff --git a/dlls/usp10/usp10.spec b/dlls/usp10/usp10.spec index 05269c581be..63375a59808 100644 --- a/dlls/usp10/usp10.spec +++ b/dlls/usp10/usp10.spec @@ -10,7 +10,7 @@ @ stub ScriptGetFontFeatureTags @ stub ScriptGetFontLanguageTags @ stdcall ScriptGetFontProperties(long ptr ptr) -@ stub ScriptGetFontScriptTags +@ stdcall ScriptGetFontScriptTags(long ptr ptr long ptr ptr) @ stdcall ScriptGetGlyphABCWidth(ptr ptr long ptr) @ stdcall ScriptGetLogicalWidths(ptr long long ptr ptr ptr ptr) @ stdcall ScriptGetProperties(ptr long) diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index ea04324bde6..559a0bc22b4 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -184,6 +184,7 @@ void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa) DECLSPEC_HIDDEN; void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN; INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, const WCHAR *chars, INT write_dir, INT count, const char* feature) DECLSPEC_HIDDEN; +HRESULT SHAPE_GetFontScriptTags( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags); void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChars, IndicSyllable **syllables, int *syllable_count, lexical_function lexical_f, reorder_function reorder_f, BOOL modern) DECLSPEC_HIDDEN; void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern);