vf_drawtext: fontconfig support.

This commit is contained in:
Nicolas George 2012-04-07 15:09:16 +02:00
parent be9b0d2c5a
commit 40b7a27bad
4 changed files with 111 additions and 8 deletions

View File

@ -23,6 +23,7 @@ version next:
- OpenEXR image decoder
- removelogo filter
- drop support for ffmpeg without libavfilter
- drawtext video filter: fontconfig support
version 0.10:

3
configure vendored
View File

@ -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

View File

@ -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
@option{fontfile} can be a fontconfig pattern or omitted.
Some examples follow.
@itemize
@ -1467,11 +1470,20 @@ 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
@item
Use fontconfig to set the font. Note that the colons need to be escaped.
@example
drawtext='fontfile=Linux Libertine O-40\\:style=Semibold:text=FFmpeg'
@end example
@end itemize
For more information about libfreetype, check:
@url{http://www.freetype.org/}.
For more information about fontconfig, check:
@url{http://freedesktop.org/software/fontconfig/fontconfig-user.html}.
@section fade
Apply fade-in/out effect to input video.

View File

@ -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 = "could not parse fontconfig pattern";
return AVERROR(EINVAL);
}
if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) {
*error = "could not substitue 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,12 +469,11 @@ 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));