1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_GLYPH_HH 2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_GLYPH_HH 3*2d1272b8SAndroid Build Coastguard Worker 4*2d1272b8SAndroid Build Coastguard Worker 5*2d1272b8SAndroid Build Coastguard Worker #include "../../hb-open-type.hh" 6*2d1272b8SAndroid Build Coastguard Worker 7*2d1272b8SAndroid Build Coastguard Worker #include "GlyphHeader.hh" 8*2d1272b8SAndroid Build Coastguard Worker #include "SimpleGlyph.hh" 9*2d1272b8SAndroid Build Coastguard Worker #include "CompositeGlyph.hh" 10*2d1272b8SAndroid Build Coastguard Worker 11*2d1272b8SAndroid Build Coastguard Worker 12*2d1272b8SAndroid Build Coastguard Worker namespace OT { 13*2d1272b8SAndroid Build Coastguard Worker 14*2d1272b8SAndroid Build Coastguard Worker struct glyf_accelerator_t; 15*2d1272b8SAndroid Build Coastguard Worker 16*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl { 17*2d1272b8SAndroid Build Coastguard Worker 18*2d1272b8SAndroid Build Coastguard Worker 19*2d1272b8SAndroid Build Coastguard Worker enum phantom_point_index_t 20*2d1272b8SAndroid Build Coastguard Worker { 21*2d1272b8SAndroid Build Coastguard Worker PHANTOM_LEFT = 0, 22*2d1272b8SAndroid Build Coastguard Worker PHANTOM_RIGHT = 1, 23*2d1272b8SAndroid Build Coastguard Worker PHANTOM_TOP = 2, 24*2d1272b8SAndroid Build Coastguard Worker PHANTOM_BOTTOM = 3, 25*2d1272b8SAndroid Build Coastguard Worker PHANTOM_COUNT = 4 26*2d1272b8SAndroid Build Coastguard Worker }; 27*2d1272b8SAndroid Build Coastguard Worker 28*2d1272b8SAndroid Build Coastguard Worker struct Glyph 29*2d1272b8SAndroid Build Coastguard Worker { 30*2d1272b8SAndroid Build Coastguard Worker enum glyph_type_t { 31*2d1272b8SAndroid Build Coastguard Worker EMPTY, 32*2d1272b8SAndroid Build Coastguard Worker SIMPLE, 33*2d1272b8SAndroid Build Coastguard Worker COMPOSITE, 34*2d1272b8SAndroid Build Coastguard Worker }; 35*2d1272b8SAndroid Build Coastguard Worker 36*2d1272b8SAndroid Build Coastguard Worker public: get_composite_iteratorOT::glyf_impl::Glyph37*2d1272b8SAndroid Build Coastguard Worker composite_iter_t get_composite_iterator () const 38*2d1272b8SAndroid Build Coastguard Worker { 39*2d1272b8SAndroid Build Coastguard Worker if (type != COMPOSITE) return composite_iter_t (); 40*2d1272b8SAndroid Build Coastguard Worker return CompositeGlyph (*header, bytes).iter (); 41*2d1272b8SAndroid Build Coastguard Worker } 42*2d1272b8SAndroid Build Coastguard Worker trim_paddingOT::glyf_impl::Glyph43*2d1272b8SAndroid Build Coastguard Worker const hb_bytes_t trim_padding () const 44*2d1272b8SAndroid Build Coastguard Worker { 45*2d1272b8SAndroid Build Coastguard Worker switch (type) { 46*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding (); 47*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding (); 48*2d1272b8SAndroid Build Coastguard Worker case EMPTY: return bytes; 49*2d1272b8SAndroid Build Coastguard Worker default: return bytes; 50*2d1272b8SAndroid Build Coastguard Worker } 51*2d1272b8SAndroid Build Coastguard Worker } 52*2d1272b8SAndroid Build Coastguard Worker drop_hintsOT::glyf_impl::Glyph53*2d1272b8SAndroid Build Coastguard Worker void drop_hints () 54*2d1272b8SAndroid Build Coastguard Worker { 55*2d1272b8SAndroid Build Coastguard Worker switch (type) { 56*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return; 57*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return; 58*2d1272b8SAndroid Build Coastguard Worker case EMPTY: return; 59*2d1272b8SAndroid Build Coastguard Worker } 60*2d1272b8SAndroid Build Coastguard Worker } 61*2d1272b8SAndroid Build Coastguard Worker set_overlaps_flagOT::glyf_impl::Glyph62*2d1272b8SAndroid Build Coastguard Worker void set_overlaps_flag () 63*2d1272b8SAndroid Build Coastguard Worker { 64*2d1272b8SAndroid Build Coastguard Worker switch (type) { 65*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return; 66*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return; 67*2d1272b8SAndroid Build Coastguard Worker case EMPTY: return; 68*2d1272b8SAndroid Build Coastguard Worker } 69*2d1272b8SAndroid Build Coastguard Worker } 70*2d1272b8SAndroid Build Coastguard Worker drop_hints_bytesOT::glyf_impl::Glyph71*2d1272b8SAndroid Build Coastguard Worker void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const 72*2d1272b8SAndroid Build Coastguard Worker { 73*2d1272b8SAndroid Build Coastguard Worker switch (type) { 74*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return; 75*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return; 76*2d1272b8SAndroid Build Coastguard Worker case EMPTY: return; 77*2d1272b8SAndroid Build Coastguard Worker } 78*2d1272b8SAndroid Build Coastguard Worker } 79*2d1272b8SAndroid Build Coastguard Worker is_compositeOT::glyf_impl::Glyph80*2d1272b8SAndroid Build Coastguard Worker bool is_composite () const 81*2d1272b8SAndroid Build Coastguard Worker { return type == COMPOSITE; } 82*2d1272b8SAndroid Build Coastguard Worker get_all_points_without_varOT::glyf_impl::Glyph83*2d1272b8SAndroid Build Coastguard Worker bool get_all_points_without_var (const hb_face_t *face, 84*2d1272b8SAndroid Build Coastguard Worker contour_point_vector_t &points /* OUT */) const 85*2d1272b8SAndroid Build Coastguard Worker { 86*2d1272b8SAndroid Build Coastguard Worker switch (type) { 87*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: 88*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points))) 89*2d1272b8SAndroid Build Coastguard Worker return false; 90*2d1272b8SAndroid Build Coastguard Worker break; 91*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: 92*2d1272b8SAndroid Build Coastguard Worker { 93*2d1272b8SAndroid Build Coastguard Worker for (auto &item : get_composite_iterator ()) 94*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!item.get_points (points))) return false; 95*2d1272b8SAndroid Build Coastguard Worker break; 96*2d1272b8SAndroid Build Coastguard Worker } 97*2d1272b8SAndroid Build Coastguard Worker case EMPTY: 98*2d1272b8SAndroid Build Coastguard Worker break; 99*2d1272b8SAndroid Build Coastguard Worker } 100*2d1272b8SAndroid Build Coastguard Worker 101*2d1272b8SAndroid Build Coastguard Worker /* Init phantom points */ 102*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false; 103*2d1272b8SAndroid Build Coastguard Worker hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); 104*2d1272b8SAndroid Build Coastguard Worker { 105*2d1272b8SAndroid Build Coastguard Worker int lsb = 0; 106*2d1272b8SAndroid Build Coastguard Worker int h_delta = face->table.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ? 107*2d1272b8SAndroid Build Coastguard Worker (int) header->xMin - lsb : 0; 108*2d1272b8SAndroid Build Coastguard Worker HB_UNUSED int tsb = 0; 109*2d1272b8SAndroid Build Coastguard Worker int v_orig = (int) header->yMax + 110*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL 111*2d1272b8SAndroid Build Coastguard Worker ((void) face->table.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb) 112*2d1272b8SAndroid Build Coastguard Worker #else 113*2d1272b8SAndroid Build Coastguard Worker 0 114*2d1272b8SAndroid Build Coastguard Worker #endif 115*2d1272b8SAndroid Build Coastguard Worker ; 116*2d1272b8SAndroid Build Coastguard Worker unsigned h_adv = face->table.hmtx->get_advance_without_var_unscaled (gid); 117*2d1272b8SAndroid Build Coastguard Worker unsigned v_adv = 118*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL 119*2d1272b8SAndroid Build Coastguard Worker face->table.vmtx->get_advance_without_var_unscaled (gid) 120*2d1272b8SAndroid Build Coastguard Worker #else 121*2d1272b8SAndroid Build Coastguard Worker - face->get_upem () 122*2d1272b8SAndroid Build Coastguard Worker #endif 123*2d1272b8SAndroid Build Coastguard Worker ; 124*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_LEFT].x = h_delta; 125*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta; 126*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_TOP].y = v_orig; 127*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv; 128*2d1272b8SAndroid Build Coastguard Worker } 129*2d1272b8SAndroid Build Coastguard Worker return true; 130*2d1272b8SAndroid Build Coastguard Worker } 131*2d1272b8SAndroid Build Coastguard Worker update_mtxOT::glyf_impl::Glyph132*2d1272b8SAndroid Build Coastguard Worker void update_mtx (const hb_subset_plan_t *plan, 133*2d1272b8SAndroid Build Coastguard Worker int xMin, int xMax, 134*2d1272b8SAndroid Build Coastguard Worker int yMin, int yMax, 135*2d1272b8SAndroid Build Coastguard Worker const contour_point_vector_t &all_points) const 136*2d1272b8SAndroid Build Coastguard Worker { 137*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_gid = 0; 138*2d1272b8SAndroid Build Coastguard Worker if (!plan->new_gid_for_old_gid (gid, &new_gid)) 139*2d1272b8SAndroid Build Coastguard Worker return; 140*2d1272b8SAndroid Build Coastguard Worker 141*2d1272b8SAndroid Build Coastguard Worker if (type != EMPTY) 142*2d1272b8SAndroid Build Coastguard Worker { 143*2d1272b8SAndroid Build Coastguard Worker plan->bounds_width_vec[new_gid] = xMax - xMin; 144*2d1272b8SAndroid Build Coastguard Worker plan->bounds_height_vec[new_gid] = yMax - yMin; 145*2d1272b8SAndroid Build Coastguard Worker } 146*2d1272b8SAndroid Build Coastguard Worker 147*2d1272b8SAndroid Build Coastguard Worker unsigned len = all_points.length; 148*2d1272b8SAndroid Build Coastguard Worker float leftSideX = all_points[len - 4].x; 149*2d1272b8SAndroid Build Coastguard Worker float rightSideX = all_points[len - 3].x; 150*2d1272b8SAndroid Build Coastguard Worker float topSideY = all_points[len - 2].y; 151*2d1272b8SAndroid Build Coastguard Worker float bottomSideY = all_points[len - 1].y; 152*2d1272b8SAndroid Build Coastguard Worker 153*2d1272b8SAndroid Build Coastguard Worker uint32_t hash = hb_hash (new_gid); 154*2d1272b8SAndroid Build Coastguard Worker 155*2d1272b8SAndroid Build Coastguard Worker signed hori_aw = roundf (rightSideX - leftSideX); 156*2d1272b8SAndroid Build Coastguard Worker if (hori_aw < 0) hori_aw = 0; 157*2d1272b8SAndroid Build Coastguard Worker int lsb = roundf (xMin - leftSideX); 158*2d1272b8SAndroid Build Coastguard Worker plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb)); 159*2d1272b8SAndroid Build Coastguard Worker //flag value should be computed using non-empty glyphs 160*2d1272b8SAndroid Build Coastguard Worker if (type != EMPTY && lsb != xMin) 161*2d1272b8SAndroid Build Coastguard Worker plan->head_maxp_info.allXMinIsLsb = false; 162*2d1272b8SAndroid Build Coastguard Worker 163*2d1272b8SAndroid Build Coastguard Worker signed vert_aw = roundf (topSideY - bottomSideY); 164*2d1272b8SAndroid Build Coastguard Worker if (vert_aw < 0) vert_aw = 0; 165*2d1272b8SAndroid Build Coastguard Worker int tsb = roundf (topSideY - yMax); 166*2d1272b8SAndroid Build Coastguard Worker plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb)); 167*2d1272b8SAndroid Build Coastguard Worker } 168*2d1272b8SAndroid Build Coastguard Worker compile_header_bytesOT::glyf_impl::Glyph169*2d1272b8SAndroid Build Coastguard Worker bool compile_header_bytes (const hb_subset_plan_t *plan, 170*2d1272b8SAndroid Build Coastguard Worker const contour_point_vector_t &all_points, 171*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t &dest_bytes /* OUT */) const 172*2d1272b8SAndroid Build Coastguard Worker { 173*2d1272b8SAndroid Build Coastguard Worker GlyphHeader *glyph_header = nullptr; 174*2d1272b8SAndroid Build Coastguard Worker if (!plan->pinned_at_default && type != EMPTY && all_points.length >= 4) 175*2d1272b8SAndroid Build Coastguard Worker { 176*2d1272b8SAndroid Build Coastguard Worker glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size); 177*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!glyph_header)) return false; 178*2d1272b8SAndroid Build Coastguard Worker } 179*2d1272b8SAndroid Build Coastguard Worker 180*2d1272b8SAndroid Build Coastguard Worker float xMin = 0, xMax = 0; 181*2d1272b8SAndroid Build Coastguard Worker float yMin = 0, yMax = 0; 182*2d1272b8SAndroid Build Coastguard Worker if (all_points.length > 4) 183*2d1272b8SAndroid Build Coastguard Worker { 184*2d1272b8SAndroid Build Coastguard Worker xMin = xMax = all_points[0].x; 185*2d1272b8SAndroid Build Coastguard Worker yMin = yMax = all_points[0].y; 186*2d1272b8SAndroid Build Coastguard Worker 187*2d1272b8SAndroid Build Coastguard Worker unsigned count = all_points.length - 4; 188*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 1; i < count; i++) 189*2d1272b8SAndroid Build Coastguard Worker { 190*2d1272b8SAndroid Build Coastguard Worker float x = all_points[i].x; 191*2d1272b8SAndroid Build Coastguard Worker float y = all_points[i].y; 192*2d1272b8SAndroid Build Coastguard Worker xMin = hb_min (xMin, x); 193*2d1272b8SAndroid Build Coastguard Worker xMax = hb_max (xMax, x); 194*2d1272b8SAndroid Build Coastguard Worker yMin = hb_min (yMin, y); 195*2d1272b8SAndroid Build Coastguard Worker yMax = hb_max (yMax, y); 196*2d1272b8SAndroid Build Coastguard Worker } 197*2d1272b8SAndroid Build Coastguard Worker } 198*2d1272b8SAndroid Build Coastguard Worker 199*2d1272b8SAndroid Build Coastguard Worker 200*2d1272b8SAndroid Build Coastguard Worker // These are destined for storage in a 16 bit field to clamp the values to 201*2d1272b8SAndroid Build Coastguard Worker // fit into a 16 bit signed integer. 202*2d1272b8SAndroid Build Coastguard Worker int rounded_xMin = hb_clamp (roundf (xMin), -32768.0f, 32767.0f); 203*2d1272b8SAndroid Build Coastguard Worker int rounded_xMax = hb_clamp (roundf (xMax), -32768.0f, 32767.0f); 204*2d1272b8SAndroid Build Coastguard Worker int rounded_yMin = hb_clamp (roundf (yMin), -32768.0f, 32767.0f); 205*2d1272b8SAndroid Build Coastguard Worker int rounded_yMax = hb_clamp (roundf (yMax), -32768.0f, 32767.0f); 206*2d1272b8SAndroid Build Coastguard Worker 207*2d1272b8SAndroid Build Coastguard Worker update_mtx (plan, rounded_xMin, rounded_xMax, rounded_yMin, rounded_yMax, all_points); 208*2d1272b8SAndroid Build Coastguard Worker 209*2d1272b8SAndroid Build Coastguard Worker if (type != EMPTY) 210*2d1272b8SAndroid Build Coastguard Worker { 211*2d1272b8SAndroid Build Coastguard Worker plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, rounded_xMin); 212*2d1272b8SAndroid Build Coastguard Worker plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, rounded_yMin); 213*2d1272b8SAndroid Build Coastguard Worker plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, rounded_xMax); 214*2d1272b8SAndroid Build Coastguard Worker plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, rounded_yMax); 215*2d1272b8SAndroid Build Coastguard Worker } 216*2d1272b8SAndroid Build Coastguard Worker 217*2d1272b8SAndroid Build Coastguard Worker /* when pinned at default, no need to compile glyph header 218*2d1272b8SAndroid Build Coastguard Worker * and for empty glyphs: all_points only include phantom points. 219*2d1272b8SAndroid Build Coastguard Worker * just update metrics and then return */ 220*2d1272b8SAndroid Build Coastguard Worker if (!glyph_header) 221*2d1272b8SAndroid Build Coastguard Worker return true; 222*2d1272b8SAndroid Build Coastguard Worker 223*2d1272b8SAndroid Build Coastguard Worker glyph_header->numberOfContours = header->numberOfContours; 224*2d1272b8SAndroid Build Coastguard Worker 225*2d1272b8SAndroid Build Coastguard Worker glyph_header->xMin = rounded_xMin; 226*2d1272b8SAndroid Build Coastguard Worker glyph_header->yMin = rounded_yMin; 227*2d1272b8SAndroid Build Coastguard Worker glyph_header->xMax = rounded_xMax; 228*2d1272b8SAndroid Build Coastguard Worker glyph_header->yMax = rounded_yMax; 229*2d1272b8SAndroid Build Coastguard Worker 230*2d1272b8SAndroid Build Coastguard Worker dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size); 231*2d1272b8SAndroid Build Coastguard Worker return true; 232*2d1272b8SAndroid Build Coastguard Worker } 233*2d1272b8SAndroid Build Coastguard Worker compile_bytes_with_deltasOT::glyf_impl::Glyph234*2d1272b8SAndroid Build Coastguard Worker bool compile_bytes_with_deltas (const hb_subset_plan_t *plan, 235*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font, 236*2d1272b8SAndroid Build Coastguard Worker const glyf_accelerator_t &glyf, 237*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t &dest_start, /* IN/OUT */ 238*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t &dest_end /* OUT */) 239*2d1272b8SAndroid Build Coastguard Worker { 240*2d1272b8SAndroid Build Coastguard Worker contour_point_vector_t all_points, points_with_deltas; 241*2d1272b8SAndroid Build Coastguard Worker unsigned composite_contours = 0; 242*2d1272b8SAndroid Build Coastguard Worker head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info; 243*2d1272b8SAndroid Build Coastguard Worker unsigned *composite_contours_p = &composite_contours; 244*2d1272b8SAndroid Build Coastguard Worker 245*2d1272b8SAndroid Build Coastguard Worker // don't compute head/maxp values when glyph has no contours(type is EMPTY) 246*2d1272b8SAndroid Build Coastguard Worker // also ignore .notdef glyph when --notdef-outline is not enabled 247*2d1272b8SAndroid Build Coastguard Worker if (type == EMPTY || 248*2d1272b8SAndroid Build Coastguard Worker (gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))) 249*2d1272b8SAndroid Build Coastguard Worker { 250*2d1272b8SAndroid Build Coastguard Worker head_maxp_info_p = nullptr; 251*2d1272b8SAndroid Build Coastguard Worker composite_contours_p = nullptr; 252*2d1272b8SAndroid Build Coastguard Worker } 253*2d1272b8SAndroid Build Coastguard Worker 254*2d1272b8SAndroid Build Coastguard Worker if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false)) 255*2d1272b8SAndroid Build Coastguard Worker return false; 256*2d1272b8SAndroid Build Coastguard Worker 257*2d1272b8SAndroid Build Coastguard Worker // .notdef, set type to empty so we only update metrics and don't compile bytes for 258*2d1272b8SAndroid Build Coastguard Worker // it 259*2d1272b8SAndroid Build Coastguard Worker if (gid == 0 && 260*2d1272b8SAndroid Build Coastguard Worker !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) 261*2d1272b8SAndroid Build Coastguard Worker { 262*2d1272b8SAndroid Build Coastguard Worker type = EMPTY; 263*2d1272b8SAndroid Build Coastguard Worker dest_start = hb_bytes_t (); 264*2d1272b8SAndroid Build Coastguard Worker dest_end = hb_bytes_t (); 265*2d1272b8SAndroid Build Coastguard Worker } 266*2d1272b8SAndroid Build Coastguard Worker 267*2d1272b8SAndroid Build Coastguard Worker //dont compile bytes when pinned at default, just recalculate bounds 268*2d1272b8SAndroid Build Coastguard Worker if (!plan->pinned_at_default) 269*2d1272b8SAndroid Build Coastguard Worker { 270*2d1272b8SAndroid Build Coastguard Worker switch (type) 271*2d1272b8SAndroid Build Coastguard Worker { 272*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: 273*2d1272b8SAndroid Build Coastguard Worker if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start, 274*2d1272b8SAndroid Build Coastguard Worker points_with_deltas, 275*2d1272b8SAndroid Build Coastguard Worker dest_end)) 276*2d1272b8SAndroid Build Coastguard Worker return false; 277*2d1272b8SAndroid Build Coastguard Worker break; 278*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: 279*2d1272b8SAndroid Build Coastguard Worker if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points, 280*2d1272b8SAndroid Build Coastguard Worker plan->flags & HB_SUBSET_FLAGS_NO_HINTING, 281*2d1272b8SAndroid Build Coastguard Worker dest_end)) 282*2d1272b8SAndroid Build Coastguard Worker return false; 283*2d1272b8SAndroid Build Coastguard Worker break; 284*2d1272b8SAndroid Build Coastguard Worker case EMPTY: 285*2d1272b8SAndroid Build Coastguard Worker /* set empty bytes for empty glyph 286*2d1272b8SAndroid Build Coastguard Worker * do not use source glyph's pointers */ 287*2d1272b8SAndroid Build Coastguard Worker dest_start = hb_bytes_t (); 288*2d1272b8SAndroid Build Coastguard Worker dest_end = hb_bytes_t (); 289*2d1272b8SAndroid Build Coastguard Worker break; 290*2d1272b8SAndroid Build Coastguard Worker } 291*2d1272b8SAndroid Build Coastguard Worker } 292*2d1272b8SAndroid Build Coastguard Worker 293*2d1272b8SAndroid Build Coastguard Worker if (!compile_header_bytes (plan, all_points, dest_start)) 294*2d1272b8SAndroid Build Coastguard Worker { 295*2d1272b8SAndroid Build Coastguard Worker dest_end.fini (); 296*2d1272b8SAndroid Build Coastguard Worker return false; 297*2d1272b8SAndroid Build Coastguard Worker } 298*2d1272b8SAndroid Build Coastguard Worker return true; 299*2d1272b8SAndroid Build Coastguard Worker } 300*2d1272b8SAndroid Build Coastguard Worker 301*2d1272b8SAndroid Build Coastguard Worker 302*2d1272b8SAndroid Build Coastguard Worker /* Note: Recursively calls itself. 303*2d1272b8SAndroid Build Coastguard Worker * all_points includes phantom points 304*2d1272b8SAndroid Build Coastguard Worker */ 305*2d1272b8SAndroid Build Coastguard Worker template <typename accelerator_t> get_pointsOT::glyf_impl::Glyph306*2d1272b8SAndroid Build Coastguard Worker bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator, 307*2d1272b8SAndroid Build Coastguard Worker contour_point_vector_t &all_points /* OUT */, 308*2d1272b8SAndroid Build Coastguard Worker contour_point_vector_t *points_with_deltas = nullptr, /* OUT */ 309*2d1272b8SAndroid Build Coastguard Worker head_maxp_info_t * head_maxp_info = nullptr, /* OUT */ 310*2d1272b8SAndroid Build Coastguard Worker unsigned *composite_contours = nullptr, /* OUT */ 311*2d1272b8SAndroid Build Coastguard Worker bool shift_points_hori = true, 312*2d1272b8SAndroid Build Coastguard Worker bool use_my_metrics = true, 313*2d1272b8SAndroid Build Coastguard Worker bool phantom_only = false, 314*2d1272b8SAndroid Build Coastguard Worker hb_array_t<const int> coords = hb_array_t<const int> (), 315*2d1272b8SAndroid Build Coastguard Worker hb_map_t *current_glyphs = nullptr, 316*2d1272b8SAndroid Build Coastguard Worker unsigned int depth = 0, 317*2d1272b8SAndroid Build Coastguard Worker unsigned *edge_count = nullptr) const 318*2d1272b8SAndroid Build Coastguard Worker { 319*2d1272b8SAndroid Build Coastguard Worker if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false; 320*2d1272b8SAndroid Build Coastguard Worker unsigned stack_edge_count = 0; 321*2d1272b8SAndroid Build Coastguard Worker if (!edge_count) edge_count = &stack_edge_count; 322*2d1272b8SAndroid Build Coastguard Worker if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false; 323*2d1272b8SAndroid Build Coastguard Worker (*edge_count)++; 324*2d1272b8SAndroid Build Coastguard Worker 325*2d1272b8SAndroid Build Coastguard Worker hb_map_t current_glyphs_stack; 326*2d1272b8SAndroid Build Coastguard Worker if (current_glyphs == nullptr) 327*2d1272b8SAndroid Build Coastguard Worker current_glyphs = ¤t_glyphs_stack; 328*2d1272b8SAndroid Build Coastguard Worker 329*2d1272b8SAndroid Build Coastguard Worker if (head_maxp_info) 330*2d1272b8SAndroid Build Coastguard Worker { 331*2d1272b8SAndroid Build Coastguard Worker head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth); 332*2d1272b8SAndroid Build Coastguard Worker } 333*2d1272b8SAndroid Build Coastguard Worker 334*2d1272b8SAndroid Build Coastguard Worker if (!coords) 335*2d1272b8SAndroid Build Coastguard Worker coords = hb_array (font->coords, font->num_coords); 336*2d1272b8SAndroid Build Coastguard Worker 337*2d1272b8SAndroid Build Coastguard Worker contour_point_vector_t stack_points; 338*2d1272b8SAndroid Build Coastguard Worker contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points; 339*2d1272b8SAndroid Build Coastguard Worker unsigned old_length = points.length; 340*2d1272b8SAndroid Build Coastguard Worker 341*2d1272b8SAndroid Build Coastguard Worker switch (type) { 342*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: 343*2d1272b8SAndroid Build Coastguard Worker if (depth == 0 && head_maxp_info) 344*2d1272b8SAndroid Build Coastguard Worker head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours); 345*2d1272b8SAndroid Build Coastguard Worker if (depth > 0 && composite_contours) 346*2d1272b8SAndroid Build Coastguard Worker *composite_contours += (unsigned) header->numberOfContours; 347*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (all_points, phantom_only))) 348*2d1272b8SAndroid Build Coastguard Worker return false; 349*2d1272b8SAndroid Build Coastguard Worker break; 350*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: 351*2d1272b8SAndroid Build Coastguard Worker { 352*2d1272b8SAndroid Build Coastguard Worker for (auto &item : get_composite_iterator ()) 353*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!item.get_points (points))) return false; 354*2d1272b8SAndroid Build Coastguard Worker break; 355*2d1272b8SAndroid Build Coastguard Worker } 356*2d1272b8SAndroid Build Coastguard Worker case EMPTY: 357*2d1272b8SAndroid Build Coastguard Worker break; 358*2d1272b8SAndroid Build Coastguard Worker } 359*2d1272b8SAndroid Build Coastguard Worker 360*2d1272b8SAndroid Build Coastguard Worker /* Init phantom points */ 361*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false; 362*2d1272b8SAndroid Build Coastguard Worker hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); 363*2d1272b8SAndroid Build Coastguard Worker { 364*2d1272b8SAndroid Build Coastguard Worker int lsb = 0; 365*2d1272b8SAndroid Build Coastguard Worker int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ? 366*2d1272b8SAndroid Build Coastguard Worker (int) header->xMin - lsb : 0; 367*2d1272b8SAndroid Build Coastguard Worker HB_UNUSED int tsb = 0; 368*2d1272b8SAndroid Build Coastguard Worker int v_orig = (int) header->yMax + 369*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL 370*2d1272b8SAndroid Build Coastguard Worker ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb) 371*2d1272b8SAndroid Build Coastguard Worker #else 372*2d1272b8SAndroid Build Coastguard Worker 0 373*2d1272b8SAndroid Build Coastguard Worker #endif 374*2d1272b8SAndroid Build Coastguard Worker ; 375*2d1272b8SAndroid Build Coastguard Worker unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid); 376*2d1272b8SAndroid Build Coastguard Worker unsigned v_adv = 377*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL 378*2d1272b8SAndroid Build Coastguard Worker glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid) 379*2d1272b8SAndroid Build Coastguard Worker #else 380*2d1272b8SAndroid Build Coastguard Worker - font->face->get_upem () 381*2d1272b8SAndroid Build Coastguard Worker #endif 382*2d1272b8SAndroid Build Coastguard Worker ; 383*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_LEFT].x = h_delta; 384*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta; 385*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_TOP].y = v_orig; 386*2d1272b8SAndroid Build Coastguard Worker phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv; 387*2d1272b8SAndroid Build Coastguard Worker } 388*2d1272b8SAndroid Build Coastguard Worker 389*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR 390*2d1272b8SAndroid Build Coastguard Worker if (coords) 391*2d1272b8SAndroid Build Coastguard Worker glyf_accelerator.gvar->apply_deltas_to_points (gid, 392*2d1272b8SAndroid Build Coastguard Worker coords, 393*2d1272b8SAndroid Build Coastguard Worker points.as_array ().sub_array (old_length), 394*2d1272b8SAndroid Build Coastguard Worker phantom_only && type == SIMPLE); 395*2d1272b8SAndroid Build Coastguard Worker #endif 396*2d1272b8SAndroid Build Coastguard Worker 397*2d1272b8SAndroid Build Coastguard Worker // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it 398*2d1272b8SAndroid Build Coastguard Worker // with child glyphs' points 399*2d1272b8SAndroid Build Coastguard Worker if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE) 400*2d1272b8SAndroid Build Coastguard Worker { 401*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!points_with_deltas->resize (points.length))) return false; 402*2d1272b8SAndroid Build Coastguard Worker *points_with_deltas = points; 403*2d1272b8SAndroid Build Coastguard Worker } 404*2d1272b8SAndroid Build Coastguard Worker 405*2d1272b8SAndroid Build Coastguard Worker switch (type) { 406*2d1272b8SAndroid Build Coastguard Worker case SIMPLE: 407*2d1272b8SAndroid Build Coastguard Worker if (depth == 0 && head_maxp_info) 408*2d1272b8SAndroid Build Coastguard Worker head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4); 409*2d1272b8SAndroid Build Coastguard Worker break; 410*2d1272b8SAndroid Build Coastguard Worker case COMPOSITE: 411*2d1272b8SAndroid Build Coastguard Worker { 412*2d1272b8SAndroid Build Coastguard Worker unsigned int comp_index = 0; 413*2d1272b8SAndroid Build Coastguard Worker for (auto &item : get_composite_iterator ()) 414*2d1272b8SAndroid Build Coastguard Worker { 415*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t item_gid = item.get_gid (); 416*2d1272b8SAndroid Build Coastguard Worker 417*2d1272b8SAndroid Build Coastguard Worker if (unlikely (current_glyphs->has (item_gid))) 418*2d1272b8SAndroid Build Coastguard Worker continue; 419*2d1272b8SAndroid Build Coastguard Worker 420*2d1272b8SAndroid Build Coastguard Worker current_glyphs->add (item_gid); 421*2d1272b8SAndroid Build Coastguard Worker 422*2d1272b8SAndroid Build Coastguard Worker unsigned old_count = all_points.length; 423*2d1272b8SAndroid Build Coastguard Worker 424*2d1272b8SAndroid Build Coastguard Worker if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && 425*2d1272b8SAndroid Build Coastguard Worker !glyf_accelerator.glyph_for_gid (item_gid) 426*2d1272b8SAndroid Build Coastguard Worker .get_points (font, 427*2d1272b8SAndroid Build Coastguard Worker glyf_accelerator, 428*2d1272b8SAndroid Build Coastguard Worker all_points, 429*2d1272b8SAndroid Build Coastguard Worker points_with_deltas, 430*2d1272b8SAndroid Build Coastguard Worker head_maxp_info, 431*2d1272b8SAndroid Build Coastguard Worker composite_contours, 432*2d1272b8SAndroid Build Coastguard Worker shift_points_hori, 433*2d1272b8SAndroid Build Coastguard Worker use_my_metrics, 434*2d1272b8SAndroid Build Coastguard Worker phantom_only, 435*2d1272b8SAndroid Build Coastguard Worker coords, 436*2d1272b8SAndroid Build Coastguard Worker current_glyphs, 437*2d1272b8SAndroid Build Coastguard Worker depth + 1, 438*2d1272b8SAndroid Build Coastguard Worker edge_count))) 439*2d1272b8SAndroid Build Coastguard Worker { 440*2d1272b8SAndroid Build Coastguard Worker current_glyphs->del (item_gid); 441*2d1272b8SAndroid Build Coastguard Worker return false; 442*2d1272b8SAndroid Build Coastguard Worker } 443*2d1272b8SAndroid Build Coastguard Worker 444*2d1272b8SAndroid Build Coastguard Worker auto comp_points = all_points.as_array ().sub_array (old_count); 445*2d1272b8SAndroid Build Coastguard Worker 446*2d1272b8SAndroid Build Coastguard Worker /* Copy phantom points from component if USE_MY_METRICS flag set */ 447*2d1272b8SAndroid Build Coastguard Worker if (use_my_metrics && item.is_use_my_metrics ()) 448*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < PHANTOM_COUNT; i++) 449*2d1272b8SAndroid Build Coastguard Worker phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; 450*2d1272b8SAndroid Build Coastguard Worker 451*2d1272b8SAndroid Build Coastguard Worker if (comp_points) // Empty in case of phantom_only 452*2d1272b8SAndroid Build Coastguard Worker { 453*2d1272b8SAndroid Build Coastguard Worker float matrix[4]; 454*2d1272b8SAndroid Build Coastguard Worker contour_point_t default_trans; 455*2d1272b8SAndroid Build Coastguard Worker item.get_transformation (matrix, default_trans); 456*2d1272b8SAndroid Build Coastguard Worker 457*2d1272b8SAndroid Build Coastguard Worker /* Apply component transformation & translation (with deltas applied) */ 458*2d1272b8SAndroid Build Coastguard Worker item.transform_points (comp_points, matrix, points[comp_index]); 459*2d1272b8SAndroid Build Coastguard Worker } 460*2d1272b8SAndroid Build Coastguard Worker 461*2d1272b8SAndroid Build Coastguard Worker if (item.is_anchored () && !phantom_only) 462*2d1272b8SAndroid Build Coastguard Worker { 463*2d1272b8SAndroid Build Coastguard Worker unsigned int p1, p2; 464*2d1272b8SAndroid Build Coastguard Worker item.get_anchor_points (p1, p2); 465*2d1272b8SAndroid Build Coastguard Worker if (likely (p1 < all_points.length && p2 < comp_points.length)) 466*2d1272b8SAndroid Build Coastguard Worker { 467*2d1272b8SAndroid Build Coastguard Worker contour_point_t delta; 468*2d1272b8SAndroid Build Coastguard Worker delta.init (all_points[p1].x - comp_points[p2].x, 469*2d1272b8SAndroid Build Coastguard Worker all_points[p1].y - comp_points[p2].y); 470*2d1272b8SAndroid Build Coastguard Worker 471*2d1272b8SAndroid Build Coastguard Worker item.translate (delta, comp_points); 472*2d1272b8SAndroid Build Coastguard Worker } 473*2d1272b8SAndroid Build Coastguard Worker } 474*2d1272b8SAndroid Build Coastguard Worker 475*2d1272b8SAndroid Build Coastguard Worker all_points.resize (all_points.length - PHANTOM_COUNT); 476*2d1272b8SAndroid Build Coastguard Worker 477*2d1272b8SAndroid Build Coastguard Worker if (all_points.length > HB_GLYF_MAX_POINTS) 478*2d1272b8SAndroid Build Coastguard Worker { 479*2d1272b8SAndroid Build Coastguard Worker current_glyphs->del (item_gid); 480*2d1272b8SAndroid Build Coastguard Worker return false; 481*2d1272b8SAndroid Build Coastguard Worker } 482*2d1272b8SAndroid Build Coastguard Worker 483*2d1272b8SAndroid Build Coastguard Worker comp_index++; 484*2d1272b8SAndroid Build Coastguard Worker current_glyphs->del (item_gid); 485*2d1272b8SAndroid Build Coastguard Worker } 486*2d1272b8SAndroid Build Coastguard Worker 487*2d1272b8SAndroid Build Coastguard Worker if (head_maxp_info && depth == 0) 488*2d1272b8SAndroid Build Coastguard Worker { 489*2d1272b8SAndroid Build Coastguard Worker if (composite_contours) 490*2d1272b8SAndroid Build Coastguard Worker head_maxp_info->maxCompositeContours = hb_max (head_maxp_info->maxCompositeContours, *composite_contours); 491*2d1272b8SAndroid Build Coastguard Worker head_maxp_info->maxCompositePoints = hb_max (head_maxp_info->maxCompositePoints, all_points.length); 492*2d1272b8SAndroid Build Coastguard Worker head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index); 493*2d1272b8SAndroid Build Coastguard Worker } 494*2d1272b8SAndroid Build Coastguard Worker all_points.extend (phantoms); 495*2d1272b8SAndroid Build Coastguard Worker } break; 496*2d1272b8SAndroid Build Coastguard Worker case EMPTY: 497*2d1272b8SAndroid Build Coastguard Worker all_points.extend (phantoms); 498*2d1272b8SAndroid Build Coastguard Worker break; 499*2d1272b8SAndroid Build Coastguard Worker } 500*2d1272b8SAndroid Build Coastguard Worker 501*2d1272b8SAndroid Build Coastguard Worker if (depth == 0 && shift_points_hori) /* Apply at top level */ 502*2d1272b8SAndroid Build Coastguard Worker { 503*2d1272b8SAndroid Build Coastguard Worker /* Undocumented rasterizer behavior: 504*2d1272b8SAndroid Build Coastguard Worker * Shift points horizontally by the updated left side bearing 505*2d1272b8SAndroid Build Coastguard Worker */ 506*2d1272b8SAndroid Build Coastguard Worker float v = -phantoms[PHANTOM_LEFT].x; 507*2d1272b8SAndroid Build Coastguard Worker if (v) 508*2d1272b8SAndroid Build Coastguard Worker for (auto &point : all_points) 509*2d1272b8SAndroid Build Coastguard Worker point.x += v; 510*2d1272b8SAndroid Build Coastguard Worker } 511*2d1272b8SAndroid Build Coastguard Worker 512*2d1272b8SAndroid Build Coastguard Worker return !all_points.in_error (); 513*2d1272b8SAndroid Build Coastguard Worker } 514*2d1272b8SAndroid Build Coastguard Worker get_extents_without_var_scaledOT::glyf_impl::Glyph515*2d1272b8SAndroid Build Coastguard Worker bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator, 516*2d1272b8SAndroid Build Coastguard Worker hb_glyph_extents_t *extents) const 517*2d1272b8SAndroid Build Coastguard Worker { 518*2d1272b8SAndroid Build Coastguard Worker if (type == EMPTY) return true; /* Empty glyph; zero extents. */ 519*2d1272b8SAndroid Build Coastguard Worker return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents); 520*2d1272b8SAndroid Build Coastguard Worker } 521*2d1272b8SAndroid Build Coastguard Worker get_bytesOT::glyf_impl::Glyph522*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t get_bytes () const { return bytes; } get_typeOT::glyf_impl::Glyph523*2d1272b8SAndroid Build Coastguard Worker glyph_type_t get_type () const { return type; } get_headerOT::glyf_impl::Glyph524*2d1272b8SAndroid Build Coastguard Worker const GlyphHeader *get_header () const { return header; } 525*2d1272b8SAndroid Build Coastguard Worker GlyphOT::glyf_impl::Glyph526*2d1272b8SAndroid Build Coastguard Worker Glyph () : bytes (), 527*2d1272b8SAndroid Build Coastguard Worker header (bytes.as<GlyphHeader> ()), 528*2d1272b8SAndroid Build Coastguard Worker gid (-1), 529*2d1272b8SAndroid Build Coastguard Worker type(EMPTY) 530*2d1272b8SAndroid Build Coastguard Worker {} 531*2d1272b8SAndroid Build Coastguard Worker GlyphOT::glyf_impl::Glyph532*2d1272b8SAndroid Build Coastguard Worker Glyph (hb_bytes_t bytes_, 533*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_), 534*2d1272b8SAndroid Build Coastguard Worker header (bytes.as<GlyphHeader> ()), 535*2d1272b8SAndroid Build Coastguard Worker gid (gid_) 536*2d1272b8SAndroid Build Coastguard Worker { 537*2d1272b8SAndroid Build Coastguard Worker int num_contours = header->numberOfContours; 538*2d1272b8SAndroid Build Coastguard Worker if (unlikely (num_contours == 0)) type = EMPTY; 539*2d1272b8SAndroid Build Coastguard Worker else if (num_contours > 0) type = SIMPLE; 540*2d1272b8SAndroid Build Coastguard Worker else if (num_contours <= -1) type = COMPOSITE; 541*2d1272b8SAndroid Build Coastguard Worker else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild. 542*2d1272b8SAndroid Build Coastguard Worker } 543*2d1272b8SAndroid Build Coastguard Worker 544*2d1272b8SAndroid Build Coastguard Worker protected: 545*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t bytes; 546*2d1272b8SAndroid Build Coastguard Worker const GlyphHeader *header; 547*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid; 548*2d1272b8SAndroid Build Coastguard Worker glyph_type_t type; 549*2d1272b8SAndroid Build Coastguard Worker }; 550*2d1272b8SAndroid Build Coastguard Worker 551*2d1272b8SAndroid Build Coastguard Worker 552*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */ 553*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 554*2d1272b8SAndroid Build Coastguard Worker 555*2d1272b8SAndroid Build Coastguard Worker 556*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_GLYPH_HH */ 557