summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-03-07 01:04:41 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-03-07 01:04:41 +0200
commite0172b96e3b6cc6a8b62ee5a52f780941a43de8b (patch)
treef652f6d15740667d5434e526db3fd12a0573aa0f /libass
parent0c6f667896620943ee6ae899d6e36c3da5c98c54 (diff)
parent7e253f01715811e0c4f5f5b54317b098f2cd59d9 (diff)
downloadmpv-e0172b96e3b6cc6a8b62ee5a52f780941a43de8b.tar.bz2
mpv-e0172b96e3b6cc6a8b62ee5a52f780941a43de8b.tar.xz
Merge svn changes up to r28862
Diffstat (limited to 'libass')
-rw-r--r--libass/ass.c4
-rw-r--r--libass/ass_bitmap.c43
-rw-r--r--libass/ass_bitmap.h2
-rw-r--r--libass/ass_cache.c50
-rw-r--r--libass/ass_cache.h21
-rw-r--r--libass/ass_render.c194
-rw-r--r--libass/ass_types.h1
-rw-r--r--libass/ass_utils.c11
-rw-r--r--libass/ass_utils.h1
9 files changed, 282 insertions, 45 deletions
diff --git a/libass/ass.c b/libass/ass.c
index 8022dfc9be..612c8d6aae 100644
--- a/libass/ass.c
+++ b/libass/ass.c
@@ -347,6 +347,8 @@ void process_force_style(ass_track_t* track) {
track->Timer = atof(token);
else if(!strcasecmp(*fs, "WrapStyle"))
track->WrapStyle = atoi(token);
+ else if(!strcasecmp(*fs, "ScaledBorderAndShadow"))
+ track->ScaledBorderAndShadow = parse_bool(token);
dt = strrchr(*fs, '.');
if (dt) {
@@ -520,6 +522,8 @@ static int process_info_line(ass_track_t* track, char *str)
track->Timer = atof(str + 6);
} else if (!strncmp(str,"WrapStyle:", 10)) {
track->WrapStyle = atoi(str + 10);
+ } else if (!strncmp(str, "ScaledBorderAndShadow:", 22)) {
+ track->ScaledBorderAndShadow = parse_bool(str + 22);
}
return 0;
}
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c
index 9ccb1bada9..61457f1fcc 100644
--- a/libass/ass_bitmap.c
+++ b/libass/ass_bitmap.c
@@ -214,6 +214,7 @@ static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
dst += bm->w;
}
+ FT_Done_Glyph(glyph);
return bm;
}
@@ -242,7 +243,7 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o)
unsigned char c_g, c_o;
c_g = g[x];
c_o = o[x];
- o[x] = (c_o > c_g) ? c_o : 0;
+ o[x] = (c_o > c_g) ? c_o - (c_g/2) : 0;
s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF;
}
g += bm_g->w;
@@ -254,11 +255,38 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o)
return bm_s;
}
-int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur,
+/**
+ * \brief Blur with [[1,2,1]. [2,4,2], [1,2,1]] kernel
+ * This blur is the same as the one employed by vsfilter.
+ */
+static void be_blur(unsigned char *buf, int w, int h) {
+ unsigned int x, y;
+ unsigned int old_sum, new_sum;
+
+ for (y=0; y<h; y++) {
+ old_sum = 2 * buf[y*w];
+ for (x=0; x<w-1; x++) {
+ new_sum = buf[y*w+x] + buf[y*w+x+1];
+ buf[y*w+x] = (old_sum + new_sum) >> 2;
+ old_sum = new_sum;
+ }
+ }
+
+ for (x=0; x<w; x++) {
+ old_sum = 2 * buf[x];
+ for (y=0; y<h-1; y++) {
+ new_sum = buf[y*w+x] + buf[(y+1)*w+x];
+ buf[y*w+x] = (old_sum + new_sum) >> 2;
+ old_sum = new_sum;
+ }
+ }
+}
+
+int glyph_to_bitmap(ass_synth_priv_t* priv_blur,
FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g,
bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius)
{
- int bord = be ? (be+1) : 0;
+ int bord = be ? (be/4+1) : 0;
blur_radius *= 2;
bord = (blur_radius > 0.0) ? blur_radius : bord;
@@ -278,19 +306,16 @@ int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur,
return 1;
}
}
- if (*bm_o) {
- resize_tmp(priv, (*bm_o)->w, (*bm_o)->h);
+ if (*bm_o)
resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h);
- }
- resize_tmp(priv, (*bm_g)->w, (*bm_g)->h);
resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h);
if (be) {
while (be--) {
if (*bm_o)
- blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+ be_blur((*bm_o)->buffer, (*bm_o)->w, (*bm_o)->h);
else
- blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+ be_blur((*bm_g)->buffer, (*bm_g)->w, (*bm_g)->h);
}
} else {
if (blur_radius > 0.0) {
diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h
index 5f45aae4b2..c0b4ad201f 100644
--- a/libass/ass_bitmap.h
+++ b/libass/ass_bitmap.h
@@ -46,7 +46,7 @@ typedef struct bitmap_s {
* \param bm_g out: pointer to the bitmap of glyph shadow is returned here
* \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
*/
-int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius);
+int glyph_to_bitmap(ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius);
void ass_free_bitmap(bitmap_t* bm);
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index 8c4c91e739..8b9926915f 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -332,3 +332,53 @@ void ass_glyph_cache_reset(void)
ass_glyph_cache_done();
ass_glyph_cache_init();
}
+
+
+//---------------------------------
+// composite cache
+
+hashmap_t* composite_cache;
+
+static void composite_hash_dtor(void* key, size_t key_size, void* value, size_t value_size)
+{
+ composite_hash_val_t* v = value;
+ free(v->a);
+ free(v->b);
+ free(key);
+ free(value);
+}
+
+void* cache_add_composite(composite_hash_key_t* key, composite_hash_val_t* val)
+{
+ return hashmap_insert(composite_cache, key, val);
+}
+
+/**
+ * \brief Get a composite bitmap from composite cache.
+ * \param key hash key
+ * \return requested hash val or 0 if not found
+*/
+composite_hash_val_t* cache_find_composite(composite_hash_key_t* key)
+{
+ return hashmap_find(composite_cache, key);
+}
+
+void ass_composite_cache_init(void)
+{
+ composite_cache = hashmap_init(sizeof(composite_hash_key_t),
+ sizeof(composite_hash_val_t),
+ 0xFFFF + 13,
+ composite_hash_dtor, NULL, NULL);
+}
+
+void ass_composite_cache_done(void)
+{
+ hashmap_done(composite_cache);
+}
+
+void ass_composite_cache_reset(void)
+{
+ ass_composite_cache_done();
+ ass_composite_cache_init();
+}
+
diff --git a/libass/ass_cache.h b/libass/ass_cache.h
index a76d935992..bad0ed8e6e 100644
--- a/libass/ass_cache.h
+++ b/libass/ass_cache.h
@@ -49,6 +49,27 @@ bitmap_hash_val_t* cache_find_bitmap(bitmap_hash_key_t* key);
void ass_bitmap_cache_reset(void);
void ass_bitmap_cache_done(void);
+
+// Cache for composited bitmaps
+typedef struct composite_hash_key_s {
+ int aw, ah, bw, bh;
+ int ax, ay, bx, by;
+ bitmap_hash_key_t a;
+ bitmap_hash_key_t b;
+} composite_hash_key_t;
+
+typedef struct composite_hash_val_s {
+ unsigned char* a;
+ unsigned char* b;
+} composite_hash_val_t;
+
+void ass_composite_cache_init(void);
+void* cache_add_composite(composite_hash_key_t* key, composite_hash_val_t* val);
+composite_hash_val_t* cache_find_composite(composite_hash_key_t* key);
+void ass_composite_cache_reset(void);
+void ass_composite_cache_done(void);
+
+
typedef struct glyph_hash_val_s {
FT_Glyph glyph;
FT_Glyph outline_glyph;
diff --git a/libass/ass_render.c b/libass/ass_render.c
index a755f23223..5eb28ccff0 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -43,8 +43,10 @@
#define MAX_GLYPHS 3000
#define MAX_LINES 300
-#define BE_RADIUS 1.5
#define BLUR_MAX_RADIUS 50.0
+#define MAX_BE 100
+#define ROUND(x) ((int) ((x) + .5))
+#define SUBPIXEL_MASK 56 // d6 bitmask for subpixel accuracy adjustment
static int last_render_id = 0;
@@ -82,7 +84,6 @@ struct ass_renderer_s {
ass_settings_t settings;
int render_id;
ass_synth_priv_t* synth_priv;
- ass_synth_priv_t* synth_priv_blur;
ass_image_t* images_root; // rendering result is stored here
ass_image_t* prev_images_root;
@@ -116,7 +117,7 @@ typedef struct glyph_info_s {
// int height;
int be; // blur edges
double blur; // gaussian blur
- int shadow;
+ double shadow;
double frx, fry, frz; // rotation
bitmap_hash_key_t hash_key;
@@ -165,7 +166,7 @@ typedef struct render_context_s {
uint32_t fade; // alpha from \fad
char be; // blur edges
double blur; // gaussian blur
- int shadow;
+ double shadow;
int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags
effect_t effect_type;
@@ -224,9 +225,15 @@ static void ass_lazy_track_init(void)
} else {
double orig_aspect = (global_settings->aspect * frame_context.height * frame_context.orig_width) /
frame_context.orig_height / frame_context.width;
- if (!track->PlayResY) {
+ if (!track->PlayResY && track->PlayResX == 1280) {
+ track->PlayResY = 1024;
+ mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY);
+ } else if (!track->PlayResY) {
track->PlayResY = track->PlayResX / orig_aspect + .5;
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY);
+ } else if (!track->PlayResX && track->PlayResY == 1024) {
+ track->PlayResX = 1280;
+ mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX);
} else if (!track->PlayResX) {
track->PlayResX = track->PlayResY * orig_aspect + .5;
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX);
@@ -263,8 +270,7 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library)
goto ass_init_exit;
}
- priv->synth_priv = ass_synth_init(BE_RADIUS);
- priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS);
+ priv->synth_priv = ass_synth_init(BLUR_MAX_RADIUS);
priv->library = library;
priv->ftlibrary = ft;
@@ -272,6 +278,7 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library)
ass_font_cache_init();
ass_bitmap_cache_init();
+ ass_composite_cache_init();
ass_glyph_cache_init();
text_info.glyphs = calloc(MAX_GLYPHS, sizeof(glyph_info_t));
@@ -287,6 +294,7 @@ void ass_renderer_done(ass_renderer_t* priv)
{
ass_font_cache_done();
ass_bitmap_cache_done();
+ ass_composite_cache_done();
ass_glyph_cache_done();
if (render_context.stroker) {
FT_Stroker_Done(render_context.stroker);
@@ -399,6 +407,93 @@ static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t c
}
/**
+ * \brief Calculate overlapping area of two consecutive bitmaps and in case they
+ * overlap, composite them together
+ * Mainly useful for translucent glyphs and especially borders, to avoid the
+ * luminance adding up where they overlap (which looks ugly)
+ */
+static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_hash_key_t *last_hash, bitmap_hash_key_t* hash) {
+ int left, top, bottom, right;
+ int old_left, old_top, w, h, cur_left, cur_top;
+ int x, y, opos, cpos;
+ char m;
+ composite_hash_key_t hk;
+ composite_hash_val_t *hv;
+ composite_hash_key_t *nhk;
+ int ax = (*last_tail)->dst_x;
+ int ay = (*last_tail)->dst_y;
+ int aw = (*last_tail)->w;
+ int ah = (*last_tail)->h;
+ int bx = (*tail)->dst_x;
+ int by = (*tail)->dst_y;
+ int bw = (*tail)->w;
+ int bh = (*tail)->h;
+ unsigned char* a;
+ unsigned char* b;
+
+ if ((*last_tail)->bitmap == (*tail)->bitmap)
+ return;
+
+ // Calculate overlap coordinates
+ left = (ax > bx) ? ax : bx;
+ top = (ay > by) ? ay : by;
+ right = ((ax+aw) < (bx+bw)) ? (ax+aw) : (bx+bw);
+ bottom = ((ay+ah) < (by+bh)) ? (ay+ah) : (by+bh);
+ if ((right <= left) || (bottom <= top))
+ return;
+ old_left = left-(ax);
+ old_top = top-(ay);
+ w = right-left;
+ h = bottom-top;
+ cur_left = left-(bx);
+ cur_top = top-(by);
+
+ // Query cache
+ memcpy(&hk.a, last_hash, sizeof(*last_hash));
+ memcpy(&hk.b, hash, sizeof(*hash));
+ hk.aw = aw;
+ hk.ah = ah;
+ hk.bw = bw;
+ hk.bh = bh;
+ hk.ax = ax;
+ hk.ay = ay;
+ hk.bx = bx;
+ hk.by = by;
+ hv = cache_find_composite(&hk);
+ if (hv) {
+ (*last_tail)->bitmap = hv->a;
+ (*tail)->bitmap = hv->b;
+ return;
+ }
+
+ // Allocate new bitmaps and copy over data
+ a = (*last_tail)->bitmap;
+ b = (*tail)->bitmap;
+ (*last_tail)->bitmap = malloc(aw*ah);
+ (*tail)->bitmap = malloc(bw*bh);
+ memcpy((*last_tail)->bitmap, a, aw*ah);
+ memcpy((*tail)->bitmap, b, bw*bh);
+
+ // Composite overlapping area
+ for (y=0; y<h; y++)
+ for (x=0; x<w; x++) {
+ opos = (old_top+y)*(aw) + (old_left+x);
+ cpos = (cur_top+y)*(bw) + (cur_left+x);
+ m = (a[opos] > b[cpos]) ? a[opos] : b[cpos];
+ (*last_tail)->bitmap[opos] = 0;
+ (*tail)->bitmap[cpos] = m;
+ }
+
+ // Insert bitmaps into the cache
+ nhk = calloc(1, sizeof(*nhk));
+ memcpy(nhk, &hk, sizeof(*nhk));
+ hv = calloc(1, sizeof(*hv));
+ hv->a = (*last_tail)->bitmap;
+ hv->b = (*tail)->bitmap;
+ cache_add_composite(nhk, hv);
+}
+
+/**
* \brief Convert text_info_t struct to ass_image_t list
* Splits glyphs in halves when needed (for \kf karaoke).
*/
@@ -409,19 +504,28 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
bitmap_t* bm;
ass_image_t* head;
ass_image_t** tail = &head;
+ ass_image_t** last_tail = 0;
+ ass_image_t** here_tail = 0;
+ bitmap_hash_key_t* last_hash = 0;
for (i = 0; i < text_info->length; ++i) {
glyph_info_t* info = text_info->glyphs + i;
if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0))
continue;
- pen_x = dst_x + info->pos.x + info->shadow;
- pen_y = dst_y + info->pos.y + info->shadow;
+ pen_x = dst_x + info->pos.x + ROUND(info->shadow * frame_context.border_scale);
+ pen_y = dst_y + info->pos.y + ROUND(info->shadow * frame_context.border_scale);
bm = info->bm_s;
+ here_tail = tail;
tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail);
+ if (last_tail && tail != here_tail && ((info->c[3] & 0xff) > 0))
+ render_overlap(last_tail, here_tail, last_hash, &info->hash_key);
+ last_tail = here_tail;
+ last_hash = &info->hash_key;
}
+ last_tail = 0;
for (i = 0; i < text_info->length; ++i) {
glyph_info_t* info = text_info->glyphs + i;
if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o)
@@ -433,8 +537,14 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) {
// do nothing
- } else
+ } else {
+ here_tail = tail;
tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail);
+ if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0))
+ render_overlap(last_tail, here_tail, last_hash, &info->hash_key);
+ last_tail = here_tail;
+ last_hash = &info->hash_key;
+ }
}
for (i = 0; i < text_info->length; ++i) {
glyph_info_t* info = text_info->glyphs + i;
@@ -467,13 +577,22 @@ static int x2scr(double x) {
return x*frame_context.orig_width_nocrop / frame_context.track->PlayResX +
FFMAX(global_settings->left_margin, 0);
}
+static double x2scr_pos(double x) {
+ return x*frame_context.orig_width / frame_context.track->PlayResX +
+ global_settings->left_margin;
+}
/**
* \brief Mapping between script and screen coordinates
*/
-static int y2scr(double y) {
+static double y2scr(double y) {
return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY +
FFMAX(global_settings->top_margin, 0);
}
+static double y2scr_pos(double y) {
+ return y * frame_context.orig_height / frame_context.track->PlayResY +
+ global_settings->top_margin;
+}
+
// the same for toptitles
static int y2scr_top(double y) {
if (global_settings->use_margins)
@@ -776,29 +895,29 @@ static char* parse_tag(char* p, double pwr) {
val = -1.; // reset to default
change_border(val);
} else if (mystrcmp(&p, "move")) {
- int x1, x2, y1, y2;
+ double x1, x2, y1, y2;
long long t1, t2, delta_t, t;
double x, y;
double k;
skip('(');
- mystrtoi(&p, &x1);
+ mystrtod(&p, &x1);
skip(',');
- mystrtoi(&p, &y1);
+ mystrtod(&p, &y1);
skip(',');
- mystrtoi(&p, &x2);
+ mystrtod(&p, &x2);
skip(',');
- mystrtoi(&p, &y2);
+ mystrtod(&p, &y2);
if (*p == ',') {
skip(',');
mystrtoll(&p, &t1);
skip(',');
mystrtoll(&p, &t2);
- mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%d, %d) -> (%d, %d), (%" PRId64 " .. %" PRId64 ")\n",
+ mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%f, %f) -> (%f, %f), (%" PRId64 " .. %" PRId64 ")\n",
x1, y1, x2, y2, (int64_t)t1, (int64_t)t2);
} else {
t1 = 0;
t2 = render_context.event->Duration;
- mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%d, %d) -> (%d, %d)\n", x1, y1, x2, y2);
+ mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%f, %f) -> (%f, %f)\n", x1, y1, x2, y2);
}
skip(')');
delta_t = t2 - t1;
@@ -884,13 +1003,13 @@ static char* parse_tag(char* p, double pwr) {
else
render_context.alignment = render_context.style->Alignment;
} else if (mystrcmp(&p, "pos")) {
- int v1, v2;
+ double v1, v2;
skip('(');
- mystrtoi(&p, &v1);
+ mystrtod(&p, &v1);
skip(',');
- mystrtoi(&p, &v2);
+ mystrtod(&p, &v2);
skip(')');
- mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%d, %d)\n", v1, v2);
+ mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%f, %f)\n", v1, v2);
if (render_context.evt_type == EVENT_POSITIONED) {
mp_msg(MSGT_ASS, MSGL_V, "Subtitle has a new \\pos "
"after \\move or \\pos, ignoring\n");
@@ -1043,9 +1162,9 @@ static char* parse_tag(char* p, double pwr) {
} else if (mystrcmp(&p, "be")) {
int val;
if (mystrtoi(&p, &val)) {
- // Clamp to 10, since high values need excessive CPU
+ // Clamp to a safe upper limit, since high values need excessive CPU
val = (val < 0) ? 0 : val;
- val = (val > 10) ? 10 : val;
+ val = (val > MAX_BE) ? MAX_BE : val;
render_context.be = val;
} else
render_context.be = 0;
@@ -1386,10 +1505,9 @@ static void get_bitmap_glyph(glyph_info_t* info)
// render glyph
error = glyph_to_bitmap(ass_renderer->synth_priv,
- ass_renderer->synth_priv_blur,
info->glyph, info->outline_glyph,
&info->bm, &info->bm_o,
- &info->bm_s, info->be, info->blur);
+ &info->bm_s, info->be, info->blur * frame_context.border_scale);
if (error)
info->symbol = 0;
@@ -1851,8 +1969,13 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
pen.y += delta.y * render_context.scale_y;
}
- shift.x = pen.x & 63;
- shift.y = pen.y & 63;
+ shift.x = pen.x & SUBPIXEL_MASK;
+ shift.y = pen.y & SUBPIXEL_MASK;
+
+ if (render_context.evt_type == EVENT_POSITIONED) {
+ shift.x += double_to_d6(x2scr_pos(render_context.pos_x)) & SUBPIXEL_MASK;
+ shift.y -= double_to_d6(y2scr_pos(render_context.pos_y)) & SUBPIXEL_MASK;
+ }
ass_font_set_transform(render_context.font,
render_context.scale_x * frame_context.font_scale_x,
@@ -2017,8 +2140,8 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
int base_y = 0;
mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y);
get_base_point(bbox, alignment, &base_x, &base_y);
- device_x = x2scr(render_context.pos_x) - base_x;
- device_y = y2scr(render_context.pos_y) - base_y;
+ device_x = x2scr_pos(render_context.pos_x) - base_x;
+ device_y = y2scr_pos(render_context.pos_y) - base_y;
}
// fix clip coordinates (they depend on alignment)
@@ -2103,6 +2226,7 @@ static void ass_reconfigure(ass_renderer_t* priv)
priv->render_id = ++last_render_id;
ass_glyph_cache_reset();
ass_bitmap_cache_reset();
+ ass_composite_cache_reset();
ass_free_images(priv->prev_images_root);
priv->prev_images_root = 0;
}
@@ -2225,12 +2349,12 @@ static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long n
frame_context.font_scale = global_settings->font_size_coeff *
frame_context.orig_height / frame_context.track->PlayResY;
- frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY;
-
- if (frame_context.orig_width * track->PlayResY == frame_context.orig_height * track->PlayResX)
- frame_context.font_scale_x = 1.;
+ if (frame_context.track->ScaledBorderAndShadow)
+ frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY;
else
- frame_context.font_scale_x = ((double)(frame_context.orig_width * track->PlayResY)) / (frame_context.orig_height * track->PlayResX);
+ frame_context.border_scale = 1.;
+
+ frame_context.font_scale_x = 1.;
priv->prev_images_root = priv->images_root;
priv->images_root = 0;
diff --git a/libass/ass_types.h b/libass/ass_types.h
index 870fab4caa..52aff0fb85 100644
--- a/libass/ass_types.h
+++ b/libass/ass_types.h
@@ -105,6 +105,7 @@ typedef struct ass_track_s {
int PlayResY;
double Timer;
int WrapStyle;
+ char ScaledBorderAndShadow;
int default_style; // index of default style
diff --git a/libass/ass_utils.c b/libass/ass_utils.c
index 25e4d4fe7b..7f728f1bb1 100644
--- a/libass/ass_utils.c
+++ b/libass/ass_utils.c
@@ -96,6 +96,17 @@ int strtocolor(char** q, uint32_t* res)
return result;
}
+// Return a boolean value for a string
+char parse_bool(char* str) {
+ while (*str == ' ' || *str == '\t')
+ str++;
+ if (!strncasecmp(str, "yes", 3))
+ return 1;
+ else if (strtol(str, NULL, 10) > 0)
+ return 1;
+ return 0;
+}
+
#if 0
static void sprint_tag(uint32_t tag, char* dst)
{
diff --git a/libass/ass_utils.h b/libass/ass_utils.h
index f37bc0edc1..8c5f3e8f49 100644
--- a/libass/ass_utils.h
+++ b/libass/ass_utils.h
@@ -30,6 +30,7 @@ int mystrtoll(char** p, long long* res);
int mystrtou32(char** p, int base, uint32_t* res);
int mystrtod(char** p, double* res);
int strtocolor(char** q, uint32_t* res);
+char parse_bool(char* str);
static inline int d6_to_int(int x) {
return (x + 32) >> 6;