Merge commit 'f1b239ec8b38474d31f3bfea1f0b1693774fa432'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 17 Apr 2014 01:42:17 +0000 (03:42 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 17 Apr 2014 03:15:26 +0000 (05:15 +0200)
* commit 'f1b239ec8b38474d31f3bfea1f0b1693774fa432':
  drawtext: Add fontconfig support

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

See: 40b7a27bad8b8b35cb215bf4f4cba02a00d6f9e2
Merged-by: Michael Niedermayer <michaelni@gmx.at>
configure
doc/filters.texi
libavfilter/vf_drawtext.c

index e7c2d10..a4d1c59 100755 (executable)
--- a/configure
+++ b/configure
@@ -1304,7 +1304,6 @@ EXTERNAL_LIBRARY_LIST="
     bzlib
     crystalhd
     decklink
-    fontconfig
     frei0r
     gnutls
     iconv
@@ -1319,6 +1318,7 @@ EXTERNAL_LIBRARY_LIST="
     libfaac
     libfdk_aac
     libflite
+    libfontconfig
     libfreetype
     libgme
     libgsm
@@ -1445,6 +1445,7 @@ CONFIG_LIST="
     $LIBRARY_LIST
     $PROGRAM_LIST
     $SUBSYSTEM_LIST
+    fontconfig
     incompatible_libav_abi
     incompatible_fork_abi
     memalign_hack
@@ -4587,7 +4588,6 @@ enabled avisynth          && { { check_lib2 "windows.h" LoadLibrary; } ||
                                { check_lib2 "dlfcn.h" dlopen -ldl; } ||
                                die "ERROR: LoadLibrary/dlopen not found for avisynth"; }
 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 gnutls            && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
 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
 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"
 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 libgme            && require  libgme gme/gme.h gme_new_emu -lgme -lstdc++
 enabled libgsm            && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do
index fdbe80d..e943923 100644 (file)
@@ -3580,6 +3580,8 @@ libfreetype library.
 
 To enable compilation of this filter, you need to configure FFmpeg with
 @code{--enable-libfreetype}.
+To enable default font fallback and the @var{font} option you need to
+configure FFmpeg with @code{--enable-libfontconfig}.
 
 @subsection Syntax
 
@@ -3623,9 +3625,12 @@ the "Color" section in the ffmpeg-utils manual.
 
 The default value of @var{fontcolor} is "black".
 
+@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 fontsize
 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
 each other, so you can for example specify @code{y=x/dar}.
 @end table
 
-If libavfilter was built with @code{--enable-fontconfig}, then
-@option{fontfile} can be a fontconfig pattern or omitted.
-
 @anchor{drawtext_expansion}
 @subsection Text expansion
 
index 1690b38..ef82eed 100644 (file)
  */
 
 #include "config.h"
+
 #if HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <time.h>
+#include <unistd.h>
+
+#if CONFIG_LIBFONTCONFIG
+#include <fontconfig/fontconfig.h>
+#endif
 
 #include "libavutil/avstring.h"
 #include "libavutil/bprint.h"
@@ -53,9 +61,6 @@
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
 #include FT_STROKER_H
-#if CONFIG_FONTCONFIG
-#include <fontconfig/fontconfig.h>
-#endif
 
 static const char *const var_names[] = {
     "dar",
@@ -125,6 +130,9 @@ typedef struct {
     const AVClass *class;
     enum expansion_mode exp_mode;   ///< expansion mode to use for the text
     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 *text;                  ///< text to be drawn
     AVBPrint expanded_text;         ///< used to contain the expanded text
@@ -198,6 +206,9 @@ static const AVOption drawtext_options[]= {
 #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},
 #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"},
         {"none",     "set no expansion",                    OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE},     0, 0, FLAGS, "expansion"},
@@ -337,68 +348,90 @@ error:
     return ret;
 }
 
-static int load_font_file(AVFilterContext *ctx, const char *path, int index,
-                          const char **error)
+static int load_font_file(AVFilterContext *ctx, const char *path, int index)
 {
     DrawTextContext *s = ctx->priv;
     int err;
 
     err = FT_New_Face(s->library, path, index, &s->face);
     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 0;
 }
 
-#if CONFIG_FONTCONFIG
-static int load_font_fontconfig(AVFilterContext *ctx, const char **error)
+#if CONFIG_LIBFONTCONFIG
+static int load_font_fontconfig(AVFilterContext *ctx)
 {
     DrawTextContext *s = ctx->priv;
     FcConfig *fontconfig;
-    FcPattern *pattern, *fpat;
+    FcPattern *pat, *best;
     FcResult result = FcResultMatch;
     FcChar8 *filename;
-    int err, index;
+    int index;
     double size;
+    int err = AVERROR(ENOENT);
 
     fontconfig = FcInitLoadConfigAndFonts();
     if (!fontconfig) {
-        *error = "impossible to init fontconfig\n";
-        return AVERROR(EINVAL);
+        av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n");
+        return AVERROR_UNKNOWN;
     }
-    pattern = FcNameParse(s->fontfile ? s->fontfile :
+    pat = FcNameParse(s->fontfile ? s->fontfile :
                           (uint8_t *)(intptr_t)"default");
-    if (!pattern) {
-        *error = "could not parse fontconfig pattern";
+    if (!pat) {
+        av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat");
         return AVERROR(EINVAL);
     }
-    if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) {
-        *error = "could not substitue fontconfig options"; /* very unlikely */
-        return AVERROR(EINVAL);
+
+    FcPatternAddString(pat, FC_FAMILY, s->font);
+    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);
-    if (!fpat || result != FcResultMatch) {
-        *error = "impossible to find a matching font";
-        return AVERROR(EINVAL);
+
+    best = FcFontMatch(fontconfig, pat, &result);
+    FcPatternDestroy(pat);
+
+    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 ||
-        FcPatternGetDouble (fpat, FC_SIZE,  0, &size    ) != FcResultMatch) {
-        *error = "impossible to find font information";
+
+    if (
+        FcPatternGetInteger(best, FC_INDEX, 0, &index   ) != FcResultMatch ||
+        FcPatternGetDouble (best, FC_SIZE,  0, &size    ) != FcResultMatch) {
+        av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
         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);
     if (!s->fontsize)
         s->fontsize = size + 0.5;
-    err = load_font_file(ctx, filename, index, error);
+
+    err = load_font_file(ctx, filename, index);
     if (err)
         return err;
-    FcPatternDestroy(fpat);
-    FcPatternDestroy(pattern);
     FcConfigDestroy(fontconfig);
-    return 0;
+fail:
+    FcPatternDestroy(best);
+    return err;
 }
 #endif
 
@@ -406,19 +439,16 @@ static int load_font(AVFilterContext *ctx)
 {
     DrawTextContext *s = 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, s->fontfile, 0, &error);
+    err = load_font_file(ctx, s->fontfile, 0);
     if (!err)
         return 0;
-#if CONFIG_FONTCONFIG
-    err = load_font_fontconfig(ctx, &error);
+#if CONFIG_LIBFONTCONFIG
+    err = load_font_fontconfig(ctx);
     if (!err)
         return 0;
 #endif
-    av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
-           s->fontfile, error);
     return err;
 }
 
@@ -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");
 #endif
 
-    if (!s->fontfile && !CONFIG_FONTCONFIG) {
+    if (!s->fontfile && !CONFIG_LIBFONTCONFIG) {
         av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
         return AVERROR(EINVAL);
     }