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