Go to the documentation of this file.
76 #define USER_VAR_COUNT 20
79 #define VAR_COUNT (VAR_U0 + USER_VAR_COUNT)
116 static double vgs_fn_p(
void *,
double,
double);
204 {
"butt", CAIRO_LINE_CAP_BUTT },
205 {
"round", CAIRO_LINE_CAP_ROUND },
206 {
"square", CAIRO_LINE_CAP_SQUARE },
211 {
"bevel", CAIRO_LINE_JOIN_BEVEL },
212 {
"miter", CAIRO_LINE_JOIN_MITER },
213 {
"round", CAIRO_LINE_JOIN_ROUND },
239 #define MAX_COMMAND_PARAMS 8
245 #define MAX_PROC_ARGS (MAX_COMMAND_PARAMS - 2)
256 #define PARAMS(...) (const struct VGSParameter[]){ __VA_ARGS__ }
257 #define L(...) PARAMS(__VA_ARGS__, { PARAM_END })
258 #define R(...) PARAMS(__VA_ARGS__, { PARAM_MAY_REPEAT })
259 #define NONE PARAMS({ PARAM_END })
262 #define N { PARAM_NUMERIC }
263 #define V { PARAM_VAR_NAME }
264 #define P { PARAM_SUBPROGRAM }
265 #define C(c) { PARAM_CONSTANT, .constants = c }
284 {
"call",
CMD_PROC_CALL,
L({ PARAM_PROC_NAME }, { PARAM_PROC_ARGS }) },
306 {
"print",
CMD_PRINT,
L({ PARAM_NUMERIC_METADATA }, { PARAM_VARIADIC }) },
363 if (length >=
sizeof(bufname))
366 memcpy(bufname,
name, length);
367 bufname[length] =
'\0';
483 && str[token->
length] ==
'\0';
498 const char *sep = strchr(
source,
'\n');
511 void vgs_log_invalid_token(
515 const
char *extra_fmt,
525 va_start(ap, extra_fmt);
526 vsnprintf(extra,
sizeof(extra), extra_fmt, ap);
530 "Invalid token '%.*s' at line %zu, column %zu: %s\n",
531 (
int)token->length, token->lexeme,
line, column, extra);
547 #define WORD_SEPARATOR " \n\t\r,"
550 size_t cursor, length;
563 token->
type = TOKEN_EOF;
574 switch (
source[cursor + length]) {
577 vgs_log_invalid_token(log_ctx, parser, token,
"Unmatched parenthesis.");
592 token->
type = TOKEN_EXPR;
597 token->
type = TOKEN_LEFT_BRACKET;
602 token->
type = TOKEN_RIGHT_BRACKET;
619 token->
type = TOKEN_LITERAL;
628 if (
source[cursor + 1] ==
'/') {
629 parser->
cursor += cursor + strcspn(token->
lexeme,
"\n");
636 token->
type = TOKEN_WORD;
731 for (
int i = 0;
i <
program->statements_count;
i++)
737 for (
int i = 0;
i <
program->proc_names_count;
i++)
754 vgs_log_invalid_token(log_ctx, parser, token,
"Expected color.");
791 if (token.
length + 1 <
sizeof(stack_buf)) {
803 switch (token.
type) {
805 arg->type = ARG_LITERAL;
809 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected valid number.");
815 arg->type = ARG_EXPR;
829 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid expression.");
837 if (accept_colors &&
lexeme[0] ==
'#') {
849 arg->type = ARG_VARIABLE;
862 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected numeric argument.");
875 memset(
arg, 0,
sizeof(*
arg));
898 switch (token.
type) {
913 if (accept_colors && token.
lexeme[0] ==
'#')
939 for (
int i = 0;
i < token->
length;
i++) {
942 && !(
c >=
'a' &&
c <=
'z')
943 && !(
c >=
'A' &&
c <=
'Z')
944 && !(
i > 0 &&
c >=
'0' &&
c <=
'9')
966 vgs_statement_free(&statement); \
967 return AVERROR(err); \
978 int proc_args_count = 0;
987 switch (param->
type) {
1003 case PARAM_MAY_REPEAT:
1016 if (param->
type != PARAM_END
1019 param = &decl->
params[0];
1020 statement.args =
NULL;
1021 statement.args_count = 0;
1054 case PARAM_CONSTANT: {
1056 char expected_names[64] = { 0 };
1081 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected one of%s.", expected_names);
1088 case PARAM_PROC_ARGS:
1096 vgs_log_invalid_token(log_ctx, parser, &token,
1104 case PARAM_NUMERIC_COLOR:
1105 case PARAM_NUMERIC_METADATA:
1110 param->
type == PARAM_NUMERIC_METADATA,
1111 param->
type == PARAM_NUMERIC_COLOR || param->
type == PARAM_PROC_ARGS
1119 case PARAM_PROC_NAME: {
1127 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid procedure name.");
1160 case PARAM_RAW_IDENT:
1165 switch (token.
type) {
1173 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1179 case PARAM_SUBPROGRAM:
1184 if (token.
type != TOKEN_LEFT_BRACKET) {
1185 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1200 case PARAM_PROC_PARAMS:
1206 vgs_log_invalid_token(log_ctx, parser, &token,
1211 if (token.
type != TOKEN_WORD) {
1219 case PARAM_VAR_NAME: {
1238 if (var_idx == -1) {
1239 vgs_log_invalid_token(log_ctx, parser, &token,
1240 "Too many user variables. Can define up to %d variables.",
USER_VAR_COUNT);
1247 vgs_log_invalid_token(log_ctx, parser, &token,
"Reserved variable name.");
1254 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid variable name.");
1262 arg.constant = var_idx;
1271 (
void*)&statement.
args,
1280 switch (param->
type) {
1281 case PARAM_PROC_ARGS:
1282 case PARAM_PROC_PARAMS:
1343 switch (token.
type) {
1346 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '}'.");
1368 case TOKEN_RIGHT_BRACKET:
1382 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected command.");
1399 #define RANDOM_STATES 4
1481 int max_segments = (int)
arg;
1483 double lmx =
NAN, lmy =
NAN;
1484 double cx =
NAN, cy =
NAN;
1487 cairo_path_t *path = cairo_copy_path_flat(
state->cairo_ctx);
1489 for (
int i = 0;
i < path->num_data;
i += path->data[
i].header.length) {
1491 cairo_path_data_t *
data = &path->data[
i];
1494 case CAIRO_PATH_MOVE_TO:
1495 cx = lmx =
data[1].point.x;
1496 cy = lmy =
data[1].point.y;
1501 case CAIRO_PATH_LINE_TO:
1502 x =
data[1].point.x;
1503 y =
data[1].point.y;
1506 case CAIRO_PATH_CLOSE_PATH:
1515 length +=
hypot(cx - x, cy - y);
1522 if (--max_segments == 0)
1526 cairo_path_destroy(path);
1545 const uint64_t iarg = (uint64_t)
arg;
1570 cairo_user_to_device(
state->cairo_ctx, &x0, &y0);
1572 const int x = (int)x0;
1573 const int y = (int)y0;
1575 if (x < 0 || y < 0 || x >=
frame->width || y >=
frame->height)
1580 uint32_t
color[4] = { 0, 0, 0, 255 };
1582 for (
int c = 0;
c <
desc->nb_components;
c++) {
1596 const int depth =
desc->comp[
c].depth;
1620 state->last_fn_p_color.numeric = num;
1622 state->last_fn_p_color.components[
i] = (uint8_t)
color[
i];
1639 state->last_fn_p_color.numeric =
NAN;
1660 cairo_pattern_destroy(
state->pattern_builder);
1673 static void draw_ellipse(cairo_t *
c,
double x,
double y,
double rx,
double ry) {
1675 cairo_translate(
c, x, y);
1678 cairo_scale(
c, 1, ry / rx);
1680 cairo_new_sub_path(
c);
1681 cairo_arc(
c, 0, 0, rx, 0, 2 *
M_PI);
1682 cairo_close_path(
c);
1683 cairo_new_sub_path(
c);
1703 double x0 = 0, y0 = 0;
1704 double xa, ya, xb, yb;
1706 const int use_reflected =
isnan(x1);
1711 if (!use_reflected) {
1720 if (use_reflected) {
1722 x1 =
state->rcp.quad_x;
1723 y1 =
state->rcp.quad_y;
1730 xa = (x0 + 2 * x1) / 3;
1731 ya = (y0 + 2 * y1) / 3;
1732 xb = (x + 2 * x1) / 3;
1733 yb = (y + 2 * y1) / 3;
1734 cairo_curve_to(
state->cairo_ctx, xa, ya, xb, yb, x, y);
1737 state->rcp.cubic_x = x1;
1738 state->rcp.cubic_y = y1;
1739 state->rcp.quad_x = 2 * x - x1;
1740 state->rcp.quad_y = 2 * y - y1;
1754 double x0 = 0, y0 = 0;
1756 const int use_reflected =
isnan(x1);
1761 if (!use_reflected) {
1772 if (use_reflected) {
1774 x1 =
state->rcp.cubic_x;
1775 y1 =
state->rcp.cubic_y;
1782 cairo_curve_to(
state->cairo_ctx, x1, y1, x2, y2, x, y);
1785 state->rcp.cubic_x = 2 * x - x2;
1786 state->rcp.cubic_y = 2 * y - y2;
1787 state->rcp.quad_x = x2;
1788 state->rcp.quad_y = y2;
1801 cairo_new_sub_path(
c);
1802 cairo_arc(
c, x + radius, y + radius, radius,
M_PI, 3 *
M_PI / 2);
1803 cairo_arc(
c, x +
width - radius, y + radius, radius, 3 *
M_PI / 2, 2 *
M_PI);
1804 cairo_arc(
c, x +
width - radius, y +
height - radius, radius, 0,
M_PI / 2);
1805 cairo_arc(
c, x + radius, y +
height - radius, radius,
M_PI / 2,
M_PI);
1806 cairo_close_path(
c);
1821 if (h < 0 || h >= 360)
1831 switch ((
int)
floor(h1)) {
1888 #define ASSERT_ARGS(n) av_assert0(statement->args_count == n)
1892 #define MAY_PRESERVE(funcname) \
1894 if (state->preserve_path) { \
1895 state->preserve_path = 0; \
1896 funcname##_preserve(state->cairo_ctx); \
1898 funcname(state->cairo_ctx); \
1909 for (
int st_number = 0; st_number <
program->statements_count; st_number++) {
1942 numerics[
arg] =
a->literal;
1947 numerics[
arg] =
state->vars[
a->variable];
1966 switch (statement->
cmd) {
1973 cairo_pattern_destroy(
state->pattern_builder);
1979 switch (statement->
cmd) {
2006 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[2]);
2012 cairo_set_fill_rule(
2015 CAIRO_FILL_RULE_WINDING :
2016 CAIRO_FILL_RULE_EVEN_ODD
2024 cairo_close_path(
state->cairo_ctx);
2034 cairo_pattern_add_color_stop_rgba(
2035 state->pattern_builder,
2069 hsl2rgb(numerics[1], numerics[2], numerics[3], &
r, &
g, &
b);
2076 double *
const color_var =
state->color_vars[user_var -
VAR_U0];
2080 color_var[3] = numerics[4];
2087 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2094 cairo_set_fill_rule(
2097 CAIRO_FILL_RULE_WINDING :
2098 CAIRO_FILL_RULE_EVEN_ODD
2131 state->interrupted = 1;
2137 if (
isfinite(numerics[0]) && numerics[0] != 0.0) {
2139 if (
ret != 0 ||
state->interrupted != 0)
2149 cairo_pattern_destroy(
state->pattern_builder);
2151 state->pattern_builder = cairo_pattern_create_linear(
2161 cairo_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2166 cairo_rel_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2171 cairo_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2176 cairo_rel_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2181 cairo_new_sub_path(
state->cairo_ctx);
2186 state->preserve_path = 1;
2195 int capacity =
sizeof(msg) -
len;
2207 if (written >= capacity)
2220 const int proc_args = statement->
args_count - 2;
2228 proc->
args[
i] = i < proc_args ? statement->
args[
i + 1].constant : -1;
2234 const int proc_args = statement->
args_count - 1;
2245 "Procedure expects %d arguments, but received %d.",
2254 const char *proc_name =
state->proc_names[proc_id];
2256 "Missing body for procedure '%s'\n", proc_name);
2262 for (
int i = 0;
i < proc_args;
i++) {
2263 const int var = proc->
args[
i];
2267 const int color_var = var -
VAR_U0;
2271 current_vars[
i] =
state->vars[var];
2274 state->vars[var] = numerics[
i + 1];
2281 for (
int i = 0;
i < proc_args;
i++) {
2282 const int var = proc->
args[
i];
2286 const int color_var = var -
VAR_U0;
2289 state->vars[var] = current_vars[
i];
2296 if (
state->interrupted) {
2297 state->interrupted = 0;
2323 cairo_pattern_destroy(
state->pattern_builder);
2325 state->pattern_builder = cairo_pattern_create_radial(
2336 cairo_reset_clip(
state->cairo_ctx);
2344 cairo_identity_matrix(
state->cairo_ctx);
2349 cairo_rectangle(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2360 for (
int i = 0, count = (
int)numerics[0];
i < count;
i++) {
2368 if (
state->interrupted) {
2369 state->interrupted = 0;
2380 cairo_restore(
state->cairo_ctx);
2385 cairo_rotate(
state->cairo_ctx, numerics[0]);
2402 cairo_save(
state->cairo_ctx);
2407 cairo_scale(
state->cairo_ctx, numerics[0], numerics[0]);
2412 cairo_scale(
state->cairo_ctx, numerics[0], numerics[1]);
2419 cairo_pattern_destroy(
state->pattern_builder);
2421 state->pattern_builder = cairo_pattern_create_rgba(
2441 cairo_set_line_width(
state->cairo_ctx, numerics[0]);
2447 double *dashes,
offset, stack_buf[16];
2456 dashes =
av_calloc(num + 1,
sizeof(
double));
2465 dashes[num] = numerics[0];
2473 if (dashes != stack_buf)
2486 cairo_pattern_destroy(
state->pattern_builder);
2489 hsl2rgb(numerics[0], numerics[1], numerics[2], &
r, &
g, &
b);
2496 state->pattern_builder = cairo_pattern_create_rgba(
r,
g,
b, numerics[3]);
2506 state->vars[user_var] = numerics[1];
2510 if (
state->last_fn_p_color.numeric == numerics[1]) {
2512 (*
color)[
i] =
state->last_fn_p_color.components[
i] / 255.0;
2542 cairo_translate(
state->cairo_ctx, numerics[0], numerics[1]);
2559 double d = numerics[0];
2561 switch (statement->
cmd) {
2568 cairo_line_to(
state->cairo_ctx, cx, cy);
2577 if (
state->rcp.status == RCP_UPDATED) {
2578 state->rcp.status = RCP_VALID;
2580 state->rcp.status = RCP_NONE;
2588 "Error in cairo context: %s\n",
2626 #define OPT(name, field, help) \
2630 offsetof(DrawVGContext, field), \
2631 AV_OPT_TYPE_STRING, \
2634 AV_OPT_FLAG_FILTERING_PARAM \
2635 | AV_OPT_FLAG_VIDEO_PARAM \
2639 OPT(
"script", script_text,
"script source to draw the graphics"),
2640 OPT(
"s", script_text,
"script source to draw the graphics"),
2641 OPT(
"file", script_file,
"file to load the script source"),
2665 CAIRO_FORMAT_ARGB32,
2667 CAIRO_FORMAT_RGB16_565,
2669 CAIRO_FORMAT_INVALID,
2680 return CAIRO_FORMAT_INVALID;
2686 cairo_surface_t* surface;
2700 surface = cairo_image_surface_create_for_data(
2708 if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
2713 eval_state.
cairo_ctx = cairo_create(surface);
2732 cairo_surface_destroy(surface);
2761 drawvg->time_start =
NAN;
2763 if ((drawvg->script_text ==
NULL) == (drawvg->script_file ==
NULL)) {
2765 "Either 'source' or 'file' must be provided\n");
2770 if (drawvg->script_file !=
NULL) {
2773 (
const char *)drawvg->script_file,
2774 &drawvg->script_text,
2809 .p.priv_class = &drawvg_class,
FFSFC64 random_state[RANDOM_STATES]
State for each index available for the randomg function.
static const AVFilterPad drawvg_inputs[]
AVPixelFormat
Pixel format.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
@ CMD_PROC_ASSIGN
proc name varnames* { subprogram }
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C program
enum VGSParameter::@387 type
#define MAX_COMMAND_PARAMS
static const AVOption drawvg_options[]
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
@ CMD_COLOR_STOP
colorstop (offset color)
int args[MAX_PROC_ARGS]
Variable ids where each argument is stored.
void cairo_set_dash(cairo_t *cr, const double *dashes, int num_dashes, double offset)
@ VAR_T
Timestamp in seconds.
@ CMD_DEF_RGBA
defrgba (varname r g b a)
AVFILTER_DEFINE_CLASS(drawvg)
#define FILTER_PIXFMTS_ARRAY(array)
@ VAR_CX
X coordinate for current point.
static const char *const vgs_default_vars[]
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
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.
static int vgs_eval(struct VGSEvalState *state, const struct VGSProgram *program)
Interpreter for VGSProgram.
@ CMD_Q_CURVE_TO
Q (x1 y1 x y)
static void vgs_statement_free(struct VGSStatement *stm)
static double vgs_fn_pathlen(void *, double)
Function pathlen(n) for av_expr_eval.
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
char * av_asprintf(const char *fmt,...)
@ CMD_ARC_NEG
arcn (cx cy radius angle1 angle2)
@ CMD_ROTATE
rotate (angle)
AVDictionary * metadata
Frame metadata, if any.
#define FILTER_INPUTS(array)
@ CMD_SCALEXY
scalexy (sx sy)
This structure describes decoded (raw) audio or video data.
@ CMD_RECT
rect (x y width height)
static av_cold int drawvg_init(AVFilterContext *ctx)
enum VGSArgument::@389 type
static int vgs_comp_command_spec(const void *cs1, const void *cs2)
Comparator for VGSCommandDecl, to be used with bsearch(3).
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.
uint8_t * script_text
Inline source.
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.
@ CMD_T_CURVE_TO_REL
t (dx dy)
enum VGSEvalState::@393::@394 status
static int drawvg_config_props(AVFilterLink *inlink)
static av_always_inline void color_reset(cairo_color *const dest)
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.
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.
@ CMD_ARC
arc (cx cy radius angle1 angle2)
static int vgs_parser_next_token(void *log_ctx, struct VGSParser *parser, struct VGSParserToken *token, int advance)
Return the next token in the source.
struct VGSArgument * args
const char * name
Filter name.
@ CMD_MOVE_TO
M, moveto (x y)
static const struct VGSConstant vgs_consts_line_join[]
int preserve_path
Next call to [eo]fill, [eo]clip, or stroke, should use the _preserve function.
A link between two filters.
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
@ CMD_SET_LINE_CAP
setlinecap (cap)
#define OPT(name, field, help)
static cairo_format_t cairo_format_from_pix_fmt(DrawVGContext *ctx, enum AVPixelFormat format)
static void vgs_parser_free(struct VGSParser *parser)
Link properties exposed to filter code, but not external callers.
@ CMD_RESET_CLIP
resetclip
@ CMD_IF
if (condition) { subprogram }
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.
struct VGSProgram * subprogram
struct VGSProcedure * procedures
Subprograms associated to each procedure identifier.
cairo_bool_t cairo_get_dash_count(cairo_t *cr)
@ CMD_SET_DASH
setdash (length)
@ CMD_SET_RGBA
setrgba (r g b a)
static double(*const vgs_func2_impls[])(void *, double, double)
Constants for some commands, like setlinejoin.
@ CMD_RESET_MATRIX
resetmatrix
static av_cold void drawvg_uninit(AVFilterContext *ctx)
static double vgs_fn_randomg(void *, double)
Function randomg(n) for av_expr_eval.
static FilteringContext * filter_ctx
@ CMD_MOVE_TO_REL
m, rmoveto (dx dy)
static int vgs_token_is_string(const struct VGSParserToken *token, const char *str)
Check if token is the value of str.
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
A filter pad used for either input or output.
#define VAR_COUNT
Total number of variables (default- and user-variables).
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),...
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
@ CMD_CIRCLE
circle (cx cy radius)
int ff_load_textfile(void *log_ctx, const char *textfile, unsigned char **text, size_t *text_size)
@ VAR_CY
Y coordinate for current point.
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
const FFFilter ff_vf_drawvg
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
double cairo_color[4]
Colors in cairo are defined by 4 values, between 0 and 1.
@ CMD_Q_CURVE_TO_REL
q (dx1 dy1 dx dy)
static __device__ float floor(float a)
enum VGSParserToken::@388 type
static double av_q2d(AVRational a)
Convert an AVRational to a double.
static int vgs_is_valid_identifier(const struct VGSParserToken *token)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
void cairo_set_source(cairo_t *cr, cairo_pattern_t *source)
#define FILTER_OUTPUTS(array)
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.
static void vgs_free(struct VGSProgram *program)
Release the memory allocated by the program.
cairo_bool_t cairo_has_current_point(cairo_t *cr)
@ CMD_LINE_TO_REL
l, rlineto (dx dy)
Describe the class of an AVClass context structure.
static __device__ float fabs(float a)
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
void cairo_get_dash(cairo_t *cr, double *dashes, double *offset)
double vars[VAR_COUNT]
Values for the variables in expressions.
@ CMD_CURVE_TO_REL
c, rcurveto (dx1 dy1 dx2 dy2 dx dy)
static double(*const vgs_func1_impls[])(void *, double)
static int vgs_parse(void *log_ctx, struct VGSParser *parser, struct VGSProgram *program, int subprogram)
Build a program by parsing a script.
@ CMD_S_CURVE_TO
S (x2 y2 x y)
cairo_pattern_t * pattern_builder
Pattern being built by commands like colorstop.
struct VGSEvalState::@392 last_fn_p_color
Track last color read by the p() function.
static void draw_ellipse(cairo_t *c, double x, double y, double rx, double ry)
Draw an ellipse.
@ CMD_REPEAT
repeat (count) { subprogram }
static av_always_inline void color_copy(cairo_color *dest, const cairo_color *src)
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
@ VAR_DURATION
Frame duration.
static FilterLink * ff_filter_link(AVFilterLink *link)
uint8_t * script_file
File path to load the source.
static int vgs_parse_color(void *log_ctx, struct VGSArgument *arg, const struct VGSParser *parser, const struct VGSParserToken *token)
@ CMD_SET_VAR
setvar (varname value)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a source
void cairo_get_current_point(cairo_t *cr, double *x, double *y)
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
static IPT relative(const CmsCtx *ctx, IPT ipt)
double time_start
Time in seconds of the first frame.
int(* init)(AVBSFContext *ctx)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
int interrupted
Register if break was called in a subprogram.
const struct VGSParameter * params
static av_const double hypot(double x, double y)
@ CMD_ELLIPSE
ellipse (cx cy rx ry)
static int drawvg_filter_frame(AVFilterLink *inlink, AVFrame *frame)
static const uint8_t header[24]
static int vgs_eval_state_init(struct VGSEvalState *state, const struct VGSProgram *program, void *log_ctx, AVFrame *frame)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
cairo_t * cairo_ctx
Cairo context for drawing operations.
#define AVERROR_EXTERNAL
Generic error in an external library.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
static const struct VGSConstant vgs_consts_line_cap[]
#define AV_LOG_INFO
Standard information.
@ CMD_SET_COLOR
setcolor (color)
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
@ CMD_RADIAL_GRAD
radialgrad (cx0 cy0 radius0 cx1 cy1 radius1)
static int vgs_cmd_change_path(enum VGSCommand cmd)
Return 1 if the command changes the current path in the cairo context.
static void uninit(AVBSFContext *ctx)
@ CMD_S_CURVE_TO_REL
s (dx2 dy2 dx dy)
struct VGSStatement * statements
#define i(width, name, range_min, range_max)
static double vgs_fn_p(void *, double, double)
Function p(x, y) for av_expr_eval.
AVFrame * frame
Current frame.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
@ CMD_GET_METADATA
getmetadata varname key
#define AV_PIX_FMT_X2RGB10
#define USER_VAR_COUNT
Number of user variables that can be created with setvar.
@ CMD_LINEAR_GRAD
lineargrad (x0 y0 x1 y1)
const char * name
Pad name.
Block assigned to a procedure by a call to the proc command.
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,...
struct VGSProgram program
@ CMD_RESET_DASH
resetdash
void * av_calloc(size_t nmemb, size_t size)
static uint64_t ff_sfc64_get(FFSFC64 *s)
#define AV_PIX_FMT_RGB565
@ VAR_TS
Time in seconds of the first frame.
@ CMD_SET_LINE_JOIN
setlinejoin (join)
@ CMD_CURVE_TO
C, curveto (x1 y1 x2 y2 x y)
static const char *const vgs_func2_names[]
struct VGSEvalState::@393 rcp
static enum AVPixelFormat drawvg_pix_fmts[]
#define FFSWAP(type, a, b)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
double av_strtod(const char *numstr, char **tail)
Parse the string in numstr and return its value as a double.
#define AV_PIX_FMT_0RGB32
void * av_malloc(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
@ CMD_SET_LINE_WIDTH
setlinewidth (width)
static void vgs_eval_state_free(struct VGSEvalState *state)
@ CMD_SET_DASH_OFFSET
setdashoffset (offset)
@ CMD_ROUNDEDRECT
roundedrect (x y width height radius)
static av_printf_format(4, 5)
const struct VGSProgram * program
@ CMD_DEF_HSLA
defhsla (varname h s l a)
const FormatMap format_map[]
const char * var_names[VAR_COUNT+1]
@ VAR_I
Loop counter, to use with repeat {}.
cairo_status_t cairo_status(cairo_t *cr)
@ CMD_TRANSLATE
translate (tx ty)
AVFilter p
The public AVFilter.
static const struct VGSCommandSpec vgs_commands[]
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.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
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.
@ CMD_PROC_CALL
call name (expr)*
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define MAY_PRESERVE(funcname)
const char *const * proc_names
Reference to the procedure names in the VGSProgram.
const struct VGSConstant * constants
Array for PARAM_CONSTANT.
#define RANDOM_STATES
Number of different states for the randomg function.
@ CMD_SET_HSLA
sethsla (h s l a)
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
static void draw_rounded_rect(cairo_t *c, double x, double y, double width, double height, double radius)
static void hsl2rgb(double h, double s, double l, double *pr, double *pg, double *pb)
cairo_color color_vars[USER_VAR_COUNT]
Colors stored in variables.
cairo_format_t cairo_format
Equivalent to AVPixelFormat.
@ CMD_LINE_TO
L, lineto (x y)
static void vgs_parser_init(struct VGSParser *parser, const char *source)
static const char *const vgs_func1_names[]
int proc_args_count
Number of expected arguments.
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common like for each output line the vertical scaler pulls lines from a ring buffer When the ring buffer does not contain the wanted line
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.
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.
@ CMD_CLOSE_PATH
Z, z, closepath.