cairo_int_status_t _cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes) { int nboxes; pixman_box32_t *pboxes; cairo_box_int_t *cboxes; int i; pboxes = pixman_region32_rectangles (®ion->rgn, &nboxes); if (nboxes == 0) { *num_boxes = 0; return CAIRO_STATUS_SUCCESS; } if (nboxes > *num_boxes) { cboxes = _cairo_malloc_ab (nboxes, sizeof (cairo_box_int_t)); if (unlikely (cboxes == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else cboxes = *boxes; for (i = 0; i < nboxes; i++) { cboxes[i].p1.x = pboxes[i].x1; cboxes[i].p1.y = pboxes[i].y1; cboxes[i].p2.x = pboxes[i].x2; cboxes[i].p2.y = pboxes[i].y2; } *num_boxes = nboxes; *boxes = cboxes; return CAIRO_STATUS_SUCCESS; }
cairo_box_t * _cairo_region_get_boxes (const cairo_region_t *region, int *nbox) { if (region->status) { nbox = 0; return NULL; } return (cairo_box_t *) pixman_region32_rectangles (CONST_CAST ®ion->rgn, nbox); }
void nsRegion::VisitEdges (visit_fn visit, void *closure) { pixman_box32_t *boxes; int n; boxes = pixman_region32_rectangles(&mImpl, &n); // if we have no rectangles then we're done if (!n) return; pixman_box32_t *end = boxes + n; pixman_box32_t *topRectsEnd = boxes + 1; pixman_box32_t *topRects = boxes; // find the end of the first span of rectangles while (topRectsEnd < end && topRectsEnd->y1 == topRects->y1) { topRectsEnd++; } // In order to properly handle convex corners we always visit the sides first // that way when we visit the corners we can pad using the value from the sides VisitSides(visit, closure, topRects, topRectsEnd); VisitAbove(visit, closure, topRects, topRectsEnd); pixman_box32_t *bottomRects = topRects; pixman_box32_t *bottomRectsEnd = topRectsEnd; if (topRectsEnd != end) { do { // find the next row of rects bottomRects = topRectsEnd; bottomRectsEnd = topRectsEnd + 1; while (bottomRectsEnd < end && bottomRectsEnd->y1 == bottomRects->y1) { bottomRectsEnd++; } VisitSides(visit, closure, bottomRects, bottomRectsEnd); if (topRects->y2 == bottomRects->y1) { VisitInbetween(visit, closure, topRects, topRectsEnd, bottomRects, bottomRectsEnd); } else { VisitBelow(visit, closure, topRects, topRectsEnd); VisitAbove(visit, closure, bottomRects, bottomRectsEnd); } topRects = bottomRects; topRectsEnd = bottomRectsEnd; } while (bottomRectsEnd != end); } // the bottom of the region doesn't touch anything else so we // can always visit it at the end VisitBelow(visit, closure, bottomRects, bottomRectsEnd); }
static inline pixman_bool_t miClipPictureReg (pixman_region32_t * pRegion, pixman_region32_t * pClip, int dx, int dy) { if (pixman_region32_n_rects(pRegion) == 1 && pixman_region32_n_rects(pClip) == 1) { pixman_box32_t * pRbox = pixman_region32_rectangles(pRegion, NULL); pixman_box32_t * pCbox = pixman_region32_rectangles(pClip, NULL); int v; if (pRbox->x1 < (v = pCbox->x1 + dx)) pRbox->x1 = BOUND(v); if (pRbox->x2 > (v = pCbox->x2 + dx)) pRbox->x2 = BOUND(v); if (pRbox->y1 < (v = pCbox->y1 + dy)) pRbox->y1 = BOUND(v); if (pRbox->y2 > (v = pCbox->y2 + dy)) pRbox->y2 = BOUND(v); if (pRbox->x1 >= pRbox->x2 || pRbox->y1 >= pRbox->y2) { pixman_region32_init (pRegion); } } else if (!pixman_region32_not_empty (pClip)) return FALSE; else { if (dx || dy) pixman_region32_translate (pRegion, -dx, -dy); if (!pixman_region32_intersect (pRegion, pRegion, pClip)) return FALSE; if (dx || dy) pixman_region32_translate(pRegion, dx, dy); } return pixman_region32_not_empty(pRegion); }
std::ostream& operator<<(std::ostream& stream, const nsRegion& m) { stream << "["; int n; pixman_box32_t *boxes = pixman_region32_rectangles(const_cast<pixman_region32_t*>(&m.mImpl), &n); for (int i=0; i<n; i++) { if (i != 0) { stream << "; "; } stream << boxes[i].x1 << "," << boxes[i].y1 << "," << boxes[i].x2 << "," << boxes[i].y2; } stream << "]"; return stream; }
void default_fill_region(struct wld_renderer * renderer, uint32_t color, pixman_region32_t * region) { pixman_box32_t * box; int num_boxes; box = pixman_region32_rectangles(region, &num_boxes); while (num_boxes--) { renderer->impl->fill_rectangle(renderer, color, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); ++box; } }
void RedScreen::composit_to_screen(RedDrawable& win_dc, const QRegion& region) { pixman_box32_t *rects; int num_rects; rects = pixman_region32_rectangles((pixman_region32_t *)®ion, &num_rects); for (int i = 0; i < num_rects; i++) { SpiceRect r; r.left = rects[i].x1; r.top = rects[i].y1; r.right = rects[i].x2; r.bottom = rects[i].y2; win_dc.copy_pixels(*_composit_area, r.left, r.top, r); } }
void nsRegion::SimplifyOutward (uint32_t aMaxRects) { MOZ_ASSERT(aMaxRects >= 1, "Invalid max rect count"); if (GetNumRects() <= aMaxRects) return; pixman_box32_t *boxes; int n; boxes = pixman_region32_rectangles(&mImpl, &n); // Try combining rects in horizontal bands into a single rect int dest = 0; for (int src = 1; src < n; src++) { // The goal here is to try to keep groups of rectangles that are vertically // discontiguous as separate rectangles in the final region. This is // simple and fast to implement and page contents tend to vary more // vertically than horizontally (which is why our rectangles are stored // sorted by y-coordinate, too). // // Note: if boxes share y1 because of the canonical representation they // will share y2 while ((src < (n)) && boxes[dest].y1 == boxes[src].y1) { // merge box[i] and box[i+1] boxes[dest].x2 = boxes[src].x2; src++; } if (src < n) { dest++; boxes[dest] = boxes[src]; } } uint32_t reducedCount = dest+1; // pixman has a special representation for // regions of 1 rectangle. So just use the // bounds in that case if (reducedCount > 1 && reducedCount <= aMaxRects) { // reach into pixman and lower the number // of rects stored in data. mImpl.data->numRects = reducedCount; } else { *this = GetBounds(); } }
void nsRegion::Inflate(const nsMargin& aMargin) { int n; pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n); for (int i=0; i<n; i++) { nsRect rect = BoxToRect(boxes[i]); rect.Inflate(aMargin); boxes[i] = RectToBox(rect); } pixman_region32_t region; // This will union all of the rectangles and runs in about O(n lg(n)) pixman_region32_init_rects(®ion, boxes, n); pixman_region32_fini(&mImpl); mImpl = region; }
nsRegion& nsRegion::Transform (const gfx3DMatrix &aTransform) { int n; pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n); for (int i=0; i<n; i++) { nsRect rect = BoxToRect(boxes[i]); boxes[i] = RectToBox(nsIntRegion::ToRect(TransformRect(nsIntRegion::FromRect(rect), aTransform))); } pixman_region32_t region; // This will union all of the rectangles and runs in about O(n lg(n)) pixman_region32_init_rects(®ion, boxes, n); pixman_region32_fini(&mImpl); mImpl = region; return *this; }
inline void RedScreen::erase_background(RedDrawable& dc, const QRegion& composit_rgn) { pixman_box32_t *rects; int num_rects; rects = pixman_region32_rectangles((pixman_region32_t *)&composit_rgn, &num_rects); for (int i = 0; i < num_rects; i++) { SpiceRect r; r.left = rects[i].x1; r.top = rects[i].y1; r.right = rects[i].x2; r.bottom = rects[i].y2; dc.fill_rect(r, 0); } }
void SCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc) { pixman_box32_t *rects; int num_rects; ASSERT(_pixmap != NULL); rects = pixman_region32_rectangles((pixman_region32_t *)®ion, &num_rects); for (int i = 0; i < num_rects; i++) { SpiceRect r; r.left = rects[i].x1; r.top = rects[i].y1; r.right = rects[i].x2; r.bottom = rects[i].y2; dest_dc.copy_pixels(*_pixmap, r.left, r.top, r); } }
void default_copy_region(struct wld_renderer * renderer, struct buffer * buffer, int32_t dst_x, int32_t dst_y, pixman_region32_t * region) { pixman_box32_t * box; int num_boxes; box = pixman_region32_rectangles(region, &num_boxes); while (num_boxes--) { renderer->impl->copy_rectangle(renderer, buffer, dst_x + box->x1, dst_y + box->y1, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); ++box; } }
nsRegion& nsRegion::ScaleInverseRoundOut (float aXScale, float aYScale) { int n; pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n); for (int i=0; i<n; i++) { nsRect rect = BoxToRect(boxes[i]); rect.ScaleInverseRoundOut(aXScale, aYScale); boxes[i] = RectToBox(rect); } pixman_region32_t region; // This will union all of the rectangles and runs in about O(n lg(n)) pixman_region32_init_rects(®ion, boxes, n); pixman_region32_fini(&mImpl); mImpl = region; return *this; }
nsCString nsRegion::ToString() const { nsCString result; result.Append('['); int n; pixman_box32_t *boxes = pixman_region32_rectangles(const_cast<pixman_region32_t*>(&mImpl), &n); for (int i=0; i<n; i++) { if (i != 0) { result.AppendLiteral("; "); } result.Append(nsPrintfCString("%d,%d,%d,%d", boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2)); } result.Append(']'); return result; }
void RedScreen::invalidate(const QRegion ®ion) { pixman_box32_t *rects, *end; int num_rects; rects = pixman_region32_rectangles((pixman_region32_t *)®ion, &num_rects); end = rects + num_rects; while (rects != end) { SpiceRect r; r.left = rects->x1; r.top = rects->y1; r.right = rects->x2; r.bottom = rects->y2; rects++; invalidate(r, false); } }
/** * cairo_region_get_rectangle: * @region: a #cairo_region_t * @nth: a number indicating which rectangle should be returned * @rectangle: return location for a #cairo_rectangle_int_t * * Stores the @nth rectangle from the region in @rectangle. * * Since: 1.10 **/ void cairo_region_get_rectangle (const cairo_region_t *region, int nth, cairo_rectangle_int_t *rectangle) { pixman_box32_t *pbox; if (region->status) { rectangle->x = rectangle->y = 0; rectangle->width = rectangle->height = 0; return; } pbox = pixman_region32_rectangles (CONST_CAST ®ion->rgn, NULL) + nth; rectangle->x = pbox->x1; rectangle->y = pbox->y1; rectangle->width = pbox->x2 - pbox->x1; rectangle->height = pbox->y2 - pbox->y1; }
nsIntRegion nsRegion::ToPixels (nscoord aAppUnitsPerPixel, bool aOutsidePixels) const { nsRegion region = *this; int n; pixman_box32_t *boxes = pixman_region32_rectangles(®ion.mImpl, &n); for (int i=0; i<n; i++) { nsRect rect = BoxToRect(boxes[i]); nsIntRect deviceRect; if (aOutsidePixels) deviceRect = rect.ToOutsidePixels(aAppUnitsPerPixel); else deviceRect = rect.ToNearestPixels(aAppUnitsPerPixel); boxes[i] = RectToBox(deviceRect); } nsIntRegion intRegion; pixman_region32_fini(&intRegion.mImpl.mImpl); // This will union all of the rectangles and runs in about O(n lg(n)) pixman_region32_init_rects(&intRegion.mImpl.mImpl, boxes, n); return intRegion; }
nsRegion nsRegion::ConvertAppUnitsRoundIn (int32_t aFromAPP, int32_t aToAPP) const { if (aFromAPP == aToAPP) { return *this; } nsRegion region = *this; int n; pixman_box32_t *boxes = pixman_region32_rectangles(®ion.mImpl, &n); for (int i=0; i<n; i++) { nsRect rect = BoxToRect(boxes[i]); rect = rect.ConvertAppUnitsRoundIn(aFromAPP, aToAPP); boxes[i] = RectToBox(rect); } pixman_region32_t pixmanRegion; // This will union all of the rectangles and runs in about O(n lg(n)) pixman_region32_init_rects(&pixmanRegion, boxes, n); pixman_region32_fini(®ion.mImpl); region.mImpl = pixmanRegion; return region; }
static void UwacSubmitBufferPtr(UwacWindow* window, UwacBuffer* buffer) { UINT32 nrects, i; #ifdef HAVE_PIXMAN_REGION const pixman_box32_t* box; #else const RECTANGLE_16* box; #endif wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0); #ifdef HAVE_PIXMAN_REGION box = pixman_region32_rectangles(&buffer->damage, &nrects); for (i = 0; i < nrects; i++, box++) wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1)); #else box = region16_rects(&buffer->damage, &nrects); for (i = 0; i < nrects; i++, box++) wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left), (box->bottom - box->top)); #endif if (window->frame_callback) wl_callback_destroy(window->frame_callback); window->frame_callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->frame_callback, &frame_listener, window); wl_surface_commit(window->surface); #ifdef HAVE_PIXMAN_REGION pixman_region32_clear(&buffer->damage); #else region16_clear(&buffer->damage); #endif }
void nsRegion::SimplifyOutwardByArea(uint32_t aThreshold) { pixman_box32_t *boxes; int n; boxes = pixman_region32_rectangles(&mImpl, &n); // if we have no rectangles then we're done if (!n) return; pixman_box32_t *end = boxes + n; pixman_box32_t *topRectsEnd = boxes+1; pixman_box32_t *topRects = boxes; // we need some temporary storage for merging both rows of rectangles nsAutoTArray<pixman_box32_t, 10> tmpStorage; tmpStorage.SetCapacity(n); pixman_box32_t *tmpRect = tmpStorage.Elements(); pixman_box32_t *destRect = boxes; pixman_box32_t *rect = tmpRect; // find the end of the first span of rectangles while (topRectsEnd < end && topRectsEnd->y1 == topRects->y1) { topRectsEnd++; } // if we only have one row we are done if (topRectsEnd == end) return; pixman_box32_t *bottomRects = topRectsEnd; pixman_box32_t *bottomRectsEnd = bottomRects+1; do { // find the end of the bottom span of rectangles while (bottomRectsEnd < end && bottomRectsEnd->y1 == bottomRects->y1) { bottomRectsEnd++; } uint32_t totalArea = ComputeMergedAreaIncrease(topRects, topRectsEnd, bottomRects, bottomRectsEnd); if (totalArea <= aThreshold) { // merge the rects into tmpRect rect = MergeRects(topRects, topRectsEnd, bottomRects, bottomRectsEnd, tmpRect); // copy the merged rects back into the destination topRectsEnd = CopyRow(destRect, tmpRect, rect); topRects = destRect; bottomRects = bottomRectsEnd; destRect = topRects; } else { // copy the unmerged rects destRect = CopyRow(destRect, topRects, topRectsEnd); topRects = bottomRects; topRectsEnd = bottomRectsEnd; bottomRects = bottomRectsEnd; if (bottomRectsEnd == end) { // copy the last row when we are done topRectsEnd = CopyRow(destRect, topRects, topRectsEnd); } } } while (bottomRectsEnd != end); uint32_t reducedCount = topRectsEnd - pixman_region32_rectangles(&this->mImpl, &n); // pixman has a special representation for // regions of 1 rectangle. So just use the // bounds in that case if (reducedCount > 1) { // reach into pixman and lower the number // of rects stored in data. this->mImpl.data->numRects = reducedCount; } else { *this = GetBounds(); } }
int main () { pixman_region32_t r1; pixman_region32_t r2; pixman_region32_t r3; pixman_box32_t boxes[] = { { 10, 10, 20, 20 }, { 30, 30, 30, 40 }, { 50, 45, 60, 44 }, }; pixman_box32_t boxes2[] = { { 2, 6, 7, 6 }, { 4, 1, 6, 7 }, }; pixman_box32_t boxes3[] = { { 2, 6, 7, 6 }, { 4, 1, 6, 1 }, }; int i; pixman_box32_t *b; /* This used to go into an infinite loop before pixman-region.c * was fixed to not use explict "short" variables */ pixman_region32_init_rect (&r1, 0, 0, 20, 64000); pixman_region32_init_rect (&r2, 0, 0, 20, 64000); pixman_region32_init_rect (&r3, 0, 0, 20, 64000); pixman_region32_subtract (&r1, &r2, &r3); /* This would produce a region containing an empty * rectangle in it. Such regions are considered malformed, * but using an empty rectangle for initialization should * work. */ pixman_region32_init_rects (&r1, boxes, 3); b = pixman_region32_rectangles (&r1, &i); assert (i == 1); while (i--) { assert (b[i].x1 < b[i].x2); assert (b[i].y1 < b[i].y2); } /* This would produce a rectangle containing the bounding box * of the two rectangles. The correct result is to eliminate * the broken rectangle. */ pixman_region32_init_rects (&r1, boxes2, 2); b = pixman_region32_rectangles (&r1, &i); assert (i == 1); assert (b[0].x1 == 4); assert (b[0].y1 == 1); assert (b[0].x2 == 6); assert (b[0].y2 == 7); /* This should produce an empty region */ pixman_region32_init_rects (&r1, boxes3, 2); b = pixman_region32_rectangles (&r1, &i); assert (i == 0); return 0; }
nsIntRegion nsRegion::ScaleToInsidePixels (float aScaleX, float aScaleY, nscoord aAppUnitsPerPixel) const { /* When scaling a rect, walk forward through the rect list up until the y value is greater * than the current rect's YMost() value. * * For each rect found, check if the rects have a touching edge (in unscaled coordinates), * and if one edge is entirely contained within the other. * * If it is, then the contained edge can be moved (in scaled pixels) to ensure that no * gap exists. * * Since this could be potentially expensive - O(n^2), we only attempt this algorithm * for the first rect. */ // make a copy of this region so that we can mutate it in place nsRegion region = *this; int n; pixman_box32_t *boxes = pixman_region32_rectangles(®ion.mImpl, &n); nsIntRegion intRegion; if (n) { nsRect first = BoxToRect(boxes[0]); nsIntRect firstDeviceRect = first.ScaleToInsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel); for (int i=1; i<n; i++) { nsRect rect = nsRect(boxes[i].x1, boxes[i].y1, boxes[i].x2 - boxes[i].x1, boxes[i].y2 - boxes[i].y1); nsIntRect deviceRect = rect.ScaleToInsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel); if (rect.y <= first.YMost()) { if (rect.XMost() == first.x && rect.YMost() <= first.YMost()) { // rect is touching on the left edge of the first rect and contained within // the length of its left edge deviceRect.SetRightEdge(firstDeviceRect.x); } else if (rect.x == first.XMost() && rect.YMost() <= first.YMost()) { // rect is touching on the right edge of the first rect and contained within // the length of its right edge deviceRect.SetLeftEdge(firstDeviceRect.XMost()); } else if (rect.y == first.YMost()) { // The bottom of the first rect is on the same line as the top of rect, but // they aren't necessarily contained. if (rect.x <= first.x && rect.XMost() >= first.XMost()) { // The top of rect contains the bottom of the first rect firstDeviceRect.SetBottomEdge(deviceRect.y); } else if (rect.x >= first.x && rect.XMost() <= first.XMost()) { // The bottom of the first contains the top of rect deviceRect.SetTopEdge(firstDeviceRect.YMost()); } } } boxes[i] = RectToBox(deviceRect); } boxes[0] = RectToBox(firstDeviceRect); pixman_region32_fini(&intRegion.mImpl.mImpl); // This will union all of the rectangles and runs in about O(n lg(n)) pixman_region32_init_rects(&intRegion.mImpl.mImpl, boxes, n); } return intRegion; }
int main () { pixman_region32_t r1; pixman_region32_t r2; pixman_region32_t r3; pixman_box32_t boxes[] = { { 10, 10, 20, 20 }, { 30, 30, 30, 40 }, { 50, 45, 60, 44 }, }; pixman_box32_t boxes2[] = { { 2, 6, 7, 6 }, { 4, 1, 6, 7 }, }; pixman_box32_t boxes3[] = { { 2, 6, 7, 6 }, { 4, 1, 6, 1 }, }; int i, j; pixman_box32_t *b; pixman_image_t *image, *fill; pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; /* This used to go into an infinite loop before pixman-region.c * was fixed to not use explict "short" variables */ pixman_region32_init_rect (&r1, 0, 0, 20, 64000); pixman_region32_init_rect (&r2, 0, 0, 20, 64000); pixman_region32_init_rect (&r3, 0, 0, 20, 64000); pixman_region32_subtract (&r1, &r2, &r3); /* This would produce a region containing an empty * rectangle in it. Such regions are considered malformed, * but using an empty rectangle for initialization should * work. */ pixman_region32_init_rects (&r1, boxes, 3); b = pixman_region32_rectangles (&r1, &i); assert (i == 1); while (i--) { assert (b[i].x1 < b[i].x2); assert (b[i].y1 < b[i].y2); } /* This would produce a rectangle containing the bounding box * of the two rectangles. The correct result is to eliminate * the broken rectangle. */ pixman_region32_init_rects (&r1, boxes2, 2); b = pixman_region32_rectangles (&r1, &i); assert (i == 1); assert (b[0].x1 == 4); assert (b[0].y1 == 1); assert (b[0].x2 == 6); assert (b[0].y2 == 7); /* This should produce an empty region */ pixman_region32_init_rects (&r1, boxes3, 2); b = pixman_region32_rectangles (&r1, &i); assert (i == 0); fill = pixman_image_create_solid_fill (&white); for (i = 0; i < 100; i++) { int image_size = 128; pixman_region32_init (&r1); /* Add some random rectangles */ for (j = 0; j < 64; j++) pixman_region32_union_rect (&r1, &r1, lcg_rand_n (image_size), lcg_rand_n (image_size), lcg_rand_n (25), lcg_rand_n (25)); /* Clip to image size */ pixman_region32_init_rect (&r2, 0, 0, image_size, image_size); pixman_region32_intersect (&r1, &r1, &r2); pixman_region32_fini (&r2); /* render region to a1 mask */ image = pixman_image_create_bits (PIXMAN_a1, image_size, image_size, NULL, 0); pixman_image_set_clip_region32 (image, &r1); pixman_image_composite32 (PIXMAN_OP_SRC, fill, NULL, image, 0, 0, 0, 0, 0, 0, image_size, image_size); pixman_region32_init_from_image (&r2, image); pixman_image_unref (image); assert (pixman_region32_equal (&r1, &r2)); pixman_region32_fini (&r1); pixman_region32_fini (&r2); } pixman_image_unref (fill); return 0; }
static void composite_clipped(pixman_image_t *src, pixman_image_t *mask, pixman_image_t *dest, const pixman_transform_t *transform, pixman_filter_t filter, pixman_region32_t *src_clip) { int n_box; pixman_box32_t *boxes; int32_t dest_width; int32_t dest_height; int src_stride; int bitspp; pixman_format_code_t src_format; void *src_data; int i; /* Hardcoded to use PIXMAN_OP_OVER, because sampling outside of * a Pixman image produces (0,0,0,0) instead of discarding the * fragment. */ dest_width = pixman_image_get_width(dest); dest_height = pixman_image_get_height(dest); src_format = pixman_image_get_format(src); src_stride = pixman_image_get_stride(src); bitspp = PIXMAN_FORMAT_BPP(src_format); src_data = pixman_image_get_data(src); assert(src_format); /* This would be massive overdraw, except when n_box is 1. */ boxes = pixman_region32_rectangles(src_clip, &n_box); for (i = 0; i < n_box; i++) { uint8_t *ptr = src_data; pixman_image_t *boximg; pixman_transform_t adj = *transform; ptr += boxes[i].y1 * src_stride; ptr += boxes[i].x1 * bitspp / 8; boximg = pixman_image_create_bits_no_clear(src_format, boxes[i].x2 - boxes[i].x1, boxes[i].y2 - boxes[i].y1, (uint32_t *)ptr, src_stride); pixman_transform_translate(&adj, NULL, pixman_int_to_fixed(-boxes[i].x1), pixman_int_to_fixed(-boxes[i].y1)); pixman_image_set_transform(boximg, &adj); pixman_image_set_filter(boximg, filter, NULL, 0); pixman_image_composite32(PIXMAN_OP_OVER, boximg, mask, dest, 0, 0, /* src_x, src_y */ 0, 0, /* mask_x, mask_y */ 0, 0, /* dest_x, dest_y */ dest_width, dest_height); pixman_image_unref(boximg); } if (n_box > 1) { static bool warned = false; if (!warned) weston_log("Pixman-renderer warning: %dx overdraw\n", n_box); warned = true; } }