| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2011,2012 Google, Inc. | 2 * Copyright © 2011,2012 Google, Inc. |
| 3 * | 3 * |
| 4 * This is part of HarfBuzz, a text shaping library. | 4 * This is part of HarfBuzz, a text shaping library. |
| 5 * | 5 * |
| 6 * Permission is hereby granted, without written agreement and without | 6 * Permission is hereby granted, without written agreement and without |
| 7 * license or royalty fees, to use, copy, modify, and distribute this | 7 * license or royalty fees, to use, copy, modify, and distribute this |
| 8 * software and its documentation for any purpose, provided that the | 8 * software and its documentation for any purpose, provided that the |
| 9 * above copyright notice and the following two paragraphs appear in | 9 * above copyright notice and the following two paragraphs appear in |
| 10 * all copies of this software. | 10 * all copies of this software. |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 skip_char (buffer); | 206 skip_char (buffer); |
| 207 else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) | 207 else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) |
| 208 next_char (buffer, glyph); | 208 next_char (buffer, glyph); |
| 209 else if (decompose_compatibility (c, buffer->cur().codepoint)) | 209 else if (decompose_compatibility (c, buffer->cur().codepoint)) |
| 210 skip_char (buffer); | 210 skip_char (buffer); |
| 211 else | 211 else |
| 212 next_char (buffer, glyph); /* glyph is initialized in earlier branches. */ | 212 next_char (buffer, glyph); /* glyph is initialized in earlier branches. */ |
| 213 } | 213 } |
| 214 | 214 |
| 215 static inline void | 215 static inline void |
| 216 handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
igned int end) | 216 handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
igned int end, bool short_circuit) |
| 217 { | 217 { |
| 218 /* TODO Currently if there's a variation-selector we give-up, it's just too ha
rd. */ |
| 218 hb_buffer_t * const buffer = c->buffer; | 219 hb_buffer_t * const buffer = c->buffer; |
| 219 hb_font_t * const font = c->font; | 220 hb_font_t * const font = c->font; |
| 220 for (; buffer->idx < end - 1;) { | 221 for (; buffer->idx < end - 1;) { |
| 221 if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepo
int))) { | 222 if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepo
int))) { |
| 222 /* The next two lines are some ugly lines... But work. */ | 223 /* The next two lines are some ugly lines... But work. */ |
| 223 if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &
buffer->cur().glyph_index())) | 224 if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &
buffer->cur().glyph_index())) |
| 224 { | 225 { |
| 225 buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); | 226 buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); |
| 226 } | 227 } |
| 227 else | 228 else |
| (...skipping 15 matching lines...) Expand all Loading... |
| 243 buffer->next_glyph (); | 244 buffer->next_glyph (); |
| 244 } | 245 } |
| 245 } | 246 } |
| 246 if (likely (buffer->idx < end)) { | 247 if (likely (buffer->idx < end)) { |
| 247 set_glyph (buffer->cur(), font); | 248 set_glyph (buffer->cur(), font); |
| 248 buffer->next_glyph (); | 249 buffer->next_glyph (); |
| 249 } | 250 } |
| 250 } | 251 } |
| 251 | 252 |
| 252 static inline void | 253 static inline void |
| 253 decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned
int end) | 254 decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned
int end, bool short_circuit) |
| 254 { | 255 { |
| 255 hb_buffer_t * const buffer = c->buffer; | 256 hb_buffer_t * const buffer = c->buffer; |
| 256 /* TODO Currently if there's a variation-selector we give-up, it's just too ha
rd. */ | |
| 257 for (unsigned int i = buffer->idx; i < end; i++) | 257 for (unsigned int i = buffer->idx; i < end; i++) |
| 258 if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepo
int))) { | 258 if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepo
int))) { |
| 259 handle_variation_selector_cluster (c, end); | 259 handle_variation_selector_cluster (c, end, short_circuit); |
| 260 return; | 260 return; |
| 261 } | 261 } |
| 262 | 262 |
| 263 while (buffer->idx < end) | 263 while (buffer->idx < end) |
| 264 decompose_current_character (c, false); | 264 decompose_current_character (c, short_circuit); |
| 265 } | 265 } |
| 266 | 266 |
| 267 static inline void | 267 static inline void |
| 268 decompose_cluster (const hb_ot_shape_normalize_context_t *c, bool short_circuit,
unsigned int end) | 268 decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, b
ool might_short_circuit, bool always_short_circuit) |
| 269 { | 269 { |
| 270 if (likely (c->buffer->idx + 1 == end)) | 270 if (likely (c->buffer->idx + 1 == end)) |
| 271 decompose_current_character (c, short_circuit); | 271 decompose_current_character (c, might_short_circuit); |
| 272 else | 272 else |
| 273 decompose_multi_char_cluster (c, end); | 273 decompose_multi_char_cluster (c, end, always_short_circuit); |
| 274 } | 274 } |
| 275 | 275 |
| 276 | 276 |
| 277 static int | 277 static int |
| 278 compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) | 278 compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) |
| 279 { | 279 { |
| 280 unsigned int a = _hb_glyph_info_get_modified_combining_class (pa); | 280 unsigned int a = _hb_glyph_info_get_modified_combining_class (pa); |
| 281 unsigned int b = _hb_glyph_info_get_modified_combining_class (pb); | 281 unsigned int b = _hb_glyph_info_get_modified_combining_class (pb); |
| 282 | 282 |
| 283 return a < b ? -1 : a == b ? 0 : +1; | 283 return a < b ? -1 : a == b ? 0 : +1; |
| 284 } | 284 } |
| 285 | 285 |
| 286 | 286 |
| 287 void | 287 void |
| 288 _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, | 288 _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, |
| 289 hb_buffer_t *buffer, | 289 hb_buffer_t *buffer, |
| 290 hb_font_t *font) | 290 hb_font_t *font) |
| 291 { | 291 { |
| 292 hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference
? | 292 hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference
; |
| 293 » » » » » plan->shaper->normalization_preference
(&buffer->props) : | |
| 294 » » » » » HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT
; | |
| 295 const hb_ot_shape_normalize_context_t c = { | 293 const hb_ot_shape_normalize_context_t c = { |
| 296 plan, | 294 plan, |
| 297 buffer, | 295 buffer, |
| 298 font, | 296 font, |
| 299 buffer->unicode, | 297 buffer->unicode, |
| 300 plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode, | 298 plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode, |
| 301 plan->shaper->compose ? plan->shaper->compose : compose_unicode | 299 plan->shaper->compose ? plan->shaper->compose : compose_unicode |
| 302 }; | 300 }; |
| 303 | 301 |
| 304 bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && | 302 bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE; |
| 305 » » mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITIC
S_NO_SHORT_CIRCUIT; | 303 bool might_short_circuit = always_short_circuit || |
| 304 » » » (mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED
&& |
| 305 » » » mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DI
ACRITICS_NO_SHORT_CIRCUIT); |
| 306 unsigned int count; | 306 unsigned int count; |
| 307 | 307 |
| 308 /* We do a fairly straightforward yet custom normalization process in three | 308 /* We do a fairly straightforward yet custom normalization process in three |
| 309 * separate rounds: decompose, reorder, recompose (if desired). Currently | 309 * separate rounds: decompose, reorder, recompose (if desired). Currently |
| 310 * this makes two buffer swaps. We can make it faster by moving the last | 310 * this makes two buffer swaps. We can make it faster by moving the last |
| 311 * two rounds into the inner loop for the first round, but it's more readable | 311 * two rounds into the inner loop for the first round, but it's more readable |
| 312 * this way. */ | 312 * this way. */ |
| 313 | 313 |
| 314 | 314 |
| 315 /* First round, decompose */ | 315 /* First round, decompose */ |
| 316 | 316 |
| 317 buffer->clear_output (); | 317 buffer->clear_output (); |
| 318 count = buffer->len; | 318 count = buffer->len; |
| 319 for (buffer->idx = 0; buffer->idx < count;) | 319 for (buffer->idx = 0; buffer->idx < count;) |
| 320 { | 320 { |
| 321 unsigned int end; | 321 unsigned int end; |
| 322 for (end = buffer->idx + 1; end < count; end++) | 322 for (end = buffer->idx + 1; end < count; end++) |
| 323 if (buffer->cur().cluster != buffer->info[end].cluster) | 323 if (buffer->cur().cluster != buffer->info[end].cluster) |
| 324 break; | 324 break; |
| 325 | 325 |
| 326 decompose_cluster (&c, short_circuit, end); | 326 decompose_cluster (&c, end, might_short_circuit, always_short_circuit); |
| 327 } | 327 } |
| 328 buffer->swap_buffers (); | 328 buffer->swap_buffers (); |
| 329 | 329 |
| 330 | 330 |
| 331 /* Second round, reorder (inplace) */ | 331 /* Second round, reorder (inplace) */ |
| 332 | 332 |
| 333 count = buffer->len; | 333 count = buffer->len; |
| 334 for (unsigned int i = 0; i < count; i++) | 334 for (unsigned int i = 0; i < count; i++) |
| 335 { | 335 { |
| 336 if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) | 336 if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 348 i = end; | 348 i = end; |
| 349 continue; | 349 continue; |
| 350 } | 350 } |
| 351 | 351 |
| 352 hb_bubble_sort (buffer->info + i, end - i, compare_combining_class); | 352 hb_bubble_sort (buffer->info + i, end - i, compare_combining_class); |
| 353 | 353 |
| 354 i = end; | 354 i = end; |
| 355 } | 355 } |
| 356 | 356 |
| 357 | 357 |
| 358 if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) | 358 if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE || |
| 359 mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) |
| 359 return; | 360 return; |
| 360 | 361 |
| 361 /* Third round, recompose */ | 362 /* Third round, recompose */ |
| 362 | 363 |
| 363 /* As noted in the comment earlier, we don't try to combine | 364 /* As noted in the comment earlier, we don't try to combine |
| 364 * ccc=0 chars with their previous Starter. */ | 365 * ccc=0 chars with their previous Starter. */ |
| 365 | 366 |
| 366 buffer->clear_output (); | 367 buffer->clear_output (); |
| 367 count = buffer->len; | 368 count = buffer->len; |
| 368 unsigned int starter = 0; | 369 unsigned int starter = 0; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 386 &composed) && | 387 &composed) && |
| 387 /* And the font has glyph for the composite. */ | 388 /* And the font has glyph for the composite. */ |
| 388 font->get_glyph (composed, 0, &glyph)) | 389 font->get_glyph (composed, 0, &glyph)) |
| 389 { | 390 { |
| 390 /* Composes. */ | 391 /* Composes. */ |
| 391 buffer->next_glyph (); /* Copy to out-buffer. */ | 392 buffer->next_glyph (); /* Copy to out-buffer. */ |
| 392 if (unlikely (buffer->in_error)) | 393 if (unlikely (buffer->in_error)) |
| 393 return; | 394 return; |
| 394 buffer->merge_out_clusters (starter, buffer->out_len); | 395 buffer->merge_out_clusters (starter, buffer->out_len); |
| 395 buffer->out_len--; /* Remove the second composable. */ | 396 buffer->out_len--; /* Remove the second composable. */ |
| 396 buffer->out_info[starter].codepoint = composed; /* Modify starter and carr
y on. */ | 397 /* Modify starter and carry on. */ |
| 397 set_glyph (buffer->out_info[starter], font); | 398 buffer->out_info[starter].codepoint = composed; |
| 399 buffer->out_info[starter].glyph_index() = glyph; |
| 398 _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unic
ode); | 400 _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unic
ode); |
| 399 | 401 |
| 400 continue; | 402 continue; |
| 401 } | 403 } |
| 402 | 404 |
| 403 /* Blocked, or doesn't compose. */ | 405 /* Blocked, or doesn't compose. */ |
| 404 buffer->next_glyph (); | 406 buffer->next_glyph (); |
| 405 | 407 |
| 406 if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) | 408 if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) |
| 407 starter = buffer->out_len - 1; | 409 starter = buffer->out_len - 1; |
| 408 } | 410 } |
| 409 buffer->swap_buffers (); | 411 buffer->swap_buffers (); |
| 410 | 412 |
| 411 } | 413 } |
| OLD | NEW |