From d15e5d05477d351ab318b91415680ad471fc8dc7 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Fri, 9 Oct 2026 15:05:36 +0100 Subject: [PATCH 1/4] tests/resources/test_5118_expected_*.png: new, for test_5118. --- .../resources/test_5118_expected_class_fill.png | Bin 0 -> 1235 bytes .../test_5118_expected_element_fill.png | Bin 0 -> 1235 bytes tests/resources/test_5118_expected_gradient.png | Bin 0 -> 3507 bytes ...118_expected_gradient_percent_coordinates.png | Bin 0 -> 3507 bytes ...test_5118_expected_gradient_percent_stops.png | Bin 0 -> 3507 bytes .../test_5118_expected_gradient_stop_style.png | Bin 0 -> 3507 bytes .../test_5118_expected_gradient_user_space.png | Bin 0 -> 3507 bytes .../test_5118_expected_inline_fill_control.png | Bin 0 -> 1235 bytes .../test_5118_expected_solid_fill_control.png | Bin 0 -> 813 bytes ...test_5118_expected_text_anchor_group_only.png | Bin 0 -> 2483 bytes .../resources/test_5118_expected_text_direct.png | Bin 0 -> 2483 bytes .../test_5118_expected_text_edge_direct.png | Bin 0 -> 2485 bytes .../test_5118_expected_text_edge_group.png | Bin 0 -> 2485 bytes ...test_5118_expected_text_family_group_only.png | Bin 0 -> 2537 bytes .../resources/test_5118_expected_text_group.png | Bin 0 -> 2537 bytes .../resources/test_5118_expected_text_inline.png | Bin 0 -> 2483 bytes 16 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/resources/test_5118_expected_class_fill.png create mode 100644 tests/resources/test_5118_expected_element_fill.png create mode 100644 tests/resources/test_5118_expected_gradient.png create mode 100644 tests/resources/test_5118_expected_gradient_percent_coordinates.png create mode 100644 tests/resources/test_5118_expected_gradient_percent_stops.png create mode 100644 tests/resources/test_5118_expected_gradient_stop_style.png create mode 100644 tests/resources/test_5118_expected_gradient_user_space.png create mode 100644 tests/resources/test_5118_expected_inline_fill_control.png create mode 100644 tests/resources/test_5118_expected_solid_fill_control.png create mode 100644 tests/resources/test_5118_expected_text_anchor_group_only.png create mode 100644 tests/resources/test_5118_expected_text_direct.png create mode 100644 tests/resources/test_5118_expected_text_edge_direct.png create mode 100644 tests/resources/test_5118_expected_text_edge_group.png create mode 100644 tests/resources/test_5118_expected_text_family_group_only.png create mode 100644 tests/resources/test_5118_expected_text_group.png create mode 100644 tests/resources/test_5118_expected_text_inline.png diff --git a/tests/resources/test_5118_expected_class_fill.png b/tests/resources/test_5118_expected_class_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..acf087a19a5b72fe96650743837383f919e49306 GIT binary patch literal 1235 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJCpWt8ulAh%XTY(g3fk$L90|Va?5N4dJ%_q&k zz|!jJ;uumf=k1k)oXi0ntOxJcU-o3&`Q%xbaSkIt%YF8QPIFs^2k~-Z8`|1g*E~#Q z%&v$yAT=boSKGhNTXJ&JqRr3NtIFzYT4n!>y7Y0BI~p3pGcj;Km_F2UD6|;)$QoSV W`P9Je^h#hU#o+1c=d#Wzp$P!?tUVO~ literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_element_fill.png b/tests/resources/test_5118_expected_element_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..acf087a19a5b72fe96650743837383f919e49306 GIT binary patch literal 1235 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJCpWt8ulAh%XTY(g3fk$L90|Va?5N4dJ%_q&k zz|!jJ;uumf=k1k)oXi0ntOxJcU-o3&`Q%xbaSkIt%YF8QPIFs^2k~-Z8`|1g*E~#Q z%&v$yAT=boSKGhNTXJ&JqRr3NtIFzYT4n!>y7Y0BI~p3pGcj;Km_F2UD6|;)$QoSV W`P9Je^h#hU#o+1c=d#Wzp$P!?tUVO~ literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_gradient.png b/tests/resources/test_5118_expected_gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..f263e8b7e35b2d90ec3f99b0b0b0657731040326 GIT binary patch literal 3507 zcma)9eOyxa8n-PqDz!+{G)gAsOi{0)Ogh(m4tqc*flr+dqZab{+-*wF7=b3TB+ak##`4xaw8IxN6TZ^yBOB z8=fsF6pb=gn?0mN42SgIuI982sBWvC?7jN`xUm!wnk-(E`y)a_X^EH4E+K3PjAnAYfok1gj~>?!z9;SKF6UoE)$CowpfiZ> zqvk=4H61Z{0aZXd81uNlRzmb8-WE@=LZbLXM$xc2Vt0NwAT8C}ltZVLcpQwB0qW02e{_w|5*@o&fr|{#eBi3^EdMP!wZ!i;F z&d*(iF@1?L0ryqS_3ibR)z`OkEo-ia$%gCk;I){(ahXd@U#!|DZj0M!r21cOqi*UQ zZlh^hnA%%LR$hPjd)~#BnXhqb_fIB8&vMmEv`L>#Rws0qto42qc5dL8x9%HrA9-WF zn@1hNC|O%v^e2;t652`><%2(uHp|X8p5)aM9zJ)(S|tlgyNKz1`O)01jf&0bz4_=u z@lJ_6&PhS@5NAuq;w%-Kj~T}UTT<-#=eyb&Em6VswT(SdgWBf8`qsvt4H|DNwng)h zv-?ekWmMSa+#gqc<~Y>sA}W=AtU#bkb|^2%R#UG$jv1-`YEf|7@qnbtkD{MfQ)M~# zE0FEas*_|H_bXi5y9aPjgVTyc9odUM zkcgy*=_dlHRa|sR#(7cuVfx8k*dWQTUeurLdt9{LW4kZBktoLv#>j$^BPTp0{dNPmmnpqHvLwMsb&l`& z=G``O^lwhQAeogsd5Mi&qPEaX<}f$9D=8c0(tJ-P#Z@sl$m}Pdw^_=3*k@Rx1?Bg&l_ndH`+J+)b%_Q*uBxh_46 zB{ya}kR}B1z#aW24U`6hiNbxCpArg;*cj?TI}BJ(Kv*g`!nrye9V7ogXsS2w)^VT1 zZ(q;X6~F5X^FEab6?Du`EvsQwkckBL$nC6BAsWh?>gb6j?t&ATdeT$uM0!{d(QAH2 z=64Lt>-?DpLcNf5+w5Ug>o8b{J_s6N4lMq@2NVRYJ22n@2d5Jvb@&&+jWX($(XZ$Y z(pzvX0>GJctNT`0q^<(BbPF7IG87XA;VIvh3TaQYM%{f4=nbmG0C)H09AuTY3Z3h; zsEj!Ho!pH&%`|?7t$MOFV}f^tCL&QwKY-e-nC)}ep0I{J5_=v?bken8UX2$|#4LMR zybXqG%x?#;SEUP#GUW zQlBuM7f{S}Zwl~$E8FL~iHRv{H;MdkOV^?3H&L7Gvt8?^pkmKq)rxqeUj_TBqr= zFY}IyqAU-Ft7?MbA#CVV8w@A3FN0|uaKJM52nqMIxsI994j&iz*bEH~ih*kk#kb8k zEucQ#Itr`|g85w)-YH^js0s(xuP7BRpCK}&3l9soo^b-zxkF=4vnq8>^@D2iTizpV zLSi(;0AU8k4h+0;DkX4{lQpfkk%J*pi)P_B3l_{W&l{RB9w7eu-YSYj{A- z?r7Gr0sdfT%|(d{4Nm=4=oESA4seT;^`EmpX=>cD1TyWkf0rY*gz5jF(t_6DuOQ8) zofXSSr!Hq*4rm1@(ti+-cZX_zWZ=(Ul1FIHF`jlS6OU1X#VMri{0+iZ(pvsL;Vkgq z6z1{%@)MjrlW|Nj66`o};H6_@NeA>szrSS6f4!52RxKC>XOkC+ajh#XtIkAsH&8nZ z+p*NGxM5Tkw_QH4Et}ciIbgZzG`efC`6eFvL3w)He)PB)P~hohO{7g68Hrvacn(_7 zzZ6Dae(WXwO|h7~Nlb5TdIi>LyLOrPXlciq6p9c!^g_>Nf=I1U-~z^yZx$fN8JHk< sM8PBeacT35T28@&g-cW|#Y1mrwUW`2z}OpF=wFx_E+Qtp5kuMkUopFfj{pDw literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_gradient_percent_coordinates.png b/tests/resources/test_5118_expected_gradient_percent_coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..f263e8b7e35b2d90ec3f99b0b0b0657731040326 GIT binary patch literal 3507 zcma)9eOyxa8n-PqDz!+{G)gAsOi{0)Ogh(m4tqc*flr+dqZab{+-*wF7=b3TB+ak##`4xaw8IxN6TZ^yBOB z8=fsF6pb=gn?0mN42SgIuI982sBWvC?7jN`xUm!wnk-(E`y)a_X^EH4E+K3PjAnAYfok1gj~>?!z9;SKF6UoE)$CowpfiZ> zqvk=4H61Z{0aZXd81uNlRzmb8-WE@=LZbLXM$xc2Vt0NwAT8C}ltZVLcpQwB0qW02e{_w|5*@o&fr|{#eBi3^EdMP!wZ!i;F z&d*(iF@1?L0ryqS_3ibR)z`OkEo-ia$%gCk;I){(ahXd@U#!|DZj0M!r21cOqi*UQ zZlh^hnA%%LR$hPjd)~#BnXhqb_fIB8&vMmEv`L>#Rws0qto42qc5dL8x9%HrA9-WF zn@1hNC|O%v^e2;t652`><%2(uHp|X8p5)aM9zJ)(S|tlgyNKz1`O)01jf&0bz4_=u z@lJ_6&PhS@5NAuq;w%-Kj~T}UTT<-#=eyb&Em6VswT(SdgWBf8`qsvt4H|DNwng)h zv-?ekWmMSa+#gqc<~Y>sA}W=AtU#bkb|^2%R#UG$jv1-`YEf|7@qnbtkD{MfQ)M~# zE0FEas*_|H_bXi5y9aPjgVTyc9odUM zkcgy*=_dlHRa|sR#(7cuVfx8k*dWQTUeurLdt9{LW4kZBktoLv#>j$^BPTp0{dNPmmnpqHvLwMsb&l`& z=G``O^lwhQAeogsd5Mi&qPEaX<}f$9D=8c0(tJ-P#Z@sl$m}Pdw^_=3*k@Rx1?Bg&l_ndH`+J+)b%_Q*uBxh_46 zB{ya}kR}B1z#aW24U`6hiNbxCpArg;*cj?TI}BJ(Kv*g`!nrye9V7ogXsS2w)^VT1 zZ(q;X6~F5X^FEab6?Du`EvsQwkckBL$nC6BAsWh?>gb6j?t&ATdeT$uM0!{d(QAH2 z=64Lt>-?DpLcNf5+w5Ug>o8b{J_s6N4lMq@2NVRYJ22n@2d5Jvb@&&+jWX($(XZ$Y z(pzvX0>GJctNT`0q^<(BbPF7IG87XA;VIvh3TaQYM%{f4=nbmG0C)H09AuTY3Z3h; zsEj!Ho!pH&%`|?7t$MOFV}f^tCL&QwKY-e-nC)}ep0I{J5_=v?bken8UX2$|#4LMR zybXqG%x?#;SEUP#GUW zQlBuM7f{S}Zwl~$E8FL~iHRv{H;MdkOV^?3H&L7Gvt8?^pkmKq)rxqeUj_TBqr= zFY}IyqAU-Ft7?MbA#CVV8w@A3FN0|uaKJM52nqMIxsI994j&iz*bEH~ih*kk#kb8k zEucQ#Itr`|g85w)-YH^js0s(xuP7BRpCK}&3l9soo^b-zxkF=4vnq8>^@D2iTizpV zLSi(;0AU8k4h+0;DkX4{lQpfkk%J*pi)P_B3l_{W&l{RB9w7eu-YSYj{A- z?r7Gr0sdfT%|(d{4Nm=4=oESA4seT;^`EmpX=>cD1TyWkf0rY*gz5jF(t_6DuOQ8) zofXSSr!Hq*4rm1@(ti+-cZX_zWZ=(Ul1FIHF`jlS6OU1X#VMri{0+iZ(pvsL;Vkgq z6z1{%@)MjrlW|Nj66`o};H6_@NeA>szrSS6f4!52RxKC>XOkC+ajh#XtIkAsH&8nZ z+p*NGxM5Tkw_QH4Et}ciIbgZzG`efC`6eFvL3w)He)PB)P~hohO{7g68Hrvacn(_7 zzZ6Dae(WXwO|h7~Nlb5TdIi>LyLOrPXlciq6p9c!^g_>Nf=I1U-~z^yZx$fN8JHk< sM8PBeacT35T28@&g-cW|#Y1mrwUW`2z}OpF=wFx_E+Qtp5kuMkUopFfj{pDw literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_gradient_percent_stops.png b/tests/resources/test_5118_expected_gradient_percent_stops.png new file mode 100644 index 0000000000000000000000000000000000000000..f263e8b7e35b2d90ec3f99b0b0b0657731040326 GIT binary patch literal 3507 zcma)9eOyxa8n-PqDz!+{G)gAsOi{0)Ogh(m4tqc*flr+dqZab{+-*wF7=b3TB+ak##`4xaw8IxN6TZ^yBOB z8=fsF6pb=gn?0mN42SgIuI982sBWvC?7jN`xUm!wnk-(E`y)a_X^EH4E+K3PjAnAYfok1gj~>?!z9;SKF6UoE)$CowpfiZ> zqvk=4H61Z{0aZXd81uNlRzmb8-WE@=LZbLXM$xc2Vt0NwAT8C}ltZVLcpQwB0qW02e{_w|5*@o&fr|{#eBi3^EdMP!wZ!i;F z&d*(iF@1?L0ryqS_3ibR)z`OkEo-ia$%gCk;I){(ahXd@U#!|DZj0M!r21cOqi*UQ zZlh^hnA%%LR$hPjd)~#BnXhqb_fIB8&vMmEv`L>#Rws0qto42qc5dL8x9%HrA9-WF zn@1hNC|O%v^e2;t652`><%2(uHp|X8p5)aM9zJ)(S|tlgyNKz1`O)01jf&0bz4_=u z@lJ_6&PhS@5NAuq;w%-Kj~T}UTT<-#=eyb&Em6VswT(SdgWBf8`qsvt4H|DNwng)h zv-?ekWmMSa+#gqc<~Y>sA}W=AtU#bkb|^2%R#UG$jv1-`YEf|7@qnbtkD{MfQ)M~# zE0FEas*_|H_bXi5y9aPjgVTyc9odUM zkcgy*=_dlHRa|sR#(7cuVfx8k*dWQTUeurLdt9{LW4kZBktoLv#>j$^BPTp0{dNPmmnpqHvLwMsb&l`& z=G``O^lwhQAeogsd5Mi&qPEaX<}f$9D=8c0(tJ-P#Z@sl$m}Pdw^_=3*k@Rx1?Bg&l_ndH`+J+)b%_Q*uBxh_46 zB{ya}kR}B1z#aW24U`6hiNbxCpArg;*cj?TI}BJ(Kv*g`!nrye9V7ogXsS2w)^VT1 zZ(q;X6~F5X^FEab6?Du`EvsQwkckBL$nC6BAsWh?>gb6j?t&ATdeT$uM0!{d(QAH2 z=64Lt>-?DpLcNf5+w5Ug>o8b{J_s6N4lMq@2NVRYJ22n@2d5Jvb@&&+jWX($(XZ$Y z(pzvX0>GJctNT`0q^<(BbPF7IG87XA;VIvh3TaQYM%{f4=nbmG0C)H09AuTY3Z3h; zsEj!Ho!pH&%`|?7t$MOFV}f^tCL&QwKY-e-nC)}ep0I{J5_=v?bken8UX2$|#4LMR zybXqG%x?#;SEUP#GUW zQlBuM7f{S}Zwl~$E8FL~iHRv{H;MdkOV^?3H&L7Gvt8?^pkmKq)rxqeUj_TBqr= zFY}IyqAU-Ft7?MbA#CVV8w@A3FN0|uaKJM52nqMIxsI994j&iz*bEH~ih*kk#kb8k zEucQ#Itr`|g85w)-YH^js0s(xuP7BRpCK}&3l9soo^b-zxkF=4vnq8>^@D2iTizpV zLSi(;0AU8k4h+0;DkX4{lQpfkk%J*pi)P_B3l_{W&l{RB9w7eu-YSYj{A- z?r7Gr0sdfT%|(d{4Nm=4=oESA4seT;^`EmpX=>cD1TyWkf0rY*gz5jF(t_6DuOQ8) zofXSSr!Hq*4rm1@(ti+-cZX_zWZ=(Ul1FIHF`jlS6OU1X#VMri{0+iZ(pvsL;Vkgq z6z1{%@)MjrlW|Nj66`o};H6_@NeA>szrSS6f4!52RxKC>XOkC+ajh#XtIkAsH&8nZ z+p*NGxM5Tkw_QH4Et}ciIbgZzG`efC`6eFvL3w)He)PB)P~hohO{7g68Hrvacn(_7 zzZ6Dae(WXwO|h7~Nlb5TdIi>LyLOrPXlciq6p9c!^g_>Nf=I1U-~z^yZx$fN8JHk< sM8PBeacT35T28@&g-cW|#Y1mrwUW`2z}OpF=wFx_E+Qtp5kuMkUopFfj{pDw literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_gradient_stop_style.png b/tests/resources/test_5118_expected_gradient_stop_style.png new file mode 100644 index 0000000000000000000000000000000000000000..f263e8b7e35b2d90ec3f99b0b0b0657731040326 GIT binary patch literal 3507 zcma)9eOyxa8n-PqDz!+{G)gAsOi{0)Ogh(m4tqc*flr+dqZab{+-*wF7=b3TB+ak##`4xaw8IxN6TZ^yBOB z8=fsF6pb=gn?0mN42SgIuI982sBWvC?7jN`xUm!wnk-(E`y)a_X^EH4E+K3PjAnAYfok1gj~>?!z9;SKF6UoE)$CowpfiZ> zqvk=4H61Z{0aZXd81uNlRzmb8-WE@=LZbLXM$xc2Vt0NwAT8C}ltZVLcpQwB0qW02e{_w|5*@o&fr|{#eBi3^EdMP!wZ!i;F z&d*(iF@1?L0ryqS_3ibR)z`OkEo-ia$%gCk;I){(ahXd@U#!|DZj0M!r21cOqi*UQ zZlh^hnA%%LR$hPjd)~#BnXhqb_fIB8&vMmEv`L>#Rws0qto42qc5dL8x9%HrA9-WF zn@1hNC|O%v^e2;t652`><%2(uHp|X8p5)aM9zJ)(S|tlgyNKz1`O)01jf&0bz4_=u z@lJ_6&PhS@5NAuq;w%-Kj~T}UTT<-#=eyb&Em6VswT(SdgWBf8`qsvt4H|DNwng)h zv-?ekWmMSa+#gqc<~Y>sA}W=AtU#bkb|^2%R#UG$jv1-`YEf|7@qnbtkD{MfQ)M~# zE0FEas*_|H_bXi5y9aPjgVTyc9odUM zkcgy*=_dlHRa|sR#(7cuVfx8k*dWQTUeurLdt9{LW4kZBktoLv#>j$^BPTp0{dNPmmnpqHvLwMsb&l`& z=G``O^lwhQAeogsd5Mi&qPEaX<}f$9D=8c0(tJ-P#Z@sl$m}Pdw^_=3*k@Rx1?Bg&l_ndH`+J+)b%_Q*uBxh_46 zB{ya}kR}B1z#aW24U`6hiNbxCpArg;*cj?TI}BJ(Kv*g`!nrye9V7ogXsS2w)^VT1 zZ(q;X6~F5X^FEab6?Du`EvsQwkckBL$nC6BAsWh?>gb6j?t&ATdeT$uM0!{d(QAH2 z=64Lt>-?DpLcNf5+w5Ug>o8b{J_s6N4lMq@2NVRYJ22n@2d5Jvb@&&+jWX($(XZ$Y z(pzvX0>GJctNT`0q^<(BbPF7IG87XA;VIvh3TaQYM%{f4=nbmG0C)H09AuTY3Z3h; zsEj!Ho!pH&%`|?7t$MOFV}f^tCL&QwKY-e-nC)}ep0I{J5_=v?bken8UX2$|#4LMR zybXqG%x?#;SEUP#GUW zQlBuM7f{S}Zwl~$E8FL~iHRv{H;MdkOV^?3H&L7Gvt8?^pkmKq)rxqeUj_TBqr= zFY}IyqAU-Ft7?MbA#CVV8w@A3FN0|uaKJM52nqMIxsI994j&iz*bEH~ih*kk#kb8k zEucQ#Itr`|g85w)-YH^js0s(xuP7BRpCK}&3l9soo^b-zxkF=4vnq8>^@D2iTizpV zLSi(;0AU8k4h+0;DkX4{lQpfkk%J*pi)P_B3l_{W&l{RB9w7eu-YSYj{A- z?r7Gr0sdfT%|(d{4Nm=4=oESA4seT;^`EmpX=>cD1TyWkf0rY*gz5jF(t_6DuOQ8) zofXSSr!Hq*4rm1@(ti+-cZX_zWZ=(Ul1FIHF`jlS6OU1X#VMri{0+iZ(pvsL;Vkgq z6z1{%@)MjrlW|Nj66`o};H6_@NeA>szrSS6f4!52RxKC>XOkC+ajh#XtIkAsH&8nZ z+p*NGxM5Tkw_QH4Et}ciIbgZzG`efC`6eFvL3w)He)PB)P~hohO{7g68Hrvacn(_7 zzZ6Dae(WXwO|h7~Nlb5TdIi>LyLOrPXlciq6p9c!^g_>Nf=I1U-~z^yZx$fN8JHk< sM8PBeacT35T28@&g-cW|#Y1mrwUW`2z}OpF=wFx_E+Qtp5kuMkUopFfj{pDw literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_gradient_user_space.png b/tests/resources/test_5118_expected_gradient_user_space.png new file mode 100644 index 0000000000000000000000000000000000000000..f263e8b7e35b2d90ec3f99b0b0b0657731040326 GIT binary patch literal 3507 zcma)9eOyxa8n-PqDz!+{G)gAsOi{0)Ogh(m4tqc*flr+dqZab{+-*wF7=b3TB+ak##`4xaw8IxN6TZ^yBOB z8=fsF6pb=gn?0mN42SgIuI982sBWvC?7jN`xUm!wnk-(E`y)a_X^EH4E+K3PjAnAYfok1gj~>?!z9;SKF6UoE)$CowpfiZ> zqvk=4H61Z{0aZXd81uNlRzmb8-WE@=LZbLXM$xc2Vt0NwAT8C}ltZVLcpQwB0qW02e{_w|5*@o&fr|{#eBi3^EdMP!wZ!i;F z&d*(iF@1?L0ryqS_3ibR)z`OkEo-ia$%gCk;I){(ahXd@U#!|DZj0M!r21cOqi*UQ zZlh^hnA%%LR$hPjd)~#BnXhqb_fIB8&vMmEv`L>#Rws0qto42qc5dL8x9%HrA9-WF zn@1hNC|O%v^e2;t652`><%2(uHp|X8p5)aM9zJ)(S|tlgyNKz1`O)01jf&0bz4_=u z@lJ_6&PhS@5NAuq;w%-Kj~T}UTT<-#=eyb&Em6VswT(SdgWBf8`qsvt4H|DNwng)h zv-?ekWmMSa+#gqc<~Y>sA}W=AtU#bkb|^2%R#UG$jv1-`YEf|7@qnbtkD{MfQ)M~# zE0FEas*_|H_bXi5y9aPjgVTyc9odUM zkcgy*=_dlHRa|sR#(7cuVfx8k*dWQTUeurLdt9{LW4kZBktoLv#>j$^BPTp0{dNPmmnpqHvLwMsb&l`& z=G``O^lwhQAeogsd5Mi&qPEaX<}f$9D=8c0(tJ-P#Z@sl$m}Pdw^_=3*k@Rx1?Bg&l_ndH`+J+)b%_Q*uBxh_46 zB{ya}kR}B1z#aW24U`6hiNbxCpArg;*cj?TI}BJ(Kv*g`!nrye9V7ogXsS2w)^VT1 zZ(q;X6~F5X^FEab6?Du`EvsQwkckBL$nC6BAsWh?>gb6j?t&ATdeT$uM0!{d(QAH2 z=64Lt>-?DpLcNf5+w5Ug>o8b{J_s6N4lMq@2NVRYJ22n@2d5Jvb@&&+jWX($(XZ$Y z(pzvX0>GJctNT`0q^<(BbPF7IG87XA;VIvh3TaQYM%{f4=nbmG0C)H09AuTY3Z3h; zsEj!Ho!pH&%`|?7t$MOFV}f^tCL&QwKY-e-nC)}ep0I{J5_=v?bken8UX2$|#4LMR zybXqG%x?#;SEUP#GUW zQlBuM7f{S}Zwl~$E8FL~iHRv{H;MdkOV^?3H&L7Gvt8?^pkmKq)rxqeUj_TBqr= zFY}IyqAU-Ft7?MbA#CVV8w@A3FN0|uaKJM52nqMIxsI994j&iz*bEH~ih*kk#kb8k zEucQ#Itr`|g85w)-YH^js0s(xuP7BRpCK}&3l9soo^b-zxkF=4vnq8>^@D2iTizpV zLSi(;0AU8k4h+0;DkX4{lQpfkk%J*pi)P_B3l_{W&l{RB9w7eu-YSYj{A- z?r7Gr0sdfT%|(d{4Nm=4=oESA4seT;^`EmpX=>cD1TyWkf0rY*gz5jF(t_6DuOQ8) zofXSSr!Hq*4rm1@(ti+-cZX_zWZ=(Ul1FIHF`jlS6OU1X#VMri{0+iZ(pvsL;Vkgq z6z1{%@)MjrlW|Nj66`o};H6_@NeA>szrSS6f4!52RxKC>XOkC+ajh#XtIkAsH&8nZ z+p*NGxM5Tkw_QH4Et}ciIbgZzG`efC`6eFvL3w)He)PB)P~hohO{7g68Hrvacn(_7 zzZ6Dae(WXwO|h7~Nlb5TdIi>LyLOrPXlciq6p9c!^g_>Nf=I1U-~z^yZx$fN8JHk< sM8PBeacT35T28@&g-cW|#Y1mrwUW`2z}OpF=wFx_E+Qtp5kuMkUopFfj{pDw literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_inline_fill_control.png b/tests/resources/test_5118_expected_inline_fill_control.png new file mode 100644 index 0000000000000000000000000000000000000000..acf087a19a5b72fe96650743837383f919e49306 GIT binary patch literal 1235 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJCpWt8ulAh%XTY(g3fk$L90|Va?5N4dJ%_q&k zz|!jJ;uumf=k1k)oXi0ntOxJcU-o3&`Q%xbaSkIt%YF8QPIFs^2k~-Z8`|1g*E~#Q z%&v$yAT=boSKGhNTXJ&JqRr3NtIFzYT4n!>y7Y0BI~p3pGcj;Km_F2UD6|;)$QoSV W`P9Je^h#hU#o+1c=d#Wzp$P!?tUVO~ literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_solid_fill_control.png b/tests/resources/test_5118_expected_solid_fill_control.png new file mode 100644 index 0000000000000000000000000000000000000000..0a06bd9eae748e7e9c614ebc0a2b0776aa2fe27d GIT binary patch literal 813 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJCpWt8ulAh%XTY(g3fk$L90|Va?5N4dJ%_q&k zz;xf!#WAE}&f6=FUWWr1Tra+>uU)&@%|&P1+?Fl3EH0Hi5&PH5%r2MDTyB0}?)`Jg zgo4wxcXK~~s;d1R!_ZbbLvQ)(PdwMk_Fao_Nc5H8oWRK2#G1k(HbF7Mp)G+?a+EU~ z26RaWALZ8^F1g8fV8gfLpN%7cX_PIYVEg;|_L_mMvnDy4qyy7GgQu&X%Q~loCIFZ` B=bQil literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_text_anchor_group_only.png b/tests/resources/test_5118_expected_text_anchor_group_only.png new file mode 100644 index 0000000000000000000000000000000000000000..16befb86eb3d211200eecad5dce55d4e6bf83e52 GIT binary patch literal 2483 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 ZQr78b{9XGSH{c(p-~qnlPQ4C)@;`fpsEYsq literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_text_edge_group.png b/tests/resources/test_5118_expected_text_edge_group.png new file mode 100644 index 0000000000000000000000000000000000000000..2bac44c4c3fa46d84449f803f9b630f9809450e3 GIT binary patch literal 2485 zcmdUx`8(U$9>=wm+bXJxqL%8E+g4~tEwzqTni^HLT+0MWWt6EXp(GJ$twf`#CBzznEca{viryd2`JCsR=Q-!|d7t;|IVbb(9f;a7 z{bLFW3Ths=+qMQsX?J~q7?D>Nbk@xGkKmbc@EdUEZ@L%V48FN=`Z@KO zwoaF;#;u579{JL%o3oeU;D}$+zXerKGSijQCVr(+r(i~6oaN`8zWu)(i!a0O&xAHy zJ@m~0|8|i=bJs}=6SbDZgD1YW@Z`?+C^U8&%}psv*$&1k5{bkscVRI6bH$24T25{U z$#`{qw_s3+-4PN$1;SFQ5gkj-n%r#Sm`dSg1%O!po&-k@XzE{9hICyz-M; z)$H1epiJbobxlVC+)eGNiiVL3PWyIE3vTwx4XfcHVtBU%4O09^lBI^Gg-EguJS`*|do_)Gv$j~~fGkl^Yt7nyr748D+ z<;hmSW7JSY&wq|;WkuURyqPRovVk}MJG@DsaynxL<-uP2uPUd(z!tdxNHYQC>eWk= z*H-J6>#pZd-Pz(r$Ub_3CJ=??eY4OCmay|B+T*N4iB(4@po#nb>Y z$1?aOMXB||dO>*4^YflruY%v-*GAt1Y`4DAVT`v>4*Qw^aul*0^5lq(JKgl3keo9Y zYT8&HAHyne(Y~ zfZ;l|yqyLP@*yRVzm52Q{T8%dwkNQvoqZA>s&q-HhnI@R;%BE~*+l%~$BHWL$$*Y1 zv<{xTWRBbA=Q0AF2AMA5^CvAz@2#=Rp}aIxa#}g`VIBWB%%h8=Bk*a!AB=}lQKjm5 z@u&0%(gXFYHf-5^Z@#VoklTnlUL75XYy^s)a*}I(MsS-_1f!J%1@N0J5SVV}P5v1E zCq_9NOBG`|Z>dyaTmourw8Xn858~u?P<>_EaXsJZlPybAHL;1F*cN@)R2&5_+nryE zYqY@nC%i7(6~QP|r@VgJlt4eveRy-@ePn;md^fM6#(o9UjMSuT?AHzgCJ)~?FT!ms zzwc+F4{J8rlEyQYR3F$E!l!?pFJ#DM`>PeL>mdQ#rC+}D+Z5oJhRYaXtYne=2VfaJ z=_FqgqF##yZ9{^#Os%5Sy~W;qyN+{VFQ{NTuZhM}!Q^*3Jx; z)B1yG=l86R=C=?VmApKd99r{`D0*?huN-1^k(nypv+ZZs?{6&*Aws1f34rW206du9 z=OCbjHYB~Y26)aSqWp9O;({3#w!`(7sN@8gbHA@(VlSi6lm0qw=xD$Yd&i1n#~XO3 z;Ub;|QpxE81bTU3INlx!q1~Hx8@JBUO-xK&&#-&6@BzTMxObB#Y;@S)D)8DEVLr9kFSHjUsXi7>74t{`RCEJEnQ_f9-VOOfTxJ@tYJZ#$e zZGfbacA_xP6))p)2!vR!fxdngyfUONUcB~+KMvLn-P#k-a*fBw$Hn3~66Ac(<3ozd zZ3txk-|)%nFdqpg+>h8I$Kz(3AFCg)Vgdl#M2}K}7~xaQn37}{R5TMg@n@o7R2zl` zb8KTKPZdh}xv=h6rGpUTlv6c<`F626?o8RUaXTSBoE8$xVk`5GU=ukc;|KTk=l ZQr78b{9XGSH{c(p-~qnlPQ4C)@;`fpsEYsq literal 0 HcmV?d00001 diff --git a/tests/resources/test_5118_expected_text_family_group_only.png b/tests/resources/test_5118_expected_text_family_group_only.png new file mode 100644 index 0000000000000000000000000000000000000000..830c1aea3050307a59b3d73c309fcf81149aad9c GIT binary patch literal 2537 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 Date: Fri, 9 Oct 2026 15:20:17 +0100 Subject: [PATCH 2/4] tests/test_svg.py: new, adding test_5118(). We expect success for mupdf>=1.29, otherwise expect failure. --- tests/test_svg.py | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 tests/test_svg.py diff --git a/tests/test_svg.py b/tests/test_svg.py new file mode 100644 index 000000000..11904b236 --- /dev/null +++ b/tests/test_svg.py @@ -0,0 +1,146 @@ +import os +import pathlib + +import pymupdf + +import gentle_compare + + +def test_5118(): + print() + out = pathlib.Path(os.path.normpath(f'{__file__}/../../tests/test_5118_out')) + print(f'{out=}') + out.mkdir(exist_ok=True) + + def svg(body): + return ( + '' + + body + + '' + ) + + + gradient = svg(''' + + + + + + + + ''') + + text_attributes = ( + 'text-anchor="middle" font-family="Arial, sans-serif" font-size="20"' + ) + cases = { + "gradient": gradient, + "gradient_percent_stops": gradient.replace( + 'offset="0"', 'offset="0%"' + ).replace('offset="1"', 'offset="100%"'), + "gradient_percent_coordinates": gradient.replace( + 'x1="0" x2="1"', 'x1="0%" y1="0%" x2="100%" y2="0%"' + ), + "gradient_stop_style": gradient.replace( + 'stop-color="#f5f8ff"', 'style="stop-color:#f5f8ff"' + ).replace('stop-color="#eefbf6"', 'style="stop-color:#eefbf6"'), + "gradient_user_space": gradient.replace( + 'x1="0" x2="1"', + 'gradientUnits="userSpaceOnUse" x1="1" y1="1" x2="399" y2="1"', + ), + "solid_fill_control": gradient.replace('url(#bg)', '#f5f8ff'), + "text_direct": svg( + f'middle label' + ), + "text_group": svg( + f'' + 'middle label' + ), + "text_inline": svg( + '' + 'middle label' + ), + "text_anchor_group_only": svg( + '' + '' + 'middle label' + ), + "text_family_group_only": svg( + '' + '' + 'middle label' + ), + "class_fill": svg( + '' + '' + ), + "element_fill": svg( + '' + '' + ), + "inline_fill_control": svg( + '' + ), + } + cases["text_edge_direct"] = cases["text_direct"].replace('x="200"', 'x="320"') + cases["text_edge_group"] = cases["text_anchor_group_only"].replace( + 'x="200"', 'x="320"' + ) + + png_names = list() + + for name, content in cases.items(): + svg_bytes = content.encode("utf-8") + (out / f"{name}.svg").write_bytes(svg_bytes) + with pymupdf.open(stream=svg_bytes, filetype="svg") as doc: + page = doc[0] + pix = page.get_pixmap(alpha=False) + png_name = f"{name}.png" + pix.save(out / png_name) + png_names.append(png_name) + print(name, "center RGB", pix.pixel(200, 100)) + for block in page.get_text("dict")["blocks"]: + if block["type"] != 0: + continue + for line in block["lines"]: + for span in line["spans"]: + print( + " text", repr(span["text"]), + "font", span["font"], + "size", span["size"], + "origin", tuple(round(v, 2) for v in span["origin"]), + ) + + # Check .png files. + num_errors = 0 + for png_name in png_names: + expected = os.path.normpath(f'{__file__}/../../tests/resources/test_5118_expected_{png_name}') + actual = str(out / png_name) + rms = gentle_compare.pixmaps_rms(expected, actual, verbose=0) + print(f'{png_name=}: {rms=}') + if rms > 1: + num_errors += 1 + + # Confirm the same problems through Markdown-to-PDF conversion. + for name in ("gradient", "text_direct", "text_group", "class_fill"): + markdown_path = out / f"{name}.md" + markdown_path.write_text(f"![SVG example]({name}.svg)\n", encoding="utf-8") + with pymupdf.open( + markdown_path, + rect=pymupdf.paper_rect("A4"), + archive=pymupdf.Archive(str(out)), + ) as doc: + doc.ez_save(out / f"{name}_from_markdown.pdf") + + print(f'{num_errors=}') + + if pymupdf.mupdf_version_tuple >= (1, 29): + assert not num_errors, f'{num_errors=}' + else: + # 2026-10-09. + # num_errors = 9 with mupdf-1.28.x 393e18b3c66c4 `When adding colorspace do not write Device colorspaces as ICC.`. + # num_errors = 10 with pymupdf-1.28.2. + assert num_errors From 27e4768533d719cf7d12e4edbf3bccb9c180b0d4 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Fri, 9 Oct 2026 15:21:10 +0100 Subject: [PATCH 3/4] tests/test_story.py:test_5119(): new, does not reproduce the problem. --- tests/test_story.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/test_story.py b/tests/test_story.py index b9b00debc..da71eb1a1 100644 --- a/tests/test_story.py +++ b/tests/test_story.py @@ -325,3 +325,40 @@ def test_5110(): else: # 2026-09-11: Expect error. assert num_drawings == 1 + + +def test_5119(): + # This does not yet reproduce the problem - does not hang. + + chinese_text = '\u4f60\u7684' * 1000 + html = textwrap.dedent(f''' + +
+ {chinese_text} +
+ ''') + path_out = os.path.normpath(f'{__file__}/../../tests/test_5119_out.pdf') + story = pymupdf.Story(html=html) + mediabox = pymupdf.paper_rect("a4") + where = mediabox + (36, 36, -36, -36) + writer = pymupdf.DocumentWriter(path_out) + more = 1 + page_count = 0 + while more: + page_count += 1 + # Safety limit added only to demonstrate the problem. + if page_count > 100: + raise RuntimeError('Story.place() did not make progress') + device = writer.begin_page(mediabox) + more, filled = story.place(where) + print( + f'page={page_count}, more={more}, filled={filled}' + ) + story.draw(device) + writer.end_page() + writer.close() + From c77f88dc7e72bcea031f9c0ea1660f8c347f4680 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Fri, 9 Oct 2026 15:22:44 +0100 Subject: [PATCH 4/4] .github/workflows/test_quick.yml: use PYMUPDF_TEST_QUICK=1 to reduce delay. --- .github/workflows/test_quick.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_quick.yml b/.github/workflows/test_quick.yml index e1a782ffa..8a95d837e 100644 --- a/.github/workflows/test_quick.yml +++ b/.github/workflows/test_quick.yml @@ -36,4 +36,4 @@ jobs: import subprocess import sys subprocess.run(f'git clone https://github.com/ArtifexSoftware/aptest.git', shell=1, check=1) - subprocess.run(f'{sys.executable} aptest/aptest.py -a APTEST_MUPDF_LOCATION -p . --4llm git: --layout git: build test -t p -a APTEST_args', shell=1, check=1) + subprocess.run(f'{sys.executable} aptest/aptest.py -a APTEST_MUPDF_LOCATION -p . --4llm git: --layout git: build test -t p -e PYMUPDF_TEST_QUICK=1 -a APTEST_args', shell=1, check=1)