app: preserve projection priority rect across structure/bounds changes

In GimpProjection, store the priority rect in image coordinates,
and only convert it to projectable coordinates when initializing
the chunk-iterator's priority rect.  This allows us to preserve the
priority rect across projectable structure/bounds changes.
This commit is contained in:
Ell
2019-03-26 04:54:59 -04:00
parent b2969a11e1
commit 9d80ccc3e6

View File

@ -135,6 +135,7 @@ static void gimp_projection_add_update_area (GimpProjection *proj,
static void gimp_projection_flush_whenever (GimpProjection *proj,
gboolean now,
gboolean direct);
static void gimp_projection_update_priority_rect (GimpProjection *proj);
static void gimp_projection_chunk_render_start (GimpProjection *proj);
static void gimp_projection_chunk_render_stop (GimpProjection *proj,
gboolean merge);
@ -505,30 +506,11 @@ gimp_projection_set_priority_rect (GimpProjection *proj,
gint w,
gint h)
{
gint off_x, off_y;
gint width, height;
g_return_if_fail (GIMP_IS_PROJECTION (proj));
gimp_projectable_get_offset (proj->priv->projectable, &off_x, &off_y);
gimp_projectable_get_size (proj->priv->projectable, &width, &height);
proj->priv->priority_rect = *GEGL_RECTANGLE (x, y, w, h);
/* subtract the projectable's offsets because the list of update
* areas is in tile-pyramid coordinates, but our external API is
* always in terms of image coordinates.
*/
x -= off_x;
y -= off_y;
gegl_rectangle_intersect (&proj->priv->priority_rect,
GEGL_RECTANGLE (x, y, w, h),
GEGL_RECTANGLE (0, 0, width, height));
if (proj->priv->iter)
{
gimp_chunk_iterator_set_priority_rect (proj->priv->iter,
&proj->priv->priority_rect);
}
gimp_projection_update_priority_rect (proj);
}
void
@ -707,6 +689,35 @@ gimp_projection_flush_whenever (GimpProjection *proj,
}
}
static void
gimp_projection_update_priority_rect (GimpProjection *proj)
{
if (proj->priv->iter)
{
GeglRectangle rect;
gint off_x, off_y;
gint width, height;
rect = proj->priv->priority_rect;
gimp_projectable_get_offset (proj->priv->projectable, &off_x, &off_y);
gimp_projectable_get_size (proj->priv->projectable, &width, &height);
/* subtract the projectable's offsets because the list of update
* areas is in tile-pyramid coordinates, but our external API is
* always in terms of image coordinates.
*/
rect.x -= off_x;
rect.y -= off_y;
gegl_rectangle_intersect (&rect,
&rect,
GEGL_RECTANGLE (0, 0, width, height));
gimp_chunk_iterator_set_priority_rect (proj->priv->iter, &rect);
}
}
static void
gimp_projection_chunk_render_start (GimpProjection *proj)
{
@ -736,8 +747,7 @@ gimp_projection_chunk_render_start (GimpProjection *proj)
{
proj->priv->iter = gimp_chunk_iterator_new (region);
gimp_chunk_iterator_set_priority_rect (proj->priv->iter,
&proj->priv->priority_rect);
gimp_projection_update_priority_rect (proj);
if (! proj->priv->idle_id)
{
@ -955,11 +965,6 @@ gimp_projection_projectable_structure_changed (GimpProjectable *projectable,
gimp_projectable_get_size (projectable, &width, &height);
gimp_projection_add_update_area (proj, 0, 0, width, height);
proj->priv->priority_rect.x = 0;
proj->priv->priority_rect.y = 0;
proj->priv->priority_rect.width = width;
proj->priv->priority_rect.height = height;
}
static void
@ -1054,25 +1059,6 @@ gimp_projection_projectable_bounds_changed (GimpProjectable *projectable,
cairo_region_intersect_rectangle (proj->priv->update_region, &bounds);
}
if (proj->priv->priority_rect.width > 0 &&
proj->priv->priority_rect.height > 0)
{
proj->priv->priority_rect.x += dx;
proj->priv->priority_rect.y += dy;
gimp_rectangle_intersect (proj->priv->priority_rect.x,
proj->priv->priority_rect.y,
proj->priv->priority_rect.width,
proj->priv->priority_rect.height,
0, 0, w, h,
&proj->priv->priority_rect.x,
&proj->priv->priority_rect.y,
&proj->priv->priority_rect.width,
&proj->priv->priority_rect.height);
}
if (dx > 0)
gimp_projection_add_update_area (proj, 0, 0, dx, h);
if (dy > 0)