1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_COMPOSITEGLYPH_HH 2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_COMPOSITEGLYPH_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 #include "composite-iter.hh" 7*2d1272b8SAndroid Build Coastguard Worker 8*2d1272b8SAndroid Build Coastguard Worker 9*2d1272b8SAndroid Build Coastguard Worker namespace OT { 10*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl { 11*2d1272b8SAndroid Build Coastguard Worker 12*2d1272b8SAndroid Build Coastguard Worker 13*2d1272b8SAndroid Build Coastguard Worker struct CompositeGlyphRecord 14*2d1272b8SAndroid Build Coastguard Worker { 15*2d1272b8SAndroid Build Coastguard Worker protected: 16*2d1272b8SAndroid Build Coastguard Worker enum composite_glyph_flag_t 17*2d1272b8SAndroid Build Coastguard Worker { 18*2d1272b8SAndroid Build Coastguard Worker ARG_1_AND_2_ARE_WORDS = 0x0001, 19*2d1272b8SAndroid Build Coastguard Worker ARGS_ARE_XY_VALUES = 0x0002, 20*2d1272b8SAndroid Build Coastguard Worker ROUND_XY_TO_GRID = 0x0004, 21*2d1272b8SAndroid Build Coastguard Worker WE_HAVE_A_SCALE = 0x0008, 22*2d1272b8SAndroid Build Coastguard Worker MORE_COMPONENTS = 0x0020, 23*2d1272b8SAndroid Build Coastguard Worker WE_HAVE_AN_X_AND_Y_SCALE = 0x0040, 24*2d1272b8SAndroid Build Coastguard Worker WE_HAVE_A_TWO_BY_TWO = 0x0080, 25*2d1272b8SAndroid Build Coastguard Worker WE_HAVE_INSTRUCTIONS = 0x0100, 26*2d1272b8SAndroid Build Coastguard Worker USE_MY_METRICS = 0x0200, 27*2d1272b8SAndroid Build Coastguard Worker OVERLAP_COMPOUND = 0x0400, 28*2d1272b8SAndroid Build Coastguard Worker SCALED_COMPONENT_OFFSET = 0x0800, 29*2d1272b8SAndroid Build Coastguard Worker UNSCALED_COMPONENT_OFFSET = 0x1000, 30*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 31*2d1272b8SAndroid Build Coastguard Worker GID_IS_24BIT = 0x2000 32*2d1272b8SAndroid Build Coastguard Worker #endif 33*2d1272b8SAndroid Build Coastguard Worker }; 34*2d1272b8SAndroid Build Coastguard Worker 35*2d1272b8SAndroid Build Coastguard Worker public: get_sizeOT::glyf_impl::CompositeGlyphRecord36*2d1272b8SAndroid Build Coastguard Worker unsigned int get_size () const 37*2d1272b8SAndroid Build Coastguard Worker { 38*2d1272b8SAndroid Build Coastguard Worker unsigned int size = min_size; 39*2d1272b8SAndroid Build Coastguard Worker /* glyphIndex is 24bit instead of 16bit */ 40*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 41*2d1272b8SAndroid Build Coastguard Worker if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size; 42*2d1272b8SAndroid Build Coastguard Worker #endif 43*2d1272b8SAndroid Build Coastguard Worker /* arg1 and 2 are int16 */ 44*2d1272b8SAndroid Build Coastguard Worker if (flags & ARG_1_AND_2_ARE_WORDS) size += 4; 45*2d1272b8SAndroid Build Coastguard Worker /* arg1 and 2 are int8 */ 46*2d1272b8SAndroid Build Coastguard Worker else size += 2; 47*2d1272b8SAndroid Build Coastguard Worker 48*2d1272b8SAndroid Build Coastguard Worker /* One x 16 bit (scale) */ 49*2d1272b8SAndroid Build Coastguard Worker if (flags & WE_HAVE_A_SCALE) size += 2; 50*2d1272b8SAndroid Build Coastguard Worker /* Two x 16 bit (xscale, yscale) */ 51*2d1272b8SAndroid Build Coastguard Worker else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4; 52*2d1272b8SAndroid Build Coastguard Worker /* Four x 16 bit (xscale, scale01, scale10, yscale) */ 53*2d1272b8SAndroid Build Coastguard Worker else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8; 54*2d1272b8SAndroid Build Coastguard Worker 55*2d1272b8SAndroid Build Coastguard Worker return size; 56*2d1272b8SAndroid Build Coastguard Worker } 57*2d1272b8SAndroid Build Coastguard Worker drop_instructions_flagOT::glyf_impl::CompositeGlyphRecord58*2d1272b8SAndroid Build Coastguard Worker void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; } set_overlaps_flagOT::glyf_impl::CompositeGlyphRecord59*2d1272b8SAndroid Build Coastguard Worker void set_overlaps_flag () 60*2d1272b8SAndroid Build Coastguard Worker { 61*2d1272b8SAndroid Build Coastguard Worker flags = (uint16_t) flags | OVERLAP_COMPOUND; 62*2d1272b8SAndroid Build Coastguard Worker } 63*2d1272b8SAndroid Build Coastguard Worker has_instructionsOT::glyf_impl::CompositeGlyphRecord64*2d1272b8SAndroid Build Coastguard Worker bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; } 65*2d1272b8SAndroid Build Coastguard Worker has_moreOT::glyf_impl::CompositeGlyphRecord66*2d1272b8SAndroid Build Coastguard Worker bool has_more () const { return flags & MORE_COMPONENTS; } is_use_my_metricsOT::glyf_impl::CompositeGlyphRecord67*2d1272b8SAndroid Build Coastguard Worker bool is_use_my_metrics () const { return flags & USE_MY_METRICS; } is_anchoredOT::glyf_impl::CompositeGlyphRecord68*2d1272b8SAndroid Build Coastguard Worker bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); } get_anchor_pointsOT::glyf_impl::CompositeGlyphRecord69*2d1272b8SAndroid Build Coastguard Worker void get_anchor_points (unsigned int &point1, unsigned int &point2) const 70*2d1272b8SAndroid Build Coastguard Worker { 71*2d1272b8SAndroid Build Coastguard Worker const auto *p = &StructAfter<const HBUINT8> (flags); 72*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 73*2d1272b8SAndroid Build Coastguard Worker if (flags & GID_IS_24BIT) 74*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID24::static_size; 75*2d1272b8SAndroid Build Coastguard Worker else 76*2d1272b8SAndroid Build Coastguard Worker #endif 77*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID16::static_size; 78*2d1272b8SAndroid Build Coastguard Worker if (flags & ARG_1_AND_2_ARE_WORDS) 79*2d1272b8SAndroid Build Coastguard Worker { 80*2d1272b8SAndroid Build Coastguard Worker point1 = ((const HBUINT16 *) p)[0]; 81*2d1272b8SAndroid Build Coastguard Worker point2 = ((const HBUINT16 *) p)[1]; 82*2d1272b8SAndroid Build Coastguard Worker } 83*2d1272b8SAndroid Build Coastguard Worker else 84*2d1272b8SAndroid Build Coastguard Worker { 85*2d1272b8SAndroid Build Coastguard Worker point1 = p[0]; 86*2d1272b8SAndroid Build Coastguard Worker point2 = p[1]; 87*2d1272b8SAndroid Build Coastguard Worker } 88*2d1272b8SAndroid Build Coastguard Worker } 89*2d1272b8SAndroid Build Coastguard Worker transformOT::glyf_impl::CompositeGlyphRecord90*2d1272b8SAndroid Build Coastguard Worker static void transform (const float (&matrix)[4], 91*2d1272b8SAndroid Build Coastguard Worker hb_array_t<contour_point_t> points) 92*2d1272b8SAndroid Build Coastguard Worker { 93*2d1272b8SAndroid Build Coastguard Worker if (matrix[0] != 1.f || matrix[1] != 0.f || 94*2d1272b8SAndroid Build Coastguard Worker matrix[2] != 0.f || matrix[3] != 1.f) 95*2d1272b8SAndroid Build Coastguard Worker for (auto &point : points) 96*2d1272b8SAndroid Build Coastguard Worker point.transform (matrix); 97*2d1272b8SAndroid Build Coastguard Worker } 98*2d1272b8SAndroid Build Coastguard Worker translateOT::glyf_impl::CompositeGlyphRecord99*2d1272b8SAndroid Build Coastguard Worker static void translate (const contour_point_t &trans, 100*2d1272b8SAndroid Build Coastguard Worker hb_array_t<contour_point_t> points) 101*2d1272b8SAndroid Build Coastguard Worker { 102*2d1272b8SAndroid Build Coastguard Worker if (HB_OPTIMIZE_SIZE_VAL) 103*2d1272b8SAndroid Build Coastguard Worker { 104*2d1272b8SAndroid Build Coastguard Worker if (trans.x != 0.f || trans.y != 0.f) 105*2d1272b8SAndroid Build Coastguard Worker for (auto &point : points) 106*2d1272b8SAndroid Build Coastguard Worker point.translate (trans); 107*2d1272b8SAndroid Build Coastguard Worker } 108*2d1272b8SAndroid Build Coastguard Worker else 109*2d1272b8SAndroid Build Coastguard Worker { 110*2d1272b8SAndroid Build Coastguard Worker if (trans.x != 0.f && trans.y != 0.f) 111*2d1272b8SAndroid Build Coastguard Worker for (auto &point : points) 112*2d1272b8SAndroid Build Coastguard Worker point.translate (trans); 113*2d1272b8SAndroid Build Coastguard Worker else 114*2d1272b8SAndroid Build Coastguard Worker { 115*2d1272b8SAndroid Build Coastguard Worker if (trans.x != 0.f) 116*2d1272b8SAndroid Build Coastguard Worker for (auto &point : points) 117*2d1272b8SAndroid Build Coastguard Worker point.x += trans.x; 118*2d1272b8SAndroid Build Coastguard Worker else if (trans.y != 0.f) 119*2d1272b8SAndroid Build Coastguard Worker for (auto &point : points) 120*2d1272b8SAndroid Build Coastguard Worker point.y += trans.y; 121*2d1272b8SAndroid Build Coastguard Worker } 122*2d1272b8SAndroid Build Coastguard Worker } 123*2d1272b8SAndroid Build Coastguard Worker } 124*2d1272b8SAndroid Build Coastguard Worker transform_pointsOT::glyf_impl::CompositeGlyphRecord125*2d1272b8SAndroid Build Coastguard Worker void transform_points (hb_array_t<contour_point_t> points, 126*2d1272b8SAndroid Build Coastguard Worker const float (&matrix)[4], 127*2d1272b8SAndroid Build Coastguard Worker const contour_point_t &trans) const 128*2d1272b8SAndroid Build Coastguard Worker { 129*2d1272b8SAndroid Build Coastguard Worker if (scaled_offsets ()) 130*2d1272b8SAndroid Build Coastguard Worker { 131*2d1272b8SAndroid Build Coastguard Worker translate (trans, points); 132*2d1272b8SAndroid Build Coastguard Worker transform (matrix, points); 133*2d1272b8SAndroid Build Coastguard Worker } 134*2d1272b8SAndroid Build Coastguard Worker else 135*2d1272b8SAndroid Build Coastguard Worker { 136*2d1272b8SAndroid Build Coastguard Worker transform (matrix, points); 137*2d1272b8SAndroid Build Coastguard Worker translate (trans, points); 138*2d1272b8SAndroid Build Coastguard Worker } 139*2d1272b8SAndroid Build Coastguard Worker } 140*2d1272b8SAndroid Build Coastguard Worker get_pointsOT::glyf_impl::CompositeGlyphRecord141*2d1272b8SAndroid Build Coastguard Worker bool get_points (contour_point_vector_t &points) const 142*2d1272b8SAndroid Build Coastguard Worker { 143*2d1272b8SAndroid Build Coastguard Worker float matrix[4]; 144*2d1272b8SAndroid Build Coastguard Worker contour_point_t trans; 145*2d1272b8SAndroid Build Coastguard Worker get_transformation (matrix, trans); 146*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points 147*2d1272b8SAndroid Build Coastguard Worker points.push (trans); 148*2d1272b8SAndroid Build Coastguard Worker return true; 149*2d1272b8SAndroid Build Coastguard Worker } 150*2d1272b8SAndroid Build Coastguard Worker compile_with_pointOT::glyf_impl::CompositeGlyphRecord151*2d1272b8SAndroid Build Coastguard Worker unsigned compile_with_point (const contour_point_t &point, 152*2d1272b8SAndroid Build Coastguard Worker char *out) const 153*2d1272b8SAndroid Build Coastguard Worker { 154*2d1272b8SAndroid Build Coastguard Worker const HBINT8 *p = &StructAfter<const HBINT8> (flags); 155*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 156*2d1272b8SAndroid Build Coastguard Worker if (flags & GID_IS_24BIT) 157*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID24::static_size; 158*2d1272b8SAndroid Build Coastguard Worker else 159*2d1272b8SAndroid Build Coastguard Worker #endif 160*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID16::static_size; 161*2d1272b8SAndroid Build Coastguard Worker 162*2d1272b8SAndroid Build Coastguard Worker unsigned len = get_size (); 163*2d1272b8SAndroid Build Coastguard Worker unsigned len_before_val = (const char *)p - (const char *)this; 164*2d1272b8SAndroid Build Coastguard Worker if (flags & ARG_1_AND_2_ARE_WORDS) 165*2d1272b8SAndroid Build Coastguard Worker { 166*2d1272b8SAndroid Build Coastguard Worker // no overflow, copy value 167*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, this, len); 168*2d1272b8SAndroid Build Coastguard Worker 169*2d1272b8SAndroid Build Coastguard Worker HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val); 170*2d1272b8SAndroid Build Coastguard Worker o[0] = roundf (point.x); 171*2d1272b8SAndroid Build Coastguard Worker o[1] = roundf (point.y); 172*2d1272b8SAndroid Build Coastguard Worker } 173*2d1272b8SAndroid Build Coastguard Worker else 174*2d1272b8SAndroid Build Coastguard Worker { 175*2d1272b8SAndroid Build Coastguard Worker int new_x = roundf (point.x); 176*2d1272b8SAndroid Build Coastguard Worker int new_y = roundf (point.y); 177*2d1272b8SAndroid Build Coastguard Worker if (new_x <= 127 && new_x >= -128 && 178*2d1272b8SAndroid Build Coastguard Worker new_y <= 127 && new_y >= -128) 179*2d1272b8SAndroid Build Coastguard Worker { 180*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, this, len); 181*2d1272b8SAndroid Build Coastguard Worker HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val); 182*2d1272b8SAndroid Build Coastguard Worker o[0] = new_x; 183*2d1272b8SAndroid Build Coastguard Worker o[1] = new_y; 184*2d1272b8SAndroid Build Coastguard Worker } 185*2d1272b8SAndroid Build Coastguard Worker else 186*2d1272b8SAndroid Build Coastguard Worker { 187*2d1272b8SAndroid Build Coastguard Worker // new point value has an int8 overflow 188*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, this, len_before_val); 189*2d1272b8SAndroid Build Coastguard Worker 190*2d1272b8SAndroid Build Coastguard Worker //update flags 191*2d1272b8SAndroid Build Coastguard Worker CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out); 192*2d1272b8SAndroid Build Coastguard Worker o->flags = flags | ARG_1_AND_2_ARE_WORDS; 193*2d1272b8SAndroid Build Coastguard Worker out += len_before_val; 194*2d1272b8SAndroid Build Coastguard Worker 195*2d1272b8SAndroid Build Coastguard Worker HBINT16 new_value; 196*2d1272b8SAndroid Build Coastguard Worker new_value = new_x; 197*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, &new_value, HBINT16::static_size); 198*2d1272b8SAndroid Build Coastguard Worker out += HBINT16::static_size; 199*2d1272b8SAndroid Build Coastguard Worker 200*2d1272b8SAndroid Build Coastguard Worker new_value = new_y; 201*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, &new_value, HBINT16::static_size); 202*2d1272b8SAndroid Build Coastguard Worker out += HBINT16::static_size; 203*2d1272b8SAndroid Build Coastguard Worker 204*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, p+2, len - len_before_val - 2); 205*2d1272b8SAndroid Build Coastguard Worker len += 2; 206*2d1272b8SAndroid Build Coastguard Worker } 207*2d1272b8SAndroid Build Coastguard Worker } 208*2d1272b8SAndroid Build Coastguard Worker return len; 209*2d1272b8SAndroid Build Coastguard Worker } 210*2d1272b8SAndroid Build Coastguard Worker 211*2d1272b8SAndroid Build Coastguard Worker protected: scaled_offsetsOT::glyf_impl::CompositeGlyphRecord212*2d1272b8SAndroid Build Coastguard Worker bool scaled_offsets () const 213*2d1272b8SAndroid Build Coastguard Worker { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; } 214*2d1272b8SAndroid Build Coastguard Worker 215*2d1272b8SAndroid Build Coastguard Worker public: get_transformationOT::glyf_impl::CompositeGlyphRecord216*2d1272b8SAndroid Build Coastguard Worker bool get_transformation (float (&matrix)[4], contour_point_t &trans) const 217*2d1272b8SAndroid Build Coastguard Worker { 218*2d1272b8SAndroid Build Coastguard Worker matrix[0] = matrix[3] = 1.f; 219*2d1272b8SAndroid Build Coastguard Worker matrix[1] = matrix[2] = 0.f; 220*2d1272b8SAndroid Build Coastguard Worker 221*2d1272b8SAndroid Build Coastguard Worker const auto *p = &StructAfter<const HBINT8> (flags); 222*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 223*2d1272b8SAndroid Build Coastguard Worker if (flags & GID_IS_24BIT) 224*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID24::static_size; 225*2d1272b8SAndroid Build Coastguard Worker else 226*2d1272b8SAndroid Build Coastguard Worker #endif 227*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID16::static_size; 228*2d1272b8SAndroid Build Coastguard Worker int tx, ty; 229*2d1272b8SAndroid Build Coastguard Worker if (flags & ARG_1_AND_2_ARE_WORDS) 230*2d1272b8SAndroid Build Coastguard Worker { 231*2d1272b8SAndroid Build Coastguard Worker tx = *(const HBINT16 *) p; 232*2d1272b8SAndroid Build Coastguard Worker p += HBINT16::static_size; 233*2d1272b8SAndroid Build Coastguard Worker ty = *(const HBINT16 *) p; 234*2d1272b8SAndroid Build Coastguard Worker p += HBINT16::static_size; 235*2d1272b8SAndroid Build Coastguard Worker } 236*2d1272b8SAndroid Build Coastguard Worker else 237*2d1272b8SAndroid Build Coastguard Worker { 238*2d1272b8SAndroid Build Coastguard Worker tx = *p++; 239*2d1272b8SAndroid Build Coastguard Worker ty = *p++; 240*2d1272b8SAndroid Build Coastguard Worker } 241*2d1272b8SAndroid Build Coastguard Worker if (is_anchored ()) tx = ty = 0; 242*2d1272b8SAndroid Build Coastguard Worker 243*2d1272b8SAndroid Build Coastguard Worker /* set is_end_point flag to true, used by IUP delta optimization */ 244*2d1272b8SAndroid Build Coastguard Worker trans.init ((float) tx, (float) ty, true); 245*2d1272b8SAndroid Build Coastguard Worker 246*2d1272b8SAndroid Build Coastguard Worker { 247*2d1272b8SAndroid Build Coastguard Worker const F2DOT14 *points = (const F2DOT14 *) p; 248*2d1272b8SAndroid Build Coastguard Worker if (flags & WE_HAVE_A_SCALE) 249*2d1272b8SAndroid Build Coastguard Worker { 250*2d1272b8SAndroid Build Coastguard Worker matrix[0] = matrix[3] = points[0].to_float (); 251*2d1272b8SAndroid Build Coastguard Worker return true; 252*2d1272b8SAndroid Build Coastguard Worker } 253*2d1272b8SAndroid Build Coastguard Worker else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) 254*2d1272b8SAndroid Build Coastguard Worker { 255*2d1272b8SAndroid Build Coastguard Worker matrix[0] = points[0].to_float (); 256*2d1272b8SAndroid Build Coastguard Worker matrix[3] = points[1].to_float (); 257*2d1272b8SAndroid Build Coastguard Worker return true; 258*2d1272b8SAndroid Build Coastguard Worker } 259*2d1272b8SAndroid Build Coastguard Worker else if (flags & WE_HAVE_A_TWO_BY_TWO) 260*2d1272b8SAndroid Build Coastguard Worker { 261*2d1272b8SAndroid Build Coastguard Worker matrix[0] = points[0].to_float (); 262*2d1272b8SAndroid Build Coastguard Worker matrix[1] = points[1].to_float (); 263*2d1272b8SAndroid Build Coastguard Worker matrix[2] = points[2].to_float (); 264*2d1272b8SAndroid Build Coastguard Worker matrix[3] = points[3].to_float (); 265*2d1272b8SAndroid Build Coastguard Worker return true; 266*2d1272b8SAndroid Build Coastguard Worker } 267*2d1272b8SAndroid Build Coastguard Worker } 268*2d1272b8SAndroid Build Coastguard Worker return tx || ty; 269*2d1272b8SAndroid Build Coastguard Worker } 270*2d1272b8SAndroid Build Coastguard Worker get_gidOT::glyf_impl::CompositeGlyphRecord271*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_gid () const 272*2d1272b8SAndroid Build Coastguard Worker { 273*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 274*2d1272b8SAndroid Build Coastguard Worker if (flags & GID_IS_24BIT) 275*2d1272b8SAndroid Build Coastguard Worker return StructAfter<const HBGlyphID24> (flags); 276*2d1272b8SAndroid Build Coastguard Worker else 277*2d1272b8SAndroid Build Coastguard Worker #endif 278*2d1272b8SAndroid Build Coastguard Worker return StructAfter<const HBGlyphID16> (flags); 279*2d1272b8SAndroid Build Coastguard Worker } set_gidOT::glyf_impl::CompositeGlyphRecord280*2d1272b8SAndroid Build Coastguard Worker void set_gid (hb_codepoint_t gid) 281*2d1272b8SAndroid Build Coastguard Worker { 282*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 283*2d1272b8SAndroid Build Coastguard Worker if (flags & GID_IS_24BIT) 284*2d1272b8SAndroid Build Coastguard Worker StructAfter<HBGlyphID24> (flags) = gid; 285*2d1272b8SAndroid Build Coastguard Worker else 286*2d1272b8SAndroid Build Coastguard Worker #endif 287*2d1272b8SAndroid Build Coastguard Worker /* TODO assert? */ 288*2d1272b8SAndroid Build Coastguard Worker StructAfter<HBGlyphID16> (flags) = gid; 289*2d1272b8SAndroid Build Coastguard Worker } 290*2d1272b8SAndroid Build Coastguard Worker 291*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K lower_gid_24_to_16OT::glyf_impl::CompositeGlyphRecord292*2d1272b8SAndroid Build Coastguard Worker void lower_gid_24_to_16 () 293*2d1272b8SAndroid Build Coastguard Worker { 294*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = get_gid (); 295*2d1272b8SAndroid Build Coastguard Worker if (!(flags & GID_IS_24BIT) || gid > 0xFFFFu) 296*2d1272b8SAndroid Build Coastguard Worker return; 297*2d1272b8SAndroid Build Coastguard Worker 298*2d1272b8SAndroid Build Coastguard Worker /* Lower the flag and move the rest of the struct down. */ 299*2d1272b8SAndroid Build Coastguard Worker 300*2d1272b8SAndroid Build Coastguard Worker unsigned size = get_size (); 301*2d1272b8SAndroid Build Coastguard Worker char *end = (char *) this + size; 302*2d1272b8SAndroid Build Coastguard Worker char *p = &StructAfter<char> (flags); 303*2d1272b8SAndroid Build Coastguard Worker p += HBGlyphID24::static_size; 304*2d1272b8SAndroid Build Coastguard Worker 305*2d1272b8SAndroid Build Coastguard Worker flags = flags & ~GID_IS_24BIT; 306*2d1272b8SAndroid Build Coastguard Worker set_gid (gid); 307*2d1272b8SAndroid Build Coastguard Worker 308*2d1272b8SAndroid Build Coastguard Worker memmove (p - HBGlyphID24::static_size + HBGlyphID16::static_size, p, end - p); 309*2d1272b8SAndroid Build Coastguard Worker } 310*2d1272b8SAndroid Build Coastguard Worker #endif 311*2d1272b8SAndroid Build Coastguard Worker 312*2d1272b8SAndroid Build Coastguard Worker protected: 313*2d1272b8SAndroid Build Coastguard Worker HBUINT16 flags; 314*2d1272b8SAndroid Build Coastguard Worker HBUINT24 pad; 315*2d1272b8SAndroid Build Coastguard Worker public: 316*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_MIN (4); 317*2d1272b8SAndroid Build Coastguard Worker }; 318*2d1272b8SAndroid Build Coastguard Worker 319*2d1272b8SAndroid Build Coastguard Worker using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>; 320*2d1272b8SAndroid Build Coastguard Worker 321*2d1272b8SAndroid Build Coastguard Worker struct CompositeGlyph 322*2d1272b8SAndroid Build Coastguard Worker { 323*2d1272b8SAndroid Build Coastguard Worker const GlyphHeader &header; 324*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t bytes; CompositeGlyphOT::glyf_impl::CompositeGlyph325*2d1272b8SAndroid Build Coastguard Worker CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) : 326*2d1272b8SAndroid Build Coastguard Worker header (header_), bytes (bytes_) {} 327*2d1272b8SAndroid Build Coastguard Worker iterOT::glyf_impl::CompositeGlyph328*2d1272b8SAndroid Build Coastguard Worker composite_iter_t iter () const 329*2d1272b8SAndroid Build Coastguard Worker { return composite_iter_t (bytes, &StructAfter<CompositeGlyphRecord, GlyphHeader> (header)); } 330*2d1272b8SAndroid Build Coastguard Worker instructions_lengthOT::glyf_impl::CompositeGlyph331*2d1272b8SAndroid Build Coastguard Worker unsigned int instructions_length (hb_bytes_t bytes) const 332*2d1272b8SAndroid Build Coastguard Worker { 333*2d1272b8SAndroid Build Coastguard Worker unsigned int start = bytes.length; 334*2d1272b8SAndroid Build Coastguard Worker unsigned int end = bytes.length; 335*2d1272b8SAndroid Build Coastguard Worker const CompositeGlyphRecord *last = nullptr; 336*2d1272b8SAndroid Build Coastguard Worker for (auto &item : iter ()) 337*2d1272b8SAndroid Build Coastguard Worker last = &item; 338*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!last)) return 0; 339*2d1272b8SAndroid Build Coastguard Worker 340*2d1272b8SAndroid Build Coastguard Worker if (last->has_instructions ()) 341*2d1272b8SAndroid Build Coastguard Worker start = (char *) last - &bytes + last->get_size (); 342*2d1272b8SAndroid Build Coastguard Worker if (unlikely (start > end)) return 0; 343*2d1272b8SAndroid Build Coastguard Worker return end - start; 344*2d1272b8SAndroid Build Coastguard Worker } 345*2d1272b8SAndroid Build Coastguard Worker 346*2d1272b8SAndroid Build Coastguard Worker /* Trimming for composites not implemented. 347*2d1272b8SAndroid Build Coastguard Worker * If removing hints it falls out of that. */ trim_paddingOT::glyf_impl::CompositeGlyph348*2d1272b8SAndroid Build Coastguard Worker const hb_bytes_t trim_padding () const { return bytes; } 349*2d1272b8SAndroid Build Coastguard Worker drop_hintsOT::glyf_impl::CompositeGlyph350*2d1272b8SAndroid Build Coastguard Worker void drop_hints () 351*2d1272b8SAndroid Build Coastguard Worker { 352*2d1272b8SAndroid Build Coastguard Worker for (const auto &_ : iter ()) 353*2d1272b8SAndroid Build Coastguard Worker const_cast<CompositeGlyphRecord &> (_).drop_instructions_flag (); 354*2d1272b8SAndroid Build Coastguard Worker } 355*2d1272b8SAndroid Build Coastguard Worker 356*2d1272b8SAndroid Build Coastguard Worker /* Chop instructions off the end */ drop_hints_bytesOT::glyf_impl::CompositeGlyph357*2d1272b8SAndroid Build Coastguard Worker void drop_hints_bytes (hb_bytes_t &dest_start) const 358*2d1272b8SAndroid Build Coastguard Worker { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); } 359*2d1272b8SAndroid Build Coastguard Worker set_overlaps_flagOT::glyf_impl::CompositeGlyph360*2d1272b8SAndroid Build Coastguard Worker void set_overlaps_flag () 361*2d1272b8SAndroid Build Coastguard Worker { 362*2d1272b8SAndroid Build Coastguard Worker CompositeGlyphRecord& glyph_chain = const_cast<CompositeGlyphRecord &> ( 363*2d1272b8SAndroid Build Coastguard Worker StructAfter<CompositeGlyphRecord, GlyphHeader> (header)); 364*2d1272b8SAndroid Build Coastguard Worker if (!bytes.check_range(&glyph_chain, CompositeGlyphRecord::min_size)) 365*2d1272b8SAndroid Build Coastguard Worker return; 366*2d1272b8SAndroid Build Coastguard Worker glyph_chain.set_overlaps_flag (); 367*2d1272b8SAndroid Build Coastguard Worker } 368*2d1272b8SAndroid Build Coastguard Worker compile_bytes_with_deltasOT::glyf_impl::CompositeGlyph369*2d1272b8SAndroid Build Coastguard Worker bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes, 370*2d1272b8SAndroid Build Coastguard Worker const contour_point_vector_t &points_with_deltas, 371*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t &dest_bytes /* OUT */) 372*2d1272b8SAndroid Build Coastguard Worker { 373*2d1272b8SAndroid Build Coastguard Worker if (source_bytes.length <= GlyphHeader::static_size || 374*2d1272b8SAndroid Build Coastguard Worker header.numberOfContours != -1) 375*2d1272b8SAndroid Build Coastguard Worker { 376*2d1272b8SAndroid Build Coastguard Worker dest_bytes = hb_bytes_t (); 377*2d1272b8SAndroid Build Coastguard Worker return true; 378*2d1272b8SAndroid Build Coastguard Worker } 379*2d1272b8SAndroid Build Coastguard Worker 380*2d1272b8SAndroid Build Coastguard Worker unsigned source_len = source_bytes.length - GlyphHeader::static_size; 381*2d1272b8SAndroid Build Coastguard Worker 382*2d1272b8SAndroid Build Coastguard Worker /* try to allocate more memories than source glyph bytes 383*2d1272b8SAndroid Build Coastguard Worker * in case that there might be an overflow for int8 value 384*2d1272b8SAndroid Build Coastguard Worker * and we would need to use int16 instead */ 385*2d1272b8SAndroid Build Coastguard Worker char *o = (char *) hb_calloc (source_len * 2, sizeof (char)); 386*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!o)) return false; 387*2d1272b8SAndroid Build Coastguard Worker 388*2d1272b8SAndroid Build Coastguard Worker const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size); 389*2d1272b8SAndroid Build Coastguard Worker auto it = composite_iter_t (hb_bytes_t ((const char *)c, source_len), c); 390*2d1272b8SAndroid Build Coastguard Worker 391*2d1272b8SAndroid Build Coastguard Worker char *p = o; 392*2d1272b8SAndroid Build Coastguard Worker unsigned i = 0, source_comp_len = 0; 393*2d1272b8SAndroid Build Coastguard Worker for (const auto &component : it) 394*2d1272b8SAndroid Build Coastguard Worker { 395*2d1272b8SAndroid Build Coastguard Worker /* last 4 points in points_with_deltas are phantom points and should not be included */ 396*2d1272b8SAndroid Build Coastguard Worker if (i >= points_with_deltas.length - 4) { 397*2d1272b8SAndroid Build Coastguard Worker hb_free (o); 398*2d1272b8SAndroid Build Coastguard Worker return false; 399*2d1272b8SAndroid Build Coastguard Worker } 400*2d1272b8SAndroid Build Coastguard Worker 401*2d1272b8SAndroid Build Coastguard Worker unsigned comp_len = component.get_size (); 402*2d1272b8SAndroid Build Coastguard Worker if (component.is_anchored ()) 403*2d1272b8SAndroid Build Coastguard Worker { 404*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (p, &component, comp_len); 405*2d1272b8SAndroid Build Coastguard Worker p += comp_len; 406*2d1272b8SAndroid Build Coastguard Worker } 407*2d1272b8SAndroid Build Coastguard Worker else 408*2d1272b8SAndroid Build Coastguard Worker { 409*2d1272b8SAndroid Build Coastguard Worker unsigned new_len = component.compile_with_point (points_with_deltas[i], p); 410*2d1272b8SAndroid Build Coastguard Worker p += new_len; 411*2d1272b8SAndroid Build Coastguard Worker } 412*2d1272b8SAndroid Build Coastguard Worker i++; 413*2d1272b8SAndroid Build Coastguard Worker source_comp_len += comp_len; 414*2d1272b8SAndroid Build Coastguard Worker } 415*2d1272b8SAndroid Build Coastguard Worker 416*2d1272b8SAndroid Build Coastguard Worker //copy instructions if any 417*2d1272b8SAndroid Build Coastguard Worker if (source_len > source_comp_len) 418*2d1272b8SAndroid Build Coastguard Worker { 419*2d1272b8SAndroid Build Coastguard Worker unsigned instr_len = source_len - source_comp_len; 420*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (p, (const char *)c + source_comp_len, instr_len); 421*2d1272b8SAndroid Build Coastguard Worker p += instr_len; 422*2d1272b8SAndroid Build Coastguard Worker } 423*2d1272b8SAndroid Build Coastguard Worker 424*2d1272b8SAndroid Build Coastguard Worker unsigned len = p - o; 425*2d1272b8SAndroid Build Coastguard Worker dest_bytes = hb_bytes_t (o, len); 426*2d1272b8SAndroid Build Coastguard Worker return true; 427*2d1272b8SAndroid Build Coastguard Worker } 428*2d1272b8SAndroid Build Coastguard Worker }; 429*2d1272b8SAndroid Build Coastguard Worker 430*2d1272b8SAndroid Build Coastguard Worker 431*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */ 432*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 433*2d1272b8SAndroid Build Coastguard Worker 434*2d1272b8SAndroid Build Coastguard Worker 435*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_COMPOSITEGLYPH_HH */ 436