priv->shaper = ass_shaper_new(0);
ass_shaper_info(library);
+ priv->settings.shaper = ASS_SHAPING_COMPLEX;
ass_init_exit:
if (priv)
* The glyphs are returned in info->glyph and info->outline_glyph
*/
static void
-get_outline_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
+get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
{
OutlineHashValue *val;
OutlineHashKey key;
memset(&info->hash_key, 0, sizeof(key));
- fill_glyph_hash(render_priv, &key, info);
- val = ass_cache_get(render_priv->cache.outline_cache, &key);
+ fill_glyph_hash(priv, &key, info);
+ val = ass_cache_get(priv->cache.outline_cache, &key);
if (val) {
info->hash_key.u.outline.outline = val;
info->outline = val->outline;
info->border = val->border;
info->bbox = val->bbox_scaled;
- if (info->drawing) {
+ if (info->drawing || priv->settings.shaper == ASS_SHAPING_SIMPLE) {
info->cluster_advance.x = info->advance.x = val->advance.x;
info->cluster_advance.y = info->advance.y = val->advance.y;
}
ass_drawing_hash(drawing);
if(!ass_drawing_parse(drawing, 0))
return;
- outline_copy(render_priv->ftlibrary, &drawing->outline,
+ outline_copy(priv->ftlibrary, &drawing->outline,
&info->outline);
info->cluster_advance.x = info->advance.x = drawing->advance.x;
info->cluster_advance.y = info->advance.y = drawing->advance.y;
info->font_size);
ass_font_set_transform(info->font, info->scale_x,
info->scale_y, NULL);
- // 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,
+ ass_font_get_glyph(priv->fontconfig_priv, info->font,
info->symbol, info->face_index, info->glyph_index,
- render_priv->settings.hinting, info->flags);
+ priv->settings.hinting, info->flags);
if (glyph != NULL) {
- outline_copy(render_priv->ftlibrary,
+ outline_copy(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);
+ if (priv->settings.shaper == ASS_SHAPING_SIMPLE) {
+ info->cluster_advance.x = d16_to_d6(glyph->advance.x);
+ info->cluster_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);
FT_Outline_Get_CBox(info->outline, &info->bbox);
- if (render_priv->state.style->BorderStyle == 3 &&
+ if (priv->state.style->BorderStyle == 3 &&
(info->border_x > 0|| info->border_y > 0)) {
- outline_copy(render_priv->ftlibrary, info->outline, &info->border);
- draw_opaque_box(render_priv, info->symbol, info->border,
+ outline_copy(priv->ftlibrary, info->outline, &info->border);
+ draw_opaque_box(priv, info->symbol, info->border,
info->advance,
- double_to_d6(info->border_x *
- render_priv->border_scale),
- double_to_d6(info->border_y *
- render_priv->border_scale));
+ double_to_d6(info->border_x * priv->border_scale),
+ double_to_d6(info->border_y * priv->border_scale));
} else if ((info->border_x > 0 || info->border_y > 0)
&& double_to_d6(info->scale_x) && double_to_d6(info->scale_y)) {
- outline_copy(render_priv->ftlibrary, info->outline, &info->border);
- stroke_outline(render_priv, info->border,
- double_to_d6(info->border_x * render_priv->border_scale),
- double_to_d6(info->border_y * render_priv->border_scale));
+ outline_copy(priv->ftlibrary, info->outline, &info->border);
+ stroke_outline(priv, info->border,
+ double_to_d6(info->border_x * priv->border_scale),
+ double_to_d6(info->border_y * priv->border_scale));
}
memset(&v, 0, sizeof(v));
- v.lib = render_priv->ftlibrary;
+ v.lib = priv->ftlibrary;
v.outline = info->outline;
v.border = info->border;
v.advance = info->cluster_advance;
v.asc = info->asc;
v.desc = info->desc;
info->hash_key.u.outline.outline =
- ass_cache_put(render_priv->cache.outline_cache, &key, &v);
+ ass_cache_put(priv->cache.outline_cache, &key, &v);
}
}
ass_shaper_set_kerning(render_priv->shaper, track->Kerning);
if (track->Language)
ass_shaper_set_language(render_priv->shaper, track->Language);
+ ass_shaper_set_level(render_priv->shaper, render_priv->settings.shaper);
// PAR correction
render_priv->font_scale_x = render_priv->settings.aspect /
#define NUM_FEATURES 3
struct ass_shaper {
+ ASS_ShapingLevel shaping_level;
// FriBidi log2vis
int n_glyphs;
FriBidiChar *event_text;
* Arabic shaping.
* \param len number of clusters
*/
-static void shape_fribidi(ASS_Shaper *shaper, size_t len)
+static void shape_fribidi(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
{
+ int i;
FriBidiJoiningType *joins = calloc(sizeof(*joins), len);
+ // shape on codepoint level
fribidi_get_joining_types(shaper->event_text, len, joins);
fribidi_join_arabic(shaper->ctypes, len, shaper->emblevels, joins);
fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC,
shaper->emblevels, len, joins, shaper->event_text);
+ // update indexes
+ for (i = 0; i < len; i++) {
+ GlyphInfo *info = glyphs + i;
+ FT_Face face = info->font->faces[info->face_index];
+ info->symbol = shaper->event_text[i];
+ info->glyph_index = FT_Get_Char_Index(face, shaper->event_text[i]);
+ }
+
free(joins);
}
shaper->language = hb_language_from_string(code);
}
+/**
+ * Set shaping level. Essentially switches between FriBidi and HarfBuzz.
+ */
+void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level)
+{
+ shaper->shaping_level = level;
+}
+
/**
* \brief Shape an event's text. Calculates directional runs and shapes them.
* \param text_info event's text
glyphs[i].shape_run_id += shaper->emblevels[i];
}
- //shape_fribidi(shaper, text_info->length);
- shape_harfbuzz(shaper, glyphs, text_info->length);
+ switch (shaper->shaping_level) {
+ case ASS_SHAPING_SIMPLE:
+ shape_fribidi(shaper, glyphs, text_info->length);
+ break;
+ case ASS_SHAPING_COMPLEX:
+ shape_harfbuzz(shaper, glyphs, text_info->length);
+ break;
+ }
- // Update glyphs
+ // clean up
for (i = 0; i < text_info->length; i++) {
- glyphs[i].symbol = shaper->event_text[i];
// Skip direction override control characters
// NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't
// been implemented yet