31 |
31 |
32 #include "hb-private.hh" |
32 #include "hb-private.hh" |
33 |
33 |
34 #include "hb-font-private.hh" |
34 #include "hb-font-private.hh" |
35 #include "hb-buffer-private.hh" |
35 #include "hb-buffer-private.hh" |
36 #include "hb-set-private.hh" |
36 #include "hb-set-digest-private.hh" |
|
37 #include "hb-open-type-private.hh" |
37 |
38 |
38 |
39 |
39 /* Private API corresponding to hb-ot-layout.h: */ |
40 /* Private API corresponding to hb-ot-layout.h: */ |
40 |
41 |
41 HB_INTERNAL hb_bool_t |
42 HB_INTERNAL hb_bool_t |
151 struct hb_ot_layout_t |
154 struct hb_ot_layout_t |
152 { |
155 { |
153 hb_blob_t *gdef_blob; |
156 hb_blob_t *gdef_blob; |
154 hb_blob_t *gsub_blob; |
157 hb_blob_t *gsub_blob; |
155 hb_blob_t *gpos_blob; |
158 hb_blob_t *gpos_blob; |
156 hb_blob_t *math_blob; |
|
157 |
159 |
158 const struct OT::GDEF *gdef; |
160 const struct OT::GDEF *gdef; |
159 const struct OT::GSUB *gsub; |
161 const struct OT::GSUB *gsub; |
160 const struct OT::GPOS *gpos; |
162 const struct OT::GPOS *gpos; |
161 const struct OT::MATH *math; |
163 |
|
164 /* TODO Move the following out of this struct. */ |
|
165 OT::hb_lazy_table_loader_t<struct OT::MATH> math; |
|
166 OT::hb_lazy_table_loader_t<struct OT::fvar> fvar; |
|
167 OT::hb_lazy_table_loader_t<struct OT::avar> avar; |
162 |
168 |
163 unsigned int gsub_lookup_count; |
169 unsigned int gsub_lookup_count; |
164 unsigned int gpos_lookup_count; |
170 unsigned int gpos_lookup_count; |
165 |
171 |
166 hb_ot_layout_lookup_accelerator_t *gsub_accels; |
172 hb_ot_layout_lookup_accelerator_t *gsub_accels; |
189 #define glyph_props() var1.u16[0] /* GDEF glyph properties */ |
195 #define glyph_props() var1.u16[0] /* GDEF glyph properties */ |
190 #define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */ |
196 #define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */ |
191 #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ |
197 #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ |
192 |
198 |
193 |
199 |
194 /* loop over syllables */ |
200 /* Loop over syllables. Based on foreach_cluster(). */ |
195 |
|
196 #define foreach_syllable(buffer, start, end) \ |
201 #define foreach_syllable(buffer, start, end) \ |
197 for (unsigned int \ |
202 for (unsigned int \ |
198 _count = buffer->len, \ |
203 _count = buffer->len, \ |
199 start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \ |
204 start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \ |
200 start < _count; \ |
205 start < _count; \ |
219 /* Design: |
224 /* Design: |
220 * unicode_props() is a two-byte number. The low byte includes: |
225 * unicode_props() is a two-byte number. The low byte includes: |
221 * - General_Category: 5 bits. |
226 * - General_Category: 5 bits. |
222 * - A bit each for: |
227 * - A bit each for: |
223 * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). |
228 * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). |
224 * * Whether it's one of the three Mongolian Free Variation Selectors. |
229 * * Whether it's one of the three Mongolian Free Variation Selectors, |
|
230 * CGJ, or other characters that are hidden but should not be ignored |
|
231 * like most other Default_Ignorable()s do during matching. |
225 * * One free bit right now. |
232 * * One free bit right now. |
226 * |
233 * |
227 * The high-byte has different meanings, switched by the Gen-Cat: |
234 * The high-byte has different meanings, switched by the Gen-Cat: |
228 * - For Mn,Mc,Me: the modified Combining_Class. |
235 * - For Mn,Mc,Me: the modified Combining_Class. |
229 * - For Cf: whether it's ZWJ, ZWNJ, or something else. |
236 * - For Cf: whether it's ZWJ, ZWNJ, or something else. |
232 */ |
239 */ |
233 |
240 |
234 enum hb_unicode_props_flags_t { |
241 enum hb_unicode_props_flags_t { |
235 UPROPS_MASK_GEN_CAT = 0x001Fu, |
242 UPROPS_MASK_GEN_CAT = 0x001Fu, |
236 UPROPS_MASK_IGNORABLE = 0x0020u, |
243 UPROPS_MASK_IGNORABLE = 0x0020u, |
237 UPROPS_MASK_FVS = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3 */ |
244 UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, |
|
245 * or TAG characters */ |
238 |
246 |
239 /* If GEN_CAT=FORMAT, top byte masks: */ |
247 /* If GEN_CAT=FORMAT, top byte masks: */ |
240 UPROPS_MASK_Cf_ZWJ = 0x0100u, |
248 UPROPS_MASK_Cf_ZWJ = 0x0100u, |
241 UPROPS_MASK_Cf_ZWNJ = 0x0200u |
249 UPROPS_MASK_Cf_ZWNJ = 0x0200u |
242 }; |
250 }; |
256 if (unlikely (unicode->is_default_ignorable (u))) |
264 if (unlikely (unicode->is_default_ignorable (u))) |
257 { |
265 { |
258 buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES; |
266 buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES; |
259 props |= UPROPS_MASK_IGNORABLE; |
267 props |= UPROPS_MASK_IGNORABLE; |
260 if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ; |
268 if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ; |
261 if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ; |
269 else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ; |
262 /* Mongolian Free Variation Selectors need to be remembered |
270 /* Mongolian Free Variation Selectors need to be remembered |
263 * because although we need to hide them like default-ignorables, |
271 * because although we need to hide them like default-ignorables, |
264 * they need to non-ignorable during shaping. This is similar to |
272 * they need to non-ignorable during shaping. This is similar to |
265 * what we do for joiners in Indic-like shapers, but since the |
273 * what we do for joiners in Indic-like shapers, but since the |
266 * FVSes are GC=Mn, we have use a separate bit to remember them. |
274 * FVSes are GC=Mn, we have use a separate bit to remember them. |
267 * Fixes: |
275 * Fixes: |
268 * https://github.com/behdad/harfbuzz/issues/234 |
276 * https://github.com/behdad/harfbuzz/issues/234 */ |
269 */ |
277 else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN; |
270 if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_FVS; |
278 /* TAG characters need similar treatment. Fixes: |
|
279 * https://github.com/behdad/harfbuzz/issues/463 */ |
|
280 else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN; |
|
281 /* COMBINING GRAPHEME JOINER should not be skipped; at least some times. |
|
282 * https://github.com/behdad/harfbuzz/issues/554 */ |
|
283 else if (unlikely (u == 0x034Fu)) props |= UPROPS_MASK_HIDDEN; |
271 } |
284 } |
272 else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat))) |
285 else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat))) |
273 { |
286 { |
274 /* The above check is just an optimization to let in only things we need further |
287 /* The above check is just an optimization to let in only things we need further |
275 * processing on. */ |
288 * processing on. */ |
335 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) |
348 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) |
336 { |
349 { |
337 return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0; |
350 return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0; |
338 } |
351 } |
339 |
352 |
|
353 #define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info))) |
|
354 |
340 static inline bool |
355 static inline bool |
341 _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info) |
356 _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info) |
342 { |
357 { |
343 return _hb_glyph_info_get_general_category (info) == |
358 return _hb_glyph_info_get_general_category (info) == |
344 HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR; |
359 HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR; |
365 { |
380 { |
366 return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && |
381 return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && |
367 !_hb_glyph_info_ligated (info); |
382 !_hb_glyph_info_ligated (info); |
368 } |
383 } |
369 static inline hb_bool_t |
384 static inline hb_bool_t |
370 _hb_glyph_info_is_default_ignorable_and_not_fvs (const hb_glyph_info_t *info) |
385 _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) |
371 { |
386 { |
372 return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_FVS)) |
387 return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN)) |
373 == UPROPS_MASK_IGNORABLE) && |
388 == UPROPS_MASK_IGNORABLE) && |
374 !_hb_glyph_info_ligated (info); |
389 !_hb_glyph_info_ligated (info); |
375 } |
390 } |
376 |
391 |
377 static inline bool |
392 static inline bool |