1#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
2#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
3
4namespace OT {
5namespace Layout {
6namespace GPOS_impl {
7
8struct 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 (c->plan->layout_variation_idx_delta_map.has (x_varidx))
56 {
57 int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (x_varidx));
58 if (delta != 0)
59 {
60 if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
61 HB_SERIALIZE_ERROR_INT_OVERFLOW))
62 return_trace (false);
63 }
64 }
65
66 unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
67 if (c->plan->layout_variation_idx_delta_map.has (y_varidx))
68 {
69 int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (y_varidx));
70 if (delta != 0)
71 {
72 if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
73 HB_SERIALIZE_ERROR_INT_OVERFLOW))
74 return_trace (false);
75 }
76 }
77
78 if (c->plan->all_axes_pinned)
79 return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
80
81 if (!c->serializer->embed (xDeviceTable)) return_trace (false);
82 if (!c->serializer->embed (yDeviceTable)) return_trace (false);
83
84 out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
85 out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
86 return_trace (out);
87 }
88
89 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
90 {
91 (this+xDeviceTable).collect_variation_indices (c);
92 (this+yDeviceTable).collect_variation_indices (c);
93 }
94};
95
96
97}
98}
99}
100
101#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
102