1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-21 10:55:51 +02:00

drawtext: refactor draw_text

Split the memory allocation from the actual drawing.
This commit is contained in:
Luca Barbato 2011-12-01 11:14:54 +01:00
parent 84994421bc
commit a2fb4bcb01

View File

@ -55,8 +55,8 @@ typedef struct {
FT_Vector *positions; ///< positions for each element in the text
size_t nb_positions; ///< number of elements of positions array
char *textfile; ///< file with text to be drawn
unsigned int x; ///< x position to start drawing text
unsigned int y; ///< y position to start drawing text
int x, y; ///< position to start drawing text
int w, h; ///< dimension of the text block
int shadowx, shadowy;
unsigned int fontsize; ///< font size to use
char *fontcolor_string; ///< font color as string
@ -542,8 +542,7 @@ static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
return 0;
}
static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
int width, int height)
static int dtext_prepare_text(AVFilterContext *ctx, int width, int height)
{
DrawTextContext *dtext = ctx->priv;
uint32_t code = 0, prev_code = 0;
@ -582,15 +581,19 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
text = dtext->expanded_text = buf;
dtext->expanded_text_size = buf_size;
#endif
if ((len = strlen(text)) > dtext->nb_positions) {
if (!(dtext->positions =
av_realloc(dtext->positions, len*sizeof(*dtext->positions))))
return AVERROR(ENOMEM);
dtext->nb_positions = len;
}
x = dtext->x;
y = dtext->y;
if ((len = strlen(text)) > dtext->nb_positions) {
FT_Vector *p = av_realloc(dtext->positions,
len * sizeof(*dtext->positions));
if (!p) {
av_freep(dtext->positions);
dtext->nb_positions = 0;
return AVERROR(ENOMEM);
} else {
dtext->positions = p;
dtext->nb_positions = len;
}
}
/* load and cache glyphs */
for (i = 0, p = text; *p; i++) {
@ -600,7 +603,8 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
dummy.code = code;
glyph = av_tree_find(dtext->glyphs, &dummy, glyph_cmp, NULL);
if (!glyph)
load_glyph(ctx, &glyph, code);
ret = load_glyph(ctx, &glyph, code);
if (ret) return ret;
y_min = FFMIN(glyph->bbox.yMin, y_min);
y_max = FFMAX(glyph->bbox.yMax, y_max);
@ -621,7 +625,7 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
if (is_newline(code)) {
str_w = FFMAX(str_w, x - dtext->x);
y += text_height;
x = dtext->x;
x = 0;
continue;
}
@ -638,9 +642,9 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
}
if (x + glyph->bbox.xMax >= width) {
str_w = FFMAX(str_w, x - dtext->x);
str_w = FFMAX(str_w, x);
y += text_height;
x = dtext->x;
x = 0;
}
/* save position */
@ -650,23 +654,43 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
else x += glyph->advance;
}
str_w = FFMIN(width - dtext->x - 1, FFMAX(str_w, x - dtext->x));
str_w = FFMIN(width - 1, FFMAX(str_w, x));
y = FFMIN(y + text_height, height - 1);
dtext->w = str_w;
dtext->h = y;
return 0;
}
static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
int width, int height)
{
DrawTextContext *dtext = ctx->priv;
int ret;
/* draw box */
if (dtext->draw_box)
drawbox(picref, dtext->x, dtext->y, str_w, y-dtext->y,
drawbox(picref, dtext->x, dtext->y, dtext->w, dtext->h,
dtext->box_line, dtext->pixel_step, dtext->boxcolor,
dtext->hsub, dtext->vsub, dtext->is_packed_rgb, dtext->rgba_map);
dtext->hsub, dtext->vsub, dtext->is_packed_rgb,
dtext->rgba_map);
if (dtext->shadowx || dtext->shadowy) {
if ((ret = draw_glyphs(dtext, picref, width, height, dtext->shadowcolor_rgba,
dtext->shadowcolor, dtext->shadowx, dtext->shadowy)) < 0)
if ((ret = draw_glyphs(dtext, picref, width, height,
dtext->shadowcolor_rgba,
dtext->shadowcolor,
dtext->x + dtext->shadowx,
dtext->y + dtext->shadowy)) < 0)
return ret;
}
if ((ret = draw_glyphs(dtext, picref, width, height, dtext->fontcolor_rgba,
dtext->fontcolor, 0, 0)) < 0)
if ((ret = draw_glyphs(dtext, picref, width, height,
dtext->fontcolor_rgba,
dtext->fontcolor,
dtext->x,
dtext->y)) < 0)
return ret;
return 0;
@ -679,6 +703,7 @@ static void end_frame(AVFilterLink *inlink)
AVFilterLink *outlink = inlink->dst->outputs[0];
AVFilterBufferRef *picref = inlink->cur_buf;
dtext_prepare_text(inlink->dst, picref->video->w, picref->video->h);
draw_text(inlink->dst, picref, picref->video->w, picref->video->h);
avfilter_draw_slice(outlink, 0, picref->video->h, 1);