xref: /aosp_15_r20/external/harfbuzz_ng/src/OT/Layout/GPOS/AnchorFormat3.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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 
sanitizeOT::Layout::GPOS_impl::AnchorFormat325   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 
get_anchorOT::Layout::GPOS_impl::AnchorFormat333   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     {
42       hb_barrier ();
43       *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
44     }
45     if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
46     {
47       hb_barrier ();
48       *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
49     }
50   }
51 
subsetOT::Layout::GPOS_impl::AnchorFormat352   bool subset (hb_subset_context_t *c) const
53   {
54     TRACE_SUBSET (this);
55     auto *out = c->serializer->start_embed (*this);
56     if (unlikely (!c->serializer->embed (format))) return_trace (false);
57     if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
58     if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
59 
60     unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
61     if (x_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
62     {
63       hb_pair_t<unsigned, int> *new_varidx_delta;
64       if (!c->plan->layout_variation_idx_delta_map.has (x_varidx, &new_varidx_delta))
65         return_trace (false);
66 
67       x_varidx = hb_first (*new_varidx_delta);
68       int delta = hb_second (*new_varidx_delta);
69       if (delta != 0)
70       {
71         if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
72                                           HB_SERIALIZE_ERROR_INT_OVERFLOW))
73           return_trace (false);
74       }
75     }
76 
77     unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
78     if (y_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
79     {
80       hb_pair_t<unsigned, int> *new_varidx_delta;
81       if (!c->plan->layout_variation_idx_delta_map.has (y_varidx, &new_varidx_delta))
82         return_trace (false);
83 
84       y_varidx = hb_first (*new_varidx_delta);
85       int delta = hb_second (*new_varidx_delta);
86       if (delta != 0)
87       {
88         if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
89                                           HB_SERIALIZE_ERROR_INT_OVERFLOW))
90           return_trace (false);
91       }
92     }
93 
94     /* in case that all axes are pinned or no variations after instantiation,
95      * both var_idxes will be mapped to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */
96     if (x_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX &&
97         y_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
98       return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
99 
100     if (!c->serializer->embed (xDeviceTable)) return_trace (false);
101     if (!c->serializer->embed (yDeviceTable)) return_trace (false);
102 
103     out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
104     out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
105     return_trace (out);
106   }
107 
collect_variation_indicesOT::Layout::GPOS_impl::AnchorFormat3108   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
109   {
110     (this+xDeviceTable).collect_variation_indices (c);
111     (this+yDeviceTable).collect_variation_indices (c);
112   }
113 };
114 
115 
116 }
117 }
118 }
119 
120 #endif  // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
121