diff options
author | Grigori Goronzy <greg@blackbox> | 2011-07-11 20:35:16 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@blackbox> | 2011-07-11 20:35:16 +0200 |
commit | 8e87db144289d8f7418f4b0dcd2a02d2f7b1d7eb (patch) | |
tree | 60bd7f0a0e8354fb0e9e76969f626ac64f029ed6 /libass/ass_shaper.c | |
parent | db6ccb3634db5ccbce1a2fdaa383085242d52c82 (diff) | |
download | libass-8e87db144289d8f7418f4b0dcd2a02d2f7b1d7eb.tar.bz2 libass-8e87db144289d8f7418f4b0dcd2a02d2f7b1d7eb.tar.xz |
Support glyph clusters of multiple glyphs
Sometimes a glyph cluster resolves to multiple glyphs, for example when
diacritics are used with Arabic script. This doesn't map well to the
list of glyphs expected by libass.
Extend the glyph list to a list of singly-linked glyph clusters of
glyphs and adapt the renderer to support this.
Diffstat (limited to 'libass/ass_shaper.c')
-rw-r--r-- | libass/ass_shaper.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index 911732c..7f581f3 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -128,6 +128,9 @@ void ass_shaper_shape(TextInfo *text_info, FriBidiCharType *ctypes, // Update glyphs for (j = 0; j < num_glyphs; j++) { int idx = glyph_info[j].cluster + runs[i].offset; + GlyphInfo *info = glyphs + idx; + GlyphInfo *root = info; + #if 0 printf("run %d cluster %d codepoint %d -> '%c'\n", i, idx, glyph_info[j].codepoint, event_text[idx]); @@ -135,12 +138,30 @@ void ass_shaper_shape(TextInfo *text_info, FriBidiCharType *ctypes, pos[j].x_offset, pos[j].y_offset, pos[j].x_advance, pos[j].y_advance); #endif - glyphs[idx].skip = 0; - glyphs[idx].glyph_index = glyph_info[j].codepoint; - glyphs[idx].offset.x = pos[j].x_offset * glyphs[idx].scale_x; - glyphs[idx].offset.y = pos[j].y_offset * glyphs[idx].scale_y; - glyphs[idx].advance.x = pos[j].x_advance * glyphs[idx].scale_x; - glyphs[idx].advance.y = pos[j].y_advance * glyphs[idx].scale_y; + + // if we have more than one glyph per cluster, allocate a new one + // and attach to the root glyph + if (info->skip == 0) { + //printf("duplicate cluster entry, adding glyph\n"); + while (info->next) + info = info->next; + info->next = malloc(sizeof(GlyphInfo)); + memcpy(info->next, info, sizeof(GlyphInfo)); + info = info->next; + info->next = NULL; + } + + // set position and advance + info->skip = 0; + info->glyph_index = glyph_info[j].codepoint; + info->offset.x = pos[j].x_offset * info->scale_x; + info->offset.y = pos[j].y_offset * info->scale_y; + info->advance.x = pos[j].x_advance * info->scale_x; + info->advance.y = pos[j].y_advance * info->scale_y; + + // accumulate maximum advance in the root glyph + root->advance.x = FFMAX(root->advance.x, info->advance.x); + root->advance.y = FFMAX(root->advance.y, info->advance.y); } } @@ -166,6 +187,25 @@ void ass_shaper_shape(TextInfo *text_info, FriBidiCharType *ctypes, free(event_text); } +/** + * \brief clean up additional data temporarily needed for shaping and + * (e.g. additional glyphs allocated) + */ +void ass_shaper_cleanup(TextInfo *text_info) +{ + int i; + + for (i = 0; i < text_info->length; i++) { + GlyphInfo *info = text_info->glyphs + i; + info = info->next; + while (info) { + GlyphInfo *next = info->next; + free(info); + info = next; + } + } +} + void ass_shaper_reorder(TextInfo *text_info, FriBidiCharType *ctypes, FriBidiLevel *emblevels, FriBidiStrIndex *cmap) { |