OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2011 Martin Hosken | 2 * Copyright © 2011 Martin Hosken |
3 * Copyright © 2011 SIL International | 3 * Copyright © 2011 SIL International |
4 * Copyright © 2011,2012 Google, Inc. | 4 * Copyright © 2011,2012 Google, Inc. |
5 * | 5 * |
6 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
7 * | 7 * |
8 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
9 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
10 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 /* | 209 /* |
210 * shaper | 210 * shaper |
211 */ | 211 */ |
212 | 212 |
213 struct hb_graphite2_cluster_t { | 213 struct hb_graphite2_cluster_t { |
214 unsigned int base_char; | 214 unsigned int base_char; |
215 unsigned int num_chars; | 215 unsigned int num_chars; |
216 unsigned int base_glyph; | 216 unsigned int base_glyph; |
217 unsigned int num_glyphs; | 217 unsigned int num_glyphs; |
218 unsigned int cluster; | 218 unsigned int cluster; |
| 219 float advance; |
219 }; | 220 }; |
220 | 221 |
221 hb_bool_t | 222 hb_bool_t |
222 _hb_graphite2_shape (hb_shape_plan_t *shape_plan, | 223 _hb_graphite2_shape (hb_shape_plan_t *shape_plan, |
223 hb_font_t *font, | 224 hb_font_t *font, |
224 hb_buffer_t *buffer, | 225 hb_buffer_t *buffer, |
225 const hb_feature_t *features, | 226 const hb_feature_t *features, |
226 unsigned int num_features) | 227 unsigned int num_features) |
227 { | 228 { |
228 hb_face_t *face = font->face; | 229 hb_face_t *face = font->face; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 304 |
304 ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len); | 305 ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len); |
305 ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count); | 306 ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count); |
306 | 307 |
307 #undef ALLOCATE_ARRAY | 308 #undef ALLOCATE_ARRAY |
308 | 309 |
309 memset (clusters, 0, sizeof (clusters[0]) * buffer->len); | 310 memset (clusters, 0, sizeof (clusters[0]) * buffer->len); |
310 | 311 |
311 hb_codepoint_t *pg = gids; | 312 hb_codepoint_t *pg = gids; |
312 clusters[0].cluster = buffer->info[0].cluster; | 313 clusters[0].cluster = buffer->info[0].cluster; |
| 314 float curradv = HB_DIRECTION_IS_BACKWARD(buffer->props.direction) ? gr_slot_or
igin_X(gr_seg_first_slot(seg)) : 0.; |
| 315 if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) |
| 316 { |
| 317 curradv = gr_slot_origin_X(gr_seg_first_slot(seg)); |
| 318 clusters[0].advance = gr_seg_advance_X(seg) - curradv; |
| 319 } |
313 for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (i
s), ic++) | 320 for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (i
s), ic++) |
314 { | 321 { |
315 unsigned int before = gr_slot_before (is); | 322 unsigned int before = gr_slot_before (is); |
316 unsigned int after = gr_slot_after (is); | 323 unsigned int after = gr_slot_after (is); |
317 *pg = gr_slot_gid (is); | 324 *pg = gr_slot_gid (is); |
318 pg++; | 325 pg++; |
319 while (clusters[ci].base_char > before && ci) | 326 while (clusters[ci].base_char > before && ci) |
320 { | 327 { |
321 clusters[ci-1].num_chars += clusters[ci].num_chars; | 328 clusters[ci-1].num_chars += clusters[ci].num_chars; |
322 clusters[ci-1].num_glyphs += clusters[ci].num_glyphs; | 329 clusters[ci-1].num_glyphs += clusters[ci].num_glyphs; |
| 330 clusters[ci-1].advance += clusters[ci].advance; |
323 ci--; | 331 ci--; |
324 } | 332 } |
325 | 333 |
326 if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= cl
usters[ci].base_char + clusters[ci].num_chars) | 334 if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= cl
usters[ci].base_char + clusters[ci].num_chars) |
327 { | 335 { |
328 hb_graphite2_cluster_t *c = clusters + ci + 1; | 336 hb_graphite2_cluster_t *c = clusters + ci + 1; |
329 c->base_char = clusters[ci].base_char + clusters[ci].num_chars; | 337 c->base_char = clusters[ci].base_char + clusters[ci].num_chars; |
330 c->cluster = buffer->info[c->base_char].cluster; | 338 c->cluster = buffer->info[c->base_char].cluster; |
331 c->num_chars = before - c->base_char; | 339 c->num_chars = before - c->base_char; |
332 c->base_glyph = ic; | 340 c->base_glyph = ic; |
333 c->num_glyphs = 0; | 341 c->num_glyphs = 0; |
334 ci++; | 342 if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) |
| 343 { |
| 344 ci++; |
| 345 clusters[ci].advance = curradv - gr_slot_origin_X(is); |
| 346 } else { |
| 347 clusters[ci].advance = gr_slot_origin_X(is) - curradv; |
| 348 ci++; |
| 349 } |
| 350 curradv = gr_slot_origin_X(is); |
335 } | 351 } |
336 clusters[ci].num_glyphs++; | 352 clusters[ci].num_glyphs++; |
337 | 353 |
338 if (clusters[ci].base_char + clusters[ci].num_chars < after + 1) | 354 if (clusters[ci].base_char + clusters[ci].num_chars < after + 1) |
339 clusters[ci].num_chars = after + 1 - clusters[ci].base_char; | 355 clusters[ci].num_chars = after + 1 - clusters[ci].base_char; |
340 } | 356 } |
| 357 |
| 358 if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) |
| 359 clusters[ci].advance = gr_seg_advance_X(seg) - curradv; |
341 ci++; | 360 ci++; |
342 | 361 |
343 for (unsigned int i = 0; i < ci; ++i) | 362 for (unsigned int i = 0; i < ci; ++i) |
344 { | 363 { |
345 for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j) | 364 for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j) |
346 { | 365 { |
347 hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j]; | 366 hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j]; |
348 info->codepoint = gids[clusters[i].base_glyph + j]; | 367 info->codepoint = gids[clusters[i].base_glyph + j]; |
349 info->cluster = clusters[i].cluster; | 368 info->cluster = clusters[i].cluster; |
| 369 info->var1.i32 = clusters[i].advance; // all glyphs in the cluster get
the same advance |
350 } | 370 } |
351 } | 371 } |
352 buffer->len = glyph_count; | 372 buffer->len = glyph_count; |
353 | 373 |
354 float yscale = font->y_scale / font->x_scale; | 374 float yscale = font->y_scale / font->x_scale; |
355 /* Positioning. */ | 375 /* Positioning. */ |
356 if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) | 376 if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) |
357 { | 377 { |
358 hb_glyph_position_t *pPos; | 378 int currclus = -1; |
359 for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_
slot (seg); | 379 const hb_glyph_info_t *info = buffer->info; |
360 is; pPos++, is = gr_slot_next_in_segment (is)) | 380 hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL); |
| 381 curradvx = 0; |
| 382 for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_
segment (is)) |
361 { | 383 { |
362 pPos->x_offset = gr_slot_origin_X (is) - curradvx; | 384 pPos->x_offset = gr_slot_origin_X (is) - curradvx; |
363 pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; | 385 pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; |
364 pPos->x_advance = gr_slot_advance_X (is, grface, grfont); | 386 if (info->cluster != currclus) { |
| 387 pPos->x_advance = info->var1.i32; |
| 388 curradvx += pPos->x_advance; |
| 389 currclus = info->cluster; |
| 390 } else |
| 391 pPos->x_advance = 0.; |
| 392 |
365 pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; | 393 pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; |
366 curradvx += pPos->x_advance; | |
367 curradvy += pPos->y_advance; | 394 curradvy += pPos->y_advance; |
368 } | 395 } |
369 pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx; | |
370 } | 396 } |
371 else | 397 else |
372 { | 398 { |
373 hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL) + b
uffer->len - 1; | |
374 const hb_glyph_info_t *info = buffer->info + buffer->len - 1; | |
375 const hb_glyph_info_t *tinfo; | |
376 const gr_slot *tis; | |
377 int currclus = -1; | 399 int currclus = -1; |
378 float clusx = 0., clusy = 0.; | 400 const hb_glyph_info_t *info = buffer->info; |
379 for (is = gr_seg_last_slot (seg); is; pPos--, info--, is = gr_slot_prev_in_s
egment (is)) | 401 hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL); |
| 402 curradvx = gr_seg_advance_X(seg); |
| 403 for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_
segment (is)) |
380 { | 404 { |
381 if (info->cluster != currclus) | 405 if (info->cluster != currclus) |
382 { | 406 { |
383 curradvx += clusx; | 407 pPos->x_advance = info->var1.i32; |
384 curradvy += clusy; | 408 if (currclus != -1) curradvx -= info[-1].var1.i32; |
385 currclus = info->cluster; | 409 currclus = info->cluster; |
386 clusx = 0.; | 410 } else |
387 clusy = 0.; | 411 pPos->x_advance = 0.; |
388 for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr
_slot_prev_in_segment (tis), tinfo--) | 412 |
389 { | |
390 clusx += gr_slot_advance_X (tis, grface, grfont); | |
391 clusy += gr_slot_advance_Y (tis, grface, grfont) * yscale; | |
392 } | |
393 curradvx += clusx; | |
394 curradvy += clusy; | |
395 } | |
396 pPos->x_advance = gr_slot_advance_X (is, grface, grfont); | |
397 pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; | 413 pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; |
398 curradvx -= pPos->x_advance; | |
399 curradvy -= pPos->y_advance; | 414 curradvy -= pPos->y_advance; |
400 pPos->x_offset = gr_slot_origin_X (is) - curradvx; | 415 pPos->x_offset = gr_slot_origin_X (is) - curradvx + pPos->x_advance; |
401 pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; | 416 pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; |
402 } | 417 } |
403 hb_buffer_reverse_clusters (buffer); | 418 hb_buffer_reverse_clusters (buffer); |
404 } | 419 } |
405 | 420 |
406 if (feats) gr_featureval_destroy (feats); | 421 if (feats) gr_featureval_destroy (feats); |
407 gr_seg_destroy (seg); | 422 gr_seg_destroy (seg); |
408 | 423 |
409 return true; | 424 return true; |
410 } | 425 } |
OLD | NEW |