diff options
-rw-r--r-- | libass/ass_cache.c | 12 | ||||
-rw-r--r-- | libass/ass_cache.h | 5 | ||||
-rw-r--r-- | libass/ass_font.c | 19 | ||||
-rw-r--r-- | libass/ass_font.h | 4 | ||||
-rw-r--r-- | libass/ass_render.c | 143 | ||||
-rw-r--r-- | libass/ass_render.h | 4 |
6 files changed, 108 insertions, 79 deletions
diff --git a/libass/ass_cache.c b/libass/ass_cache.c index e6dae0a..5f24548 100644 --- a/libass/ass_cache.c +++ b/libass/ass_cache.c @@ -22,7 +22,7 @@ #include <inttypes.h> #include <ft2build.h> #include FT_FREETYPE_H -#include FT_GLYPH_H +#include FT_OUTLINE_H #include <assert.h> @@ -105,21 +105,23 @@ static size_t bitmap_size(void *value, size_t value_size) static void glyph_destruct(void *key, void *value) { GlyphHashValue *v = value; - if (v->glyph) - FT_Done_Glyph(v->glyph); - if (v->outline_glyph) - FT_Done_Glyph(v->outline_glyph); + if (v->outline) + outline_free(v->lib, v->outline); + if (v->border) + outline_free(v->lib, v->border); free(key); free(value); } static size_t glyph_size(void *value, size_t value_size) { +#if 0 GlyphHashValue *val = value; if (val->glyph && val->glyph->format == FT_GLYPH_FORMAT_BITMAP) { FT_Bitmap *bitmap = &((FT_BitmapGlyph) val->glyph)->bitmap; return bitmap->rows * bitmap->pitch; } +#endif return 0; } diff --git a/libass/ass_cache.h b/libass/ass_cache.h index 68449cf..cf2c400 100644 --- a/libass/ass_cache.h +++ b/libass/ass_cache.h @@ -42,8 +42,9 @@ typedef struct { } CompositeHashValue; typedef struct { - FT_Glyph glyph; - FT_Glyph outline_glyph; + FT_Library lib; + FT_Outline *outline; + FT_Outline *border; FT_BBox bbox_scaled; // bbox after scaling, but before rotation FT_Vector advance; // 26.6, advance distance to the next bitmap in line int asc, desc; // ascender/descender of a drawing diff --git a/libass/ass_font.c b/libass/ass_font.c index 7b55e81..400dad6 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -388,6 +388,25 @@ static int ass_strike_outline_glyph(FT_Face face, ASS_Font *font, return 0; } +void outline_copy(FT_Library lib, FT_Outline *source, FT_Outline **dest) +{ + if (source == NULL) { + *dest = NULL; + return; + } + *dest = calloc(1, sizeof(**dest)); + + FT_Outline_New(lib, source->n_points, source->n_contours, *dest); + FT_Outline_Copy(source, *dest); +} + +void outline_free(FT_Library lib, FT_Outline *outline) +{ + if (outline) + FT_Outline_Done(lib, outline); + free(outline); +} + /** * Slightly embold a glyph without touching its metrics */ diff --git a/libass/ass_font.h b/libass/ass_font.h index 6f16821..af40ce2 100644 --- a/libass/ass_font.h +++ b/libass/ass_font.h @@ -22,6 +22,8 @@ #include <stdint.h> #include <ft2build.h> #include FT_GLYPH_H +#include FT_OUTLINE_H + #include "ass.h" #include "ass_types.h" @@ -63,5 +65,7 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ASS_Font *font, FT_Vector ass_font_get_kerning(ASS_Font *font, uint32_t c1, uint32_t c2); void ass_font_free(ASS_Font *font); void fix_freetype_stroker(FT_Outline *outline, int border_x, int border_y); +void outline_copy(FT_Library lib, FT_Outline *source, FT_Outline **dest); +void outline_free(FT_Library lib, FT_Outline *outline); #endif /* LIBASS_FONT_H */ 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; } diff --git a/libass/ass_render.h b/libass/ass_render.h index e19bd07..0876589 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -99,8 +99,8 @@ typedef enum { typedef struct { unsigned symbol; unsigned skip; // skip glyph when layouting text - FT_Glyph glyph; - FT_Glyph outline_glyph; + FT_Outline *outline; + FT_Outline *border; Bitmap *bm; // glyph bitmap Bitmap *bm_o; // outline bitmap Bitmap *bm_s; // shadow bitmap |