From f1b239ec8b38474d31f3bfea1f0b1693774fa432 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 12 Apr 2014 16:02:50 +0200 Subject: [PATCH] drawtext: Add fontconfig support Introduce the `font` option and make it optional to pass a fontfile. Signed-off-by: Luca Barbato --- configure | 2 + doc/filters.texi | 7 ++- libavfilter/vf_drawtext.c | 100 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 3c49d9c8b6..63a9e723bd 100755 --- a/configure +++ b/configure @@ -1128,6 +1128,7 @@ EXTERNAL_LIBRARY_LIST=" libdc1394 libfaac libfdk_aac + libfontconfig libfreetype libgsm libilbc @@ -4024,6 +4025,7 @@ enabled frei0r && { check_header frei0r.h || die "ERROR: frei0r.h hea enabled gnutls && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac enabled libfdk_aac && require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac +enabled libfontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do check_lib "${gsm_hdr}" gsm_create -lgsm && break; diff --git a/doc/filters.texi b/doc/filters.texi index 18531de295..d10a107b64 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1115,6 +1115,8 @@ libfreetype library. To enable compilation of this filter, you need to configure Libav with @code{--enable-libfreetype}. +To enable default font fallback and the @var{font} option you need to +configure Libav with @code{--enable-libfontconfig}. The filter also recognizes strftime() sequences in the provided text and expands them accordingly. Check the documentation of strftime(). @@ -1123,9 +1125,12 @@ It accepts the following parameters: @table @option +@item font +The font family to be used for drawing text. By default Sans. + @item fontfile The font file to be used for drawing text. The path must be included. -This parameter is mandatory. +This parameter is mandatory if the fontconfig support is disabled. @item text The text string to be drawn. The text must be a sequence of UTF-8 diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 314e0fc808..2338b03229 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -26,8 +26,17 @@ * filter by Gustavo Sverzut Barbieri */ +#include "config.h" + +#include #include +#include #include +#include + +#if CONFIG_LIBFONTCONFIG +#include +#endif #include "libavutil/colorspace.h" #include "libavutil/common.h" @@ -98,6 +107,9 @@ enum var_name { typedef struct { const AVClass *class; +#if CONFIG_LIBFONTCONFIG + uint8_t *font; ///< font to be used +#endif uint8_t *fontfile; ///< font to be used uint8_t *text; ///< text to be drawn uint8_t *expanded_text; ///< used to contain the strftime()-expanded text @@ -146,6 +158,9 @@ typedef struct { #define FLAGS AV_OPT_FLAG_VIDEO_PARAM static const AVOption drawtext_options[]= { +#if CONFIG_LIBFONTCONFIG + { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS }, +#endif { "fontfile", NULL, OFFSET(fontfile), AV_OPT_TYPE_STRING, .flags = FLAGS }, { "text", NULL, OFFSET(text), AV_OPT_TYPE_STRING, .flags = FLAGS }, { "textfile", NULL, OFFSET(textfile), AV_OPT_TYPE_STRING, .flags = FLAGS }, @@ -279,17 +294,94 @@ error: return ret; } -static av_cold int init(AVFilterContext *ctx) +static int parse_font(AVFilterContext *ctx) { - int err; DrawTextContext *s = ctx->priv; - Glyph *glyph; - +#if !CONFIG_LIBFONTCONFIG if (!s->fontfile) { av_log(ctx, AV_LOG_ERROR, "No font filename provided\n"); return AVERROR(EINVAL); } + return 0; +#else + FcPattern *pat, *best; + FcResult result = FcResultMatch; + + FcBool fc_bool; + FcChar8* fc_string; + int err = AVERROR(ENOENT); + + if (s->fontfile) + return 0; + + if (!FcInit()) + return AVERROR_UNKNOWN; + + if (!(pat = FcPatternCreate())) + return AVERROR(ENOMEM); + + FcPatternAddString(pat, FC_FAMILY, s->font); + FcPatternAddBool(pat, FC_OUTLINE, FcTrue); + FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize); + + FcDefaultSubstitute(pat); + + if (!FcConfigSubstitute(NULL, pat, FcMatchPattern)) { + FcPatternDestroy(pat); + return AVERROR(ENOMEM); + } + + best = FcFontMatch(NULL, pat, &result); + FcPatternDestroy(pat); + + if (!best || result == FcResultNoMatch) { + av_log(ctx, AV_LOG_ERROR, + "Cannot find a valid font for the family %s\n", + s->font); + goto fail; + } + + if (FcPatternGetBool(best, FC_OUTLINE, 0, &fc_bool) != FcResultMatch || + !fc_bool) { + av_log(ctx, AV_LOG_ERROR, "Outline not available for %s\n", + s->font); + goto fail; + } + + if (FcPatternGetString(best, FC_FAMILY, 0, &fc_string) != FcResultMatch) { + av_log(ctx, AV_LOG_ERROR, "No matches for %s\n", + s->font); + goto fail; + } + + if (FcPatternGetString(best, FC_FILE, 0, &fc_string) != FcResultMatch) { + av_log(ctx, AV_LOG_ERROR, "No file path for %s\n", + s->font); + goto fail; + } + + s->fontfile = av_strdup(fc_string); + if (!s->fontfile) + err = AVERROR(ENOMEM); + else + err = 0; + +fail: + FcPatternDestroy(best); + return err; +#endif +} + +static av_cold int init(AVFilterContext *ctx) +{ + int err; + DrawTextContext *s = ctx->priv; + Glyph *glyph; + + if ((err = parse_font(ctx)) < 0) + return err; + if (s->textfile) { uint8_t *textbuf; size_t textbuf_size;