clutter: Fix capture_into on non-origin view

The capture_into() function wrote out of bounds when capturing from a
non-origin view (not positioned at (0,0)). At the time of
implementation, this API was used to capture pixels across views into a
single data buffer, but the way it's used, and the way views may work
now, makes this impossible to do properly.

So remove the ability to capture into a pre-allocated buffer from
multiple views, and complain if the passed rectantgle overlapps with
multiple views. This removes the broken offset calculation all
together, fixing the bug motivating this change.

https://bugzilla.gnome.org/show_bug.cgi?id=787715
This commit is contained in:
Jonas Ådahl 2017-09-15 16:25:19 +08:00
parent a35274ddb7
commit ba194bd19e

View File

@ -4856,11 +4856,9 @@ capture_view_into (ClutterStage *stage,
cogl_object_unref (bitmap); cogl_object_unref (bitmap);
} }
void static ClutterStageView *
clutter_stage_capture_into (ClutterStage *stage, get_view_at_rect (ClutterStage *stage,
gboolean paint, cairo_rectangle_int_t *rect)
cairo_rectangle_int_t *rect,
uint8_t *data)
{ {
ClutterStagePrivate *priv = stage->priv; ClutterStagePrivate *priv = stage->priv;
GList *views = _clutter_stage_window_get_views (priv->impl); GList *views = _clutter_stage_window_get_views (priv->impl);
@ -4872,8 +4870,6 @@ clutter_stage_capture_into (ClutterStage *stage,
cairo_rectangle_int_t view_layout; cairo_rectangle_int_t view_layout;
cairo_region_t *region; cairo_region_t *region;
cairo_rectangle_int_t view_capture_rect; cairo_rectangle_int_t view_capture_rect;
int offset;
const int bpp = 4;
clutter_stage_view_get_layout (view, &view_layout); clutter_stage_view_get_layout (view, &view_layout);
region = cairo_region_create_rectangle (&view_layout); region = cairo_region_create_rectangle (&view_layout);
@ -4884,8 +4880,23 @@ clutter_stage_capture_into (ClutterStage *stage,
if (view_capture_rect.width == 0 || view_capture_rect.height == 0) if (view_capture_rect.width == 0 || view_capture_rect.height == 0)
continue; continue;
offset = bpp * (view_capture_rect.y * rect->width + view_capture_rect.x); g_assert (view_capture_rect.width == rect->width &&
capture_view_into (stage, paint, view, &view_capture_rect, view_capture_rect.height == rect->height);
data + offset, rect->width * bpp); return view;
} }
return NULL;
}
void
clutter_stage_capture_into (ClutterStage *stage,
gboolean paint,
cairo_rectangle_int_t *rect,
uint8_t *data)
{
ClutterStageView *view;
int bpp = 4;
view = get_view_at_rect (stage, rect);
capture_view_into (stage, paint, view, rect, data, rect->width * bpp);
} }