[FFmpeg-cvslog] avfilter/vf_drawtext: add y_align option
yethie
git at videolan.org
Mon Jun 19 23:41:42 EEST 2023
ffmpeg | branch: master | yethie <klimklim at tiscali.it> | Wed Jun 14 18:58:32 2023 +0200| [692d37d2e9ac641fa477c7a039f4d1e3beb3bd47] | committer: Paul B Mahol
avfilter/vf_drawtext: add y_align option
The new y_align option specifies if the user provided y value
is referred to the top of the text, to the font baseline or to the
top of the font
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=692d37d2e9ac641fa477c7a039f4d1e3beb3bd47
---
doc/filters.texi | 10 ++++++++++
libavfilter/vf_drawtext.c | 47 ++++++++++++++++++++++++++++++++++++-----------
2 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 891c051029..9730444337 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -12390,6 +12390,16 @@ The value must contain exactly two letters, one for the vertical alignment (T=to
M=middle, B=bottom) and one for the horizontal alignment (L=left, C=center, R=right).
Please note that tab characters are only supported with the left horizontal alignment.
+ at item y_align
+Specify what the @var{y} value is referred to. Possible values are:
+ at itemize @bullet
+ at item @code{text} the top of the highest glyph of the first text line is placed at @var{y}
+ at item @code{baseline} the baseline of the first text line is placed at @var{y}
+ at item @code{font} the baseline of the first text line is placed at @var{y} plus the
+ ascent (in pixels) defined in the font metrics
+ at end itemize
+The default value of @var{y_align} is "text" for backward compatibility.
+
@item borderw
Set the width of the border to be drawn around the text using @var{bordercolor}.
The default value of @var{borderw} is 0.
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index e147196844..59ba3e40c0 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -171,6 +171,12 @@ enum expansion_mode {
EXP_STRFTIME,
};
+enum y_alignment {
+ YA_TEXT,
+ YA_BASELINE,
+ YA_FONT,
+};
+
typedef struct HarfbuzzData {
hb_buffer_t* buf;
hb_font_t* font;
@@ -310,6 +316,7 @@ typedef struct DrawTextContext {
int boxw; ///< the value of the boxw parameter
int boxh; ///< the value of the boxh parameter
uint8_t *text_align; ///< the horizontal and vertical text alignment
+ int y_align; ///< the value of the y_align parameter
TextLine *lines; ///< computed information about text lines
int line_count; ///< the number of text lines
@@ -353,6 +360,10 @@ static const AVOption drawtext_options[]= {
{"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"},
{"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"},
{"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"},
+ {"y_align", "set the y alignment", OFFSET(y_align), AV_OPT_TYPE_INT, {.i64=YA_TEXT}, 0, 2, FLAGS, "y_align"},
+ {"text", "y is referred to the top of the first text line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_TEXT}, 0, 0, FLAGS, "y_align"},
+ {"baseline", "y is referred to the baseline of the first line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_BASELINE}, 0, 0, FLAGS, "y_align"},
+ {"font", "y is referred to the font defined line metrics", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_FONT}, 0, 0, FLAGS, "y_align"},
{"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
{"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
@@ -958,11 +969,13 @@ static av_cold int init(AVFilterContext *ctx)
if ((err = update_fontsize(ctx)) < 0)
return err;
+ // Always init the stroker, may be needed if borderw is set via command
+ if (FT_Stroker_New(s->library, &s->stroker)) {
+ av_log(ctx, AV_LOG_ERROR, "Could not init FT stroker\n");
+ return AVERROR_EXTERNAL;
+ }
+
if (s->borderw) {
- if (FT_Stroker_New(s->library, &s->stroker)) {
- av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n");
- return AVERROR_EXTERNAL;
- }
FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
FT_STROKER_LINEJOIN_ROUND, 0);
}
@@ -1634,7 +1647,6 @@ static int measure_text(AVFilterContext *ctx, TextMetrics *metrics)
int line_count = 0;
uint32_t code = 0;
Glyph *glyph = NULL;
- int height64;
int i, tab_idx = 0, last_tab_idx = 0, line_offset = 0;
char* p;
@@ -1753,10 +1765,13 @@ continue_on_failed2:
metrics->line_height64 = s->face->size->metrics.height;
metrics->width = POS_CEIL(width64, 64);
- height64 = (metrics->line_height64 + s->line_spacing * 64) *
- (FFMAX(0, line_count - 1)) + first_max_y64 - cur_min_y64;
- metrics->height = POS_CEIL(height64, 64);
-
+ if (s->y_align == YA_FONT) {
+ metrics->height = POS_CEIL(metrics->line_height64 * line_count, 64);
+ } else {
+ int height64 = (metrics->line_height64 + s->line_spacing * 64) *
+ (FFMAX(0, line_count - 1)) + first_max_y64 - cur_min_y64;
+ metrics->height = POS_CEIL(height64, 64);
+ }
metrics->offset_top64 = first_max_y64;
metrics->offset_right64 = last_max_x64;
metrics->offset_bottom64 = cur_min_y64;
@@ -1929,7 +1944,13 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame)
x = 0;
y = 0;
x64 = (int)(s->x * 64.);
- y64 = (int)(s->y * 64. + metrics.offset_top64);
+ if (s->y_align == YA_FONT) {
+ y64 = (int)(s->y * 64. + s->face->size->metrics.ascender);
+ } else if (s->y_align == YA_BASELINE) {
+ y64 = (int)(s->y * 64.);
+ } else {
+ y64 = (int)(s->y * 64. + metrics.offset_top64);
+ }
for (int l = 0; l < s->line_count; ++l) {
TextLine *line = &s->lines[l];
@@ -1973,7 +1994,11 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame)
}
metrics.rect_x = s->x;
- metrics.rect_y = s->y;
+ if (s->y_align == YA_BASELINE) {
+ metrics.rect_y = s->y - metrics.offset_top64 / 64;
+ } else {
+ metrics.rect_y = s->y;
+ }
s->box_width = s->boxw == 0 ? metrics.width : s->boxw;
s->box_height = s->boxh == 0 ? metrics.height : s->boxh;
More information about the ffmpeg-cvslog
mailing list