whatwg / html

HTML Standard

Home Page:https://html.spec.whatwg.org/multipage/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TextMetrics doesn't have an initial advance attribute

litherum opened this issue · comments

There's a collection of advances, but no initial advance. The initial advance is used in complex scripts where the first glyph in the string has to draw before the origin.

Oh, it's a very good point.

Can I ask a clarification; is it the initial glyph advance, or the initial glyph offset? Our logic is like this:

  1. The layout engine has a current_pen_point.
  2. Each glyph is drawn at current_pen_point + glyph_offset.
  3. After each glyph is drawn, current_pen_point += glyph_advance.

So our logic handles the initial glyph positioning as an offset, and offsets are not accumulated to the advance. IIUC this is what OpenType has in its format, but I'm mostly seeing it through HarfBuzz API surface, so I might be wrong for other formats or platform APIs.


(Terminologies are old because the best picture I could find in OpenType spec was for TrueType 1.0)

If we were going to the initial advance model, I think we need how to compute it when the underlying API or format provides the initial offset but not the initial advance, whether it should be zero or it should be synthesized. If we were going with advances and offsets model, I think we need initialOffset member separately from advances, or it could even be offsets array. Probably offsets array is not useful unless we also provide glyph bounding box?

/cc @FremyCompany @dbaron @jfkthame @fserb @domenic @eaenet @whatwg/canvas

Right, that model is the same as the OpenType model. The good thing about that model is that it includes both visual information and layout information in a single place; the glyph_offset isn't used for layout, but is used for painting. The bad thing about that model is that it's pretty complicated to understand.

In WebKit, we use a slightly different model, where we completely separate paint information from layout information, and put the information into different data structures. Each data structure is just a flat array of advances. Layout information doesn't need an initial advance, but paint information does.

I made an ascii-art picture of it here inside the WebKit source: https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/ComplexTextController.h#L108

In order to have rendering consistent with the browser, one or the other needs to be exposed. I assume that the advances exposed by this API are visual advances, not layout advances. I recommend the WebKit way because it's simpler to understand and use.

Thank you, the ascii-chart looks great!! I understand the distinction much clearer.

In your terminology, I thought advances are about layout advance. We only have layout advance and use it to layout. As I wrote above, we have glyph offset too, but it's only for paint and computing glyph bounding boxes.

As I re-read the OpenType spec now, I found the spec for hmtx says:

In a font with CFF version 1 outline data, the 'CFF ' table does include advance widths. These values are used by PostScript processors, but are not used in OpenType layout. In an OpenType context, the 'hmtx' table is required and must be used for advance widths.

From this I'm guessing that paint advance is the one in CFF table and layout advance is the one in hmtx table, and TrueType has only layout advance?

From this I'm guessing that paint advance is the one in CFF table and layout advance is the one in hmtx table, and TrueType has only layout advance?

Nope, that's not right. A font where CFF disagrees with hmtx is a broken font. (I learned this the hard way...)

The offsets come from the GPOS table. You only get them if you have font features.

This type of confusion that you had is exactly the reason that a flat set of advances is a better API than a hybrid advance/offset combination.

Originally, transforming the data into a flat list of paint advances was required for us because it's the interface to the text drawing routine we used. Now, it's no longer required because we switched to one that accepts positions instead of advances, but the argument still holds. Either way, the "two separate flat lists" approach doesn't require diagrams, but the hybrid advance/offset does.

It would definitely be a mistake for this API to produce layout advances because this is a canvas API, which is presumably used for drawing things. If clients use this API to draw characters, the characters would all end up at the wrong place.

Thank you for the explanation. It clarifies that I didn't understand the differences between the two correctly, please give me some time to learn further.

In the meantime, allow me to comment that we would like this API and Houdini Font Metrics API as much compatible as possible, or even unify if possible. So great if we can try to cover the use cases both for canvas and for the layout purposes. I hope this goal is good to us all.

It would definitely be a mistake for this API to produce layout advances because this is a canvas API, which is presumably used for drawing things.

I think this API is confused, and doesn't adequately address the character/glyph model of text rendering. (See #4026.) If "this is a canvas API ... used for drawing", it should work in terms of the things that are actually drawn to the canvas, which are glyphs, not characters.

If clients use this API to draw characters, the characters would all end up at the wrong place.

So how are clients going to use this API to do anything useful, except in simple cases where there's basically a 1:1 character/glyph mapping?

I think this API is confused

I think you're right. These discussions we're having would benefit from some use cases.

In the meantime, allow me to comment that we would like this API and Houdini Font Metrics API as much compatible as possible, or even unify if possible.

+1

The API is based on characters, not glyphs, so this issue is completely moot to begin with.