Intent to Ship: New TextMetrics API in Canvas

159 views
Skip to first unread message

Fernando Serboncini

unread,
Aug 31, 2018, 3:48:23 PM8/31/18
to blink-dev

(sent on behalf of davidqu@, because his emails are still being moderated. Moderators, feel free to drop his previous emails)


Contact emails

dav...@chromium.org, fs...@chromium.org


Spec

https://html.spec.whatwg.org/multipage/canvas.html#textmetrics


Summary

The current canvas TextMetrics API only exposes the width of the measured text. Part of the new API was already implemented under a flag, but there were some inconsistencies and bugs, especially with RightToLeft text. We fixed the problems and implemented a new version of the spec including an array of advances per character and a dictionary returning baselines.

The feature bug (https://crbug.com/277215) has strong user support (21 stars)


Link to “Intent to Implement” blink-dev discussion

https://groups.google.com/a/chromium.org/forum/?fromgroups#!searchin/blink-dev/textmetrics|sort:date/blink-dev/SgofW_bQ3ps/jNYamQHplAMJ

The thread was titled “Intend to ship”, but it was seen as “Intend to implement” and was never actually shipped.


Is this feature supported on all six Blink platforms (Windows, Mac, Linux, Chrome OS, Android, and Android WebView)?

Yes


Demo link

-


Debuggability

No DevTools needed for debug. Users can console print the full TextMetrics object in one line.


Risks

Interoperability and Compatibility

Safari already has some of the metrics implemented but since the spec was recently updated some work still needs to be done (advances and getBaselines) to have full interoperability with Chrome. Firefox started development 4 years ago but never shipped. Edge is the only one that has no public signals of implementing yet.


Edge: No signals

Firefox: In development

Safari: Partially Shipped


We know this is a major feature requested by developers (as well as internal Google teams like Google Docs). This API will help developers have more control and more accurate text rendering. As of today a different way to achieve this is by using rendering text to the DOM and using getBoundingClientRect to get some measurements. This process not only requires a draw call but also doesn’t help obtaining the advances or the more granular metrics.


Activation

Enable the platform experiment ExtendedTextMetrics


Is this feature fully tested by web-platform-tests? Link to test suite results from wpt.fyi.

A set of test for each metric, prefixed by “2d.text.measure”:

https://wpt.fyi/results/2dcontext/drawing-text-to-the-canvas



Entry on the feature dashboard

https://www.chromestatus.com/feature/5307344997056512

Chris Harrelson

unread,
Aug 31, 2018, 4:25:50 PM8/31/18
to Fernando Serboncini, blink-dev
Hi,

Two pieces of initial feedback:

1. I don't see a TAG review, has one been filed.

2. It sounds like you are actually adding features to an existing partial API, rather than shipping an entirely new one from scratch. Also, you mentioned that WebKit shipped some TextMetrics APIs also. Is this correct?
Could you enumerate exactly the things being added, and also speak to whether the Blink and WebKit features already shipped are compatible with each other, and with the spec?

Chris


--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CADp2-T9J%2BO%3D7AxKx0Ab1isbszhXrr9_xa-7Ck5A6EFhEqmnp1Q%40mail.gmail.com.

Johnny Stenback

unread,
Aug 31, 2018, 4:46:33 PM8/31/18
to chri...@chromium.org, fs...@chromium.org, blink-dev
Specifics aside, I wanted to say non-owner LGTM as this has been a much requested feature for quite some time now. Let's figure out the specifics and finally ship these additional text measurement APIs!

Fernando Serboncini

unread,
Aug 31, 2018, 5:00:13 PM8/31/18
to Chris Harrelson, blink-dev
TAG review request: https://github.com/w3ctag/design-reviews/issues/302

Fair enough, let me try to recap the situation. We are talking about the TextMetric dictionary that is returned by canvas2d.measureText("text");
Currently,  TextMetrics returns a single field ("width").

The old API (that is also what has been shipped by Safari) contains the extra fields: actualBoundingBoxLeft, actualBoundingBoxRight,  fontBoundingBoxAscent, fontBoundingBoxDescent, actualBoundingBoxAscent, actualBoundingBoxDescent, emHeightAscent, emHeightDescent, alphabeticBaseline, hangingBaseline, ideographicBaseline.

The new API that is on spec + WPT and behind a flag on Chrome is the old API with the following diff:
remove alphabeticBaseline, hangingBaseline, ideographicBaseline.
add a getBaselines() method that returns a dictionary of optional baselines: alphabetic, hanging, ideographic.
add a advances attribute returning an array of advances per grapheme.

this new API matches a discussion around TextMetric within CSS-Houdini and addresses some small inconsistencies in the original spec (some values were wrongly defined on spec, correctly implemented on Safari, wrongly implemented on Chrome initially, and fixed now and on spec).

The advances attribute is a new addition, so not really incompatible.

The baselines changes does add an incompatibility. But this was done to address deeper problems with the spec definition around baselines (i.e., nobody can agree what a hanging or an ideographic baseline is supposed to mean). This meant that the original values were meaningless heuristics (hanging is ALWAYS 80% of emHeightAscent, not spec'ed anywhere, but following some Apache guideline). The new spec basically states that, if you are not sure what the baseline is - i.e., not available on the font or on your text layout system -, don't return it. 

Both our implementation and Firefox's were on hold for years due to mostly those two issues (baselines and wrong definition of Descent on the spec).

smaug

unread,
Aug 31, 2018, 5:16:37 PM8/31/18
to Fernando Serboncini, blink-dev
On 08/31/2018 10:48 PM, Fernando Serboncini wrote:
> (sent on behalf of davidqu@, because his emails are still being moderated. Moderators, feel free to drop his previous emails)
>
>
> Contact emails
>
> dav...@chromium.org <mailto:dav...@chromium.org>, fs...@chromium.org <mailto:fs...@chromium.org>
>
>
> Spec
>
> https://html.spec.whatwg.org/multipage/canvas.html#textmetrics
>
>
> Summary
>
> The current canvas TextMetrics API only exposes the width of the measured text. Part of the new API was already implemented under a flag, but there
> were some inconsistencies and bugs, especially with RightToLeft text. We fixed the problems and implemented a new version of the spec including an
> array of advances per character and a dictionary returning baselines.
>
> The feature bug (https://crbug.com/277215) has strong user support (21 stars)
>
>
> Link to “Intent to Implement” blink-dev discussion
>
> https://groups.google.com/a/chromium.org/forum/?fromgroups#!searchin/blink-dev/textmetrics|sort:date/blink-dev/SgofW_bQ3ps/jNYamQHplAMJ
> <https://groups.google.com/a/chromium.org/forum/?fromgroups#!searchin/blink-dev/textmetrics%7Csort:date/blink-dev/SgofW_bQ3ps/jNYamQHplAMJ>
>
> The thread was titled “Intend to ship”, but it was seen as “Intend to implement” and was never actually shipped.
>
>
> Is this feature supported on all six Blink platforms (Windows, Mac, Linux, Chrome OS, Android, and Android WebView)?
>
> Yes
>
>
> Demo link
>
> -
>
>
> Debuggability
>
> No DevTools needed for debug. Users can console print the full TextMetrics object in one line.
>
>
> Risks
>
> Interoperability and Compatibility
>
> Safari already has some of the metrics implemented but since the spec was recently updated some work still needs to be done (advances and
> getBaselines) to have full interoperability with Chrome. Firefox started development 4 years ago but never shipped. Edge is the only one that has no
> public signals of implementing yet.
>
>
> Edge: No signals <https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18848270/>
>
> Firefox: In development <https://bugzilla.mozilla.org/show_bug.cgi?id=1102584>

FWIW, a bug filed and active two years ago isn't exactly in-development.


>
> Safari: Partially Shipped <https://bugs.webkit.org/show_bug.cgi?id=157629>
>
>
> We know this is a major feature requested by developers (as well as internal Google teams like Google Docs). This API will help developers have more
> control and more accurate text rendering. As of today a different way to achieve this is by using rendering text to the DOM and using
> getBoundingClientRect to get some measurements. This process not only requires a draw call but also doesn’t help obtaining the advances or the more
> granular metrics.
>
>
> Activation
>
> Enable the platform experiment ExtendedTextMetrics
>
>
> Is this feature fully tested by web-platform-tests <https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_platform_tests.md>? Link
> to test suite results from wpt.fyi <https://wpt.fyi/results/?label=experimental>.
>
> A set of test for each metric, prefixed by “2d.text.measure”:
>
> https://wpt.fyi/results/2dcontext/drawing-text-to-the-canvas
>
>
>
> Entry on the feature dashboard <http://www.chromestatus.com/>
>
> https://www.chromestatus.com/feature/5307344997056512
>
> --
> You received this message because you are subscribed to the Google Groups "blink-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org
> <mailto:blink-dev+...@chromium.org>.
> <https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CADp2-T9J%2BO%3D7AxKx0Ab1isbszhXrr9_xa-7Ck5A6EFhEqmnp1Q%40mail.gmail.com?utm_medium=email&utm_source=footer>.

Fernando Serboncini

unread,
Aug 31, 2018, 5:58:50 PM8/31/18
to smaug, blink-dev
TAG review request: https://github.com/w3ctag/design-reviews/issues/302

Fair enough, let me try to recap the situation. We are talking about the TextMetric dictionary that is returned by canvas2d.measureText("text");
Currently,  TextMetrics returns a single field ("width").

The old API (that is also what has been shipped by Safari) contains the extra fields: actualBoundingBoxLeft, actualBoundingBoxRight,  fontBoundingBoxAscent, fontBoundingBoxDescent, actualBoundingBoxAscent, actualBoundingBoxDescent, emHeightAscent, emHeightDescent, alphabeticBaseline, hangingBaseline, ideographicBaseline.

The new API that is on spec + WPT and behind a flag on Chrome is the old API with the following diff:
remove alphabeticBaseline, hangingBaseline, ideographicBaseline.
add a getBaselines() method that returns a dictionary of optional baselines: alphabetic, hanging, ideographic.
add a advances attribute returning an array of advances per grapheme.

this new API matches a discussion around TextMetric within CSS-Houdini and addresses some small inconsistencies in the original spec (some values were wrongly defined on spec, correctly implemented on Safari, wrongly implemented on Chrome initially, and fixed now and on spec).

The advances attribute is a new addition, so not really incompatible.

The baselines changes does add an incompatibility. But this was done to address deeper problems with the spec definition around baselines (i.e., nobody can agree what a hanging or an ideographic baseline is supposed to mean). This meant that the original values were meaningless heuristics (hanging is ALWAYS 80% of emHeightAscent, not spec'ed anywhere, but following some Apache guideline). The new spec basically states that, if you are not sure what the baseline is - i.e., not available on the font or on your text layout system -, don't return it. 

Both our implementation and Firefox's were on hold for years due to mostly those two issues (baselines and wrong definition of Descent on the spec).


Koji Ishii

unread,
Sep 3, 2018, 5:05:46 PM9/3/18
to Fernando Serboncini, smaug, blink-dev
Fernando Serboncini <fs...@chromium.org>:

this new API matches a discussion around TextMetric within CSS-Houdini and addresses some small inconsistencies in the original spec (some values were wrongly defined on spec, correctly implemented on Safari, wrongly implemented on Chrome initially, and fixed now and on spec).

Can you tell me where the CSS-Houdini discussion has happened? I was talking to other browsers about the font metrics API discussion coming soon and we're looking forward to it, but I guess I missed the discussion had happened.

Fernando Serboncini

unread,
Sep 3, 2018, 8:39:38 PM9/3/18
to Koji Ishii, Emil A Eklund, smaug, blink-dev
[+eae]

I think there was some draft here: https://drafts.css-houdini.org/font-metrics-api-1/
I'm not sure there was an online discussion, but I'm sure Emil mentioned some offline ones.

Koji Ishii

unread,
Sep 4, 2018, 10:57:37 AM9/4/18
to Fernando Serboncini, Koji Ishii, eae, smaug, blink-dev
I see, from that IIUC you meant canvas API now matches "advances" member to the current ED of Houdini Font Metrics API, and other members are still to be discussed?

That seems reasonable to me then. Sorry I thought there was a discussion I missed.

2018年9月4日(火) 9:39 Fernando Serboncini <fs...@chromium.org>:

dav...@chromium.org

unread,
Sep 6, 2018, 12:05:48 PM9/6/18
to blink-dev, fs...@chromium.org, ko...@chromium.org, e...@chromium.org, sm...@welho.com
Friendly ping about this Intend to ship. 

The change that removes the flag to expose the full API is ready to be cherry picked and is passing all tests: https://chromium-review.googlesource.com/c/chromium/src/+/1199810. I'm just missing one LGTM from third_party/blink/API_OWNERS

I know there was a discussion on the spec thread about Safari shipping the old spec to their stable channel, but someone commented on that thread agreeing with the idea of making baselines optional, which is not possible with the current API.

Any comment or suggestion about this would be very appreciated.

Thanks,
David

Chris Harrelson

unread,
Sep 6, 2018, 12:33:23 PM9/6/18
to dav...@chromium.org, blink-dev, Fernando Serboncini, Koji Ishii, eae, smaug
On Thu, Sep 6, 2018 at 9:05 AM <dav...@chromium.org> wrote:
Friendly ping about this Intend to ship. 

The change that removes the flag to expose the full API is ready to be cherry picked and is passing all tests: https://chromium-review.googlesource.com/c/chromium/src/+/1199810. I'm just missing one LGTM from third_party/blink/API_OWNERS

To ship you'll also need 3 LGTMs on this thread. I'm holding off on approval for that patch until we can get clarity about whether this feature is ready to ship.
 

I know there was a discussion on the spec thread about Safari shipping the old spec to their stable channel, but someone commented on that thread agreeing with the idea of making baselines optional, which is not possible with the current API.

There is also a concern that the WebKit team didn't provide any feedback on the pull request. I asked Emil (author of draft Houdini TextMetrics spec) to look at the spec proposal. He'll also reach out to Apple to get feedback from them as well.
  

Any comment or suggestion about this would be very appreciated.

Thanks,
David

On Tuesday, September 4, 2018 at 10:57:37 AM UTC-4, Koji Ishii wrote:
I see, from that IIUC you meant canvas API now matches "advances" member to the current ED of Houdini Font Metrics API, and other members are still to be discussed?

That seems reasonable to me then. Sorry I thought there was a discussion I missed.

2018年9月4日(火) 9:39 Fernando Serboncini <fs...@chromium.org>:
[+eae]

I think there was some draft here: https://drafts.css-houdini.org/font-metrics-api-1/
I'm not sure there was an online discussion, but I'm sure Emil mentioned some offline ones.

On Mon, Sep 3, 2018 at 5:05 PM Koji Ishii <ko...@chromium.org> wrote:
Fernando Serboncini <fs...@chromium.org>:

this new API matches a discussion around TextMetric within CSS-Houdini and addresses some small inconsistencies in the original spec (some values were wrongly defined on spec, correctly implemented on Safari, wrongly implemented on Chrome initially, and fixed now and on spec).

Can you tell me where the CSS-Houdini discussion has happened? I was talking to other browsers about the font metrics API discussion coming soon and we're looking forward to it, but I guess I missed the discussion had happened.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/98c0c883-1478-47df-8cef-d409d6bc384d%40chromium.org.

David Quiroz Marin

unread,
Sep 6, 2018, 12:56:50 PM9/6/18
to Chris Harrelson, blin...@chromium.org, fs...@chromium.org, ko...@chromium.org, e...@chromium.org, sm...@welho.com
Thank you Chris, I'll keep an eye on this thread for more comments.

Chris Harrelson

unread,
Sep 10, 2018, 2:14:20 PM9/10/18
to dav...@chromium.org, blink-dev, Fernando Serboncini, Koji Ishii, eae, smaug
An update on this intent: there have been discussions ongoing off of this thread (e.g. in the whatwg, see here for example). I think we should put the intent on hold pending these discussions.

Thanks,
Chris

Thiemo Nagel

unread,
Sep 28, 2018, 6:37:12 AM9/28/18
to chri...@chromium.org, dav...@chromium.org, blin...@chromium.org, fs...@chromium.org, ko...@chromium.org, e...@chromium.org, sm...@welho.com
What are the fingerprinting implications of this change? It seems to me that providing more details and increasing performance (compared to rendering text to the DOM and using getBoundingClientRect) could increase the obtainable entropy and reduce the cost for doing so.

Has this been considered? How could it be mitigated?

Thiemo Nagel

Software Engineer


Google Germany GmbH, Erika-Mann-Straße 33, 80686 München

Geschäftsführer: Paul Manicle, Halimah DeLaine Prado

Registergericht und -nummer: Hamburg, HRB 86891

Sitz der Gesellschaft: Hamburg

Fernando Serboncini

unread,
Oct 1, 2018, 1:18:30 PM10/1/18
to Thiemo Nagel, chri...@chromium.org, dav...@chromium.org, blin...@chromium.org, ko...@chromium.org, e...@chromium.org, sm...@welho.com
There's definitely a speed improvement, not only compared to DOM/getBoundingClientRect but also compared to drawing on a Canvas and getPixelData. But I don't see how this would increase the entropy.

That said, I think it's probably worth talking to someone on security about this. Would you have a suggestion on who to talk to on this?

Reply all
Reply to author
Forward
0 new messages