[HarfBuzz] HarfBuzz 1.0 API; the message you were hoping would never come

Behdad Esfahbod behdad at behdad.org
Thu Jan 23 13:36:31 PST 2014


On 14-01-23 03:54 PM, Konstantin Ritt wrote:
> Hi guys,
> 
> There is yet another issue left out of the scope: 
> hb_position_t is a typedef of int32_t, you know, and to avoid float-to-integer
> truncation the proposed solution was to specify scale factor shifted left.
> For example to make all results in 26.6 float format, scale shall be shifted 6
> bits left and then the result must be divided to 64.0 to get the original
> float (well, almost original but 6 digit after the point is quite enough for
> all use-cases).

So far so good.


> However, the scale factor applied to results in OT shaper only,

The OT shaper doesn't know about the scale factor whatsoever.  And it
shouldn't need to.


> the other
> shapers doesn't respect the scale factor and truncation may occur there (i.e.
> double advance = ..; pos->x_advance = advance;). This also leads to unexpected
> results since 1) pos->x_advance / 64.0 ~= 0 and 2)
> CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL)
> falls back to pointSize=12 when y_scale is out of bounds. (BTW, what ppem is
> for, then?)

Then this is a bug that should be fixed.  We should just use font->y_scale /
64. here, and scale back the results accordingly.


> I'd propose change hb_position_t to be in 26.6 float format everywhere and
> explicitly mention that in the docs.

The 26.6 is NOT enforced and is NOT a limitation of the code.  For example,
you can do all layout in "font space" by setting scale to upem.


> This would guarantee an expected/unified
> results for any shaper, w/o having to do some tricky scaling.

That tricky scaling shouldn't be needed.  If it is, it's a bug we should fix.


> We could also want to introduce an API to fine-tune the hinting preference, so
> that all metrics would be either in design units or in hinted advances (after
> a brief review, it looks like it isn't possible to achieve that on client side
> only).

It is.  But you need to know what you are using first and what you have set up
to return in your font callbacks.  Right?

behdad


> Correct me if I'm wrong.
> 
> Best regards,
> Konstantin
> 
> 2014/1/6 Konstantin Ritt <ritt.ks at gmail.com <mailto:ritt.ks at gmail.com>>
> 
> 
>     2014/1/6 Khaled Hosny <khaledhosny at eglug.org <mailto:khaledhosny at eglug.org>>
> 
>         Another thing that I’d like to see sorted before the API is finalised,
>         is reverse mapping of output glyphs to input characters with proper
>         handling of combing marks. I feel we should keep the current cluster
>         stuff since it might have its uses (I’m not sure though) and introduce a
>         separate way for that mapping. Either way, I think a more indicative
>         name would be better (it took me sometime to understand what those
>         clusters are for and they mislead me quit a bit when I tried to use
>         HarfBuzz for the first time).
> 
>         Regards,
>         Khaled
> 
> 
>     Oh, I thought I'm the only one who felt into that trouble :)
> 
>     Here is a result of my tries and fails:
>     [code]
> 
>             ushort *log_clusters = ...;
> 
> 
> 
>             const uint num_glyphs = hb_buffer_get_length(buffer);
> 
> 
> 
>             hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, 0);
> 
>             for (uint i = 0; i < num_glyphs; ++i) {
> 
>                 log_clusters[i] = infos[i].cluster;
> 
> 
> 
>                 // ... glyphs[i] = infos[i].codepoint; and so on
> 
>             }
> 
> 
>             // adjust clusters
> 
>             uint glyph_pos = 0;
> 
>             for (uint i = 0; i < num_characters; ++i) {
> 
>                 if (i != infos[glyph_pos].cluster) {
> 
>                     for (uint j = glyph_pos + 1; j < num_glyphs; ++j) {
> 
>                         if (i <= infos[j].cluster) {
> 
>                             if (i == infos[j].cluster)
> 
>                                 glyph_pos = j;
> 
>                             break;
> 
>                         }
> 
>                     }
> 
>                 }
> 
>                 log_clusters[i] = glyph_pos;
> 
>             }
> 
>     [/code]
> 
>     You could agree that the latter part is not obvious.
>     And except of bringing some inconvenience to the user, lack of reverse
>     mapping API also hits the performance a bit since we can not avoid this
>     loop with "if (num_glyphs != num_characters)".
> 
>     Regards,
>     Konstantin
> 
> 

-- 
behdad
http://behdad.org/


More information about the HarfBuzz mailing list