Commit 3d98085d authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

usp10: Implement ScriptGetFontFeatureTags.

parent dbe02b96
......@@ -3878,6 +3878,112 @@ static HRESULT GSUB_GetFontLanguageTags(ScriptCache *psc, OPENTYPE_TAG script_ta
return rc;
}
static void GSUB_initialize_feature_cache(LPCVOID table, LoadedLanguage *language)
{
int i;
if (!language->feature_count)
{
const GSUB_LangSys *lang= language->table;
const GSUB_Header *header = (const GSUB_Header *)table;
const GSUB_FeatureList *feature_list;
language->feature_count = GET_BE_WORD(lang->FeatureCount);
TRACE("%i features\n",language->feature_count);
language->features = HeapAlloc(GetProcessHeap(),0,sizeof(LoadedFeature)*language->feature_count);
feature_list = (const GSUB_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
for (i = 0; i < language->feature_count; i++)
{
int index = GET_BE_WORD(lang->FeatureIndex[i]);
language->features[i].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]);
language->features[i].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature));
}
}
}
static HRESULT GSUB_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature)
{
int i;
HRESULT rc = S_OK;
LoadedScript *script = NULL;
LoadedLanguage *language = NULL;
GSUB_initialize_script_cache(psc);
for (i = 0; i < psc->script_count; i++)
{
if (psc->scripts[i].tag == script_tag)
{
script = &psc->scripts[i];
break;
}
}
if (!script)
{
*pcTags = 0;
if (!filtered)
return S_OK;
else
return E_INVALIDARG;
}
GSUB_initialize_language_cache(script);
if (script->default_language.table && script->default_language.tag == language_tag)
language = &script->default_language;
else
{
for (i = 0; i < script->language_count; i++)
{
if (script->languages[i].tag == language_tag)
{
language = &script->languages[i];
break;
}
}
}
if (!language)
{
*pcTags = 0;
return S_OK;
}
GSUB_initialize_feature_cache(psc->GSUB_Table, language);
*pcTags = language->feature_count;
if (!searchingFor && cMaxTags < *pcTags)
rc = E_OUTOFMEMORY;
else if (searchingFor)
rc = E_INVALIDARG;
for (i = 0; i < language->feature_count; i++)
{
if (i < cMaxTags)
pFeatureTags[i] = language->features[i].tag;
if (searchingFor)
{
if (searchingFor == language->features[i].tag)
{
pFeatureTags[0] = language->features[i].tag;
*pcTags = 1;
if (feature)
*feature = &language->features[i];
rc = S_OK;
break;
}
}
}
return rc;
}
HRESULT SHAPE_GetFontScriptTags( HDC hdc, ScriptCache *psc,
SCRIPT_ANALYSIS *psa, int cMaxTags,
OPENTYPE_TAG *pScriptTags, int *pcTags)
......@@ -3925,3 +4031,27 @@ HRESULT SHAPE_GetFontLanguageTags( HDC hdc, ScriptCache *psc,
hr = E_INVALIDARG;
return hr;
}
HRESULT SHAPE_GetFontFeatureTags( HDC hdc, ScriptCache *psc,
SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript,
OPENTYPE_TAG tagLangSys, int cMaxTags,
OPENTYPE_TAG *pFeatureTags, int *pcTags)
{
HRESULT hr;
BOOL filter = FALSE;
if (!psc->GSUB_Table)
psc->GSUB_Table = load_gsub_table(hdc);
if (psa && scriptInformation[psa->eScript].scriptTag)
{
FIXME("Filtering not implemented\n");
filter = TRUE;
}
hr = GSUB_GetFontFeatureTags(psc, tagScript, tagLangSys, filter, 0x00000000, cMaxTags, pFeatureTags, pcTags, NULL);
if (FAILED(hr))
*pcTags = 0;
return hr;
}
......@@ -61,6 +61,7 @@ static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWO
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);
static inline void _test_items_ok(LPCWSTR string, DWORD cchString,
SCRIPT_CONTROL *Control, SCRIPT_STATE *State,
......@@ -2873,9 +2874,10 @@ static void test_ScriptGetFontFunctions(HDC hdc)
HRESULT hr;
pScriptGetFontScriptTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontScriptTags");
pScriptGetFontLanguageTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontLanguageTags");
if (!pScriptGetFontScriptTags || !pScriptGetFontLanguageTags)
pScriptGetFontFeatureTags = (void*)GetProcAddress(GetModuleHandleA("usp10.dll"), "ScriptGetFontFeatureTags");
if (!pScriptGetFontScriptTags || !pScriptGetFontLanguageTags || !pScriptGetFontFeatureTags)
{
win_skip("ScriptGetFontScriptTags or ScriptGetFontLanguageTags not available on this platform\n");
win_skip("ScriptGetFontScriptTags,ScriptGetFontLanguageTags or ScriptGetFontFeatureTags not available on this platform\n");
}
else
{
......@@ -2936,6 +2938,31 @@ static void test_ScriptGetFontFunctions(HDC hdc)
else if (hr == E_OUTOFMEMORY)
ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n");
ScriptFreeCache(&sc);
sc = NULL;
hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, NULL, NULL);
ok(hr == E_INVALIDARG,"Incorrect return code\n");
ok(sc == NULL, "ScriptCache should remain uninitialized\n");
hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, NULL, &count);
ok(hr == E_INVALIDARG,"Incorrect return code\n");
ok(sc == NULL, "ScriptCache should remain uninitialized\n");
hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 5, tags, NULL);
ok(hr == E_INVALIDARG,"Incorrect return code\n");
ok(sc == NULL, "ScriptCache should remain uninitialized\n");
hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, tags, &count);
ok(hr == E_INVALIDARG,"Incorrect return code\n");
ok(sc == NULL, "ScriptCache should remain uninitialized\n");
hr = pScriptGetFontFeatureTags(NULL, &sc, NULL, latn_tag, 0x0, 5, tags, &count);
ok(hr == E_PENDING,"Incorrect return code\n");
ok(sc == NULL, "ScriptCache should remain uninitialized\n");
hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 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");
memset(&Control, 0, sizeof(Control));
memset(&State, 0, sizeof(State));
......@@ -2950,6 +2977,11 @@ static void test_ScriptGetFontFunctions(HDC hdc)
hr = pScriptGetFontLanguageTags(hdc, &sc, &outpItems[0].a, dsrt_tag, 5, tags, &count);
ok( hr == E_INVALIDARG || broken(hr == S_OK), "wrong return code\n");
hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, dsrt_tag, 0x0, 5, tags, &count);
ok( hr == S_OK, "wrong return code\n");
hr = pScriptGetFontFeatureTags(hdc, &sc, &outpItems[0].a, dsrt_tag, 0x0, 5, tags, &count);
ok( hr == E_INVALIDARG || broken(hr == S_OK), "wrong return code\n");
ScriptFreeCache(&sc);
}
}
......
......@@ -926,7 +926,12 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
heap_free(((ScriptCache *)*psc)->GDEF_Table);
heap_free(((ScriptCache *)*psc)->CMAP_Table);
for (i = 0; i < ((ScriptCache *)*psc)->script_count; i++)
{
int j;
for (j = 0; j < ((ScriptCache *)*psc)->scripts[i].language_count; j++)
heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features);
heap_free(((ScriptCache *)*psc)->scripts[i].languages);
}
heap_free(((ScriptCache *)*psc)->scripts);
heap_free(((ScriptCache *)*psc)->features);
heap_free(*psc);
......@@ -3563,3 +3568,12 @@ HRESULT WINAPI ScriptGetFontLanguageTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANA
return SHAPE_GetFontLanguageTags(hdc, (ScriptCache *)*psc, psa, tagScript, cMaxTags, pLangSysTags, pcTags);
}
HRESULT WINAPI ScriptGetFontFeatureTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags)
{
HRESULT hr;
if (!pFeatureTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
return SHAPE_GetFontFeatureTags(hdc, (ScriptCache *)*psc, psa, tagScript, tagLangSys, cMaxTags, pFeatureTags, pcTags);
}
......@@ -7,7 +7,7 @@
@ stdcall ScriptFreeCache(ptr)
@ stdcall ScriptGetCMap(ptr ptr ptr long long ptr)
@ stub ScriptGetFontAlternateGlyphs
@ stub ScriptGetFontFeatureTags
@ stdcall ScriptGetFontFeatureTags(long ptr ptr long long long ptr ptr)
@ stdcall ScriptGetFontLanguageTags(long ptr ptr long long ptr ptr)
@ stdcall ScriptGetFontProperties(long ptr ptr)
@ stdcall ScriptGetFontScriptTags(long ptr ptr long ptr ptr)
......
......@@ -134,6 +134,8 @@ typedef struct {
typedef struct {
OPENTYPE_TAG tag;
LPCVOID table;
INT feature_count;
LoadedFeature *features;
} LoadedLanguage;
typedef struct {
......@@ -213,6 +215,7 @@ void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const
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) DECLSPEC_HIDDEN;
HRESULT SHAPE_GetFontLanguageTags( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags) DECLSPEC_HIDDEN;
HRESULT SHAPE_GetFontFeatureTags( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags) DECLSPEC_HIDDEN;
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) DECLSPEC_HIDDEN;
......
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