Go to the documentation of this file.
75 #define USER_VAR_COUNT 20
78 #define VAR_COUNT (VAR_U0 + USER_VAR_COUNT)
115 static double vgs_fn_p(
void *,
double,
double);
203 {
"butt", CAIRO_LINE_CAP_BUTT },
204 {
"round", CAIRO_LINE_CAP_ROUND },
205 {
"square", CAIRO_LINE_CAP_SQUARE },
210 {
"bevel", CAIRO_LINE_JOIN_BEVEL },
211 {
"miter", CAIRO_LINE_JOIN_MITER },
212 {
"round", CAIRO_LINE_JOIN_ROUND },
237 #define MAX_COMMAND_PARAMS 8
243 #define MAX_PROC_ARGS (MAX_COMMAND_PARAMS - 2)
254 #define PARAMS(...) (const struct VGSParameter[]){ __VA_ARGS__ }
255 #define L(...) PARAMS(__VA_ARGS__, { PARAM_END })
256 #define R(...) PARAMS(__VA_ARGS__, { PARAM_MAY_REPEAT })
257 #define NONE PARAMS({ PARAM_END })
260 #define N { PARAM_NUMERIC }
261 #define V { PARAM_VAR_NAME }
262 #define P { PARAM_SUBPROGRAM }
263 #define C(c) { PARAM_CONSTANT, .constants = c }
282 {
"call",
CMD_PROC_CALL,
L({ PARAM_PROC_NAME }, { PARAM_PROC_ARGS }) },
304 {
"print",
CMD_PRINT,
L({ PARAM_NUMERIC_METADATA }, { PARAM_VARIADIC }) },
361 if (length >=
sizeof(bufname))
364 memcpy(bufname,
name, length);
365 bufname[length] =
'\0';
465 && str[token->
length] ==
'\0';
480 const char *sep = strchr(
source,
'\n');
493 void vgs_log_invalid_token(
497 const
char *extra_fmt,
507 va_start(ap, extra_fmt);
508 vsnprintf(extra,
sizeof(extra), extra_fmt, ap);
512 "Invalid token '%.*s' at line %zu, column %zu: %s\n",
513 (
int)token->length, token->lexeme,
line, column, extra);
529 #define WORD_SEPARATOR " \n\t\r,"
532 size_t cursor, length;
545 token->
type = TOKEN_EOF;
556 switch (
source[cursor + length]) {
559 vgs_log_invalid_token(log_ctx, parser, token,
"Unmatched parenthesis.");
574 token->
type = TOKEN_EXPR;
579 token->
type = TOKEN_LEFT_BRACKET;
584 token->
type = TOKEN_RIGHT_BRACKET;
601 token->
type = TOKEN_LITERAL;
610 if (
source[cursor + 1] ==
'/') {
611 parser->
cursor += cursor + strcspn(token->
lexeme,
"\n");
618 token->
type = TOKEN_WORD;
710 for (
int i = 0;
i <
program->statements_count;
i++)
716 for (
int i = 0;
i <
program->proc_names_count;
i++)
743 if (token.
length + 1 <
sizeof(stack_buf)) {
755 switch (token.
type) {
757 arg->type = ARG_LITERAL;
761 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected valid number.");
767 arg->type = ARG_EXPR;
781 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid expression.");
793 arg->type = ARG_VARIABLE;
806 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected numeric argument.");
819 memset(
arg, 0,
sizeof(*
arg));
838 switch (token.
type) {
874 for (
int i = 0;
i < token->
length;
i++) {
877 && !(
c >=
'a' &&
c <=
'z')
878 && !(
c >=
'A' &&
c <=
'Z')
879 && !(
i > 0 &&
c >=
'0' &&
c <=
'9')
901 vgs_statement_free(&statement); \
902 return AVERROR(err); \
913 int proc_args_count = 0;
922 switch (param->
type) {
938 case PARAM_MAY_REPEAT:
951 if (param->
type != PARAM_END
955 statement.args =
NULL;
956 statement.args_count = 0;
985 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected color.");
991 case PARAM_CONSTANT: {
993 char expected_names[64] = { 0 };
1018 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected one of%s.", expected_names);
1025 case PARAM_PROC_ARGS:
1033 vgs_log_invalid_token(log_ctx, parser, &token,
1041 case PARAM_NUMERIC_METADATA:
1046 param->
type == PARAM_NUMERIC_METADATA
1054 case PARAM_PROC_NAME: {
1062 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid procedure name.");
1095 case PARAM_RAW_IDENT:
1100 switch (token.
type) {
1108 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1114 case PARAM_SUBPROGRAM:
1119 if (token.
type != TOKEN_LEFT_BRACKET) {
1120 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '{'.");
1135 case PARAM_PROC_PARAMS:
1141 vgs_log_invalid_token(log_ctx, parser, &token,
1146 if (token.
type != TOKEN_WORD) {
1154 case PARAM_VAR_NAME: {
1173 if (var_idx == -1) {
1174 vgs_log_invalid_token(log_ctx, parser, &token,
1175 "Too many user variables. Can define up to %d variables.",
USER_VAR_COUNT);
1182 vgs_log_invalid_token(log_ctx, parser, &token,
"Reserved variable name.");
1189 vgs_log_invalid_token(log_ctx, parser, &token,
"Invalid variable name.");
1197 arg.constant = var_idx;
1206 (
void*)&statement.
args,
1215 switch (param->
type) {
1216 case PARAM_PROC_ARGS:
1217 case PARAM_PROC_PARAMS:
1278 switch (token.
type) {
1281 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected '}'.");
1303 case TOKEN_RIGHT_BRACKET:
1317 vgs_log_invalid_token(log_ctx, parser, &token,
"Expected command.");
1334 #define RANDOM_STATES 4
1407 int max_segments = (int)
arg;
1409 double lmx =
NAN, lmy =
NAN;
1410 double cx =
NAN, cy =
NAN;
1413 cairo_path_t *path = cairo_copy_path_flat(
state->cairo_ctx);
1415 for (
int i = 0;
i < path->num_data;
i += path->data[
i].header.length) {
1417 cairo_path_data_t *
data = &path->data[
i];
1420 case CAIRO_PATH_MOVE_TO:
1421 cx = lmx =
data[1].point.x;
1422 cy = lmy =
data[1].point.y;
1427 case CAIRO_PATH_LINE_TO:
1428 x =
data[1].point.x;
1429 y =
data[1].point.y;
1432 case CAIRO_PATH_CLOSE_PATH:
1441 length +=
hypot(cx - x, cy - y);
1448 if (--max_segments == 0)
1452 cairo_path_destroy(path);
1471 const uint64_t iarg = (uint64_t)
arg;
1496 cairo_user_to_device(
state->cairo_ctx, &x0, &y0);
1498 const int x = (int)x0;
1499 const int y = (int)y0;
1501 if (x < 0 || y < 0 || x >=
frame->width || y >=
frame->height)
1506 uint32_t
color[4] = { 0, 0, 0, 255 };
1508 for (
int c = 0;
c <
desc->nb_components;
c++) {
1510 const int depth =
desc->comp[
c].depth;
1562 cairo_pattern_destroy(
state->pattern_builder);
1575 static void draw_ellipse(cairo_t *
c,
double x,
double y,
double rx,
double ry) {
1577 cairo_translate(
c, x, y);
1580 cairo_scale(
c, 1, ry / rx);
1582 cairo_new_sub_path(
c);
1583 cairo_arc(
c, 0, 0, rx, 0, 2 *
M_PI);
1584 cairo_close_path(
c);
1585 cairo_new_sub_path(
c);
1605 double x0 = 0, y0 = 0;
1606 double xa, ya, xb, yb;
1608 const int use_reflected =
isnan(x1);
1613 if (!use_reflected) {
1622 if (use_reflected) {
1624 x1 =
state->rcp.quad_x;
1625 y1 =
state->rcp.quad_y;
1632 xa = (x0 + 2 * x1) / 3;
1633 ya = (y0 + 2 * y1) / 3;
1634 xb = (x + 2 * x1) / 3;
1635 yb = (y + 2 * y1) / 3;
1636 cairo_curve_to(
state->cairo_ctx, xa, ya, xb, yb, x, y);
1639 state->rcp.cubic_x = x1;
1640 state->rcp.cubic_y = y1;
1641 state->rcp.quad_x = 2 * x - x1;
1642 state->rcp.quad_y = 2 * y - y1;
1656 double x0 = 0, y0 = 0;
1658 const int use_reflected =
isnan(x1);
1663 if (!use_reflected) {
1674 if (use_reflected) {
1676 x1 =
state->rcp.cubic_x;
1677 y1 =
state->rcp.cubic_y;
1684 cairo_curve_to(
state->cairo_ctx, x1, y1, x2, y2, x, y);
1687 state->rcp.cubic_x = 2 * x - x2;
1688 state->rcp.cubic_y = 2 * y - y2;
1689 state->rcp.quad_x = x2;
1690 state->rcp.quad_y = y2;
1703 cairo_new_sub_path(
c);
1704 cairo_arc(
c, x + radius, y + radius, radius,
M_PI, 3 *
M_PI / 2);
1705 cairo_arc(
c, x +
width - radius, y + radius, radius, 3 *
M_PI / 2, 2 *
M_PI);
1706 cairo_arc(
c, x +
width - radius, y +
height - radius, radius, 0,
M_PI / 2);
1707 cairo_arc(
c, x + radius, y +
height - radius, radius,
M_PI / 2,
M_PI);
1708 cairo_close_path(
c);
1723 if (h < 0 || h >= 360)
1733 switch ((
int)
floor(h1)) {
1790 #define ASSERT_ARGS(n) av_assert0(statement->args_count == n)
1794 #define MAY_PRESERVE(funcname) \
1796 if (state->preserve_path) { \
1797 state->preserve_path = 0; \
1798 funcname##_preserve(state->cairo_ctx); \
1800 funcname(state->cairo_ctx); \
1811 for (
int st_number = 0; st_number <
program->statements_count; st_number++) {
1856 numerics[
arg] =
a->literal;
1861 numerics[
arg] =
state->vars[
a->variable];
1874 switch (statement->
cmd) {
1881 cairo_pattern_destroy(
state->pattern_builder);
1887 switch (statement->
cmd) {
1914 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[2]);
1920 cairo_set_fill_rule(
1923 CAIRO_FILL_RULE_WINDING :
1924 CAIRO_FILL_RULE_EVEN_ODD
1932 cairo_close_path(
state->cairo_ctx);
1942 cairo_pattern_add_color_stop_rgba(
1943 state->pattern_builder,
1977 hsl2rgb(numerics[1], numerics[2], numerics[3], &
r, &
g, &
b);
1984 #define C(v, o) ((uint32_t)(av_clipd(v, 0, 1) * 255) << o)
2000 draw_ellipse(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2007 cairo_set_fill_rule(
2010 CAIRO_FILL_RULE_WINDING :
2011 CAIRO_FILL_RULE_EVEN_ODD
2044 state->interrupted = 1;
2050 if (
isfinite(numerics[0]) && numerics[0] != 0.0) {
2052 if (
ret != 0 ||
state->interrupted != 0)
2062 cairo_pattern_destroy(
state->pattern_builder);
2064 state->pattern_builder = cairo_pattern_create_linear(
2074 cairo_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2079 cairo_rel_line_to(
state->cairo_ctx, numerics[0], numerics[1]);
2084 cairo_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2089 cairo_rel_move_to(
state->cairo_ctx, numerics[0], numerics[1]);
2094 cairo_new_sub_path(
state->cairo_ctx);
2099 state->preserve_path = 1;
2108 int capacity =
sizeof(msg) -
len;
2120 if (written >= capacity)
2133 const int proc_args = statement->
args_count - 2;
2141 proc->
args[
i] = i < proc_args ? statement->
args[
i + 1].constant : -1;
2147 const int proc_args = statement->
args_count - 1;
2158 "Procedure expects %d arguments, but received %d.",
2167 const char *proc_name =
state->proc_names[proc_id];
2169 "Missing body for procedure '%s'\n", proc_name);
2175 for (
int i = 0;
i < proc_args;
i++) {
2176 const int var = proc->
args[
i];
2178 current_vars[
i] =
state->vars[var];
2179 state->vars[var] = numerics[
i + 1];
2186 for (
int i = 0;
i < proc_args;
i++) {
2187 const int var = proc->
args[
i];
2189 state->vars[var] = current_vars[
i];
2197 if (
state->interrupted) {
2198 state->interrupted = 0;
2224 cairo_pattern_destroy(
state->pattern_builder);
2226 state->pattern_builder = cairo_pattern_create_radial(
2237 cairo_reset_clip(
state->cairo_ctx);
2245 cairo_identity_matrix(
state->cairo_ctx);
2250 cairo_rectangle(
state->cairo_ctx, numerics[0], numerics[1], numerics[2], numerics[3]);
2261 for (
int i = 0, count = (
int)numerics[0];
i < count;
i++) {
2269 if (
state->interrupted) {
2270 state->interrupted = 0;
2281 cairo_restore(
state->cairo_ctx);
2286 cairo_rotate(
state->cairo_ctx, numerics[0]);
2303 cairo_save(
state->cairo_ctx);
2308 cairo_scale(
state->cairo_ctx, numerics[0], numerics[0]);
2313 cairo_scale(
state->cairo_ctx, numerics[0], numerics[1]);
2320 cairo_pattern_destroy(
state->pattern_builder);
2322 state->pattern_builder = cairo_pattern_create_rgba(
2342 cairo_set_line_width(
state->cairo_ctx, numerics[0]);
2348 double *dashes,
offset, stack_buf[16];
2357 dashes =
av_calloc(num + 1,
sizeof(
double));
2366 dashes[num] = numerics[0];
2374 if (dashes != stack_buf)
2387 cairo_pattern_destroy(
state->pattern_builder);
2390 hsl2rgb(numerics[0], numerics[1], numerics[2], &
r, &
g, &
b);
2397 state->pattern_builder = cairo_pattern_create_rgba(
r,
g,
b, numerics[3]);
2407 state->vars[user_var] = numerics[1];
2433 cairo_translate(
state->cairo_ctx, numerics[0], numerics[1]);
2450 double d = numerics[0];
2452 switch (statement->
cmd) {
2459 cairo_line_to(
state->cairo_ctx, cx, cy);
2468 if (
state->rcp.status == RCP_UPDATED) {
2469 state->rcp.status = RCP_VALID;
2471 state->rcp.status = RCP_NONE;
2479 "Error in cairo context: %s\n",
2517 #define OPT(name, field, help) \
2521 offsetof(DrawVGContext, field), \
2522 AV_OPT_TYPE_STRING, \
2525 AV_OPT_FLAG_FILTERING_PARAM \
2526 | AV_OPT_FLAG_VIDEO_PARAM \
2530 OPT(
"script", script_text,
"script source to draw the graphics"),
2531 OPT(
"s", script_text,
"script source to draw the graphics"),
2532 OPT(
"file", script_file,
"file to load the script source"),
2556 CAIRO_FORMAT_ARGB32,
2558 CAIRO_FORMAT_RGB16_565,
2560 CAIRO_FORMAT_INVALID,
2571 return CAIRO_FORMAT_INVALID;
2577 cairo_surface_t* surface;
2591 surface = cairo_image_surface_create_for_data(
2599 if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
2604 eval_state.
cairo_ctx = cairo_create(surface);
2623 cairo_surface_destroy(surface);
2652 drawvg->time_start =
NAN;
2654 if ((drawvg->script_text ==
NULL) == (drawvg->script_file ==
NULL)) {
2656 "Either 'source' or 'file' must be provided\n");
2661 if (drawvg->script_file !=
NULL) {
2664 (
const char *)drawvg->script_file,
2665 &drawvg->script_text,
2700 .p.priv_class = &drawvg_class,
FFSFC64 random_state[RANDOM_STATES]
State for each index available for the randomg function.
static const AVFilterPad drawvg_inputs[]
enum VGSEvalState::@386::@387 status
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[]
enum VGSParserToken::@382 type
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)
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.
enum VGSArgument::@383 type
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.
@ CMD_T_CURVE_TO_REL
t (dx dy)
static int drawvg_config_props(AVFilterLink *inlink)
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 int vgs_parse_numeric_argument(void *log_ctx, struct VGSParser *parser, struct VGSArgument *arg, int metadata)
Consume the next argument as a numeric value, and store it in arg.
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.
@ VAR_CY
Y coordinate for current point.
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.
@ VAR_TS
Time in seconds of the first frame.
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).
#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)
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.
@ VAR_T
Timestamp in seconds.
@ CMD_Q_CURVE_TO_REL
q (dx1 dy1 dx dy)
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.
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)
@ VAR_CX
X coordinate for current point.
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.
static void draw_ellipse(cairo_t *c, double x, double y, double rx, double ry)
Draw an ellipse.
@ CMD_REPEAT
repeat (count) { 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 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.
@ 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
enum VGSParameter::@381 type
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
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
#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
@ CMD_SET_LINE_JOIN
setlinejoin (join)
@ CMD_CURVE_TO
C, curveto (x1 y1 x2 y2 x y)
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
struct VGSEvalState::@386 rcp
@ 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)
@ VAR_I
Loop counter, to use with repeat {}.
static int vgs_parser_can_repeat_cmd(void *log_ctx, struct VGSParser *parser)
Check if the next token is a numeric value, so the last command must be repeated.
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.
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)
@ VAR_DURATION
Frame duration.
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.