mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-03 21:42:09 +00:00
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
This commit is contained in:
parent
5f2d907de2
commit
692d37d2e9
@ -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.
|
||||
|
||||
@item y_align
|
||||
Specify what the @var{y} value is referred to. Possible values are:
|
||||
@itemize @bullet
|
||||
@item @code{text} the top of the highest glyph of the first text line is placed at @var{y}
|
||||
@item @code{baseline} the baseline of the first text line is placed at @var{y}
|
||||
@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
|
||||
@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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user