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