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().
This commit is contained in:
Benjamin Otte 2024-09-14 21:39:02 +02:00
parent 28a01ca954
commit eed58b4051
2 changed files with 49 additions and 30 deletions

View File

@ -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,

View File

@ -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)
{