void pixman_image_destroy (pixman_image_t *image) { pixman_image_destroyClip (image); if (image->freeCompClip) { pixman_region_destroy (image->pCompositeClip); image->pCompositeClip = NULL; } if (image->freeSourceClip) { pixman_region_destroy (image->pSourceClip); image->pSourceClip = NULL; } if (image->owns_pixels) { FbPixelsDestroy (image->pixels); image->pixels = NULL; } if (image->transform) { free (image->transform); image->transform = NULL; } free (image); }
int pixman_image_set_clip_region (pixman_image_t *image, pixman_region16_t *region) { pixman_image_destroyClip (image); if (region) { image->clientClip = pixman_region_create (); pixman_region_copy (image->clientClip, region); image->clientClipType = CT_REGION; } if (image->freeCompClip) pixman_region_destroy (image->pCompositeClip); image->pCompositeClip = pixman_region_create(); pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip, 0, 0, image->pixels->width, image->pixels->height); image->freeCompClip = 1; if (region) { pixman_region_translate (image->pCompositeClip, - image->clipOrigin.x, - image->clipOrigin.y); pixman_region_intersect (image->pCompositeClip, image->pCompositeClip, region); pixman_region_translate (image->pCompositeClip, image->clipOrigin.x, image->clipOrigin.y); } image->stateChanges |= CPClipMask; return 0; }
static cairo_status_t _cairo_quartz_surface_finish(void *abstract_surface) { cairo_quartz_surface_t *surface = abstract_surface; if (surface->clip_region) pixman_region_destroy (surface->clip_region); return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_clip_intersect_region (cairo_clip_t *clip, cairo_traps_t *traps, cairo_surface_t *target) { pixman_region16_t *region; cairo_status_t status; if (clip->mode != CAIRO_CLIP_MODE_REGION) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_traps_extract_region (traps, ®ion); if (status) return status; if (region == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; status = CAIRO_STATUS_SUCCESS; if (clip->region == NULL) { clip->region = region; } else { pixman_region16_t *intersection = pixman_region_create(); if (pixman_region_intersect (intersection, clip->region, region) == PIXMAN_REGION_STATUS_SUCCESS) { pixman_region_destroy (clip->region); clip->region = intersection; } else { status = CAIRO_STATUS_NO_MEMORY; } pixman_region_destroy (region); } clip->serial = _cairo_surface_allocate_clip_serial (target); return status; }
void _cairo_clip_fini (cairo_clip_t *clip) { cairo_surface_destroy (clip->surface); clip->surface = NULL; clip->serial = 0; if (clip->region) pixman_region_destroy (clip->region); clip->region = NULL; _cairo_clip_path_destroy (clip->path); clip->path = NULL; }
void pixman_image_destroyClip (pixman_image_t *image) { switch (image->clientClipType) { case CT_NONE: return; case CT_PIXMAP: pixman_image_destroy (image->clientClip); break; default: pixman_region_destroy (image->clientClip); break; } image->clientClip = NULL; image->clientClipType = CT_NONE; }
/** * _cairo_region_create_from_rectangle: * @rect: a #cairo_rectangle_t * * Creates a region with extents initialized from the given * rectangle. * * Return value: a newly created #pixman_region16_t or %NULL if * memory couldn't a allocated. **/ pixman_region16_t * _cairo_region_create_from_rectangle (cairo_rectangle_t *rect) { /* We can't use pixman_region_create_simple(), because it doesn't * have an error return */ pixman_region16_t *region = pixman_region_create (); if (pixman_region_union_rect (region, region, rect->x, rect->y, rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) { pixman_region_destroy (region); return NULL; } return region; }
static cairo_int_status_t _cairo_quartz_surface_set_clip_region(void *abstract_surface, pixman_region16_t * region) { cairo_quartz_surface_t *surface = abstract_surface; if (surface->clip_region) pixman_region_destroy (surface->clip_region); if (region) { surface->clip_region = pixman_region_create (); pixman_region_copy (surface->clip_region, region); } else surface->clip_region = NULL; return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_clip_reset (cairo_clip_t *clip) { /* destroy any existing clip-region artifacts */ cairo_surface_destroy (clip->surface); clip->surface = NULL; clip->serial = 0; if (clip->region) pixman_region_destroy (clip->region); clip->region = NULL; _cairo_clip_path_destroy (clip->path); clip->path = NULL; return CAIRO_STATUS_SUCCESS; }
/** * _cairo_traps_extract_region: * @traps: a #cairo_traps_t * @region: on return, %NULL is stored here if the trapezoids aren't * exactly representable as a pixman region, otherwise a * a pointer to such a region, newly allocated. * (free with pixman region destroy) * * Determines if a set of trapezoids are exactly representable as a * pixman region, and if so creates such a region. * * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY **/ cairo_status_t _cairo_traps_extract_region (cairo_traps_t *traps, pixman_region16_t **region) { int i; for (i = 0; i < traps->num_traps; i++) if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x && _cairo_fixed_is_integer(traps->traps[i].top) && _cairo_fixed_is_integer(traps->traps[i].bottom) && _cairo_fixed_is_integer(traps->traps[i].left.p1.x) && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) { *region = NULL; return CAIRO_STATUS_SUCCESS; } *region = pixman_region_create (); for (i = 0; i < traps->num_traps; i++) { int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x); int y = _cairo_fixed_integer_part(traps->traps[i].top); int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x; int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y; /* XXX: Sometimes we get degenerate trapezoids from the tesellator, * if we call pixman_region_union_rect(), it bizarrly fails on such * an empty rectangle, so skip them. */ if (width == 0 || height == 0) continue; if (pixman_region_union_rect (*region, *region, x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) { pixman_region_destroy (*region); return CAIRO_STATUS_NO_MEMORY; } } return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, cairo_rectangle_int16_t *rectangle) { if (!clip) return CAIRO_STATUS_SUCCESS; if (clip->path) { /* Intersect path extents here. */ } if (clip->region) { pixman_region16_t *intersection; cairo_status_t status = CAIRO_STATUS_SUCCESS; pixman_region_status_t pixman_status; intersection = _cairo_region_create_from_rectangle (rectangle); if (intersection == NULL) return CAIRO_STATUS_NO_MEMORY; pixman_status = pixman_region_intersect (intersection, clip->region, intersection); if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS) _cairo_region_extents_rectangle (intersection, rectangle); else status = CAIRO_STATUS_NO_MEMORY; pixman_region_destroy (intersection); if (status) return status; } if (clip->surface) _cairo_rectangle_intersect (rectangle, &clip->surface_rect); return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_clip_intersect_to_region (cairo_clip_t *clip, pixman_region16_t *region) { if (!clip) return CAIRO_STATUS_SUCCESS; if (clip->path) { /* Intersect clip path into region. */ } if (clip->region) pixman_region_intersect (region, clip->region, region); if (clip->surface) { pixman_region16_t *clip_rect; pixman_region_status_t pixman_status; cairo_status_t status = CAIRO_STATUS_SUCCESS; clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect); if (clip_rect == NULL) return CAIRO_STATUS_NO_MEMORY; pixman_status = pixman_region_intersect (region, clip_rect, region); if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS) status = CAIRO_STATUS_NO_MEMORY; pixman_region_destroy (clip_rect); if (status) return status; } return CAIRO_STATUS_SUCCESS; }
int FbComputeCompositeRegion (pixman_region16_t *region, pixman_image_t *iSrc, pixman_image_t *iMask, pixman_image_t *iDst, int16_t xSrc, int16_t ySrc, int16_t xMask, int16_t yMask, int16_t xDst, int16_t yDst, uint16_t width, uint16_t height) { int v; int x1, y1, x2, y2; /* XXX: This code previously directly set the extents of the region here. I need to decide whether removing that has broken this. Also, it might be necessary to just make the pixman_region16_t data structure transparent anyway in which case I can just put the code back. */ x1 = xDst; v = xDst + width; x2 = BOUND(v); y1 = yDst; v = yDst + height; y2 = BOUND(v); /* Check for empty operation */ if (x1 >= x2 || y1 >= y2) { pixman_region_empty (region); return 1; } /* clip against src */ if (!FbClipImageSrc (region, iSrc, xDst - xSrc, yDst - ySrc)) { pixman_region_destroy (region); return 0; } if (iSrc->alphaMap) { if (!FbClipImageSrc (region, iSrc->alphaMap, xDst - (xSrc + iSrc->alphaOrigin.x), yDst - (ySrc + iSrc->alphaOrigin.y))) { pixman_region_destroy (region); return 0; } } /* clip against mask */ if (iMask) { if (!FbClipImageSrc (region, iMask, xDst - xMask, yDst - yMask)) { pixman_region_destroy (region); return 0; } if (iMask->alphaMap) { if (!FbClipImageSrc (region, iMask->alphaMap, xDst - (xMask + iMask->alphaOrigin.x), yDst - (yMask + iMask->alphaOrigin.y))) { pixman_region_destroy (region); return 0; } } } if (!FbClipImageReg (region, iDst->pCompositeClip, 0, 0)) { pixman_region_destroy (region); return 0; } if (iDst->alphaMap) { if (!FbClipImageReg (region, iDst->alphaMap->pCompositeClip, -iDst->alphaOrigin.x, -iDst->alphaOrigin.y)) { pixman_region_destroy (region); return 0; } } return 1; }
/* XXX: There are failure cases in this function. Don't we need to * propagate the errors out? */ void pixman_composite_trapezoids (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, int xSrc, int ySrc, const pixman_trapezoid_t *traps, int ntraps) { pixman_image_t *image = NULL; pixman_box16_t traps_bounds, dst_bounds, bounds; pixman_region16_t *traps_region, *dst_region; int16_t xDst, yDst; int16_t xRel, yRel; pixman_format_t *format; if (ntraps == 0) return; /* * Check for solid alpha add */ if (op == PIXMAN_OPERATOR_ADD && miIsSolidAlpha (src)) { for (; ntraps; ntraps--, traps++) fbRasterizeTrapezoid (dst, traps, 0, 0); return; } xDst = traps[0].left.p1.x >> 16; yDst = traps[0].left.p1.y >> 16; pixman_trapezoid_bounds (ntraps, traps, &traps_bounds); traps_region = pixman_region_create_simple (&traps_bounds); /* XXX: If the image has a clip region set, we should really be * fetching it here instead, but it looks like we don't yet expose * a pixman_image_get_clip_region function. */ dst_bounds.x1 = 0; dst_bounds.y1 = 0; dst_bounds.x2 = pixman_image_get_width (dst); dst_bounds.y2 = pixman_image_get_height (dst); dst_region = pixman_region_create_simple (&dst_bounds); pixman_region_intersect (traps_region, traps_region, dst_region); bounds = *(pixman_region_extents (traps_region)); pixman_region_destroy (traps_region); pixman_region_destroy (dst_region); if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) return; format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); if (!format) return; image = FbCreateAlphaPicture (dst, format, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); if (!image) { pixman_format_destroy (format); return; } for (; ntraps; ntraps--, traps++) { if (!xTrapezoidValid(traps)) continue; fbRasterizeTrapezoid (image, traps, -bounds.x1, -bounds.y1); } xRel = bounds.x1 + xSrc - xDst; yRel = bounds.y1 + ySrc - yDst; pixman_composite (op, src, image, dst, xRel, yRel, 0, 0, bounds.x1, bounds.y1, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); pixman_image_destroy (image); pixman_format_destroy (format); }
/* Warning: This call modifies the coordinates of traps */ static cairo_status_t _clip_and_composite_trapezoids (cairo_pattern_t *src, cairo_operator_t op, cairo_surface_t *dst, cairo_traps_t *traps, cairo_clip_t *clip, cairo_antialias_t antialias) { cairo_status_t status; pixman_region16_t *trap_region; pixman_region16_t *clear_region = NULL; cairo_rectangle_int16_t extents; cairo_composite_traps_info_t traps_info; if (traps->num_traps == 0) return CAIRO_STATUS_SUCCESS; status = _cairo_traps_extract_region (traps, &trap_region); if (status) return status; if (_cairo_operator_bounded_by_mask (op)) { if (trap_region) { status = _cairo_clip_intersect_to_region (clip, trap_region); _cairo_region_extents_rectangle (trap_region, &extents); } else { cairo_box_t trap_extents; _cairo_traps_extents (traps, &trap_extents); _cairo_box_round_to_rectangle (&trap_extents, &extents); status = _cairo_clip_intersect_to_rectangle (clip, &extents); } } else { cairo_surface_t *clip_surface = clip ? clip->surface : NULL; status = _cairo_surface_get_extents (dst, &extents); if (status) return status; if (trap_region && !clip_surface) { /* If we optimize drawing with an unbounded operator to * _cairo_surface_fill_rectangles() or to drawing with a * clip region, then we have an additional region to clear. */ clear_region = _cairo_region_create_from_rectangle (&extents); if (clear_region == NULL) return CAIRO_STATUS_NO_MEMORY; status = _cairo_clip_intersect_to_region (clip, clear_region); if (status) return status; _cairo_region_extents_rectangle (clear_region, &extents); if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS) return CAIRO_STATUS_NO_MEMORY; if (!pixman_region_not_empty (clear_region)) { pixman_region_destroy (clear_region); clear_region = NULL; } } else { status = _cairo_clip_intersect_to_rectangle (clip, &extents); if (status) return status; } } if (status) goto out; if (trap_region) { cairo_surface_t *clip_surface = clip ? clip->surface : NULL; if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) && !clip_surface) { const cairo_color_t *color; if (op == CAIRO_OPERATOR_CLEAR) color = CAIRO_COLOR_TRANSPARENT; else color = &((cairo_solid_pattern_t *)src)->color; /* Solid rectangles special case */ status = _cairo_surface_fill_region (dst, op, color, trap_region); if (!status && clear_region) status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, clear_region); goto out; } if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) || !clip_surface) { /* For a simple rectangle, we can just use composite(), for more * rectangles, we have to set a clip region. The cost of rasterizing * trapezoids is pretty high for most backends currently, so it's * worthwhile even if a region is needed. * * If we have a clip surface, we set it as the mask; this only works * for bounded operators other than SOURCE; for unbounded operators, * clip and mask cannot be interchanged. For SOURCE, the operator * as implemented by the backends is different in it's handling * of the mask then what we want. * * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has * more than rectangle and the destination doesn't support clip * regions. In that case, we fall through. */ status = _composite_trap_region (clip, src, op, dst, trap_region, &extents); if (status != CAIRO_INT_STATUS_UNSUPPORTED) { if (!status && clear_region) status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, clear_region); goto out; } } } traps_info.traps = traps; traps_info.antialias = antialias; status = _clip_and_composite (clip, op, src, _composite_traps_draw_func, &traps_info, dst, &extents); out: if (trap_region) pixman_region_destroy (trap_region); if (clear_region) pixman_region_destroy (clear_region); return status; }
static void pixman_color_rects (pixman_image_t *dst, pixman_image_t *clipPict, pixman_color_t *color, int nRect, pixman_rectangle_t *rects, int xoff, int yoff) { pixman_bits_t pixel; pixman_region16_t *clip; pixman_region16_t *rects_as_region; pixman_box16_t *clipped_rects; int i, n_clipped_rects; FillFunc func; pixman_color_to_pixel (&dst->image_format, color, &pixel); /* offset to the right place on the destination image */ xoff -= dst->pixels->x; yoff -= dst->pixels->y; clip = pixman_region_create(); pixman_region_union_rect (clip, clip, dst->pixels->x, dst->pixels->y, dst->pixels->width, dst->pixels->height); pixman_region_intersect (clip, clip, clipPict->pCompositeClip); if (clipPict->alphaMap) { pixman_region_translate (clip, -clipPict->alphaOrigin.x, -clipPict->alphaOrigin.y); pixman_region_intersect (clip, clip, clipPict->alphaMap->pCompositeClip); pixman_region_translate (clip, clipPict->alphaOrigin.x, clipPict->alphaOrigin.y); } if (xoff || yoff) { for (i = 0; i < nRect; i++) { rects[i].x -= xoff; rects[i].y -= yoff; } } rects_as_region = pixman_region_create (); for (i = 0; i < nRect; i++) { pixman_region_union_rect (rects_as_region, rects_as_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height); } pixman_region_intersect (rects_as_region, rects_as_region, clip); pixman_region_destroy (clip); n_clipped_rects = pixman_region_num_rects (rects_as_region); clipped_rects = pixman_region_rects (rects_as_region); if (dst->pixels->bpp == 8) func = pixman_fill_rect_8bpp; else if (dst->pixels->bpp == 32) func = pixman_fill_rect_32bpp; else if (dst->pixels->bpp == 1) func = pixman_fill_rect_1bpp; else func = pixman_fill_rect_general; for (i = 0; i < n_clipped_rects; i++) { (*func) (dst, clipped_rects[i].x1, clipped_rects[i].y1, clipped_rects[i].x2 - clipped_rects[i].x1, clipped_rects[i].y2 - clipped_rects[i].y1, &pixel); } pixman_region_destroy (rects_as_region); if (xoff || yoff) { for (i = 0; i < nRect; i++) { rects[i].x += xoff; rects[i].y += yoff; } } }