[FFmpeg-devel] [PATCH 2/2] lavfi/drawtext: add option for drawing border around text
Stefano Sabatini
stefasab at gmail.com
Fri Jan 10 09:46:20 CET 2014
On date Friday 2014-01-10 04:36:36 -0200, Ramiro Polla encoded:
>
> From 56ca123357def67b281a28143a9faa52ecad603b Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 10 Jan 2014 04:30:09 -0200
> Subject: [PATCH 2/2] lavfi/drawtext: add option for drawing border around
> text
>
> ---
> doc/filters.texi | 10 +++++++++
> libavfilter/vf_drawtext.c | 50 +++++++++++++++++++++++++++++++++++++++------
> 2 files changed, 54 insertions(+), 6 deletions(-)
Reminder: missing micro bump
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index c896edb..f32a969 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -3548,6 +3548,16 @@ option, check the "Color" section in the ffmpeg-utils manual.
>
> The default value of @var{boxcolor} is "white".
>
> + at item borderw
> +The width of the border to be drawn around the text using @var{bordercolor}.
> +The default value of @var{borderw} is 0.
Set the width ...
> + at item bordercolor
> +The color to be used for drawing border around text. For the syntax of this
> +option, check the "Color" section in the ffmpeg-utils manual.
Set the color ...
(the other options should be fixed as well).
> +
> +The default value of @var{bordercolor} is "black".
> +
> @item expansion
> Select how the @var{text} is expanded. Can be either @code{none},
> @code{strftime} (deprecated) or
> diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
> index 2dd95ce..7e92dd6 100644
> --- a/libavfilter/vf_drawtext.c
> +++ b/libavfilter/vf_drawtext.c
> @@ -50,6 +50,7 @@
> #include <ft2build.h>
> #include FT_FREETYPE_H
> #include FT_GLYPH_H
> +#include FT_STROKER_H
> #if CONFIG_FONTCONFIG
> #include <fontconfig/fontconfig.h>
> #endif
> @@ -134,6 +135,7 @@ typedef struct {
> int max_glyph_w; ///< max glyph width
> int max_glyph_h; ///< max glyph height
> int shadowx, shadowy;
> + int borderw; ///< border width
> unsigned int fontsize; ///< font size to use
>
> short int draw_box; ///< draw box around text - true or false
> @@ -144,10 +146,12 @@ typedef struct {
> FFDrawContext dc;
> FFDrawColor fontcolor; ///< foreground color
> FFDrawColor shadowcolor; ///< shadow color
> + FFDrawColor bordercolor; ///< border color
> FFDrawColor boxcolor; ///< background color
>
> FT_Library library; ///< freetype font library handle
> FT_Face face; ///< freetype font face handle
> + FT_Stroker stroker; ///< freetype stroker handle
> struct AVTreeNode *glyphs; ///< rendered glyphs, stored using the UTF-32 char code
> char *x_expr; ///< expression for x position
> char *y_expr; ///< expression for y position
> @@ -179,12 +183,14 @@ static const AVOption drawtext_options[]= {
> {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
> + {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_INT, {.i64=0}, 0, 1 , FLAGS},
> {"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX , FLAGS},
> {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"shadowx", "set x", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
> {"shadowy", "set y", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
> + {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
> {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX , FLAGS},
> {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX , FLAGS},
> #if FF_API_DRAWTEXT_OLD_TIMELINE
> @@ -245,6 +251,7 @@ typedef struct {
> FT_Glyph *glyph;
> uint32_t code;
> FT_Bitmap bitmap; ///< array holding bitmaps of font
> + FT_Bitmap border_bitmap; ///< array holding bitmaps of font border
> FT_BBox bbox;
> int advance;
> int bitmap_left;
> @@ -285,6 +292,13 @@ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
> ret = AVERROR(EINVAL);
> goto error;
> }
> + if (s->borderw) {
> + FT_Glyph border_glyph = *glyph->glyph;
> + FT_Glyph_StrokeBorder(&border_glyph, s->stroker, 0, 0);
> + FT_Glyph_To_Bitmap(&border_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
> + bitmapglyph = (FT_BitmapGlyph) border_glyph;
> + glyph->border_bitmap = bitmapglyph->bitmap;
> + }
Probably you want to add some error checks.
> if (FT_Glyph_To_Bitmap(glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
> ret = AVERROR(EINVAL);
> goto error;
> @@ -490,6 +504,16 @@ static av_cold int init(AVFilterContext *ctx)
> return AVERROR(EINVAL);
> }
>
> + if (s->borderw) {
> + err = FT_Stroker_New(s->library, &s->stroker);
> + if (err) {
> + av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n");
> + return AVERROR(EINVAL);
AVERROR_EXTERNAL
> + }
> + FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
> + FT_STROKER_LINEJOIN_ROUND, 0);
> + }
> +
> s->use_kerning = FT_HAS_KERNING(s->face);
>
> /* load the fallback glyph with code 0 */
> @@ -546,6 +570,7 @@ static av_cold void uninit(AVFilterContext *ctx)
> s->glyphs = NULL;
>
> FT_Done_Face(s->face);
> + FT_Stroker_Done(s->stroker);
> FT_Done_FreeType(s->library);
>
> av_bprint_finalize(&s->expanded_text, NULL);
> @@ -565,6 +590,7 @@ static int config_input(AVFilterLink *inlink)
> ff_draw_init(&s->dc, inlink->format, 0);
> ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
> ff_draw_color(&s->dc, &s->shadowcolor, s->shadowcolor.rgba);
> + ff_draw_color(&s->dc, &s->bordercolor, s->bordercolor.rgba);
> ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba);
>
> s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w;
> @@ -812,7 +838,8 @@ static int expand_text(AVFilterContext *ctx)
> }
>
> static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
> - int width, int height, const uint8_t rgbcolor[4], FFDrawColor *color, int x, int y)
> + int width, int height, const uint8_t rgbcolor[4],
> + FFDrawColor *color, int x, int y, int border)
> {
> char *text = s->expanded_text.str;
> uint32_t code = 0;
> @@ -821,6 +848,7 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
> Glyph *glyph = NULL;
>
> for (i = 0, p = text; *p; i++) {
> + FT_Bitmap bitmap;
> Glyph dummy = { 0 };
> GET_UTF8(code, *p++, continue;);
>
> @@ -831,6 +859,11 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
> dummy.code = code;
> glyph = av_tree_find(s->glyphs, &dummy, (void *)glyph_cmp, NULL);
>
> + if (border)
> + bitmap = glyph->border_bitmap;
> + else
> + bitmap = glyph->bitmap;
nit++: bitmap = border ? ...;
[...]
Should be fine otherwise if works as expected.
--
FFmpeg = Forgiving & Fancy Mastodontic Peaceful Eccentric Ghost
More information about the ffmpeg-devel
mailing list