diff options
author | wm4 <wm4@nowhere> | 2013-09-25 19:23:52 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-09-26 00:39:13 +0200 |
commit | 4f542f2b9d003125c3b04416074078c3d81c0d6c (patch) | |
tree | 0cb8817499bd558a08e1d21a514fa9e2c1afa7fb | |
parent | 9b48357234806a4fe29ec97eba6c998a26033b5d (diff) | |
download | libass-4f542f2b9d003125c3b04416074078c3d81c0d6c.tar.bz2 libass-4f542f2b9d003125c3b04416074078c3d81c0d6c.tar.xz |
Fix Hinting again
Commit 05eb520 missed some duplicated bits in ass_shaper.c.
<wm4> oh crap
<zgreg> oh crap indeed
Instead of duplicating the logic in ass_shaper.c, just change the
glyphs before they even get into processing. This way, all code
reading the font size etc. is affected. This essentially reverts
commit c207000c, because it's not needed anymore.
-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; |