forked from AuroraMiddleware/gtk
Merge branch 'wip/baedert/radial-gradient' into 'master'
Radial gradients Closes #2262, #3170, and #3173 See merge request GNOME/gtk!2597
This commit is contained in:
commit
57253b0039
@ -37,9 +37,11 @@ GskCrossFadeNode
|
||||
GskDebugNode
|
||||
GskInsetShadowNode
|
||||
GskLinearGradientNode
|
||||
GskRadialGradientNode
|
||||
GskOpacityNode
|
||||
GskOutsetShadowNode
|
||||
GskRepeatingLinearGradientNode
|
||||
GskRepeatingRadialGradientNode
|
||||
GskRepeatNode
|
||||
GskRoundedClipNode
|
||||
GskShadowNode
|
||||
@ -71,6 +73,15 @@ gsk_linear_gradient_node_peek_end
|
||||
gsk_linear_gradient_node_get_n_color_stops
|
||||
gsk_linear_gradient_node_peek_color_stops
|
||||
gsk_repeating_linear_gradient_node_new
|
||||
gsk_radial_gradient_node_new
|
||||
gsk_radial_gradient_node_get_n_color_stops
|
||||
gsk_radial_gradient_node_peek_color_stops
|
||||
gsk_radial_gradient_node_get_start
|
||||
gsk_radial_gradient_node_get_end
|
||||
gsk_radial_gradient_node_get_hradius
|
||||
gsk_radial_gradient_node_get_vradius
|
||||
gsk_radial_gradient_node_peek_center
|
||||
gsk_repeating_radial_gradient_node_new
|
||||
gsk_border_node_new
|
||||
gsk_border_node_peek_outline
|
||||
gsk_border_node_peek_widths
|
||||
|
@ -1192,6 +1192,32 @@ render_linear_gradient_node (GskGLRenderer *self,
|
||||
load_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
}
|
||||
|
||||
static inline void
|
||||
render_radial_gradient_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const int n_color_stops = MIN (8, gsk_radial_gradient_node_get_n_color_stops (node));
|
||||
const GskColorStop *stops = gsk_radial_gradient_node_peek_color_stops (node, NULL);
|
||||
const graphene_point_t *center = gsk_radial_gradient_node_peek_center (node);
|
||||
const float start = gsk_radial_gradient_node_get_start (node);
|
||||
const float end = gsk_radial_gradient_node_get_end (node);
|
||||
const float hradius = gsk_radial_gradient_node_get_hradius (node);
|
||||
const float vradius = gsk_radial_gradient_node_get_vradius (node);
|
||||
|
||||
ops_set_program (builder, &self->programs->radial_gradient_program);
|
||||
ops_set_radial_gradient (builder,
|
||||
n_color_stops,
|
||||
stops,
|
||||
builder->dx + center->x,
|
||||
builder->dy + center->y,
|
||||
start, end,
|
||||
hradius * scale, vradius * scale);
|
||||
|
||||
load_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
|
||||
const graphene_rect_t *rect)
|
||||
@ -2761,6 +2787,25 @@ apply_linear_gradient_op (const Program *program,
|
||||
glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_radial_gradient_op (const Program *program,
|
||||
const OpRadialGradient *op)
|
||||
{
|
||||
OP_PRINT (" -> Radial gradient");
|
||||
if (op->n_color_stops.send)
|
||||
glUniform1i (program->radial_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||
|
||||
if (op->color_stops.send)
|
||||
glUniform1fv (program->radial_gradient.color_stops_location,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform1f (program->radial_gradient.start_location, op->start);
|
||||
glUniform1f (program->radial_gradient.end_location, op->end);
|
||||
glUniform2f (program->radial_gradient.radius_location, op->radius[0], op->radius[1]);
|
||||
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_border_op (const Program *program,
|
||||
const OpBorder *op)
|
||||
@ -2903,6 +2948,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
{ "/org/gtk/libgsk/glsl/cross_fade.glsl", "cross fade" },
|
||||
{ "/org/gtk/libgsk/glsl/inset_shadow.glsl", "inset shadow" },
|
||||
{ "/org/gtk/libgsk/glsl/linear_gradient.glsl", "linear gradient" },
|
||||
{ "/org/gtk/libgsk/glsl/radial_gradient.glsl", "radial gradient" },
|
||||
{ "/org/gtk/libgsk/glsl/outset_shadow.glsl", "outset shadow" },
|
||||
{ "/org/gtk/libgsk/glsl/repeat.glsl", "repeat" },
|
||||
{ "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", "unblurred_outset shadow" },
|
||||
@ -2984,6 +3030,14 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, start_point);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, end_point);
|
||||
|
||||
/* radial gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, center);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, start);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
|
||||
|
||||
/* blur */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_size);
|
||||
@ -3035,6 +3089,10 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
out:
|
||||
gsk_gl_shader_builder_finish (&shader_builder);
|
||||
|
||||
if (error && !(*error))
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
"Failed to compile all shader programs"); /* Probably, eh. */
|
||||
|
||||
return programs;
|
||||
}
|
||||
|
||||
@ -3328,6 +3386,10 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
render_linear_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
render_radial_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
render_clip_node (self, node, builder);
|
||||
break;
|
||||
@ -3384,6 +3446,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
{
|
||||
@ -3678,6 +3741,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self)
|
||||
apply_linear_gradient_op (program, ptr);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_RADIAL_GRADIENT:
|
||||
apply_radial_gradient_op (program, ptr);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_BLUR:
|
||||
apply_blur_op (program, ptr);
|
||||
break;
|
||||
|
@ -960,3 +960,32 @@ ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
op->end_point[0] = end_x;
|
||||
op->end_point[1] = end_y;
|
||||
}
|
||||
|
||||
void
|
||||
ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
float end,
|
||||
float hradius,
|
||||
float vradius)
|
||||
{
|
||||
const guint real_n_color_stops = MIN (MAX_GRADIENT_STOPS, n_color_stops);
|
||||
OpRadialGradient *op;
|
||||
|
||||
/* TODO: State tracking? */
|
||||
|
||||
op = ops_begin (self, OP_CHANGE_RADIAL_GRADIENT);
|
||||
op->n_color_stops.value = real_n_color_stops;
|
||||
op->n_color_stops.send = true;
|
||||
op->color_stops.value = color_stops;
|
||||
op->color_stops.send = true;
|
||||
op->center[0] = center_x;
|
||||
op->center[1] = center_y;
|
||||
op->radius[0] = hradius;
|
||||
op->radius[1] = vradius;
|
||||
op->start = start;
|
||||
op->end = end;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "opbuffer.h"
|
||||
|
||||
#define GL_N_VERTICES 6
|
||||
#define GL_N_PROGRAMS 13
|
||||
#define GL_N_PROGRAMS 14
|
||||
#define MAX_GRADIENT_STOPS 8
|
||||
|
||||
typedef struct
|
||||
@ -62,6 +62,14 @@ struct _Program
|
||||
int start_point_location;
|
||||
int end_point_location;
|
||||
} linear_gradient;
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int center_location;
|
||||
int start_location;
|
||||
int end_location;
|
||||
int radius_location;
|
||||
} radial_gradient;
|
||||
struct {
|
||||
int blur_radius_location;
|
||||
int blur_size_location;
|
||||
@ -143,6 +151,14 @@ typedef struct
|
||||
float start_point[2];
|
||||
float end_point[2];
|
||||
} linear_gradient;
|
||||
struct {
|
||||
int n_color_stops;
|
||||
GskColorStop color_stops[MAX_GRADIENT_STOPS];
|
||||
float center[2];
|
||||
float start;
|
||||
float end;
|
||||
float radius[2]; /* h/v */
|
||||
} radial_gradient;
|
||||
};
|
||||
} ProgramState;
|
||||
|
||||
@ -161,6 +177,7 @@ typedef struct {
|
||||
Program cross_fade_program;
|
||||
Program inset_shadow_program;
|
||||
Program linear_gradient_program;
|
||||
Program radial_gradient_program;
|
||||
Program outset_shadow_program;
|
||||
Program repeat_program;
|
||||
Program unblurred_outset_shadow_program;
|
||||
@ -278,6 +295,15 @@ void ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
float start_y,
|
||||
float end_x,
|
||||
float end_y);
|
||||
void ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
float end,
|
||||
float hradius,
|
||||
float vradius);
|
||||
|
||||
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES]);
|
||||
|
@ -15,6 +15,7 @@ static guint op_sizes[OP_LAST] = {
|
||||
sizeof (OpTexture),
|
||||
sizeof (OpRepeat),
|
||||
sizeof (OpLinearGradient),
|
||||
sizeof (OpRadialGradient),
|
||||
sizeof (OpColorMatrix),
|
||||
sizeof (OpBlur),
|
||||
sizeof (OpShadow),
|
||||
|
@ -23,21 +23,22 @@ typedef enum
|
||||
OP_CHANGE_SOURCE_TEXTURE = 9,
|
||||
OP_CHANGE_REPEAT = 10,
|
||||
OP_CHANGE_LINEAR_GRADIENT = 11,
|
||||
OP_CHANGE_COLOR_MATRIX = 12,
|
||||
OP_CHANGE_BLUR = 13,
|
||||
OP_CHANGE_INSET_SHADOW = 14,
|
||||
OP_CHANGE_OUTSET_SHADOW = 15,
|
||||
OP_CHANGE_BORDER = 16,
|
||||
OP_CHANGE_BORDER_COLOR = 17,
|
||||
OP_CHANGE_BORDER_WIDTH = 18,
|
||||
OP_CHANGE_CROSS_FADE = 19,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
|
||||
OP_CLEAR = 21,
|
||||
OP_DRAW = 22,
|
||||
OP_DUMP_FRAMEBUFFER = 23,
|
||||
OP_PUSH_DEBUG_GROUP = 24,
|
||||
OP_POP_DEBUG_GROUP = 25,
|
||||
OP_CHANGE_BLEND = 26,
|
||||
OP_CHANGE_RADIAL_GRADIENT = 12,
|
||||
OP_CHANGE_COLOR_MATRIX = 13,
|
||||
OP_CHANGE_BLUR = 14,
|
||||
OP_CHANGE_INSET_SHADOW = 15,
|
||||
OP_CHANGE_OUTSET_SHADOW = 16,
|
||||
OP_CHANGE_BORDER = 17,
|
||||
OP_CHANGE_BORDER_COLOR = 18,
|
||||
OP_CHANGE_BORDER_WIDTH = 19,
|
||||
OP_CHANGE_CROSS_FADE = 20,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 21,
|
||||
OP_CLEAR = 22,
|
||||
OP_DRAW = 23,
|
||||
OP_DUMP_FRAMEBUFFER = 24,
|
||||
OP_PUSH_DEBUG_GROUP = 25,
|
||||
OP_POP_DEBUG_GROUP = 26,
|
||||
OP_CHANGE_BLEND = 27,
|
||||
OP_LAST
|
||||
} OpKind;
|
||||
|
||||
@ -137,6 +138,16 @@ typedef struct
|
||||
float end_point[2];
|
||||
} OpLinearGradient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ColorStopUniformValue color_stops;
|
||||
IntUniformValue n_color_stops;
|
||||
float start;
|
||||
float end;
|
||||
float radius[2];
|
||||
float center[2];
|
||||
} OpRadialGradient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const graphene_matrix_t *matrix;
|
||||
|
@ -30,6 +30,8 @@
|
||||
* @GSK_COLOR_NODE: A node drawing a single color rectangle
|
||||
* @GSK_LINEAR_GRADIENT_NODE: A node drawing a linear gradient
|
||||
* @GSK_REPEATING_LINEAR_GRADIENT_NODE: A node drawing a repeating linear gradient
|
||||
* @GSK_RADIAL_GRADIENT_NODE: A node drawing a radial gradient
|
||||
* @GSK_REPEATING_RADIAL_GRADIENT_NODE: A node drawing a repeating radial gradient
|
||||
* @GSK_BORDER_NODE: A node stroking a border around an area
|
||||
* @GSK_TEXTURE_NODE: A node drawing a #GdkTexture
|
||||
* @GSK_INSET_SHADOW_NODE: A node drawing an inset shadow
|
||||
@ -56,6 +58,8 @@ typedef enum {
|
||||
GSK_COLOR_NODE,
|
||||
GSK_LINEAR_GRADIENT_NODE,
|
||||
GSK_REPEATING_LINEAR_GRADIENT_NODE,
|
||||
GSK_RADIAL_GRADIENT_NODE,
|
||||
GSK_REPEATING_RADIAL_GRADIENT_NODE,
|
||||
GSK_BORDER_NODE,
|
||||
GSK_TEXTURE_NODE,
|
||||
GSK_INSET_SHADOW_NODE,
|
||||
|
@ -104,6 +104,8 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
|
||||
#define GSK_TYPE_TEXTURE_NODE (gsk_texture_node_get_type())
|
||||
#define GSK_TYPE_LINEAR_GRADIENT_NODE (gsk_linear_gradient_node_get_type())
|
||||
#define GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE (gsk_repeating_linear_gradient_node_get_type())
|
||||
#define GSK_TYPE_RADIAL_GRADIENT_NODE (gsk_radial_gradient_node_get_type())
|
||||
#define GSK_TYPE_REPEATING_RADIAL_GRADIENT_NODE (gsk_repeating_radial_gradient_node_get_type())
|
||||
#define GSK_TYPE_BORDER_NODE (gsk_border_node_get_type())
|
||||
#define GSK_TYPE_INSET_SHADOW_NODE (gsk_inset_shadow_node_get_type())
|
||||
#define GSK_TYPE_OUTSET_SHADOW_NODE (gsk_outset_shadow_node_get_type())
|
||||
@ -126,6 +128,8 @@ typedef struct _GskColorNode GskColorNode;
|
||||
typedef struct _GskTextureNode GskTextureNode;
|
||||
typedef struct _GskLinearGradientNode GskLinearGradientNode;
|
||||
typedef struct _GskRepeatingLinearGradientNode GskRepeatingLinearGradientNode;
|
||||
typedef struct _GskRadialGradientNode GskRadialGradientNode;
|
||||
typedef struct _GskRepeatingRadialGradientNode GskRepeatingRadialGradientNode;
|
||||
typedef struct _GskBorderNode GskBorderNode;
|
||||
typedef struct _GskInsetShadowNode GskInsetShadowNode;
|
||||
typedef struct _GskOutsetShadowNode GskOutsetShadowNode;
|
||||
@ -196,6 +200,45 @@ GskRenderNode * gsk_repeating_linear_gradient_node_new (const graph
|
||||
const GskColorStop *color_stops,
|
||||
gsize n_color_stops);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_radial_gradient_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskRenderNode * gsk_radial_gradient_node_new (const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *color_stops,
|
||||
gsize n_color_stops);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gsize gsk_radial_gradient_node_get_n_color_stops (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GskColorStop * gsk_radial_gradient_node_peek_color_stops (GskRenderNode *node,
|
||||
gsize *n_stops);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const graphene_point_t *gsk_radial_gradient_node_peek_center (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_radial_gradient_node_get_hradius (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_radial_gradient_node_get_vradius (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_radial_gradient_node_get_start (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_radial_gradient_node_get_end (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_repeating_radial_gradient_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskRenderNode * gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *color_stops,
|
||||
gsize n_color_stops);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_border_node_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@ -226,6 +226,8 @@ gsk_linear_gradient_node_diff (GskRenderNode *node1,
|
||||
* @start: the point at which the linear gradient will begin
|
||||
* @end: the point at which the linear gradient will finish
|
||||
* @color_stops: (array length=n_color_stops): a pointer to an array of #GskColorStop defining the gradient
|
||||
* The offsets of all color steps must be increasing. The first stop's offset must be >= 0 and the last
|
||||
* stop's offset must be <= 1.
|
||||
* @n_color_stops: the number of elements in @color_stops
|
||||
*
|
||||
* Creates a #GskRenderNode that will create a linear gradient from the given
|
||||
@ -274,6 +276,8 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
|
||||
* @start: the point at which the linear gradient will begin
|
||||
* @end: the point at which the linear gradient will finish
|
||||
* @color_stops: (array length=n_color_stops): a pointer to an array of #GskColorStop defining the gradient
|
||||
* The offsets of all color steps must be increasing. The first stop's offset must be >= 0 and the last
|
||||
* stop's offset must be <= 1.
|
||||
* @n_color_stops: the number of elements in @color_stops
|
||||
*
|
||||
* Creates a #GskRenderNode that will create a repeating linear gradient
|
||||
@ -386,6 +390,300 @@ gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node,
|
||||
return self->stops;
|
||||
}
|
||||
|
||||
/*** GSK_RADIAL_GRADIENT_NODE ***/
|
||||
|
||||
struct _GskRadialGradientNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
|
||||
graphene_point_t center;
|
||||
|
||||
float hradius;
|
||||
float vradius;
|
||||
float start;
|
||||
float end;
|
||||
|
||||
gsize n_stops;
|
||||
GskColorStop *stops;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_radial_gradient_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_RADIAL_GRADIENT_NODE));
|
||||
|
||||
g_free (self->stops);
|
||||
|
||||
parent_class->finalize (node);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_radial_gradient_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
cairo_pattern_t *pattern;
|
||||
gsize i;
|
||||
|
||||
pattern = cairo_pattern_create_radial (0, 0, self->hradius * self->start,
|
||||
0, 0, self->hradius * self->end);
|
||||
|
||||
if (self->hradius != self->vradius)
|
||||
{
|
||||
cairo_matrix_t matrix;
|
||||
|
||||
cairo_matrix_init_scale (&matrix, 1.0, self->hradius / self->vradius);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
}
|
||||
|
||||
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE)
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
else
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
|
||||
for (i = 0; i < self->n_stops; i++)
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
self->stops[i].offset,
|
||||
self->stops[i].color.red,
|
||||
self->stops[i].color.green,
|
||||
self->stops[i].color.blue,
|
||||
self->stops[i].color.alpha);
|
||||
|
||||
gsk_cairo_rectangle (cr, &node->bounds);
|
||||
cairo_translate (cr, self->center.x, self->center.y);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_radial_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GskRadialGradientNode *self1 = (GskRadialGradientNode *) node1;
|
||||
GskRadialGradientNode *self2 = (GskRadialGradientNode *) node2;
|
||||
|
||||
if (graphene_point_equal (&self1->center, &self2->center) &&
|
||||
self1->hradius == self2->hradius &&
|
||||
self1->vradius == self2->vradius &&
|
||||
self1->start == self2->start &&
|
||||
self1->end == self2->end &&
|
||||
self1->n_stops == self2->n_stops)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < self1->n_stops; i++)
|
||||
{
|
||||
GskColorStop *stop1 = &self1->stops[i];
|
||||
GskColorStop *stop2 = &self2->stops[i];
|
||||
|
||||
if (stop1->offset == stop2->offset &&
|
||||
gdk_rgba_equal (&stop1->color, &stop2->color))
|
||||
continue;
|
||||
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_radial_gradient_node_new:
|
||||
* @bounds: the bounds of the node
|
||||
* @center: the center of the gradient
|
||||
* @hradius: the horizontal radius
|
||||
* @vradius: the vertical radius
|
||||
* @start: a percentage >= 0 that defines the start of the gradient around @center
|
||||
* @end: a percentage >= 0 that defines the end of the gradient around @center
|
||||
* @color_stops: (array length=n_color_stops): a pointer to an array of #GskColorStop defining the gradient
|
||||
* The offsets of all color steps must be increasing. The first stop's offset must be >= 0 and the last
|
||||
* stop's offset must be <= 1.
|
||||
* @n_color_stops: the number of elements in @color_stops
|
||||
*
|
||||
* Creates a #GskRenderNode that draws a radial gradient. The radial gradient
|
||||
* starts around @center. The size of the gradient is dictated by @hradius
|
||||
* in horizontal orientation and by @vradius in vertial orientation.
|
||||
*
|
||||
* Returns: (transfer full) (type GskRadialGradientNode): A new #GskRenderNode
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_radial_gradient_node_new (const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *color_stops,
|
||||
gsize n_color_stops)
|
||||
{
|
||||
GskRadialGradientNode *self;
|
||||
GskRenderNode *node;
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (bounds != NULL, NULL);
|
||||
g_return_val_if_fail (center != NULL, NULL);
|
||||
g_return_val_if_fail (hradius > 0., NULL);
|
||||
g_return_val_if_fail (vradius > 0., NULL);
|
||||
g_return_val_if_fail (start >= 0., NULL);
|
||||
g_return_val_if_fail (end >= 0., NULL);
|
||||
g_return_val_if_fail (end > start, NULL);
|
||||
g_return_val_if_fail (color_stops != NULL, NULL);
|
||||
g_return_val_if_fail (n_color_stops >= 2, NULL);
|
||||
g_return_val_if_fail (color_stops[0].offset >= 0, NULL);
|
||||
for (i = 1; i < n_color_stops; i++)
|
||||
g_return_val_if_fail (color_stops[i].offset >= color_stops[i - 1].offset, NULL);
|
||||
g_return_val_if_fail (color_stops[n_color_stops - 1].offset <= 1, NULL);
|
||||
|
||||
self = gsk_render_node_alloc (GSK_RADIAL_GRADIENT_NODE);
|
||||
node = (GskRenderNode *) self;
|
||||
|
||||
graphene_rect_init_from_rect (&node->bounds, bounds);
|
||||
graphene_point_init_from_point (&self->center, center);
|
||||
|
||||
self->hradius = hradius;
|
||||
self->vradius = vradius;
|
||||
self->start = start;
|
||||
self->end = end;
|
||||
|
||||
self->n_stops = n_color_stops;
|
||||
self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
|
||||
memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_repeating_radial_gradient_node_new:
|
||||
* @bounds: the bounds of the node
|
||||
* @center: the center of the gradient
|
||||
* @hradius: the horizontal radius
|
||||
* @vradius: the vertical radius
|
||||
* @start: a percentage >= 0 that defines the start of the gradient around @center
|
||||
* @end: a percentage >= 0 that defines the end of the gradient around @center
|
||||
* @color_stops: (array length=n_color_stops): a pointer to an array of #GskColorStop defining the gradient
|
||||
* The offsets of all color steps must be increasing. The first stop's offset must be >= 0 and the last
|
||||
* stop's offset must be <= 1.
|
||||
* @n_color_stops: the number of elements in @color_stops
|
||||
*
|
||||
* Creates a #GskRenderNode that draws a repeating radial gradient. The radial gradient
|
||||
* starts around @center. The size of the gradient is dictated by @hradius
|
||||
* in horizontal orientation and by @vradius in vertial orientation.
|
||||
*
|
||||
* Returns: (transfer full) (type GskRepeatingRadialGradientNode): A new #GskRenderNode
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *color_stops,
|
||||
gsize n_color_stops)
|
||||
{
|
||||
GskRadialGradientNode *self;
|
||||
GskRenderNode *node;
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (bounds != NULL, NULL);
|
||||
g_return_val_if_fail (center != NULL, NULL);
|
||||
g_return_val_if_fail (hradius > 0., NULL);
|
||||
g_return_val_if_fail (vradius > 0., NULL);
|
||||
g_return_val_if_fail (start >= 0., NULL);
|
||||
g_return_val_if_fail (end >= 0., NULL);
|
||||
g_return_val_if_fail (end > start, NULL);
|
||||
g_return_val_if_fail (color_stops != NULL, NULL);
|
||||
g_return_val_if_fail (n_color_stops >= 2, NULL);
|
||||
g_return_val_if_fail (color_stops[0].offset >= 0, NULL);
|
||||
for (i = 1; i < n_color_stops; i++)
|
||||
g_return_val_if_fail (color_stops[i].offset >= color_stops[i - 1].offset, NULL);
|
||||
g_return_val_if_fail (color_stops[n_color_stops - 1].offset <= 1, NULL);
|
||||
|
||||
self = gsk_render_node_alloc (GSK_REPEATING_RADIAL_GRADIENT_NODE);
|
||||
node = (GskRenderNode *) self;
|
||||
|
||||
graphene_rect_init_from_rect (&node->bounds, bounds);
|
||||
graphene_point_init_from_point (&self->center, center);
|
||||
|
||||
self->hradius = hradius;
|
||||
self->vradius = vradius;
|
||||
self->start = start;
|
||||
self->end = end;
|
||||
|
||||
self->n_stops = n_color_stops;
|
||||
self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
|
||||
memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_radial_gradient_node_get_n_color_stops (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
return self->n_stops;
|
||||
}
|
||||
|
||||
const GskColorStop *
|
||||
gsk_radial_gradient_node_peek_color_stops (GskRenderNode *node,
|
||||
gsize *n_stops)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
if (n_stops != NULL)
|
||||
*n_stops = self->n_stops;
|
||||
|
||||
return self->stops;
|
||||
}
|
||||
|
||||
const graphene_point_t *
|
||||
gsk_radial_gradient_node_peek_center (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
return &self->center;
|
||||
}
|
||||
|
||||
float
|
||||
gsk_radial_gradient_node_get_hradius (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
return self->hradius;
|
||||
}
|
||||
|
||||
float
|
||||
gsk_radial_gradient_node_get_vradius (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
return self->vradius;
|
||||
}
|
||||
|
||||
float
|
||||
gsk_radial_gradient_node_get_start (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
return self->start;
|
||||
}
|
||||
|
||||
float
|
||||
gsk_radial_gradient_node_get_end (GskRenderNode *node)
|
||||
{
|
||||
GskRadialGradientNode *self = (GskRadialGradientNode *) node;
|
||||
|
||||
return self->end;
|
||||
}
|
||||
|
||||
/*** GSK_BORDER_NODE ***/
|
||||
|
||||
struct _GskBorderNode
|
||||
@ -4191,6 +4489,8 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_cairo_node, GSK_CAIRO_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_color_node, GSK_COLOR_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_linear_gradient_node, GSK_LINEAR_GRADIENT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_linear_gradient_node, GSK_REPEATING_LINEAR_GRADIENT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_radial_gradient_node, GSK_RADIAL_GRADIENT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_radial_gradient_node, GSK_REPEATING_RADIAL_GRADIENT_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_border_node, GSK_BORDER_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_texture_node, GSK_TEXTURE_NODE)
|
||||
GSK_DEFINE_RENDER_NODE_TYPE (gsk_inset_shadow_node, GSK_INSET_SHADOW_NODE)
|
||||
@ -4291,6 +4591,38 @@ gsk_render_node_init_types_once (void)
|
||||
gsk_render_node_types[GSK_REPEATING_LINEAR_GRADIENT_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
GSK_RADIAL_GRADIENT_NODE,
|
||||
sizeof (GskRadialGradientNode),
|
||||
NULL,
|
||||
gsk_radial_gradient_node_finalize,
|
||||
gsk_radial_gradient_node_draw,
|
||||
NULL,
|
||||
gsk_radial_gradient_node_diff,
|
||||
};
|
||||
|
||||
GType node_type = gsk_render_node_type_register_static (I_("GskRadialGradientNode"), &node_info);
|
||||
gsk_render_node_types[GSK_RADIAL_GRADIENT_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
GSK_REPEATING_RADIAL_GRADIENT_NODE,
|
||||
sizeof (GskRadialGradientNode),
|
||||
NULL,
|
||||
gsk_radial_gradient_node_finalize,
|
||||
gsk_radial_gradient_node_draw,
|
||||
NULL,
|
||||
gsk_radial_gradient_node_diff,
|
||||
};
|
||||
|
||||
GType node_type = gsk_render_node_type_register_static (I_("GskRepeatingRadialGradientNode"), &node_info);
|
||||
gsk_render_node_types[GSK_REPEATING_RADIAL_GRADIENT_NODE] = node_type;
|
||||
}
|
||||
|
||||
{
|
||||
const GskRenderNodeTypeInfo node_info =
|
||||
{
|
||||
|
@ -1012,6 +1012,63 @@ parse_repeating_linear_gradient_node (GtkCssParser *parser)
|
||||
return parse_linear_gradient_node_internal (parser, TRUE);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_radial_gradient_node_internal (GtkCssParser *parser,
|
||||
gboolean repeating)
|
||||
{
|
||||
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
|
||||
graphene_point_t center = GRAPHENE_POINT_INIT (25, 25);
|
||||
double hradius = 25.0;
|
||||
double vradius = 25.0;
|
||||
double start = 0;
|
||||
double end = 1.0;
|
||||
GArray *stops = NULL;
|
||||
const Declaration declarations[] = {
|
||||
{ "bounds", parse_rect, NULL, &bounds },
|
||||
{ "center", parse_point, NULL, ¢er },
|
||||
{ "hradius", parse_double, NULL, &hradius },
|
||||
{ "vradius", parse_double, NULL, &vradius },
|
||||
{ "start", parse_double, NULL, &start },
|
||||
{ "end", parse_double, NULL, &end },
|
||||
{ "stops", parse_stops, clear_stops, &stops },
|
||||
};
|
||||
GskRenderNode *result;
|
||||
|
||||
parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
|
||||
if (stops == NULL)
|
||||
{
|
||||
GskColorStop from = { 0.0, GDK_RGBA("AAFF00") };
|
||||
GskColorStop to = { 1.0, GDK_RGBA("FF00CC") };
|
||||
|
||||
stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop));
|
||||
g_array_append_val (stops, from);
|
||||
g_array_append_val (stops, to);
|
||||
}
|
||||
|
||||
if (repeating)
|
||||
result = gsk_repeating_radial_gradient_node_new (&bounds, ¢er, hradius, vradius, start, end,
|
||||
(GskColorStop *) stops->data, stops->len);
|
||||
else
|
||||
result = gsk_radial_gradient_node_new (&bounds, ¢er, hradius, vradius, start, end,
|
||||
(GskColorStop *) stops->data, stops->len);
|
||||
|
||||
g_array_free (stops, TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_radial_gradient_node (GtkCssParser *parser)
|
||||
{
|
||||
return parse_radial_gradient_node_internal (parser, FALSE);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_repeating_radial_gradient_node (GtkCssParser *parser)
|
||||
{
|
||||
return parse_radial_gradient_node_internal (parser, TRUE);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_inset_shadow_node (GtkCssParser *parser)
|
||||
{
|
||||
@ -1535,10 +1592,12 @@ parse_node (GtkCssParser *parser,
|
||||
{ "debug", parse_debug_node },
|
||||
{ "inset-shadow", parse_inset_shadow_node },
|
||||
{ "linear-gradient", parse_linear_gradient_node },
|
||||
{ "radial-gradient", parse_radial_gradient_node },
|
||||
{ "opacity", parse_opacity_node },
|
||||
{ "outset-shadow", parse_outset_shadow_node },
|
||||
{ "repeat", parse_repeat_node },
|
||||
{ "repeating-linear-gradient", parse_repeating_linear_gradient_node },
|
||||
{ "repeating-radial-gradient", parse_repeating_radial_gradient_node },
|
||||
{ "rounded-clip", parse_rounded_clip_node },
|
||||
{ "shadow", parse_shadow_node },
|
||||
{ "text", parse_text_node },
|
||||
@ -2003,6 +2062,42 @@ render_node_print (Printer *p,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
{
|
||||
const gsize n_stops = gsk_radial_gradient_node_get_n_color_stops (node);
|
||||
const GskColorStop *stops = gsk_radial_gradient_node_peek_color_stops (node, NULL);
|
||||
gsize i;
|
||||
|
||||
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE)
|
||||
start_node (p, "repeating-radial-gradient");
|
||||
else
|
||||
start_node (p, "radial-gradient");
|
||||
|
||||
append_rect_param (p, "bounds", &node->bounds);
|
||||
append_point_param (p, "center", gsk_radial_gradient_node_peek_center (node));
|
||||
append_float_param (p, "hradius", gsk_radial_gradient_node_get_hradius (node), 0.0f);
|
||||
append_float_param (p, "vradius", gsk_radial_gradient_node_get_vradius (node), 0.0f);
|
||||
append_float_param (p, "start", gsk_radial_gradient_node_get_start (node), 0.0f);
|
||||
append_float_param (p, "end", gsk_radial_gradient_node_get_end (node), 1.0f);
|
||||
|
||||
_indent (p);
|
||||
g_string_append (p->str, "stops: ");
|
||||
for (i = 0; i < n_stops; i ++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (p->str, ", ");
|
||||
|
||||
string_append_double (p->str, stops[i].offset);
|
||||
g_string_append_c (p->str, ' ');
|
||||
append_rgba (p->str, &stops[i].color);
|
||||
}
|
||||
g_string_append (p->str, ";\n");
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_OPACITY_NODE:
|
||||
{
|
||||
start_node (p, "opacity");
|
||||
|
@ -7,6 +7,7 @@ gsk_private_gl_shaders = [
|
||||
'resources/glsl/coloring.glsl',
|
||||
'resources/glsl/color.glsl',
|
||||
'resources/glsl/linear_gradient.glsl',
|
||||
'resources/glsl/radial_gradient.glsl',
|
||||
'resources/glsl/color_matrix.glsl',
|
||||
'resources/glsl/blur.glsl',
|
||||
'resources/glsl/inset_shadow.glsl',
|
||||
|
@ -10,9 +10,7 @@ _OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
final_color = u_color;
|
||||
final_color.rgb *= final_color.a; // pre-multiply
|
||||
final_color *= u_alpha;
|
||||
final_color = premultiply(u_color) * u_alpha;
|
||||
|
||||
RoundedRect outside = create_rect(u_outline_rect);
|
||||
RoundedRect inside = rounded_rect_shrink (outside, u_widths);
|
||||
|
@ -6,10 +6,7 @@ _OUT_ vec4 final_color;
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
final_color = u_color;
|
||||
// Pre-multiply alpha
|
||||
final_color.rgb *= final_color.a;
|
||||
final_color *= u_alpha;
|
||||
final_color = premultiply(u_color) * u_alpha;
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
|
@ -8,10 +8,7 @@ void main() {
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
|
||||
final_color = u_color;
|
||||
// pre-multiply
|
||||
final_color.rgb *= final_color.a;
|
||||
final_color *= u_alpha;
|
||||
final_color = premultiply(u_color) * u_alpha;
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
|
@ -25,10 +25,10 @@ void main() {
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i].r = u_color_stops[(i * 5) + 1];
|
||||
color_stops[i].g = u_color_stops[(i * 5) + 2];
|
||||
color_stops[i].b = u_color_stops[(i * 5) + 3];
|
||||
color_stops[i].a = u_color_stops[(i * 5) + 4];
|
||||
color_stops[i] = premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,8 +66,5 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
/* Pre-multiply */
|
||||
color.rgb *= color.a;
|
||||
|
||||
setOutputColor(color * u_alpha);
|
||||
}
|
||||
|
@ -10,10 +10,7 @@ void main() {
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
|
||||
final_color = u_color;
|
||||
// pre-multiply
|
||||
final_color.rgb *= final_color.a;
|
||||
final_color *= u_alpha;
|
||||
final_color = premultiply(u_color) * u_alpha;
|
||||
|
||||
RoundedRect outline = create_rect(u_outline_rect);
|
||||
rounded_rect_transform(outline, u_modelview);
|
||||
|
@ -35,3 +35,7 @@ create_rect(vec4[3] data)
|
||||
|
||||
return RoundedRect(bounds, corner_points1, corner_points2);
|
||||
}
|
||||
|
||||
vec4 premultiply(vec4 c) {
|
||||
return vec4(c.rgb * c.a, c.a);
|
||||
}
|
||||
|
84
gsk/resources/glsl/radial_gradient.glsl
Normal file
84
gsk/resources/glsl/radial_gradient.glsl
Normal file
@ -0,0 +1,84 @@
|
||||
// VERTEX_SHADER
|
||||
uniform float u_start;
|
||||
uniform float u_end;
|
||||
uniform float u_color_stops[8 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec2 u_radius;
|
||||
uniform vec2 u_center;
|
||||
|
||||
_OUT_ vec2 center;
|
||||
_OUT_ vec4 color_stops[8];
|
||||
_OUT_ float color_offsets[8];
|
||||
_OUT_ float start;
|
||||
_OUT_ float end;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
center = (u_modelview * vec4(u_center, 0, 1)).xy;
|
||||
start = u_start;
|
||||
end = u_end;
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
#ifdef GSK_LEGACY
|
||||
uniform int u_num_color_stops;
|
||||
#else
|
||||
uniform highp int u_num_color_stops;
|
||||
#endif
|
||||
|
||||
uniform vec2 u_radius;
|
||||
uniform float u_end;
|
||||
|
||||
_IN_ vec2 center;
|
||||
_IN_ vec4 color_stops[8];
|
||||
_IN_ float color_offsets[8];
|
||||
_IN_ float start;
|
||||
_IN_ float end;
|
||||
|
||||
// The offsets in the color stops are relative to the
|
||||
// start and end values of the gradient.
|
||||
float abs_offset(float offset) {
|
||||
return start + ((end - start) * offset);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 pixel = get_frag_coord();
|
||||
vec2 rel = (center - pixel) / (u_radius);
|
||||
float d = sqrt(dot(rel, rel));
|
||||
|
||||
if (d < abs_offset (color_offsets[0])) {
|
||||
setOutputColor(color_stops[0] * u_alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d > end) {
|
||||
setOutputColor(color_stops[u_num_color_stops - 1] * u_alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 color = vec4(0, 0, 0, 0);
|
||||
for (int i = 1; i < u_num_color_stops; i++) {
|
||||
float last_offset = abs_offset(color_offsets[i - 1]);
|
||||
float this_offset = abs_offset(color_offsets[i]);
|
||||
|
||||
// We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
|
||||
// We now need to map `d` between those two offsets and simply mix linearly between them
|
||||
if (d >= last_offset && d <= this_offset) {
|
||||
float f = (d - last_offset) / (this_offset - last_offset);
|
||||
|
||||
color = mix(color_stops[i - 1], color_stops[i], f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setOutputColor(color * u_alpha);
|
||||
}
|
@ -257,6 +257,8 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
case GSK_SHADOW_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
default:
|
||||
FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
|
||||
|
||||
|
@ -80,18 +80,13 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
|
||||
double height)
|
||||
{
|
||||
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
GskColorStop *stops;
|
||||
double x, y;
|
||||
double radius, yscale;
|
||||
double hradius, vradius;
|
||||
double start, end;
|
||||
double r1, r2, r3, r4, r;
|
||||
double offset;
|
||||
int i, last;
|
||||
cairo_t *cr;
|
||||
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
x = _gtk_css_position_value_get_x (radial->position, width);
|
||||
y = _gtk_css_position_value_get_y (radial->position, height);
|
||||
@ -101,13 +96,13 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
|
||||
switch (radial->size)
|
||||
{
|
||||
case GTK_CSS_EXPLICIT_SIZE:
|
||||
radius = _gtk_css_number_value_get (radial->sizes[0], width);
|
||||
hradius = _gtk_css_number_value_get (radial->sizes[0], width);
|
||||
break;
|
||||
case GTK_CSS_CLOSEST_SIDE:
|
||||
radius = MIN (MIN (x, width - x), MIN (y, height - y));
|
||||
hradius = MIN (MIN (x, width - x), MIN (y, height - y));
|
||||
break;
|
||||
case GTK_CSS_FARTHEST_SIDE:
|
||||
radius = MAX (MAX (x, width - x), MAX (y, height - y));
|
||||
hradius = MAX (MAX (x, width - x), MAX (y, height - y));
|
||||
break;
|
||||
case GTK_CSS_CLOSEST_CORNER:
|
||||
case GTK_CSS_FARTHEST_CORNER:
|
||||
@ -119,19 +114,17 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
|
||||
r = MIN ( MIN (r1, r2), MIN (r3, r4));
|
||||
else
|
||||
r = MAX ( MAX (r1, r2), MAX (r3, r4));
|
||||
radius = sqrt (r);
|
||||
hradius = sqrt (r);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
radius = MAX (1.0, radius);
|
||||
yscale = 1.0;
|
||||
hradius = MAX (1.0, hradius);
|
||||
vradius = hradius;
|
||||
}
|
||||
else
|
||||
{
|
||||
double hradius, vradius;
|
||||
|
||||
switch (radial->size)
|
||||
{
|
||||
case GTK_CSS_EXPLICIT_SIZE:
|
||||
@ -160,27 +153,14 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
|
||||
|
||||
hradius = MAX (1.0, hradius);
|
||||
vradius = MAX (1.0, vradius);
|
||||
|
||||
radius = hradius;
|
||||
yscale = vradius / hradius;
|
||||
}
|
||||
|
||||
gtk_css_image_radial_get_start_end (radial, radius, &start, &end);
|
||||
|
||||
pattern = cairo_pattern_create_radial (0, 0, radius * start, 0, 0, radius * end);
|
||||
if (yscale != 1.0)
|
||||
{
|
||||
cairo_matrix_init_scale (&matrix, 1.0, 1.0 / yscale);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
}
|
||||
|
||||
if (radial->repeating)
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
else
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
gtk_css_image_radial_get_start_end (radial, hradius, &start, &end);
|
||||
|
||||
offset = start;
|
||||
last = -1;
|
||||
stops = g_newa (GskColorStop, radial->n_stops);
|
||||
|
||||
for (i = 0; i < radial->n_stops; i++)
|
||||
{
|
||||
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
|
||||
@ -196,39 +176,44 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
|
||||
continue;
|
||||
}
|
||||
else
|
||||
pos = _gtk_css_number_value_get (stop->offset, radius) / radius;
|
||||
pos = MIN (1.0, _gtk_css_number_value_get (stop->offset, hradius) / hradius);
|
||||
|
||||
pos = MAX (pos, 0);
|
||||
step = (pos - offset) / (i - last);
|
||||
for (last = last + 1; last <= i; last++)
|
||||
{
|
||||
const GdkRGBA *rgba;
|
||||
|
||||
stop = &radial->color_stops[last];
|
||||
|
||||
rgba = gtk_css_color_value_get_rgba (stop->color);
|
||||
offset += step;
|
||||
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
(offset - start) / (end - start),
|
||||
rgba->red,
|
||||
rgba->green,
|
||||
rgba->blue,
|
||||
rgba->alpha);
|
||||
stops[last].offset = (offset - start) / (end - start);
|
||||
stops[last].color = *gtk_css_color_value_get_rgba (stop->color);
|
||||
}
|
||||
|
||||
offset = pos;
|
||||
last = i;
|
||||
}
|
||||
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_translate (cr, x, y);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
cairo_destroy (cr);
|
||||
if (radial->repeating)
|
||||
gtk_snapshot_append_repeating_radial_gradient (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height),
|
||||
&GRAPHENE_POINT_INIT (x, y),
|
||||
hradius,
|
||||
vradius,
|
||||
start,
|
||||
end,
|
||||
stops,
|
||||
radial->n_stops);
|
||||
else
|
||||
gtk_snapshot_append_radial_gradient (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height),
|
||||
&GRAPHENE_POINT_INIT (x, y),
|
||||
hradius,
|
||||
vradius,
|
||||
start,
|
||||
end,
|
||||
stops,
|
||||
radial->n_stops);
|
||||
}
|
||||
|
||||
static guint
|
||||
|
@ -1250,6 +1250,9 @@ captured_motion (GtkEventController *controller,
|
||||
if (!priv->use_indicators)
|
||||
return;
|
||||
|
||||
if (!priv->child)
|
||||
return;
|
||||
|
||||
target = gtk_event_controller_get_target (controller);
|
||||
state = gtk_event_controller_get_current_event_state (controller);
|
||||
event = gtk_event_controller_get_current_event (controller);
|
||||
|
@ -1967,6 +1967,82 @@ gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot *snapshot,
|
||||
gtk_snapshot_append_node_internal (snapshot, node);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_snapshot_append_radial_gradient (GtkSnapshot *snapshot,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
graphene_rect_t real_bounds;
|
||||
graphene_point_t real_center;
|
||||
float scale_x, scale_y, dx, dy;
|
||||
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
g_return_if_fail (center != NULL);
|
||||
g_return_if_fail (stops != NULL);
|
||||
g_return_if_fail (n_stops > 1);
|
||||
|
||||
gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
|
||||
gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
|
||||
real_center.x = scale_x * center->x + dx;
|
||||
real_center.y = scale_y * center->y + dy;
|
||||
|
||||
node = gsk_radial_gradient_node_new (&real_bounds,
|
||||
&real_center,
|
||||
hradius * scale_x,
|
||||
vradius * scale_y,
|
||||
start,
|
||||
end,
|
||||
stops,
|
||||
n_stops);
|
||||
|
||||
gtk_snapshot_append_node_internal (snapshot, node);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_snapshot_append_repeating_radial_gradient (GtkSnapshot *snapshot,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
graphene_rect_t real_bounds;
|
||||
graphene_point_t real_center;
|
||||
float scale_x, scale_y, dx, dy;
|
||||
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
g_return_if_fail (center != NULL);
|
||||
g_return_if_fail (stops != NULL);
|
||||
g_return_if_fail (n_stops > 1);
|
||||
|
||||
gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
|
||||
gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
|
||||
real_center.x = scale_x * center->x + dx;
|
||||
real_center.y = scale_y * center->y + dy;
|
||||
|
||||
node = gsk_repeating_radial_gradient_node_new (&real_bounds,
|
||||
&real_center,
|
||||
hradius * scale_x,
|
||||
vradius * scale_y,
|
||||
start,
|
||||
end,
|
||||
stops,
|
||||
n_stops);
|
||||
|
||||
gtk_snapshot_append_node_internal (snapshot, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_append_border:
|
||||
* @snapshot: a #GtkSnapshot
|
||||
|
@ -165,6 +165,26 @@ void gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_append_radial_gradient (GtkSnapshot *snapshot,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_append_repeating_radial_gradient (GtkSnapshot *snapshot,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_point_t *center,
|
||||
float hradius,
|
||||
float vradius,
|
||||
float start,
|
||||
float end,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_snapshot_append_border (GtkSnapshot *snapshot,
|
||||
const GskRoundedRect *outline,
|
||||
const float border_width[4],
|
||||
|
@ -131,6 +131,8 @@ create_list_model_for_render_node (GskRenderNode *node)
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_BORDER_NODE:
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
@ -234,6 +236,10 @@ node_type_name (GskRenderNodeType type)
|
||||
return "Linear Gradient";
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
return "Repeating Linear Gradient";
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
return "Radial Gradient";
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
return "Repeating Radial Gradient";
|
||||
case GSK_BORDER_NODE:
|
||||
return "Border";
|
||||
case GSK_TEXTURE_NODE:
|
||||
@ -279,6 +285,8 @@ node_name (GskRenderNode *node)
|
||||
case GSK_CAIRO_NODE:
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_BORDER_NODE:
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
@ -625,6 +633,52 @@ populate_render_node_properties (GtkListStore *store,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
{
|
||||
const graphene_point_t *center = gsk_radial_gradient_node_peek_center (node);
|
||||
const float start = gsk_radial_gradient_node_get_start (node);
|
||||
const float end = gsk_radial_gradient_node_get_end (node);
|
||||
const float hradius = gsk_radial_gradient_node_get_hradius (node);
|
||||
const float vradius = gsk_radial_gradient_node_get_vradius (node);
|
||||
const gsize n_stops = gsk_radial_gradient_node_get_n_color_stops (node);
|
||||
const GskColorStop *stops = gsk_radial_gradient_node_peek_color_stops (node, NULL);
|
||||
int i;
|
||||
GString *s;
|
||||
GdkTexture *texture;
|
||||
|
||||
tmp = g_strdup_printf ("%.2f, %.2f", center->x, center->y);
|
||||
add_text_row (store, "Center", tmp);
|
||||
g_free (tmp);
|
||||
|
||||
tmp = g_strdup_printf ("%.2f ⟶ %.2f", start, end);
|
||||
add_text_row (store, "Direction", tmp);
|
||||
g_free (tmp);
|
||||
|
||||
tmp = g_strdup_printf ("%.2f, %.2f", hradius, vradius);
|
||||
add_text_row (store, "Radius", tmp);
|
||||
g_free (tmp);
|
||||
|
||||
s = g_string_new ("");
|
||||
for (i = 0; i < n_stops; i++)
|
||||
{
|
||||
tmp = gdk_rgba_to_string (&stops[i].color);
|
||||
g_string_append_printf (s, "%.2f, %s\n", stops[i].offset, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
texture = get_linear_gradient_texture (n_stops, stops);
|
||||
gtk_list_store_insert_with_values (store, NULL, -1,
|
||||
0, "Color Stops",
|
||||
1, s->str,
|
||||
2, TRUE,
|
||||
3, texture,
|
||||
-1);
|
||||
g_string_free (s, TRUE);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TEXT_NODE:
|
||||
{
|
||||
const PangoFont *font = gsk_text_node_peek_font (node);
|
||||
|
Loading…
Reference in New Issue
Block a user