From eed58b405186dbef14921229314d419d734deb22 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 14 Sep 2024 21:39:02 +0200 Subject: [PATCH] gpu: Split out rect grid snapping function We might want to use it outside of the nodeprocessor. The function is now called gsk_rect_snap_to_grid(). --- gsk/gpu/gskgpunodeprocessor.c | 40 +++++++++-------------------------- gsk/gskrectprivate.h | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 40b4844155..49702a7762 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -288,26 +288,6 @@ gsk_gpu_node_processor_color_states_explicit (GskGpuNodeProcessor *self, alt_premultiplied); } -static void -rect_round_to_pixels (const graphene_rect_t *src, - const graphene_vec2_t *pixel_scale, - const graphene_point_t *pixel_offset, - graphene_rect_t *dest) -{ - float x, y, xscale, yscale; - - xscale = graphene_vec2_get_x (pixel_scale); - yscale = graphene_vec2_get_y (pixel_scale); - - x = floorf ((src->origin.x + pixel_offset->x) * xscale); - y = floorf ((src->origin.y + pixel_offset->y) * yscale); - *dest = GRAPHENE_RECT_INIT ( - x / xscale - pixel_offset->x, - y / yscale - pixel_offset->y, - (ceilf ((src->origin.x + pixel_offset->x + src->size.width) * xscale) - x) / xscale, - (ceilf ((src->origin.y + pixel_offset->y + src->size.height) * yscale) - y) / yscale); -} - static GskGpuImage * gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self, GskGpuFrame *frame, @@ -828,7 +808,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self, if (!gsk_rect_intersection (clip_bounds, &node->bounds, &clip)) return NULL; } - rect_round_to_pixels (&clip, &self->scale, &self->offset, &clip); + gsk_rect_snap_to_grid (&clip, &self->scale, &self->offset, &clip); return gsk_gpu_get_node_as_image (self->frame, flags, @@ -866,7 +846,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self, if (!gsk_rect_intersection (rect, &clip_rect, &intermediate_rect)) return; - rect_round_to_pixels (&intermediate_rect, &self->scale, &self->offset, &intermediate_rect); + gsk_rect_snap_to_grid (&intermediate_rect, &self->scale, &self->offset, &intermediate_rect); intermediate = gsk_gpu_node_processor_init_draw (&other, self->frame, @@ -941,7 +921,7 @@ gsk_gpu_node_processor_add_cairo_node (GskGpuNodeProcessor *self, if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clipped_bounds)) return; - rect_round_to_pixels (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds); + gsk_rect_snap_to_grid (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds); gsk_gpu_node_processor_sync_globals (self, 0); @@ -1263,7 +1243,7 @@ gsk_gpu_node_processor_add_rounded_clip_node_with_mask (GskGpuNodeProcessor *sel if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds)) return; - rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds); + gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds); child_image = gsk_gpu_node_processor_get_node_as_image (self, 0, @@ -2130,7 +2110,7 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip)) return; - rect_round_to_pixels (&clip, &self->scale, &self->offset, &rounded_clip); + gsk_rect_snap_to_grid (&clip, &self->scale, &self->offset, &rounded_clip); image = gsk_gpu_get_texture_tiles_as_image (self->frame, self->ccs, @@ -2260,7 +2240,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, gsk_gpu_node_processor_get_clip_bounds (self, &clip_bounds); /* first round to pixel boundaries, so we make sure the full pixels are covered */ - rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds); + gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds); /* then expand by half a pixel so that pixels needed for eventual linear * filtering are available */ graphene_rect_inset (&clip_bounds, -0.5, -0.5); @@ -2501,7 +2481,7 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self, if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &bounds)) return; - rect_round_to_pixels (&bounds, &self->scale, &self->offset, &bounds); + gsk_rect_snap_to_grid (&bounds, &self->scale, &self->offset, &bounds); image = gsk_gpu_node_processor_init_draw (&other, self->frame, @@ -3429,7 +3409,7 @@ gsk_gpu_node_processor_add_fill_node (GskGpuNodeProcessor *self, if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds)) return; - rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds); + gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds); child = gsk_fill_node_get_child (node); @@ -3532,7 +3512,7 @@ gsk_gpu_node_processor_add_stroke_node (GskGpuNodeProcessor *self, if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds)) return; - rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds); + gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds); child = gsk_stroke_node_get_child (node); @@ -4378,7 +4358,7 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame, if (!gsk_gpu_node_processor_clip_node_bounds (&self, node, &clip_bounds)) continue; - rect_round_to_pixels (&clip_bounds, &self.scale, &self.offset, &clip_bounds); + gsk_rect_snap_to_grid (&clip_bounds, &self.scale, &self.offset, &clip_bounds); image = gsk_gpu_get_node_as_image (self.frame, 0, ccs, diff --git a/gsk/gskrectprivate.h b/gsk/gskrectprivate.h index 1c07b2a63d..a20b1e6da3 100644 --- a/gsk/gskrectprivate.h +++ b/gsk/gskrectprivate.h @@ -160,6 +160,45 @@ gsk_rect_coverage (const graphene_rect_t *r1, *res = r; } +/** + * gsk_rect_snap_to_grid: + * @src: rectangle to snap + * @grid_scale: the scale of the grid + * @grid_offset: the offset of the grid + * @dest: target to snap to. Can be identical to source + * + * Snaps @src to the grid specified by the given scale + * and offset. + * Grid points to snap to will be at the given offset and + * then spaced apart by the inverse of the given scale, + * ie an offset of 0.5 and a scale of 3 will snap to + * (..., 0.1667, 0.5, 0.8333, 1.1667, 1.5, ...). + * + * Snapping is done by growing the rectangle. + * + * Note that floating point rounding issues might result + * in the snapping not being perfectly exact. + **/ +static inline void +gsk_rect_snap_to_grid (const graphene_rect_t *src, + const graphene_vec2_t *grid_scale, + const graphene_point_t *grid_offset, + graphene_rect_t *dest) +{ + float x, y, xscale, yscale; + + xscale = graphene_vec2_get_x (grid_scale); + yscale = graphene_vec2_get_y (grid_scale); + + x = floorf ((src->origin.x + grid_offset->x) * xscale); + y = floorf ((src->origin.y + grid_offset->y) * yscale); + *dest = GRAPHENE_RECT_INIT ( + x / xscale - grid_offset->x, + y / yscale - grid_offset->y, + (ceilf ((src->origin.x + grid_offset->x + src->size.width) * xscale) - x) / xscale, + (ceilf ((src->origin.y + grid_offset->y + src->size.height) * yscale) - y) / yscale); +} + static inline gboolean G_GNUC_PURE gsk_rect_is_empty (const graphene_rect_t *rect) {