pixman-utils.c \
pixman-edge.c \
pixman-edge-imp.h \
- pixman-trap.c
-
+ pixman-trap.c \
+ pixman-compute-region.c
if USE_MMX
noinst_LTLIBRARIES = libpixman-mmx.la
--- /dev/null
+/*
+ *
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "pixman-private.h"
+
+#define BOUND(v) (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
+
+static inline pixman_bool_t
+miClipPictureReg (pixman_region16_t * pRegion,
+ pixman_region16_t * pClip,
+ int dx,
+ int dy)
+{
+ if (pixman_region_n_rects(pRegion) == 1 &&
+ pixman_region_n_rects(pClip) == 1)
+ {
+ pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL);
+ pixman_box16_t * pCbox = pixman_region_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_region_init (pRegion);
+ }
+ }
+ else if (!pixman_region_not_empty (pClip))
+ return FALSE;
+ else
+ {
+ if (dx || dy)
+ pixman_region_translate (pRegion, -dx, -dy);
+ if (!pixman_region_intersect (pRegion, pRegion, pClip))
+ return FALSE;
+ if (dx || dy)
+ pixman_region_translate(pRegion, dx, dy);
+ }
+ return pixman_region_not_empty(pRegion);
+}
+
+
+static inline pixman_bool_t
+miClipPictureSrc (pixman_region16_t * pRegion,
+ pixman_image_t * pPicture,
+ int dx,
+ int dy)
+{
+ /* XXX what to do with clipping from transformed pictures? */
+ if (pPicture->common.transform || pPicture->type != BITS)
+ return TRUE;
+
+ if (pPicture->common.repeat)
+ {
+ /* If the clip region was set by a client, then it should be intersected
+ * with the composite region since it's interpreted as happening
+ * after the repeat algorithm.
+ *
+ * If the clip region was not set by a client, then it was imposed by
+ * boundaries of the pixmap, or by sibling or child windows, which means
+ * it should in theory be repeated along. FIXME: we ignore that case.
+ * It is only relevant for windows that are (a) clipped by siblings/children
+ * and (b) used as source. However this case is not useful anyway due
+ * to lack of GraphicsExpose events.
+ */
+ if (pPicture->common.has_client_clip)
+ {
+ pixman_region_translate ( pRegion, dx, dy);
+
+ if (!pixman_region_intersect (pRegion, pRegion,
+ (pixman_region16_t *) &pPicture->common.clip_region))
+ return FALSE;
+
+ pixman_region_translate ( pRegion, -dx, -dy);
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ return miClipPictureReg (pRegion,
+ &pPicture->common.clip_region,
+ dx,
+ dy);
+ }
+}
+
+/*
+ * returns FALSE if the final region is empty. Indistinguishable from
+ * an allocation failure, but rendering ignores those anyways.
+ */
+
+pixman_bool_t
+pixman_compute_composite_region (pixman_region16_t * pRegion,
+ pixman_image_t * pSrc,
+ pixman_image_t * pMask,
+ pixman_image_t * pDst,
+ 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;
+
+ pRegion->extents.x1 = xDst;
+ v = xDst + width;
+ pRegion->extents.x2 = BOUND(v);
+ pRegion->extents.y1 = yDst;
+ v = yDst + height;
+ pRegion->extents.y2 = BOUND(v);
+ pRegion->data = 0;
+ /* Check for empty operation */
+ if (pRegion->extents.x1 >= pRegion->extents.x2 ||
+ pRegion->extents.y1 >= pRegion->extents.y2)
+ {
+ pixman_region_init (pRegion);
+ return FALSE;
+ }
+ /* clip against dst */
+ if (!miClipPictureReg (pRegion, &pDst->common.clip_region, 0, 0))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ if (pDst->common.alpha_map)
+ {
+ if (!miClipPictureReg (pRegion, &pDst->common.alpha_map->common.clip_region,
+ -pDst->common.alpha_origin.x,
+ -pDst->common.alpha_origin.y))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ }
+ /* clip against src */
+ if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ if (pSrc->common.alpha_map)
+ {
+ if (!miClipPictureSrc (pRegion, (pixman_image_t *)pSrc->common.alpha_map,
+ xDst - (xSrc + pSrc->common.alpha_origin.x),
+ yDst - (ySrc + pSrc->common.alpha_origin.y)))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ }
+ /* clip against mask */
+ if (pMask)
+ {
+ if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ if (pMask->common.alpha_map)
+ {
+ if (!miClipPictureSrc (pRegion, (pixman_image_t *)pMask->common.alpha_map,
+ xDst - (xMask + pMask->common.alpha_origin.x),
+ yDst - (yMask + pMask->common.alpha_origin.y)))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
image_common_t *common = &image->common;
pixman_region_init (&common->clip_region);
+ common->has_client_clip = FALSE;
common->transform = NULL;
common->repeat = PIXMAN_REPEAT_NONE;
common->filter = PIXMAN_FILTER_NEAREST;
}
}
+/* Sets whether the clip region includes a clip region set by the client
+ */
+void
+pixman_image_set_has_client_clip (pixman_image_t *image,
+ pixman_bool_t client_clip)
+{
+ image->common.has_client_clip = client_clip;
+}
+
void
pixman_image_set_transform (pixman_image_t *image,
const pixman_transform_t *transform)
#endif
}
-#define BOUND(v) (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
-
-static __inline pixman_bool_t
-miClipPictureReg (pixman_region16_t * pRegion,
- pixman_region16_t * pClip,
- int dx,
- int dy)
-{
- if (pixman_region_n_rects(pRegion) == 1 &&
- pixman_region_n_rects(pClip) == 1)
- {
- pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL);
- pixman_box16_t * pCbox = pixman_region_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_region_init (pRegion);
- }
- }
- else if (!pixman_region_not_empty (pClip))
- return FALSE;
- else
- {
- if (dx || dy)
- pixman_region_translate (pRegion, -dx, -dy);
- if (!pixman_region_intersect (pRegion, pRegion, pClip))
- return FALSE;
- if (dx || dy)
- pixman_region_translate(pRegion, dx, dy);
- }
- return pixman_region_not_empty (pRegion);
-}
-
-static __inline pixman_bool_t
-miClipPictureSrc (pixman_region16_t * pRegion,
- pixman_image_t * pPicture,
- int dx,
- int dy)
-{
- /* XXX what to do with clipping from transformed pictures? */
- if (pPicture->common.transform || pPicture->type != BITS)
- return TRUE;
-
- return miClipPictureReg (pRegion,
- &pPicture->common.clip_region,
- dx,
- dy);
-}
-
-static pixman_bool_t
-compute_composite_region (pixman_region16_t * pRegion,
- pixman_image_t * pSrc,
- pixman_image_t * pMask,
- pixman_image_t * pDst,
- 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;
-
- pRegion->extents.x1 = xDst;
- v = xDst + width;
- pRegion->extents.x2 = BOUND(v);
- pRegion->extents.y1 = yDst;
- v = yDst + height;
- pRegion->extents.y2 = BOUND(v);
- pRegion->data = 0;
- /* Check for empty operation */
- if (pRegion->extents.x1 >= pRegion->extents.x2 ||
- pRegion->extents.y1 >= pRegion->extents.y2)
- {
- pixman_region_init (pRegion);
- return FALSE;
- }
- /* clip against dst */
- if (!miClipPictureReg (pRegion, &pDst->common.clip_region, 0, 0))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pDst->common.alpha_map)
- {
- if (!miClipPictureReg (pRegion, &pDst->common.alpha_map->common.clip_region,
- -pDst->common.alpha_origin.x,
- -pDst->common.alpha_origin.y))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- /* clip against src */
- if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pSrc->common.alpha_map)
- {
- if (!miClipPictureSrc (pRegion, (pixman_image_t *)pSrc->common.alpha_map,
- xDst - (xSrc + pSrc->common.alpha_origin.x),
- yDst - (ySrc + pSrc->common.alpha_origin.y)))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- /* clip against mask */
- if (pMask)
- {
- if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pMask->common.alpha_map)
- {
- if (!miClipPictureSrc (pRegion, (pixman_image_t *)pMask->common.alpha_map,
- xDst - (xMask + pMask->common.alpha_origin.x),
- yDst - (yMask + pMask->common.alpha_origin.y)))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
static void
pixman_walk_composite_region (pixman_op_t op,
pixman_image_t * pSrc,
uint16_t height,
pixman_bool_t srcRepeat,
pixman_bool_t maskRepeat,
- CompositeFunc compositeRect,
- pixman_region16_t *region)
+ CompositeFunc compositeRect)
{
-#if 0
- pixman_region16_t region;
-#endif
int n;
const pixman_box16_t *pbox;
int w, h, w_this, h_this;
int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
-
-#if 0
- if (!compute_composite_region (®ion, pSrc, pMask, pDst, xSrc, ySrc,
- xMask, yMask, xDst, yDst, width, height))
+ pixman_region16_t reg;
+ pixman_region16_t *region;
+
+ pixman_region_init (®);
+ if (!pixman_compute_composite_region (®, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
{
- fprinf ("blah\n");
- return;
+ return;
}
-#endif
+
+ region = ®
pbox = pixman_region_rectangles (region, &n);
while (n--)
}
pbox++;
}
-#if 0
- pixman_region_fini (®ion);
-#endif
+ pixman_region_fini (®);
}
static pixman_bool_t
int16_t xDst,
int16_t yDst,
uint16_t width,
- uint16_t height,
- pixman_region16_t *region)
+ uint16_t height)
{
pixman_bool_t srcRepeat = pSrc->type == BITS && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL;
pixman_bool_t maskRepeat = FALSE;
pixman_bool_t maskAlphaMap = FALSE;
pixman_bool_t dstAlphaMap = pDst->common.alpha_map != NULL;
CompositeFunc func = NULL;
-
+
#ifdef USE_MMX
static pixman_bool_t mmx_setup = FALSE;
if (!mmx_setup)
pixman_walk_composite_region (op, pSrc, pMask, pDst, xSrc, ySrc,
xMask, yMask, xDst, yDst, width, height,
- srcRepeat, maskRepeat, func, region);
+ srcRepeat, maskRepeat, func);
}
image_type_t type;
int32_t ref_count;
pixman_region16_t clip_region;
+ pixman_bool_t has_client_clip;
pixman_transform_t *transform;
pixman_repeat_t repeat;
pixman_filter_t filter;
#include <stdlib.h>
#include <limits.h>
#include <string.h>
+#include <stdio.h>
#include "pixman-private.h"
#include "pixman.h"
return TRUE;
}
-#ifdef DEBUG_PIXREGION
-static int
+int
pixman_region16_print(rgn)
pixman_region16_t * rgn;
{
num = PIXREGION_NUM_RECTS(rgn);
size = PIXREGION_SIZE(rgn);
rects = PIXREGION_RECTS(rgn);
- ErrorF("num: %d size: %d\n", num, size);
- ErrorF("extents: %d %d %d %d\n",
+ fprintf(stderr, "num: %d size: %d\n", num, size);
+ fprintf(stderr, "extents: %d %d %d %d\n",
rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
for (i = 0; i < num; i++)
- ErrorF("%d %d %d %d \n",
- rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
- ErrorF("\n");
+ fprintf(stderr, "%d %d %d %d \n",
+ rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
+ fprintf(stderr, "\n");
return(num);
}
-#endif /* DEBUG_PIXREGION */
void
pixman_region_init (pixman_region16_t *region)
return PIXREGION_RECTS (region);
}
-const pixman_box16_t *
+pixman_box16_t *
pixman_region_rectangles (pixman_region16_t *region,
int *n_rects)
{
pixman_bool_t pixman_region_not_empty (pixman_region16_t *region);
pixman_box16_t * pixman_region_extents (pixman_region16_t *region);
int pixman_region_n_rects (pixman_region16_t *region);
-const pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region,
+pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region,
int *n_rects);
pixman_bool_t pixman_region_equal (pixman_region16_t *region1,
pixman_region16_t *region2);
/* Set properties */
void pixman_image_set_clip_region (pixman_image_t *image,
pixman_region16_t *region);
+void pixman_image_set_has_client_clip (pixman_image_t *image,
+ pixman_bool_t clien_clip);
void pixman_image_set_transform (pixman_image_t *image,
const pixman_transform_t *transform);
void pixman_image_set_repeat (pixman_image_t *image,
const pixman_indexed_t *indexed);
/* Composite */
+pixman_bool_t pixman_compute_composite_region (pixman_region16_t * pRegion,
+ pixman_image_t * pSrc,
+ pixman_image_t * pMask,
+ pixman_image_t * pDst,
+ int16_t xSrc,
+ int16_t ySrc,
+ int16_t xMask,
+ int16_t yMask,
+ int16_t xDst,
+ int16_t yDst,
+ uint16_t width,
+ uint16_t height);
void pixman_image_composite (pixman_op_t op,
pixman_image_t *src,
pixman_image_t *mask,
int16_t dest_x,
int16_t dest_y,
uint16_t width,
- uint16_t height,
- pixman_region16_t *composite_region);
+ uint16_t height);
void pixman_image_composite_rect (pixman_op_t op,
pixman_image_t *src,
pixman_image_t *mask,