[PATCH 2/2] gdi32/tests: Test extended TTF font names and collisions.

Rémi Bernon rbernon at codeweavers.com
Mon Aug 31 08:26:27 CDT 2020


This shows that although Windows is only matching family names up to
LF_FACESIZE chars, and that it doesn't match against the preferred /
typographic family names and styles, it still keeps the faces separate
when the full names don't match. Wine incorrectly discard one of them.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

Just stumbled upon this while playing with fonts and fontconfig. Noto
fonts have a lot of collisions because of this, as they have all sorts
of density / weight / slant variations.

I don't have a fix yet, I'm not sure how to do it yet and I'd also like
to take the opportunity to clean the corresponding gdi32 code a bit.

I thought it could be nice to use the typographic / preferred family and
style names to enumerate and match them, as fontconfig does, but that's
not what Windows is doing, sadly.

It could be a host integration and user experience improvement though,
but it will require patching the font data before returning it, to pass
the other tests.

 dlls/gdi32/tests/font.c                 |  70 +++++++++++++++++++
 dlls/gdi32/tests/resource.rc            |   6 ++
 dlls/gdi32/tests/wine_ttfnames.sfd      |  85 ++++++++++++++++++++++++
 dlls/gdi32/tests/wine_ttfnames.ttf      | Bin 0 -> 2232 bytes
 dlls/gdi32/tests/wine_ttfnames_bold.sfd |  85 ++++++++++++++++++++++++
 dlls/gdi32/tests/wine_ttfnames_bold.ttf | Bin 0 -> 2272 bytes
 6 files changed, 246 insertions(+)
 create mode 100644 dlls/gdi32/tests/wine_ttfnames.sfd
 create mode 100644 dlls/gdi32/tests/wine_ttfnames.ttf
 create mode 100644 dlls/gdi32/tests/wine_ttfnames_bold.sfd
 create mode 100644 dlls/gdi32/tests/wine_ttfnames_bold.ttf

diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index ad894dfdcad..a452b362228 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -6940,6 +6940,75 @@ static void test_long_names(void)
     ReleaseDC(NULL, dc);
 }
 
