HiDPI (dppx > 1.1) scales -moz-image-region incorrectly

RESOLVED INVALID

Status

()

Core
Layout
RESOLVED INVALID
a year ago
a year ago

People

(Reporter: jaws, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

STR:
In about:config set layout.devPixelsPerPx is 1.5 (ensure HiDPI rendering)
Save the attached SVG file locally
Open the browser toolbox's Inspector
Select the Home button on the toolbar (#home-button)
On the right-side, switch to the Computed View
See that the button has a computed width of 32x28
Switch to the Rules view
Add the following two rules to the 'element' selector:
  list-style-image: url(<path-to-locally-saved-svg-file>);
  -moz-image-region: rect(0, 18px, 18px, 0);
Hover your mouse over the #home-button in the Tree view to invalidate the rendering
Switch to the Computed View

Expected results:
The width of the button should still be 32x28

Actual results:
The width of the button is 31.333x28
Created attachment 8813776 [details]
1f923.svg
Daniel, do you know who could help look in to this? This showed up in the new Theme work we're doing in bug 1306671.
Component: WebExtensions: General → Layout
Flags: needinfo?(dholbert)
Product: Toolkit → Core
A few notes:
 - For me (on Linux), the button is shown as 30px tall (not 28px tall).  My results do match yours for the width, though (32 and then 31.3333).
 - To trigger this behavior, technically you don't need to bother downloading the SVG or setting "list-style-image".  Just the "-moz-image-region: rect(0, 18px, 18px, 0)" style on is own is sufficient to trigger the 31.3333 value.
 - On my machine, this seems to happen for *any* fractional HiDPI setting, but not for any whole-number HiDPI settings:
  layout.devPixelsPerPx  Reported width
  =====================  ==============
                  unset  32
                  1.25   31.6
                  1.5    31.3333
                  2      32
                  2.9    31.4
                  3      32
                  3.1    31.9
Thank you, I can confirm that I am running with 150% display scaling. The 30px tall vs 28px tall is just a minor difference in the theme between Linux and Windows I believe.
OK -- so these styles are actually correct (i.e. they're accurate representations of the width).

The problem here is actually here -- we've got this border around the image inside of the button:
>   border: 1px solid transparent;
https://dxr.mozilla.org/mozilla-central/rev/0ddfec7126ec503b54df9c4b7c3b988906f6c882/browser/themes/linux/browser.css#373-380

We pixel-snap borders to display pixels, so this border ends up being a fractional number of CSS pixels in width.  This means the button (which shrinkwraps its contents, including this border around the image) also ends up being a fractional number of CSS pixels wide.

If we can get rid of that border, the problem should go away.
Flags: needinfo?(dholbert)
This border only presents a problem if you explicitly add the styling:
  -moz-image-region: rect(0, 18px, 18px, 0);

...because otherwise, you get our native HiDPI settings, which e.g. for me includes:
   -moz-image-region: rect(0, 252px, 36px, 216px);

...and that is a wider image (36px wide) which (combined with the fractional border) surpasses a separate "max-width: 32px" declaration.  So that "max-width"/large-image-region combination is why we end up with 32px in Nightly right now, when you have fractional HiDPI settings.
So basically, what's going on here is:
  * The button gets sized to image-region + image-padding + image-border.
  * There's 12px of horizontal padding (6px on each side), and 2px of horizontal border (1px on each side)
  * So, you'd rightly expect that with an 18px-wide image, you'd end up with 18px + 12px + 2px = 32px wide image.

  * BUT: the 2px of border gets pixel-snapped -- so it's not actually 2 CSS pixels wide.  It's 2/3 of a CSS pixel wide, which is 1 dev pixel wide.  So really, our button is 18px + 12px + 2/3px + 2/3px = 31.3333 CSS pixels wide.

  * If you use a larger -moz-image-region (as we do in current Nightly with a "@min-resolution: 1.1dppx" media query), then we end up instead with 36px + 12px + 2/3px + 2/3px = 49.3333px.  But that gets clamped by "max-width" to exactly 32px.  So that's why you only see this problem if you provide a -moz-image-region of 18px wide or smaller. Anything larger will push the button-width over 32px and get clamped.
So this is INVALID as a gecko bug, I think.  (To the extent that there's a problem here, it's that borders are device-pixel-snapped, and that's not something that's likely to change because it's important for nice crisp rendering.)

Please let me know if anything here doesn't make sense.
Status: NEW → RESOLVED
Last Resolved: a year ago
Resolution: --- → INVALID
Thanks, this is a great explanation! I filed bug 1320077 for us to use HiDPI sizes with -moz-image-region when > 1.1dppx so that WebExtension themes match the implementation behavior of our default theme.
You need to log in before you can comment on or make changes to this bug.