Open Bug 1890198 Opened 6 months ago Updated 6 months ago

getScreenCTM returns different answers from other browsers, in the presence of padding-left or padding-top and a rotation transform

Categories

(Core :: SVG, defect)

defect

Tracking

()

People

(Reporter: dholbert, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(5 files)

STR:

  1. Load attached testcase.
  2. Look at the red dot.
  3. (for more details) look at the text that displays the CTM and the transformed point's coordinates.

EXPECTED RESULTS:

  • The textual display of the CTM should show 100, 100 as the last two components.
  • The textual display of the transformed point should show 50, 50
  • Visually, the red dot should be inside the lime square.

ACTUAL RESULTS:

  • The textual display of the CTM shows 124, 100 as the last two components. (offset by 24 from what we expect)
  • The textual display of the transformed point shows 74, 50 (offset by 24 from what we expect)
  • Visually, the red dot is offset 24px to the left from its expected position in the lime square.

This testcase uses padding-top and shows the same breakage described above, except in the vertical axis (the red dot ends up being drawn 24px higher than expected, and the coordinate/CTM have their vertical components off by 24px as well).

Chrome gives EXPECTED RESULTS here.

(WebKit (epiphany) doesn't quite get EXPECTED RESULTS; they show a different bug from us. They report the CTM as 1, 0, 0, 1, 100, 100 with positive 1 instead of negative 1 in the 1st and 4th components, so they end up drawing the red dot offscreen (at point -50, -50 in SVG coordinates).)

Why is 100, 100 as the last two components correct? What happened to the padding?

Flags: needinfo?(dholbert)

The padding on the left becomes padding on the right once rotated and therefore has no effect, right?

(In reply to Robert Longson [:longsonr] from comment #4)

The padding on the left becomes padding on the right once rotated and therefore has no effect, right?

I think that's basically right, yeah. You can mess with the testcase to add arbitrary amounts of padding-left, without impacting the rendering of the SVG (the blue circle). That's because -- with the default transform-origin and transform-box, combined with the 180deg rotation -- we rotate about the center of the SVG's border-box. So the padding ends up on the right side in the final visualization, and the visible SVG content always ends up in the same spot, perfectly flush with the left side of the viewport.

Since the SVG content always ends up in the same spot in this testcase (regardless of the amount of padding-left), that means getScreenCTM should also always produce the same matrix, with 100 100 at the end (regardless of padding-left), in order to reliably produce a transform that can interconvert between the outer coordinate space to the SVG-internal coordinate space.

Flags: needinfo?(dholbert)

Here's another testcase with a different transform-origin so that the rotation does actually move the SVG such that the padding does impact the CTM.

Chrome still seems correct to me here (representing the offset , and Firefox seems incorrect.

In particular:

  1. The padding on the left side shifts over the 100%,100% transform-origin by exactly the size of the padding-left amount.
  2. When we rotate around that 100%,100% point, the content ends up all on the other side of the transform-origin, so the content is still shifted by exactly the size of the padding-left amount.
  3. The padding ends up being drawn on the right side, where it doesn't directly impact the geometry anymore, but the impact that it had via (1) + (2) does still make it effectively a horizontal translation in the CTM by precisely the amount of the padding.
Attachment #9395619 - Attachment description: testcase 3: with `tran → testcase 3: with `transform-origin: 100% 100%`

If I modify testcase 1 to use transform-box: content-box (so that we rotate the content-box about its center, with the 12px padding-left essentially being an external offset), then we're consistent with Chrome, and it seems clearly correct for the 12px to be reflected as an offset in the CTM (since it shows up in the actual visual positioning).

Given that we double-apply the padding in testcase 1 and 2 (with 12px of padding yielding final values that are off by 24px), I wonder if we're trying to cancel out the padding but we're doing addition instead of subtraction, or something to that effect?

Attachment #9395622 - Attachment description: testcase 4: similar to 1 but now with `transform-box: content-box` → testcase 4: similar to 1 but now with `transform-box: content-box` [no bug here]

We ignored padding for years and then implemented a naive version that doesn't deal with transforms: https://searchfox.org/mozilla-central/rev/cfcb29f7705d0601ef151dea87c534637c7da936/dom/svg/SVGContentUtils.cpp#533 that's better than nothing but it only looks at the top and left padding. If you apply a 180 degree rotation it should look at the bottom and right padding instead for instance.

(In reply to Robert Longson [:longsonr] from comment #8)

If you apply a 180 degree rotation it should look at the bottom and right padding instead for instance.

We actually already get the answer correct if you use padding-right, though, FWIW -- here's a version of testcase 1 modified to use padding-right.

(Visually, the padding-right: 12px ends up being an offset from the left edge of the page, due to the 180 degree rotation; and we represent that correctly as a +12px offset in our CTM, as shown by the correspondence between the green box and red dot here, and by our agreement with Chrome on this testcase.)

Not sure if we get this right just due to luck (and/or things working out "just right" under default transform-origin/transform-box values), vs. because we properly/intentionally account for the padding-right somewhere.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: