diff options
author | Grigori Goronzy <greg@blackbox> | 2011-07-11 13:00:08 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@blackbox> | 2011-07-11 13:05:52 +0200 |
commit | db6ccb3634db5ccbce1a2fdaa383085242d52c82 (patch) | |
tree | 33cf84b60230d8a6f2188af87581580cad3d8102 /libass/ass_render.c | |
parent | 778c5cebe439598bf3a6f0277ed7516928f0ff00 (diff) | |
download | libass-db6ccb3634db5ccbce1a2fdaa383085242d52c82.tar.bz2 libass-db6ccb3634db5ccbce1a2fdaa383085242d52c82.tar.xz |
HarfBuzz shaping support
Split up text into runs with the same direction, font face and font
size, shape these runs with HarfBuzz and reorder accordingly.
This noticeably improves Arabic shaping and should make shaping for many
other scripts work. HarfBuzz also does kerning for Latin text.
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r-- | libass/ass_render.c | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index 3aaf943..b634577 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -1050,7 +1050,8 @@ fill_glyph_hash(ASS_Renderer *priv, OutlineHashKey *outline_key, outline_key->type = OUTLINE_GLYPH; key->font = info->font; key->size = info->font_size; - key->ch = info->symbol; + key->face_index = info->face_index; + key->glyph_index = info->glyph_index; key->bold = info->bold; key->italic = info->italic; key->scale_x = double_to_d16(info->scale_x); @@ -1085,8 +1086,11 @@ get_outline_glyph(ASS_Renderer *render_priv, GlyphInfo *info) info->outline = val->outline; info->border = val->border; info->bbox = val->bbox_scaled; - info->advance.x = val->advance.x; - info->advance.y = val->advance.y; + // XXX: more elegant solution? + if (info->drawing) { + info->advance.x = info->drawing->advance.x; + info->advance.y = info->drawing->advance.y; + } info->asc = val->asc; info->desc = val->desc; } else { @@ -1106,22 +1110,22 @@ get_outline_glyph(ASS_Renderer *render_priv, GlyphInfo *info) } else { double size_scaled = ensure_font_size(render_priv, info->font_size * render_priv->font_scale); - int face_index = 0; - int index = 0; ass_font_set_size(info->font, size_scaled); ass_font_set_transform(info->font, info->scale_x, info->scale_y, NULL); - ass_font_get_index(render_priv->fontconfig_priv, info->font, - info->symbol, &face_index, &index); + // symbol might have been changed. re-get it. + //if (info->face_index < 0) + // ass_font_get_index(render_priv->fontconfig_priv, info->font, + // info->symbol, &info->face_index, &info->glyph_index); FT_Glyph glyph = ass_font_get_glyph(render_priv->fontconfig_priv, info->font, - info->symbol, face_index, index, + info->symbol, info->face_index, info->glyph_index, render_priv->settings.hinting, info->flags); if (glyph != NULL) { outline_copy(render_priv->ftlibrary, &((FT_OutlineGlyph)glyph)->outline, &info->outline); - info->advance.x = d16_to_d6(glyph->advance.x); - info->advance.y = d16_to_d6(glyph->advance.y); + //info->advance.x = d16_to_d6(glyph->advance.x); + //info->advance.y = d16_to_d6(glyph->advance.y); FT_Done_Glyph(glyph); ass_font_get_asc_desc(info->font, info->symbol, &info->asc, &info->desc); @@ -1795,6 +1799,35 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, } + // Determine shape runs + int shape_run = 0; + for (i = 0; i < text_info->length; i++) { + GlyphInfo *last = glyphs + i - 1; + GlyphInfo *info = glyphs + i; + // skip drawings + if (info->symbol == 0xfffc) + continue; + // initialize face_index to continue with the same face, if possible + // XXX: can be problematic in some cases, for example if a font misses + // a single glyph, like space (U+0020) + if (i > 0) + info->face_index = last->face_index; + // set size and get glyph index + double size_scaled = ensure_font_size(render_priv, + info->font_size * render_priv->font_scale); + ass_font_set_size(info->font, size_scaled); + ass_font_get_index(render_priv->fontconfig_priv, info->font, + info->symbol, &info->face_index, &info->glyph_index); + // shape runs share the same font face and size + if (i > 0 && (last->font != info->font || + last->font_size != info->font_size || + last->face_index != info->face_index)) + shape_run++; + info->shape_run_id = shape_run; + //printf("glyph '%c' shape run id %d face %d\n", info->symbol, info->shape_run_id, + // info->face_index); + } + if (text_info->length == 0) { // no valid symbols in the event; this can be smth like {comment} free_render_context(render_priv); @@ -1831,14 +1864,6 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, GlyphInfo *info = glyphs + i; #if 0 - // Add kerning to pen - if (kern && previous && info->symbol && !info->drawing) { - FT_Vector delta; - delta = ass_font_get_kerning(info->font, previous, info->symbol); - pen.x += delta.x * info->scale_x; - pen.y += delta.y * info->scale_y; - } - // Add additional space after italic to non-italic style changes if (i && glyphs[i - 1].italic && !info->italic) { int back = i - 1; @@ -1916,8 +1941,8 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, lineno++; } if (info->skip) continue; - info->pos.x = pen.x; - info->pos.y = pen.y; + info->pos.x = info->offset.x + pen.x; + info->pos.y = info->offset.y + pen.y; pen.x += info->advance.x; pen.y += info->advance.y; } |