1#ifndef OT_LAYOUT_GSUB_SINGLESUBST_HH
2#define OT_LAYOUT_GSUB_SINGLESUBST_HH
3
4#include "Common.hh"
5#include "SingleSubstFormat1.hh"
6#include "SingleSubstFormat2.hh"
7
8namespace OT {
9namespace Layout {
10namespace GSUB_impl {
11
12struct SingleSubst
13{
14 protected:
15 union {
16 HBUINT16 format; /* Format identifier */
17 SingleSubstFormat1_3<SmallTypes> format1;
18 SingleSubstFormat2_4<SmallTypes> format2;
19#ifndef HB_NO_BEYOND_64K
20 SingleSubstFormat1_3<MediumTypes> format3;
21 SingleSubstFormat2_4<MediumTypes> format4;
22#endif
23 } u;
24
25 public:
26
27 template <typename context_t, typename ...Ts>
28 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
29 {
30 if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
31 TRACE_DISPATCH (this, u.format);
32 switch (u.format) {
33 case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
34 case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
35#ifndef HB_NO_BEYOND_64K
36 case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
37 case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
38#endif
39 default:return_trace (c->default_return_value ());
40 }
41 }
42
43 template<typename Iterator,
44 hb_requires (hb_is_sorted_source_of (Iterator,
45 const hb_codepoint_pair_t))>
46 bool serialize (hb_serialize_context_t *c,
47 Iterator glyphs)
48 {
49 TRACE_SERIALIZE (this);
50 if (unlikely (!c->extend_min (u.format))) return_trace (false);
51 unsigned format = 2;
52 unsigned delta = 0;
53 if (glyphs)
54 {
55 format = 1;
56 hb_codepoint_t mask = 0xFFFFu;
57
58#ifndef HB_NO_BEYOND_64K
59 if (+ glyphs
60 | hb_map_retains_sorting (hb_second)
61 | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
62 {
63 format += 2;
64 mask = 0xFFFFFFu;
65 }
66#endif
67
68 auto get_delta = [=] (hb_codepoint_pair_t _)
69 { return (unsigned) (_.second - _.first) & mask; };
70 delta = get_delta (*glyphs);
71 if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
72 }
73
74 u.format = format;
75 switch (u.format) {
76 case 1: return_trace (u.format1.serialize (c,
77 + glyphs
78 | hb_map_retains_sorting (hb_first),
79 delta));
80 case 2: return_trace (u.format2.serialize (c, glyphs));
81#ifndef HB_NO_BEYOND_64K
82 case 3: return_trace (u.format3.serialize (c,
83 + glyphs
84 | hb_map_retains_sorting (hb_first),
85 delta));
86 case 4: return_trace (u.format4.serialize (c, glyphs));
87#endif
88 default:return_trace (false);
89 }
90 }
91};
92
93template<typename Iterator>
94static void
95SingleSubst_serialize (hb_serialize_context_t *c,
96 Iterator it)
97{ c->start_embed<SingleSubst> ()->serialize (c, it); }
98
99}
100}
101}
102
103#endif /* OT_LAYOUT_GSUB_SINGLESUBST_HH */
104