Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / src / OT / Layout / GSUB / SingleSubst.hh
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
8 namespace OT {
9 namespace Layout {
10 namespace GSUB_impl {
11
12 struct 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
93 template<typename Iterator>
94 static void
95 SingleSubst_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 */