1 #ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
2 #define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
11 HBUINT16 format; /* Format identifier--format = 3 */
12 FWORD xCoordinate; /* Horizontal value--in design units */
13 FWORD yCoordinate; /* Vertical value--in design units */
15 xDeviceTable; /* Offset to Device table for X
16 * coordinate-- from beginning of
17 * Anchor table (may be NULL) */
19 yDeviceTable; /* Offset to Device table for Y
20 * coordinate-- from beginning of
21 * Anchor table (may be NULL) */
23 DEFINE_SIZE_STATIC (10);
25 bool sanitize (hb_sanitize_context_t *c) const
27 TRACE_SANITIZE (this);
28 if (unlikely (!c->check_struct (this))) return_trace (false);
30 return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
33 void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
34 float *x, float *y) const
36 hb_font_t *font = c->font;
37 *x = font->em_fscale_x (xCoordinate);
38 *y = font->em_fscale_y (yCoordinate);
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);
46 bool subset (hb_subset_context_t *c) const
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);
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)
57 hb_pair_t<unsigned, int> *new_varidx_delta;
58 if (!c->plan->layout_variation_idx_delta_map.has (x_varidx, &new_varidx_delta))
61 x_varidx = hb_first (*new_varidx_delta);
62 int delta = hb_second (*new_varidx_delta);
65 if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
66 HB_SERIALIZE_ERROR_INT_OVERFLOW))
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)
74 hb_pair_t<unsigned, int> *new_varidx_delta;
75 if (!c->plan->layout_variation_idx_delta_map.has (y_varidx, &new_varidx_delta))
78 y_varidx = hb_first (*new_varidx_delta);
79 int delta = hb_second (*new_varidx_delta);
82 if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
83 HB_SERIALIZE_ERROR_INT_OVERFLOW))
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));
94 if (!c->serializer->embed (xDeviceTable)) return_trace (false);
95 if (!c->serializer->embed (yDeviceTable)) return_trace (false);
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);
102 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
104 (this+xDeviceTable).collect_variation_indices (c);
105 (this+yDeviceTable).collect_variation_indices (c);
114 #endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH