diff options
-rw-r--r-- | libass/ass_render.c | 64 | ||||
-rw-r--r-- | libass/ass_render.h | 1 | ||||
-rw-r--r-- | libass/ass_shaper.c | 13 |
3 files changed, 49 insertions, 29 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index 0cf1f16..734dc6c 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -937,8 +937,8 @@ static void draw_opaque_box(ASS_Renderer *render_priv, GlyphInfo *info, { int i; int adv = advance.x; - double scale_y = info->scale_y; - double scale_x = info->scale_x; + double scale_y = info->orig_scale_y; + double scale_x = info->orig_scale_x; // to avoid gaps sx = FFMAX(64, sx); @@ -1099,21 +1099,10 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info) v.desc = drawing->desc; key.u.drawing.text = strdup(drawing->text); } else { - double ft_size; - if (priv->settings.hinting == ASS_HINTING_NONE) { - // arbitrary, not too small to prevent grid fitting rounding effects - // XXX: this is a rather crude hack - ft_size = 256.0; - } else { - // If hinting is enabled, we want to pass the real font size - // to freetype. Normalize scale_y to 1.0. - ft_size = info->scale_y * info->font_size; - } - ass_face_set_size(info->font->faces[info->face_index], ft_size); - ass_font_set_transform(info->font, - info->scale_x * info->font_size / ft_size, - info->scale_y * info->font_size / ft_size, - NULL); + ass_face_set_size(info->font->faces[info->face_index], + info->font_size); + ass_font_set_transform(info->font, info->scale_x, + info->scale_y, NULL); FT_Glyph glyph = ass_font_get_glyph(priv->fontconfig_priv, info->font, info->symbol, info->face_index, info->glyph_index, @@ -1128,8 +1117,8 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info) FT_Done_Glyph(glyph); ass_font_get_asc_desc(info->font, info->symbol, &v.asc, &v.desc); - v.asc *= info->scale_y * info->font_size / ft_size; - v.desc *= info->scale_y * info->font_size / ft_size; + v.asc *= info->scale_y; + v.desc *= info->scale_y; } } @@ -1682,6 +1671,33 @@ fill_bitmap_hash(ASS_Renderer *priv, GlyphInfo *info, } /** + * \brief Adjust the glyph's font size and scale factors to ensure smooth + * scaling and handle pathological font sizes. The main problem here is + * freetype's grid fitting, which destroys animations by font size, or will + * result in incorrect final text size if font sizes are very small and + * scale factors very large. See Google Code issue #46. + * \param priv guess what + * \param glyph the glyph to be modified + */ +static void +fix_glyph_scaling(ASS_Renderer *priv, GlyphInfo *glyph) +{ + double ft_size; + if (priv->settings.hinting == ASS_HINTING_NONE) { + // arbitrary, not too small to prevent grid fitting rounding effects + // XXX: this is a rather crude hack + ft_size = 256.0; + } else { + // If hinting is enabled, we want to pass the real font size + // to freetype. Normalize scale_y to 1.0. + ft_size = glyph->scale_y * glyph->font_size; + } + glyph->scale_x = glyph->scale_x * glyph->font_size / ft_size; + glyph->scale_y = glyph->scale_y * glyph->font_size / ft_size; + glyph->font_size = ft_size; +} + +/** * \brief Main ass rendering function, glues everything together * \param event event to render * \param event_images struct containing resulting images, will also be initialized @@ -1808,8 +1824,12 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, glyphs[text_info->length].blur = render_priv->state.blur; glyphs[text_info->length].shadow_x = render_priv->state.shadow_x; glyphs[text_info->length].shadow_y = render_priv->state.shadow_y; - glyphs[text_info->length].scale_x= render_priv->state.scale_x; - glyphs[text_info->length].scale_y = render_priv->state.scale_y; + glyphs[text_info->length].orig_scale_x + = glyphs[text_info->length].scale_x + = render_priv->state.scale_x; + glyphs[text_info->length].orig_scale_y + = glyphs[text_info->length].scale_y + = render_priv->state.scale_y; glyphs[text_info->length].border_style = render_priv->state.border_style; glyphs[text_info->length].border_x= render_priv->state.border_x; glyphs[text_info->length].border_y = render_priv->state.border_y; @@ -1827,6 +1847,8 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, if (glyphs[text_info->length].drawing) { drawing = render_priv->state.drawing = ass_drawing_new(render_priv->library, render_priv->ftlibrary); + } else { + fix_glyph_scaling(render_priv, &glyphs[text_info->length]); } text_info->length++; diff --git a/libass/ass_render.h b/libass/ass_render.h index ecfca61..3a7c6d9 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -143,6 +143,7 @@ typedef struct glyph_info { double frx, fry, frz; // rotation double fax, fay; // text shearing double scale_x, scale_y; + double orig_scale_x, orig_scale_y; // scale_x,y before fix_glyph_scaling int border_style; double border_x, border_y; double hspacing; diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index 46b11fe..46e6edc 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -392,9 +392,7 @@ static hb_font_t *get_hb_font(ASS_Shaper *shaper, GlyphInfo *info) font->faces[info->face_index], NULL); } - // XXX: this is a rather crude hack - const double ft_size = 256.0; - ass_face_set_size(font->faces[info->face_index], ft_size); + ass_face_set_size(font->faces[info->face_index], info->font_size); update_hb_size(hb_fonts[info->face_index], font->faces[info->face_index]); // update hash key for cached metrics @@ -525,7 +523,6 @@ static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) hb_buffer_t *buf; hb_font_t *font; } runs[MAX_RUNS]; - const double ft_size = 256.0; for (i = 0; i < len && run < MAX_RUNS; i++, run++) { // get length and level of the current run @@ -581,10 +578,10 @@ static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) // 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->font_size / ft_size); - info->offset.y = -pos[j].y_offset * info->scale_y * (info->font_size / ft_size); - info->advance.x = pos[j].x_advance * info->scale_x * (info->font_size / ft_size); - info->advance.y = -pos[j].y_advance * info->scale_y * (info->font_size / ft_size); + 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 advance in the root glyph root->cluster_advance.x += info->advance.x; |