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 */ 424