This source file includes following definitions.
- GradientGetMatrix
- DestroyGradient
- UpdateLinearGradient
- LG_ComputeMatrix
- BuildLinearGradientTexture
- compositor_init_linear_gradient
- BuildRadialGradientTexture
- UpdateRadialGradient
- RG_ComputeMatrix
- compositor_init_radial_gradient
- compositor_mpeg4_get_gradient_texture
- compositor_gradient_update
#include "nodes_stacks.h"
#include "texturing.h"
#ifndef GPAC_DISABLE_VRML
#define GRAD_TEXTURE_SIZE 128
#define GRAD_TEXTURE_HSIZE 64
enum
{
GF_SR_TEXTURE_GRAD_REGISTERED = 1<<6,
GF_SR_TEXTURE_GRAD_NO_RGB = 1<<7,
};
typedef struct
{
GF_TextureHandler txh;
char *tx_data;
} GradientStack;
void GradientGetMatrix(GF_Node *transform, GF_Matrix2D *mat)
{
gf_mx2d_init(*mat);
if (transform) {
switch (gf_node_get_tag(transform) ) {
case TAG_MPEG4_Transform2D:
{
M_Transform2D *tr = (M_Transform2D *)transform;
gf_mx2d_add_scale_at(mat, 0, 0, tr->scale.x, tr->scale.y, tr->scaleOrientation);
gf_mx2d_add_rotation(mat, tr->center.x, tr->center.y, tr->rotationAngle);
gf_mx2d_add_translation(mat, tr->translation.x, tr->translation.y);
}
break;
case TAG_MPEG4_TransformMatrix2D:
{
M_TransformMatrix2D *tm = (M_TransformMatrix2D*)transform;
gf_mx2d_init(*mat);
mat->m[0] = tm->mxx;
mat->m[1] = tm->mxy;
mat->m[2] = tm->tx;
mat->m[3] = tm->myx;
mat->m[4] = tm->myy;
mat->m[5] = tm->ty;
}
break;
default:
break;
}
}
}
static void DestroyGradient(GF_Node *node, void *rs, Bool is_destroy)
{
if (is_destroy) {
GradientStack *st = (GradientStack *) gf_node_get_private(node);
gf_sc_texture_destroy(&st->txh);
if (st->tx_data) gf_free(st->tx_data);
gf_free(st);
}
}
static void UpdateLinearGradient(GF_TextureHandler *txh)
{
u32 i, *cols;
Fixed a;
Bool const_a;
GF_STENCIL stencil;
M_LinearGradient *lg = (M_LinearGradient *) txh->owner;
GradientStack *st = (GradientStack *) gf_node_get_private(txh->owner);
if (!gf_node_dirty_get(txh->owner)) {
txh->needs_refresh = 0;
return;
}
if (lg->key.count > lg->keyValue.count) return;
if (!txh->tx_io) {
gf_node_dirty_set(gf_node_get_parent(txh->owner, 0), 0, 1);
gf_node_dirty_set(txh->owner, 0, 1);
gf_sc_texture_allocate(txh);
}
stencil = gf_sc_texture_get_stencil(txh);
if (!stencil) stencil = txh->compositor->rasterizer->stencil_new(txh->compositor->rasterizer, GF_STENCIL_LINEAR_GRADIENT);
gf_sc_texture_set_stencil(txh, stencil);
gf_node_dirty_clear(txh->owner, 0);
txh->needs_refresh = 1;
st->txh.transparent = 0;
const_a = (lg->opacity.count == 1) ? 1 : 0;
cols = (u32*)gf_malloc(sizeof(u32) * lg->key.count);
for (i=0; i<lg->key.count; i++) {
a = (const_a ? lg->opacity.vals[0] : lg->opacity.vals[i]);
cols[i] = GF_COL_ARGB_FIXED(a, lg->keyValue.vals[i].red, lg->keyValue.vals[i].green, lg->keyValue.vals[i].blue);
if (a != FIX_ONE) txh->transparent = 1;
}
txh->compositor->rasterizer->stencil_set_gradient_interpolation(stencil, lg->key.vals, cols, lg->key.count);
gf_free(cols);
txh->compositor->rasterizer->stencil_set_gradient_mode(stencil, (GF_GradientMode) lg->spreadMethod);
}
static void LG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat, Bool for_3d)
{
GF_STENCIL stencil;
M_LinearGradient *lg = (M_LinearGradient *) txh->owner;
stencil = gf_sc_texture_get_stencil(txh);
if (!stencil) return;
if (lg->key.count<2) return;
if (lg->key.count != lg->keyValue.count) return;
if (!txh->tx_io) return;
GradientGetMatrix((GF_Node *) lg->transform, mat);
gf_mx2d_add_translation(mat, gf_divfix(bounds->x, bounds->width), gf_divfix(bounds->y - bounds->height, bounds->height));
gf_mx2d_add_scale(mat, bounds->width, bounds->height);
txh->compositor->rasterizer->stencil_set_linear_gradient(stencil, lg->startPoint.x, lg->startPoint.y, lg->endPoint.x, lg->endPoint.y);
}
static void BuildLinearGradientTexture(GF_TextureHandler *txh)
{
u32 i;
SFVec2f start, end;
u32 *cols;
Fixed a;
Bool const_a;
GF_Matrix2D mat;
GF_STENCIL stenc;
GF_SURFACE surface;
GF_STENCIL texture2D;
GF_Path *path;
GF_Err e;
Bool transparent;
u32 pix_fmt = 0;
M_LinearGradient *lg = (M_LinearGradient *) txh->owner;
GradientStack *st = (GradientStack *) gf_node_get_private(txh->owner);
GF_Raster2D *raster = txh->compositor->rasterizer;
if (!txh->tx_io) return;
if (!(txh->flags & GF_SR_TEXTURE_GRAD_REGISTERED)) {
txh->flags |= GF_SR_TEXTURE_GRAD_REGISTERED;
if (gf_list_find(txh->compositor->textures, txh)<0)
gf_list_insert(txh->compositor->textures, txh, 0);
}
if (lg->key.count<2) return;
if (lg->key.count != lg->keyValue.count) return;
start = lg->startPoint;
end = lg->endPoint;
transparent = (lg->opacity.count==1) ? (lg->opacity.vals[0]!=FIX_ONE) : 1;
texture2D = raster->stencil_new(raster, GF_STENCIL_TEXTURE);
if (!texture2D) return;
surface = raster->surface_new(raster, 1);
if (!surface) {
raster->stencil_delete(texture2D);
return;
}
if (st->txh.flags & GF_SR_TEXTURE_GRAD_NO_RGB) transparent = 1;
if (st->tx_data && (st->txh.transparent != transparent)) {
gf_free(st->tx_data);
st->tx_data = NULL;
}
if (transparent) {
if (!st->tx_data) {
st->tx_data = (char *) gf_malloc(sizeof(char)*GRAD_TEXTURE_SIZE*GRAD_TEXTURE_SIZE*4);
}
memset(st->tx_data, 0, sizeof(char)*txh->stride*txh->height);
pix_fmt = GF_PIXEL_RGBA;
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 4*GRAD_TEXTURE_SIZE, pix_fmt, pix_fmt, 1);
if (e) {
pix_fmt = GF_PIXEL_ARGB;
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 4*GRAD_TEXTURE_SIZE, pix_fmt, pix_fmt, 1);
}
} else {
if (!st->tx_data) {
st->tx_data = (char *) gf_malloc(sizeof(char)*GRAD_TEXTURE_SIZE*GRAD_TEXTURE_SIZE*3);
}
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 3*GRAD_TEXTURE_SIZE, GF_PIXEL_RGB_24, GF_PIXEL_RGB_24, 1);
if (e) {
st->txh.flags |= GF_SR_TEXTURE_GRAD_NO_RGB;
transparent = 1;
gf_free(st->tx_data);
st->tx_data = (char *) gf_malloc(sizeof(char)*GRAD_TEXTURE_SIZE*GRAD_TEXTURE_SIZE*4);
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 4*GRAD_TEXTURE_SIZE, GF_PIXEL_ARGB, GF_PIXEL_ARGB, 1);
}
}
st->txh.transparent = transparent;
if (e) {
gf_free(st->tx_data);
raster->stencil_delete(texture2D);
raster->surface_delete(surface);
return;
}
e = raster->surface_attach_to_texture(surface, texture2D);
if (e) {
raster->stencil_delete(texture2D);
raster->surface_delete(surface);
return;
}
stenc = raster->stencil_new(raster, GF_STENCIL_LINEAR_GRADIENT);
if (!stenc) {
raster->stencil_delete(texture2D);
raster->surface_delete(surface);
return;
}
start.x *= GRAD_TEXTURE_SIZE;
end.x *= GRAD_TEXTURE_SIZE;
start.y *= GRAD_TEXTURE_SIZE;
end.y *= GRAD_TEXTURE_SIZE;
raster->stencil_set_linear_gradient(stenc, start.x, start.y, end.x, end.y);
const_a = (lg->opacity.count == 1) ? 1 : 0;
cols = (u32*)gf_malloc(sizeof(u32) * lg->key.count);
for (i=0; i<lg->key.count; i++) {
a = (const_a ? lg->opacity.vals[0] : lg->opacity.vals[i]);
cols[i] = GF_COL_ARGB_FIXED(a, lg->keyValue.vals[i].red, lg->keyValue.vals[i].green, lg->keyValue.vals[i].blue);
}
raster->stencil_set_gradient_interpolation(stenc, lg->key.vals, cols, lg->key.count);
gf_free(cols);
raster->stencil_set_gradient_mode(stenc, (GF_GradientMode)lg->spreadMethod);
path = gf_path_new();
gf_path_add_move_to(path, -INT2FIX(GRAD_TEXTURE_HSIZE), -INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_add_line_to(path, INT2FIX(GRAD_TEXTURE_HSIZE), -INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_add_line_to(path, INT2FIX(GRAD_TEXTURE_HSIZE), INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_add_line_to(path, -INT2FIX(GRAD_TEXTURE_HSIZE), INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_close(path);
GradientGetMatrix(lg->transform, &mat);
mat.m[2] *= GRAD_TEXTURE_SIZE;
mat.m[5] *= GRAD_TEXTURE_SIZE;
gf_mx2d_add_translation(&mat, -INT2FIX(GRAD_TEXTURE_HSIZE), -INT2FIX(GRAD_TEXTURE_HSIZE));
gf_mx2d_add_scale(&mat, FIX_ONE, -FIX_ONE);
raster->stencil_set_matrix(stenc, &mat);
raster->surface_set_raster_level(surface, GF_RASTER_HIGH_QUALITY);
raster->surface_set_path(surface, path);
raster->surface_fill(surface, stenc);
raster->stencil_delete(stenc);
raster->surface_delete(surface);
raster->stencil_delete(texture2D);
gf_path_del(path);
txh->data = st->tx_data;
txh->width = GRAD_TEXTURE_SIZE;
txh->height = GRAD_TEXTURE_SIZE;
txh->transparent = transparent;
if (transparent) {
u32 j;
txh->stride = GRAD_TEXTURE_SIZE*4;
txh->pixelformat = GF_PIXEL_RGBA;
if (pix_fmt != GF_PIXEL_RGBA) {
for (i=0; i<txh->height; i++) {
char *data = txh->data + i*txh->stride;
for (j=0; j<txh->width; j++) {
u32 val = *(u32 *) &data[4*j];
data[4*j] = (val>>16) & 0xFF;
data[4*j+1] = (val>>8) & 0xFF;
data[4*j+2] = (val) & 0xFF;
data[4*j+3] = (val>>24) & 0xFF;
}
}
}
} else {
txh->stride = GRAD_TEXTURE_SIZE*3;
txh->pixelformat = GF_PIXEL_RGB_24;
}
txh->flags |= GF_SR_TEXTURE_NO_GL_FLIP;
gf_sc_texture_set_data(txh);
}
void compositor_init_linear_gradient(GF_Compositor *compositor, GF_Node *node)
{
GradientStack *st;
GF_SAFEALLOC(st, GradientStack);
if (!st) {
GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate gradient stack\n"));
return;
}
st->txh.owner = node;
st->txh.compositor = compositor;
st->txh.update_texture_fcnt = UpdateLinearGradient;
st->txh.compute_gradient_matrix = LG_ComputeMatrix;
gf_node_set_private(node, st);
gf_node_set_callback_function(node, DestroyGradient);
}
static void BuildRadialGradientTexture(GF_TextureHandler *txh)
{
u32 i;
SFVec2f center, focal;
u32 *cols;
Fixed a, radius;
Bool const_a;
GF_Matrix2D mat;
GF_STENCIL stenc;
GF_SURFACE surface;
GF_STENCIL texture2D;
GF_Path *path;
GF_Err e;
u32 pix_fmt = 0;
Bool transparent;
M_RadialGradient *rg = (M_RadialGradient*) txh->owner;
GradientStack *st = (GradientStack *) gf_node_get_private(txh->owner);
GF_Raster2D *raster = txh->compositor->rasterizer;
if (!txh->tx_io) return;
if (!(txh->flags & GF_SR_TEXTURE_GRAD_REGISTERED)) {
txh->flags |= GF_SR_TEXTURE_GRAD_REGISTERED;
if (gf_list_find(txh->compositor->textures, txh)<0)
gf_list_insert(txh->compositor->textures, txh, 0);
}
if (rg->key.count<2) return;
if (rg->key.count != rg->keyValue.count) return;
transparent = (rg->opacity.count==1) ? ((rg->opacity.vals[0]!=FIX_ONE) ? 1 : 0) : 1;
texture2D = raster->stencil_new(raster, GF_STENCIL_TEXTURE);
if (!texture2D) return;
surface = raster->surface_new(raster, 1);
if (!surface) {
raster->stencil_delete(texture2D);
return;
}
if (st->txh.flags & GF_SR_TEXTURE_GRAD_NO_RGB) transparent = 1;
if (st->tx_data && (st->txh.transparent != transparent)) {
gf_free(st->tx_data);
st->tx_data = NULL;
}
if (transparent) {
if (!st->tx_data) {
st->tx_data = (char *) gf_malloc(sizeof(char)*GRAD_TEXTURE_SIZE*GRAD_TEXTURE_SIZE*4);
}
memset(st->tx_data, 0, sizeof(char)*txh->stride*txh->height);
pix_fmt = GF_PIXEL_RGBA;
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 4*GRAD_TEXTURE_SIZE, pix_fmt, pix_fmt, 1);
if (e) {
pix_fmt = GF_PIXEL_ARGB;
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 4*GRAD_TEXTURE_SIZE, pix_fmt, pix_fmt, 1);
}
} else {
if (!st->tx_data) {
st->tx_data = (char *) gf_malloc(sizeof(char)*GRAD_TEXTURE_SIZE*GRAD_TEXTURE_SIZE*3);
}
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 3*GRAD_TEXTURE_SIZE, GF_PIXEL_RGB_24, GF_PIXEL_RGB_24, 1);
if (e) {
st->txh.flags |= GF_SR_TEXTURE_GRAD_NO_RGB;
transparent = 1;
gf_free(st->tx_data);
st->tx_data = (char *) gf_malloc(sizeof(char)*GRAD_TEXTURE_SIZE*GRAD_TEXTURE_SIZE*4);
e = raster->stencil_set_texture(texture2D, st->tx_data, GRAD_TEXTURE_SIZE, GRAD_TEXTURE_SIZE, 4*GRAD_TEXTURE_SIZE, GF_PIXEL_ARGB, GF_PIXEL_ARGB, 1);
}
}
st->txh.transparent = transparent;
if (e) {
gf_free(st->tx_data);
raster->stencil_delete(texture2D);
raster->surface_delete(surface);
return;
}
e = raster->surface_attach_to_texture(surface, texture2D);
if (e) {
raster->stencil_delete(texture2D);
raster->surface_delete(surface);
return;
}
stenc = raster->stencil_new(raster, GF_STENCIL_RADIAL_GRADIENT);
if (!stenc) {
raster->stencil_delete(texture2D);
raster->surface_delete(surface);
}
center = rg->center;
focal = rg->focalPoint;
radius = rg->radius;
center.x *= GRAD_TEXTURE_SIZE;
center.y *= GRAD_TEXTURE_SIZE;
focal.x *= GRAD_TEXTURE_SIZE;
focal.y *= GRAD_TEXTURE_SIZE;
radius *= GRAD_TEXTURE_SIZE;
raster->stencil_set_radial_gradient(stenc, center.x, center.y, focal.x, focal.y, radius, radius);
const_a = (rg->opacity.count == 1) ? 1 : 0;
cols = (u32*) gf_malloc(sizeof(u32) * rg->key.count);
for (i=0; i<rg->key.count; i++) {
a = (const_a ? rg->opacity.vals[0] : rg->opacity.vals[i]);
cols[i] = GF_COL_ARGB_FIXED(a, rg->keyValue.vals[i].red, rg->keyValue.vals[i].green, rg->keyValue.vals[i].blue);
}
raster->stencil_set_gradient_interpolation(stenc, rg->key.vals, cols, rg->key.count);
gf_free(cols);
raster->stencil_set_gradient_mode(stenc, (GF_GradientMode)rg->spreadMethod);
path = gf_path_new();
gf_path_add_move_to(path, -INT2FIX(GRAD_TEXTURE_HSIZE), -INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_add_line_to(path, INT2FIX(GRAD_TEXTURE_HSIZE), -INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_add_line_to(path, INT2FIX(GRAD_TEXTURE_HSIZE), INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_add_line_to(path, -INT2FIX(GRAD_TEXTURE_HSIZE), INT2FIX(GRAD_TEXTURE_HSIZE));
gf_path_close(path);
GradientGetMatrix(rg->transform, &mat);
mat.m[2] *= GRAD_TEXTURE_SIZE;
mat.m[5] *= GRAD_TEXTURE_SIZE;
gf_mx2d_add_translation(&mat, -INT2FIX(GRAD_TEXTURE_HSIZE), -INT2FIX(GRAD_TEXTURE_HSIZE));
gf_mx2d_add_scale(&mat, FIX_ONE, -FIX_ONE);
raster->stencil_set_matrix(stenc, &mat);
raster->surface_set_raster_level(surface, GF_RASTER_HIGH_QUALITY);
raster->surface_set_path(surface, path);
raster->surface_fill(surface, stenc);
raster->stencil_delete(stenc);
raster->surface_delete(surface);
raster->stencil_delete(texture2D);
gf_path_del(path);
txh->data = st->tx_data;
txh->width = GRAD_TEXTURE_SIZE;
txh->height = GRAD_TEXTURE_SIZE;
txh->transparent = transparent;
if (transparent) {
u32 j;
txh->stride = GRAD_TEXTURE_SIZE*4;
txh->pixelformat = GF_PIXEL_RGBA;
if (pix_fmt == GF_PIXEL_ARGB) {
for (i=0; i<txh->height; i++) {
char *data = txh->data + i*txh->stride;
for (j=0; j<txh->width; j++) {
u32 val = *(u32 *) &data[4*j];
data[4*j] = (val>>16) & 0xFF;
data[4*j+1] = (val>>8) & 0xFF;
data[4*j+2] = (val) & 0xFF;
data[4*j+3] = (val>>24) & 0xFF;
}
}
}
} else {
txh->stride = GRAD_TEXTURE_SIZE*3;
txh->pixelformat = GF_PIXEL_RGB_24;
}
txh->flags |= GF_SR_TEXTURE_NO_GL_FLIP;
gf_sc_texture_set_data(txh);
return;
}
static void UpdateRadialGradient(GF_TextureHandler *txh)
{
Bool const_a;
GF_STENCIL stencil;
u32 i, *cols;
Fixed a;
M_RadialGradient *rg = (M_RadialGradient*) txh->owner;
GradientStack *st = (GradientStack *) gf_node_get_private(txh->owner);
if (!gf_node_dirty_get(txh->owner)) {
txh->needs_refresh = 0;
return;
}
if (rg->key.count > rg->keyValue.count) return;
if (!txh->tx_io) gf_sc_texture_allocate(txh);
stencil = gf_sc_texture_get_stencil(txh);
if (!stencil)stencil = txh->compositor->rasterizer->stencil_new(txh->compositor->rasterizer, GF_STENCIL_RADIAL_GRADIENT);
gf_sc_texture_set_stencil(txh, stencil);
gf_node_dirty_clear(txh->owner, 0);
txh->needs_refresh = 1;
st->txh.transparent = 0;
for (i=0; i<rg->opacity.count; i++) {
if (rg->opacity.vals[i] != FIX_ONE) {
st->txh.transparent = 1;
break;
}
}
const_a = (rg->opacity.count == 1) ? 1 : 0;
cols = (u32*)gf_malloc(sizeof(u32) * rg->key.count);
for (i=0; i<rg->key.count; i++) {
a = (const_a ? rg->opacity.vals[0] : rg->opacity.vals[i]);
cols[i] = GF_COL_ARGB_FIXED(a, rg->keyValue.vals[i].red, rg->keyValue.vals[i].green, rg->keyValue.vals[i].blue);
}
txh->compositor->rasterizer->stencil_set_gradient_interpolation(stencil, rg->key.vals, cols, rg->key.count);
gf_free(cols);
txh->compositor->rasterizer->stencil_set_gradient_mode(stencil, (GF_GradientMode) rg->spreadMethod);
}
static void RG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat, Bool for_3d)
{
GF_STENCIL stencil;
M_RadialGradient *rg = (M_RadialGradient *) txh->owner;
if (rg->key.count<2) return;
if (rg->key.count != rg->keyValue.count) return;
if (!txh->tx_io) return;
stencil = gf_sc_texture_get_stencil(txh);
if (!stencil) return;
GradientGetMatrix((GF_Node *) rg->transform, mat);
txh->compositor->rasterizer->stencil_set_radial_gradient(stencil, rg->center.x, rg->center.y, rg->focalPoint.x, rg->focalPoint.y, rg->radius, rg->radius);
gf_mx2d_add_translation(mat, gf_divfix(bounds->x, bounds->width), gf_divfix(bounds->y - bounds->height, bounds->height));
gf_mx2d_add_scale(mat, bounds->width, bounds->height);
}
void compositor_init_radial_gradient(GF_Compositor *compositor, GF_Node *node)
{
GradientStack *st;
GF_SAFEALLOC(st, GradientStack);
if (!st) {
GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate gradient stack\n"));
return;
}
st->txh.owner = node;
st->txh.compositor = compositor;
st->txh.update_texture_fcnt = UpdateRadialGradient;
st->txh.compute_gradient_matrix = RG_ComputeMatrix;
gf_node_set_private(node, st);
gf_node_set_callback_function(node, DestroyGradient);
}
GF_TextureHandler *compositor_mpeg4_get_gradient_texture(GF_Node *node)
{
GradientStack *st = (GradientStack*) gf_node_get_private(node);
st->txh.update_texture_fcnt(&st->txh);
return &st->txh;
}
#endif
void compositor_gradient_update(GF_TextureHandler *txh)
{
switch (gf_node_get_tag(txh->owner) ) {
#ifndef GPAC_DISABLE_VRML
case TAG_MPEG4_RadialGradient:
BuildRadialGradientTexture(txh);
break;
case TAG_MPEG4_LinearGradient:
BuildLinearGradientTexture(txh);
break;
#endif
#ifndef GPAC_DISABLE_SVG
case TAG_SVG_linearGradient:
case TAG_SVG_radialGradient:
compositor_svg_build_gradient_texture(txh);
break;
#endif
}
}