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 (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 | |