77#define USER_VAR_COUNT 20
80#define VAR_COUNT (VAR_U0 + USER_VAR_COUNT)
117static double vgs_fn_p(
void *,
double,
double);
205 {
"butt", CAIRO_LINE_CAP_BUTT },
206 {
"round", CAIRO_LINE_CAP_ROUND },
207 {
"square", CAIRO_LINE_CAP_SQUARE },
212 {
"bevel", CAIRO_LINE_JOIN_BEVEL },
213 {
"miter", CAIRO_LINE_JOIN_MITER },
214 {
"round", CAIRO_LINE_JOIN_ROUND },
240#define MAX_COMMAND_PARAMS 8
246#define MAX_PROC_ARGS (MAX_COMMAND_PARAMS - 2)
248#define VGS_MAX_RECURSION_DEPTH 100
259#define PARAMS(...) (const struct VGSParameter[]){ __VA_ARGS__ }
260#define L(...) PARAMS(__VA_ARGS__, { PARAM_END })
261#define R(...) PARAMS(__VA_ARGS__, { PARAM_MAY_REPEAT })
262#define NONE PARAMS({ PARAM_END })
265#define N { PARAM_NUMERIC }
266#define V { PARAM_VAR_NAME }
267#define P { PARAM_SUBPROGRAM }
268#define C(c) { PARAM_CONSTANT, .constants = c }
287 {
"call",
CMD_PROC_CALL,
L({ PARAM_PROC_NAME }, { PARAM_PROC_ARGS }) },
309 {
"print",
CMD_PRINT,
L({ PARAM_NUMERIC_METADATA }, { PARAM_VARIADIC }) },
366 if (length >=
sizeof(bufname))
369 memcpy(bufname,
name, length);
370 bufname[length] =
'\0';
487 && str[token->
length] ==
'\0';
497 const char *source = parser->
source;
502 const char *sep = strchr(source,
'\n');
515void vgs_log_invalid_token(
519 const
char *extra_fmt,
529 va_start(ap, extra_fmt);
530 vsnprintf(extra,
sizeof(extra), extra_fmt, ap);
534 "Invalid token '%.*s' at line %zu, column %zu: %s\n",
535 (
int)token->length, token->lexeme,
line, column, extra);
551 #define WORD_SEPARATOR " \n\t\r,"
554 size_t cursor, length;
563 token->
lexeme = &source[cursor];
565 switch (source[cursor]) {
567 token->
type = TOKEN_EOF;
578 switch (source[cursor + length]) {
581 vgs_log_invalid_token(log_ctx, parser, token,
"Unmatched parenthesis.");
596 token->
type = TOKEN_EXPR;
601 token->
type = TOKEN_LEFT_BRACKET;
606 token->
type = TOKEN_RIGHT_BRACKET;
623 token->
type = TOKEN_LITERAL;
632 if (source[cursor + 1] ==
'/') {
633 parser->
cursor += cursor + strcspn(token->
lexeme,
"\n");
640 token->
type = TOKEN_WORD;
758 vgs_log_invalid_token(log_ctx, parser, token,
"Expected color.");
795 if (token.
length + 1 <
sizeof(stack_buf)) {
807 switch (token.
type) {
809 arg->type = ARG_LITERAL;
813 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected valid number.");
819 arg->type = ARG_EXPR;
833 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid expression.");
841 if (accept_colors &&
lexeme[0] ==
'#') {
853 arg->type = ARG_VARIABLE;
866 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected numeric argument.");
879 memset(
arg, 0,
sizeof(*
arg));
902 switch (token.
type) {
917 if (accept_colors && token.
lexeme[0] ==
'#')
943 for (
int i = 0;
i < token->
length;
i++) {
946 && !(
c >=
'a' &&
c <=
'z')
947 && !(
c >=
'A' &&
c <=
'Z')
948 && !(
i > 0 &&
c >=
'0' &&
c <=
'9')
970 vgs_statement_free(&statement); \
971 return AVERROR(err); \
982 int proc_args_count = 0;
991 switch (param->
type) {
1007 case PARAM_MAY_REPEAT:
1020 if (param->
type != PARAM_END
1023 param = &decl->
params[0];
1024 statement.args =
NULL;
1025 statement.args_count = 0;
1058 case PARAM_CONSTANT: {
1060 char expected_names[64] = { 0 };
1085 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected one of%s.", expected_names);
1092 case PARAM_PROC_ARGS:
1100 vgs_log_invalid_token(log_ctx, parser, &token,
1108 case PARAM_NUMERIC_COLOR:
1109 case PARAM_NUMERIC_METADATA:
1114 param->
type == PARAM_NUMERIC_METADATA,
1115 param->
type == PARAM_NUMERIC_COLOR || param->
type == PARAM_PROC_ARGS
1123 case PARAM_PROC_NAME: {
1131 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid procedure name.");
1164 case PARAM_RAW_IDENT:
1169 switch (token.
type) {
1177 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1183 case PARAM_SUBPROGRAM:
1188 if (token.
type != TOKEN_LEFT_BRACKET) {
1189 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1204 case PARAM_PROC_PARAMS:
1210 vgs_log_invalid_token(log_ctx, parser, &token,
1215 if (token.
type != TOKEN_WORD) {
1223 case PARAM_VAR_NAME: {
1242 if (var_idx == -1) {
1243 vgs_log_invalid_token(log_ctx, parser, &token,
1244 "Too many user variables. Can define up to %d variables.",
USER_VAR_COUNT);
1251 vgs_log_invalid_token(log_ctx, parser, &token,
"Reserved variable name.");
1258 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid variable name.");
1266 arg.constant = var_idx;
1275 (
void*)&statement.
args,
1284 switch (param->
type) {
1285 case PARAM_PROC_ARGS:
1286 case PARAM_PROC_PARAMS:
1339 memset(program, 0,
sizeof(*program));
1344 "Exceeded maximum drawvg block nesting depth (%d)\n",
1356 switch (token.
type) {
1359 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '}'.");
1381 case TOKEN_RIGHT_BRACKET:
1396 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected command.");
1417#define RANDOM_STATES 4
1499 int max_segments = (int)
arg;
1501 double lmx =
NAN, lmy =
NAN;
1502 double cx =
NAN, cy =
NAN;
1505 cairo_path_t *path = cairo_copy_path_flat(
state->cairo_ctx);
1507 for (
int i = 0;
i < path->num_data;
i += path->data[
i].header.length) {
1509 cairo_path_data_t *
data = &path->data[
i];
1512 case CAIRO_PATH_MOVE_TO:
1513 cx = lmx =
data[1].point.x;
1514 cy = lmy =
data[1].point.y;
1519 case CAIRO_PATH_LINE_TO:
1520 x =
data[1].point.x;
1521 y =
data[1].point.y;
1524 case CAIRO_PATH_CLOSE_PATH:
1533 length +=
hypot(cx - x, cy - y);
1540 if (--max_segments == 0)
1544 cairo_path_destroy(path);
1563 const uint64_t iarg = (uint64_t)
arg;
1588 cairo_user_to_device(
state->cairo_ctx, &x0, &y0);
1590 const int x = (int)x0;
1591 const int y = (int)y0;
1593 if (x < 0 || y < 0 || x >=
frame->width || y >=
frame->height)
1598 uint32_t
color[4] = { 0, 0, 0, 255 };
1600 for (
int c = 0;
c <
desc->nb_components;
c++) {
1614 const int depth =
desc->comp[
c].depth;
1638 state->last_fn_p_color.numeric = num;
1640 state->last_fn_p_color.components[
i] = (uint8_t)
color[
i];
1657 state->last_fn_p_color.numeric =
NAN;
1678 cairo_pattern_destroy(
state->pattern_builder);
1693 cairo_translate(
c, x, y);
1696 cairo_scale(
c, 1, ry / rx);
1698 cairo_new_sub_path(
c);
1699 cairo_arc(
c, 0, 0, rx, 0, 2 *
M_PI);
1700 cairo_close_path(
c);
1701 cairo_new_sub_path(
c);
1721 double x0 = 0, y0 = 0;
1722 double xa, ya, xb, yb;
1724 const int use_reflected =
isnan(x1);
1729 if (!use_reflected) {
1738 if (use_reflected) {
1740 x1 =
state->rcp.quad_x;
1741 y1 =
state->rcp.quad_y;
1748 xa = (x0 + 2 * x1) / 3;
1749 ya = (y0 + 2 * y1) / 3;
1750 xb = (x + 2 * x1) / 3;
1751 yb = (y + 2 * y1) / 3;
1752 cairo_curve_to(
state->cairo_ctx, xa, ya, xb, yb, x, y);
1755 state->rcp.cubic_x = x1;
1756 state->rcp.cubic_y = y1;
1757 state->rcp.quad_x = 2 * x - x1;
1758 state->rcp.quad_y = 2 * y - y1;
1772 double x0 = 0, y0 = 0;
1774 const int use_reflected =
isnan(x1);
1779 if (!use_reflected) {
1790 if (use_reflected) {
1792 x1 =
state->rcp.cubic_x;
1793 y1 =
state->rcp.cubic_y;
1800 cairo_curve_to(
state->cairo_ctx, x1, y1, x2, y2, x, y);
1803 state->rcp.cubic_x = 2 * x - x2;
1804 state->rcp.cubic_y = 2 * y - y2;
1805 state->rcp.quad_x = x2;
1806 state->rcp.quad_y = y2;
1819 cairo_new_sub_path(
c);
1820 cairo_arc(
c, x + radius, y + radius, radius,
M_PI, 3 *
M_PI / 2);
1821 cairo_arc(
c, x +
width - radius, y + radius, radius, 3 *
M_PI / 2, 2 *
M_PI);
1822 cairo_arc(
c, x +
width - radius, y +
height - radius, radius, 0,
M_PI / 2);
1823 cairo_arc(
c, x + radius, y +
height - radius, radius,
M_PI / 2,
M_PI);
1824 cairo_close_path(
c);
1849 switch ((
int)
floor(h1)) {
1912 #define ASSERT_ARGS(n) av_assert0(statement->args_count == n)
1916 #define MAY_PRESERVE(funcname) \
1918 if (state->preserve_path) { \
1919 state->preserve_path = 0; \
1920 funcname##_preserve(state->cairo_ctx); \
1922 funcname(state->cairo_ctx); \
1933 for (
int st_number = 0; st_number < program->
statements_count; st_number++) {
1966 numerics[
arg] =
a->literal;
1971 numerics[
arg] =
state->vars[
a->variable];
1990 switch (statement->
cmd) {
1997 cairo_pattern_destroy(
state->pattern_builder);
2003 switch (statement->
cmd) {
2030 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[2]);
2036 cairo_set_fill_rule(
2039 CAIRO_FILL_RULE_WINDING :
2040 CAIRO_FILL_RULE_EVEN_ODD
2048 cairo_close_path(
state->cairo_ctx);
2058 cairo_pattern_add_color_stop_rgba(
2059 state->pattern_builder,
2093 hsl2rgb(numerics[1], numerics[2], numerics[3], &
r, &
g, &
b);
2100 double *
const color_var =
state->color_vars[user_var -
VAR_U0];
2104 color_var[3] = numerics[4];
2111 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2118 cairo_set_fill_rule(
2121 CAIRO_FILL_RULE_WINDING :
2122 CAIRO_FILL_RULE_EVEN_ODD
2155 state->interrupted = 1;
2161 if (
isfinite(numerics[0]) && numerics[0] != 0.0) {
2164 if (ret != 0 ||
state->interrupted != 0)
2174 cairo_pattern_destroy(
state->pattern_builder);
2176 state->pattern_builder = cairo_pattern_create_linear(
2186 cairo_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2191 cairo_rel_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2196 cairo_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2201 cairo_rel_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2206 cairo_new_sub_path(
state->cairo_ctx);
2211 state->preserve_path = 1;
2220 int capacity =
sizeof(msg) -
len;
2232 if (written >= capacity)
2245 const int proc_args = statement->
args_count - 2;
2259 const int proc_args = statement->
args_count - 1;
2270 "Procedure expects %d arguments, but received %d.",
2279 const char *proc_name =
state->proc_names[proc_id];
2281 "Missing body for procedure '%s'\n", proc_name);
2287 for (
int i = 0;
i < proc_args;
i++) {
2288 const int var = proc->
args[
i];
2292 const int color_var = var -
VAR_U0;
2296 current_vars[
i] =
state->vars[var];
2299 state->vars[var] = numerics[
i + 1];
2306 for (
int i = 0;
i < proc_args;
i++) {
2307 const int var = proc->
args[
i];
2311 const int color_var = var -
VAR_U0;
2314 state->vars[var] = current_vars[
i];
2321 if (
state->interrupted) {
2322 state->interrupted = 0;
2348 cairo_pattern_destroy(
state->pattern_builder);
2350 state->pattern_builder = cairo_pattern_create_radial(
2361 cairo_reset_clip(
state->cairo_ctx);
2369 cairo_identity_matrix(
state->cairo_ctx);
2374 cairo_rectangle(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2385 for (
int i = 0, count = (
int)numerics[0];
i < count;
i++) {
2393 if (
state->interrupted) {
2394 state->interrupted = 0;
2405 cairo_restore(
state->cairo_ctx);
2410 cairo_rotate(
state->cairo_ctx, numerics[0]);
2427 cairo_save(
state->cairo_ctx);
2432 cairo_scale(
state->cairo_ctx, numerics[0], numerics[0]);
2437 cairo_scale(
state->cairo_ctx, numerics[0], numerics[1]);
2444 cairo_pattern_destroy(
state->pattern_builder);
2446 state->pattern_builder = cairo_pattern_create_rgba(
2466 cairo_set_line_width(
state->cairo_ctx, numerics[0]);
2472 double *dashes,
offset, stack_buf[16];
2481 dashes =
av_calloc(num + 1,
sizeof(
double));
2490 dashes[num] = numerics[0];
2498 if (dashes != stack_buf)
2511 cairo_pattern_destroy(
state->pattern_builder);
2514 hsl2rgb(numerics[0], numerics[1], numerics[2], &
r, &
g, &
b);
2521 state->pattern_builder = cairo_pattern_create_rgba(
r,
g,
b, numerics[3]);
2531 state->vars[user_var] = numerics[1];
2535 if (
state->last_fn_p_color.numeric == numerics[1]) {
2537 (*
color)[
i] =
state->last_fn_p_color.components[
i] / 255.0;
2567 cairo_translate(
state->cairo_ctx, numerics[0], numerics[1]);
2584 double d = numerics[0];
2586 switch (statement->
cmd) {
2593 cairo_line_to(
state->cairo_ctx, cx, cy);
2602 if (
state->rcp.status == RCP_UPDATED) {
2603 state->rcp.status = RCP_VALID;
2605 state->rcp.status = RCP_NONE;
2613 "Error in cairo context: %s\n",
2651#define OPT(name, field, help) \
2655 offsetof(DrawVGContext, field), \
2656 AV_OPT_TYPE_STRING, \
2659 AV_OPT_FLAG_FILTERING_PARAM \
2660 | AV_OPT_FLAG_VIDEO_PARAM \
2664 OPT(
"script", script_text,
"script source to draw the graphics"),
2665 OPT(
"s", script_text,
"script source to draw the graphics"),
2666 OPT(
"file", script_file,
"file to load the script source"),
2690 CAIRO_FORMAT_ARGB32,
2692 CAIRO_FORMAT_RGB16_565,
2694 CAIRO_FORMAT_INVALID,
2705 return CAIRO_FORMAT_INVALID;
2711 cairo_surface_t* surface;
2725 surface = cairo_image_surface_create_for_data(
2733 if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
2738 eval_state.
cairo_ctx = cairo_create(surface);
2757 cairo_surface_destroy(surface);
2786 drawvg->time_start =
NAN;
2788 if ((drawvg->script_text ==
NULL) == (drawvg->script_file ==
NULL)) {
2790 "Either 'source' or 'file' must be provided\n");
2795 if (drawvg->script_file !=
NULL) {
2798 (
const char *)drawvg->script_file,
2799 &drawvg->script_text,
2809 ret =
vgs_parse(drawvg, &parser, &drawvg->program, 0);
2834 .p.priv_class = &drawvg_class,
static const char *const format[]
const FFFilter ff_vf_drawvg
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Main libavfilter public API header.
char * av_asprintf(const char *fmt,...)
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define i(width, name, range_min, range_max)
static IPT relative(const CmsCtx *ctx, IPT ipt)
static __device__ float fabs(float a)
static __device__ float floor(float a)
cairo_status_t cairo_status(cairo_t *cr)
cairo_bool_t cairo_has_current_point(cairo_t *cr)
cairo_bool_t cairo_get_dash_count(cairo_t *cr)
void cairo_set_source(cairo_t *cr, cairo_pattern_t *source)
void cairo_get_current_point(cairo_t *cr, double *x, double *y)
void cairo_get_dash(cairo_t *cr, double *dashes, double *offset)
void cairo_set_dash(cairo_t *cr, const double *dashes, int num_dashes, double offset)
int(* init)(AVBSFContext *ctx)
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
double av_strtod(const char *numstr, char **tail)
Parse the string in numstr and return its value as a double.
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
simple arithmetic expression evaluator
static struct @346255127015250356166251341105367306144006377143 state
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
void * av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data)
Add an element of size elem_size to a dynamic array.
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
const FormatMap format_map[]
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
#define FILTER_PIXFMTS_ARRAY(array)
static FilterLink * ff_filter_link(AVFilterLink *link)
#define AVFILTER_DEFINE_CLASS(fname)
Macro definitions for various function/variable attributes.
#define av_printf_format(fmtpos, attrpos)
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static av_const double hypot(double x, double y)
Utility Preprocessor macros.
#define FFSWAP(type, a, b)
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
void av_read_image_line2(void *dst, const uint8_t *data[4], const int linesize[4], const AVPixFmtDescriptor *desc, int x, int y, int c, int w, int read_pal_component, int dst_element_size)
Read a line from an image, and write the values of the pixel format component c to dst.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_0RGB32
#define AV_PIX_FMT_X2RGB10
AVPixelFormat
Pixel format.
#define AV_PIX_FMT_RGB565
static const uint8_t header[24]
simple Pseudo Random Number Generator
static uint64_t ff_sfc64_get(FFSFC64 *s)
static void ff_sfc64_init(FFSFC64 *s, uint64_t seeda, uint64_t seedb, uint64_t seedc, int rounds)
Initialize sfc64 with up to 3 seeds.
#define FF_ARRAY_ELEMS(a)
Describe the class of an AVClass context structure.
AVFilterLink ** outputs
array of pointers to output links
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
AVFilterContext * dst
dest filter
int format
agreed upon media format
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
uint8_t * script_text
Inline source.
cairo_format_t cairo_format
Equivalent to AVPixelFormat.
struct VGSProgram program
uint8_t * script_file
File path to load the source.
double time_start
Time in seconds of the first frame.
Link properties exposed to filter code, but not external callers.
struct VGSProgram * subprogram
const struct VGSParameter * params
Constants for some commands, like setlinejoin.
struct VGSEvalState::@052052206070033266046172264355235315226035177334 last_fn_p_color
Track last color read by the p() function.
cairo_t * cairo_ctx
Cairo context for drawing operations.
struct VGSEvalState::@155271003302334067043040321160256211361153312131 rcp
double vars[VAR_COUNT]
Values for the variables in expressions.
int preserve_path
Next call to [eo]fill, [eo]clip, or stroke, should use the _preserve function.
cairo_pattern_t * pattern_builder
Pattern being built by commands like colorstop.
AVFrame * frame
Current frame.
FFSFC64 random_state[RANDOM_STATES]
State for each index available for the randomg function.
const char *const * proc_names
Reference to the procedure names in the VGSProgram.
cairo_color color_vars[USER_VAR_COUNT]
Colors stored in variables.
int interrupted
Register if break was called in a subprogram.
struct VGSProcedure * procedures
Subprograms associated to each procedure identifier.
AVDictionary * metadata
Frame metadata, if any.
enum VGSEvalState::@155271003302334067043040321160256211361153312131::@232275036207102156113101253305127226350234230172 status
enum VGSParameter::@143265147051371323252026120223356212015016027230 type
const struct VGSConstant * constants
Array for PARAM_CONSTANT.
enum VGSParserToken::@305003223102135214130200176027047114127146020233 type
const char * var_names[VAR_COUNT+1]
Block assigned to a procedure by a call to the proc command.
const struct VGSProgram * program
int args[MAX_PROC_ARGS]
Variable ids where each argument is stored.
int proc_args_count
Number of expected arguments.
struct VGSStatement * statements
struct VGSArgument * args
static AVFormatContext * ctx
int ff_load_textfile(void *log_ctx, const char *textfile, unsigned char **text, size_t *text_size)
static FilteringContext * filter_ctx
static const AVFilterPad drawvg_inputs[]
static int vgs_parser_can_repeat_cmd(void *log_ctx, struct VGSParser *parser, bool accept_colors)
Check if the next token is a numeric value (or a color, if accept_colors is true),...
static void draw_ellipse(cairo_t *c, double x, double y, double rx, double ry)
Draw an ellipse.
static enum AVPixelFormat drawvg_pix_fmts[]
static av_always_inline void color_reset(cairo_color *const dest)
static const struct VGSConstant vgs_consts_line_join[]
static int vgs_parse_statement(void *log_ctx, struct VGSParser *parser, struct VGSProgram *program, const struct VGSCommandSpec *decl)
Extract the arguments for a command, and add a new statement to the program.
static double(*const vgs_func1_impls[])(void *, double)
static int vgs_parse_numeric_argument(void *log_ctx, struct VGSParser *parser, struct VGSArgument *arg, int metadata, bool accept_colors)
Consume the next argument as a numeric value, and store it in arg.
static void vgs_eval_state_free(struct VGSEvalState *state)
static int vgs_eval_state_init(struct VGSEvalState *state, const struct VGSProgram *program, void *log_ctx, AVFrame *frame)
static void draw_rounded_rect(cairo_t *c, double x, double y, double width, double height, double radius)
static cairo_format_t cairo_format_from_pix_fmt(DrawVGContext *ctx, enum AVPixelFormat format)
static av_always_inline void color_copy(cairo_color *dest, const cairo_color *src)
static double vgs_fn_p(void *, double, double)
Function p(x, y) for av_expr_eval.
static int vgs_cmd_change_path(enum VGSCommand cmd)
Return 1 if the command changes the current path in the cairo context.
static double(*const vgs_func2_impls[])(void *, double, double)
#define USER_VAR_COUNT
Number of user variables that can be created with setvar.
double cairo_color[4]
Colors in cairo are defined by 4 values, between 0 and 1.
static double vgs_fn_randomg(void *, double)
Function randomg(n) for av_expr_eval.
static int vgs_eval(struct VGSEvalState *state, const struct VGSProgram *program, int stack_level)
Interpreter for VGSProgram.
static double vgs_fn_pathlen(void *, double)
Function pathlen(n) for av_expr_eval.
static void vgs_parser_init(struct VGSParser *parser, const char *source)
static int vgs_is_valid_identifier(const struct VGSParserToken *token)
static void hsl2rgb(double h, double s, double l, double *pr, double *pg, double *pb)
#define MAX_COMMAND_PARAMS
static void vgs_token_span(const struct VGSParser *parser, const struct VGSParserToken *token, size_t *line, size_t *column)
Compute the line/column numbers of the given token.
static int vgs_parse_color(void *log_ctx, struct VGSArgument *arg, const struct VGSParser *parser, const struct VGSParserToken *token)
static const char *const vgs_func1_names[]
static void draw_cubic_curve_to(struct VGSEvalState *state, int relative, double x1, double y1, double x2, double y2, double x, double y)
Similar to quad_curve_to, but for cubic curves.
static const char *const vgs_default_vars[]
#define OPT(name, field, help)
#define VGS_MAX_RECURSION_DEPTH
@ VAR_CY
Y coordinate for current point.
@ VAR_CX
X coordinate for current point.
static int vgs_comp_command_spec(const void *cs1, const void *cs2)
Comparator for VGSCommandDecl, to be used with bsearch(3).
static int vgs_parser_next_token(void *log_ctx, struct VGSParser *parser, struct VGSParserToken *token, int advance)
Return the next token in the source.
#define RANDOM_STATES
Number of different states for the randomg function.
static av_cold int drawvg_init(AVFilterContext *ctx)
static void vgs_free(struct VGSProgram *program)
Release the memory allocated by the program.
static const struct VGSCommandSpec vgs_commands[]
static const struct VGSCommandSpec * vgs_get_command(const char *name, size_t length)
Return the specs for the given command, or NULL if the name is not valid.
static const AVOption drawvg_options[]
static void draw_quad_curve_to(struct VGSEvalState *state, int relative, double x1, double y1, double x, double y)
Draw a quadratic bezier from the current point to x, y, The control point is specified by x1,...
static av_cold void drawvg_uninit(AVFilterContext *ctx)
static void vgs_parser_free(struct VGSParser *parser)
static const char *const vgs_func2_names[]
static const struct VGSConstant vgs_consts_line_cap[]
@ CMD_PROC_CALL
call name (expr)*
@ CMD_ELLIPSE
ellipse (cx cy rx ry)
@ CMD_ARC
arc (cx cy radius angle1 angle2)
@ CMD_SET_LINE_JOIN
setlinejoin (join)
@ CMD_MOVE_TO_REL
m, rmoveto (dx dy)
@ CMD_CIRCLE
circle (cx cy radius)
@ CMD_DEF_HSLA
defhsla (varname h s l a)
@ CMD_CURVE_TO
C, curveto (x1 y1 x2 y2 x y)
@ CMD_PROC_ASSIGN
proc name varnames* { subprogram }
@ CMD_S_CURVE_TO_REL
s (dx2 dy2 dx dy)
@ CMD_RADIAL_GRAD
radialgrad (cx0 cy0 radius0 cx1 cy1 radius1)
@ CMD_ARC_NEG
arcn (cx cy radius angle1 angle2)
@ CMD_SET_DASH
setdash (length)
@ CMD_S_CURVE_TO
S (x2 y2 x y)
@ CMD_TRANSLATE
translate (tx ty)
@ CMD_REPEAT
repeat (count) { subprogram }
@ CMD_RESET_MATRIX
resetmatrix
@ CMD_MOVE_TO
M, moveto (x y)
@ CMD_RECT
rect (x y width height)
@ CMD_SET_HSLA
sethsla (h s l a)
@ CMD_ROTATE
rotate (angle)
@ CMD_Q_CURVE_TO_REL
q (dx1 dy1 dx dy)
@ CMD_SET_LINE_WIDTH
setlinewidth (width)
@ CMD_LINE_TO_REL
l, rlineto (dx dy)
@ CMD_IF
if (condition) { subprogram }
@ CMD_DEF_RGBA
defrgba (varname r g b a)
@ CMD_SET_COLOR
setcolor (color)
@ CMD_RESET_CLIP
resetclip
@ CMD_ROUNDEDRECT
roundedrect (x y width height radius)
@ CMD_SET_VAR
setvar (varname value)
@ CMD_CURVE_TO_REL
c, rcurveto (dx1 dy1 dx2 dy2 dx dy)
@ CMD_T_CURVE_TO_REL
t (dx dy)
@ CMD_SCALEXY
scalexy (sx sy)
@ CMD_COLOR_STOP
colorstop (offset color)
@ CMD_LINEAR_GRAD
lineargrad (x0 y0 x1 y1)
@ CMD_GET_METADATA
getmetadata varname key
@ CMD_SET_LINE_CAP
setlinecap (cap)
@ CMD_Q_CURVE_TO
Q (x1 y1 x y)
@ CMD_SET_DASH_OFFSET
setdashoffset (offset)
@ CMD_CLOSE_PATH
Z, z, closepath.
@ CMD_SET_RGBA
setrgba (r g b a)
@ CMD_LINE_TO
L, lineto (x y)
@ CMD_RESET_DASH
resetdash
static int drawvg_config_props(AVFilterLink *inlink)
static int vgs_token_is_string(const struct VGSParserToken *token, const char *str)
Check if token is the value of str.
static int vgs_parse(void *log_ctx, struct VGSParser *parser, struct VGSProgram *program, int subprogram)
Build a program by parsing a script.
#define MAY_PRESERVE(funcname)
#define VAR_COUNT
Total number of variables (default- and user-variables).
static int drawvg_filter_frame(AVFilterLink *inlink, AVFrame *frame)
static void vgs_statement_free(struct VGSStatement *stm)
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.