Browse code

avfilter/showcqt: add font option

this is fontconfig pattern

Signed-off-by: Muhammad Faiz <mfcc64@gmail.com>

Muhammad Faiz authored on 2016/10/17 07:59:57
Showing 3 changed files
... ...
@@ -16870,6 +16870,10 @@ use embedded font. Note that drawing with font file or embedded font is not
16870 16870
 implemented with custom @var{basefreq} and @var{endfreq}, use @var{axisfile}
16871 16871
 option instead.
16872 16872
 
16873
+@item font
16874
+Specify fontconfig pattern. This has lower priority than @var{fontfile}.
16875
+The : in the pattern may be replaced by | to avoid unnecessary escaping.
16876
+
16873 16877
 @item fontcolor
16874 16878
 Specify font color expression. This is arithmetic expression that should return
16875 16879
 integer value 0xRRGGBB. It can contain variables:
... ...
@@ -16993,6 +16997,12 @@ fontcolor='if(mod(floor(midi(f)+0.5),12), 0x0000FF, g(1))':fontfile=myfont.ttf
16993 16993
 @end example
16994 16994
 
16995 16995
 @item
16996
+Custom font using fontconfig:
16997
+@example
16998
+font='Courier New,Monospace,mono|bold'
16999
+@end example
17000
+
17001
+@item
16996 17002
 Custom frequency range with custom axis using image file:
16997 17003
 @example
16998 17004
 axisfile=myaxis.png:basefreq=40:endfreq=10000
... ...
@@ -36,6 +36,10 @@
36 36
 #include FT_FREETYPE_H
37 37
 #endif
38 38
 
39
+#if CONFIG_LIBFONTCONFIG
40
+#include <fontconfig/fontconfig.h>
41
+#endif
42
+
39 43
 #include "avf_showcqt.h"
40 44
 
41 45
 #define BASEFREQ        20.01523126408007475
... ...
@@ -78,7 +82,8 @@ static const AVOption showcqt_options[] = {
78 78
     { "tlength",         "set tlength", OFFSET(tlength),   AV_OPT_TYPE_STRING, { .str = TLENGTH },   CHAR_MIN, CHAR_MAX, FLAGS },
79 79
     { "count",   "set transform count", OFFSET(count),        AV_OPT_TYPE_INT, { .i64 = 6 },                1, 30,       FLAGS },
80 80
     { "fcount",  "set frequency count", OFFSET(fcount),       AV_OPT_TYPE_INT, { .i64 = 0 },                0, 10,       FLAGS },
81
-    { "fontfile",      "set axis font", OFFSET(fontfile),  AV_OPT_TYPE_STRING, { .str = NULL },      CHAR_MIN, CHAR_MAX, FLAGS },
81
+    { "fontfile", "set axis font file", OFFSET(fontfile),  AV_OPT_TYPE_STRING, { .str = NULL },      CHAR_MIN, CHAR_MAX, FLAGS },
82
+    { "font",          "set axis font", OFFSET(font),      AV_OPT_TYPE_STRING, { .str = NULL },      CHAR_MIN, CHAR_MAX, FLAGS },
82 83
     { "fontcolor",    "set font color", OFFSET(fontcolor), AV_OPT_TYPE_STRING, { .str = FONTCOLOR }, CHAR_MIN, CHAR_MAX, FLAGS },
83 84
     { "axisfile",     "set axis image", OFFSET(axisfile),  AV_OPT_TYPE_STRING, { .str = NULL },      CHAR_MIN, CHAR_MAX, FLAGS },
84 85
     { "axis",              "draw axis", OFFSET(axis),        AV_OPT_TYPE_BOOL, { .i64 = 1 },                0, 1,        FLAGS },
... ...
@@ -492,7 +497,7 @@ static int init_axis_color(ShowCQTContext *s, AVFrame *tmp, int half)
492 492
     return 0;
493 493
 }
494 494
 
