1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_SUBSETGLYPH_HH 2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_SUBSETGLYPH_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 8*2d1272b8SAndroid Build Coastguard Worker namespace OT { 9*2d1272b8SAndroid Build Coastguard Worker 10*2d1272b8SAndroid Build Coastguard Worker struct glyf_accelerator_t; 11*2d1272b8SAndroid Build Coastguard Worker 12*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl { 13*2d1272b8SAndroid Build Coastguard Worker 14*2d1272b8SAndroid Build Coastguard Worker 15*2d1272b8SAndroid Build Coastguard Worker struct SubsetGlyph 16*2d1272b8SAndroid Build Coastguard Worker { 17*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid; 18*2d1272b8SAndroid Build Coastguard Worker Glyph source_glyph; 19*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t dest_start; /* region of source_glyph to copy first */ 20*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t dest_end; /* region of source_glyph to copy second */ 21*2d1272b8SAndroid Build Coastguard Worker bool allocated; 22*2d1272b8SAndroid Build Coastguard Worker serializeOT::glyf_impl::SubsetGlyph23*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, 24*2d1272b8SAndroid Build Coastguard Worker bool use_short_loca, 25*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan) const 26*2d1272b8SAndroid Build Coastguard Worker { 27*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 28*2d1272b8SAndroid Build Coastguard Worker 29*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t dest_glyph = dest_start.copy (c); 30*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t end_copy = dest_end.copy (c); 31*2d1272b8SAndroid Build Coastguard Worker if (!end_copy.arrayZ || !dest_glyph.arrayZ) { 32*2d1272b8SAndroid Build Coastguard Worker return false; 33*2d1272b8SAndroid Build Coastguard Worker } 34*2d1272b8SAndroid Build Coastguard Worker 35*2d1272b8SAndroid Build Coastguard Worker dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length); 36*2d1272b8SAndroid Build Coastguard Worker unsigned int pad_length = use_short_loca ? padding () : 0; 37*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length); 38*2d1272b8SAndroid Build Coastguard Worker 39*2d1272b8SAndroid Build Coastguard Worker HBUINT8 pad; 40*2d1272b8SAndroid Build Coastguard Worker pad = 0; 41*2d1272b8SAndroid Build Coastguard Worker while (pad_length > 0) 42*2d1272b8SAndroid Build Coastguard Worker { 43*2d1272b8SAndroid Build Coastguard Worker (void) c->embed (pad); 44*2d1272b8SAndroid Build Coastguard Worker pad_length--; 45*2d1272b8SAndroid Build Coastguard Worker } 46*2d1272b8SAndroid Build Coastguard Worker 47*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!dest_glyph.length)) return_trace (true); 48*2d1272b8SAndroid Build Coastguard Worker 49*2d1272b8SAndroid Build Coastguard Worker /* update components gids. */ 50*2d1272b8SAndroid Build Coastguard Worker for (auto &_ : Glyph (dest_glyph).get_composite_iterator ()) 51*2d1272b8SAndroid Build Coastguard Worker { 52*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_gid; 53*2d1272b8SAndroid Build Coastguard Worker if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid)) 54*2d1272b8SAndroid Build Coastguard Worker const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid); 55*2d1272b8SAndroid Build Coastguard Worker } 56*2d1272b8SAndroid Build Coastguard Worker 57*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BEYOND_64K 58*2d1272b8SAndroid Build Coastguard Worker auto it = Glyph (dest_glyph).get_composite_iterator (); 59*2d1272b8SAndroid Build Coastguard Worker if (it) 60*2d1272b8SAndroid Build Coastguard Worker { 61*2d1272b8SAndroid Build Coastguard Worker /* lower GID24 to GID16 in components if possible. */ 62*2d1272b8SAndroid Build Coastguard Worker char *p = it ? (char *) &*it : nullptr; 63*2d1272b8SAndroid Build Coastguard Worker char *q = p; 64*2d1272b8SAndroid Build Coastguard Worker const char *end = dest_glyph.arrayZ + dest_glyph.length; 65*2d1272b8SAndroid Build Coastguard Worker while (it) 66*2d1272b8SAndroid Build Coastguard Worker { 67*2d1272b8SAndroid Build Coastguard Worker auto &rec = const_cast<CompositeGlyphRecord &> (*it); 68*2d1272b8SAndroid Build Coastguard Worker ++it; 69*2d1272b8SAndroid Build Coastguard Worker 70*2d1272b8SAndroid Build Coastguard Worker q += rec.get_size (); 71*2d1272b8SAndroid Build Coastguard Worker 72*2d1272b8SAndroid Build Coastguard Worker rec.lower_gid_24_to_16 (); 73*2d1272b8SAndroid Build Coastguard Worker 74*2d1272b8SAndroid Build Coastguard Worker unsigned size = rec.get_size (); 75*2d1272b8SAndroid Build Coastguard Worker 76*2d1272b8SAndroid Build Coastguard Worker memmove (p, &rec, size); 77*2d1272b8SAndroid Build Coastguard Worker 78*2d1272b8SAndroid Build Coastguard Worker p += size; 79*2d1272b8SAndroid Build Coastguard Worker } 80*2d1272b8SAndroid Build Coastguard Worker memmove (p, q, end - q); 81*2d1272b8SAndroid Build Coastguard Worker p += end - q; 82*2d1272b8SAndroid Build Coastguard Worker 83*2d1272b8SAndroid Build Coastguard Worker /* We want to shorten the glyph, but we can't do that without 84*2d1272b8SAndroid Build Coastguard Worker * updating the length in the loca table, which is already 85*2d1272b8SAndroid Build Coastguard Worker * written out :-(. So we just fill the rest of the glyph with 86*2d1272b8SAndroid Build Coastguard Worker * harmless instructions, since that's what they will be 87*2d1272b8SAndroid Build Coastguard Worker * interpreted as. 88*2d1272b8SAndroid Build Coastguard Worker * 89*2d1272b8SAndroid Build Coastguard Worker * Should move the lowering to _populate_subset_glyphs() to 90*2d1272b8SAndroid Build Coastguard Worker * fix this issue. */ 91*2d1272b8SAndroid Build Coastguard Worker 92*2d1272b8SAndroid Build Coastguard Worker hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p); 93*2d1272b8SAndroid Build Coastguard Worker p += end - p; 94*2d1272b8SAndroid Build Coastguard Worker dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ); 95*2d1272b8SAndroid Build Coastguard Worker 96*2d1272b8SAndroid Build Coastguard Worker // TODO: Padding; & trim serialized bytes. 97*2d1272b8SAndroid Build Coastguard Worker // TODO: Update length in loca. Ugh. 98*2d1272b8SAndroid Build Coastguard Worker } 99*2d1272b8SAndroid Build Coastguard Worker #endif 100*2d1272b8SAndroid Build Coastguard Worker 101*2d1272b8SAndroid Build Coastguard Worker if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) 102*2d1272b8SAndroid Build Coastguard Worker Glyph (dest_glyph).drop_hints (); 103*2d1272b8SAndroid Build Coastguard Worker 104*2d1272b8SAndroid Build Coastguard Worker if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG) 105*2d1272b8SAndroid Build Coastguard Worker Glyph (dest_glyph).set_overlaps_flag (); 106*2d1272b8SAndroid Build Coastguard Worker 107*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 108*2d1272b8SAndroid Build Coastguard Worker } 109*2d1272b8SAndroid Build Coastguard Worker compile_bytes_with_deltasOT::glyf_impl::SubsetGlyph110*2d1272b8SAndroid Build Coastguard Worker bool compile_bytes_with_deltas (const hb_subset_plan_t *plan, 111*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font, 112*2d1272b8SAndroid Build Coastguard Worker const glyf_accelerator_t &glyf) 113*2d1272b8SAndroid Build Coastguard Worker { 114*2d1272b8SAndroid Build Coastguard Worker allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); 115*2d1272b8SAndroid Build Coastguard Worker return allocated; 116*2d1272b8SAndroid Build Coastguard Worker } 117*2d1272b8SAndroid Build Coastguard Worker free_compiled_bytesOT::glyf_impl::SubsetGlyph118*2d1272b8SAndroid Build Coastguard Worker void free_compiled_bytes () 119*2d1272b8SAndroid Build Coastguard Worker { 120*2d1272b8SAndroid Build Coastguard Worker if (likely (allocated)) { 121*2d1272b8SAndroid Build Coastguard Worker allocated = false; 122*2d1272b8SAndroid Build Coastguard Worker dest_start.fini (); 123*2d1272b8SAndroid Build Coastguard Worker dest_end.fini (); 124*2d1272b8SAndroid Build Coastguard Worker } 125*2d1272b8SAndroid Build Coastguard Worker } 126*2d1272b8SAndroid Build Coastguard Worker drop_hints_bytesOT::glyf_impl::SubsetGlyph127*2d1272b8SAndroid Build Coastguard Worker void drop_hints_bytes () 128*2d1272b8SAndroid Build Coastguard Worker { source_glyph.drop_hints_bytes (dest_start, dest_end); } 129*2d1272b8SAndroid Build Coastguard Worker lengthOT::glyf_impl::SubsetGlyph130*2d1272b8SAndroid Build Coastguard Worker unsigned int length () const { return dest_start.length + dest_end.length; } 131*2d1272b8SAndroid Build Coastguard Worker /* pad to 2 to ensure 2-byte loca will be ok */ paddingOT::glyf_impl::SubsetGlyph132*2d1272b8SAndroid Build Coastguard Worker unsigned int padding () const { return length () % 2; } padded_sizeOT::glyf_impl::SubsetGlyph133*2d1272b8SAndroid Build Coastguard Worker unsigned int padded_size () const { return length () + padding (); } 134*2d1272b8SAndroid Build Coastguard Worker }; 135*2d1272b8SAndroid Build Coastguard Worker 136*2d1272b8SAndroid Build Coastguard Worker 137*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */ 138*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 139*2d1272b8SAndroid Build Coastguard Worker 140*2d1272b8SAndroid Build Coastguard Worker 141*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_SUBSETGLYPH_HH */ 142