+static void test_ttf_names(void)
+{
+    struct enum_fullname_data efnd;
+    char ttf_name[MAX_PATH], ttf_name_bold[MAX_PATH];
+    LOGFONTA font = {0};
+    HFONT handle_font;
+    int ret;
+    HDC dc;
+
+    if (!write_ttf_file("wine_ttfnames.ttf", ttf_name))
+    {
+        skip("Failed to create ttf file for testing\n");
+        return;
+    }
+
+    if (!write_ttf_file("wine_ttfnames_bold.ttf", ttf_name_bold))
+    {
+        skip("Failed to create ttf file for testing\n");
+        DeleteFileA(ttf_name);
+        return;
+    }
+
+    ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
+    ok(ret, "AddFontResourceEx() failed\n");
+
+    ret = AddFontResourceExA(ttf_name_bold, FR_PRIVATE, 0);
+    ok(ret, "AddFontResourceEx() failed\n");
+
+    dc = GetDC(NULL);
+
+    strcpy(font.lfFaceName, "Wine_TTF_Names_Long_Family1_Con");
+    memset(&efnd, 0, sizeof(efnd));
+    EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+    ok(efnd.total == 0, "EnumFontFamiliesExA must not find font.\n");
+
+    /* Windows doesn't match with Typographic/Preferred Family tags */
+    strcpy(font.lfFaceName, "Wine TTF Names Long Family1");
+    memset(&efnd, 0, sizeof(efnd));
+    EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+    ok(efnd.total == 0, "EnumFontFamiliesExA must not find font.\n");
+
+    strcpy(font.lfFaceName, "Wine TTF Names Long Family1 Ext");
+    memset(&efnd, 0, sizeof(efnd));
+    EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+    todo_wine
+    ok(efnd.total == 2, "EnumFontFamiliesExA found %d fonts, expected 2.\n", efnd.total);
+
+    strcpy(font.lfFaceName, "Wine TTF Names Long Family1 Con");
+    memset(&efnd, 0, sizeof(efnd));
+    EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+    todo_wine
+    ok(efnd.total == 2, "EnumFontFamiliesExA found %d fonts, expected 2.\n", efnd.total);
+
+    handle_font = CreateFontIndirectA(&font);
+    ok(handle_font != NULL, "CreateFontIndirectA failed\n");
+    DeleteObject(handle_font);
+
+    ret = RemoveFontResourceExA(ttf_name_bold, FR_PRIVATE, 0);
+    ok(ret, "RemoveFontResourceEx() failed\n");
+
+    DeleteFileA(ttf_name_bold);
+
+    ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
+    ok(ret, "RemoveFontResourceEx() failed\n");
+
+    DeleteFileA(ttf_name);
+    ReleaseDC(NULL, dc);
+}
+
 typedef struct
 {
     USHORT majorVersion;
@@ -7351,6 +7420,7 @@ START_TEST(font)
     test_bitmap_font_glyph_index();
     test_GetCharWidthI();
     test_long_names();
+    test_ttf_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 6dcbd42ab52..b5a6107a987 100644
--- a/dlls/gdi32/tests/resource.rc
+++ b/dlls/gdi32/tests/resource.rc
@@ -31,3 +31,9 @@ vertical.ttf RCDATA vertical.ttf
 
 /* @makedep: wine_longname.ttf */
 wine_longname.ttf RCDATA wine_longname.ttf
+
+/* @makedep: wine_ttfnames.ttf */
+wine_ttfnames.ttf RCDATA wine_ttfnames.ttf
+
+/* @makedep: wine_ttfnames_bold.ttf */
+wine_ttfnames_bold.ttf RCDATA wine_ttfnames_bold.ttf
diff --git a/dlls/gdi32/tests/wine_ttfnames.sfd b/dlls/gdi32/tests/wine_ttfnames.sfd
new file mode 100644
index 00000000000..566749d19a7
--- /dev/null
+++ b/dlls/gdi32/tests/wine_ttfnames.sfd
@@ -0,0 +1,85 @@
+SplineFontDB: 3.2
+FontName: Wine_TTF_Names_Long_Family1_Cond_Regular
+FamilyName: Wine_TTF_Names_Long_Family1_Cond
+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: 1598865292
+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 TTF Names Long Family1 Cond" \
+    "Regular" \
+    "" \
+    "Wine TTF Names Long Family1 Extremely Long Full Name Condensed" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "Wine TTF Names Long Family1" \
+    "Condensed Regular" \
+
+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_ttfnames.ttf b/dlls/gdi32/tests/wine_ttfnames.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..2eb2ad1f95e7bb384abe41bcf68f64da320fefb9
GIT binary patch
literal 2232
zcmdT`O>7%Q6#iy+?W8oKb_J*AFt|aaC_ft;MWu?6mDHvOQ>qXpJyhK+$@)jKcdfM(
zVhN-kdqAQW1eFk%-YVsgs22{1142S57eGR&px#j_Js>zi%{SwT?exH(xG>i2eDBSB
zZ{FX|8UnzRxCR^R#p22<Z-00-0!BX|cl_n^g(9BDQ>3pc`qkHFv#SaJ4M0>$uWvN`
zCQc;plm3=-abvqJk+H4=_Bi*Qir;E>yR?ka9nzzfdZ+x^-oDHIDbmeq;BTJ%;nphg
zkDT*WG7`s}1Z_=_o~Sn3J7W;flKz}@svd3lcpWR$m!zL)_&ZHpz>D0!Kw5@=BY3zw
z(d9n<cXpdmtKGeac^+Nj{_{|=a(=ygx$B)+_yxxuGJtPhcz8>#-^I-_WB|*uZj&5^
zrMMi_(VQzidCSt4dV9U6qd87rM`;Sp%VS21I25 at 7#%A5L4#;_ at w~G77iDTp<!KWF@
z&;GbnE^M+sdF1U}H-{_Q6YW!9L_*Lrdd{fz6wJBGyPo65+XYg}@;HSgSBF1E=UF5D
z?0#w_A(Ddwgo;JY;c>*n;f(=S$N$fV?q&9k`kiGgmddfnvH~_nFtaBxyRbjv;6ZjT
znfQKT-?j*`XDfC>vG+%k;<tr;rtm>FmwqPwTrPb&BT_#d99Xx1U(Hx$niIAtvE$xX
zIToi#emNsbqV(vFO5RD_JFE$2v2L(n{k}5T!U(I~tA~yA;$4FsykuQAIDwS)k-<q!
z^6l)&r*O)C%iuK9_Q$G29My+cIeS<jj~fPCyeWP**v55n++YW9in|6UAg%WdPU4dF
zg~2Jz+XaKu$k;crga}P^5Tk|)s%SH+No?Q@*DPE;r-+vkpg|dlMWPrX^+Hl*t}$0-
zXOlZ?oIbX-Obb|wnw_{-skY_h#u=G)v+k5!4jMJN7{p-|%5oITrD!u)3;gXMrotM}
z2&pZ3!>pjl^&;&x$Y~Lm^r;o1qUP36r|)y5)%hVkz*;Q~<jP7>UgSm8lBFoD$fDn<
z)jM-MDWrr7rGhQ0`g9%3L1nA%6BM<Hwq9dOC?~SKI9#shI1gR(jBDPIYhK?q?=jcB
zzH8oNC-<!8=>9Ytd%B-)6r-?RjN(clvoo$dCsjxuL-KS;o(jn`A$ck!&xAnH+}!lp
zX_e-GpUDDt*ab1eS6Ns2J(_owxH@@<bs6M7U<F##`HLzPcG_{!2<jbEoUM9Y7fY8X
z2wMU5S7|1uv6`-lWDQ*AN!3FABn8+lH8zmz&ds>4OU{2?9^FZQC+&ly|5?-iS*!BR
zF%3OPYVRc+>ReTOoiDypriXcBn6E_l4sxUf=h5Mi6qGux*@EAl!IyN5|1;FSvY|A4
Q+WL9-*GHcyjp6U~A6<%D%m4rY

literal 0
HcmV?d00001

diff --git a/dlls/gdi32/tests/wine_ttfnames_bold.sfd b/dlls/gdi32/tests/wine_ttfnames_bold.sfd
new file mode 100644
index 00000000000..b3bf4ddfe90
--- /dev/null
+++ b/dlls/gdi32/tests/wine_ttfnames_bold.sfd
@@ -0,0 +1,85 @@
+SplineFontDB: 3.2
+FontName: Wine_TTF_Names_Long_Family1_Cond_Regular
+FamilyName: Wine_TTF_Names_Long_Family1_Cond
+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: 1598865292
+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 TTF Names Long Family1 CondBold" \
+    "Regular" \
+    "" \
+    "Wine TTF Names Long Family1 Extremely Long Full Name Condensed Bold" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "" \
+    "Wine TTF Names Long Family1" \
+    "Condensed Bold Regular" \
+
+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_ttfnames_bold.ttf b/dlls/gdi32/tests/wine_ttfnames_bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..919a5ea1310dd95904d882afb56b95aaf94dc9be
GIT binary patch
literal 2272
zcmdT`O>7%Q6#iy+?W7Qqq~hn$9ELQA6eZ5aMxj(bL`h?M2yGRj<WhCB#2eevde>Sz
zA-)v}p&pRvjUpj_)C<ZjR_+`Ci9;?(2v9*iAc0i1g%g~h=9}@vPAY^7;=)+7?|X0F
zn|Xh`V+a6`;R<Z56$;BQzxDp*80i0u(vg?WE)?(t9w+~?;xD{1m0d~suK}V=er>(#
z*D#pAL;hRNx%I7v#He)@ut&J=l>B<F-R92d|B!rtDQs?hzT0xSK0&@#4*cTr+c#E-
z?{dzRDM%f2Qrv5d{8+i#*dBm*hWr=ghr)Q>$E#STy(Irg)!(k+9A4!5Ir1{{tHC>&
z*AuS4$K$`L#q~z}7G`*KgX_;h#mf1{&IcE~!Thgy)S&?Q`uSgODEeJe8^9=FS=J8O
zeppJ%K^rZ()X}#ry;Enc^K`Vt>Dnkup=GnkXcdPl*TC4UcddO&-tJIw2RU(!Ql$7a
zL;2Yq7dIA)xPn>C+PQWPm$WC^r>=^Gpl9@)QR^v~bCq{JM~t_5a%$%hDoIj at KgG|o
zM*7+Q)M!Gadj|*=i<*bW5f2Y9^sqYqe?D|Cvv1VzG-I(;jzyLgu+fLiuE12j)#u<|
zb~l~+KHst}LhRZ~oKoUeUt0X0Z!v}Uvbo`>ho8+2pBxoKKkx5bJAbT<S{vL>*kX|#
zcU|RJoFMyUMl6cO`+F*R$8qbRCYZvS!2)BrX|RPpF=()jv*IIz9n4#i!6^(`Um2Xn
zxc!2`LpWhyH+UFN+CQicaa12(=Img>H|(0h7QYngeO5X)u8OA&cJQY7$>0>E)iOAZ
zi`I_ at 4`Ie$Gk6#i_8#UDqlP9DR8T at 04R+-?)^Un73s=tx;w1#AQb%HrC_zNKh};Hg
zLaO#Da%Gj%$ClQq1M_jMnN&*Uh8$l%C9`hUosdgGwIb(&B#I-s5hrp!E(WWCzZE1j
zSmhZJttG!O%P5eZ=YCa6>cors)DlraODhQJ`!soVenb!ENJCPrR-!;IFBjx_evs;N
zF^)>I;8!bQbDAec#kn}7mI|wcO`7-&14}_^GxP}xdb at _E2{n{MS$;%Z(leX~ZhFQ|
z?~t2b*G=yMH@&W#-UBChcFi%ANjCXpH}xpQQKJwir9fsgt~?`ESRTXjbXcAW%QInl
zDlE^0K-Jvz<mpM3 at _(Pz1#Gh;5{9oTpmKe*1}bqOWd}9t)gfRt>a;0x^`UCAu-!<4
zY7jO}sW!t<mrfTei0VO6c1pIwT@&tI(It{BiOaO9(x{&VR at g`t_Ll2TXI$5%<iD<#
zZmx%^LhtB**3W;}y?m)mum4q!J8$ZtmR3#COCMi8)8PlVNqY}DerE*d(V;FeL9LTo
gEO<ZlZrlO>A5rV-MpBj?YyG_W+x<_J#o_z>Pvq`pzyJUM

literal 0
HcmV?d00001

-- 
2.28.0




More information about the wine-devel mailing list