forked from AuroraMiddleware/gtk
Make mask nodes more versatile
Add a GskMaskMode enumeration and implement it in the GL and cairo renderers.
This commit is contained in:
parent
f1311dc053
commit
0eb791eaaa
@ -92,7 +92,7 @@ demo4_widget_snapshot (GtkWidget *widget,
|
|||||||
width = gtk_widget_get_width (widget);
|
width = gtk_widget_get_width (widget);
|
||||||
height = gtk_widget_get_height (widget);
|
height = gtk_widget_get_height (widget);
|
||||||
|
|
||||||
gtk_snapshot_push_mask (snapshot);
|
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_INVERTED_ALPHA);
|
||||||
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
|
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
|
||||||
gtk_snapshot_pop (snapshot);
|
gtk_snapshot_pop (snapshot);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "gdkdisplay-wayland.h"
|
#include "gdkdisplay-wayland.h"
|
||||||
#include "gdksurface-wayland.h"
|
#include "gdksurface-wayland.h"
|
||||||
|
#include "gdksurface-wayland-private.h"
|
||||||
|
|
||||||
#include "gdkwaylanddisplay.h"
|
#include "gdkwaylanddisplay.h"
|
||||||
#include "gdkwaylandglcontext.h"
|
#include "gdkwaylandglcontext.h"
|
||||||
@ -60,10 +61,15 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
|
|||||||
cairo_region_t *painted)
|
cairo_region_t *painted)
|
||||||
{
|
{
|
||||||
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
|
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
|
||||||
|
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||||
|
int dx = impl->pending_buffer_offset_x;
|
||||||
|
int dy = impl->pending_buffer_offset_y;
|
||||||
|
|
||||||
gdk_wayland_surface_sync (surface);
|
gdk_wayland_surface_sync (surface);
|
||||||
gdk_wayland_surface_request_frame (surface);
|
gdk_wayland_surface_request_frame (surface);
|
||||||
|
|
||||||
|
wl_surface_offset (impl->display_server.wl_surface, dx, dy);
|
||||||
|
|
||||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
|
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
|
||||||
|
|
||||||
gdk_wayland_surface_notify_committed (surface);
|
gdk_wayland_surface_notify_committed (surface);
|
||||||
|
@ -229,7 +229,7 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
|
|||||||
|
|
||||||
if (impl->display_server.egl_window)
|
if (impl->display_server.egl_window)
|
||||||
wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
|
wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
|
||||||
if (impl->display_server.wl_surface)
|
if (impl->display_server.wl_surface && scale_changed)
|
||||||
wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
|
wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
|
||||||
|
|
||||||
gdk_surface_invalidate_rect (surface, NULL);
|
gdk_surface_invalidate_rect (surface, NULL);
|
||||||
@ -588,6 +588,7 @@ gdk_wayland_surface_sync_offset (GdkSurface *surface)
|
|||||||
WL_SURFACE_OFFSET_SINCE_VERSION)
|
WL_SURFACE_OFFSET_SINCE_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (impl->pending_buffer_offset_x == 0 &&
|
if (impl->pending_buffer_offset_x == 0 &&
|
||||||
impl->pending_buffer_offset_y == 0)
|
impl->pending_buffer_offset_y == 0)
|
||||||
return;
|
return;
|
||||||
@ -597,6 +598,7 @@ gdk_wayland_surface_sync_offset (GdkSurface *surface)
|
|||||||
impl->pending_buffer_offset_y);
|
impl->pending_buffer_offset_y);
|
||||||
impl->pending_buffer_offset_x = 0;
|
impl->pending_buffer_offset_x = 0;
|
||||||
impl->pending_buffer_offset_y = 0;
|
impl->pending_buffer_offset_y = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -62,7 +62,8 @@ GSK_GL_DEFINE_PROGRAM (linear_gradient,
|
|||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (mask,
|
GSK_GL_DEFINE_PROGRAM (mask,
|
||||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("mask.glsl")),
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("mask.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, MASK_SOURCE, u_mask))
|
GSK_GL_ADD_UNIFORM (1, MASK_SOURCE, u_mask)
|
||||||
|
GSK_GL_ADD_UNIFORM (2, MASK_MODE, u_mode))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (outset_shadow,
|
GSK_GL_DEFINE_PROGRAM (outset_shadow,
|
||||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("outset_shadow.glsl")),
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("outset_shadow.glsl")),
|
||||||
|
@ -3278,8 +3278,8 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
||||||
const GskRenderNode *node)
|
const GskRenderNode *node)
|
||||||
{
|
{
|
||||||
const GskRenderNode *source = gsk_mask_node_get_source (node);
|
const GskRenderNode *source = gsk_mask_node_get_source (node);
|
||||||
const GskRenderNode *mask = gsk_mask_node_get_mask (node);
|
const GskRenderNode *mask = gsk_mask_node_get_mask (node);
|
||||||
@ -3293,6 +3293,7 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
|||||||
mask_offscreen.bounds = &node->bounds;
|
mask_offscreen.bounds = &node->bounds;
|
||||||
mask_offscreen.force_offscreen = TRUE;
|
mask_offscreen.force_offscreen = TRUE;
|
||||||
mask_offscreen.reset_clip = TRUE;
|
mask_offscreen.reset_clip = TRUE;
|
||||||
|
mask_offscreen.do_not_cache = TRUE;
|
||||||
|
|
||||||
/* TODO: We create 2 textures here as big as the mask node, but both
|
/* TODO: We create 2 textures here as big as the mask node, but both
|
||||||
* nodes might be a lot smaller than that.
|
* nodes might be a lot smaller than that.
|
||||||
@ -3323,6 +3324,9 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
|||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
GL_TEXTURE1,
|
GL_TEXTURE1,
|
||||||
mask_offscreen.texture_id);
|
mask_offscreen.texture_id);
|
||||||
|
gsk_gl_program_set_uniform1i (job->current_program,
|
||||||
|
UNIFORM_MASK_MODE, 0,
|
||||||
|
gsk_mask_node_get_mask_mode (node));
|
||||||
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
|
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
|
||||||
gsk_gl_render_job_end_draw (job);
|
gsk_gl_render_job_end_draw (job);
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,24 @@ void main() {
|
|||||||
// FRAGMENT_SHADER:
|
// FRAGMENT_SHADER:
|
||||||
// mask.glsl
|
// mask.glsl
|
||||||
|
|
||||||
|
uniform int u_mode;
|
||||||
uniform sampler2D u_mask;
|
uniform sampler2D u_mask;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 source = GskTexture(u_source, vUv);
|
vec4 source = GskTexture(u_source, vUv);
|
||||||
vec4 mask = GskTexture(u_mask, vUv);
|
vec4 mask = GskTexture(u_mask, vUv);
|
||||||
gskSetOutputColor(vec4 (source * mask.a));
|
float mask_value;
|
||||||
|
|
||||||
|
if (u_mode == 0)
|
||||||
|
mask_value = mask.a;
|
||||||
|
else if (u_mode == 1)
|
||||||
|
mask_value = 1 - mask.a;
|
||||||
|
else if (u_mode == 2)
|
||||||
|
mask_value = (0.2126 * mask.r + 0.7152 * mask.g + 0.0722 * mask.b) * mask.a;
|
||||||
|
else if (u_mode == 3)
|
||||||
|
mask_value = 1 - (0.2126 * mask.r + 0.7152 * mask.g + 0.0722 * mask.b) * mask.a;
|
||||||
|
else
|
||||||
|
mask_value = 0;
|
||||||
|
|
||||||
|
gskSetOutputColor(vec4 (source * mask_value));
|
||||||
}
|
}
|
||||||
|
@ -255,5 +255,25 @@ typedef enum
|
|||||||
GSK_GL_UNIFORM_TYPE_VEC4,
|
GSK_GL_UNIFORM_TYPE_VEC4,
|
||||||
} GskGLUniformType;
|
} GskGLUniformType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GskMaskMode:
|
||||||
|
* @GSK_MASK_MODE_ALPHA: Use the alpha channel of the mask
|
||||||
|
* @GSK_MASK_MODE_INVERTED_ALPHA: Use the inverted alpha channel of the mask
|
||||||
|
* @GSK_MASK_MODE_LUMINANCE: Use the luminance of the mask,
|
||||||
|
* multiplied by mask alpha
|
||||||
|
* @GSK_MASK_MODE_INVERTED_LUMINANCE: Use the inverted luminance of the mask,
|
||||||
|
* multiplied by mask alpha
|
||||||
|
*
|
||||||
|
* The mask modes available for mask nodes.
|
||||||
|
*
|
||||||
|
* Since: 4.10
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSK_MASK_MODE_ALPHA,
|
||||||
|
GSK_MASK_MODE_INVERTED_ALPHA,
|
||||||
|
GSK_MASK_MODE_LUMINANCE,
|
||||||
|
GSK_MASK_MODE_INVERTED_LUMINANCE
|
||||||
|
} GskMaskMode;
|
||||||
|
|
||||||
#endif /* __GSK_TYPES_H__ */
|
#endif /* __GSK_TYPES_H__ */
|
||||||
|
@ -535,11 +535,14 @@ GDK_AVAILABLE_IN_4_10
|
|||||||
GType gsk_mask_node_get_type (void) G_GNUC_CONST;
|
GType gsk_mask_node_get_type (void) G_GNUC_CONST;
|
||||||
GDK_AVAILABLE_IN_4_10
|
GDK_AVAILABLE_IN_4_10
|
||||||
GskRenderNode * gsk_mask_node_new (GskRenderNode *source,
|
GskRenderNode * gsk_mask_node_new (GskRenderNode *source,
|
||||||
GskRenderNode *mask);
|
GskRenderNode *mask,
|
||||||
|
GskMaskMode mask_mode);
|
||||||
GDK_AVAILABLE_IN_4_10
|
GDK_AVAILABLE_IN_4_10
|
||||||
GskRenderNode * gsk_mask_node_get_source (const GskRenderNode *node);
|
GskRenderNode * gsk_mask_node_get_source (const GskRenderNode *node);
|
||||||
GDK_AVAILABLE_IN_4_10
|
GDK_AVAILABLE_IN_4_10
|
||||||
GskRenderNode * gsk_mask_node_get_mask (const GskRenderNode *node);
|
GskRenderNode * gsk_mask_node_get_mask (const GskRenderNode *node);
|
||||||
|
GDK_AVAILABLE_IN_4_10
|
||||||
|
GskMaskMode gsk_mask_node_get_mask_mode (const GskRenderNode *node);
|
||||||
|
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
GType gsk_gl_shader_node_get_type (void) G_GNUC_CONST;
|
GType gsk_gl_shader_node_get_type (void) G_GNUC_CONST;
|
||||||
|
@ -3410,29 +3410,18 @@ gsk_color_matrix_node_finalize (GskRenderNode *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_color_matrix_node_draw (GskRenderNode *node,
|
apply_color_matrix_to_pattern (cairo_pattern_t *pattern,
|
||||||
cairo_t *cr)
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset,
|
||||||
|
gboolean multiply_alpha)
|
||||||
{
|
{
|
||||||
GskColorMatrixNode *self = (GskColorMatrixNode *) node;
|
|
||||||
cairo_pattern_t *pattern;
|
|
||||||
cairo_surface_t *surface, *image_surface;
|
cairo_surface_t *surface, *image_surface;
|
||||||
graphene_vec4_t pixel;
|
|
||||||
guint32* pixel_data;
|
|
||||||
guchar *data;
|
guchar *data;
|
||||||
gsize x, y, width, height, stride;
|
gsize x, y, width, height, stride;
|
||||||
float alpha;
|
float alpha, orig_alpha;
|
||||||
|
graphene_vec4_t pixel;
|
||||||
|
guint32* pixel_data;
|
||||||
|
|
||||||
cairo_save (cr);
|
|
||||||
|
|
||||||
/* clip so the push_group() creates a smaller surface */
|
|
||||||
gsk_cairo_rectangle (cr, &node->bounds);
|
|
||||||
cairo_clip (cr);
|
|
||||||
|
|
||||||
cairo_push_group (cr);
|
|
||||||
|
|
||||||
gsk_render_node_draw (self->child, cr);
|
|
||||||
|
|
||||||
pattern = cairo_pop_group (cr);
|
|
||||||
cairo_pattern_get_surface (pattern, &surface);
|
cairo_pattern_get_surface (pattern, &surface);
|
||||||
image_surface = cairo_surface_map_to_image (surface, NULL);
|
image_surface = cairo_surface_map_to_image (surface, NULL);
|
||||||
|
|
||||||
@ -3446,7 +3435,7 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
|
|||||||
pixel_data = (guint32 *) data;
|
pixel_data = (guint32 *) data;
|
||||||
for (x = 0; x < width; x++)
|
for (x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
|
alpha = orig_alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
|
||||||
|
|
||||||
if (alpha == 0)
|
if (alpha == 0)
|
||||||
{
|
{
|
||||||
@ -3459,12 +3448,16 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
|
|||||||
((pixel_data[x] >> 8) & 0xFF) / (255.0 * alpha),
|
((pixel_data[x] >> 8) & 0xFF) / (255.0 * alpha),
|
||||||
( pixel_data[x] & 0xFF) / (255.0 * alpha),
|
( pixel_data[x] & 0xFF) / (255.0 * alpha),
|
||||||
alpha);
|
alpha);
|
||||||
graphene_matrix_transform_vec4 (&self->color_matrix, &pixel, &pixel);
|
graphene_matrix_transform_vec4 (color_matrix, &pixel, &pixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphene_vec4_add (&pixel, &self->color_offset, &pixel);
|
graphene_vec4_add (&pixel, color_offset, &pixel);
|
||||||
|
|
||||||
alpha = graphene_vec4_get_w (&pixel);
|
alpha = graphene_vec4_get_w (&pixel);
|
||||||
|
|
||||||
|
if (multiply_alpha)
|
||||||
|
alpha *= orig_alpha;
|
||||||
|
|
||||||
if (alpha > 0.0)
|
if (alpha > 0.0)
|
||||||
{
|
{
|
||||||
alpha = MIN (alpha, 1.0);
|
alpha = MIN (alpha, 1.0);
|
||||||
@ -3483,6 +3476,28 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
|
|||||||
|
|
||||||
cairo_surface_mark_dirty (image_surface);
|
cairo_surface_mark_dirty (image_surface);
|
||||||
cairo_surface_unmap_image (surface, image_surface);
|
cairo_surface_unmap_image (surface, image_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_color_matrix_node_draw (GskRenderNode *node,
|
||||||
|
cairo_t *cr)
|
||||||
|
{
|
||||||
|
GskColorMatrixNode *self = (GskColorMatrixNode *) node;
|
||||||
|
cairo_pattern_t *pattern;
|
||||||
|
|
||||||
|
cairo_save (cr);
|
||||||
|
|
||||||
|
/* clip so the push_group() creates a smaller surface */
|
||||||
|
gsk_cairo_rectangle (cr, &node->bounds);
|
||||||
|
cairo_clip (cr);
|
||||||
|
|
||||||
|
cairo_push_group (cr);
|
||||||
|
|
||||||
|
gsk_render_node_draw (self->child, cr);
|
||||||
|
|
||||||
|
pattern = cairo_pop_group (cr);
|
||||||
|
|
||||||
|
apply_color_matrix_to_pattern (pattern, &self->color_matrix, &self->color_offset, FALSE);
|
||||||
|
|
||||||
cairo_set_source (cr, pattern);
|
cairo_set_source (cr, pattern);
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
@ -5202,6 +5217,7 @@ struct _GskMaskNode
|
|||||||
|
|
||||||
GskRenderNode *mask;
|
GskRenderNode *mask;
|
||||||
GskRenderNode *source;
|
GskRenderNode *source;
|
||||||
|
GskMaskMode mask_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -5219,6 +5235,8 @@ gsk_mask_node_draw (GskRenderNode *node,
|
|||||||
{
|
{
|
||||||
GskMaskNode *self = (GskMaskNode *) node;
|
GskMaskNode *self = (GskMaskNode *) node;
|
||||||
cairo_pattern_t *mask_pattern;
|
cairo_pattern_t *mask_pattern;
|
||||||
|
graphene_matrix_t color_matrix;
|
||||||
|
graphene_vec4_t color_offset;
|
||||||
|
|
||||||
cairo_push_group (cr);
|
cairo_push_group (cr);
|
||||||
gsk_render_node_draw (self->source, cr);
|
gsk_render_node_draw (self->source, cr);
|
||||||
@ -5228,6 +5246,41 @@ gsk_mask_node_draw (GskRenderNode *node,
|
|||||||
gsk_render_node_draw (self->mask, cr);
|
gsk_render_node_draw (self->mask, cr);
|
||||||
mask_pattern = cairo_pop_group (cr);
|
mask_pattern = cairo_pop_group (cr);
|
||||||
|
|
||||||
|
switch (self->mask_mode)
|
||||||
|
{
|
||||||
|
case GSK_MASK_MODE_ALPHA:
|
||||||
|
break;
|
||||||
|
case GSK_MASK_MODE_INVERTED_ALPHA:
|
||||||
|
graphene_matrix_init_from_float (&color_matrix, (float[]){ 1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, -1 });
|
||||||
|
graphene_vec4_init (&color_offset, 0, 0, 0, 1);
|
||||||
|
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset, FALSE);
|
||||||
|
break;
|
||||||
|
case GSK_MASK_MODE_LUMINANCE:
|
||||||
|
graphene_matrix_init_from_float (&color_matrix, (float[]){ 1, 0, 0, 0.2126,
|
||||||
|
0, 1, 0, 0.7152,
|
||||||
|
0, 0, 1, 0.0722,
|
||||||
|
0, 0, 0, 0 });
|
||||||
|
graphene_vec4_init (&color_offset, 0, 0, 0, 0);
|
||||||
|
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset, TRUE);
|
||||||
|
break;
|
||||||
|
case GSK_MASK_MODE_INVERTED_LUMINANCE:
|
||||||
|
graphene_matrix_init_from_float (&color_matrix, (float[]){ 1, 0, 0, -0.2126,
|
||||||
|
0, 1, 0, -0.7152,
|
||||||
|
0, 0, 1, -0.0722,
|
||||||
|
0, 0, 0, 0 });
|
||||||
|
graphene_vec4_init (&color_offset, 0, 0, 0, 1);
|
||||||
|
apply_color_matrix_to_pattern (mask_pattern, &color_matrix, &color_offset, TRUE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_cairo_rectangle (cr, &node->bounds);
|
||||||
|
cairo_clip (cr);
|
||||||
|
|
||||||
cairo_mask (cr, mask_pattern);
|
cairo_mask (cr, mask_pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5245,11 +5298,15 @@ gsk_mask_node_diff (GskRenderNode *node1,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_mask_node_new:
|
* gsk_mask_node_new:
|
||||||
* @source: The bottom node to be drawn
|
* @source: The source node to be drawn
|
||||||
* @mask: The node to be blended onto the @bottom node
|
* @mask: The node to be used as mask
|
||||||
|
* @mask_mode: The mask mode to use
|
||||||
*
|
*
|
||||||
* Creates a `GskRenderNode` that will use @blend_mode to blend the @top
|
* Creates a `GskRenderNode` that will mask a given node by another.
|
||||||
* node onto the @bottom node.
|
*
|
||||||
|
* The @mask_mode determines how the 'mask values' are derived from
|
||||||
|
* the colors of the @mask. Applying the mask consists of multiplying
|
||||||
|
* the 'mask value' with the alpha of the source.
|
||||||
*
|
*
|
||||||
* Returns: (transfer full) (type GskMaskNode): A new `GskRenderNode`
|
* Returns: (transfer full) (type GskMaskNode): A new `GskRenderNode`
|
||||||
*
|
*
|
||||||
@ -5257,7 +5314,8 @@ gsk_mask_node_diff (GskRenderNode *node1,
|
|||||||
*/
|
*/
|
||||||
GskRenderNode *
|
GskRenderNode *
|
||||||
gsk_mask_node_new (GskRenderNode *source,
|
gsk_mask_node_new (GskRenderNode *source,
|
||||||
GskRenderNode *mask)
|
GskRenderNode *mask,
|
||||||
|
GskMaskMode mask_mode)
|
||||||
{
|
{
|
||||||
GskMaskNode *self;
|
GskMaskNode *self;
|
||||||
|
|
||||||
@ -5267,15 +5325,18 @@ gsk_mask_node_new (GskRenderNode *source,
|
|||||||
self = gsk_render_node_alloc (GSK_MASK_NODE);
|
self = gsk_render_node_alloc (GSK_MASK_NODE);
|
||||||
self->source = gsk_render_node_ref (source);
|
self->source = gsk_render_node_ref (source);
|
||||||
self->mask = gsk_render_node_ref (mask);
|
self->mask = gsk_render_node_ref (mask);
|
||||||
|
self->mask_mode = mask_mode;
|
||||||
|
|
||||||
graphene_rect_union (&source->bounds, &mask->bounds, &self->render_node.bounds);
|
self->render_node.bounds = source->bounds;
|
||||||
|
|
||||||
|
self->render_node.prefers_high_depth = gsk_render_node_prefers_high_depth (source);
|
||||||
|
|
||||||
return &self->render_node;
|
return &self->render_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_mask_node_get_source:
|
* gsk_mask_node_get_source:
|
||||||
* @node: (type GskBlendNode): a mask `GskRenderNode`
|
* @node: (type GskMaskNode): a mask `GskRenderNode`
|
||||||
*
|
*
|
||||||
* Retrieves the source `GskRenderNode` child of the @node.
|
* Retrieves the source `GskRenderNode` child of the @node.
|
||||||
*
|
*
|
||||||
@ -5295,7 +5356,7 @@ gsk_mask_node_get_source (const GskRenderNode *node)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_mask_node_get_mask:
|
* gsk_mask_node_get_mask:
|
||||||
* @node: (type GskBlendNode): a mask `GskRenderNode`
|
* @node: (type GskMaskNode): a mask `GskRenderNode`
|
||||||
*
|
*
|
||||||
* Retrieves the mask `GskRenderNode` child of the @node.
|
* Retrieves the mask `GskRenderNode` child of the @node.
|
||||||
*
|
*
|
||||||
@ -5313,6 +5374,24 @@ gsk_mask_node_get_mask (const GskRenderNode *node)
|
|||||||
return self->mask;
|
return self->mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsk_mask_node_get_mask_mode:
|
||||||
|
* @node: (type GskMaskNode): a blending `GskRenderNode`
|
||||||
|
*
|
||||||
|
* Retrieves the mask mode used by @node.
|
||||||
|
*
|
||||||
|
* Returns: the mask mode
|
||||||
|
*
|
||||||
|
* Since: 4.10
|
||||||
|
*/
|
||||||
|
GskMaskMode
|
||||||
|
gsk_mask_node_get_mask_mode (const GskRenderNode *node)
|
||||||
|
{
|
||||||
|
const GskMaskNode *self = (const GskMaskNode *) node;
|
||||||
|
|
||||||
|
return self->mask_mode;
|
||||||
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ GSK_DEBUG_NODE */
|
/* {{{ GSK_DEBUG_NODE */
|
||||||
|
|
||||||
|
@ -649,6 +649,18 @@ static const struct
|
|||||||
{ GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
|
{ GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_blend_mode_name (GskBlendMode mode)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < G_N_ELEMENTS (blend_modes); i++)
|
||||||
|
{
|
||||||
|
if (blend_modes[i].mode == mode)
|
||||||
|
return blend_modes[i].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_blend_mode (GtkCssParser *parser,
|
parse_blend_mode (GtkCssParser *parser,
|
||||||
gpointer out_mode)
|
gpointer out_mode)
|
||||||
@ -667,6 +679,46 @@ parse_blend_mode (GtkCssParser *parser,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
GskMaskMode mode;
|
||||||
|
const char *name;
|
||||||
|
} mask_modes[] = {
|
||||||
|
{ GSK_MASK_MODE_ALPHA, "alpha" },
|
||||||
|
{ GSK_MASK_MODE_INVERTED_ALPHA, "inverted-alpha" },
|
||||||
|
{ GSK_MASK_MODE_LUMINANCE, "luminance" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_mask_mode_name (GskMaskMode mode)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < G_N_ELEMENTS (mask_modes); i++)
|
||||||
|
{
|
||||||
|
if (mask_modes[i].mode == mode)
|
||||||
|
return mask_modes[i].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_mask_mode (GtkCssParser *parser,
|
||||||
|
gpointer out_mode)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (mask_modes); i++)
|
||||||
|
{
|
||||||
|
if (gtk_css_parser_try_ident (parser, mask_modes[i].name))
|
||||||
|
{
|
||||||
|
*(GskMaskMode *) out_mode = mask_modes[i].mode;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static PangoFont *
|
static PangoFont *
|
||||||
font_from_string (const char *string)
|
font_from_string (const char *string)
|
||||||
{
|
{
|
||||||
@ -1381,7 +1433,9 @@ parse_mask_node (GtkCssParser *parser)
|
|||||||
{
|
{
|
||||||
GskRenderNode *source = NULL;
|
GskRenderNode *source = NULL;
|
||||||
GskRenderNode *mask = NULL;
|
GskRenderNode *mask = NULL;
|
||||||
|
GskMaskMode mode = GSK_MASK_MODE_ALPHA;
|
||||||
const Declaration declarations[] = {
|
const Declaration declarations[] = {
|
||||||
|
{ "mode", parse_mask_mode, NULL, &mode },
|
||||||
{ "source", parse_node, clear_node, &source },
|
{ "source", parse_node, clear_node, &source },
|
||||||
{ "mask", parse_node, clear_node, &mask },
|
{ "mask", parse_node, clear_node, &mask },
|
||||||
};
|
};
|
||||||
@ -1393,7 +1447,7 @@ parse_mask_node (GtkCssParser *parser)
|
|||||||
if (mask == NULL)
|
if (mask == NULL)
|
||||||
mask = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
|
mask = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
|
||||||
|
|
||||||
result = gsk_mask_node_new (source, mask);
|
result = gsk_mask_node_new (source, mask, mode);
|
||||||
|
|
||||||
gsk_render_node_unref (source);
|
gsk_render_node_unref (source);
|
||||||
gsk_render_node_unref (mask);
|
gsk_render_node_unref (mask);
|
||||||
@ -3103,21 +3157,13 @@ render_node_print (Printer *p,
|
|||||||
case GSK_BLEND_NODE:
|
case GSK_BLEND_NODE:
|
||||||
{
|
{
|
||||||
GskBlendMode mode = gsk_blend_node_get_blend_mode (node);
|
GskBlendMode mode = gsk_blend_node_get_blend_mode (node);
|
||||||
guint i;
|
|
||||||
|
|
||||||
start_node (p, "blend");
|
start_node (p, "blend");
|
||||||
|
|
||||||
if (mode != GSK_BLEND_MODE_DEFAULT)
|
if (mode != GSK_BLEND_MODE_DEFAULT)
|
||||||
{
|
{
|
||||||
_indent (p);
|
_indent (p);
|
||||||
for (i = 0; i < G_N_ELEMENTS (blend_modes); i++)
|
g_string_append_printf (p->str, "mode: %s;\n", get_blend_mode_name (mode));
|
||||||
{
|
|
||||||
if (blend_modes[i].mode == mode)
|
|
||||||
{
|
|
||||||
g_string_append_printf (p->str, "mode: %s;\n", blend_modes[i].name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
append_node_param (p, "bottom", gsk_blend_node_get_bottom_child (node));
|
append_node_param (p, "bottom", gsk_blend_node_get_bottom_child (node));
|
||||||
append_node_param (p, "top", gsk_blend_node_get_top_child (node));
|
append_node_param (p, "top", gsk_blend_node_get_top_child (node));
|
||||||
@ -3128,8 +3174,15 @@ render_node_print (Printer *p,
|
|||||||
|
|
||||||
case GSK_MASK_NODE:
|
case GSK_MASK_NODE:
|
||||||
{
|
{
|
||||||
|
GskMaskMode mode = gsk_mask_node_get_mask_mode (node);
|
||||||
|
|
||||||
start_node (p, "mask");
|
start_node (p, "mask");
|
||||||
|
|
||||||
|
if (mode != GSK_MASK_MODE_ALPHA)
|
||||||
|
{
|
||||||
|
_indent (p);
|
||||||
|
g_string_append_printf (p->str, "mode: %s;\n", get_mask_mode_name (mode));
|
||||||
|
}
|
||||||
append_node_param (p, "source", gsk_mask_node_get_source (node));
|
append_node_param (p, "source", gsk_mask_node_get_source (node));
|
||||||
append_node_param (p, "mask", gsk_mask_node_get_mask (node));
|
append_node_param (p, "mask", gsk_mask_node_get_mask (node));
|
||||||
|
|
||||||
|
@ -122,6 +122,7 @@ struct _GtkSnapshotState {
|
|||||||
char *message;
|
char *message;
|
||||||
} debug;
|
} debug;
|
||||||
struct {
|
struct {
|
||||||
|
GskMaskMode mask_mode;
|
||||||
GskRenderNode *mask_node;
|
GskRenderNode *mask_node;
|
||||||
} mask;
|
} mask;
|
||||||
} data;
|
} data;
|
||||||
@ -1258,7 +1259,7 @@ gtk_snapshot_collect_mask_source (GtkSnapshot *snapshot,
|
|||||||
if (source_child == NULL || mask_child == NULL)
|
if (source_child == NULL || mask_child == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
mask_node = gsk_mask_node_new (source_child, mask_child);
|
mask_node = gsk_mask_node_new (source_child, mask_child, state->data.mask.mask_mode);
|
||||||
|
|
||||||
gsk_render_node_unref (source_child);
|
gsk_render_node_unref (source_child);
|
||||||
gsk_render_node_unref (mask_child);
|
gsk_render_node_unref (mask_child);
|
||||||
@ -1290,9 +1291,11 @@ gtk_snapshot_collect_mask_mask (GtkSnapshot *snapshot,
|
|||||||
/**
|
/**
|
||||||
* gtk_snapshot_push_mask:
|
* gtk_snapshot_push_mask:
|
||||||
* @snapshot: a #GtkSnapshot
|
* @snapshot: a #GtkSnapshot
|
||||||
|
* @mask_mode: mask mode to use
|
||||||
*
|
*
|
||||||
* Until the first call to [method@Gtk.Snapshot.pop], the
|
* Until the first call to [method@Gtk.Snapshot.pop], the
|
||||||
* mask image for the mask operation will be recorded.
|
* mask image for the mask operation will be recorded.
|
||||||
|
*
|
||||||
* After that call, the source image will be recorded until
|
* After that call, the source image will be recorded until
|
||||||
* the second call to [method@Gtk.Snapshot.pop].
|
* the second call to [method@Gtk.Snapshot.pop].
|
||||||
*
|
*
|
||||||
@ -1301,7 +1304,8 @@ gtk_snapshot_collect_mask_mask (GtkSnapshot *snapshot,
|
|||||||
* Since: 4.10
|
* Since: 4.10
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gtk_snapshot_push_mask (GtkSnapshot *snapshot)
|
gtk_snapshot_push_mask (GtkSnapshot *snapshot,
|
||||||
|
GskMaskMode mask_mode)
|
||||||
{
|
{
|
||||||
GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
|
GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
|
||||||
GtkSnapshotState *source_state;
|
GtkSnapshotState *source_state;
|
||||||
@ -1311,6 +1315,8 @@ gtk_snapshot_push_mask (GtkSnapshot *snapshot)
|
|||||||
gtk_snapshot_collect_mask_source,
|
gtk_snapshot_collect_mask_source,
|
||||||
gtk_snapshot_clear_mask_source);
|
gtk_snapshot_clear_mask_source);
|
||||||
|
|
||||||
|
source_state->data.mask.mask_mode = mask_mode;
|
||||||
|
|
||||||
gtk_snapshot_push_state (snapshot,
|
gtk_snapshot_push_state (snapshot,
|
||||||
source_state->transform,
|
source_state->transform,
|
||||||
gtk_snapshot_collect_mask_mask,
|
gtk_snapshot_collect_mask_mask,
|
||||||
|
@ -96,7 +96,8 @@ GDK_AVAILABLE_IN_ALL
|
|||||||
void gtk_snapshot_push_blend (GtkSnapshot *snapshot,
|
void gtk_snapshot_push_blend (GtkSnapshot *snapshot,
|
||||||
GskBlendMode blend_mode);
|
GskBlendMode blend_mode);
|
||||||
GDK_AVAILABLE_IN_4_10
|
GDK_AVAILABLE_IN_4_10
|
||||||
void gtk_snapshot_push_mask (GtkSnapshot *snapshot);
|
void gtk_snapshot_push_mask (GtkSnapshot *snapshot,
|
||||||
|
GskMaskMode mask_mode);
|
||||||
|
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
void gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
|
void gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
|
||||||
|
@ -1140,6 +1140,12 @@ populate_render_node_properties (GListStore *store,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GSK_MASK_NODE:
|
case GSK_MASK_NODE:
|
||||||
|
{
|
||||||
|
GskMaskMode mode = gsk_mask_node_get_mask_mode (node);
|
||||||
|
tmp = g_enum_to_string (GSK_TYPE_MASK_MODE, mode);
|
||||||
|
add_text_row (store, "Mask mode", tmp);
|
||||||
|
g_free (tmp);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GSK_BLUR_NODE:
|
case GSK_BLUR_NODE:
|
||||||
|
Loading…
Reference in New Issue
Block a user