Issue 12705 in skia: canvaskit-wasm doesn not support measureText

190 views
Skip to first unread message

g… via monorail

unread,
Dec 2, 2021, 1:41:04 PM12/2/21
to bu...@skia.org
Status: Untriaged
Owner: ----
Priority: Medium
Type: Defect

New issue 12705 by gm...@chromium.org: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705

What steps will reproduce the problem?

call ctx.measureText()




What is the expected output?


The docs claim this is a drop in replacement for the Canvas2D api so the expected output is the text is measured


What do you see instead?

An error "Clients wishing to properly measure text should use the Paragraph API"


I can certainly understand that measureText might not be but best API. For my needs I don't need to "properly measure text" though, instead I need the emulated Canvas2D api to work as a "drop in replacement".



What version of the product are you using?

0.31.0

On what operating system?

MacOS


Please submit a code sample via fiddle.skia.org showing the issue.

https://jsfiddle.skia.org/canvaskit/12e1b4defb748b38eca2ea4869e5c12ef2194719b7c1cbfe24b637081cc51b73

--
You received this message because:
1. The project was configured to send all issue notifications to this address

You may adjust your notification preferences at:
https://bugs.chromium.org/hosting/settings

tdenn… via monorail

unread,
Dec 2, 2021, 4:16:06 PM12/2/21
to bu...@skia.org
Updates:
Owner: kjlu...@google.com

Comment #1 on issue 12705 by tdenn...@google.com: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c1

Over to Kevin for CanvasKit API triage

kjlub… via monorail

unread,
Dec 3, 2021, 10:46:04 AM12/3/21
to bu...@skia.org
Updates:
Status: Accepted

Comment #2 on issue 12705 by kjlu...@google.com: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c2

Yes, I've been meaning to backport this functionality in some capacity.

g… via monorail

unread,
Dec 3, 2021, 10:42:23 PM12/3/21
to bu...@skia.org

Comment #3 on issue 12705 by gm...@chromium.org: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c3

First off I wanted to thank you for this library. My initial goal was to use it as a replacement for node-canvas (https://www.npmjs.com/package/canvas) (canvas in node). The problem with node canvas it's it's a native plugin which ends up causing problems for me (for example it doesn't work out-of-the-box on an M1 Mac)


I'd love to help make it drop in replacement for node-canvas if possible. On top of measureText, I noticed textAlign and textBaseline are not yet supported either. I thought about trying to implement them myself but I'm really not familiar with Skia.

Another issue I'm running into is the way fonts *seem* to managed. In the browser I use CSS to load a font. CSS lets me associate a name with the font. Example:

@font-face {
font-family: "lesson-font";
src: url("fonts/KlokanTechNotoSansCJK-Bold.otf");
}

So now I can reference that font as "lesson-font". It didn't appear that similar functionality (this indirection) was part of the current canvaskit-wasm implementation. That's problematic because I don't know the name of the font. "foo.ttf" might internally have the name "bar-font" and short of parsing the font file myself I have no way to know the name of a user supplied font. It's possible I just didn't get how it works.

On more thing, the Image implementation via canvas.decoderImage returns an Image that has the functions width and height, instead of getters. Meaning someImage.width() instead of someImage.width. That's another place where you have existing code that uses img.width and img.height but it breaks cause of the difference.

That's one place I could easily help out (I guess I'll punch up a CL)

In any case, if there's any way to help out more please reach out. Like I said, I don't know Skia so I suspect you'd spend more time answering my questions than it would take to write the solution I'm totally up for helping out if I can.

kjlub… via monorail

unread,
Dec 6, 2021, 9:06:47 AM12/6/21
to bu...@skia.org

Comment #4 on issue 12705 by kjlu...@google.com: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c4

Looks like there are a few issues going on here:

1) The lack of measureText on the Canvas2D emulation layer (this bug).
2) textAlign and textBaseline are not supported in the emulation layer.
3) An inability for CanvasKit to respond to CSS font-face declarations to load fonts. The emulation layer only has .loadFont() [1]
4) The Image object returned by decodeImage does not exactly have the same API as the Canvas2D counterpart. One example is a lack of the width and height properties.

Implementing 1) using the current font in some capacity should be straightforward using the Paragraph API in a self-contained way.

Implementing 2) seems a bit difficult, as it would require the use of the Paragraph API through more of the emulation layer. If getting text to work well is important for your use case, you might want to deviate from the Canvas2D API to something else.

3) seems difficult to solve in general, i.e. make CanvasKit look for style sheets. You might look into the https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet API to try this yourself, but I don't think this is something we are going to put into CanvasKit. The JS API we have should be sufficient to load fonts and switch between them.

4) You are welcome to add a Image class or other wrapper that provides these properties. Add an image.js to modules/canvaskit/htmlcanvas/ similar to imagedata.js



[1] https://github.com/google/skia/blob/8893fe4772f1cb5972e4773b7d8020fb49a84991/modules/canvaskit/htmlcanvas/htmlcanvas.js#L24

Git Watcher via monorail

unread,
Dec 6, 2021, 3:06:04 PM12/6/21
to bu...@skia.org

Comment #5 on issue 12705 by Git Watcher: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c5

The following revision refers to this bug:
https://skia.googlesource.com/skia/+/5f9ec39daf7722ce23e9b206410a9d1f82fce14b

commit 5f9ec39daf7722ce23e9b206410a9d1f82fce14b
Author: Gregg Tavares <gm...@google.com>
Date: Mon Dec 06 19:11:44 2021

Wrap SkImage into HTMLImage

Canvas-wasm says it's a drop in replacement for the Canvas API.
Unfortunately HTMLCanvas.decodeImage returns an SkImage which
has functions width() and height() for getting the width and height
of an image whereas HTMLImageElement has properties width and height.

