From 2ed22b1bbe4f34f44aa54d77dadd8495cedd890c Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Mon, 5 Jan 2026 12:52:40 +0100 Subject: [PATCH 1/3] text: Allow small shear when displaying device text Flash does not show device text when there's shear, rotation, or negative scale, because device text cannot be transformed. However, it does allow small leeway for shear so that objects with very small shear can still be rendered. (Perhaps the limit was chosen in such a way that the visual difference between sheared and non-sheared text is negligible.) This patch adds such leeway which is a bit higher than Flash's due to the fact that Ruffle can diverge in calculations from Flash. --- core/src/display_object/edit_text.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/display_object/edit_text.rs b/core/src/display_object/edit_text.rs index 8fd24beab50d..f811d225e3c9 100644 --- a/core/src/display_object/edit_text.rs +++ b/core/src/display_object/edit_text.rs @@ -2672,7 +2672,12 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> { fn is_transform_positive_scale_only(context: &mut RenderContext) -> bool { let Matrix { a, b, c, d, .. } = context.transform_stack.transform().matrix; - b == 0.0 && c == 0.0 && a > 0.0 && d > 0.0 + // Flash does allow small shear. The following value is higher than + // expected due to the fact that the final calculated shear differs + // between Flash and Ruffle, and using a precise value would hide + // some objects that should otherwise be shown. + const ALLOWED_SHEAR: f32 = 0.006; + b.abs() < ALLOWED_SHEAR && c.abs() < ALLOWED_SHEAR && a > 0.0 && d > 0.0 } // EditText is not rendered if device font is used From a719e653823de20d48a2e12b21ce627632fff121 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Mon, 5 Jan 2026 12:16:29 +0100 Subject: [PATCH 2/3] tests: Add visual/edittext/edittext_device_transform_small_shear test --- .../output.expected.png | Bin 0 -> 801 bytes .../output.txt | 0 .../test.as | 89 ++++++++++++++++++ .../test.swf | Bin 0 -> 741 bytes .../test.toml | 8 ++ 5 files changed, 97 insertions(+) create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/output.expected.png create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/output.txt create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.as create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.swf create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.toml diff --git a/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/output.expected.png b/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/output.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..81ee68a871608635971d29fda99269d2552b5500 GIT binary patch literal 801 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J2BoosZ$T+u%tWsIx;Y9 z?C1WI$O_~uBzpw;GB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZk1_q}2 zo-U3d6}R5rb?iH2AmDoNe#h_ln=uS7Vn=SgU1i!m&%-~tV9phZWR{B84}}^W9267; z1UNWYSeTd?8xK^@n{FQ|Zl4}6_ummDGo1k}4pDYO(E4TBiI4IuaP<)Jj=5iI>?hml z%?saOt$wd&@AGK83FYDo_2L%H`f`27`tLQDw*I*#w>{a@FP%-dOTYB^%yuM$925kA;^OI--Y#iY6$AM+ zFYHWvbye0STc>BQZR2Op7JYqOe8HJ?J8vDh&vvkYoSbs{_TBVcwwXXD7w)!>NNRLA zaCcAS^UivZzSr*kX$yA;p56W)>On{#A_W-8v`01`dz{YHSWM=FgaS0AL4Jh!6E381 zZprg!;gwgL-rq33U-x-yrF-JvA52qzo=NXy1;!3UJvd4lbAFb5kDToYa)-@bS)Gjz z3J>z`dA9xRo4@|--97*RJj&R2?{g&3!Lay+`wU`A$7h9`pWbZzS#|!oj}^#c5Oqjt z0iq73{n8`ZR=$r#Pn@OOn*T>6F~Xe#_T$TU3KMqJvUuyjl*0o7&5sW8`lgLt=Py~t R0+TKSgQu&X%Q~loCIJ2B9EAV? literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/output.txt b/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/output.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.as b/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.as new file mode 100644 index 000000000000..8e57112e0c1d --- /dev/null +++ b/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.as @@ -0,0 +1,89 @@ +Stage.scaleMode = "noScale"; + +var nextX = 10; +var nextY = 30; + +function renderField(mc, a, b, c, d) { + var x = nextX; + var y = nextY; + var mc2 = mc.createEmptyMovieClip("mc_" + x + "_" + y, mc.getNextHighestDepth()); + mc2.transform.matrix = new flash.geom.Matrix(a, b, c, d, x, y); + + var tf = mc2.createTextField( + "field_" + x + "_" + y, + mc2.getNextHighestDepth(), + 0, 0, 5, 5); + tf.borderColor = 0xFF00FF; + tf.backgroundColor = 0x0000FF; + tf.border = true; + tf.background = false; + tf.embedFonts = false; + + var tf = mc2.createTextField( + "field_" + x + "_" + y + "_2", + mc2.getNextHighestDepth(), + 7, 0, 8, 5); + tf.borderColor = 0xFF00FF; + tf.backgroundColor = 0x0000FF; + tf.border = true; + tf.background = false; + tf.embedFonts = false; + + var tf = mc2.createTextField( + "field_" + x + "_" + y + "_3", + mc2.getNextHighestDepth(), + 0, 7, 15, 8); + tf.borderColor = 0xFF00FF; + tf.backgroundColor = 0x0000FF; + tf.border = true; + tf.background = false; + tf.embedFonts = false; + + nextX += 40; +} + +renderField(_root, 1, 0, 0, 1); +renderField(_root, 1, 0.00488281273, 0, 1); +renderField(_root, 1, 0, 0.00488281273, 1); +renderField(_root, 1, 0.00488281273, 0.00488281273, 1); + +nextX = 10; +nextY = 50; + +renderField(_root, 1, 0, 0, 1); +renderField(_root, 1, -0.00488281273, 0, 1); +renderField(_root, 1, 0, -0.00488281273, 1); +renderField(_root, 1, -0.00488281273, -0.00488281273, 1); + +nextX = 10; +nextY = 70; + +renderField(_root, 2, 0, 0, 2); +renderField(_root, 2, 0.00488281273, 0, 2); +renderField(_root, 2, 0, 0.00488281273, 2); +renderField(_root, 2, 0.00488281273, 0.00488281273, 2); + +nextX = 10; +nextY = 120; + +renderField(_root, 2, 0, 0, 2); +renderField(_root, 2, -0.00488281273, 0, 2); +renderField(_root, 2, 0, -0.00488281273, 2); +renderField(_root, 2, -0.00488281273, -0.00488281273, 2); + +nextX = 10; +nextY = 170; + +var mc = _root.createEmptyMovieClip("outer", _root.getNextHighestDepth()); +mc.transform.matrix = new flash.geom.Matrix(1, 500.001, 0, 1, nextX, nextY); +var mc2 = mc.createEmptyMovieClip("inner", mc.getNextHighestDepth()); +mc2.transform.matrix = new flash.geom.Matrix(1, -500, 0, 1, 0, 0); +var tf = mc2.createTextField( + "field_inner", + mc2.getNextHighestDepth(), + 0, 0, 10, 10); +tf.borderColor = 0xFF00FF; +tf.backgroundColor = 0x0000FF; +tf.border = true; +tf.background = false; +tf.embedFonts = false; diff --git a/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.swf b/tests/tests/swfs/visual/edittext/edittext_device_transform_small_shear/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..136e7dcf131e99bed379ce2cf36d77f4f9e6eeb0 GIT binary patch literal 741 zcmVuhgqE55sM-bA6IgbIpC>39L2fC9-aG>D292vr^ev$MXl*MD$E5!lk~e6u?<-`wua zUL8vX#J&MZ4I6V1zjeLS>9mm*s)3D*`xna^I^sV&pFDg2z4+teawz&*=p9k`wi+u~m16bDVKRToiQ8(Y4m!J5^;{h5ee zBm>H>S7qM1+jKpYt;%7|bB~>>kL8?V2D8hoT67)WLTLr1Rg^r}f;D4|6{Z|@C6H!$-Mn#iGBh?Ehn zz^LL39o${y(q}Sf|FZo{IgQf6ZRL7V>0M zj0YmdW}Y-{!U59!vzN~GwoRag$LSHL1VkBp?Q->NDxBkxL->rUW9Y1EKgjp`!HPsz zSbuxk`rCh7e_N?PMAq^37lZos3H9s0W22AO-`j~lJ5JdD=^R669bf Date: Mon, 5 Jan 2026 12:17:32 +0100 Subject: [PATCH 3/3] tests: Add visual/edittext/edittext_device_transform_small_rotation test --- .../output.expected.png | Bin 0 -> 388 bytes .../output.txt | 0 .../test.as | 35 ++++++++++++++++++ .../test.swf | Bin 0 -> 564 bytes .../test.toml | 8 ++++ 5 files changed, 43 insertions(+) create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/output.expected.png create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/output.txt create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/test.as create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/test.swf create mode 100644 tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/test.toml diff --git a/tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/output.expected.png b/tests/tests/swfs/visual/edittext/edittext_device_transform_small_rotation/output.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..1aec40807c5a5df41e930a861abbd523949cba8e GIT binary patch literal 388 zcmeAS@N?(olHy`uVBq!ia0vp^DImeK@{Ea{HEjtmSN z`?>!lvI6-E$sR$z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBXbzL7 zi(^Q|t+zJ=yIKu+94?03`9JNkSV+^6XLsH^O7QDnN=r>^yH!%b>cGO%(ZC=mpul9b z`}4Q>b?p9UdFO@yjoT!ZGF^P{p%X$t873Ep29Az6d7jn$p?Bwh|GM(OpvSj=?n=En zjEqVO4lF?F6MnVL&P(R*ny3ooLrhfvx*_<#Y6np4skD+p(cgE!Y-9FINA6REn%A(S zj{o}mb@!1>$++ZK`{Zh;><+LNsJgjTHyUrRl#XOlQgB{(e|fER*ZuDJ4rGf;)jwpE mWWNrMR)V|By!pPF`QDq% zBUM~^L|;lmeg)#m$&<VMK_{j3AOTqB`8nn28%I@bn{&V~f|C482CJ%}Sol;Cfr+qsjP9*5}uqW{dTB zo^^Q(cO2HXEm&yytj5`G5ibx0s}E}cYsaxgmepdSh{N(dUgM7EqVD-N^K)L?^HHxg z?lyhzzH9H{AQqv)I(23jJeT)K!sGCnD^jLAbsBJ7R}@T-aIMqjgOa!Huw2{eVkpBv znyf@dE_BZn^C?}0E{Wecx?3vr5eq-zmUho=-G)DdA+Da1z! zN8-zSIMVM@+$u^|(ve<`W0yCENoe0Lo-ohn(m&z^PQ?k7>bJ~auYZ1u6Sxp3@b$rC z^WoZ?;(