Commit 443261cb authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit 'f1b239ec'

* commit 'f1b239ec':
  drawtext: Add fontconfig support

Conflicts:
	configure
	doc/filters.texi
	libavfilter/vf_drawtext.c

See: 40b7a27bMerged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents c150e2cf f1b239ec
...@@ -1304,7 +1304,6 @@ EXTERNAL_LIBRARY_LIST=" ...@@ -1304,7 +1304,6 @@ EXTERNAL_LIBRARY_LIST="
bzlib bzlib
crystalhd crystalhd
decklink decklink
fontconfig
frei0r frei0r
gnutls gnutls
iconv iconv
...@@ -1319,6 +1318,7 @@ EXTERNAL_LIBRARY_LIST=" ...@@ -1319,6 +1318,7 @@ EXTERNAL_LIBRARY_LIST="
libfaac libfaac
libfdk_aac libfdk_aac
libflite libflite
libfontconfig
libfreetype libfreetype
libgme libgme
libgsm libgsm
...@@ -1445,6 +1445,7 @@ CONFIG_LIST=" ...@@ -1445,6 +1445,7 @@ CONFIG_LIST="
$LIBRARY_LIST $LIBRARY_LIST
$PROGRAM_LIST $PROGRAM_LIST
$SUBSYSTEM_LIST $SUBSYSTEM_LIST
fontconfig
incompatible_libav_abi incompatible_libav_abi
incompatible_fork_abi incompatible_fork_abi
memalign_hack memalign_hack
...@@ -4587,7 +4588,6 @@ enabled avisynth && { { check_lib2 "windows.h" LoadLibrary; } || ...@@ -4587,7 +4588,6 @@ enabled avisynth && { { check_lib2 "windows.h" LoadLibrary; } ||
{ check_lib2 "dlfcn.h" dlopen -ldl; } || { check_lib2 "dlfcn.h" dlopen -ldl; } ||
die "ERROR: LoadLibrary/dlopen not found for avisynth"; } die "ERROR: LoadLibrary/dlopen not found for avisynth"; }
enabled decklink && { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; } enabled decklink && { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; }
enabled fontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit
enabled frei0r && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; } 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 gnutls && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
enabled ladspa && { check_header ladspa.h || die "ERROR: ladspa.h header not found"; } enabled ladspa && { check_header ladspa.h || die "ERROR: ladspa.h header not found"; }
...@@ -4603,6 +4603,8 @@ enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersio ...@@ -4603,6 +4603,8 @@ enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersio
enabled libfdk_aac && require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac enabled libfdk_aac && require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac
flite_libs="-lflite_cmu_time_awb -lflite_cmu_us_awb -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_cmu_us_rms -lflite_cmu_us_slt -lflite_usenglish -lflite_cmulex -lflite" flite_libs="-lflite_cmu_time_awb -lflite_cmu_us_awb -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_cmu_us_rms -lflite_cmu_us_slt -lflite_usenglish -lflite_cmulex -lflite"
enabled libflite && require2 libflite "flite/flite.h" flite_init $flite_libs enabled libflite && require2 libflite "flite/flite.h" flite_init $flite_libs
enabled fontconfig && enable libfontconfig
enabled libfontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit
enabled libfreetype && require_libfreetype enabled libfreetype && require_libfreetype
enabled libgme && require libgme gme/gme.h gme_new_emu -lgme -lstdc++ enabled libgme && require libgme gme/gme.h gme_new_emu -lgme -lstdc++
enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do
......
...@@ -3580,6 +3580,8 @@ libfreetype library. ...@@ -3580,6 +3580,8 @@ libfreetype library.
To enable compilation of this filter, you need to configure FFmpeg with To enable compilation of this filter, you need to configure FFmpeg with
@code{--enable-libfreetype}. @code{--enable-libfreetype}.
To enable default font fallback and the @var{font} option you need to
configure FFmpeg with @code{--enable-libfontconfig}.
@subsection Syntax @subsection Syntax
...@@ -3623,9 +3625,12 @@ the "Color" section in the ffmpeg-utils manual. ...@@ -3623,9 +3625,12 @@ the "Color" section in the ffmpeg-utils manual.
The default value of @var{fontcolor} is "black". The default value of @var{fontcolor} is "black".
@item font
The font family to be used for drawing text. By default Sans.
@item fontfile @item fontfile
The font file to be used for drawing text. The path must be included. 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 fontsize @item fontsize
The font size to be used for drawing text. The font size to be used for drawing text.
...@@ -3786,9 +3791,6 @@ These parameters allow the @var{x} and @var{y} expressions to refer ...@@ -3786,9 +3791,6 @@ These parameters allow the @var{x} and @var{y} expressions to refer
each other, so you can for example specify @code{y=x/dar}. each other, so you can for example specify @code{y=x/dar}.
@end table @end table
If libavfilter was built with @code{--enable-fontconfig}, then
@option{fontfile} can be a fontconfig pattern or omitted.
@anchor{drawtext_expansion} @anchor{drawtext_expansion}
@subsection Text expansion @subsection Text expansion
......
...@@ -27,10 +27,18 @@ ...@@ -27,10 +27,18 @@
*/ */
#include "config.h" #include "config.h"
#if HAVE_SYS_TIME_H #if HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#if CONFIG_LIBFONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavutil/bprint.h" #include "libavutil/bprint.h"
...@@ -53,9 +61,6 @@ ...@@ -53,9 +61,6 @@
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_GLYPH_H #include FT_GLYPH_H
#include FT_STROKER_H #include FT_STROKER_H
#if CONFIG_FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
static const char *const var_names[] = { static const char *const var_names[] = {
"dar", "dar",
...@@ -125,6 +130,9 @@ typedef struct { ...@@ -125,6 +130,9 @@ typedef struct {
const AVClass *class; const AVClass *class;
enum expansion_mode exp_mode; ///< expansion mode to use for the text enum expansion_mode exp_mode; ///< expansion mode to use for the text
int reinit; ///< tells if the filter is being reinited int reinit; ///< tells if the filter is being reinited
#if CONFIG_LIBFONTCONFIG
uint8_t *font; ///< font to be used
#endif
uint8_t *fontfile; ///< font to be used uint8_t *fontfile; ///< font to be used
uint8_t *text; ///< text to be drawn uint8_t *text; ///< text to be drawn
AVBPrint expanded_text; ///< used to contain the expanded text AVBPrint expanded_text; ///< used to contain the expanded text
...@@ -198,6 +206,9 @@ static const AVOption drawtext_options[]= { ...@@ -198,6 +206,9 @@ static const AVOption drawtext_options[]= {
#if FF_API_DRAWTEXT_OLD_TIMELINE #if FF_API_DRAWTEXT_OLD_TIMELINE
{"draw", "if false do not draw (deprecated)", OFFSET(draw_expr), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, {"draw", "if false do not draw (deprecated)", OFFSET(draw_expr), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
#endif #endif
#if CONFIG_LIBFONTCONFIG
{ "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS },
#endif
{"expansion", "set the expansion mode", OFFSET(exp_mode), AV_OPT_TYPE_INT, {.i64=EXP_NORMAL}, 0, 2, FLAGS, "expansion"}, {"expansion", "set the expansion mode", OFFSET(exp_mode), AV_OPT_TYPE_INT, {.i64=EXP_NORMAL}, 0, 2, FLAGS, "expansion"},
{"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"}, {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"},
...@@ -337,68 +348,90 @@ error: ...@@ -337,68 +348,90 @@ error:
return ret; return ret;
} }
static int load_font_file(AVFilterContext *ctx, const char *path, int index, static int load_font_file(AVFilterContext *ctx, const char *path, int index)
const char **error)
{ {
DrawTextContext *s = ctx->priv; DrawTextContext *s = ctx->priv;
int err; int err;
err = FT_New_Face(s->library, path, index, &s->face); err = FT_New_Face(s->library, path, index, &s->face);
if (err) { if (err) {
*error = FT_ERRMSG(err); av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
s->fontfile, FT_ERRMSG(err));
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
return 0; return 0;
} }
#if CONFIG_FONTCONFIG #if CONFIG_LIBFONTCONFIG
static int load_font_fontconfig(AVFilterContext *ctx, const char **error) static int load_font_fontconfig(AVFilterContext *ctx)
{ {
DrawTextContext *s = ctx->priv; DrawTextContext *s = ctx->priv;
FcConfig *fontconfig; FcConfig *fontconfig;
FcPattern *pattern, *fpat; FcPattern *pat, *best;
FcResult result = FcResultMatch; FcResult result = FcResultMatch;
FcChar8 *filename; FcChar8 *filename;
int err, index; int index;
double size; double size;
int err = AVERROR(ENOENT);
fontconfig = FcInitLoadConfigAndFonts(); fontconfig = FcInitLoadConfigAndFonts();
if (!fontconfig) { if (!fontconfig) {
*error = "impossible to init fontconfig\n"; av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n");
return AVERROR(EINVAL); return AVERROR_UNKNOWN;
} }
pattern = FcNameParse(s->fontfile ? s->fontfile : pat = FcNameParse(s->fontfile ? s->fontfile :
(uint8_t *)(intptr_t)"default"); (uint8_t *)(intptr_t)"default");
if (!pattern) { if (!pat) {
*error = "could not parse fontconfig pattern"; av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat");
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) {
*error = "could not substitue fontconfig options"; /* very unlikely */ FcPatternAddString(pat, FC_FAMILY, s->font);
return AVERROR(EINVAL); if (s->fontsize)
FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize);
FcDefaultSubstitute(pat);
if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */
FcPatternDestroy(pat);
return AVERROR(ENOMEM);
} }
FcDefaultSubstitute(pattern);
fpat = FcFontMatch(fontconfig, pattern, &result); best = FcFontMatch(fontconfig, pat, &result);
if (!fpat || result != FcResultMatch) { FcPatternDestroy(pat);
*error = "impossible to find a matching font";
return AVERROR(EINVAL); if (!best || result != FcResultMatch) {
av_log(ctx, AV_LOG_ERROR,
"Cannot find a valid font for the family %s\n",
s->font);
goto fail;
} }
if (FcPatternGetString (fpat, FC_FILE, 0, &filename) != FcResultMatch ||
FcPatternGetInteger(fpat, FC_INDEX, 0, &index ) != FcResultMatch || if (
FcPatternGetDouble (fpat, FC_SIZE, 0, &size ) != FcResultMatch) { FcPatternGetInteger(best, FC_INDEX, 0, &index ) != FcResultMatch ||
*error = "impossible to find font information"; FcPatternGetDouble (best, FC_SIZE, 0, &size ) != FcResultMatch) {
av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) {
av_log(ctx, AV_LOG_ERROR, "No file path for %s\n",
s->font);
goto fail;
}
av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename); av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
if (!s->fontsize) if (!s->fontsize)
s->fontsize = size + 0.5; s->fontsize = size + 0.5;
err = load_font_file(ctx, filename, index, error);
err = load_font_file(ctx, filename, index);
if (err) if (err)
return err; return err;
FcPatternDestroy(fpat);
FcPatternDestroy(pattern);
FcConfigDestroy(fontconfig); FcConfigDestroy(fontconfig);
return 0; fail:
FcPatternDestroy(best);
return err;
} }
#endif #endif
...@@ -406,19 +439,16 @@ static int load_font(AVFilterContext *ctx) ...@@ -406,19 +439,16 @@ static int load_font(AVFilterContext *ctx)
{ {
DrawTextContext *s = ctx->priv; DrawTextContext *s = ctx->priv;
int err; int err;
const char *error = "unknown error\n";
/* load the face, and set up the encoding, which is by default UTF-8 */ /* load the face, and set up the encoding, which is by default UTF-8 */
err = load_font_file(ctx, s->fontfile, 0, &error); err = load_font_file(ctx, s->fontfile, 0);
if (!err) if (!err)
return 0; return 0;
#if CONFIG_FONTCONFIG #if CONFIG_LIBFONTCONFIG
err = load_font_fontconfig(ctx, &error); err = load_font_fontconfig(ctx);
if (!err) if (!err)
return 0; return 0;
#endif #endif
av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
s->fontfile, error);
return err; return err;
} }
...@@ -457,7 +487,7 @@ static av_cold int init(AVFilterContext *ctx) ...@@ -457,7 +487,7 @@ static av_cold int init(AVFilterContext *ctx)
"you are encouraged to use the generic timeline support through the 'enable' option\n"); "you are encouraged to use the generic timeline support through the 'enable' option\n");
#endif #endif
if (!s->fontfile && !CONFIG_FONTCONFIG) { if (!s->fontfile && !CONFIG_LIBFONTCONFIG) {
av_log(ctx, AV_LOG_ERROR, "No font filename provided\n"); av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment