summaryrefslogtreecommitdiffstats
path: root/libass/ass_render.c
diff options
context:
space:
mode:
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r--libass/ass_render.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c
index a9c1447..8a95985 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -38,6 +38,7 @@
#define RASTERIZER_PRECISION 16 // rasterizer spline approximation error in 1/64 pixel units
#define POSITION_PRECISION 8.0 // rough estimate of transform error in 1/64 pixel units
#define MAX_PERSP_SCALE 16.0
+#define SUBPIXEL_ORDER 3 // ~ log2(64 / POSITION_PRECISION)
ASS_Renderer *ass_renderer_init(ASS_Library *library)
@@ -446,7 +447,8 @@ render_glyph(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y,
return tail;
}
-static bool quantize_transform(double m[3][3], BitmapHashKey *key)
+static bool quantize_transform(double m[3][3], ASS_Vector *pos,
+ BitmapHashKey *key)
{
// Full transform:
// x_out = (m_xx * x + m_xy * y + m_xz) / z,
@@ -481,7 +483,7 @@ static bool quantize_transform(double m[3][3], BitmapHashKey *key)
int32_t qr[2];
for (int i = 0; i < 2; i++) {
- center[i] /= POSITION_PRECISION;
+ center[i] /= 64 >> SUBPIXEL_ORDER;
if (!(fabs(center[i]) < max_val))
return false;
qr[i] = lrint(center[i]);
@@ -571,7 +573,10 @@ static bool quantize_transform(double m[3][3], BitmapHashKey *key)
qm[2][j] = lrint(val);
}
- key->offset.x = qr[0]; key->offset.y = qr[1];
+ pos->x = qr[0] >> SUBPIXEL_ORDER;
+ pos->y = qr[1] >> SUBPIXEL_ORDER;
+ key->offset.x = qr[0] & ((1 << SUBPIXEL_ORDER) - 1);
+ key->offset.y = qr[1] & ((1 << SUBPIXEL_ORDER) - 1);
key->matrix_x.x = qm[0][0]; key->matrix_x.y = qm[0][1];
key->matrix_y.x = qm[1][0]; key->matrix_y.y = qm[1][1];
key->matrix_z.x = qm[2][0]; key->matrix_z.y = qm[2][1];
@@ -605,8 +610,8 @@ static void restore_transform(double m[3][3], const BitmapHashKey *key)
m[2][2] = FFMIN(m[2][2], MAX_PERSP_SCALE);
double center[2] = {
- key->offset.x * POSITION_PRECISION,
- key->offset.y * POSITION_PRECISION,
+ key->offset.x * (64 >> SUBPIXEL_ORDER),
+ key->offset.y * (64 >> SUBPIXEL_ORDER),
};
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
@@ -645,9 +650,10 @@ static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head)
m[0][2] = int_to_d6(render_priv->settings.left_margin);
m[1][2] = int_to_d6(render_priv->settings.top_margin);
+ ASS_Vector pos;
BitmapHashKey key;
key.outline = ass_cache_get(render_priv->cache.outline_cache, &ol_key, render_priv);
- if (!key.outline || !key.outline->valid || !quantize_transform(m, &key)) {
+ if (!key.outline || !key.outline->valid || !quantize_transform(m, &pos, &key)) {
ass_cache_dec_ref(key.outline);
return;
}
@@ -673,8 +679,8 @@ static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head)
aw = cur->w;
ah = cur->h;
as = cur->stride;
- bx = clip_bm->left;
- by = clip_bm->top;
+ bx = pos.x + clip_bm->left;
+ by = pos.y + clip_bm->top;
bw = clip_bm->w;
bh = clip_bm->h;
bs = clip_bm->stride;
@@ -1272,8 +1278,8 @@ static void calc_transform_matrix(ASS_Renderer *render_priv,
z4[2] += dist;
double scale_x = dist * render_priv->font_scale_x;
- double offs_x = info->bitmap_advance.x - info->shift.x * render_priv->font_scale_x;
- double offs_y = info->bitmap_advance.y - info->shift.y;
+ double offs_x = info->pos.x - info->shift.x * render_priv->font_scale_x;
+ double offs_y = info->pos.y - info->shift.y;
for (int i = 0; i < 3; i++) {
m[0][i] = z4[i] * offs_x + x4[i] * scale_x;
m[1][i] = z4[i] * offs_y + y3[i] * dist;
@@ -1290,7 +1296,8 @@ static void calc_transform_matrix(ASS_Renderer *render_priv,
* They are returned in info->image (glyph), info->image_o (outline).
*/
static void
-get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
+get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info,
+ ASS_Vector *pos, ASS_Vector *pos_o)
{
if (!info->outline || info->symbol == '\n' || info->symbol == 0 || info->skip) {
ass_cache_dec_ref(info->outline);
@@ -1309,11 +1316,12 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
BitmapHashKey key;
key.outline = info->outline;
- if (!quantize_transform(m, &key)) {
+ if (!quantize_transform(m, pos, &key)) {
ass_cache_dec_ref(info->outline);
return;
}
info->image = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv);
+ *pos_o = *pos;
OutlineHashKey ol_key;
if (info->border_style == 3) {
@@ -1412,7 +1420,7 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
}
key.outline = ass_cache_get(render_priv->cache.outline_cache, &ol_key, render_priv);
- if (!key.outline || !key.outline->valid || !quantize_transform(m, &key)) {
+ if (!key.outline || !key.outline->valid || !quantize_transform(m, pos_o, &key)) {
ass_cache_dec_ref(key.outline);
return;
}
@@ -2195,12 +2203,10 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
continue;
}
for (; info; info = info->next) {
+ ASS_Vector pos, pos_o;
info->pos.x = double_to_d6(device_x + d6_to_double(info->pos.x) * render_priv->font_scale_x);
info->pos.y = double_to_d6(device_y) + info->pos.y;
- info->bitmap_advance.x = info->pos.x & SUBPIXEL_MASK;
- info->bitmap_advance.y = info->pos.y & SUBPIXEL_MASK;
- int x = info->pos.x >> 6, y = info->pos.y >> 6;
- get_bitmap_glyph(render_priv, info);
+ get_bitmap_glyph(render_priv, info, &pos, &pos_o);
if (linebreak || is_new_bm_run(info, last_info)) {
linebreak = 0;
@@ -2273,20 +2279,22 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
}
current_info->bitmaps[current_info->bitmap_count].image = info->image;
current_info->bitmaps[current_info->bitmap_count].image_o = info->image_o;
- current_info->bitmaps[current_info->bitmap_count].x = x;
- current_info->bitmaps[current_info->bitmap_count].y = y;
+ current_info->bitmaps[current_info->bitmap_count].pos = pos;
+ current_info->bitmaps[current_info->bitmap_count].pos_o = pos_o;
current_info->bitmap_count++;
- current_info->x = FFMIN(current_info->x, x);
- current_info->y = FFMIN(current_info->y, y);
+ current_info->x = FFMIN(current_info->x, pos.x);
+ current_info->y = FFMIN(current_info->y, pos.y);
}
}
for (int i = 0; i < nb_bitmaps; i++) {
CombinedBitmapInfo *info = &combined_info[i];
for (int j = 0; j < info->bitmap_count; j++) {
- info->bitmaps[j].x -= info->x;
- info->bitmaps[j].y -= info->y;
+ info->bitmaps[j].pos.x -= info->x;
+ info->bitmaps[j].pos.y -= info->y;
+ info->bitmaps[j].pos_o.x -= info->x;
+ info->bitmaps[j].pos_o.y -= info->y;
}
CompositeHashKey key;
@@ -2330,12 +2338,12 @@ size_t ass_composite_construct(void *key, void *value, void *priv)
for (int i = 0; i < k->bitmap_count; i++) {
BitmapRef *ref = &k->bitmaps[i];
if (ref->image && ref->image->bm) {
- rectangle_combine(&rect, ref->image->bm, ref->x, ref->y);
+ rectangle_combine(&rect, ref->image->bm, ref->pos.x, ref->pos.y);
last = ref;
n_bm++;
}
if (ref->image_o && ref->image_o->bm) {
- rectangle_combine(&rect_o, ref->image_o->bm, ref->x, ref->y);
+ rectangle_combine(&rect_o, ref->image_o->bm, ref->pos_o.x, ref->pos_o.y);
last_o = ref;
n_bm_o++;
}
@@ -2345,8 +2353,8 @@ size_t ass_composite_construct(void *key, void *value, void *priv)
if (!bord && n_bm == 1) {
v->bm = copy_bitmap(render_priv->engine, last->image->bm);
if (v->bm) {
- v->bm->left += last->x;
- v->bm->top += last->y;
+ v->bm->left += last->pos.x;
+ v->bm->top += last->pos.y;
}
} else if (n_bm) {
v->bm = alloc_bitmap(render_priv->engine,
@@ -2362,8 +2370,8 @@ size_t ass_composite_construct(void *key, void *value, void *priv)
Bitmap *src = k->bitmaps[i].image->bm;
if (!src)
continue;
- int x = k->bitmaps[i].x + src->left - dst->left;
- int y = k->bitmaps[i].y + src->top - dst->top;
+ int x = k->bitmaps[i].pos.x + src->left - dst->left;
+ int y = k->bitmaps[i].pos.y + src->top - dst->top;
assert(x >= 0 && x + src->w <= dst->w);
assert(y >= 0 && y + src->h <= dst->h);
unsigned char *buf = dst->buffer + y * dst->stride + x;
@@ -2376,8 +2384,8 @@ size_t ass_composite_construct(void *key, void *value, void *priv)
if (!bord && n_bm_o == 1) {
v->bm_o = copy_bitmap(render_priv->engine, last_o->image_o->bm);
if (v->bm_o) {
- v->bm_o->left += last_o->x;
- v->bm_o->top += last_o->y;
+ v->bm_o->left += last_o->pos_o.x;
+ v->bm_o->top += last_o->pos_o.y;
}
} else if (n_bm_o) {
v->bm_o = alloc_bitmap(render_priv->engine,
@@ -2393,8 +2401,8 @@ size_t ass_composite_construct(void *key, void *value, void *priv)
Bitmap *src = k->bitmaps[i].image_o->bm;
if (!src)
continue;
- int x = k->bitmaps[i].x + src->left - dst->left;
- int y = k->bitmaps[i].y + src->top - dst->top;
+ int x = k->bitmaps[i].pos_o.x + src->left - dst->left;
+ int y = k->bitmaps[i].pos_o.y + src->top - dst->top;
assert(x >= 0 && x + src->w <= dst->w);
assert(y >= 0 && y + src->h <= dst->h);
unsigned char *buf = dst->buffer + y * dst->stride + x;