27 #ifndef HB_OT_POST_TABLE_HH |
27 #ifndef HB_OT_POST_TABLE_HH |
28 #define HB_OT_POST_TABLE_HH |
28 #define HB_OT_POST_TABLE_HH |
29 |
29 |
30 #include "hb-open-type-private.hh" |
30 #include "hb-open-type-private.hh" |
31 #include "hb-dsalgs.hh" |
31 #include "hb-dsalgs.hh" |
|
32 #include "hb-subset-plan.hh" |
32 |
33 |
33 #define HB_STRING_ARRAY_NAME format1_names |
34 #define HB_STRING_ARRAY_NAME format1_names |
34 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh" |
35 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh" |
35 #include "hb-string-array.hh" |
36 #include "hb-string-array.hh" |
36 #undef HB_STRING_ARRAY_LIST |
37 #undef HB_STRING_ARRAY_LIST |
37 #undef HB_STRING_ARRAY_NAME |
38 #undef HB_STRING_ARRAY_NAME |
38 |
39 |
39 #define NUM_FORMAT1_NAMES 258 |
40 #define NUM_FORMAT1_NAMES 258 |
40 |
41 |
41 namespace OT { |
|
42 |
|
43 |
|
44 /* |
42 /* |
45 * post -- PostScript |
43 * post -- PostScript |
|
44 * https://docs.microsoft.com/en-us/typography/opentype/spec/post |
46 */ |
45 */ |
47 |
|
48 #define HB_OT_TAG_post HB_TAG('p','o','s','t') |
46 #define HB_OT_TAG_post HB_TAG('p','o','s','t') |
|
47 |
|
48 |
|
49 namespace OT { |
49 |
50 |
50 |
51 |
51 struct postV2Tail |
52 struct postV2Tail |
52 { |
53 { |
53 inline bool sanitize (hb_sanitize_context_t *c) const |
54 inline bool sanitize (hb_sanitize_context_t *c) const |
80 return_trace (v2.sanitize (c)); |
81 return_trace (v2.sanitize (c)); |
81 } |
82 } |
82 return_trace (true); |
83 return_trace (true); |
83 } |
84 } |
84 |
85 |
|
86 inline bool subset (hb_subset_plan_t *plan) const |
|
87 { |
|
88 unsigned int post_prime_length; |
|
89 hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post)); |
|
90 hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size); |
|
91 post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length); |
|
92 hb_blob_destroy (post_blob); |
|
93 |
|
94 if (unlikely (!post_prime || post_prime_length != post::static_size)) |
|
95 { |
|
96 hb_blob_destroy (post_prime_blob); |
|
97 DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length); |
|
98 return false; |
|
99 } |
|
100 |
|
101 post_prime->version.major.set (3); // Version 3 does not have any glyph names. |
|
102 bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob); |
|
103 hb_blob_destroy (post_prime_blob); |
|
104 |
|
105 return result; |
|
106 } |
|
107 |
85 struct accelerator_t |
108 struct accelerator_t |
86 { |
109 { |
87 inline void init (hb_face_t *face) |
110 inline void init (hb_face_t *face) |
88 { |
111 { |
|
112 index_to_offset.init (); |
|
113 |
89 blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post)); |
114 blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post)); |
90 const post *table = Sanitizer<post>::lock_instance (blob); |
115 const post *table = blob->as<post> (); |
91 unsigned int table_length = hb_blob_get_length (blob); |
116 unsigned int table_length = blob->length; |
92 |
117 |
93 version = table->version.to_int (); |
118 version = table->version.to_int (); |
94 index_to_offset.init (); |
|
95 if (version != 0x00020000) |
119 if (version != 0x00020000) |
96 return; |
120 return; |
97 |
121 |
98 const postV2Tail &v2 = StructAfter<postV2Tail> (*table); |
122 const postV2Tail &v2 = StructAfter<postV2Tail> (*table); |
99 |
123 |
100 glyphNameIndex = &v2.glyphNameIndex; |
124 glyphNameIndex = &v2.glyphNameIndex; |
101 pool = &StructAfter<uint8_t> (v2.glyphNameIndex); |
125 pool = &StructAfter<uint8_t> (v2.glyphNameIndex); |
102 |
126 |
103 const uint8_t *end = (uint8_t *) table + table_length; |
127 const uint8_t *end = (uint8_t *) table + table_length; |
104 for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data) |
128 for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data) |
105 { |
129 index_to_offset.push (data - pool); |
106 uint32_t *offset = index_to_offset.push (); |
|
107 if (unlikely (!offset)) |
|
108 break; |
|
109 *offset = data - pool; |
|
110 } |
|
111 } |
130 } |
112 inline void fini (void) |
131 inline void fini (void) |
113 { |
132 { |
114 index_to_offset.finish (); |
133 index_to_offset.fini (); |
115 free (gids_sorted_by_name); |
134 free (gids_sorted_by_name); |
116 } |
135 } |
117 |
136 |
118 inline bool get_glyph_name (hb_codepoint_t glyph, |
137 inline bool get_glyph_name (hb_codepoint_t glyph, |
119 char *buf, unsigned int buf_len) const |
138 char *buf, unsigned int buf_len) const |
120 { |
139 { |
121 hb_string_t s = find_glyph_name (glyph); |
140 hb_bytes_t s = find_glyph_name (glyph); |
122 if (!s.len) |
141 if (!s.len) |
123 return false; |
142 return false; |
124 if (!buf_len) |
143 if (!buf_len) |
125 return true; |
144 return true; |
126 if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */ |
145 if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */ |
195 } |
214 } |
196 |
215 |
197 static inline int cmp_key (const void *pk, const void *po, void *arg) |
216 static inline int cmp_key (const void *pk, const void *po, void *arg) |
198 { |
217 { |
199 const accelerator_t *thiz = (const accelerator_t *) arg; |
218 const accelerator_t *thiz = (const accelerator_t *) arg; |
200 const hb_string_t *key = (const hb_string_t *) pk; |
219 const hb_bytes_t *key = (const hb_bytes_t *) pk; |
201 uint16_t o = * (const uint16_t *) po; |
220 uint16_t o = * (const uint16_t *) po; |
202 return thiz->find_glyph_name (o).cmp (*key); |
221 return thiz->find_glyph_name (o).cmp (*key); |
203 } |
222 } |
204 |
223 |
205 inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const |
224 inline hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const |
206 { |
225 { |
207 if (version == 0x00010000) |
226 if (version == 0x00010000) |
208 { |
227 { |
209 if (glyph >= NUM_FORMAT1_NAMES) |
228 if (glyph >= NUM_FORMAT1_NAMES) |
210 return hb_string_t (); |
229 return hb_bytes_t (); |
211 |
230 |
212 return format1_names (glyph); |
231 return format1_names (glyph); |
213 } |
232 } |
214 |
233 |
215 if (version != 0x00020000 || glyph >= glyphNameIndex->len) |
234 if (version != 0x00020000 || glyph >= glyphNameIndex->len) |
216 return hb_string_t (); |
235 return hb_bytes_t (); |
217 |
236 |
218 unsigned int index = glyphNameIndex->array[glyph]; |
237 unsigned int index = glyphNameIndex->arrayZ[glyph]; |
219 if (index < NUM_FORMAT1_NAMES) |
238 if (index < NUM_FORMAT1_NAMES) |
220 return format1_names (index); |
239 return format1_names (index); |
221 index -= NUM_FORMAT1_NAMES; |
240 index -= NUM_FORMAT1_NAMES; |
222 |
241 |
223 if (index >= index_to_offset.len) |
242 if (index >= index_to_offset.len) |
224 return hb_string_t (); |
243 return hb_bytes_t (); |
225 unsigned int offset = index_to_offset.array[index]; |
244 unsigned int offset = index_to_offset.arrayZ[index]; |
226 |
245 |
227 const uint8_t *data = pool + offset; |
246 const uint8_t *data = pool + offset; |
228 unsigned int name_length = *data; |
247 unsigned int name_length = *data; |
229 data++; |
248 data++; |
230 |
249 |
231 return hb_string_t ((const char *) data, name_length); |
250 return hb_bytes_t ((const char *) data, name_length); |
232 } |
251 } |
233 |
252 |
234 private: |
253 private: |
235 hb_blob_t *blob; |
254 hb_blob_t *blob; |
236 uint32_t version; |
255 uint32_t version; |
237 const ArrayOf<HBUINT16> *glyphNameIndex; |
256 const ArrayOf<HBUINT16> *glyphNameIndex; |
238 hb_prealloced_array_t<uint32_t, 1> index_to_offset; |
257 hb_vector_t<uint32_t, 1> index_to_offset; |
239 const uint8_t *pool; |
258 const uint8_t *pool; |
240 mutable uint16_t *gids_sorted_by_name; |
259 mutable uint16_t *gids_sorted_by_name; |
241 }; |
260 }; |
242 |
261 |
243 public: |
262 public: |