Skip to content
Permalink
Browse files
Percentage-based translations don't work with SVG <text>
https://bugs.webkit.org/show_bug.cgi?id=245122
<rdar://99854408>

Reviewed by Myles C. Maxfield.

The two main issues are:
- Stale SVGTextElement::animatedLocalTransform() function:
Historically, all SVG elements have had the same animatedLocalTransform function, see: f8cc29f
This looks like an artifact of when SVGTextElement did not inherit from the common SVGGraphicsElement class, where we had to add the same function twice.
Removing this code puts it in-line with SVGGraphicsElement::animatedLocalTransform() which does take in account the reference box rect (for percentage based transforms) and transform-origin.

- We also need to compute transform at the end of RenderSVGText::layout, to avoid computing with the wrong bounds (which may happen if the font hasn't loaded yet).

Rebaseline tests resulting from these changes (mainly minor differences in dimensions that match other browsers).

Test: imported/w3c/web-platform-tests/css/css-transforms/transform-box/view-box-mutation-002.html

* LayoutTests/TestExpectations:
* LayoutTests/platform/gtk/svg/W3C-SVG-1.1/types-basicDOM-01-b-expected.txt:
* LayoutTests/platform/gtk/svg/batik/text/smallFonts-expected.txt:
* LayoutTests/platform/gtk/svg/batik/text/textFeatures-expected.txt:
* LayoutTests/platform/gtk/svg/text/select-textLength-spacing-squeeze-2-expected.txt:
* LayoutTests/platform/ios/svg/W3C-SVG-1.1-SE/types-dom-01-b-expected.txt:
* LayoutTests/platform/ios/svg/W3C-SVG-1.1/types-basicDOM-01-b-expected.txt:
* LayoutTests/platform/ios/svg/batik/text/textFeatures-expected.txt:
* LayoutTests/platform/ios/svg/text/append-text-node-to-tspan-expected.txt:
* LayoutTests/platform/ios/svg/text/modify-text-node-in-tspan-expected.txt:
* LayoutTests/platform/ios/svg/text/remove-text-node-from-tspan-expected.txt:
* LayoutTests/platform/ios/svg/text/scaled-font-expected.txt:
* LayoutTests/platform/ios/svg/text/scaling-font-with-geometric-precision-expected.txt:
* LayoutTests/platform/mac/svg/W3C-SVG-1.1/types-basicDOM-01-b-expected.txt:
* LayoutTests/platform/mac/svg/batik/text/smallFonts-expected.txt:
* LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.txt:
* LayoutTests/platform/mac/svg/text/scaling-font-with-geometric-precision-expected.txt:
* Source/WebCore/svg/SVGTextElement.cpp:
(WebCore::SVGTextElement::animatedLocalTransform const): Deleted.
* Source/WebCore/svg/SVGTextElement.h:
* Source/WebCore/rendering/svg/RenderSVGText.cpp:
(WebCore::RenderSVGText::layout):

Canonical link: https://commits.webkit.org/254656@main
  • Loading branch information
nt1m committed Sep 20, 2022
1 parent 662e9f6 commit b87209ee89e8e4595ec4f5409906b368310321cd
Show file tree
Hide file tree
Showing 20 changed files with 180 additions and 207 deletions.
@@ -4177,7 +4177,6 @@ webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/scale-tra
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-background-007.html [ ImageOnlyFailure ]
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-background-008.html [ ImageOnlyFailure ]
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-box/fill-box-002.html [ ImageOnlyFailure ]
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-box/view-box-mutation-002.html [ ImageOnlyFailure ]
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-fixed-bg-002.html [ ImageOnlyFailure ]
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-fixed-bg-004.html [ ImageOnlyFailure ]
webkit.org/b/230080 imported/w3c/web-platform-tests/css/css-transforms/transform-fixed-bg-005.html [ ImageOnlyFailure ]
@@ -5,12 +5,12 @@ layer at (0,0) size 480x360
RenderSVGContainer {g} at (10,8) size 365x295
RenderSVGContainer {g} at (10,8) size 365x295
RenderSVGContainer {g} at (17,8) size 358x156 [transform={m=((1.00,0.00)(0.00,1.00)) t=(70.00,-60.00)}]
RenderSVGText {text} at (30,131) size 343x24 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 343x23
chunk 1 text run 1 at (30.00,150.00) startOffset 0 endOffset 37 width 342.78: "Rotated Text for testing SVGLocatable"
RenderSVGText {text} at (100,111) size 307x24 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 307x23
chunk 1 text run 1 at (100.00,130.00) startOffset 0 endOffset 35 width 306.35: "Some other text with id 'otherText'"
RenderSVGText {text} at (30,131) size 342x24 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 342x23
chunk 1 text run 1 at (30.00,150.00) startOffset 0 endOffset 37 width 341.78: "Rotated Text for testing SVGLocatable"
RenderSVGText {text} at (100,111) size 302x24 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 302x23
chunk 1 text run 1 at (100.00,130.00) startOffset 0 endOffset 35 width 301.78: "Some other text with id 'otherText'"
RenderSVGViewportContainer {svg} at (275,45) size 100x100
RenderSVGEllipse {circle} at (275,45) size 100x100 [fill={[type=SOLID] [color=#FF0000]}] [cx=0.00] [cy=0.00] [r=50.00]
RenderSVGText {text} at (10,189) size 280x14 contains 1 chunk(s)
@@ -134,7 +134,7 @@ layer at (0,0) size 450x500
[filter="blur"] RenderSVGResourceFilter {filter} at (0,-1.60) size 4x2
RenderSVGInlineText {#text} at (0,0) size 3x1
[filter="blur"] RenderSVGResourceFilter {filter} at (0,-1.60) size 4x2
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 2.63: "Shadow"
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 2.58: "Shadow"
RenderSVGText {text} at (0,-1) size 3x2 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 3x1
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 2.58: "Shadow"
@@ -145,11 +145,11 @@ layer at (0,0) size 450x500
RenderSVGInlineText {#text} at (0,0) size 154x17
chunk 1 text run 1 at (45.00,475.00) startOffset 0 endOffset 25 width 154.00: "filtered and transformed."
RenderSVGContainer {g} at (171,389) size 279x100 [transform={m=((1.00,0.00)(0.00,1.00)) t=(250.00,475.00)}]
RenderSVGText {text} at (0,-37) size 132x46 contains 1 chunk(s)
RenderSVGText {text} at (0,-36) size 129x45 contains 1 chunk(s)
[filter="blur"] RenderSVGResourceFilter {filter} at (0,-80) size 200x100
RenderSVGInlineText {#text} at (0,0) size 132x45
RenderSVGInlineText {#text} at (0,0) size 129x45
[filter="blur"] RenderSVGResourceFilter {filter} at (0,-80) size 200x100
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 131.58: "Shadow"
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 129.00: "Shadow"
RenderSVGText {text} at (0,-36) size 129x45 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 129x45
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 129.00: "Shadow"
@@ -2,13 +2,13 @@ layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
RenderSVGRoot {svg} at (0,4) size 308x88
RenderSVGContainer {g} at (0,4) size 307x88
RenderSVGContainer {g} at (0,4) size 302x88
RenderSVGPath {svg:line} at (151,4) size 6x57 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#000000]}] [x1=30.71] [y1=0.95] [x2=30.71] [y2=12.17]
RenderSVGPath {svg:line} at (204,4) size 6x57 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#000000]}] [x1=41.44] [y1=0.95] [x2=41.44] [y2=12.17]
RenderSVGRect {svg:rect} at (153,4) size 55x57 [fill={[type=SOLID] [color=#FF0000] [opacity=0.40]}] [x=30.71] [y=0.95] [width=10.73] [height=11.17]
RenderSVGText {svg:text} at (0,27) size 123x10 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 123x9
chunk 1 text run 1 at (0.00,35.00) startOffset 0 endOffset 40 width 122.40: "Expected 'Sq' to be selected, got: ' Sq'"
RenderSVGText {svg:text} at (0,27) size 121x10 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 121x9
chunk 1 text run 1 at (0.00,35.00) startOffset 0 endOffset 40 width 120.40: "Expected 'Sq' to be selected, got: ' Sq'"
RenderSVGText {text} at (10,0) size 52x13 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 52x12
chunk 1 text run 1 at (10.00,10.00) startOffset 0 endOffset 1 width 6.20: "T"
@@ -6,11 +6,11 @@ layer at (0,0) size 480x360
RenderSVGContainer {g} at (10,9) size 365x294
RenderSVGContainer {g} at (10,9) size 365x294
RenderSVGContainer {g} at (17,9) size 358x155 [transform={m=((1.00,0.00)(0.00,1.00)) t=(70.00,-60.00)}]
RenderSVGText {text} at (30,133) size 343x22 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 343x21
RenderSVGText {text} at (30,134) size 343x20 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 343x20
chunk 1 text run 1 at (30.00,150.00) startOffset 0 endOffset 37 width 342.40: "Rotated Text for testing SVGLocatable"
RenderSVGText {text} at (100,113) size 302x22 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 302x21
RenderSVGText {text} at (100,114) size 302x20 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 302x20
chunk 1 text run 1 at (100.00,130.00) startOffset 0 endOffset 35 width 301.10: "Some other text with id 'otherText'"
RenderSVGViewportContainer {svg} at (275,45) size 100x100
RenderSVGEllipse {circle} at (275,45) size 100x100 [fill={[type=SOLID] [color=#0000FF]}] [cx=0.00] [cy=0.00] [r=50.00]
@@ -5,11 +5,11 @@ layer at (0,0) size 480x360
RenderSVGContainer {g} at (10,8) size 365x295
RenderSVGContainer {g} at (10,8) size 365x295
RenderSVGContainer {g} at (16,8) size 359x156 [transform={m=((1.00,0.00)(0.00,1.00)) t=(70.00,-60.00)}]
RenderSVGText {text} at (30,130) size 343x25 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 343x25
RenderSVGText {text} at (30,131) size 343x24 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 343x24
chunk 1 text run 1 at (30.00,150.00) startOffset 0 endOffset 37 width 342.41: "Rotated Text for testing SVGLocatable"
RenderSVGText {text} at (100,110) size 302x25 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 302x25
RenderSVGText {text} at (100,111) size 302x24 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 302x24
chunk 1 text run 1 at (100.00,130.00) startOffset 0 endOffset 35 width 301.10: "Some other text with id 'otherText'"
RenderSVGViewportContainer {svg} at (275,45) size 100x100
RenderSVGEllipse {circle} at (275,45) size 100x100 [fill={[type=SOLID] [color=#FF0000]}] [cx=0.00] [cy=0.00] [r=50.00]
@@ -145,11 +145,11 @@ layer at (0,0) size 450x500
RenderSVGInlineText {#text} at (0,0) size 149x17
chunk 1 text run 1 at (45.00,475.00) startOffset 0 endOffset 25 width 148.69: "filtered and transformed."
RenderSVGContainer {g} at (171,389) size 279x100 [transform={m=((1.00,0.00)(0.00,1.00)) t=(250.00,475.00)}]
RenderSVGText {text} at (0,-36) size 129x46 contains 1 chunk(s)
RenderSVGText {text} at (0,-36) size 129x45 contains 1 chunk(s)
[filter="blur"] RenderSVGResourceFilter {filter} at (0,-80) size 200x100
RenderSVGInlineText {#text} at (0,0) size 129x45
[filter="blur"] RenderSVGResourceFilter {filter} at (0,-80) size 200x100
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 128.86: "Shadow"
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 128.89: "Shadow"
RenderSVGText {text} at (0,-36) size 129x45 contains 1 chunk(s)
RenderSVGInlineText {#text} at (0,0) size 129x45
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 6 width 128.89: "Shadow"
@@ -4,7 +4,7 @@ layer at (0,0) size 800x8
RenderBlock {HTML} at (0,0) size 800x8
RenderBody {BODY} at (8,8) size 784x0
layer at (0,0) size 800x600
RenderSVGRoot {svg} at (10,62) size 317x375
RenderSVGRoot {svg} at (10,60) size 317x380
RenderSVGText {text} at (0,1) size 32x38 contains 1 chunk(s)
RenderSVGTSpan {tspan} at (0,0) size 29x14
RenderSVGInlineText {#text} at (0,0) size 16x14
@@ -4,7 +4,7 @@ layer at (0,0) size 800x8
RenderBlock {HTML} at (0,0) size 800x8
RenderBody {BODY} at (8,8) size 784x0
layer at (0,0) size 800x600
RenderSVGRoot {svg} at (10,62) size 317x375
RenderSVGRoot {svg} at (10,60) size 317x380
RenderSVGText {text} at (0,1) size 32x38 contains 1 chunk(s)
RenderSVGTSpan {tspan} at (0,0) size 29x14
RenderSVGInlineText {#text} at (0,0) size 29x14
@@ -4,7 +4,7 @@ layer at (0,0) size 800x8
RenderBlock {HTML} at (0,0) size 800x8
RenderBody {BODY} at (8,8) size 784x0
layer at (0,0) size 800x600
RenderSVGRoot {svg} at (10,182) size 317x255
RenderSVGRoot {svg} at (10,180) size 317x260
RenderSVGText {text} at (0,13) size 32x26 contains 1 chunk(s)
RenderSVGTSpan {tspan} at (0,0) size 0x0
RenderSVGInlineText {#text} at (0,0) size 0x0
@@ -13,7 +13,7 @@ layer at (0,0) size 800x600
chunk 1 text run 1 at (0.00,24.00) startOffset 0 endOffset 4 width 28.69: "PASS"
RenderSVGInlineText {#text} at (28,0) size 3x14
chunk 1 text run 1 at (28.69,24.00) startOffset 0 endOffset 1 width 3.00: " "
RenderSVGTSpan {tspan} at (0,0) size 29x15
RenderSVGInlineText {#text} at (0,11) size 29x14
RenderSVGTSpan {tspan} at (0,0) size 29x14
RenderSVGInlineText {#text} at (0,12) size 29x14
chunk 1 text run 1 at (0.00,36.00) startOffset 0 endOffset 4 width 28.69: "PASS"
RenderSVGInlineText {#text} at (0,0) size 0x0
@@ -1,8 +1,8 @@
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
RenderSVGRoot {svg} at (0,188) size 494x327
RenderSVGContainer {g} at (0,188) size 494x327
RenderSVGRoot {svg} at (0,188) size 493x332
RenderSVGContainer {g} at (0,188) size 493x332
RenderSVGContainer {g} at (0,188) size 493x133 [transform={m=((1.00,0.00)(0.00,1.00)) t=(0.00,70.00)}]
RenderSVGText {text} at (0,-39) size 178x49 contains 1 chunk(s)
RenderSVGTSpan {tspan} at (0,0) size 10x16
@@ -44,44 +44,44 @@ layer at (0,0) size 800x600
RenderSVGInlineText {#text} at (146,0) size 31x48
chunk 1 text run 1 at (146.54,0.00) startOffset 0 endOffset 1 width 30.81: "A"
RenderSVGInlineText {#text} at (0,0) size 0x0
RenderSVGContainer {g} at (0,382) size 494x133 [transform={m=((1.00,0.00)(0.00,1.00)) t=(0.00,140.00)}]
RenderSVGText {text} at (0,-4) size 18x5 contains 1 chunk(s)
RenderSVGContainer {g} at (0,378) size 488x142 [transform={m=((1.00,0.00)(0.00,1.00)) t=(0.00,140.00)}]
RenderSVGText {text} at (0,-4) size 18x6 contains 1 chunk(s)
RenderSVGTSpan {tspan} at (0,0) size 1x3
RenderSVGInlineText {#text} at (0,2) size 1x2
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 1 width 0.96: "A"
chunk 1 text run 1 at (0.00,0.00) startOffset 0 endOffset 1 width 0.91: "A"
RenderSVGInlineText {#text} at (0,2) size 1x2
chunk 1 text run 1 at (0.96,0.00) startOffset 0 endOffset 1 width 0.33: " "
chunk 1 text run 1 at (0.91,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 2x3
RenderSVGInlineText {#text} at (1,2) size 2x2
chunk 1 text run 1 at (1.29,0.00) startOffset 0 endOffset 1 width 1.16: "A"
chunk 1 text run 1 at (1.22,0.00) startOffset 0 endOffset 1 width 1.17: "A"
RenderSVGInlineText {#text} at (2,2) size 1x2
chunk 1 text run 1 at (2.45,0.00) startOffset 0 endOffset 1 width 0.33: " "
chunk 1 text run 1 at (2.39,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 3x3
RenderSVGInlineText {#text} at (2,2) size 2x3
chunk 1 text run 1 at (2.78,0.00) startOffset 0 endOffset 1 width 1.35: "A"
chunk 1 text run 1 at (2.71,0.00) startOffset 0 endOffset 1 width 1.30: "A"
RenderSVGInlineText {#text} at (4,2) size 1x2
chunk 1 text run 1 at (4.14,0.00) startOffset 0 endOffset 1 width 0.33: " "
chunk 1 text run 1 at (4.01,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 3x4
RenderSVGInlineText {#text} at (4,1) size 2x3
chunk 1 text run 1 at (4.47,0.00) startOffset 0 endOffset 1 width 1.73: "A"
chunk 1 text run 1 at (4.32,0.00) startOffset 0 endOffset 1 width 1.69: "A"
RenderSVGInlineText {#text} at (6,2) size 1x2
chunk 1 text run 1 at (6.20,0.00) startOffset 0 endOffset 1 width 0.33: " "
chunk 1 text run 1 at (6.01,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 3x4
RenderSVGInlineText {#text} at (6,1) size 3x4
chunk 1 text run 1 at (6.53,0.00) startOffset 0 endOffset 1 width 2.12: "A"
chunk 1 text run 1 at (6.33,0.00) startOffset 0 endOffset 1 width 2.08: "A"
RenderSVGInlineText {#text} at (8,2) size 1x2
chunk 1 text run 1 at (8.65,0.00) startOffset 0 endOffset 1 width 0.33: " "
chunk 1 text run 1 at (8.41,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 4x5
RenderSVGInlineText {#text} at (8,0) size 3x4
chunk 1 text run 1 at (8.98,0.00) startOffset 0 endOffset 1 width 2.31: "A"
chunk 1 text run 1 at (8.72,0.00) startOffset 0 endOffset 1 width 2.34: "A"
RenderSVGInlineText {#text} at (11,2) size 1x2
chunk 1 text run 1 at (11.30,0.00) startOffset 0 endOffset 1 width 0.33: " "
chunk 1 text run 1 at (11.06,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 4x5
RenderSVGInlineText {#text} at (11,0) size 3x5
chunk 1 text run 1 at (11.63,0.00) startOffset 0 endOffset 1 width 2.69: "A"
chunk 1 text run 1 at (11.38,0.00) startOffset 0 endOffset 1 width 2.73: "A"
RenderSVGInlineText {#text} at (14,2) size 1x2
chunk 1 text run 1 at (14.32,0.00) startOffset 0 endOffset 1 width 0.33: " "
RenderSVGTSpan {tspan} at (0,0) size 4x5
RenderSVGInlineText {#text} at (14,0) size 4x5
chunk 1 text run 1 at (14.65,0.00) startOffset 0 endOffset 1 width 3.08: "A"
chunk 1 text run 1 at (14.11,0.00) startOffset 0 endOffset 1 width 0.31: " "
RenderSVGTSpan {tspan} at (0,0) size 4x6
RenderSVGInlineText {#text} at (14,0) size 4x6
chunk 1 text run 1 at (14.42,0.00) startOffset 0 endOffset 1 width 3.12: "A"
RenderSVGInlineText {#text} at (0,0) size 0x0

0 comments on commit b87209e

Please sign in to comment.