495
-static int render_freetype(ShowCQTContext *s, AVFrame *tmp)
495
+static int render_freetype(ShowCQTContext *s, AVFrame *tmp, char *fontfile)
496 496
 {
497 497
 #if CONFIG_LIBFREETYPE
498 498
     const char *str = "EF G A BC D ";
... ...
@@ -506,13 +511,13 @@ static int render_freetype(ShowCQTContext *s, AVFrame *tmp)
506 506
     int non_monospace_warning = 0;
507 507
     int x;
508 508
 
509
-    if (!s->fontfile)
509
+    if (!fontfile)
510 510
         return AVERROR(EINVAL);
511 511
 
512 512
     if (FT_Init_FreeType(&lib))
513 513
         goto fail;
514 514
 
515
-    if (FT_New_Face(lib, s->fontfile, 0, &face))
515
+    if (FT_New_Face(lib, fontfile, 0, &face))
516 516
         goto fail;
517 517
 
518 518
     if (FT_Set_Char_Size(face, 16*64, 0, 0, 0))
... ...
@@ -565,17 +570,81 @@ static int render_freetype(ShowCQTContext *s, AVFrame *tmp)
565 565
     return 0;
566 566
 
567 567
 fail:
568
-    av_log(s->ctx, AV_LOG_WARNING, "error while loading freetype font, using default font instead.\n");
568
+    av_log(s->ctx, AV_LOG_WARNING, "error while loading freetype font.\n");
569 569
     FT_Done_Face(face);
570 570
     FT_Done_FreeType(lib);
571 571
     return AVERROR(EINVAL);
572 572
 #else
573
-    if (s->fontfile)
573
+    if (fontfile)
574 574
         av_log(s->ctx, AV_LOG_WARNING, "freetype is not available, ignoring fontfile option.\n");
575 575
     return AVERROR(EINVAL);
576 576
 #endif
577 577
 }
578 578
 
579
+static int render_fontconfig(ShowCQTContext *s, AVFrame *tmp, char* font)
580
+{
581
+#if CONFIG_LIBFONTCONFIG
582
+    FcConfig *fontconfig;
583
+    FcPattern *pat, *best;
584
+    FcResult result = FcResultMatch;
585
+    char *filename;
586
+    int i, ret;
587
+
588
+    if (!font)
589
+        return AVERROR(EINVAL);
590
+
591
+    for (i = 0; font[i]; i++) {
592
+        if (font[i] == '|')
593
+            font[i] = ':';
594
+    }
595
+
596
+    if (!(fontconfig = FcInitLoadConfigAndFonts())) {
597
+        av_log(s->ctx, AV_LOG_ERROR, "impossible to init fontconfig.\n");
598
+        return AVERROR_UNKNOWN;
599
+    }
600
+
601
+    if (!(pat = FcNameParse((uint8_t *)font))) {
602
+        av_log(s->ctx, AV_LOG_ERROR, "could not parse fontconfig pat.\n");
603
+        FcConfigDestroy(fontconfig);
604
+        return AVERROR(EINVAL);
605
+    }
606
+
607
+    FcDefaultSubstitute(pat);
608
+
609
+    if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
610
+        av_log(s->ctx, AV_LOG_ERROR, "could not substitue fontconfig options.\n");
611
+        FcPatternDestroy(pat);
612
+        FcConfigDestroy(fontconfig);
613
+        return AVERROR(ENOMEM);
614
+    }
615
+
616
+    best = FcFontMatch(fontconfig, pat, &result);
617
+    FcPatternDestroy(pat);
618
+
619
+    ret = AVERROR(EINVAL);
620
+    if (!best || result != FcResultMatch) {
621
+        av_log(s->ctx, AV_LOG_ERROR, "cannot find a valid font for %s.\n", font);
622
+        goto fail;
623
+    }
624
+
625
+    if (FcPatternGetString(best, FC_FILE, 0, (FcChar8 **)&filename) != FcResultMatch) {
626
+        av_log(s->ctx, AV_LOG_ERROR, "no file path for %s\n", font);
627
+        goto fail;
628
+    }
629
+
630
+    ret = render_freetype(s, tmp, filename);
631
+
632
+fail:
633
+    FcPatternDestroy(best);
634
+    FcConfigDestroy(fontconfig);
635
+    return ret;
636
+#else
637
+    if (font)
638
+        av_log(s->ctx, AV_LOG_WARNING, "fontconfig is not available, ignoring font option.\n");
639
+    return AVERROR(EINVAL);
640
+#endif
641
+}
642
+
579 643
 static int render_default_font(AVFrame *tmp)
580 644
 {
581 645
     const char *str = "EF G A BC D ";
... ...
@@ -615,7 +684,9 @@ static int init_axis_from_font(ShowCQTContext *s)
615 615
     if (!(s->axis_frame = av_frame_alloc()))
616 616
         goto fail;
617 617
 
618
-    if (render_freetype(s, tmp) < 0 && (default_font = 1, ret = render_default_font(tmp)) < 0)
618
+    if (render_freetype(s, tmp, s->fontfile) < 0 &&
619
+        render_fontconfig(s, tmp, s->font) < 0 &&
620
+        (default_font = 1, ret = render_default_font(tmp)) < 0)
619 621
         goto fail;
620 622
 
621 623
     if (default_font)
... ...
@@ -109,6 +109,7 @@ typedef struct {
109 109
     int                 count;
110 110
     int                 fcount;
111 111
     char                *fontfile;
112
+    char                *font;
112 113
     char                *fontcolor;
113 114
     char                *axisfile;
114 115
     int                 axis;