Lots of existing code uses width and height so wrapping this
would seem to make it more closely match expectations.

Bug: skia:12705
Change-Id: I62c4f655c58f6806e836700e03b946a91f3e518d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/479936
Reviewed-by: Kevin Lubick <kjlu...@google.com>

[modify] https://crrev.com/5f9ec39daf7722ce23e9b206410a9d1f82fce14b/modules/canvaskit/compile.sh
[modify] https://crrev.com/5f9ec39daf7722ce23e9b206410a9d1f82fce14b/modules/canvaskit/htmlcanvas/canvas2dcontext.js
[modify] https://crrev.com/5f9ec39daf7722ce23e9b206410a9d1f82fce14b/modules/canvaskit/htmlcanvas/htmlcanvas.js
[modify] https://crrev.com/5f9ec39daf7722ce23e9b206410a9d1f82fce14b/modules/canvaskit/BUILD.bazel
[add] https://crrev.com/5f9ec39daf7722ce23e9b206410a9d1f82fce14b/modules/canvaskit/htmlcanvas/htmlimage.js
[modify] https://crrev.com/5f9ec39daf7722ce23e9b206410a9d1f82fce14b/modules/canvaskit/htmlcanvas/pattern.js

g… via monorail

unread,
Dec 6, 2021, 3:54:22 PM12/6/21
to bu...@skia.org

Comment #6 on issue 12705 by gm...@chromium.org: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c6


> Implementing 2) seems a bit difficult, as it would require the use of the Paragraph API through more of the emulation layer. If getting text to work well is important for your use case, you might want to deviate from the Canvas2D API to something else.

If you're not actually going to actually emulate the Canvas API then I'd like to suggest you remove the "use as a drop in replacement for the canvas API" from the docs. I wouldn't have spent the last 4 days trying to to use this as a drop in replacement for the canvas API if it hadn't told me that's what it was useful for.

g… via monorail

unread,
Dec 6, 2021, 5:28:49 PM12/6/21
to bu...@skia.org

Comment #7 on issue 12705 by gm...@chromium.org: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c7

Sorry for the last comment's tone

I'm only guessing though that supporting textAlign and textBaseAlign are not that hard? If you can do measureText then textAlign seems like

ctx.fillText = function(txt, x, y) {
switch (this.textAlign) {
case 'middle':
x -= this.measureText(txt).width / 2;
break;
case 'right':
case 'end':
x -= this.measureText(txt).width;
break;
}

....
}

Seems like textBaseline is similarly simple.

As for 3, I wasn't suggesting stylesheets, i was only suggesting indirection which actually I think is already there. I was unfamiliar with the code at that point and was getting confused between the examples using the ParagraphAPI (no indirection) and the ones using the canvas2d emulation.

marcu… via monorail

unread,
Dec 7, 2021, 7:03:50 AM12/7/21
to bu...@skia.org

Comment #8 on issue 12705 by marcu...@gmail.com: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c8

There's also text direction, but I guess it should be easy to have that naïve implementation. Text rendering is a bag of dragons tho...

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign

kjlub… via monorail

unread,
Dec 7, 2021, 8:20:52 AM12/7/21
to bu...@skia.org

Comment #9 on issue 12705 by kjlu...@google.com: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c9

I accept your apology in #c7.

I might just be feeling some trepidation around this as per #c8 "Text rendering is a bag of dragons". A naïve implementation that works for ASCII characters is probably as straightforward as you point out.

A more general text solution is much much much more complicated as can be evidenced by the ~15 kLOC from SkParagraph, the ~96 kLOC from Harfbuzz, and the >300 kLOC from ICU.

If the naïve implementation is better than nothing (and we'll make sure the documentation reflects the actual capabilities), then I can try implementing that.

Git Watcher via monorail

unread,
Dec 9, 2021, 8:08:07 AM12/9/21
to bu...@skia.org

Comment #10 on issue 12705 by Git Watcher: canvaskit-wasm doesn not support measureText
https://bugs.chromium.org/p/skia/issues/detail?id=12705#c10


The following revision refers to this bug:
https://skia.googlesource.com/skia/+/5d1d92c505c000ff0831dd47401c8b3c48e73fa8

commit 5d1d92c505c000ff0831dd47401c8b3c48e73fa8
Author: Kevin Lubick <kjlu...@google.com>
Date: Tue Dec 07 20:15:08 2021

[canvaskit] Add rough measureText to Canvas2D emulation layer

I wanted to use SkParagraph myself, but the API is a little
awkward right now in that I cannot just pass in a SkFont object
(which I have) - I would have to make a FontCollection, which
we lack the ability to do so.

Change-Id: I1488fb9c1a42af020a245a792b8e266c809b599a
Bug: skia:12705
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/481238
Reviewed-by: Nathaniel Nifong <nif...@google.com>

[modify] https://crrev.com/5d1d92c505c000ff0831dd47401c8b3c48e73fa8/modules/canvaskit/npm_build/README.md
[modify] https://crrev.com/5d1d92c505c000ff0831dd47401c8b3c48e73fa8/modules/canvaskit/htmlcanvas/canvas2dcontext.js
[modify] https://crrev.com/5d1d92c505c000ff0831dd47401c8b3c48e73fa8/modules/canvaskit/CHANGELOG.md
[modify] https://crrev.com/5d1d92c505c000ff0831dd47401c8b3c48e73fa8/modules/canvaskit/tests/canvas2d.spec.js
[modify] https://crrev.com/5d1d92c505c000ff0831dd47401c8b3c48e73fa8/modules/canvaskit/npm_build/example.html
Reply all
Reply to author
Forward
0 new messages