Closed Bug 608812 Opened 14 years ago Closed 5 years ago

Outer <SVG> element should snap to pixel coordinates

Categories

(Core :: SVG, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla68
Webcompat Priority ?
Tracking Status
firefox68 --- fixed

People

(Reporter: jorendorff, Assigned: violet.bugreport)

References

Details

(Whiteboard: [webcompat])

Attachments

(8 files, 2 obsolete files)

<!DOCTYPE HTML>
<div style="height: 0.43px"></div>
<svg width="10" height="10" style="display: block;">
<rect style="fill: none; stroke: #000;" x="1.5" y="1.5" width="7" height="7" />
</svg>

Remove the div, and the lines in the SVG are crisp.

With the div, the horizontal lines are blurry, because we're rendering the SVG at subpixel offset from the top of the page.

Instead, perhaps the SVG should snap to pixels so that if the content of the SVG puts edges on integer coordinates, they actually get drawn that way.

<roc> where we calculate the viewport box for an nsSVGOuterSVGFrame, we can snap it to pixels there


The issue seems to affect <object> as well.
Summary: SVG elements should snap to pixel coordinates → Outer <SVG> element should snap to pixel coordinates
Version: Other Branch → Trunk
Attached file Demo of the subpixel problem (obsolete) —
I have found that IE 9 and FF (13) still have this issue. There is a work around I read about that involved using getScreenCTM() to get the fraction of a pixel the root <svg> element is off by. Using relative positioning left/top you can shift the <svg> element up and left a bit to align SVG to the whole pixel boundaries.
Attachment #612774 - Attachment mime type: text/plain → text/html
Attachment #612774 - Attachment is obsolete: true
Attachment #612899 - Attachment mime type: text/plain → text/html
(Here's the testcase from comment 0, with a descriptive title added, FWIW. I still see this bug in current Nightly.)
Attached file original testcase
Attachment #8636669 - Attachment is obsolete: true
Attachment #8636669 - Attachment description: original testcase → original testcase (with typo in <title>, oops)
Attached file testcase 3
Here's another testcase from a www-svg thread (simplified slightly to not use <object>). May depend on exact fonts/font-sizes, too, since it's relying on the <h1> to give our SVG the fractional pixel-offset.
https://lists.w3.org/Archives/Public/www-svg/2015Jul/0029.html
Yes, this prevents me from doing a design that is composed from SVG blocks on Firefox.
It should be mentioned that the same problem occurs on Chrome at least.  I'd thought this wasn't true for awhile, but is certainly true now (v.51)

Content to the left of or above an <svg>, say text, will most likely cause the SVG block to start on a non-pixel boundary.  Thus making moot any attempts to draw fine lines.

In a sense, the browsers are treating <svg> blocks as ordinary content, positioning them ad-hoc, without realizing these blocks are very special in one respect.  <svg> content _itself_ has content, and which has a unique requirement.  That requirement is pixel-alignment for the canvas, which then becomes a requirement for the <svg> block has a whole.

It would be quite useful for UAs to understand <svg> blocks should have pixel-aligned top left corners.  Without some kind of alignment guarantee it would seem browsers really don't get the point of SVG.  The ability to control presentation using HTML/CSS alone becomes a lost cause given this problem.

As it is, with browsers being passive-aggressive for most things SVG, I have had to jam in some Javascript to, first, detect <svg> on non-pixel boundaries, and then second, adjust <div>s containing those <svg>s by adding a smidgeon to the divs' padding to round up to unit pixels.  Of course that then must be re-executed on resizing, reflow, changes to content left/above any <svg>, etc.  Equivalent to saying the only workaround is nigh unworkable.

SVG blocks *should* have top/left corners on pixel boundaries.  Anything less is an(other) admission that browsers have not understood the point of SVG.  Browsers should not be limited to text and JPEG's, okay?
I just ran into this with a small rectangular icon that got very blurry when positioning it since it was being pushed down by rational pixels due to em-based line heights. Are there any plans on fixing this? Firefox appears to be the only browser that has this issue; even Internet Explorer aligns SVGs properly on full pixels.
I hit this pretty frequently on GitHub, too, e.g. on the smiley emoticon menu at the top-right of each comment (if you're logged in) at https://github.com/w3c/fxtf-drafts/issues/126 -- those often have a flattened top-head for me, due to this bug. 

(This fixes itself if you add "will-change: transform" to the "octicon" class, or any affected <svg> element -- that forces it to be a layer, which makes it pixel-snapped as a side effect.  That's overkill and we don't actually want to suggest that as a fix, because layers are expensive.)

I'd like to see us fix this. Based on the roc quote in comment 0, it sounds like it may not be too difficult.
(Here's a screenshot of what this looks like at the top right of some GitHub comments.  This is taken on a desktop machine running Ubuntu 16.04.

Note for people testing using retina Mac displays: I wouldn't be surprised if this is harder to trigger there, due to higher physical pixel density.)
Another short test case for this bug with simple small SVG:

Screenshot: http://simplesvg.com/test/blur-bug.png
Test page: http://simplesvg.com/test/blur-bug.html

Left edge of SVG is blurred. Workaround for issue is to add style="transform: rotate(360deg)", shown in second sample on that page.
(In reply to CyberAlien from comment #12)
> Workaround for issue is to add style="transform: rotate(360deg)",
> shown in second sample on that page.

Uhh, that’s nice. That will be a lot easier than listening to resize events and checking the bounding box to see whether the element is positioned on a half-pixel… ^^" – Thanks for that!
See Also: → 1474141

What is the status of this bug? It’s still marked as new. Can it be closed because nothing with regards to it is going to be changed or will there be a fix?

Possible workarounds like setting "transform: translateZ(0)" or "will-change: transform" are hacks to workaround this problem. The often suggested "shape-rendering: crispEdges" makes matters worse because it allows the browser to turn off anti-aliasing for the SVG element. It’s desirable to have both anti-aliasing and alignment with the pixel grid.

Reduced test case: https://codepen.io/kleinfreund/pen/MLOWeX
Expected behavior: Both SVGs are crisp
Actual behavior: The first SVG is blurry

Reproducable in Firefox. Works fine in Chrome.

(In reply to Philipp Rudloff from comment #23)

It might not mean much, but on my system (Nightly, Linux, WebRender), the two SVGs look the same. The first one is blurry if I disable WebRender.

(In reply to Laurentiu Nicola from comment #24)

(In reply to Philipp Rudloff from comment #23)

It might not mean much, but on my system (Nightly, Linux, WebRender), the two SVGs look the same. The first one is blurry if I disable WebRender.

I see that bug on OSX. It depends on font. If text before SVG ends at pixel edge, it will look fine. Try changing text or font.

(In reply to CyberAlien from comment #25)

I see that bug on OSX. It depends on font. If text before SVG ends at pixel edge, it will look fine. Try changing text or font.

I can't manage to. https://bugzilla.mozilla.org/attachment.cgi?id=612899 is also fine for me (only with WebRender).

But of course, it might be platform-dependent. I assume you're also testing with WR and a recent Nightly?

(In reply to Laurentiu Nicola from comment #26)

(In reply to CyberAlien from comment #25)

I see that bug on OSX. It depends on font. If text before SVG ends at pixel edge, it will look fine. Try changing text or font.

I can't manage to. https://bugzilla.mozilla.org/attachment.cgi?id=612899 is also fine for me (only with WebRender).

But of course, it might be platform-dependent. I assume you're also testing with WR and a recent Nightly?

Actually no. Bug disappeared after enabling WR. So ignore my previous message, WR does make a difference.

Flags: webcompat?
Whiteboard: [webcompat]

Migrating Webcompat whiteboard priorities to project flags. See bug 1547409.

Webcompat Priority: --- → ?

See bug 1547409. Migrating whiteboard priority tags to program flags.

Assignee: nobody → violet.bugreport
Status: NEW → ASSIGNED
Attachment #9061621 - Attachment description: Bug 608812 - child-only transform should be moved out of anon child. → Bug 608812 - Should snap subpixel value for outer svg and anon child

The comment in nsDisplayTransform::GetTransformForRendering() clearly
says that |aOutOrigin| should return the same offset as GetTransform().

GetTransform() will pass the offset to GetResultingTransformMatrix()
which will round it in many cases to avoid subpixel blurry rendering.

But GetTransformForRendering() doesn't take this rounding into account,
thus contradicting the intent described by the comment.

This rounding is important to keep subpixel behavior consistent with
or without webrender enabled. Currently, SVG will be rendered blurry
in some cases if it's at a subpixel position. After fixing the problem
in non-webrender case, the strange blur still occurs in webrender case.
It turns out to be caused by this inconsistency.

Pushed by violet.bugreport@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/3dddcde1fde6
Should snap subpixel value for outer svg and anon child r=longsonr
https://hg.mozilla.org/integration/autoland/rev/75abef5719a7
Remove a bunch of WPT meta files that are no longer valid r=longsonr
https://hg.mozilla.org/integration/autoland/rev/5a252b843ac8
GetTransformForRendering() should have the same rounding behavior r=emilio
Blocks: 1533292
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: