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)
247 #define VGS_MAX_RECURSION_DEPTH 100
258 #define PARAMS(...) (const struct VGSParameter[]){ __VA_ARGS__ }
259 #define L(...) PARAMS(__VA_ARGS__, { PARAM_END })
260 #define R(...) PARAMS(__VA_ARGS__, { PARAM_MAY_REPEAT })
261 #define NONE PARAMS({ PARAM_END })
264 #define N { PARAM_NUMERIC }
265 #define V { PARAM_VAR_NAME }
266 #define P { PARAM_SUBPROGRAM }
267 #define C(c) { PARAM_CONSTANT, .constants = c }
286 {
"call",
CMD_PROC_CALL,
L({ PARAM_PROC_NAME }, { PARAM_PROC_ARGS }) },
308 {
"print",
CMD_PRINT,
L({ PARAM_NUMERIC_METADATA }, { PARAM_VARIADIC }) },
365 if (length >=
sizeof(bufname))
368 memcpy(bufname,
name, length);
369 bufname[length] =
'\0';
486 && str[token->
length] ==
'\0';
501 const char *sep = strchr(
source,
'\n');
514 void vgs_log_invalid_token(
518 const
char *extra_fmt,
528 va_start(ap, extra_fmt);
529 vsnprintf(extra,
sizeof(extra), extra_fmt, ap);
533 "Invalid token '%.*s' at line %zu, column %zu: %s\n",
534 (
int)token->length, token->lexeme,
line, column, extra);
550 #define WORD_SEPARATOR " \n\t\r,"
553 size_t cursor, length;
566 token->
type = TOKEN_EOF;
577 switch (
source[cursor + length]) {
580 vgs_log_invalid_token(log_ctx, parser, token,
"Unmatched parenthesis.");
595 token->
type = TOKEN_EXPR;
600 token->
type = TOKEN_LEFT_BRACKET;
605 token->
type = TOKEN_RIGHT_BRACKET;
622 token->
type = TOKEN_LITERAL;
631 if (
source[cursor + 1] ==
'/') {
632 parser->
cursor += cursor + strcspn(token->
lexeme,
"\n");
639 token->
type = TOKEN_WORD;
734 for (
int i = 0;
i <
program->statements_count;
i++)
740 for (
int i = 0;
i <
program->proc_names_count;
i++)
757 vgs_log_invalid_token(log_ctx, parser, token,
"Expected color.");
794 if (token.
length + 1 <
sizeof(stack_buf)) {
806 switch (token.
type) {
808 arg->type = ARG_LITERAL;
812 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected valid number.");
818 arg->type = ARG_EXPR;
832 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid expression.");
840 if (accept_colors &&
lexeme[0] ==
'#') {
852 arg->type = ARG_VARIABLE;
865 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected numeric argument.");
878 memset(
arg, 0,
sizeof(*
arg));
901 switch (token.
type) {
916 if (accept_colors && token.
lexeme[0] ==
'#')
942 for (
int i = 0;
i < token->
length;
i++) {
945 && !(
c >=
'a' &&
c <=
'z')
946 && !(
c >=
'A' &&
c <=
'Z')
947 && !(
i > 0 &&
c >=
'0' &&
c <=
'9')
969 vgs_statement_free(&statement); \
970 return AVERROR(err); \
981 int proc_args_count = 0;
990 switch (param->
type) {
1006 case PARAM_MAY_REPEAT:
1019 if (param->
type != PARAM_END
1022 param = &decl->
params[0];
1023 statement.args =
NULL;
1024 statement.args_count = 0;
1057 case PARAM_CONSTANT: {
1059 char expected_names[64] = { 0 };
1084 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected one of%s.", expected_names);
1091 case PARAM_PROC_ARGS:
1099 vgs_log_invalid_token(log_ctx, parser, &token,
1107 case PARAM_NUMERIC_COLOR:
1108 case PARAM_NUMERIC_METADATA:
1113 param->
type == PARAM_NUMERIC_METADATA,
1114 param->
type == PARAM_NUMERIC_COLOR || param->
type == PARAM_PROC_ARGS
1122 case PARAM_PROC_NAME: {
1130 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid procedure name.");
1163 case PARAM_RAW_IDENT:
1168 switch (token.
type) {
1176 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1182 case PARAM_SUBPROGRAM:
1187 if (token.
type != TOKEN_LEFT_BRACKET) {
1188 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1203 case PARAM_PROC_PARAMS:
1209 vgs_log_invalid_token(log_ctx, parser, &token,
1214 if (token.
type != TOKEN_WORD) {
1222 case PARAM_VAR_NAME: {
1241 if (var_idx == -1) {
1242 vgs_log_invalid_token(log_ctx, parser, &token,
1243 "Too many user variables. Can define up to %d variables.",
USER_VAR_COUNT);
1250 vgs_log_invalid_token(log_ctx, parser, &token,
"Reserved variable name.");
1257 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid variable name.");
1265 arg.constant = var_idx;
1274 (
void*)&statement.
args,
1283 switch (param->
type) {
1284 case PARAM_PROC_ARGS:
1285 case PARAM_PROC_PARAMS:
1343 "Exceeded maximum drawvg block nesting depth (%d)\n",
1355 switch (token.
type) {
1358 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '}'.");
1380 case TOKEN_RIGHT_BRACKET:
1395 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected command.");
1416 #define RANDOM_STATES 4
1498 int max_segments = (int)
arg;
1500 double lmx =
NAN, lmy =
NAN;
1501 double cx =
NAN, cy =
NAN;
1504 cairo_path_t *path = cairo_copy_path_flat(
state->cairo_ctx);
1506 for (
int i = 0;
i < path->num_data;
i += path->data[
i].header.length) {
1508 cairo_path_data_t *
data = &path->data[
i];
1511 case CAIRO_PATH_MOVE_TO:
1512 cx = lmx =
data[1].point.x;
1513 cy = lmy =
data[1].point.y;
1518 case CAIRO_PATH_LINE_TO:
1519 x =
data[1].point.x;
1520 y =
data[1].point.y;
1523 case CAIRO_PATH_CLOSE_PATH:
1532 length +=
hypot(cx - x, cy - y);
1539 if (--max_segments == 0)
1543 cairo_path_destroy(path);
1562 const uint64_t iarg = (uint64_t)
arg;
1587 cairo_user_to_device(
state->cairo_ctx, &x0, &y0);
1589 const int x = (int)x0;
1590 const int y = (int)y0;
1592 if (x < 0 || y < 0 || x >=
frame->width || y >=
frame->height)
1597 uint32_t
color[4] = { 0, 0, 0, 255 };
1599 for (
int c = 0;
c <
desc->nb_components;
c++) {
1613 const int depth =
desc->comp[
c].depth;
1637 state->last_fn_p_color.numeric = num;
1639 state->last_fn_p_color.components[
i] = (uint8_t)
color[
i];
1656 state->last_fn_p_color.numeric =
NAN;
1677 cairo_pattern_destroy(
state->pattern_builder);
1690 static void draw_ellipse(cairo_t *
c,
double x,
double y,
double rx,
double ry) {
1692 cairo_translate(
c, x, y);
1695 cairo_scale(
c, 1, ry / rx);
1697 cairo_new_sub_path(
c);
1698 cairo_arc(
c, 0, 0, rx, 0, 2 *
M_PI);
1699 cairo_close_path(
c);
1700 cairo_new_sub_path(
c);
1720 double x0 = 0, y0 = 0;
1721 double xa, ya, xb, yb;
1723 const int use_reflected =
isnan(x1);
1728 if (!use_reflected) {
1737 if (use_reflected) {
1739 x1 =
state->rcp.quad_x;
1740 y1 =
state->rcp.quad_y;
1747 xa = (x0 + 2 * x1) / 3;
1748 ya = (y0 + 2 * y1) / 3;
1749 xb = (x + 2 * x1) / 3;
1750 yb = (y + 2 * y1) / 3;
1751 cairo_curve_to(
state->cairo_ctx, xa, ya, xb, yb, x, y);
1754 state->rcp.cubic_x = x1;
1755 state->rcp.cubic_y = y1;
1756 state->rcp.quad_x = 2 * x - x1;
1757 state->rcp.quad_y = 2 * y - y1;
1771 double x0 = 0, y0 = 0;
1773 const int use_reflected =
isnan(x1);
1778 if (!use_reflected) {
1789 if (use_reflected) {
1791 x1 =
state->rcp.cubic_x;
1792 y1 =
state->rcp.cubic_y;
1799 cairo_curve_to(
state->cairo_ctx, x1, y1, x2, y2, x, y);
1802 state->rcp.cubic_x = 2 * x - x2;
1803 state->rcp.cubic_y = 2 * y - y2;
1804 state->rcp.quad_x = x2;
1805 state->rcp.quad_y = y2;
1818 cairo_new_sub_path(
c);
1819 cairo_arc(
c, x + radius, y + radius, radius,
M_PI, 3 *
M_PI / 2);
1820 cairo_arc(
c, x +
width - radius, y + radius, radius, 3 *
M_PI / 2, 2 *
M_PI);
1821 cairo_arc(
c, x +
width - radius, y +
height - radius, radius, 0,
M_PI / 2);
1822 cairo_arc(
c, x + radius, y +
height - radius, radius,
M_PI / 2,
M_PI);
1823 cairo_close_path(
c);
1838 if (h < 0 || h >= 360)
1848 switch ((
int)
floor(h1)) {
1911 #define ASSERT_ARGS(n) av_assert0(statement->args_count == n)
1915 #define MAY_PRESERVE(funcname) \
1917 if (state->preserve_path) { \
1918 state->preserve_path = 0; \
1919 funcname##_preserve(state->cairo_ctx); \
1921 funcname(state->cairo_ctx); \
1932 for (
int st_number = 0; st_number <
program->statements_count; st_number++) {
1965 numerics[
arg] =
a->literal;
1970 numerics[
arg] =
state->vars[
a->variable];
1989 switch (statement->
cmd) {
1996 cairo_pattern_destroy(
state->pattern_builder);
2002 switch (statement->
cmd) {
2029 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[2]);
2035 cairo_set_fill_rule(
2038 CAIRO_FILL_RULE_WINDING :
2039 CAIRO_FILL_RULE_EVEN_ODD
2047 cairo_close_path(
state->cairo_ctx);
2057 cairo_pattern_add_color_stop_rgba(
2058 state->pattern_builder,
2092 hsl2rgb(numerics[1], numerics[2], numerics[3], &
r, &
g, &
b);
2099 double *
const color_var =
state->color_vars[user_var -
VAR_U0];
2103 color_var[3] = numerics[4];
2110 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2117 cairo_set_fill_rule(
2120 CAIRO_FILL_RULE_WINDING :
2121 CAIRO_FILL_RULE_EVEN_ODD
2154 state->interrupted = 1;
2160 if (
isfinite(numerics[0]) && numerics[0] != 0.0) {
2163 if (
ret != 0 ||
state->interrupted != 0)
2173 cairo_pattern_destroy(
state->pattern_builder);
2175 state->pattern_builder = cairo_pattern_create_linear(
2185 cairo_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2190 cairo_rel_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2195 cairo_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2200 cairo_rel_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2205 cairo_new_sub_path(
state->cairo_ctx);
2210 state->preserve_path = 1;
2219 int capacity =
sizeof(msg) -
len;
2231 if (written >= capacity)
2244 const int proc_args = statement->
args_count - 2;
2252 proc->
args[
i] = i < proc_args ? statement->
args[
i + 1].constant : -1;
2258 const int proc_args = statement->
args_count - 1;
2269 "Procedure expects %d arguments, but received %d.",
2278 const char *proc_name =
state->proc_names[proc_id];
2280 "Missing body for procedure '%s'\n", proc_name);
2286 for (
int i = 0;
i < proc_args;
i++) {
2287 const int var = proc->
args[
i];
2291 const int color_var = var -
VAR_U0;
2295 current_vars[
i] =
state->vars[var];
2298 state->vars[var] = numerics[
i + 1];
2305 for (
int i = 0;
i < proc_args;
i++) {
2306 const int var = proc->
args[
i];
2310 const int color_var = var -
VAR_U0;
2313 state->vars[var] = current_vars[
i];
2320 if (
state->interrupted) {
2321 state->interrupted = 0;
2347 cairo_pattern_destroy(
state->pattern_builder);
2349 state->pattern_builder = cairo_pattern_create_radial(
2360 cairo_reset_clip(
state->cairo_ctx);
2368 cairo_identity_matrix(
state->cairo_ctx);
2373 cairo_rectangle(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2384 for (
int i = 0, count = (
int)numerics[0];
i < count;
i++) {
2392 if (
state->interrupted) {
2393 state->interrupted = 0;
2404 cairo_restore(
state->cairo_ctx);
2409 cairo_rotate(
state->cairo_ctx, numerics[0]);
2426 cairo_save(
state->cairo_ctx);
2431 cairo_scale(
state->cairo_ctx, numerics[0], numerics[0]);
2436 cairo_scale(
state->cairo_ctx, numerics[0], numerics[1]);
2443 cairo_pattern_destroy(
state->pattern_builder);
2445 state->pattern_builder = cairo_pattern_create_rgba(
2465 cairo_set_line_width(
state->cairo_ctx, numerics[0]);
2471 double *dashes,
offset, stack_buf[16];
2480 dashes =
av_calloc(num + 1,
sizeof(
double));
2489 dashes[num] = numerics[0];
2497 if (dashes != stack_buf)
2510 cairo_pattern_destroy(
state->pattern_builder);
2513 hsl2rgb(numerics[0], numerics[1], numerics[2], &
r, &
g, &
b);
2520 state->pattern_builder = cairo_pattern_create_rgba(
r,
g,
b, numerics[3]);
2530 state->vars[user_var] = numerics[1];
2534 if (
state->last_fn_p_color.numeric == numerics[1]) {
2536 (*
color)[
i] =
state->last_fn_p_color.components[
i] / 255.0;
2566 cairo_translate(
state->cairo_ctx, numerics[0], numerics[1]);
2583 double d = numerics[0];
2585 switch (statement->
cmd) {
2592 cairo_line_to(
state->cairo_ctx, cx, cy);
2601 if (
state->rcp.status == RCP_UPDATED) {
2602 state->rcp.status = RCP_VALID;
2604 state->rcp.status = RCP_NONE;
2612 "Error in cairo context: %s\n",
2650 #define OPT(name, field, help) \
2654 offsetof(DrawVGContext, field), \
2655 AV_OPT_TYPE_STRING, \
2658 AV_OPT_FLAG_FILTERING_PARAM \
2659 | AV_OPT_FLAG_VIDEO_PARAM \
2663 OPT(
"script", script_text,
"script source to draw the graphics"),
2664 OPT(
"s", script_text,
"script source to draw the graphics"),
2665 OPT(
"file", script_file,
"file to load the script source"),
2689 CAIRO_FORMAT_ARGB32,
2691 CAIRO_FORMAT_RGB16_565,
2693 CAIRO_FORMAT_INVALID,
2704 return CAIRO_FORMAT_INVALID;
2710 cairo_surface_t* surface;
2724 surface = cairo_image_surface_create_for_data(
2732 if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
2737 eval_state.
cairo_ctx = cairo_create(surface);
2756 cairo_surface_destroy(surface);
2785 drawvg->time_start =
NAN;
2787 if ((drawvg->script_text ==
NULL) == (drawvg->script_file ==
NULL)) {
2789 "Either 'source' or 'file' must be provided\n");
2794 if (drawvg->script_file !=
NULL) {
2797 (
const char *)drawvg->script_file,
2798 &drawvg->script_text,
2833 .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
#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)
@ CMD_DEF_RGBA
defrgba (varname r g b a)
AVFILTER_DEFINE_CLASS(drawvg)
#define FILTER_PIXFMTS_ARRAY(array)
enum VGSParameter::@391 type
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.
@ 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)
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)
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_T
Timestamp in seconds.
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)
enum VGSArgument::@393 type
@ VAR_CX
X coordinate for current point.
static __device__ float floor(float a)
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.
static int vgs_eval(struct VGSEvalState *state, const struct VGSProgram *program, int stack_level)
Interpreter for VGSProgram.
static AVFormatContext * ctx
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)
struct VGSEvalState::@396 last_fn_p_color
Track last color read by the p() function.
cairo_pattern_t * pattern_builder
Pattern being built by commands like colorstop.
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
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)
enum VGSEvalState::@397::@398 status
#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
@ VAR_CY
Y coordinate for current point.
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 VGS_MAX_RECURSION_DEPTH
enum VGSParserToken::@392 type
#define AV_PIX_FMT_RGB565
@ VAR_DURATION
Frame duration.
@ CMD_SET_LINE_JOIN
setlinejoin (join)
@ CMD_CURVE_TO
C, curveto (x1 y1 x2 y2 x y)
@ VAR_TS
Time in seconds of the first frame.
static const char *const vgs_func2_names[]
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]
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.
@ VAR_I
Loop counter, to use with repeat {}.
const struct VGSConstant * constants
Array for PARAM_CONSTANT.
struct VGSEvalState::@397 rcp
#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.