[FFmpeg-devel] [PATCH 2/2] vf_drawtext: fontconfig support.
Nicolas George
nicolas.george at normalesup.org
Sat Apr 7 16:46:49 CEST 2012
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
configure | 3 +
doc/filters.texi | 9 ++++
libavfilter/vf_drawtext.c | 104 +++++++++++++++++++++++++++++++++++++++++---
3 files changed, 108 insertions(+), 8 deletions(-)
diff --git a/configure b/configure
index 049708a..b4414d0 100755
--- a/configure
+++ b/configure
@@ -166,6 +166,7 @@ Individual component options:
External library support:
--enable-avisynth enable reading of AVISynth script files [no]
--enable-bzlib enable bzlib [autodetect]
+ --enable-fontconfig enable fontconfig
--enable-frei0r enable frei0r video filtering
--enable-gnutls enable gnutls [no]
--enable-libaacplus enable AAC+ encoding via libaacplus [no]
@@ -1022,6 +1023,7 @@ CONFIG_LIST="
dxva2
fastdiv
fft
+ fontconfig
frei0r
gnutls
gpl
@@ -3164,6 +3166,7 @@ check_mathfunc truncf
# these are off by default, so fail if requested and not available
enabled avisynth && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32
+enabled fontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit
enabled frei0r && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; }
enabled gnutls && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
enabled libaacplus && require "libaacplus >= 2.0.0" aacplus.h aacplusEncOpen -laacplus
diff --git a/doc/filters.texi b/doc/filters.texi
index 5d19fed..72a3e2b 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1414,6 +1414,9 @@ with or without text parameter. @var{rate} option must be specified.
frame rate (timecode only)
@end table
+If libavfilter was built with @code{--enable-fontconfig}, then
+ at option{fontfile} can be a fontconfig pattern or omitted.
+
Some examples follow.
@itemize
@@ -1467,6 +1470,12 @@ The glyph baseline is placed at half screen height.
drawtext=fontsize=60:fontfile=FreeSerif.ttf:fontcolor=green:text=g:x=(w-max_glyph_w)/2:y=h/2-ascent
@end example
+ at item
+Use fontconfig to set the font. Note that the colons need to be escaped.
+ at example
+drawtext='fontfile=Linux Libertine O-40\\:style=Semibold:text=FFmpeg'
+ at end example
+
@end itemize
For more information about libfreetype, check:
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index 43b04e0..ba8b585 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -48,6 +48,9 @@
#include <freetype/config/ftheader.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
+#if CONFIG_FONTCONFIG
+#include <fontconfig/fontconfig.h>
+#endif
static const char *const var_names[] = {
"main_w", "w", "W", ///< width of the input video
@@ -167,7 +170,7 @@ static const AVOption drawtext_options[]= {
{"boxcolor", "set box color", OFFSET(boxcolor_string), AV_OPT_TYPE_STRING, {.str="white"}, CHAR_MIN, CHAR_MAX },
{"shadowcolor", "set shadow color", OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX },
{"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
-{"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.dbl=16}, 1, INT_MAX },
+{"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.dbl=0}, 0, INT_MAX },
{"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX },
{"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX },
{"shadowx", "set x", OFFSET(shadowx), AV_OPT_TYPE_INT, {.dbl=0}, INT_MIN, INT_MAX },
@@ -298,6 +301,91 @@ error:
return ret;
}
+static int load_font_file(AVFilterContext *ctx, const char *path, int index,
+ const char **error)
+{
+ DrawTextContext *dtext = ctx->priv;
+ int err;
+
+ err = FT_New_Face(dtext->library, path, index, &dtext->face);
+ if (err) {
+ *error = FT_ERRMSG(err);
+ return AVERROR(EINVAL);
+ }
+ return 0;
+}
+
+#if CONFIG_FONTCONFIG
+static int load_font_fontconfig(AVFilterContext *ctx, const char **error)
+{
+ DrawTextContext *dtext = ctx->priv;
+ FcConfig *fontconfig;
+ FcPattern *pattern, *fpat;
+ FcResult result = FcResultMatch;
+ FcChar8 *filename;
+ int err, index;
+ double size;
+
+ fontconfig = FcInitLoadConfigAndFonts();
+ if (!fontconfig) {
+ *error = "impossible to init fontconfig.\n";
+ return AVERROR(EINVAL);
+ }
+ pattern = FcNameParse(dtext->fontfile ? dtext->fontfile :
+ (uint8_t *)(intptr_t)"default");
+ if (!pattern) {
+ *error = "error parsing fontconfig pattern";
+ return AVERROR(EINVAL);
+ }
+ if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) {
+ *error = "error substuting fontconfig options"; /* very unlikely */
+ return AVERROR(EINVAL);
+ }
+ FcDefaultSubstitute(pattern);
+ fpat = FcFontMatch(fontconfig, pattern, &result);
+ if (!fpat || result != FcResultMatch) {
+ *error = "impossible to find a matching font";
+ return AVERROR(EINVAL);
+ }
+ if (FcPatternGetString(fpat, FC_FILE, 0, &filename) != FcResultMatch ||
+ FcPatternGetInteger(fpat, FC_INDEX, 0, &index) != FcResultMatch ||
+ FcPatternGetDouble(fpat, FC_SIZE, 0, &size) != FcResultMatch) {
+ *error = "impossible to find font information";
+ return AVERROR(EINVAL);
+ }
+ av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
+ if (!dtext->fontsize)
+ dtext->fontsize = size + 0.5;
+ err = load_font_file(ctx, filename, index, error);
+ if (err)
+ return err;
+ FcPatternDestroy(fpat);
+ FcPatternDestroy(pattern);
+ FcConfigDestroy(fontconfig);
+ return 0;
+}
+#endif
+
+static int load_font(AVFilterContext *ctx)
+{
+ DrawTextContext *dtext = ctx->priv;
+ int err;
+ const char *error = "Unknown error\n";
+
+ /* load the face, and set up the encoding, which is by default UTF-8 */
+ err = load_font_file(ctx, dtext->fontfile, 0, &error);
+ if (!err)
+ return 0;
+#if CONFIG_FONTCONFIG
+ err = load_font_fontconfig(ctx, &error);
+ if (!err)
+ return 0;
+#endif
+ av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
+ dtext->fontfile, error);
+ return err;
+}
+
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
{
int err;
@@ -312,7 +400,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return err;
}
- if (!dtext->fontfile) {
+ if (!dtext->fontfile && !CONFIG_FONTCONFIG) {
av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
return AVERROR(EINVAL);
}
@@ -381,17 +469,17 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return AVERROR(EINVAL);
}
- /* load the face, and set up the encoding, which is by default UTF-8 */
- if ((err = FT_New_Face(dtext->library, dtext->fontfile, 0, &dtext->face))) {
- av_log(ctx, AV_LOG_ERROR, "Could not load fontface from file '%s': %s\n",
- dtext->fontfile, FT_ERRMSG(err));
- return AVERROR(EINVAL);
- }
+ err = load_font(ctx);
+ if (err)
+ return err;
+ if (!dtext->fontsize)
+ dtext->fontsize = 16;
if ((err = FT_Set_Pixel_Sizes(dtext->face, 0, dtext->fontsize))) {
av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
dtext->fontsize, FT_ERRMSG(err));
return AVERROR(EINVAL);
}
+ return 0;
dtext->use_kerning = FT_HAS_KERNING(dtext->face);
--
1.7.9.1
More information about the ffmpeg-devel
mailing list