[>64k:layout:SingleSubst] Implement format 3/4

Implements https://github.com/be-fonts/boring-expansion-spec/issues/31
This commit is contained in:
Behdad Esfahbod 2022-07-06 13:28:17 -06:00
parent e3caf8d50a
commit 8775e9b4a4
2 changed files with 31 additions and 3 deletions

View File

@ -16,6 +16,10 @@ struct SingleSubst
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
SingleSubstFormat1_3<SmallTypes> format1; SingleSubstFormat1_3<SmallTypes> format1;
SingleSubstFormat2_4<SmallTypes> format2; SingleSubstFormat2_4<SmallTypes> format2;
#ifndef HB_NO_BORING_EXPANSION
SingleSubstFormat1_3<MediumTypes> format3;
SingleSubstFormat2_4<MediumTypes> format4;
#endif
} u; } u;
public: public:
@ -28,6 +32,10 @@ struct SingleSubst
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }
@ -45,11 +53,24 @@ struct SingleSubst
if (glyphs) if (glyphs)
{ {
format = 1; format = 1;
auto get_delta = [=] (hb_codepoint_pair_t _) hb_codepoint_t mask = 0xFFFFu;
{ return (unsigned) (_.second - _.first) & 0xFFFF; };
delta = get_delta (*glyphs); #ifndef HB_NO_BORING_EXPANSION
if (!hb_all (++(+glyphs), delta, get_delta)) format = 2; if (+ glyphs
| hb_map_retains_sorting (hb_first)
| hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
{
format += 2;
mask = 0xFFFFFFu;
} }
#endif
auto get_delta = [=] (hb_codepoint_pair_t _)
{ return (unsigned) (_.second - _.first) & mask; };
delta = get_delta (*glyphs);
if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
}
u.format = format; u.format = format;
switch (u.format) { switch (u.format) {
case 1: return_trace (u.format1.serialize (c, case 1: return_trace (u.format1.serialize (c,
@ -57,6 +78,13 @@ struct SingleSubst
| hb_map_retains_sorting (hb_first), | hb_map_retains_sorting (hb_first),
delta)); delta));
case 2: return_trace (u.format2.serialize (c, glyphs)); case 2: return_trace (u.format2.serialize (c, glyphs));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.serialize (c,
+ glyphs
| hb_map_retains_sorting (hb_first),
delta));
case 4: return_trace (u.format4.serialize (c, glyphs));
#endif
default:return_trace (false); default:return_trace (false);
} }
} }

View File

@ -104,7 +104,7 @@ struct SingleSubstFormat2_4
+ hb_zip (this+coverage, substitute) + hb_zip (this+coverage, substitute)
| hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_first)
| hb_filter (glyphset, hb_second) | hb_filter (glyphset, hb_second)
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
; ;