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.c143
1 files changed, 73 insertions, 70 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 1d7f7a0..9a1b911 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -532,8 +532,8 @@ static void free_list_add(ASS_Renderer *render_priv, void *object)
static void blend_vector_clip(ASS_Renderer *render_priv,
ASS_Image *head)
{
- FT_Glyph glyph;
- FT_BitmapGlyph clip_bm;
+ FT_Outline *outline;
+ Bitmap *clip_bm = NULL;
ASS_Image *cur;
ASS_Drawing *drawing = render_priv->state.clip_drawing;
GlyphHashKey key;
@@ -543,6 +543,8 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
if (!drawing)
return;
+ // FIXME: reimplement cache
+#if 0
// Try to get mask from cache
ass_drawing_hash(drawing);
memset(&key, 0, sizeof(key));
@@ -553,11 +555,13 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
if (val) {
clip_bm = (FT_BitmapGlyph) val->glyph;
} else {
+#endif
GlyphHashValue v;
// Not found in cache, parse and rasterize it
- glyph = (FT_Glyph) *ass_drawing_parse(drawing, 1);
- if (!glyph) {
+ ass_drawing_parse(drawing, 1);
+ outline = &drawing->glyph->outline;
+ if (!outline) {
ass_msg(render_priv->library, MSGL_WARN,
"Clip vector parsing failed. Skipping.");
goto blend_vector_error;
@@ -574,33 +578,28 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
trans.x, trans.y);
}
- // Check glyph bounding box size
- if (check_glyph_area(render_priv->library, glyph)) {
- FT_Done_Glyph(glyph);
- glyph = 0;
- goto blend_vector_error;
- }
-
ass_msg(render_priv->library, MSGL_DBG2,
"Parsed vector clip: scales (%f, %f) string [%s]\n",
drawing->scale_x, drawing->scale_y, drawing->text);
- error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
- if (error) {
+ clip_bm = outline_to_bitmap(render_priv->library,
+ render_priv->ftlibrary, outline, 0);
+ if (clip_bm == NULL) {
ass_msg(render_priv->library, MSGL_WARN,
"Clip vector rasterization failed: %d. Skipping.", error);
- FT_Done_Glyph(glyph);
- glyph = 0;
+ FT_Outline_Done(render_priv->ftlibrary, outline);
}
-blend_vector_error:
- clip_bm = (FT_BitmapGlyph) glyph;
+ //clip_bm = (FT_BitmapGlyph) glyph;
+#if 0
// Add to cache
memset(&v, 0, sizeof(v));
v.glyph = glyph;
ass_cache_put(render_priv->cache.glyph_cache, &key, &v);
}
+#endif
+blend_vector_error:
if (!clip_bm) goto blend_vector_exit;
@@ -613,17 +612,17 @@ blend_vector_error:
unsigned char *abuffer, *bbuffer, *nbuffer;
abuffer = cur->bitmap;
- bbuffer = clip_bm->bitmap.buffer;
+ bbuffer = clip_bm->buffer;
ax = cur->dst_x;
ay = cur->dst_y;
aw = cur->w;
ah = cur->h;
as = cur->stride;
bx = clip_bm->left;
- by = -clip_bm->top;
- bw = clip_bm->bitmap.width;
- bh = clip_bm->bitmap.rows;
- bs = clip_bm->bitmap.pitch;
+ by = clip_bm->top;
+ bw = clip_bm->w;
+ bh = clip_bm->h;
+ bs = clip_bm->w; // XXX: add real stride support
// Calculate overlap coordinates
left = (ax > bx) ? ax : bx;
@@ -682,6 +681,8 @@ blend_vector_error:
}
blend_vector_exit:
+ ass_free_bitmap(clip_bm);
+ FT_Outline_Done(render_priv->ftlibrary, outline);
ass_drawing_free(render_priv->state.clip_drawing);
render_priv->state.clip_drawing = 0;
}
@@ -899,15 +900,13 @@ static void free_render_context(ASS_Renderer *render_priv)
* opaque rectangle.
*/
static void draw_opaque_box(ASS_Renderer *render_priv, uint32_t ch,
- FT_Glyph glyph, int sx, int sy)
+ FT_Outline *ol, FT_Vector advance, int sx, int sy)
{
int asc = 0, desc = 0;
int i;
- int adv = d16_to_d6(glyph->advance.x);
+ int adv = advance.x;
double scale_y = render_priv->state.scale_y;
double scale_x = render_priv->state.scale_x;
- FT_OutlineGlyph og = (FT_OutlineGlyph) glyph;
- FT_Outline *ol;
// to avoid gaps
sx = FFMAX(64, sx);
@@ -939,10 +938,9 @@ static void draw_opaque_box(ASS_Renderer *render_priv, uint32_t ch,
{ .x = -sx, .y = -desc - sy },
};
- FT_Outline_Done(render_priv->ftlibrary, &og->outline);
- FT_Outline_New(render_priv->ftlibrary, 4, 1, &og->outline);
+ FT_Outline_Done(render_priv->ftlibrary, ol);
+ FT_Outline_New(render_priv->ftlibrary, 4, 1, ol);
- ol = &og->outline;
ol->n_points = ol->n_contours = 0;
for (i = 0; i < 4; i++) {
ol->points[ol->n_points] = points[i];
@@ -1061,8 +1059,8 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
fill_glyph_hash(render_priv, &key, drawing, symbol);
val = ass_cache_get(render_priv->cache.glyph_cache, &key);
if (val) {
- info->glyph = val->glyph;
- info->outline_glyph = val->outline_glyph;
+ info->outline = val->outline;
+ info->border = val->border;
info->bbox = val->bbox_scaled;
info->advance.x = val->advance.x;
info->advance.y = val->advance.y;
@@ -1075,26 +1073,36 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
if (drawing->hash) {
if(!ass_drawing_parse(drawing, 0))
return;
- info->glyph = (FT_Glyph) drawing->glyph;
+ outline_copy(render_priv->ftlibrary, &drawing->glyph->outline,
+ &info->outline);
+ info->advance.x = d16_to_d6(((FT_Glyph)drawing->glyph)->advance.x);
+ info->advance.y = d16_to_d6(((FT_Glyph)drawing->glyph)->advance.y);
+ FT_Done_Glyph((FT_Glyph)drawing->glyph);
} else {
- info->glyph =
+ FT_Glyph glyph =
ass_font_get_glyph(render_priv->fontconfig_priv,
render_priv->state.font, symbol,
render_priv->settings.hinting,
render_priv->state.flags);
+ if (glyph != NULL) {
+ outline_copy(render_priv->ftlibrary,
+ &((FT_OutlineGlyph)glyph)->outline, &info->outline);
+ info->advance.x = d16_to_d6(glyph->advance.x);
+ info->advance.y = d16_to_d6(glyph->advance.y);
+ FT_Done_Glyph(glyph);
+ }
}
- if (!info->glyph)
+ if (!info->outline)
return;
- info->advance.x = d16_to_d6(info->glyph->advance.x);
- info->advance.y = d16_to_d6(info->glyph->advance.y);
- FT_Glyph_Get_CBox(info->glyph, FT_GLYPH_BBOX_SUBPIXELS, &info->bbox);
+ FT_Outline_Get_CBox(info->outline, &info->bbox);
if (render_priv->state.style->BorderStyle == 3 &&
(render_priv->state.border_x > 0||
render_priv->state.border_y > 0)) {
- FT_Glyph_Copy(info->glyph, &info->outline_glyph);
- draw_opaque_box(render_priv, symbol, info->outline_glyph,
+ outline_copy(render_priv->ftlibrary, info->outline, &info->border);
+ draw_opaque_box(render_priv, symbol, info->border,
+ info->advance,
double_to_d6(render_priv->state.border_x *
render_priv->border_scale),
double_to_d6(render_priv->state.border_y *
@@ -1103,9 +1111,8 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
|| render_priv->state.border_y > 0)
&& key.scale_x && key.scale_y) {
- FT_Glyph_Copy(info->glyph, &info->outline_glyph);
- stroke_outline(render_priv,
- &((FT_OutlineGlyph) info->outline_glyph)->outline,
+ outline_copy(render_priv->ftlibrary, info->outline, &info->border);
+ stroke_outline(render_priv, info->border,
double_to_d6(render_priv->state.border_x *
render_priv->border_scale),
double_to_d6(render_priv->state.border_y *
@@ -1113,8 +1120,9 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
}
memset(&v, 0, sizeof(v));
- v.glyph = info->glyph;
- v.outline_glyph = info->outline_glyph;
+ v.lib = render_priv->ftlibrary;
+ v.outline = info->outline;
+ v.border = info->border;
v.advance = info->advance;
v.bbox_scaled = info->bbox;
if (drawing->hash) {
@@ -1131,7 +1139,7 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
* onto the screen plane.
*/
static void
-transform_3d_points(FT_Vector shift, FT_Glyph glyph, double frx, double fry,
+transform_3d_points(FT_Vector shift, FT_Outline *outline, double frx, double fry,
double frz, double fax, double fay, double scale,
int yshift)
{
@@ -1141,7 +1149,6 @@ transform_3d_points(FT_Vector shift, FT_Glyph glyph, double frx, double fry,
double cx = cos(frx);
double cy = cos(fry);
double cz = cos(frz);
- FT_Outline *outline = &((FT_OutlineGlyph) glyph)->outline;
FT_Vector *p = outline->points;
double x, y, z, xx, yy, zz;
int i, dist;
@@ -1184,19 +1191,19 @@ transform_3d_points(FT_Vector shift, FT_Glyph glyph, double frx, double fry,
* Rotates both glyphs by frx, fry and frz. Shift vector is added before rotation and subtracted after it.
*/
static void
-transform_3d(FT_Vector shift, FT_Glyph *glyph, FT_Glyph *glyph2,
+transform_3d(FT_Vector shift, FT_Outline *outline, FT_Outline *border,
double frx, double fry, double frz, double fax, double fay,
double scale, int yshift)
{
frx = -frx;
frz = -frz;
if (frx != 0. || fry != 0. || frz != 0. || fax != 0. || fay != 0.) {
- if (glyph && *glyph)
- transform_3d_points(shift, *glyph, frx, fry, frz,
+ if (outline)
+ transform_3d_points(shift, outline, frx, fry, frz,
fax, fay, scale, yshift);
- if (glyph2 && *glyph2)
- transform_3d_points(shift, *glyph2, frx, fry, frz,
+ if (border)
+ transform_3d_points(shift, border, frx, fry, frz,
fax, fay, scale, yshift);
}
}
@@ -1227,14 +1234,13 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
int error;
double fax_scaled, fay_scaled;
info->bm = info->bm_o = info->bm_s = 0;
- if (info->glyph && info->symbol != '\n' && info->symbol != 0
+ if (info->outline && info->symbol != '\n' && info->symbol != 0
&& !info->skip) {
- FT_Glyph glyph;
- FT_Glyph outline;
+ FT_Outline *outline, *border;
double scale_x = render_priv->font_scale_x;
- FT_Glyph_Copy(info->glyph, &glyph);
- FT_Glyph_Copy(info->outline_glyph, &outline);
+ outline_copy(render_priv->ftlibrary, info->outline, &outline);
+ outline_copy(render_priv->ftlibrary, info->border, &border);
// calculating rotation shift vector (from rotation origin to the glyph basepoint)
shift.x = key->shift_x;
shift.y = key->shift_y;
@@ -1242,7 +1248,7 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
render_priv->state.scale_x;
fay_scaled = info->fay * render_priv->state.scale_y;
// apply rotation
- transform_3d(shift, &glyph, &outline,
+ transform_3d(shift, outline, border,
info->frx, info->fry, info->frz, fax_scaled,
fay_scaled, render_priv->font_scale, info->asc);
@@ -1251,24 +1257,21 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
0, double_to_d16(1.0) };
// subpixel shift
- if (glyph) {
- FT_Outline *outl = &((FT_OutlineGlyph) glyph)->outline;
+ if (outline) {
if (scale_x != 1.0)
- FT_Outline_Transform(outl, &m);
- FT_Outline_Translate(outl, key->advance.x, -key->advance.y);
+ FT_Outline_Transform(outline, &m);
+ FT_Outline_Translate(outline, key->advance.x, -key->advance.y);
}
- if (outline) {
- FT_Outline *outl = &((FT_OutlineGlyph) outline)->outline;
+ if (border) {
if (scale_x != 1.0)
- FT_Outline_Transform(outl, &m);
- FT_Outline_Translate(outl, key->advance.x, -key->advance.y);
+ FT_Outline_Transform(border, &m);
+ FT_Outline_Translate(border, key->advance.x, -key->advance.y);
}
// render glyph
error = outline_to_bitmap3(render_priv->library,
render_priv->synth_priv,
render_priv->ftlibrary,
- &((FT_OutlineGlyph)glyph)->outline,
- &((FT_OutlineGlyph)outline)->outline,
+ outline, border,
&info->bm, &info->bm_o,
&info->bm_s, info->be,
info->blur * render_priv->border_scale,
@@ -1282,14 +1285,14 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
hash_val.bm_s = info->bm_s;
ass_cache_put(render_priv->cache.bitmap_cache, key, &hash_val);
- FT_Done_Glyph(glyph);
- FT_Done_Glyph(outline);
+ outline_free(render_priv->ftlibrary, outline);
+ outline_free(render_priv->ftlibrary, border);
}
}
// VSFilter compatibility: invisible fill and no border?
// In this case no shadow is supposed to be rendered.
- if (!info->outline_glyph && (info->c[0] >> 24) == 0xFF)
+ if (!info->border && (info->c[0] >> 24) == 0xFF)
info->bm_s = 0;
}