mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-19 17:06:04 -07:00
Merge branch 'wip.kosugi_vertical_writing' into 'master'
win32u: Use the first vertical alternates table regardless of script. See merge request wine/wine!5633
This commit is contained in:
commit
fb6b379c08
5 changed files with 1098 additions and 123 deletions
|
@ -6298,6 +6298,31 @@ static void test_vertical_font(void)
|
|||
ok(ret, "RemoveFontResourceEx() error %ld\n", GetLastError());
|
||||
|
||||
DeleteFileA(ttf_name);
|
||||
|
||||
if (!write_ttf_file("vertical2.ttf", ttf_name))
|
||||
{
|
||||
skip("Failed to create ttf file for testing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
num = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
|
||||
ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical2.ttf\n");
|
||||
|
||||
check_vertical_font("WineTestVertical2", &installed, &selected, &gm, &hgi);
|
||||
ok(installed, "WineTestVertical2 is not installed\n");
|
||||
ok(selected, "WineTestVertical2 is not selected\n");
|
||||
|
||||
check_vertical_font("@WineTestVertical2", &installed, &selected, &gm, &vgi);
|
||||
ok(installed, "@WineTestVertical2 is not installed\n");
|
||||
ok(selected, "@WineTestVertical2 is not selected\n");
|
||||
|
||||
/* use the first vertical alternates table that doesn't replace U+2025 */
|
||||
ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
|
||||
|
||||
ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
|
||||
ok(ret, "RemoveFontResourceEx() error %ld\n", GetLastError());
|
||||
|
||||
DeleteFileA(ttf_name);
|
||||
}
|
||||
|
||||
static INT CALLBACK has_vertical_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm,
|
||||
|
|
|
@ -29,6 +29,9 @@ wine_vdmx.ttf RCDATA wine_vdmx.ttf
|
|||
/* @makedep: vertical.ttf */
|
||||
vertical.ttf RCDATA vertical.ttf
|
||||
|
||||
/* @makedep: vertical2.ttf */
|
||||
vertical2.ttf RCDATA vertical2.ttf
|
||||
|
||||
/* @makedep: wine_longname.ttf */
|
||||
wine_longname.ttf RCDATA wine_longname.ttf
|
||||
|
||||
|
|
1059
dlls/gdi32/tests/vertical2.sfd
Normal file
1059
dlls/gdi32/tests/vertical2.sfd
Normal file
File diff suppressed because it is too large
Load diff
BIN
dlls/gdi32/tests/vertical2.ttf
Normal file
BIN
dlls/gdi32/tests/vertical2.ttf
Normal file
Binary file not shown.
|
@ -2525,39 +2525,6 @@ typedef struct
|
|||
WORD LookupList;
|
||||
} GSUB_Header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CHAR ScriptTag[4];
|
||||
WORD Script;
|
||||
} GSUB_ScriptRecord;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD ScriptCount;
|
||||
GSUB_ScriptRecord ScriptRecord[1];
|
||||
} GSUB_ScriptList;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CHAR LangSysTag[4];
|
||||
WORD LangSys;
|
||||
} GSUB_LangSysRecord;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD DefaultLangSys;
|
||||
WORD LangSysCount;
|
||||
GSUB_LangSysRecord LangSysRecord[1];
|
||||
} GSUB_Script;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD LookupOrder; /* Reserved */
|
||||
WORD ReqFeatureIndex;
|
||||
WORD FeatureCount;
|
||||
WORD FeatureIndex[1];
|
||||
} GSUB_LangSys;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CHAR FeatureTag[4];
|
||||
|
@ -2627,91 +2594,13 @@ typedef struct
|
|||
WORD Substitute[1];
|
||||
} GSUB_SingleSubstFormat2;
|
||||
|
||||
static GSUB_Script *GSUB_get_script_table( GSUB_Header *header, const char *tag )
|
||||
{
|
||||
GSUB_ScriptList *script;
|
||||
GSUB_Script *deflt = NULL;
|
||||
int i;
|
||||
|
||||
script = (GSUB_ScriptList *)((BYTE *)header + GET_BE_WORD(header->ScriptList));
|
||||
TRACE("%i scripts in this font\n", GET_BE_WORD(script->ScriptCount) );
|
||||
for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
|
||||
{
|
||||
int offset = GET_BE_WORD(script->ScriptRecord[i].Script);
|
||||
GSUB_Script *scr = (GSUB_Script *)((BYTE *)script + offset);
|
||||
if (!memcmp( script->ScriptRecord[i].ScriptTag, tag, 4 )) return scr;
|
||||
if (!memcmp( script->ScriptRecord[i].ScriptTag, "dflt", 4 )) deflt = scr;
|
||||
}
|
||||
return deflt;
|
||||
}
|
||||
|
||||
static GSUB_LangSys *GSUB_get_lang_table( GSUB_Script *script, const char *tag )
|
||||
{
|
||||
int i, offset;
|
||||
GSUB_LangSys *lang;
|
||||
|
||||
TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
|
||||
|
||||
for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
|
||||
{
|
||||
offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
|
||||
lang = (GSUB_LangSys *)((BYTE *)script + offset);
|
||||
if (!memcmp( script->LangSysRecord[i].LangSysTag, tag, 4 )) return lang;
|
||||
}
|
||||
offset = GET_BE_WORD(script->DefaultLangSys);
|
||||
if (offset) return (GSUB_LangSys *)((BYTE *)script + offset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GSUB_Feature *GSUB_get_feature( GSUB_Header *header, GSUB_LangSys *lang, const char *tag )
|
||||
{
|
||||
int i;
|
||||
const GSUB_FeatureList *feature;
|
||||
|
||||
feature = (GSUB_FeatureList *)((BYTE *)header + GET_BE_WORD(header->FeatureList));
|
||||
TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
|
||||
for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
|
||||
{
|
||||
int index = GET_BE_WORD(lang->FeatureIndex[i]);
|
||||
if (!memcmp( feature->FeatureRecord[index].FeatureTag, tag, 4 ))
|
||||
return (GSUB_Feature *)((BYTE *)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *get_opentype_script( const struct gdi_font *font )
|
||||
{
|
||||
/*
|
||||
* I am not sure if this is the correct way to generate our script tag
|
||||
*/
|
||||
switch (font->charset)
|
||||
{
|
||||
case ANSI_CHARSET: return "latn";
|
||||
case BALTIC_CHARSET: return "latn"; /* ?? */
|
||||
case CHINESEBIG5_CHARSET: return "hani";
|
||||
case EASTEUROPE_CHARSET: return "latn"; /* ?? */
|
||||
case GB2312_CHARSET: return "hani";
|
||||
case GREEK_CHARSET: return "grek";
|
||||
case HANGUL_CHARSET: return "hang";
|
||||
case RUSSIAN_CHARSET: return "cyrl";
|
||||
case SHIFTJIS_CHARSET: return "kana";
|
||||
case TURKISH_CHARSET: return "latn"; /* ?? */
|
||||
case VIETNAMESE_CHARSET: return "latn";
|
||||
case JOHAB_CHARSET: return "latn"; /* ?? */
|
||||
case ARABIC_CHARSET: return "arab";
|
||||
case HEBREW_CHARSET: return "hebr";
|
||||
case THAI_CHARSET: return "thai";
|
||||
default: return "latn";
|
||||
}
|
||||
}
|
||||
|
||||
static void *get_GSUB_vert_feature( struct gdi_font *font )
|
||||
{
|
||||
int i, j;
|
||||
GSUB_Header *header;
|
||||
GSUB_Script *script;
|
||||
GSUB_LangSys *language;
|
||||
GSUB_Feature *feature;
|
||||
GSUB_FeatureList *feature_list;
|
||||
UINT length = font_funcs->get_font_data( font, MS_GSUB_TAG, 0, NULL, 0 );
|
||||
static const char* feature_tag[] = { "vrt2", "vert" };
|
||||
|
||||
if (length == GDI_ERROR) return NULL;
|
||||
|
||||
|
@ -2719,22 +2608,21 @@ static void *get_GSUB_vert_feature( struct gdi_font *font )
|
|||
font_funcs->get_font_data( font, MS_GSUB_TAG, 0, header, length );
|
||||
TRACE( "Loaded GSUB table of %i bytes\n", length );
|
||||
|
||||
if ((script = GSUB_get_script_table( header, get_opentype_script(font) )))
|
||||
/* gdi doesn't use ScriptList and LangSys for vertical writing feature */
|
||||
feature_list = (GSUB_FeatureList *)((BYTE *)header + GET_BE_WORD(header->FeatureList));
|
||||
for (i = 0; i < ARRAY_SIZE(feature_tag); i++)
|
||||
{
|
||||
if ((language = GSUB_get_lang_table( script, "xxxx" ))) /* Need to get Lang tag */
|
||||
for (j = 0; j < GET_BE_WORD(feature_list->FeatureCount); j++)
|
||||
{
|
||||
feature = GSUB_get_feature( header, language, "vrt2" );
|
||||
if (!feature) feature = GSUB_get_feature( header, language, "vert" );
|
||||
if (feature)
|
||||
GSUB_FeatureRecord *feature = &feature_list->FeatureRecord[j];
|
||||
if (!memcmp( feature->FeatureTag, feature_tag[i], 4 ))
|
||||
{
|
||||
font->gsub_table = header;
|
||||
return feature;
|
||||
return (BYTE *)feature_list + GET_BE_WORD(feature->Feature);
|
||||
}
|
||||
TRACE("vrt2/vert feature not found\n");
|
||||
}
|
||||
else TRACE("Language not found\n");
|
||||
}
|
||||
else TRACE("Script not found\n");
|
||||
TRACE("vrt2/vert feature not found\n");
|
||||
|
||||
free( header );
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in a new issue