summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2018-12-02 22:34:45 +0300
committerDr.Smile <vabnick@gmail.com>2019-05-19 20:18:51 +0300
commit59ee1255c3d0368005159b03912b747a4641336a (patch)
treea8e9cdabc2587333f8be1240e04bc9d3edc24a7e /libass
parentea7cb5f75920a16c4101a23c47fb46122caf85d8 (diff)
downloadlibass-59ee1255c3d0368005159b03912b747a4641336a.tar.bz2
libass-59ee1255c3d0368005159b03912b747a4641336a.tar.xz
drawing: separate drawing text reading from outline construction
Purpose of this commit is to simplify logic behind drawing handling.
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_drawing.c51
-rw-r--r--libass/ass_drawing.h5
-rw-r--r--libass/ass_outline.c11
-rw-r--r--libass/ass_outline.h1
-rw-r--r--libass/ass_parse.c31
-rw-r--r--libass/ass_render.c97
-rw-r--r--libass/ass_render.h7
7 files changed, 83 insertions, 120 deletions
diff --git a/libass/ass_drawing.c b/libass/ass_drawing.c
index c0ea548..11ff399 100644
--- a/libass/ass_drawing.c
+++ b/libass/ass_drawing.c
@@ -224,57 +224,21 @@ static bool drawing_add_curve(ASS_Drawing *drawing, ASS_DrawingToken *token,
}
/*
- * \brief Create and initialize a new drawing and return it
+ * \brief Convert token list to outline. Calls the line and curve evaluators.
*/
-ASS_Drawing *ass_drawing_new(ASS_Library *lib)
+ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, ASS_Library *lib, bool raw_mode)
{
- ASS_Drawing *drawing = calloc(1, sizeof(*drawing));
- if (!drawing)
- return NULL;
- rectangle_reset(&drawing->cbox);
drawing->library = lib;
- drawing->scale_x = 1.;
- drawing->scale_y = 1.;
-
- if (!outline_alloc(&drawing->outline, GLYPH_INITIAL_POINTS, GLYPH_INITIAL_SEGMENTS)) {
- free(drawing);
+ rectangle_reset(&drawing->cbox);
+ if (!outline_alloc(&drawing->outline, GLYPH_INITIAL_POINTS, GLYPH_INITIAL_SEGMENTS))
return NULL;
- }
- return drawing;
-}
-
-/*
- * \brief Free a drawing
- */
-void ass_drawing_free(ASS_Drawing *drawing)
-{
- if (drawing) {
- free(drawing->text);
- outline_free(&drawing->outline);
- }
- free(drawing);
-}
-
-/*
- * \brief Copy an ASCII string to the drawing text buffer
- */
-void ass_drawing_set_text(ASS_Drawing *drawing, char *str, size_t len)
-{
- free(drawing->text);
- drawing->text = strndup(str, len);
-}
-
-/*
- * \brief Convert token list to outline. Calls the line and curve evaluators.
- */
-ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, bool raw_mode)
-{
- bool started = false;
- ASS_Vector pen = {0, 0};
+ drawing->outline.n_points = drawing->outline.n_segments = 0;
ASS_DrawingToken *tokens = drawing_tokenize(drawing->text);
drawing_prepare(drawing);
+ bool started = false;
+ ASS_Vector pen = {0, 0};
ASS_DrawingToken *token = tokens;
while (token) {
// Draw something according to current command
@@ -349,5 +313,6 @@ ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, bool raw_mode)
error:
drawing_free_tokens(tokens);
+ outline_free(&drawing->outline);
return NULL;
}
diff --git a/libass/ass_drawing.h b/libass/ass_drawing.h
index 2b08e77..16d85ed 100644
--- a/libass/ass_drawing.h
+++ b/libass/ass_drawing.h
@@ -59,9 +59,6 @@ typedef struct {
ASS_Rect cbox; // bounding box, or let's say... VSFilter's idea of it
} ASS_Drawing;
-ASS_Drawing *ass_drawing_new(ASS_Library *lib);
-void ass_drawing_free(ASS_Drawing *drawing);
-void ass_drawing_set_text(ASS_Drawing *drawing, char *str, size_t n);
-ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, bool raw_mode);
+ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, ASS_Library *lib, bool raw_mode);
#endif /* LIBASS_DRAWING_H */
diff --git a/libass/ass_outline.c b/libass/ass_outline.c
index 1b9afe9..1ed94b8 100644
--- a/libass/ass_outline.c
+++ b/libass/ass_outline.c
@@ -218,6 +218,17 @@ bool outline_copy(ASS_Outline *outline, const ASS_Outline *source)
return true;
}
+void outline_move(ASS_Outline *outline, ASS_Outline *source)
+{
+ if (!source || !source->n_points) {
+ outline_clear(outline);
+ return;
+ }
+
+ memcpy(outline, source, sizeof(*outline));
+ outline_clear(source);
+}
+
void outline_free(ASS_Outline *outline)
{
if (!outline)
diff --git a/libass/ass_outline.h b/libass/ass_outline.h
index 6be0211..85faea9 100644
--- a/libass/ass_outline.h
+++ b/libass/ass_outline.h
@@ -89,6 +89,7 @@ typedef struct {
bool outline_alloc(ASS_Outline *outline, size_t n_points, size_t n_segments);
bool outline_convert(ASS_Outline *outline, const FT_Outline *source);
bool outline_copy(ASS_Outline *outline, const ASS_Outline *source);
+void outline_move(ASS_Outline *outline, ASS_Outline *source);
void outline_free(ASS_Outline *outline);
bool outline_add_point(ASS_Outline *outline, ASS_Vector pt, char segment);
diff --git a/libass/ass_parse.c b/libass/ass_parse.c
index 3ccf556..9397971 100644
--- a/libass/ass_parse.c
+++ b/libass/ass_parse.c
@@ -198,29 +198,20 @@ interpolate_alpha(long long now, long long t1, long long t2, long long t3,
* Parse a vector clip into an outline, using the proper scaling
* parameters. Translate it to correct for screen borders, if needed.
*/
-static int parse_vector_clip(ASS_Renderer *render_priv,
- struct arg *args, int nargs)
+static bool parse_vector_clip(ASS_Renderer *render_priv,
+ struct arg *args, int nargs)
{
- int scale = 1;
- ASS_Drawing *drawing = render_priv->state.clip_drawing;
-
if (nargs != 1 && nargs != 2)
- return 0;
+ return false;
+
+ int scale = 1;
if (nargs == 2)
scale = argtoi(args[0]);
- struct arg text = args[nargs - 1];
-
- ass_drawing_free(drawing);
- render_priv->state.clip_drawing = ass_drawing_new(render_priv->library);
- drawing = render_priv->state.clip_drawing;
- if (drawing) {
- drawing->scale = scale;
- drawing->scale_x = render_priv->font_scale_x * render_priv->font_scale;
- drawing->scale_y = render_priv->font_scale;
- ass_drawing_set_text(drawing, text.start, text.end - text.start);
- }
- return 1;
+ struct arg text = args[nargs - 1];
+ render_priv->state.clip_drawing_text = strndup(text.start, text.end - text.start);
+ render_priv->state.clip_drawing_scale = scale;
+ return true;
}
/**
@@ -361,7 +352,7 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
render_priv->state.clip_y1 =
render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr;
render_priv->state.clip_mode = 1;
- } else if (!render_priv->state.clip_drawing) {
+ } else if (!render_priv->state.clip_drawing_text) {
if (parse_vector_clip(render_priv, args, nargs))
render_priv->state.clip_drawing_mode = 1;
}
@@ -682,7 +673,7 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
render_priv->state.clip_y1 =
render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr;
render_priv->state.clip_mode = 0;
- } else if (!render_priv->state.clip_drawing) {
+ } else if (!render_priv->state.clip_drawing_text) {
if (parse_vector_clip(render_priv, args, nargs))
render_priv->state.clip_drawing_mode = 0;
}
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 5648aff..128a0dc 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -456,15 +456,14 @@ static inline size_t bitmap_size(Bitmap *bm)
static void blend_vector_clip(ASS_Renderer *render_priv,
ASS_Image *head)
{
- ASS_Drawing *drawing = render_priv->state.clip_drawing;
- if (!drawing)
+ if (!render_priv->state.clip_drawing_text)
return;
// Try to get mask from cache
BitmapHashKey key;
memset(&key, 0, sizeof(key));
key.type = BITMAP_CLIP;
- key.u.clip.text = drawing->text;
+ key.u.clip.text = render_priv->state.clip_drawing_text;
BitmapHashValue *val;
if (!ass_cache_get(render_priv->cache.bitmap_cache, &key, &val)) {
@@ -473,8 +472,13 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
val->bm = val->bm_o = NULL;
// Not found in cache, parse and rasterize it
- ASS_Outline *outline = ass_drawing_parse(drawing, true);
- if (!outline) {
+ ASS_Drawing drawing;
+ drawing.text = render_priv->state.clip_drawing_text;
+ drawing.scale = render_priv->state.clip_drawing_scale;
+ drawing.pbo = 0;
+ drawing.scale_x = render_priv->font_scale_x * render_priv->font_scale;
+ drawing.scale_y = render_priv->font_scale;
+ if (!ass_drawing_parse(&drawing, render_priv->library, true)) {
ass_msg(render_priv->library, MSGL_WARN,
"Clip vector parsing failed. Skipping.");
ass_cache_commit(val, sizeof(BitmapHashKey) + sizeof(BitmapHashValue));
@@ -489,12 +493,13 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
.x = int_to_d6(render_priv->settings.left_margin),
.y = int_to_d6(render_priv->settings.top_margin),
};
- outline_translate(outline, trans.x, trans.y);
+ outline_translate(&drawing.outline, trans.x, trans.y);
}
- val->bm = outline_to_bitmap(render_priv, outline, NULL, 1);
+ val->bm = outline_to_bitmap(render_priv, &drawing.outline, NULL, 1);
ass_cache_commit(val, bitmap_size(val->bm) +
sizeof(BitmapHashKey) + sizeof(BitmapHashValue));
+ outline_free(&drawing.outline);
}
Bitmap *clip_bm = val->bm;
@@ -896,15 +901,15 @@ static void free_render_context(ASS_Renderer *render_priv)
{
ass_cache_dec_ref(render_priv->state.font);
free(render_priv->state.family);
- ass_drawing_free(render_priv->state.clip_drawing);
+ free(render_priv->state.clip_drawing_text);
render_priv->state.font = NULL;
render_priv->state.family = NULL;
- render_priv->state.clip_drawing = NULL;
+ render_priv->state.clip_drawing_text = NULL;
TextInfo *text_info = &render_priv->text_info;
for (int n = 0; n < text_info->length; n++)
- ass_drawing_free(text_info->glyphs[n].drawing);
+ free(text_info->glyphs[n].drawing_text);
text_info->length = 0;
}
@@ -962,7 +967,7 @@ static void
fill_glyph_hash(ASS_Renderer *priv, OutlineHashKey *outline_key,
GlyphInfo *info)
{
- if (info->drawing) {
+ if (info->drawing_text) {
DrawingHashKey *key = &outline_key->u.drawing;
outline_key->type = OUTLINE_DRAWING;
key->scale_x = double_to_d16(info->scale_x);
@@ -974,9 +979,9 @@ fill_glyph_hash(ASS_Renderer *priv, OutlineHashKey *outline_key,
// so for normal borders, maximize cache utility by ignoring it
key->hspacing =
info->border_style == 3 ? double_to_d16(info->hspacing) : 0;
- key->text = info->drawing->text;
- key->pbo = info->drawing->pbo;
- key->scale = info->drawing->scale;
+ key->text = info->drawing_text;
+ key->pbo = info->drawing_pbo;
+ key->scale = info->drawing_scale;
} else {
GlyphHashKey *key = &outline_key->u.glyph;
outline_key->type = OUTLINE_GLYPH;
@@ -1028,17 +1033,22 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
return;
memset(val, 0, sizeof(*val));
- if (info->drawing) {
- ASS_Drawing *drawing = info->drawing;
- if(!ass_drawing_parse(drawing, false) ||
- !outline_copy(&val->outline, &drawing->outline)) {
+ if (info->drawing_text) {
+ ASS_Drawing drawing;
+ drawing.text = info->drawing_text;
+ drawing.scale = info->drawing_scale;
+ drawing.pbo = info->drawing_pbo;
+ drawing.scale_x = info->scale_x * priv->font_scale;
+ drawing.scale_y = info->scale_y * priv->font_scale;
+ if (!ass_drawing_parse(&drawing, priv->library, false)) {
ass_cache_commit(val, 1);
ass_cache_dec_ref(val);
return;
}
- val->advance = drawing->advance;
- val->asc = drawing->asc;
- val->desc = drawing->desc;
+ outline_move(&val->outline, &drawing.outline);
+ val->advance = drawing.advance;
+ val->asc = drawing.asc;
+ val->desc = drawing.desc;
} else {
ass_face_set_size(info->font->faces[info->face_index],
info->font_size);
@@ -1069,7 +1079,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
if (info->border_style == 3) {
int advance;
- if (priv->settings.shaper == ASS_SHAPING_SIMPLE || info->drawing)
+ if (priv->settings.shaper == ASS_SHAPING_SIMPLE || info->drawing_text)
advance = val->advance;
else
advance = info->advance.x;
@@ -1107,7 +1117,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
info->border[0] = &val->border[0];
info->border[1] = &val->border[1];
info->bbox = val->bbox_scaled;
- if (info->drawing || priv->settings.shaper == ASS_SHAPING_SIMPLE) {
+ if (info->drawing_text || priv->settings.shaper == ASS_SHAPING_SIMPLE) {
info->cluster_advance.x = info->advance.x = val->advance;
info->cluster_advance.y = info->advance.y = 0;
}
@@ -1623,7 +1633,7 @@ fix_glyph_scaling(ASS_Renderer *priv, GlyphInfo *glyph)
static int is_new_bm_run(GlyphInfo *info, GlyphInfo *last)
{
// FIXME: Don't break on glyph substitutions
- return !last || info->effect || info->drawing || last->drawing ||
+ return !last || info->effect || info->drawing_text || last->drawing_text ||
strcmp(last->font->desc.family, info->font->desc.family) ||
last->font->desc.vertical != info->font->desc.vertical ||
last->face_index != info->face_index ||
@@ -1691,18 +1701,15 @@ static void make_shadow_bitmap(CombinedBitmapInfo *info, ASS_Renderer *render_pr
static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
{
TextInfo *text_info = &render_priv->text_info;
- ASS_Drawing *drawing = NULL;
- unsigned code;
- char *p, *q;
- int i;
- p = event->Text;
+ char *p = event->Text, *q;
// Event parsing.
while (1) {
// get next char, executing style override
// this affects render_context
- code = 0;
+ unsigned code = 0;
+ char *drawing_text = NULL;
while (*p) {
if ((*p == '{') && (q = strchr(p, '}'))) {
p = parse_tags(render_priv, p, q, 1., false);
@@ -1714,12 +1721,7 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
q++;
while ((*q != '{') && (*q != 0))
q++;
- if (!drawing) {
- drawing = ass_drawing_new(render_priv->library);
- if (!drawing)
- return 1;
- }
- ass_drawing_set_text(drawing, p, q - p);
+ drawing_text = strndup(p, q - p);
code = 0xfffc; // object replacement character
p = q;
break;
@@ -1735,7 +1737,7 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
// face could have been changed in get_next_char
if (!render_priv->state.font) {
free_render_context(render_priv);
- ass_drawing_free(drawing);
+ free(drawing_text);
return 1;
}
@@ -1753,23 +1755,18 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
memset(info, 0, sizeof(GlyphInfo));
// Parse drawing
- if (drawing && drawing->text) {
- drawing->scale_x = render_priv->state.scale_x *
- render_priv->font_scale;
- drawing->scale_y = render_priv->state.scale_y *
- render_priv->font_scale;
- drawing->scale = render_priv->state.drawing_scale;
- drawing->pbo = render_priv->state.pbo;
- info->drawing = drawing;
- drawing = NULL;
+ if (drawing_text) {
+ info->drawing_text = drawing_text;
+ info->drawing_scale = render_priv->state.drawing_scale;
+ info->drawing_pbo = render_priv->state.pbo;
}
// Fill glyph information
info->symbol = code;
info->font = render_priv->state.font;
- if (!info->drawing)
+ if (!drawing_text)
ass_cache_inc_ref(info->font);
- for (i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; i++) {
uint32_t clr = render_priv->state.c[i];
// VSFilter compatibility: apply fade only when it's positive
if (render_priv->state.fade > 0)
@@ -1802,7 +1799,7 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
info->fax = render_priv->state.fax;
info->fay = render_priv->state.fay;
- if (!info->drawing)
+ if (!drawing_text)
fix_glyph_scaling(render_priv, info);
text_info->length++;
@@ -1812,8 +1809,6 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
render_priv->state.effect_skip_timing = 0;
}
- ass_drawing_free(drawing);
-
return 0;
}
diff --git a/libass/ass_render.h b/libass/ass_render.h
index c8132fc..f2af0b7 100644
--- a/libass/ass_render.h
+++ b/libass/ass_render.h
@@ -130,7 +130,9 @@ typedef struct glyph_info {
int script;
#endif
double font_size;
- ASS_Drawing *drawing;
+ char *drawing_text;
+ int drawing_scale;
+ int drawing_pbo;
ASS_Outline *outline;
ASS_Outline *border[2];
ASS_Rect bbox;
@@ -229,7 +231,8 @@ typedef struct {
double shadow_y;
int drawing_scale; // currently reading: regular text if 0, drawing otherwise
double pbo; // drawing baseline offset
- ASS_Drawing *clip_drawing; // clip vector
+ char *clip_drawing_text;
+ int clip_drawing_scale;
int clip_drawing_mode; // 0 = regular clip, 1 = inverse clip
Effect effect_type;