Outer <SVG> element should snap to pixel coordinates

NEW
Unassigned

Status

()

Core
SVG
7 years ago
5 months ago

People

(Reporter: jorendorff, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(4 attachments, 2 obsolete attachments)

(Reporter)

Description

7 years ago
<!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

Comment 1

6 years ago
Created attachment 612774 [details]
Demo of the subpixel problem

Comment 2

6 years ago
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.

Updated

6 years ago
Attachment #612774 - Attachment mime type: text/plain → text/html

Comment 3

6 years ago
Created attachment 612899 [details]
Demo of the subpixel problem & workaround
Attachment #612774 - Attachment is obsolete: true

Updated

6 years ago
Attachment #612899 - Attachment mime type: text/plain → text/html
Created attachment 8636669 [details]
original testcase (with typo in <title>, oops)

(Here's the testcase from comment 0, with a descriptive title added, FWIW. I still see this bug in current Nightly.)
Created attachment 8636671 [details]
original testcase
Attachment #8636669 - Attachment is obsolete: true
Attachment #8636669 - Attachment description: original testcase → original testcase (with typo in <title>, oops)
Created attachment 8636674 [details]
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

Comment 7

2 years ago
Yes, this prevents me from doing a design that is composed from SVG blocks on Firefox.

Comment 8

a year ago
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?

Comment 9

8 months ago
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.
Created attachment 8856714 [details]
screenshot of bug on GitHub

(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.)

Comment 12

8 months ago
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.

Comment 13

8 months ago
(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!
Comment hidden (advocacy)
Comment hidden (obsolete)
Comment hidden (advocacy)
You need to log in before you can comment on or make changes to this bug.