From 93c71b6db78724d987c088697c9da12da66a2e61 Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Tue, 19 Nov 2024 20:40:23 +0900 Subject: [PATCH 1/2] gdi32/tests: Add tests for script-independent vertical glyph lookup. vertical2.sfd is based on vertical.sfd. However, it has a different GSUB table for testing. --- dlls/gdi32/tests/font.c | 25 + dlls/gdi32/tests/resource.rc | 3 + dlls/gdi32/tests/vertical2.sfd | 1059 ++++++++++++++++++++++++++++++++ dlls/gdi32/tests/vertical2.ttf | Bin 0 -> 3700 bytes 4 files changed, 1087 insertions(+) create mode 100644 dlls/gdi32/tests/vertical2.sfd create mode 100644 dlls/gdi32/tests/vertical2.ttf diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 06d3b042deb..8c5f26547e7 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -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 */ + todo_wine 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, diff --git a/dlls/gdi32/tests/resource.rc b/dlls/gdi32/tests/resource.rc index 477d07de45d..2f1273d1e42 100644 --- a/dlls/gdi32/tests/resource.rc +++ b/dlls/gdi32/tests/resource.rc @@ -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 diff --git a/dlls/gdi32/tests/vertical2.sfd b/dlls/gdi32/tests/vertical2.sfd new file mode 100644 index 00000000000..2b8db8deb95 --- /dev/null +++ b/dlls/gdi32/tests/vertical2.sfd @@ -0,0 +1,1059 @@ +SplineFontDB: 3.0 +FontName: WineTestVertical2 +FullName: WineTestVertical2 +FamilyName: WineTestVertical2 +Weight: Regular +Copyright: Copyright(c) 2013 Wine Project +Version: 1.055 +ItalicAngle: 0 +UnderlinePosition: -100 +UnderlineWidth: 50 +Ascent: 860 +Descent: 140 +sfntRevision: 0x00010e14 +LayerCount: 2 +Layer: 0 1 "Back" 1 +Layer: 1 1 "Fore" 0 +HasVMetrics: 1 +XUID: [1021 564 53499222 16482262] +FSType: 0 +OS2Version: 1 +OS2_WeightWidthSlopeOnly: 0 +OS2_UseTypoMetrics: 1 +PfmFamily: 17 +TTFWeight: 400 +TTFWidth: 5 +LineGap: 90 +VLineGap: 0 +Panose: 2 11 5 9 2 2 3 2 2 7 +OS2TypoAscent: 860 +OS2TypoAOffset: 0 +OS2TypoDescent: -140 +OS2TypoDOffset: 0 +OS2TypoLinegap: 90 +OS2WinAscent: 1075 +OS2WinAOffset: 0 +OS2WinDescent: 320 +OS2WinDOffset: 0 +HheadAscent: 1075 +HheadAOffset: 0 +HheadDescent: -320 +HheadDOffset: 0 +OS2SubXSize: 650 +OS2SubYSize: 700 +OS2SubXOff: 0 +OS2SubYOff: 140 +OS2SupXSize: 650 +OS2SupYSize: 700 +OS2SupXOff: 0 +OS2SupYOff: 480 +OS2StrikeYSize: 49 +OS2StrikeYPos: 258 +OS2FamilyClass: 2057 +OS2Vendor: 'M+ ' +OS2CodePages: 4012019f.dfd70000 +OS2UnicodeRanges: e00002ff.4a47fdeb.00000012.00000000 +Lookup: 1 0 0 "fake-gsubvert" {"fake-vert" } ['vert' ('????' <'dflt' > ) ] +Lookup: 1 0 0 "gsubvert" {"j-vert" } ['vert' ('cyrl' <'dflt' > 'grek' <'dflt' > 'hani' <'dflt' > 'kana' <'JAN ' 'dflt' > 'latn' <'dflt' > ) ] +MarkAttachClasses: 1 +DEI: 91125 +TtTable: prep +PUSHW_1 + 511 +SCANCTRL +PUSHB_1 + 1 +SCANTYPE +SVTCA[y-axis] +MPPEM +PUSHB_1 + 8 +LT +IF +PUSHB_2 + 1 + 1 +INSTCTRL +EIF +PUSHB_2 + 70 + 6 +CALL +IF +POP +PUSHB_1 + 16 +EIF +MPPEM +PUSHB_1 + 20 +GT +IF +POP +PUSHB_1 + 128 +EIF +SCVTCI +PUSHB_1 + 6 +CALL +NOT +IF +EIF +PUSHB_1 + 20 +CALL +EndTTInstrs +TtTable: fpgm +PUSHB_1 + 0 +FDEF +PUSHB_1 + 0 +SZP0 +MPPEM +PUSHB_1 + 42 +LT +IF +PUSHB_1 + 74 +SROUND +EIF +PUSHB_1 + 0 +SWAP +MIAP[rnd] +RTG +PUSHB_1 + 6 +CALL +IF +RTDG +EIF +MPPEM +PUSHB_1 + 42 +LT +IF +RDTG +EIF +DUP +MDRP[rp0,rnd,grey] +PUSHB_1 + 1 +SZP0 +MDAP[no-rnd] +RTG +ENDF +PUSHB_1 + 1 +FDEF +DUP +MDRP[rp0,min,white] +PUSHB_1 + 12 +CALL +ENDF +PUSHB_1 + 2 +FDEF +MPPEM +GT +IF +RCVT +SWAP +EIF +POP +ENDF +PUSHB_1 + 3 +FDEF +ROUND[Black] +RTG +DUP +PUSHB_1 + 64 +LT +IF +POP +PUSHB_1 + 64 +EIF +ENDF +PUSHB_1 + 4 +FDEF +PUSHB_1 + 6 +CALL +IF +POP +SWAP +POP +ROFF +IF +MDRP[rp0,min,rnd,black] +ELSE +MDRP[min,rnd,black] +EIF +ELSE +MPPEM +GT +IF +IF +MIRP[rp0,min,rnd,black] +ELSE +MIRP[min,rnd,black] +EIF +ELSE +SWAP +POP +PUSHB_1 + 5 +CALL +IF +PUSHB_1 + 70 +SROUND +EIF +IF +MDRP[rp0,min,rnd,black] +ELSE +MDRP[min,rnd,black] +EIF +EIF +EIF +RTG +ENDF +PUSHB_1 + 5 +FDEF +GFV +NOT +AND +ENDF +PUSHB_1 + 6 +FDEF +PUSHB_2 + 34 + 1 +GETINFO +LT +IF +PUSHB_1 + 32 +GETINFO +NOT +NOT +ELSE +PUSHB_1 + 0 +EIF +ENDF +PUSHB_1 + 7 +FDEF +PUSHB_2 + 36 + 1 +GETINFO +LT +IF +PUSHB_1 + 64 +GETINFO +NOT +NOT +ELSE +PUSHB_1 + 0 +EIF +ENDF +PUSHB_1 + 8 +FDEF +SRP2 +SRP1 +DUP +IP +MDAP[rnd] +ENDF +PUSHB_1 + 9 +FDEF +DUP +RDTG +PUSHB_1 + 6 +CALL +IF +MDRP[rnd,grey] +ELSE +MDRP[min,rnd,black] +EIF +DUP +PUSHB_1 + 3 +CINDEX +MD[grid] +SWAP +DUP +PUSHB_1 + 4 +MINDEX +MD[orig] +PUSHB_1 + 0 +LT +IF +ROLL +NEG +ROLL +SUB +DUP +PUSHB_1 + 0 +LT +IF +SHPIX +ELSE +POP +POP +EIF +ELSE +ROLL +ROLL +SUB +DUP +PUSHB_1 + 0 +GT +IF +SHPIX +ELSE +POP +POP +EIF +EIF +RTG +ENDF +PUSHB_1 + 10 +FDEF +PUSHB_1 + 6 +CALL +IF +POP +SRP0 +ELSE +SRP0 +POP +EIF +ENDF +PUSHB_1 + 11 +FDEF +DUP +MDRP[rp0,white] +PUSHB_1 + 12 +CALL +ENDF +PUSHB_1 + 12 +FDEF +DUP +MDAP[rnd] +PUSHB_1 + 7 +CALL +NOT +IF +DUP +DUP +GC[orig] +SWAP +GC[cur] +SUB +ROUND[White] +DUP +IF +DUP +ABS +DIV +SHPIX +ELSE +POP +POP +EIF +ELSE +POP +EIF +ENDF +PUSHB_1 + 13 +FDEF +SRP2 +SRP1 +DUP +DUP +IP +MDAP[rnd] +DUP +ROLL +DUP +GC[orig] +ROLL +GC[cur] +SUB +SWAP +ROLL +DUP +ROLL +SWAP +MD[orig] +PUSHB_1 + 0 +LT +IF +SWAP +PUSHB_1 + 0 +GT +IF +PUSHB_1 + 64 +SHPIX +ELSE +POP +EIF +ELSE +SWAP +PUSHB_1 + 0 +LT +IF +PUSHB_1 + 64 +NEG +SHPIX +ELSE +POP +EIF +EIF +ENDF +PUSHB_1 + 14 +FDEF +PUSHB_1 + 6 +CALL +IF +RTDG +MDRP[rp0,rnd,white] +RTG +POP +POP +ELSE +DUP +MDRP[rp0,rnd,white] +ROLL +MPPEM +GT +IF +DUP +ROLL +SWAP +MD[grid] +DUP +PUSHB_1 + 0 +NEQ +IF +SHPIX +ELSE +POP +POP +EIF +ELSE +POP +POP +EIF +EIF +ENDF +PUSHB_1 + 15 +FDEF +SWAP +DUP +MDRP[rp0,rnd,white] +DUP +MDAP[rnd] +PUSHB_1 + 7 +CALL +NOT +IF +SWAP +DUP +IF +MPPEM +GTEQ +ELSE +POP +PUSHB_1 + 1 +EIF +IF +ROLL +PUSHB_1 + 4 +MINDEX +MD[grid] +SWAP +ROLL +SWAP +DUP +ROLL +MD[grid] +ROLL +SWAP +SUB +SHPIX +ELSE +POP +POP +POP +POP +EIF +ELSE +POP +POP +POP +POP +POP +EIF +ENDF +PUSHB_1 + 16 +FDEF +DUP +MDRP[rp0,min,white] +PUSHB_1 + 18 +CALL +ENDF +PUSHB_1 + 17 +FDEF +DUP +MDRP[rp0,white] +PUSHB_1 + 18 +CALL +ENDF +PUSHB_1 + 18 +FDEF +DUP +MDAP[rnd] +PUSHB_1 + 7 +CALL +NOT +IF +DUP +DUP +GC[orig] +SWAP +GC[cur] +SUB +ROUND[White] +ROLL +DUP +GC[orig] +SWAP +GC[cur] +SWAP +SUB +ROUND[White] +ADD +DUP +IF +DUP +ABS +DIV +SHPIX +ELSE +POP +POP +EIF +ELSE +POP +POP +EIF +ENDF +PUSHB_1 + 19 +FDEF +DUP +ROLL +DUP +ROLL +SDPVTL[orthog] +DUP +PUSHB_1 + 3 +CINDEX +MD[orig] +ABS +SWAP +ROLL +SPVTL[orthog] +PUSHB_1 + 32 +LT +IF +ALIGNRP +ELSE +MDRP[grey] +EIF +ENDF +PUSHB_1 + 20 +FDEF +PUSHB_4 + 0 + 64 + 1 + 64 +WS +WS +SVTCA[x-axis] +MPPEM +PUSHW_1 + 4096 +MUL +SVTCA[y-axis] +MPPEM +PUSHW_1 + 4096 +MUL +DUP +ROLL +DUP +ROLL +NEQ +IF +DUP +ROLL +DUP +ROLL +GT +IF +SWAP +DIV +DUP +PUSHB_1 + 0 +SWAP +WS +ELSE +DIV +DUP +PUSHB_1 + 1 +SWAP +WS +EIF +DUP +PUSHB_1 + 64 +GT +IF +PUSHB_3 + 0 + 32 + 0 +RS +MUL +WS +PUSHB_3 + 1 + 32 + 1 +RS +MUL +WS +PUSHB_1 + 32 +MUL +PUSHB_1 + 25 +NEG +JMPR +POP +EIF +ELSE +POP +POP +EIF +ENDF +PUSHB_1 + 21 +FDEF +PUSHB_1 + 1 +RS +MUL +SWAP +PUSHB_1 + 0 +RS +MUL +SWAP +ENDF +EndTTInstrs +ShortTable: cvt 6 + -220 + 0 + 520 + 730 + 33 + 633 +EndShort +ShortTable: maxp 16 + 1 + 0 + 7223 + 192 + 22 + 102 + 11 + 2 + 1 + 2 + 22 + 0 + 256 + 46 + 1 + 1 +EndShort +LangName: 1033 "" "" "" "FontForge 2.0 : WineTestVertical2: 11-3-2013" "" "Version 1.055" "" "" "" "" "" "http://www.winehq.com" "" "" "" "" "WineTestVertical2" "regular" +GaspTable: 1 65535 2 0 +Encoding: UnicodeFull +Compacted: 1 +UnicodeInterp: none +NameList: Adobe Glyph List +DisplaySize: -36 +AntiAlias: 1 +FitToEm: 1 +WinInfo: 0 23 9 +BeginPrivate: 0 +EndPrivate +TeXData: 1 0 0 346030 173015 115343 0 1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144 +BeginChars: 1114326 15 + +StartChar: .notdef +Encoding: 1114112 -1 0 +Width: 364 +Flags: W +TtInstrs: +PUSHB_2 + 1 + 0 +MDAP[rnd] +ALIGNRP +PUSHB_3 + 7 + 4 + 4 +MIRP[min,rnd,black] +SHP[rp2] +PUSHB_2 + 6 + 5 +MDRP[rp0,min,rnd,grey] +ALIGNRP +PUSHB_3 + 3 + 2 + 4 +MIRP[min,rnd,black] +SHP[rp2] +SVTCA[y-axis] +PUSHB_2 + 3 + 0 +MDAP[rnd] +ALIGNRP +PUSHB_3 + 5 + 4 + 4 +MIRP[min,rnd,black] +SHP[rp2] +PUSHB_3 + 7 + 6 + 5 +MIRP[rp0,min,rnd,grey] +ALIGNRP +PUSHB_3 + 1 + 2 + 4 +MIRP[min,rnd,black] +SHP[rp2] +EndTTInstrs +LayerCount: 2 +Fore +SplineSet +33 0 m 1,0,-1 + 33 666 l 1,1,-1 + 298 666 l 1,2,-1 + 298 0 l 1,3,-1 + 33 0 l 1,0,-1 +66 33 m 1,4,-1 + 265 33 l 1,5,-1 + 265 633 l 1,6,-1 + 66 633 l 1,7,-1 + 66 33 l 1,4,-1 +EndSplineSet +EndChar + +StartChar: glyph1 +Encoding: 1114113 -1 1 +Width: 0 +Flags: W +LayerCount: 2 +EndChar + +StartChar: glyph2 +Encoding: 1114114 -1 2 +Width: 333 +Flags: W +LayerCount: 2 +EndChar + +StartChar: W +Encoding: 87 87 3 +Width: 500 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +415 0 m 1,0,-1 + 257 725 l 1,1,-1 + 85 0 l 1,2,-1 + 415 0 l 1,0,-1 +EndSplineSet +EndChar + +StartChar: twodotenleader +Encoding: 8229 8229 4 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +703 290 m 1,0,-1 + 703 430 l 1,1,-1 + 797 430 l 1,2,-1 + 797 290 l 1,3,-1 + 703 290 l 1,0,-1 +203 290 m 1,4,-1 + 203 430 l 1,5,-1 + 297 430 l 1,6,-1 + 297 290 l 1,7,-1 + 203 290 l 1,4,-1 +EndSplineSet +Substitution2: "j-vert" twodotenleader.vert +EndChar + +StartChar: uni3042 +Encoding: 12354 12354 5 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +133 677 m 1,0,-1 + 133 613 l 1,1,-1 + 487 0 l 1,2,-1 + 867 613 l 1,3,-1 + 867 677 l 1,4,-1 + 133 677 l 1,0,-1 +EndSplineSet +EndChar + +StartChar: uni5EAD +Encoding: 24237 24237 6 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +21 -21 m 1,0,1 +876 741.3 m 1,2,-1 + 122 815.3 l 1,3,-1 + 122 683.3 l 1,4,-1 + 876 741.3 l 1,2,-1 +EndSplineSet +EndChar + +StartChar: uniFE30 +Encoding: 65072 65072 7 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +453 540 m 1,0,-1 + 453 680 l 1,1,-1 + 547 680 l 1,2,-1 + 547 540 l 1,3,-1 + 453 540 l 1,0,-1 +453 40 m 1,4,-1 + 453 180 l 1,5,-1 + 547 180 l 1,6,-1 + 547 40 l 1,7,-1 + 453 40 l 1,4,-1 +EndSplineSet +EndChar + +StartChar: uniFF37 +Encoding: 65335 65335 8 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +945 641 m 17,0,-1 + 519 797 l 1,1,-1 + 97 637 l 9,2,-1 + 527 0 l 25,3,-1 + 945 641 l 17,0,-1 +EndSplineSet +EndChar + +StartChar: uniFF5B +Encoding: 65371 65371 9 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +892 755 m 17,0,-1 + 428 392 l 1,1,-1 + 428 328 l 1,2,-1 + 892 -35 l 9,3,-1 + 892 755 l 17,0,-1 +EndSplineSet +Substitution2: "fake-vert" uniFF5B.vert +Substitution2: "j-vert" uniFF5B.vert +EndChar + +StartChar: uniFF9D +Encoding: 65437 65437 10 +Width: 500 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +467 623 m 17,0,-1 + 397 637 l 1,1,-1 + 77 322.2 l 17,2,-1 + 100 -10 l 1,3,-1 + 467 623 l 17,0,-1 +EndSplineSet +EndChar + +StartChar: twodotenleader.vert +Encoding: 1114272 -1 11 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +453 40 m 1,0,-1 + 453 180 l 1,1,-1 + 547 180 l 1,2,-1 + 547 40 l 1,3,-1 + 453 40 l 1,0,-1 +453 540 m 1,4,-1 + 453 680 l 1,5,-1 + 547 680 l 1,6,-1 + 547 540 l 1,7,-1 + 453 540 l 1,4,-1 +EndSplineSet +EndChar + +StartChar: uni3041.vert +Encoding: 1114293 -1 12 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +522 557 m 1,0,-1 + 875 557 l 1,1,-1 + 875 617 l 1,2,-1 + 522 617 l 1,3,-1 + 522 715 l 1,4,-1 + 454 715 l 1,5,-1 + 454 617 l 1,6,-1 + 285 617 l 1,7,-1 + 285 557 l 1,8,-1 + 522 557 l 1,0,-1 +EndSplineSet +EndChar + +StartChar: uniFF5B.vert +Encoding: 1114321 -1 13 +Width: 1000 +GlyphClass: 2 +Flags: W +LayerCount: 2 +Fore +SplineSet +543 340 m 25,0,-1 + 29 -30 l 25,1,-1 + 971 -32 l 1,2,-1 + 521 112 l 1,3,-1 + 543 340 l 25,0,-1 +EndSplineSet +EndChar + +StartChar: uni3041 +Encoding: 12353 12353 14 +Width: 1000 +Flags: W +LayerCount: 2 +Fore +SplineSet +225 503 m 1,0,-1 + 225 455 l 1,1,-1 + 490 -5 l 1,2,-1 + 775 455 l 1,3,-1 + 775 503 l 1,4,-1 + 225 503 l 1,0,-1 +EndSplineSet +Substitution2: "fake-vert" uni3041.vert +EndChar +EndChars +EndSplineFont diff --git a/dlls/gdi32/tests/vertical2.ttf b/dlls/gdi32/tests/vertical2.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f7b22386d2963562b82be2c93d2afe5c3d9d8d1e GIT binary patch literal 3700 zcmdT{ZERE58Ghe$ZRh(tURh1H>s&$uu^lHNE6q|c0UVJO8U+Y;nq@P_!~w^49g{!> ztQAGAtQ4V5)exhDX+mQfqc@?e__1k7E9#`I+C&STsv%(0CZ?``Mq9Lx*n7_PO(5MS zRs7q%I`{oP@AIB>?z!g@6HzT57V`Q1+crajP+khUw0pxwKdqrJ_50Q;?J0Teo+e`sRy;u>T73)u*>Mx32!q#h;=JDG!9lLdkccfA|ZL2tfB-cp|Ox zX6sfWTMYKn-N})$iZ_~nNTj?6pU6mPJekXp0@DfD3rAuHc5AC%KL&ru{MTqCwCkC} z7j595g8eH|C<+I~n~-0GyevAF-oHFs_;d87LS7w9ghR?LsrK^`;)waz6$?y zQjUklBA@I(u^y=quWU&s#?#}yNB&M!0zCA~WGa%>|JGEC_)f^43FNb`tJX0-jgXg3 zAYWak`X7)bp5=1nh|6pLcx_$T*DE?dp|#2#Xy{;r{`>;9=WZyoiWhPr38}>;hrca* znFjOz%B;~--j;us8JY?zGGhc}L0>RJJ%$S_`}sIoQF})G44SDtr=~UCJuj~uxJrhBlw6#lgTT|f4prJbyRNvFN#U$~U%;vRf^Oa7lA%t``CQNHC@jyBfI+Y(2zqXbW`A(US_C#3#vj_b(Q)=vs*86sfT2ex6r?;D-D}8Rktkf z(Wx(xiDW{mWL7(z&Y&Y>Nd0+9CM?dQt8`R4k)*_>UNy=ob*asILDNt`Rl7BRXpb6D zckRq~A^pl^W~5d#YInvT(lTmBGty}~^#^nxJW-!atNS8SKuo!j>B;L$oKA;&J%eFD z&?aEpZejyIxK+3`^}3l{QvKV9;`%$*0@ka<|R37J-f6_fv)xiIvtl`sdZf>AN#txxc5>eg~@nI z=j}kQX8Hr#PN3Ji93ZT9VdQ=Nff-V1eYk6eRR+=3u>Qr!QUfV^w7Ya@F)nzx@h)8A z+)a|ToIebY(q4=6aznPzJ4oGGwaK5Ct|S%2R-qX@7xtw^<1 zs%Hvp)_--*u++CzIjbIPtJ0iYbm#52#mTwdPU90q+tKG~aZTkO+ zDQ3A|spAVqKH~N^yAw_PVtDStFxOAv!q##-_fMsO?_md{8ha79-{vB&<9puhD*m+> z_M_PH!s6_L{V4C`gW{}j?zKrJocomD6^D%Y$GC>y^=B_XA`<1>x14jceEZ}II zn&OY;cyOI?D|^K(zGcMDc4xb0*X*L0L)p_Cek9zTJ9o+tCvw&0ZYi_8Esw?8Aig}8 zRW4-L@V4wRaU34CnDP0&`Aax+2QUULhA-P2NIPJYe!xD#J-2A8UjD zO_MJnJHAbMeI->1kI7e2f#?G!wiE$_gqr7>>gj7HFQ}ZpZSo4fTR%2=3)OS0$y@1B zj+(p;`fr(h39ZCQDBou#)r(@2ucC6{qxF=aBpsj>jnW83DNT)dO;?agt>mQ^Y6G_e zwm3z=^}#QJ_ap+JG|~D*@<3{IB${pvuTWdPEp6(K(Rf7dOC|P1!m!T=ZbQI00tP@+ zprZ&6Q4A?a25gIrrw1ab^k_H~gQ_21BeW0p5WJ~BGO{lg0^>*OIHDy@!9xOSB@bY# z)bRk!|D8>GwcvK6EcZfzON+bBEh~K3qVlDWqjXt> zgdu^q<0h0oKAMQDEgo+>#D^O+Idf^uWCu0lo-}R`p81)J(zD1HM(#19XgZzjXl|aI zob*g$^rO#u!U?D!E^lh_WToaOOYUXHl{+G*`M+EhcqIiZ)WH_EvW*M45c^m$mvAYU zak&i#?_{(kPg={mdKB7Xv@*jYaB7#5Y^A2gBJ&vD#dsOxi)!*3 zHFX#@Z7^!uV$>8^sN;S`pPxfIGh?3n?2`fh{cNfHN6FowOU56J9J~9MMY$tR;$MLB aO Date: Tue, 14 May 2024 21:55:17 +0900 Subject: [PATCH 2/2] win32u: Use the first vertical alternates table regardless of script. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56658 --- dlls/gdi32/tests/font.c | 2 +- dlls/win32u/font.c | 134 ++++------------------------------------ 2 files changed, 12 insertions(+), 124 deletions(-) diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 8c5f26547e7..362ddd381f1 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -6317,7 +6317,7 @@ static void test_vertical_font(void) ok(selected, "@WineTestVertical2 is not selected\n"); /* use the first vertical alternates table that doesn't replace U+2025 */ - todo_wine ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi); + 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()); diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 62a4dc51035..7d7aa26adc7 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -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;