Text rendering looks off on maps.apple.com on Windows
Categories
(Core :: Graphics: Text, defect)
Tracking
()
People
(Reporter: bgrins, Assigned: jfkthame)
References
(Blocks 1 open bug, Regression)
Details
(Keywords: regression, webcompat:platform-bug, webcompat:site-report)
Attachments
(5 files)
STR:
- Load https://beta.maps.apple.com/?address=600+Montgomery+St%2C+San+Francisco%2C+CA+94111%2C+United+States&auid=13461352009204515340&ll=37.795167%2C-122.4027996&lsp=9902&q=Transamerica+Pyramid on Firefox in Windows
- Look at the "Transamerica" text
| Reporter | ||
Comment 1•1 year ago
|
||
Same text on Edge
Comment 2•1 year ago
|
||
Jonathan, any ideas what's wrong with the glyph layout here? Apple seems interested in fixing this.
| Assignee | ||
Comment 3•1 year ago
|
||
I can't seem to inspect that text to see how it's being styled, but my guess is this might be a bad interaction between letter-spacing, scaling, and pixel-snapping of glyph positions.
Comment 4•1 year ago
|
||
The text is rendered on canvas.rt-root (you can use this search query in the inspector to find the element), which has the following rule:
.mk-map-view .rt-root {
letter-spacing: initial;
}
But removing, or changing this live doesn't seem to fix the issue, but I'm not sure the text get re-rendered without reloading the page.
Also note that the rendering issue doesn't reproduce on Linux.
Comment 5•1 year ago
|
||
Based on native method call tracing, I suspect, but I'm not 100% sure that the text is rendered around here:
https://share.firefox.dev/3TDKKL4
I don't know Canvas API enough to spot if something here would possibly render some text in the canvas.
Comment 6•1 year ago
|
||
Using the debugger, I think I found where we render the text.
https://beta.maps.apple.com/static/maps-app-web-client/mapkitjs/libs/mapkit.core.1b57c0.js?mkjsVersion=5.78.83
line 1227 (pretty printed)
eis the canvas rendering context
draw: function (e) {
var t = this._node,
i = this.params[t.kind];
this._setTextProperties(e);
var o = t.parent.annotation.darkColorScheme ? 'dark' : 'light';
e.fillStyle = i.color[o],
e.strokeStyle = this.params.haloColor[o],
e.lineWidth = this.params.haloSize;
var a = t.size.width / 2,
n = t.size.height - i.yPadding;
e.strokeText(t.text, a, n),
e.fillText(t.text, a, n)
}
- t.text = "Transamerica"
- a = 38.5
- n = 15
- e.lineWidth = 2
- e.font = 600 11px "SFProRegular", "-apple-system", "BlinkMacSystemFont", "Helvetica Neue", Helvetica, Arial, sans-serif
- e.textAlign = center
- e.textBaseline = bottom
- e.miterLimit = 2
Also interesting, in the same source.
Line 1543 (pretty printed)
eis the canvas context,tis "Transamerica pyramid"iis "600 11px "SFProRegular", "-apple-system", "BlinkMacSystemFont", "Helvetica Neue", Helvetica, Arial, sans-serif"
return function (e, t, i) {
e.font = i;
var o = t.trim().split(/[\f\n\r\t\v\u0020\u2000-\u200b\u205f\u3000]+/),
a = [];
for (; o.length > 0; ) {
for (var n = [
o.shift()
], s = n.join(' ').length; o.length > 0 && s <= 16; ) n.push(o.shift()),
s = n.join(' ').length;
s > 16 &&
n.length > 1 &&
o.unshift(n.pop());
const t = n.join(' '),
i = e.measureText(t),
l = i.width + u.labelOutlineWidth;
a.push([t,
l,
i])
}
return a
Same source, line 1135
eis "Pyramid"tis "Title"iis 47ais a TextMetrics objectlis false
function l(e, t, i, a, l) {
o.BaseNode.call(this),
this.text = e,
this.kind = t,
this._renderer = new n(this),
this.textAscent = a.ascent ||
0,
this.textDescent = a.descent ||
0,
this.size = new s(i, this._renderer.params[this.kind].height),
this.keyForFrozenLayer = (l ? 'dark' : 'light') + '-' + t + '#' + this.text
}
| Assignee | ||
Comment 7•1 year ago
|
||
Yeah, the "Transamerica Pyramid" label is drawn using canvas2d.fillText (unlike the other labels around the map), and that doesn't handle spacing well in Arial, which is the font we end up using on Windows.
The result looks a lot better if you remove Arial from the gfx.font_rendering.cleartype_params.force_gdi_classic_for_families pref. (Requires browser restart to see the change, I believe.)
There's a long history behind that setting, and it may be that it's time we got rid of it altogether, but any change to Windows font rendering tends to be controversial. :(
| Assignee | ||
Comment 8•1 year ago
•
|
||
Note that if I render the same text "Transamerica Pyramid" using font: 600 11px Arial in HTML, the spacing is much better. The bad result here is specific to canvas2d text, which apparently doesn't handle the attempt to set the cleartype mode very well.
| Assignee | ||
Comment 9•1 year ago
|
||
| Assignee | ||
Comment 10•1 year ago
|
||
In the HTML-rendered text, we can see the effect of "force GDI classic" mode, e.g. making the "m" glyph wider. It looks like the canvas2d-rendered text has laid out the glyphs according to the GDI-classic metrics, but the actual rendering is not using this mode and so we get a narrower "m" and bad spacing. (Other glyphs are also affected, but the "m" is perhaps the clearest.)
| Assignee | ||
Comment 11•1 year ago
|
||
We don't render the glyphs using "GDI classic" mode in canvas because we explicitly set params.allowGDI to false here. This dates back to bug 1730772.
Removing that line results in much better spacing of the "Transamerica Pyramid" text, but presumably it may regress things that bug 1730772 was aiming to fix.
Comment 12•1 year ago
|
||
A quick side note to explain how I found this JS code.
I hacked something to break on any function call whose any of its arguments was equal to Transamerica pyramid.
It paused on many function calls related to the left sidebar, but ultimately paused on the right function calling the canvas API.
Updated•1 year ago
|
Comment 13•1 year ago
|
||
Set release status flags based on info from the regressing bug 1730772
:bas.schouten, since you are the author of the regressor, bug 1730772, could you take a look? Also, could you set the severity field?
For more information, please visit BugBot documentation.
| Reporter | ||
Updated•1 year ago
|
Updated•1 year ago
|
| Assignee | ||
Comment 14•1 year ago
|
||
Updated•1 year ago
|
Updated•1 year ago
|
Comment 15•1 year ago
|
||
Comment 16•1 year ago
|
||
Backed out for causing bc failures on browser_less_common_selection_manipulations.js.
[task 2024-09-24T20:58:00.287Z] 20:58:00 INFO - TEST-PASS | browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js | Check initial selection - [8,13] deepEqual [8,13] -
[task 2024-09-24T20:58:00.288Z] 20:58:00 INFO - Test Drag Selection from the first character - Full host
[task 2024-09-24T20:58:00.289Z] 20:58:00 INFO - Selected text is <example.co>
[task 2024-09-24T20:58:00.289Z] 20:58:00 INFO - Buffered messages finished
[task 2024-09-24T20:58:00.291Z] 20:58:00 INFO - TEST-UNEXPECTED-FAIL | browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js | Check initial selection - [0,19] deepEqual [8,18] -
[task 2024-09-24T20:58:00.291Z] 20:58:00 INFO - Stack trace:
[task 2024-09-24T20:58:00.291Z] 20:58:00 INFO - chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js:doTest/<:275
[task 2024-09-24T20:58:00.291Z] 20:58:00 INFO - resource://testing-common/BrowserTestUtils.sys.mjs:withNewTab:121
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js:doTest:259
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js:https:250
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:handleTask:1145
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:_runTaskBasedTest:1217
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1358
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:nextTest/<:1134
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/<:1058
[task 2024-09-24T20:58:00.292Z] 20:58:00 INFO - Test Drag Selection from the last character
[task 2024-09-24T20:58:00.293Z] 20:58:00 INFO - Selected text is <example.com/test/some/page.htm>
[task 2024-09-24T20:58:00.294Z] 20:58:00 INFO - TEST-PASS | browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js | Check initial selection - [0,30] deepEqual [0,30] -
[task 2024-09-24T20:58:00.294Z] 20:58:00 INFO - Test Drag Selection in the middle of the string
[task 2024-09-24T20:58:00.294Z] 20:58:00 INFO - Selected text is <le.co>
[task 2024-09-24T20:58:00.295Z] 20:58:00 INFO - TEST-PASS | browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js | Check initial selection - [13,18] deepEqual [13,18] -
[task 2024-09-24T20:58:00.296Z] 20:58:00 INFO - Test Double-click on word
[task 2024-09-24T20:58:00.296Z] 20:58:00 INFO - Selected text is </>
[task 2024-09-24T20:58:00.297Z] 20:58:00 INFO - Not taking screenshot here: see the one that was previously logged
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - TEST-UNEXPECTED-FAIL | browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js | Check initial selection - [20,24] deepEqual [19,20] -
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - Stack trace:
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js:doTest/<:275
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - resource://testing-common/BrowserTestUtils.sys.mjs:withNewTab:121
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js:doTest:259
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js:https:250
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:handleTask:1145
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:_runTaskBasedTest:1217
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1358
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochikit/content/browser-test.js:nextTest/<:1134
[task 2024-09-24T20:58:00.298Z] 20:58:00 INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/<:1058
[task 2024-09-24T20:58:00.300Z] 20:58:00 INFO - Click at the right of the text
[task 2024-09-24T20:58:00.300Z] 20:58:00 INFO - Selected text is <https://example.com/test/some/page.htm>
[task 2024-09-24T20:58:00.301Z] 20:58:00 INFO - TEST-PASS | browser/components/urlbar/tests/browser/browser_less_common_selection_manipulations.js | Check initial selection - [0,38] deepEqual [0,38] -
| Assignee | ||
Comment 17•1 year ago
|
||
The browser_less_common_selection_manipulations.js failures are happening because the test uses canvas2d.measureText and assumes the resulting metrics will match the text in the URL bar, but because the system font in the URLbar is using GDI Classic mode, and we no longer use those metrics in canvas, the widths don't match.
A workaround for this, I think, is to use an HTML-based (rather than canvas-based) approach to measuring substrings of the URLbar content. I'll push a try run to check... https://treeherder.mozilla.org/jobs?repo=try&revision=fd3691742d870cd51d305f512af0aade142d0d0c
| Assignee | ||
Comment 18•1 year ago
|
||
Because of the possibility of different rendering modes, it's not guaranteed that
canvas2d.measureText will return exactly the same text metrics as HTML uses.
So instead of relying on canvas to measure substrings of the URLbar content,
measure by putting the text in a <span> and querying its offsetWidth.
Comment 19•1 year ago
|
||
Comment 20•1 year ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/356a7ea855bc
https://hg.mozilla.org/mozilla-central/rev/31bd8fe7b5ce
Updated•1 year ago
|
Comment 21•1 year ago
|
||
Given the regressions, this doesn't sound like something we want to fast-track shipping.
Comment 22•1 year ago
|
||
Jonathan, I think we should probably back this out for now until we get a better handle on the regressions.
| Assignee | ||
Comment 23•1 year ago
|
||
Possibly, but let's give it a little bit more time: I've just (re-)lando'd bug 1920733, which should resolve the pdf.js-related problems, assuming it sticks.
(leaving ni? in place for now)
Comment 26•1 year ago
•
|
||
Followup on backout plans: per bug 1923150 comment 12, it looks like we're leaving this fix in mozilla-central/Nightly, but we're planning to backout from the beta channel after the next central-to-beta merge (so as not to ship this bug's regressions in 133 beta/release).
[please correct me if that's wrong; I'm just noting the latest plan I could find on this & associated bugs]
Comment 27•1 year ago
|
||
Possible duplicates: bug 1885846, bug 890733, bug 1029327
Comment 28•1 year ago
|
||
Comment 29•1 year ago
|
||
Backed out of beta for causing Bug 1923150
https://hg.mozilla.org/releases/mozilla-beta/rev/9862f84eed67bde6041920e06e5e7ca8261df85e
Updated•11 months ago
|
Updated•11 months ago
|
Comment 30•11 months ago
|
||
Backed out 2 changesets (Bug 1919906) in beta for causing Bug 1923150 a=pascalc
https://hg.mozilla.org/releases/mozilla-beta/rev/0381336fa697645f73bd8d70006a4edb6c15b750
Comment 31•3 months ago
|
||
| Assignee | ||
Comment 32•3 months ago
|
||
(In reply to Will from comment #31)
Same or similar? https://www.reddit.com/r/firefox/comments/1m1eoam/apple_maps_text_rendering_firefox_14004_win10/
No, that looks like a different problem. The original issue here was about erratic glyph spacing, but the screenshot there seems to have the first letter missing from lots of (all?) text labels, and sometimes glyphs significantly misplaced vertically.
Description
•