3
* Copyright © 1999 Keith Packard
5
* Permission to use, copy, modify, distribute, and sell this software and its
6
* documentation for any purpose is hereby granted without fee, provided that
7
* the above copyright notice appear in all copies and that both that
8
* copyright notice and this permission notice appear in supporting
9
* documentation, and that the name of Keith Packard not be used in
10
* advertising or publicity pertaining to distribution of the software without
11
* specific, written prior permission. Keith Packard makes no
12
* representations about the suitability of this software for any purpose. It
13
* is provided "as is" without express or implied warranty.
15
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21
* PERFORMANCE OF THIS SOFTWARE.
27
#include "pixman-private.h"
29
#define BOUND(v) (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
31
static inline pixman_bool_t
32
miClipPictureReg (pixman_region16_t * pRegion,
33
pixman_region16_t * pClip,
37
if (pixman_region_n_rects(pRegion) == 1 &&
38
pixman_region_n_rects(pClip) == 1)
40
pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL);
41
pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL);
44
if (pRbox->x1 < (v = pCbox->x1 + dx))
46
if (pRbox->x2 > (v = pCbox->x2 + dx))
48
if (pRbox->y1 < (v = pCbox->y1 + dy))
50
if (pRbox->y2 > (v = pCbox->y2 + dy))
52
if (pRbox->x1 >= pRbox->x2 ||
53
pRbox->y1 >= pRbox->y2)
55
pixman_region_init (pRegion);
58
else if (!pixman_region_not_empty (pClip))
63
pixman_region_translate (pRegion, -dx, -dy);
64
if (!pixman_region_intersect (pRegion, pRegion, pClip))
67
pixman_region_translate(pRegion, dx, dy);
69
return pixman_region_not_empty(pRegion);
73
static inline pixman_bool_t
74
miClipPictureSrc (pixman_region16_t * pRegion,
75
pixman_image_t * pPicture,
79
/* XXX what to do with clipping from transformed pictures? */
80
if (pPicture->common.transform || pPicture->type != BITS)
83
if (pPicture->common.repeat)
85
/* If the clip region was set by a client, then it should be intersected
86
* with the composite region since it's interpreted as happening
87
* after the repeat algorithm.
89
* If the clip region was not set by a client, then it was imposed by
90
* boundaries of the pixmap, or by sibling or child windows, which means
91
* it should in theory be repeated along. FIXME: we ignore that case.
92
* It is only relevant for windows that are (a) clipped by siblings/children
93
* and (b) used as source. However this case is not useful anyway due
94
* to lack of GraphicsExpose events.
96
if (pPicture->common.has_client_clip)
98
pixman_region_translate ( pRegion, dx, dy);
100
if (!pixman_region_intersect (pRegion, pRegion,
101
(pixman_region16_t *) pPicture->common.src_clip))
104
pixman_region_translate ( pRegion, -dx, -dy);
111
return miClipPictureReg (pRegion,
112
pPicture->common.src_clip,
119
* returns FALSE if the final region is empty. Indistinguishable from
120
* an allocation failure, but rendering ignores those anyways.
124
pixman_compute_composite_region (pixman_region16_t * pRegion,
125
pixman_image_t * pSrc,
126
pixman_image_t * pMask,
127
pixman_image_t * pDst,
139
pRegion->extents.x1 = xDst;
141
pRegion->extents.x2 = BOUND(v);
142
pRegion->extents.y1 = yDst;
144
pRegion->extents.y2 = BOUND(v);
146
/* Check for empty operation */
147
if (pRegion->extents.x1 >= pRegion->extents.x2 ||
148
pRegion->extents.y1 >= pRegion->extents.y2)
150
pixman_region_init (pRegion);
153
/* clip against dst */
154
if (!miClipPictureReg (pRegion, &pDst->common.clip_region, 0, 0))
156
pixman_region_fini (pRegion);
159
if (pDst->common.alpha_map)
161
if (!miClipPictureReg (pRegion, &pDst->common.alpha_map->common.clip_region,
162
-pDst->common.alpha_origin.x,
163
-pDst->common.alpha_origin.y))
165
pixman_region_fini (pRegion);
169
/* clip against src */
170
if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
172
pixman_region_fini (pRegion);
175
if (pSrc->common.alpha_map)
177
if (!miClipPictureSrc (pRegion, (pixman_image_t *)pSrc->common.alpha_map,
178
xDst - (xSrc + pSrc->common.alpha_origin.x),
179
yDst - (ySrc + pSrc->common.alpha_origin.y)))
181
pixman_region_fini (pRegion);
185
/* clip against mask */
188
if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
190
pixman_region_fini (pRegion);
193
if (pMask->common.alpha_map)
195
if (!miClipPictureSrc (pRegion, (pixman_image_t *)pMask->common.alpha_map,
196
xDst - (xMask + pMask->common.alpha_origin.x),
197
yDst - (yMask + pMask->common.alpha_origin.y)))
199
pixman_region_fini (pRegion);