Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / src / OT / Layout / GPOS / AnchorFormat3.hh
1 #ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
2 #define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
3
4 namespace OT {
5 namespace Layout {
6 namespace GPOS_impl {
7
8 struct AnchorFormat3
9 {
10   protected:
11   HBUINT16      format;                 /* Format identifier--format = 3 */
12   FWORD         xCoordinate;            /* Horizontal value--in design units */
13   FWORD         yCoordinate;            /* Vertical value--in design units */
14   Offset16To<Device>
15                 xDeviceTable;           /* Offset to Device table for X
16                                          * coordinate-- from beginning of
17                                          * Anchor table (may be NULL) */
18   Offset16To<Device>
19                 yDeviceTable;           /* Offset to Device table for Y
20                                          * coordinate-- from beginning of
21                                          * Anchor table (may be NULL) */
22   public:
23   DEFINE_SIZE_STATIC (10);
24
25   bool sanitize (hb_sanitize_context_t *c) const
26   {
27     TRACE_SANITIZE (this);
28     if (unlikely (!c->check_struct (this))) return_trace (false);
29
30     return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
31   }
32
33   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
34                    float *x, float *y) const
35   {
36     hb_font_t *font = c->font;
37     *x = font->em_fscale_x (xCoordinate);
38     *y = font->em_fscale_y (yCoordinate);
39
40     if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
41       *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
42     if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
43       *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
44   }
45
46   bool subset (hb_subset_context_t *c) const
47   {
48     TRACE_SUBSET (this);
49     auto *out = c->serializer->start_embed (*this);
50     if (unlikely (!c->serializer->embed (format))) return_trace (false);
51     if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
52     if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
53
54     unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
55     if (x_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
56     {
57       hb_pair_t<unsigned, int> *new_varidx_delta;
58       if (!c->plan->layout_variation_idx_delta_map.has (x_varidx, &new_varidx_delta))
59         return_trace (false);
60      
61       x_varidx = hb_first (*new_varidx_delta);
62       int delta = hb_second (*new_varidx_delta);
63       if (delta != 0)
64       {
65         if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
66                                           HB_SERIALIZE_ERROR_INT_OVERFLOW))
67           return_trace (false);
68       }
69     }
70
71     unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
72     if (y_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
73     {
74       hb_pair_t<unsigned, int> *new_varidx_delta;
75       if (!c->plan->layout_variation_idx_delta_map.has (y_varidx, &new_varidx_delta))
76         return_trace (false);
77
78       y_varidx = hb_first (*new_varidx_delta);
79       int delta = hb_second (*new_varidx_delta);
80       if (delta != 0)
81       {
82         if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
83                                           HB_SERIALIZE_ERROR_INT_OVERFLOW))
84           return_trace (false);
85       }
86     }
87
88     /* in case that all axes are pinned or no variations after instantiation,
89      * both var_idxes will be mapped to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */
90     if (x_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX &&
91         y_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
92       return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
93
94     if (!c->serializer->embed (xDeviceTable)) return_trace (false);
95     if (!c->serializer->embed (yDeviceTable)) return_trace (false);
96
97     out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
98     out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
99     return_trace (out);
100   }
101
102   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
103   {
104     (this+xDeviceTable).collect_variation_indices (c);
105     (this+yDeviceTable).collect_variation_indices (c);
106   }
107 };
108
109
110 }
111 }
112 }
113
114 #endif  // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH