|
1 /* |
|
2 * Copyright © 2007,2008,2009 Red Hat, Inc. |
|
3 * Copyright © 2012,2013 Google, Inc. |
|
4 * |
|
5 * This is part of HarfBuzz, a text shaping library. |
|
6 * |
|
7 * Permission is hereby granted, without written agreement and without |
|
8 * license or royalty fees, to use, copy, modify, and distribute this |
|
9 * software and its documentation for any purpose, provided that the |
|
10 * above copyright notice and the following two paragraphs appear in |
|
11 * all copies of this software. |
|
12 * |
|
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
|
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
|
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
|
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
|
17 * DAMAGE. |
|
18 * |
|
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
|
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
|
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
|
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
|
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
|
24 * |
|
25 * Red Hat Author(s): Behdad Esfahbod |
|
26 * Google Author(s): Behdad Esfahbod |
|
27 */ |
|
28 |
|
29 #ifndef HB_OT_LAYOUT_PRIVATE_HH |
|
30 #define HB_OT_LAYOUT_PRIVATE_HH |
|
31 |
|
32 #include "hb-private.hh" |
|
33 |
|
34 #include "hb-font-private.hh" |
|
35 #include "hb-buffer-private.hh" |
|
36 #include "hb-set-private.hh" |
|
37 |
|
38 |
|
39 /* |
|
40 * GDEF |
|
41 */ |
|
42 |
|
43 typedef enum |
|
44 { |
|
45 /* The following three match LookupFlags::Ignore* numbers. */ |
|
46 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x02u, |
|
47 HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 0x04u, |
|
48 HB_OT_LAYOUT_GLYPH_PROPS_MARK = 0x08u, |
|
49 |
|
50 /* The following are used internally; not derived from GDEF. */ |
|
51 HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u, |
|
52 HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u, |
|
53 |
|
54 HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | |
|
55 HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
|
56 } hb_ot_layout_glyph_class_mask_t; |
|
57 |
|
58 |
|
59 /* |
|
60 * GSUB/GPOS |
|
61 */ |
|
62 |
|
63 HB_INTERNAL hb_bool_t |
|
64 hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, |
|
65 unsigned int lookup_index, |
|
66 const hb_codepoint_t *glyphs, |
|
67 unsigned int glyphs_length, |
|
68 hb_bool_t zero_context); |
|
69 |
|
70 |
|
71 /* Should be called before all the substitute_lookup's are done. */ |
|
72 HB_INTERNAL void |
|
73 hb_ot_layout_substitute_start (hb_font_t *font, |
|
74 hb_buffer_t *buffer); |
|
75 |
|
76 |
|
77 struct hb_ot_layout_lookup_accelerator_t; |
|
78 |
|
79 namespace OT { |
|
80 struct hb_apply_context_t; |
|
81 struct SubstLookup; |
|
82 } |
|
83 |
|
84 HB_INTERNAL void |
|
85 hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, |
|
86 const OT::SubstLookup &lookup, |
|
87 const hb_ot_layout_lookup_accelerator_t &accel); |
|
88 |
|
89 |
|
90 /* Should be called after all the substitute_lookup's are done */ |
|
91 HB_INTERNAL void |
|
92 hb_ot_layout_substitute_finish (hb_font_t *font, |
|
93 hb_buffer_t *buffer); |
|
94 |
|
95 |
|
96 /* Should be called before all the position_lookup's are done. Resets positions to zero. */ |
|
97 HB_INTERNAL void |
|
98 hb_ot_layout_position_start (hb_font_t *font, |
|
99 hb_buffer_t *buffer); |
|
100 |
|
101 /* Should be called after all the position_lookup's are done */ |
|
102 HB_INTERNAL void |
|
103 hb_ot_layout_position_finish (hb_font_t *font, |
|
104 hb_buffer_t *buffer); |
|
105 |
|
106 |
|
107 |
|
108 /* |
|
109 * hb_ot_layout_t |
|
110 */ |
|
111 |
|
112 namespace OT { |
|
113 struct GDEF; |
|
114 struct GSUB; |
|
115 struct GPOS; |
|
116 } |
|
117 |
|
118 struct hb_ot_layout_lookup_accelerator_t |
|
119 { |
|
120 template <typename TLookup> |
|
121 inline void init (const TLookup &lookup) |
|
122 { |
|
123 digest.init (); |
|
124 lookup.add_coverage (&digest); |
|
125 } |
|
126 |
|
127 template <typename TLookup> |
|
128 inline void fini (const TLookup &lookup) |
|
129 { |
|
130 } |
|
131 |
|
132 hb_set_digest_t digest; |
|
133 }; |
|
134 |
|
135 struct hb_ot_layout_t |
|
136 { |
|
137 hb_blob_t *gdef_blob; |
|
138 hb_blob_t *gsub_blob; |
|
139 hb_blob_t *gpos_blob; |
|
140 |
|
141 const struct OT::GDEF *gdef; |
|
142 const struct OT::GSUB *gsub; |
|
143 const struct OT::GPOS *gpos; |
|
144 |
|
145 unsigned int gsub_lookup_count; |
|
146 unsigned int gpos_lookup_count; |
|
147 |
|
148 hb_ot_layout_lookup_accelerator_t *gsub_accels; |
|
149 hb_ot_layout_lookup_accelerator_t *gpos_accels; |
|
150 }; |
|
151 |
|
152 |
|
153 HB_INTERNAL hb_ot_layout_t * |
|
154 _hb_ot_layout_create (hb_face_t *face); |
|
155 |
|
156 HB_INTERNAL void |
|
157 _hb_ot_layout_destroy (hb_ot_layout_t *layout); |
|
158 |
|
159 |
|
160 #define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot) |
|
161 |
|
162 |
|
163 /* |
|
164 * Buffer var routines. |
|
165 */ |
|
166 |
|
167 /* buffer var allocations, used during the entire shaping process */ |
|
168 #define unicode_props0() var2.u8[0] |
|
169 #define unicode_props1() var2.u8[1] |
|
170 |
|
171 /* buffer var allocations, used during the GSUB/GPOS processing */ |
|
172 #define glyph_props() var1.u16[0] /* GDEF glyph properties */ |
|
173 #define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */ |
|
174 #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ |
|
175 |
|
176 /* unicode_props */ |
|
177 |
|
178 enum { |
|
179 MASK0_ZWJ = 0x20u, |
|
180 MASK0_ZWNJ = 0x40u, |
|
181 MASK0_IGNORABLE = 0x80u, |
|
182 MASK0_GEN_CAT = 0x1Fu |
|
183 }; |
|
184 |
|
185 inline void |
|
186 _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode) |
|
187 { |
|
188 /* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */ |
|
189 info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) | |
|
190 (unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) | |
|
191 (info->codepoint == 0x200C ? MASK0_ZWNJ : 0) | |
|
192 (info->codepoint == 0x200D ? MASK0_ZWJ : 0); |
|
193 info->unicode_props1() = unicode->modified_combining_class (info->codepoint); |
|
194 } |
|
195 |
|
196 inline void |
|
197 _hb_glyph_info_set_general_category (hb_glyph_info_t *info, |
|
198 hb_unicode_general_category_t gen_cat) |
|
199 { |
|
200 info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT); |
|
201 } |
|
202 |
|
203 inline hb_unicode_general_category_t |
|
204 _hb_glyph_info_get_general_category (const hb_glyph_info_t *info) |
|
205 { |
|
206 return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT); |
|
207 } |
|
208 |
|
209 inline void |
|
210 _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, |
|
211 unsigned int modified_class) |
|
212 { |
|
213 info->unicode_props1() = modified_class; |
|
214 } |
|
215 |
|
216 inline unsigned int |
|
217 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) |
|
218 { |
|
219 return info->unicode_props1(); |
|
220 } |
|
221 |
|
222 inline hb_bool_t |
|
223 _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) |
|
224 { |
|
225 return !!(info->unicode_props0() & MASK0_IGNORABLE); |
|
226 } |
|
227 |
|
228 inline hb_bool_t |
|
229 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info) |
|
230 { |
|
231 return !!(info->unicode_props0() & MASK0_ZWNJ); |
|
232 } |
|
233 |
|
234 inline hb_bool_t |
|
235 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info) |
|
236 { |
|
237 return !!(info->unicode_props0() & MASK0_ZWJ); |
|
238 } |
|
239 |
|
240 inline void |
|
241 _hb_glyph_info_flip_joiners (hb_glyph_info_t *info) |
|
242 { |
|
243 info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ; |
|
244 } |
|
245 |
|
246 /* lig_props: aka lig_id / lig_comp |
|
247 * |
|
248 * When a ligature is formed: |
|
249 * |
|
250 * - The ligature glyph and any marks in between all the same newly allocated |
|
251 * lig_id, |
|
252 * - The ligature glyph will get lig_num_comps set to the number of components |
|
253 * - The marks get lig_comp > 0, reflecting which component of the ligature |
|
254 * they were applied to. |
|
255 * - This is used in GPOS to attach marks to the right component of a ligature |
|
256 * in MarkLigPos, |
|
257 * - Note that when marks are ligated together, much of the above is skipped |
|
258 * and the current lig_id reused. |
|
259 * |
|
260 * When a multiple-substitution is done: |
|
261 * |
|
262 * - All resulting glyphs will have lig_id = 0, |
|
263 * - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively. |
|
264 * - This is used in GPOS to attach marks to the first component of a |
|
265 * multiple substitution in MarkBasePos. |
|
266 * |
|
267 * The numbers are also used in GPOS to do mark-to-mark positioning only |
|
268 * to marks that belong to the same component of the same ligature. |
|
269 */ |
|
270 |
|
271 static inline void |
|
272 _hb_glyph_info_clear_lig_props (hb_glyph_info_t *info) |
|
273 { |
|
274 info->lig_props() = 0; |
|
275 } |
|
276 |
|
277 #define IS_LIG_BASE 0x10 |
|
278 |
|
279 static inline void |
|
280 _hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info, |
|
281 unsigned int lig_id, |
|
282 unsigned int lig_num_comps) |
|
283 { |
|
284 info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F); |
|
285 } |
|
286 |
|
287 static inline void |
|
288 _hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info, |
|
289 unsigned int lig_id, |
|
290 unsigned int lig_comp) |
|
291 { |
|
292 info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F); |
|
293 } |
|
294 |
|
295 static inline void |
|
296 _hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp) |
|
297 { |
|
298 _hb_glyph_info_set_lig_props_for_mark (info, 0, comp); |
|
299 } |
|
300 |
|
301 static inline unsigned int |
|
302 _hb_glyph_info_get_lig_id (const hb_glyph_info_t *info) |
|
303 { |
|
304 return info->lig_props() >> 5; |
|
305 } |
|
306 |
|
307 static inline bool |
|
308 _hb_glyph_info_ligated_internal (const hb_glyph_info_t *info) |
|
309 { |
|
310 return !!(info->lig_props() & IS_LIG_BASE); |
|
311 } |
|
312 |
|
313 static inline unsigned int |
|
314 _hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info) |
|
315 { |
|
316 if (_hb_glyph_info_ligated_internal (info)) |
|
317 return 0; |
|
318 else |
|
319 return info->lig_props() & 0x0F; |
|
320 } |
|
321 |
|
322 static inline unsigned int |
|
323 _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info) |
|
324 { |
|
325 if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) && |
|
326 _hb_glyph_info_ligated_internal (info)) |
|
327 return info->lig_props() & 0x0F; |
|
328 else |
|
329 return 1; |
|
330 } |
|
331 |
|
332 static inline uint8_t |
|
333 _hb_allocate_lig_id (hb_buffer_t *buffer) { |
|
334 uint8_t lig_id = buffer->next_serial () & 0x07; |
|
335 if (unlikely (!lig_id)) |
|
336 lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */ |
|
337 return lig_id; |
|
338 } |
|
339 |
|
340 /* glyph_props: */ |
|
341 |
|
342 inline void |
|
343 _hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props) |
|
344 { |
|
345 info->glyph_props() = props; |
|
346 } |
|
347 |
|
348 inline unsigned int |
|
349 _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info) |
|
350 { |
|
351 return info->glyph_props(); |
|
352 } |
|
353 |
|
354 inline bool |
|
355 _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info) |
|
356 { |
|
357 return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); |
|
358 } |
|
359 |
|
360 inline bool |
|
361 _hb_glyph_info_is_ligature (const hb_glyph_info_t *info) |
|
362 { |
|
363 return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE); |
|
364 } |
|
365 |
|
366 inline bool |
|
367 _hb_glyph_info_is_mark (const hb_glyph_info_t *info) |
|
368 { |
|
369 return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); |
|
370 } |
|
371 |
|
372 static inline bool |
|
373 _hb_glyph_info_substituted (const hb_glyph_info_t *info) |
|
374 { |
|
375 return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); |
|
376 } |
|
377 |
|
378 static inline bool |
|
379 _hb_glyph_info_ligated (const hb_glyph_info_t *info) |
|
380 { |
|
381 return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED); |
|
382 } |
|
383 |
|
384 /* Allocation / deallocation. */ |
|
385 |
|
386 inline void |
|
387 _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer) |
|
388 { |
|
389 HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0); |
|
390 HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1); |
|
391 } |
|
392 |
|
393 inline void |
|
394 _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer) |
|
395 { |
|
396 HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0); |
|
397 HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1); |
|
398 } |
|
399 |
|
400 inline void |
|
401 _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer) |
|
402 { |
|
403 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props); |
|
404 HB_BUFFER_ALLOCATE_VAR (buffer, lig_props); |
|
405 HB_BUFFER_ALLOCATE_VAR (buffer, syllable); |
|
406 } |
|
407 |
|
408 inline void |
|
409 _hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer) |
|
410 { |
|
411 HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); |
|
412 HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props); |
|
413 HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props); |
|
414 } |
|
415 |
|
416 /* Make sure no one directly touches our props... */ |
|
417 #undef unicode_props0 |
|
418 #undef unicode_props1 |
|
419 #undef lig_props |
|
420 #undef glyph_props |
|
421 |
|
422 |
|
423 #endif /* HB_OT_LAYOUT_PRIVATE_HH */ |