~ubuntu-branches/debian/squeeze/pixman/squeeze

« back to all changes in this revision

Viewing changes to pixman/pixman-compute-region.c

  • Committer: Bazaar Package Importer
  • Author(s): David Nusinow
  • Date: 2007-08-09 22:15:45 UTC
  • Revision ID: james.westby@ubuntu.com-20070809221545-b3rj83wnluotrybv
Tags: upstream-0.9.4
Import upstream version 0.9.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright © 1999 Keith Packard
 
4
 *
 
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.
 
14
 *
 
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.
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
#include <stdlib.h>
 
26
#include <stdio.h>
 
27
#include "pixman-private.h"
 
28
 
 
29
#define BOUND(v)        (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
 
30
 
 
31
static inline pixman_bool_t
 
32
miClipPictureReg (pixman_region16_t *   pRegion,
 
33
                  pixman_region16_t *   pClip,
 
34
                  int           dx,
 
35
                  int           dy)
 
36
{
 
37
    if (pixman_region_n_rects(pRegion) == 1 &&
 
38
        pixman_region_n_rects(pClip) == 1)
 
39
    {
 
40
        pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
 
41
        pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
 
42
        int     v;
 
43
        
 
44
        if (pRbox->x1 < (v = pCbox->x1 + dx))
 
45
            pRbox->x1 = BOUND(v);
 
46
        if (pRbox->x2 > (v = pCbox->x2 + dx))
 
47
            pRbox->x2 = BOUND(v);
 
48
        if (pRbox->y1 < (v = pCbox->y1 + dy))
 
49
            pRbox->y1 = BOUND(v);
 
50
        if (pRbox->y2 > (v = pCbox->y2 + dy))
 
51
            pRbox->y2 = BOUND(v);
 
52
        if (pRbox->x1 >= pRbox->x2 ||
 
53
            pRbox->y1 >= pRbox->y2)
 
54
        {
 
55
            pixman_region_init (pRegion);
 
56
        }
 
57
    }
 
58
    else if (!pixman_region_not_empty (pClip))
 
59
        return FALSE;
 
60
    else
 
61
    {
 
62
        if (dx || dy)
 
63
            pixman_region_translate (pRegion, -dx, -dy);
 
64
        if (!pixman_region_intersect (pRegion, pRegion, pClip))
 
65
            return FALSE;
 
66
        if (dx || dy)
 
67
            pixman_region_translate(pRegion, dx, dy);
 
68
    }
 
69
    return pixman_region_not_empty(pRegion);
 
70
}
 
71
 
 
72
 
 
73
static inline pixman_bool_t
 
74
miClipPictureSrc (pixman_region16_t *   pRegion,
 
75
                  pixman_image_t *      pPicture,
 
76
                  int           dx,
 
77
                  int           dy)
 
78
{
 
79
    /* XXX what to do with clipping from transformed pictures? */
 
80
    if (pPicture->common.transform || pPicture->type != BITS)
 
81
        return TRUE;
 
82
 
 
83
    if (pPicture->common.repeat)
 
84
    {
 
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.
 
88
         *
 
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.
 
95
         */
 
96
        if (pPicture->common.has_client_clip)
 
97
        {
 
98
            pixman_region_translate ( pRegion, dx, dy);
 
99
            
 
100
            if (!pixman_region_intersect (pRegion, pRegion, 
 
101
                                          (pixman_region16_t *) pPicture->common.src_clip))
 
102
                return FALSE;
 
103
            
 
104
            pixman_region_translate ( pRegion, -dx, -dy);
 
105
        }
 
106
            
 
107
        return TRUE;
 
108
    }
 
109
    else
 
110
    {
 
111
        return miClipPictureReg (pRegion,
 
112
                                 pPicture->common.src_clip,
 
113
                                 dx,
 
114
                                 dy);
 
115
    }
 
116
}
 
117
 
 
118
/*
 
119
 * returns FALSE if the final region is empty.  Indistinguishable from
 
120
 * an allocation failure, but rendering ignores those anyways.
 
121
 */
 
122
 
 
123
pixman_bool_t
 
124
pixman_compute_composite_region (pixman_region16_t *    pRegion,
 
125
                                 pixman_image_t *       pSrc,
 
126
                                 pixman_image_t *       pMask,
 
127
                                 pixman_image_t *       pDst,
 
128
                                 int16_t                xSrc,
 
129
                                 int16_t                ySrc,
 
130
                                 int16_t                xMask,
 
131
                                 int16_t                yMask,
 
132
                                 int16_t                xDst,
 
133
                                 int16_t                yDst,
 
134
                                 uint16_t       width,
 
135
                                 uint16_t       height)
 
136
{
 
137
    int         v;
 
138
    
 
139
    pRegion->extents.x1 = xDst;
 
140
    v = xDst + width;
 
141
    pRegion->extents.x2 = BOUND(v);
 
142
    pRegion->extents.y1 = yDst;
 
143
    v = yDst + height;
 
144
    pRegion->extents.y2 = BOUND(v);
 
145
    pRegion->data = 0;
 
146
    /* Check for empty operation */
 
147
    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
 
148
        pRegion->extents.y1 >= pRegion->extents.y2)
 
149
    {
 
150
        pixman_region_init (pRegion);
 
151
        return FALSE;
 
152
    }
 
153
    /* clip against dst */
 
154
    if (!miClipPictureReg (pRegion, &pDst->common.clip_region, 0, 0))
 
155
    {
 
156
        pixman_region_fini (pRegion);
 
157
        return FALSE;
 
158
    }
 
159
    if (pDst->common.alpha_map)
 
160
    {
 
161
        if (!miClipPictureReg (pRegion, &pDst->common.alpha_map->common.clip_region,
 
162
                               -pDst->common.alpha_origin.x,
 
163
                               -pDst->common.alpha_origin.y))
 
164
        {
 
165
            pixman_region_fini (pRegion);
 
166
            return FALSE;
 
167
        }
 
168
    }
 
169
    /* clip against src */
 
170
    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
 
171
    {
 
172
        pixman_region_fini (pRegion);
 
173
        return FALSE;
 
174
    }
 
175
    if (pSrc->common.alpha_map)
 
176
    {
 
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)))
 
180
        {
 
181
            pixman_region_fini (pRegion);
 
182
            return FALSE;
 
183
        }
 
184
    }
 
185
    /* clip against mask */
 
186
    if (pMask)
 
187
    {
 
188
        if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
 
189
        {
 
190
            pixman_region_fini (pRegion);
 
191
            return FALSE;
 
192
        }       
 
193
        if (pMask->common.alpha_map)
 
194
        {
 
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)))
 
198
            {
 
199
                pixman_region_fini (pRegion);
 
200
                return FALSE;
 
201
            }
 
202
        }
 
203
    }
 
204
    
 
205
    return TRUE;
 
206
}