Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: The first two patches are mostly unrelated to the optimization goal, and are there to test and fix the face lookup logic wrt non-english names.
Then, change of plans, although the series doesn't change much from the previous patches, I now intend to do the font parsing by hand, getting rid of freetype when possible, and not relying on fontconfig anymore. This makes the font face listing faster for all platforms and cases.
In order to achieve that, as previously, I need to first invert the creation order between FT_Face and gdi32 Face. Making face creation independent of freetype first, and make it provide all required data to then create FT_Face from it.
Next I intend to send patches that iteratively add font info parsing with a FreeType fallback to support other font formats. Ultimately it will also allow us to start using FreeType cache manager instead of creating the faces manually. It shouldn't change much for the initial listing --as in any case we should avoid using FreeType at that point-- but it could also benefit to the GdiFont logic too.
Last in the future patches, I'm planning on improving the font family indexation performance, reducing the registry load once re-parsing the system fonts is faster than caching them, listing fontconfig fonts directly from its caches, and possibly then implementing some kind of lazy initialization.
Overall I think it can achieve ~30% to ~50% prefix startup time reduction, as well as good improvements on process startup time (with the prefix already started).
dlls/gdi32/tests/Makefile.in | 3 + dlls/gdi32/tests/font.c | 265 +++++++++++++++++++++++++++ dlls/gdi32/tests/resource.rc | 9 + dlls/gdi32/tests/wine_langnames.sfd | 138 ++++++++++++++ dlls/gdi32/tests/wine_langnames.ttf | Bin 0 -> 2792 bytes dlls/gdi32/tests/wine_langnames2.sfd | 80 ++++++++ dlls/gdi32/tests/wine_langnames2.ttf | Bin 0 -> 2016 bytes dlls/gdi32/tests/wine_langnames3.sfd | 78 ++++++++ dlls/gdi32/tests/wine_langnames3.ttf | Bin 0 -> 2048 bytes 9 files changed, 573 insertions(+) create mode 100644 dlls/gdi32/tests/wine_langnames.sfd create mode 100644 dlls/gdi32/tests/wine_langnames.ttf create mode 100644 dlls/gdi32/tests/wine_langnames2.sfd create mode 100644 dlls/gdi32/tests/wine_langnames2.ttf create mode 100644 dlls/gdi32/tests/wine_langnames3.sfd create mode 100644 dlls/gdi32/tests/wine_langnames3.ttf
diff --git a/dlls/gdi32/tests/Makefile.in b/dlls/gdi32/tests/Makefile.in index 8b722cfe5d2..975750886e4 100644 --- a/dlls/gdi32/tests/Makefile.in +++ b/dlls/gdi32/tests/Makefile.in @@ -24,6 +24,9 @@ FONT_SRCS = \ wine_test.sfd \ wine_ttfnames.sfd \ wine_ttfnames_bold.sfd \ + wine_langnames.sfd \ + wine_langnames2.sfd \ + wine_langnames3.sfd \ wine_vdmx.sfd
RC_SRCS = resource.rc diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index f5c8d4dac3b..bfcfad30e24 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -2757,6 +2757,12 @@ struct enum_fullname_data ENUMLOGFONTA *elf; };
+struct enum_fullname_data_w +{ + int total, size; + ENUMLOGFONTW *elf; +}; + struct enum_font_dataW { int total, size; @@ -3110,6 +3116,23 @@ static INT CALLBACK enum_fullname_data_proc(const LOGFONTA *lf, const TEXTMETRIC return 1; }
+static INT CALLBACK enum_fullname_data_proc_w( const LOGFONTW *lf, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam ) +{ + struct enum_fullname_data_w *efnd = (struct enum_fullname_data_w *)lParam; + + if (type != TRUETYPE_FONTTYPE) return 1; + + if (efnd->total >= efnd->size) + { + efnd->size = max( (efnd->total + 1) * 2, 256 ); + efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) ); + if (!efnd->elf) return 0; + } + efnd->elf[efnd->total++] = *(ENUMLOGFONTW *)lf; + + return 1; +} + static void test_EnumFontFamiliesEx_default_charset(void) { struct enum_font_data efd; @@ -7007,6 +7030,247 @@ static void test_ttf_names(void) ReleaseDC(NULL, dc); }
+static void test_lang_names(void) +{ + static const WCHAR name_cond_ja_w[] = {0x30d5,0x30a9,0x30f3,0x30c8,0x540d,' ','C','o','n','d',' ','(','j','a',')',0}; + static const WCHAR name_cond_ja_reg_w[] = {0x30d5,0x30a9,0x30f3,0x30c8,0x540d,' ','C','o','n','d',' ','(','j','a',')',' ','R','e','g',0}; + static const WCHAR name_cond_ja_reg_ja_w[] = {0x30d5,0x30a9,0x30f3,0x30c8,0x540d,' ','C','o','n','d',' ','(','j','a',')',' ','R','e','g',' ','(','j','a',')',0}; + static const WCHAR name_wws_ja_w[] = {0x30d5,0x30a9,0x30f3,0x30c8,0x540d,' ','W','W','S',' ','(','j','a',')',0}; + + struct enum_fullname_data efnd; + struct enum_fullname_data_w efnd_w; + char ttf_name[MAX_PATH], ttf_name2[MAX_PATH], ttf_name3[MAX_PATH]; + LOGFONTA font = {0}; + LOGFONTW font_w = {0}; + int ret, i; + HDC dc; + const WCHAR *primary_family, *primary_fullname; + + if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH && PRIMARYLANGID(GetUserDefaultLangID()) != LANG_JAPANESE) + { + skip( "Primary language is neither English nor Japanese, skipping test\n" ); + return; + } + + if (!write_ttf_file( "wine_langnames.ttf", ttf_name )) + { + skip( "Failed to create ttf file for testing\n" ); + return; + } + + if (!write_ttf_file( "wine_langnames2.ttf", ttf_name2 )) + { + skip( "Failed to create ttf file for testing\n" ); + DeleteFileA( ttf_name ); + return; + } + + if (!write_ttf_file( "wine_langnames3.ttf", ttf_name3 )) + { + skip( "Failed to create ttf file for testing\n" ); + DeleteFileA( ttf_name2 ); + DeleteFileA( ttf_name ); + return; + } + + ret = AddFontResourceExA( ttf_name, FR_PRIVATE, 0 ); + ok( ret, "AddFontResourceEx() failed\n" ); + + dc = GetDC( NULL ); + + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH) + { + primary_family = L"Wine Lang Cond (en)"; + primary_fullname = L"Wine Lang Cond Reg (en)"; + } + else + { + primary_family = name_cond_ja_w; + primary_fullname = name_cond_ja_reg_w; + } + + for (i = 0; i < 3; ++i) + { + /* check that lookup by preferred or WWS family / full names or postscript FontName doesn't work */ + + strcpy( font.lfFaceName, "Wine Lang (en)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "Wine Lang Condensed Bold (ko)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + wcscpy( font_w.lfFaceName, name_wws_ja_w ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total ); + + strcpy( font.lfFaceName, "Reg WWS (zh-tw)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "Wine Lang (en) Reg WWS (en)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "WineLangNamesRegular" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + /* then, the primary ttf family name always works */ + + wcscpy( font_w.lfFaceName, primary_family ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == min( 2, i + 1 ), "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total ); + + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH) + { + wcscpy( font_w.lfFaceName, name_cond_ja_w ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total ); + } + + /* if there is no primary ttf family name, the english ttf name, or postscript FamilyName are used instead */ + + strcpy( font.lfFaceName, "Wine_Lang_Names" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + if (i == 2) + ok( efnd.total == 1, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + else + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + /* same goes for ttf full names */ + + wcscpy( font_w.lfFaceName, primary_fullname ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == 1, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total ); + + if (efnd_w.total >= 1) + { + ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfLogFont.lfFaceName, primary_family ), + "%d: (%d) unexpected lfFaceName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfLogFont.lfFaceName) ); + ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfFullName, primary_fullname ), + "%d: (%d) unexpected elfFullName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfFullName) ); + ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfStyle, PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH ? L"Reg (en)" : L"Reg (ja)" ), + "%d: (%d) unexpected elfStyle %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfStyle) ); + } + + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH) + { + wcscpy( font_w.lfFaceName, name_cond_ja_reg_w ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total ); + } + + wcscpy( font_w.lfFaceName, L"Wine_Lang_Names_Regular" ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == i, "%d: EnumFontFamiliesExW unexpected count %u.\n", i, efnd_w.total ); + + while (efnd_w.total--) + { + ok( !wcscmp( (WCHAR *)efnd_w.elf[efnd_w.total].elfLogFont.lfFaceName, efnd_w.total == 1 ? L"Wine_Lang_Names" : primary_family ), + "%d: (%d) unexpected lfFaceName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[efnd_w.total].elfLogFont.lfFaceName) ); + ok( !wcscmp( (WCHAR *)efnd_w.elf[efnd_w.total].elfFullName, L"Wine_Lang_Names_Regular" ), + "%d: (%d) unexpected elfFullName %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[efnd_w.total].elfFullName) ); + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH) + ok( !wcscmp( (WCHAR *)efnd_w.elf[efnd_w.total].elfStyle, efnd_w.total == 1 ? L"Regular" : L"Reg (en)" ), + "%d: (%d) unexpected elfStyle %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[efnd_w.total].elfStyle) ); + else + ok( !wcscmp( (WCHAR *)efnd_w.elf[0].elfStyle, L"Reg (ja)" ), + "%d: (%d) unexpected elfStyle %s\n", i, efnd_w.total, debugstr_w((WCHAR *)efnd_w.elf[0].elfStyle) ); + } + + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH) + { + wcscpy( font_w.lfFaceName, name_cond_ja_reg_ja_w ); + memset( &efnd_w, 0, sizeof(efnd_w) ); + EnumFontFamiliesExW( dc, &font_w, enum_fullname_data_proc_w, (LPARAM)&efnd_w, 0 ); + ok( efnd_w.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd_w.total ); + } + + /* another language can also be used for lookup, if the primary langid isn't english, then + english seems to have priority, otherwise or if english is already the primary langid, + the family name with the smallest langid is used as secondary lookup language. */ + + strcpy( font.lfFaceName, "Wine Lang Cond (zh-tw)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH) + todo_wine ok( efnd.total == min( 2, i + 1 ), "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + else /* (zh-tw) doesn't match here probably because there's an (en) name too */ + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "Wine Lang Cond (en)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + /* either because it's the primary language, or because it's a secondary */ + ok( efnd.total == min( 2, i + 1 ), "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "Wine Lang Cond (fr)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + /* as wine_langnames3.sfd does not specify (en) name, (fr) is preferred */ + if (i == 2) todo_wine ok( efnd.total == 1, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + else ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "Wine Lang Cond (ko)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + /* that doesn't apply to full names */ + + strcpy( font.lfFaceName, "Wine Lang Cond Reg (zh-tw)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + strcpy( font.lfFaceName, "Wine Lang Cond Reg (fr)" ); + memset( &efnd, 0, sizeof(efnd) ); + EnumFontFamiliesExA( dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0 ); + ok( efnd.total == 0, "%d: EnumFontFamiliesExA unexpected count %u.\n", i, efnd.total ); + + if (i == 0) + { + ret = AddFontResourceExA( ttf_name2, FR_PRIVATE, 0 ); + ok( ret, "AddFontResourceEx() failed\n" ); + } + else if (i == 1) + { + ret = AddFontResourceExA( ttf_name3, FR_PRIVATE, 0 ); + ok( ret, "AddFontResourceEx() failed\n" ); + } + } + + ret = RemoveFontResourceExA( ttf_name3, FR_PRIVATE, 0 ); + ok( ret, "RemoveFontResourceEx() failed\n" ); + + DeleteFileA( ttf_name3 ); + + ret = RemoveFontResourceExA( ttf_name2, FR_PRIVATE, 0 ); + ok( ret, "RemoveFontResourceEx() failed\n" ); + + DeleteFileA( ttf_name2 ); + + ret = RemoveFontResourceExA( ttf_name, FR_PRIVATE, 0 ); + ok( ret, "RemoveFontResourceEx() failed\n" ); + + DeleteFileA( ttf_name ); + ReleaseDC( NULL, dc ); +} + typedef struct { USHORT majorVersion; @@ -7419,6 +7683,7 @@ START_TEST(font) test_GetCharWidthI(); test_long_names(); test_ttf_names(); + test_lang_names(); test_char_width();
/* These tests should be last test until RemoveFontResource diff --git a/dlls/gdi32/tests/resource.rc b/dlls/gdi32/tests/resource.rc index b5a6107a987..6cbe789880b 100644 --- a/dlls/gdi32/tests/resource.rc +++ b/dlls/gdi32/tests/resource.rc @@ -37,3 +37,12 @@ wine_ttfnames.ttf RCDATA wine_ttfnames.ttf
/* @makedep: wine_ttfnames_bold.ttf */ wine_ttfnames_bold.ttf RCDATA wine_ttfnames_bold.ttf + +/* @makedep: wine_langnames.ttf */ +wine_langnames.ttf RCDATA wine_langnames.ttf + +/* @makedep: wine_langnames2.ttf */ +wine_langnames2.ttf RCDATA wine_langnames2.ttf + +/* @makedep: wine_langnames3.ttf */ +wine_langnames3.ttf RCDATA wine_langnames3.ttf diff --git a/dlls/gdi32/tests/wine_langnames.sfd b/dlls/gdi32/tests/wine_langnames.sfd new file mode 100644 index 00000000000..4ce1e70baca --- /dev/null +++ b/dlls/gdi32/tests/wine_langnames.sfd @@ -0,0 +1,138 @@ +SplineFontDB: 3.2 +FontName: WineLangNamesRegular +FullName: Wine_Lang_Names_Regular +FamilyName: Wine_Lang_Names +Weight: Regular +Copyright: Copyright (c) 2020, Remi Bernon for CodeWeavers +UComments: "2017-11-17: Created with FontForge (http://fontforge.org)" +Version: 001.000 +ItalicAngle: 0 +UnderlinePosition: -102 +UnderlineWidth: 51 +Ascent: 819 +Descent: 205 +InvalidEm: 0 +LayerCount: 2 +Layer: 0 0 "Back" 1 +Layer: 1 0 "Fore" 0 +XUID: [1021 48 28337276 3092883] +OS2Version: 0 +OS2_WeightWidthSlopeOnly: 0 +OS2_UseTypoMetrics: 1 +CreationTime: 1510948643 +ModificationTime: 1599738445 +OS2TypoAscent: 0 +OS2TypoAOffset: 1 +OS2TypoDescent: 0 +OS2TypoDOffset: 1 +OS2TypoLinegap: 0 +OS2WinAscent: 0 +OS2WinAOffset: 1 +OS2WinDescent: 0 +OS2WinDOffset: 1 +HheadAscent: 0 +HheadAOffset: 1 +HheadDescent: 0 +HheadDOffset: 1 +OS2Vendor: 'PfEd' +MarkAttachClasses: 1 +DEI: 91125 +LangName: 1033 \ + "" \ + "Wine Lang Cond (en)" \ + "Reg (en)" \ + "" \ + "Wine Lang Cond Reg (en)" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "Wine Lang (en)" \ + "Wine Lang Condensed Reg (en)" \ + "" \ + "" \ + "" \ + "Wine Lang WWS (en)" \ + "Reg WWS (en)" +LangName: 1041 \ + "" \ + "+MNUwqTDzMMhUDQAA Cond (ja)" \ + "Reg (ja)" \ + "" \ + "+MNUwqTDzMMhUDQAA Cond (ja) Reg" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "+MNUwqTDzMMhUDQAA (ja)" \ + "+MNUwqTDzMMhUDQAA Condensed Reg (ja)" \ + "" \ + "" \ + "" \ + "+MNUwqTDzMMhUDQAA WWS (ja)" \ + "Reg WWS (ja)" +LangName: 1028 \ + "" \ + "Wine Lang Cond (zh-tw)" \ + "Reg (zh-tw)" \ + "" \ + "Wine Lang Cond Reg (zh-tw)" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "Wine Lang (zh-tw)" \ + "Wine Lang Condensed Reg (zh-tw)" \ + "" \ + "" \ + "" \ + "Wine Lang WWS (zh-tw)" \ + "Reg WWS (zh-tw)" +Encoding: ISO8859-1 +UnicodeInterp: none +NameList: AGL For New Fonts +DisplaySize: -48 +AntiAlias: 1 +FitToEm: 0 +WinInfo: 64 16 4 +BeginPrivate: 0 +EndPrivate +BeginChars: 256 1 + +StartChar: at +Encoding: 64 64 0 +Width: 1024 +VWidth: 0 +Flags: HW +LayerCount: 2 +Fore +SplineSet +259 332 m 29 + 468 664 l 29 + 514 332 l 29 + 259 332 l 29 +EndSplineSet +EndChar +EndChars +EndSplineFont diff --git a/dlls/gdi32/tests/wine_langnames.ttf b/dlls/gdi32/tests/wine_langnames.ttf new file mode 100644 index 0000000000000000000000000000000000000000..674fd1bc7e42c5051eaa3870bd097e5579e981d4 GIT binary patch literal 2792 zcmdT`OKcle6g_Wd>@*>?c1cnsqB2cGNveD%c2%{NK_Q{0i_oGZiWgKkCYjhN@z}E6 zqyZ$5*swsN>_D)C1(Xd56=H{=LaIbqAOu1bD#50U5?COz;FECf_}R|KG;5yq=AC=r z{om`+Kmpi`7hz&D9v^@FmG_q%plOBN_QxJQ9Y-r#NPi&oxv~DpL?E>Qs0``Jscb5b zeZkwLzvCX7nlIVtFkS}CcHUd*R58D?LCa`*m-L?W+~UmVOUtxx_K?nJ+|=~`wY3Ap zzi=PVkP&FK0<_ghx-*k4U22AUfb@0Jp}E{t3QuF4`ZnpNZ0b@TXK<4DXGq&#D(l`K zjs48~w}9Y}`CPHIaTCWW`aJKCLUQFUJ@fVH<i6M+xXU5~`1aUuZ_9b(h0nf32VfY+ z6_R^k2$zdGKIeQ{-Y|Si<-79J@;O#jM>Lhs8$_QkVo~HWn49s2A=Q1ge5%`ssz!1V z;8QP&v$~#`IX%t(3}VoXZbWh3kHn9uDq=%1GDgm#`&+T*Qg?s1>u6)7#Bw`@Y@QZ> zLJzV>{&VA+mV^q{94N^}_U5%E!p#>oEbjm3%b#V=jr>k97ei{SBJ6;P2J|f{^v9MP zEUZSBf`K1m%cenyB~#b|VJ|lX)!(sYmT)x^4Ic_W7!4opP@!K}R*WnEOmrACG^b28 z!ijrbYOL-f`Bk49Q6uYDrFfm{qe@TEk4cRc?!m_z8=SeD8k?M@a~fMXpgz<%fRI|% zIEWUbOXCps8c%8*M!WHj#;w?I+|sxW&1Q>Cjtnq*%)c}?&}MaOY~h&oh{hpwSPL45 z@v!x##;rJN-O#uV2Lla0mYIKwTkJQ|{t;Z(*gyy?8k?BGEsZVosh2bkz*b*q97LB| z*Eqyn9@03B6UGINThVEJs&O0cHU9K*n0^nMhcu>Nvz$wq|BoZ)nC6GjVm_yF7>@ax z#;s^KuW3x1=1&+#4tXr1fLWxGL5csiE=-}DX9SMFdx%HjB1;(?Lqr95)bmKq@GS5Y zJJY;LaHlZu%M^j(Tz;`Io6eN%uBmQ2;zXPtd(_R&+Cy%^%X#)pu3!)6rrm^_ns*CS zNYIBzZ5t!B<1wbPZI9L^GMBt=ip_eiJ(BX$)b^(BF4rSdViftR)To=*S8+ew667pU zNE}4?vU7Nz;;y(&R^29XmH}ibSwvEszKA*UBwf)Npmr}`=)KiKA)fO}@mwM8+L1oT zK4nXoNeMG~maqF_k^x<uOBHxC;PjsCm3r)!@{XjorC!T%g0U7D?W~`x&FCD)C^^c{ z1}0eHSr*-K2KpSwA*YgdrPj5S%Wf+P`}LMQ{4{hHHTBKSsusT%XSq8SUz>$xYNWH$ z)gqtL<6RPVy`nqK8LD))p4kKw8>6W@u_O{>+oolQu-LAOIo~+%IlnvC$M2@SO1NVA z0w;kpw<%oB*+rw0AhyU=?QP*!{M9c{J%6=iw#T>gre5VL9wozP`8w$33t?efo?H2M zwo+^6?poVD-pO+PitO&AR)wvyl{o+Fo{iRD6&qI(C8fBxF8P>IlsfFQ6~9wzUtZ1p XE|q(+A(~}v|M~se`X{2X`Md64$O)6Q
literal 0 HcmV?d00001
diff --git a/dlls/gdi32/tests/wine_langnames2.sfd b/dlls/gdi32/tests/wine_langnames2.sfd new file mode 100644 index 00000000000..50199af9adf --- /dev/null +++ b/dlls/gdi32/tests/wine_langnames2.sfd @@ -0,0 +1,80 @@ +SplineFontDB: 3.2 +FontName: WineLangNamesRegular +FullName: Wine_Lang_Names_Regular +FamilyName: Wine_Lang_Names +Weight: Regular +Copyright: Copyright (c) 2020, Remi Bernon for CodeWeavers +UComments: "2017-11-17: Created with FontForge (http://fontforge.org)" +Version: 001.000 +ItalicAngle: 0 +UnderlinePosition: -102 +UnderlineWidth: 51 +Ascent: 819 +Descent: 205 +InvalidEm: 0 +LayerCount: 2 +Layer: 0 0 "Back" 1 +Layer: 1 0 "Fore" 0 +XUID: [1021 48 28337276 3092883] +OS2Version: 0 +OS2_WeightWidthSlopeOnly: 0 +OS2_UseTypoMetrics: 1 +CreationTime: 1510948643 +ModificationTime: 1599738445 +OS2TypoAscent: 0 +OS2TypoAOffset: 1 +OS2TypoDescent: 0 +OS2TypoDOffset: 1 +OS2TypoLinegap: 0 +OS2WinAscent: 0 +OS2WinAOffset: 1 +OS2WinDescent: 0 +OS2WinDOffset: 1 +HheadAscent: 0 +HheadAOffset: 1 +HheadDescent: 0 +HheadDOffset: 1 +OS2Vendor: 'PfEd' +MarkAttachClasses: 1 +DEI: 91125 +LangName: 1028 \ + "" \ + "Wine Lang Cond (zh-tw)" \ + "Reg (zh-tw)" \ + "" \ + "Wine Lang Cond Reg (zh-tw)" +LangName: 1041 \ + "" \ + "+MNUwqTDzMMhUDQAA Cond (ja)" \ + "Reg (ja)" +LangName: 1033 \ + "" \ + "Wine Lang Cond (en)" \ + "Reg (en)" +Encoding: ISO8859-1 +UnicodeInterp: none +NameList: AGL For New Fonts +DisplaySize: -48 +AntiAlias: 1 +FitToEm: 0 +WinInfo: 64 16 4 +BeginPrivate: 0 +EndPrivate +BeginChars: 256 1 + +StartChar: at +Encoding: 64 64 0 +Width: 1024 +VWidth: 0 +Flags: HW +LayerCount: 2 +Fore +SplineSet +259 332 m 29 + 468 664 l 29 + 514 332 l 29 + 259 332 l 29 +EndSplineSet +EndChar +EndChars +EndSplineFont diff --git a/dlls/gdi32/tests/wine_langnames2.ttf b/dlls/gdi32/tests/wine_langnames2.ttf new file mode 100644 index 0000000000000000000000000000000000000000..47082dbd67e117529574d83755fd19e969cd205f GIT binary patch literal 2016 zcmdT_O>A355dL=k>@-kl0)-xk(2^ENP~yDURYfZ!SqU{ggcgM;xl}lh<oTz>&(@2Z zHe9I0g+nEJ1c?I@7bqv29^h1oAE{EqfkP30$`y$cI3RL@m~Yn4b}SW%EBiFNGqW?Z z-^`BoK>>IWR}jN;F1PUF)sGu4Fz_X{BQHFEI)_JanDU1rpL=;KwHWs<0jflKd8Ojj za42z?@^_?}m5sW=sD2BGjd0&7dh4}Ti;*$#KIH?&wavm;jV9yACMefRzPI|&?(Pxt zzmiUrsE7|bamG4E`B<q^zkCqtNy@h<53N;KJiLkp`WwpkRlLhJoWV)%pP_65ui{@A zyqe|yd!#$H>UzDkjT1b-&i!W~xstYT&NlLgGJoQJhYH}^<G+6(>yK}I{xwDct@U+^ z2cSjEK_9C*-?rD<Mr!Z1XUA%su8(*stIHy3O&pqB19Q{w>Md&CZm;St(rS=e#5qSp zaCXN_h109Jf-JJJbSsVX7Kz2wH8D^`M&vBICB>Rc-7SqoXfu=~@(7I#SBIa-S>BPI zTVF($P>J3FN^%j}Kl%{v-{|pj{QrE|US{9O_bhYKQe&0k4a6{jWJ6&p(;RTHlWHX5 zKV_ORO%{!qsN<q;4kXlHnI=oPlS&UiG5mCT_~@t_`fY1VU;le?R2LXd#nc=-?j5PI zdW_;XNj0bD_HIb=9>y=7JHZr|BVJMeX~b*x+;+sr*h}Xk-oX*|NyNu7q;?`cfx~)C zIzbu|6Z*M`*LYOF7V!>_>o+YgJ^2br><4N86s|?Q#t^n5K86B*j(7)2)$xtPsN0b~ zfibmb`C-O+Tz?kvjHAEDEUKts6CuhdqJ%m-bPOvP=bD0RX@dMbd{k&-FhedxK)--e zfosTB;;eFKiR59!+N=Y!)!JrQE|%(MY-QY}+>|?E=KV_9%=lqY4NRdLn%U~AzvO!x zen^KUo)OU7V2*JDVrs_@7+sM0)Q!`u9QbC=3ySm(R?V0nP$?M2zH2q_7o)A5g<FTL zA&umK6dwqe>nT#_*nIccJkAn8g_i5cN1-objXFtJe5UC=$wzRqTPWnJK|NOui@r%E zU31C^%)G$NpXC#|o+qG-YhK8mX?ODEq|~FA@_#$qrhbo@z#_4RL|eAG8lrQFQF4^e z(0~;#v*@lnopfE7noioCTK7_J*RqqaJyi0rX+&A{-2d&eUS~s1vZXG`mF>HpetieT zy`%Ilwa?4F<9_7+;oe$!fSF12bsFRXZ>ayYj)oAT*R*v5X-bOJKjaZtv^r|litlsp ak8_a!W7(G&;@S4L^AEdwH^pQB|Lh+tiXH<1
literal 0 HcmV?d00001
diff --git a/dlls/gdi32/tests/wine_langnames3.sfd b/dlls/gdi32/tests/wine_langnames3.sfd new file mode 100644 index 00000000000..ea0dbff57d9 --- /dev/null +++ b/dlls/gdi32/tests/wine_langnames3.sfd @@ -0,0 +1,78 @@ +SplineFontDB: 3.2 +FontName: WineLangNamesRegular +FullName: Wine_Lang_Names_Regular +FamilyName: Wine_Lang_Names +Weight: Regular +Copyright: Copyright (c) 2020, Remi Bernon for CodeWeavers +UComments: "2017-11-17: Created with FontForge (http://fontforge.org)" +Version: 001.000 +ItalicAngle: 0 +UnderlinePosition: -102 +UnderlineWidth: 51 +Ascent: 819 +Descent: 205 +InvalidEm: 0 +LayerCount: 2 +Layer: 0 0 "Back" 1 +Layer: 1 0 "Fore" 0 +XUID: [1021 48 28337276 3092883] +OS2Version: 0 +OS2_WeightWidthSlopeOnly: 0 +OS2_UseTypoMetrics: 1 +CreationTime: 1510948643 +ModificationTime: 1599738445 +OS2TypoAscent: 0 +OS2TypoAOffset: 1 +OS2TypoDescent: 0 +OS2TypoDOffset: 1 +OS2TypoLinegap: 0 +OS2WinAscent: 0 +OS2WinAOffset: 1 +OS2WinDescent: 0 +OS2WinDOffset: 1 +HheadAscent: 0 +HheadAOffset: 1 +HheadDescent: 0 +HheadDOffset: 1 +OS2Vendor: 'PfEd' +MarkAttachClasses: 1 +DEI: 91125 +LangName: 1036 \ + "" \ + "Wine Lang Cond (fr)" \ + "Reg (fr)" \ + "" \ + "Wine Lang Cond Reg (fr)" +LangName: 1042 \ + "" \ + "Wine Lang Cond (ko)" \ + "Reg (ko)" \ + "" \ + "Wine Lang Cond Reg (ko)" +Encoding: ISO8859-1 +UnicodeInterp: none +NameList: AGL For New Fonts +DisplaySize: -48 +AntiAlias: 1 +FitToEm: 0 +WinInfo: 64 16 4 +BeginPrivate: 0 +EndPrivate +BeginChars: 256 1 + +StartChar: at +Encoding: 64 64 0 +Width: 1024 +VWidth: 0 +Flags: HW +LayerCount: 2 +Fore +SplineSet +259 332 m 29 + 468 664 l 29 + 514 332 l 29 + 259 332 l 29 +EndSplineSet +EndChar +EndChars +EndSplineFont diff --git a/dlls/gdi32/tests/wine_langnames3.ttf b/dlls/gdi32/tests/wine_langnames3.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dd76bd478bbb2546cfbbb7e9184cc7f602c59303 GIT binary patch literal 2048 zcmdT_O>7%Q6#iy*ZMRU79|cv22rX%W1SQU9jVfCCU?tS_U<xWxaw#}lXZ<7MwY70W zbD~EMNc6y=NZjC54q&U|ghT~GLMTX-1FBlo6Sq=&BI*HRzL_06i4Sc#GS=Jq-kbM7 zFB1p=Pv9aftmN~HuYK@&+XYg;Q#$_YD<|`K5@Y0lQ2gs}&U#A;|6M>-$*+{^eiK8< zJLGSW=1Utb2NUvrz#8YdUGdkO-7Y;Nb&dRi%Gzf6`*w%^t!eVjYT&PqZf_qZ{)2R^ zN<reFouIFy<d0VCtqX@Bo+Gc~53e;!KF(p0_73^S>i&f$PT@GuPmy;*zaD&H?a-I? z3F&^bvEJ(5#xchKi03at)k<3Y@vX0lL)pLZxJ?1@>r3}ORr{^?zWoUkfRyqI*#nSD z%0(M3IUDOssXfJK@z>T8yKkc`g_h-z)+#ntE`hblkL4C6AI7`5gN!&xDH8merSj~r zH_9hhaS=J>tV}n9vpN%<Q(wh_U}nsmP1hvYbJcfE<0jiIIpukrN)C6MKgH*GNBZ0S z&S*j;cLNAji=w@2Uxs@RcCiZoKVN#5IXCL}GHa2l$HL<cSV$q=7MRU;Qa0{-?PTJ& zY{!y>Xj@90P~uK1DgMrO*uuMBX5`tC7cwJ9CdBZcTU+wVKT8v`On1T(1y0;$)noBA z+3RUh5QUwqs(EAB?%fGyv0|{m5WX~6GLxSTwm3^UgKZoZpBbFMu()k-5@YfyH3_zw zx3@_#7I+4i43>Nmt{H5hj2i~qNQ;)i2{__wgOivP_cZ38E1s8WgC&OLlEJi<RgFir z&Sis@P8@5L^O%;uU;zy@v55#ZR8U2W(>jR~rnq}>HBA$rL4Z1S9Ly6%2x%9RD|3&y zD?h6|Stj||&^qhDLZi7E)hgANGg+E)JlAuloijnb=FA6C*a)3+BXSlRtHE;MZv+ty zmKh_YbrA*n37Jz7r-|y6spDE06bpV>DW2y0LxIYxg7a9TPDD1SoL}<^@;bkk-Xm%R z%+cfP;Br4fdT^ZLfZy0=j@C1L0cZN1LB0{T@{OnxI9}RyPB;Vk6-_=onR923&!`4G ztj59EgEjYj0!yqaVpnSBE?nj}r)yNmp#oc4W0zfbF73K5CB3qH&E0M7KqFNls?WO3 z{jT=Ro&N2_Hy`ru)!dYs&lIOTcD7gYV9WoiKZ$o(^ZrOZ$)iT<>6_QKdleaGE=c>A ndgKM)iz8Yr_<ryHM>@neL!B!h$}+ar-<#Vz-zbZ{|L^_<2BRY9
literal 0 HcmV?d00001