summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@blackbox>2010-07-22 19:02:12 +0200
committerGrigori Goronzy <greg@blackbox>2010-07-22 19:02:12 +0200
commitc59f2ba8dc58a2feef4fd7230d48eae19e81451f (patch)
tree9a74dbd978c60f51c475e1928c0e33fc3cb20ba2
parentaabf521fc1d29fea2c15a38bdf02a223084e9751 (diff)
downloadlibass-c59f2ba8dc58a2feef4fd7230d48eae19e81451f.tar.bz2
libass-c59f2ba8dc58a2feef4fd7230d48eae19e81451f.tar.xz
Better PAR correction
PAR correction so far merely applied a horizontal scaling factor to glyphs right after loading. This screws up transformed text, unfortunately. It's a much better approach to typeset text without correction and scale everything at the very end. In MPlayer, an EOSD rendering now looks exactly the same as a video filter rendering (except for more sharpness in the EOSD case).
-rw-r--r--Changelog1
-rw-r--r--libass/ass_render.c77
2 files changed, 49 insertions, 29 deletions
diff --git a/Changelog b/Changelog
index f7f7cce..376b337 100644
--- a/Changelog
+++ b/Changelog
@@ -4,6 +4,7 @@ libass (0.9.10)
* charmap selection fixes
* Add ass_flush_events API function
* Improve fullname font matching
+ * Better PAR correction if text transforms are used
libass (0.9.9)
* Parse numbers in a locale-independent way
diff --git a/libass/ass_render.c b/libass/ass_render.c
index cdd8425..e9ea536 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -212,6 +212,7 @@ static ASS_Image *my_draw_bitmap(unsigned char *bitmap, int bitmap_w,
}
static double x2scr_pos(ASS_Renderer *render_priv, double x);
+static double x2scr_pos_scaled(ASS_Renderer *render_priv, double x);
static double y2scr_pos(ASS_Renderer *render_priv, double y);
/*
@@ -240,9 +241,9 @@ static ASS_Image **render_glyph_i(ASS_Renderer *render_priv,
dst_y += bm->top;
// we still need to clip against screen boundaries
- zx = x2scr_pos(render_priv, 0);
+ zx = x2scr_pos_scaled(render_priv, 0);
zy = y2scr_pos(render_priv, 0);
- sx = x2scr_pos(render_priv, render_priv->track->PlayResX);
+ sx = x2scr_pos_scaled(render_priv, render_priv->track->PlayResX);
sy = y2scr_pos(render_priv, render_priv->track->PlayResY);
x0 = 0;
@@ -737,16 +738,26 @@ static ASS_Image *render_text(ASS_Renderer *render_priv, int dst_x,
*/
static double x2scr(ASS_Renderer *render_priv, double x)
{
- return x * render_priv->orig_width_nocrop /
+ return x * render_priv->orig_width_nocrop / render_priv->font_scale_x /
render_priv->track->PlayResX +
FFMAX(render_priv->settings.left_margin, 0);
}
static double x2scr_pos(ASS_Renderer *render_priv, double x)
{
+ return x * render_priv->orig_width / render_priv->font_scale_x / render_priv->track->PlayResX +
+ render_priv->settings.left_margin;
+}
+static double x2scr_scaled(ASS_Renderer *render_priv, double x)
+{
+ return x * render_priv->orig_width_nocrop /
+ render_priv->track->PlayResX +
+ FFMAX(render_priv->settings.left_margin, 0);
+}
+static double x2scr_pos_scaled(ASS_Renderer *render_priv, double x)
+{
return x * render_priv->orig_width / render_priv->track->PlayResX +
render_priv->settings.left_margin;
}
-
/**
* \brief Mapping between script and screen coordinates
*/
@@ -908,8 +919,7 @@ static void draw_opaque_box(ASS_Renderer *render_priv, uint32_t ch,
int i;
int adv = d16_to_d6(glyph->advance.x);
double scale_y = render_priv->state.scale_y;
- double scale_x = render_priv->state.scale_x
- * render_priv->font_scale_x;
+ double scale_x = render_priv->state.scale_x;
FT_OutlineGlyph og = (FT_OutlineGlyph) glyph;
FT_Outline *ol;
@@ -1139,12 +1149,14 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
&& !info->skip) {
FT_Glyph glyph;
FT_Glyph outline;
+ double scale_x = render_priv->font_scale_x;
+
FT_Glyph_Copy(info->glyph, &glyph);
FT_Glyph_Copy(info->outline_glyph, &outline);
// calculating rotation shift vector (from rotation origin to the glyph basepoint)
shift.x = info->hash_key.shift_x;
shift.y = info->hash_key.shift_y;
- fax_scaled = info->fax * render_priv->font_scale_x *
+ fax_scaled = info->fax *
render_priv->state.scale_x;
fay_scaled = info->fay * render_priv->state.scale_y;
// apply rotation
@@ -1152,18 +1164,25 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
info->frx, info->fry, info->frz, fax_scaled,
fay_scaled, render_priv->font_scale, info->asc);
+ // PAR correction scaling
+ FT_Matrix m = { double_to_d16(scale_x), 0,
+ 0, double_to_d16(1.0) };
+
// subpixel shift
- if (glyph)
- FT_Outline_Translate(
- &((FT_OutlineGlyph) glyph)->outline,
- info->hash_key.advance.x,
+ if (glyph) {
+ FT_Outline *outl = &((FT_OutlineGlyph) glyph)->outline;
+ if (scale_x != 1.0)
+ FT_Outline_Transform(outl, &m);
+ FT_Outline_Translate(outl, info->hash_key.advance.x,
-info->hash_key.advance.y);
- if (outline)
- FT_Outline_Translate(
- &((FT_OutlineGlyph) outline)->outline,
- info->hash_key.advance.x,
+ }
+ if (outline) {
+ FT_Outline *outl = &((FT_OutlineGlyph) outline)->outline;
+ if (scale_x != 1.0)
+ FT_Outline_Transform(outl, &m);
+ FT_Outline_Translate(outl, info->hash_key.advance.x,
-info->hash_key.advance.y);
-
+ }
// render glyph
error = glyph_to_bitmap(render_priv->library,
render_priv->synth_priv,
@@ -1701,7 +1720,6 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
// Parse drawing
if (drawing->i) {
drawing->scale_x = render_priv->state.scale_x *
- render_priv->font_scale_x *
render_priv->font_scale;
drawing->scale_y = render_priv->state.scale_y *
render_priv->font_scale;
@@ -1733,15 +1751,12 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
delta =
ass_font_get_kerning(render_priv->state.font, previous,
code);
- pen.x += delta.x * render_priv->state.scale_x
- * render_priv->font_scale_x;
- pen.y += delta.y * render_priv->state.scale_y
- * render_priv->font_scale_x;
+ pen.x += delta.x * render_priv->state.scale_x;
+ pen.y += delta.y * render_priv->state.scale_y;
}
ass_font_set_transform(render_priv->state.font,
- render_priv->state.scale_x *
- render_priv->font_scale_x,
+ render_priv->state.scale_x,
render_priv->state.scale_y, NULL);
get_outline_glyph(render_priv, code,
@@ -2034,9 +2049,9 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
render_priv->state.evt_type == EVENT_HSCROLL ||
render_priv->state.evt_type == EVENT_VSCROLL) {
render_priv->state.clip_x0 =
- x2scr(render_priv, render_priv->state.clip_x0);
+ x2scr_scaled(render_priv, render_priv->state.clip_x0);
render_priv->state.clip_x1 =
- x2scr(render_priv, render_priv->state.clip_x1);
+ x2scr_scaled(render_priv, render_priv->state.clip_x1);
if (valign == VALIGN_TOP) {
render_priv->state.clip_y0 =
y2scr_top(render_priv, render_priv->state.clip_y0);
@@ -2055,9 +2070,9 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
}
} else if (render_priv->state.evt_type == EVENT_POSITIONED) {
render_priv->state.clip_x0 =
- x2scr_pos(render_priv, render_priv->state.clip_x0);
+ x2scr_pos_scaled(render_priv, render_priv->state.clip_x0);
render_priv->state.clip_x1 =
- x2scr_pos(render_priv, render_priv->state.clip_x1);
+ x2scr_pos_scaled(render_priv, render_priv->state.clip_x1);
render_priv->state.clip_y0 =
y2scr_pos(render_priv, render_priv->state.clip_y0);
render_priv->state.clip_y1 =
@@ -2094,8 +2109,10 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
}
// convert glyphs to bitmaps
+ device_x *= render_priv->font_scale_x;
for (i = 0; i < text_info->length; ++i) {
GlyphInfo *g = text_info->glyphs + i;
+ g->pos.x *= render_priv->font_scale_x;
g->hash_key.advance.x =
double_to_d6(device_x - (int) device_x +
d6_to_double(g->pos.x & SUBPIXEL_MASK)) & ~SUBPIXEL_ACCURACY;
@@ -2108,8 +2125,10 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
memset(event_images, 0, sizeof(*event_images));
event_images->top = device_y - text_info->lines[0].asc;
event_images->height = text_info->height;
- event_images->left = device_x + bbox.xMin + 0.5;
- event_images->width = bbox.xMax - bbox.xMin + 0.5;
+ event_images->left =
+ (device_x + bbox.xMin * render_priv->font_scale_x) + 0.5;
+ event_images->width =
+ (bbox.xMax - bbox.xMin) * render_priv->font_scale_x + 0.5;
event_images->detect_collisions = render_priv->state.detect_collisions;
event_images->shift_direction = (valign == VALIGN_TOP) ? 1 : -1;
event_images->event = event;