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

« back to all changes in this revision

Viewing changes to pixman/pixman-edge.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
 * $Id$
 
3
 *
 
4
 * Copyright © 2004 Keith Packard
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
#include <config.h>
 
25
#include <string.h>
 
26
#include "pixman.h"
 
27
#include "pixman-private.h"
 
28
 
 
29
#ifdef PIXMAN_FB_ACCESSORS
 
30
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
 
31
#else
 
32
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
 
33
#endif
 
34
 
 
35
/*
 
36
 * 4 bit alpha
 
37
 */
 
38
 
 
39
#define N_BITS  4
 
40
#define rasterizeEdges  fbRasterizeEdges4
 
41
 
 
42
#if BITMAP_BIT_ORDER == LSBFirst
 
43
#define Shift4(o)       ((o) << 2)
 
44
#else
 
45
#define Shift4(o)       ((1-(o)) << 2)
 
46
#endif
 
47
 
 
48
#define Get4(x,o)       (((x) >> Shift4(o)) & 0xf)
 
49
#define Put4(x,o,v)     (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
 
50
 
 
51
#define DefineAlpha(line,x)                          \
 
52
    uint8_t   *__ap = (uint8_t *) line + ((x) >> 1); \
 
53
    int     __ao = (x) & 1
 
54
 
 
55
#define StepAlpha       ((__ap += __ao), (__ao ^= 1))
 
56
 
 
57
#define AddAlpha(a) {                                           \
 
58
        uint8_t   __o = READ(__ap);                             \
 
59
        uint8_t   __a = (a) + Get4(__o, __ao);                  \
 
60
        WRITE(__ap, Put4 (__o, __ao, __a | (0 - ((__a) >> 4))));        \
 
61
    }
 
62
 
 
63
#include "pixman-edge-imp.h"
 
64
 
 
65
#undef AddAlpha
 
66
#undef StepAlpha
 
67
#undef DefineAlpha
 
68
#undef rasterizeEdges
 
69
#undef N_BITS
 
70
 
 
71
 
 
72
/*
 
73
 * 1 bit alpha
 
74
 */
 
75
 
 
76
#define N_BITS 1
 
77
#define rasterizeEdges  fbRasterizeEdges1
 
78
 
 
79
#include "pixman-edge-imp.h"
 
80
 
 
81
#undef rasterizeEdges
 
82
#undef N_BITS
 
83
 
 
84
/*
 
85
 * 8 bit alpha
 
86
 */
 
87
 
 
88
static inline uint8_t
 
89
clip255 (int x)
 
90
{
 
91
    if (x > 255) return 255;
 
92
    return x;
 
93
}
 
94
 
 
95
#define add_saturate_8(buf,val,length)                          \
 
96
    do {                                                        \
 
97
        int i__ = (length);                                     \
 
98
        uint8_t *buf__ = (buf);                                 \
 
99
        int val__ = (val);                                      \
 
100
                                                                \
 
101
        while (i__--)                                           \
 
102
        {                                                       \
 
103
            WRITE((buf__), clip255 (READ((buf__)) + (val__)));  \
 
104
            (buf__)++;                                          \
 
105
        }                                                       \
 
106
    } while (0)
 
107
 
 
108
/*
 
109
 * We want to detect the case where we add the same value to a long
 
110
 * span of pixels.  The triangles on the end are filled in while we
 
111
 * count how many sub-pixel scanlines contribute to the middle section.
 
112
 *
 
113
 *                 +--------------------------+
 
114
 *  fill_height =|   \                      /
 
115
 *                     +------------------+
 
116
 *                      |================|
 
117
 *                   fill_start       fill_end
 
118
 */
 
119
static void
 
120
fbRasterizeEdges8 (pixman_image_t       *image,
 
121
                   pixman_edge_t        *l,
 
122
                   pixman_edge_t        *r,
 
123
                   pixman_fixed_t       t,
 
124
                   pixman_fixed_t       b)
 
125
{
 
126
    pixman_fixed_t  y = t;
 
127
    uint32_t  *line;
 
128
    int fill_start = -1, fill_end = -1;
 
129
    int fill_size = 0;
 
130
    uint32_t *buf = (image)->bits.bits;         
 
131
    int32_t stride = (image)->bits.rowstride;   
 
132
    uint32_t width = (image)->bits.width;
 
133
    
 
134
    line = buf + pixman_fixed_to_int (y) * stride;
 
135
    
 
136
    for (;;)
 
137
    {
 
138
        uint8_t *ap = (uint8_t *) line;
 
139
        pixman_fixed_t  lx, rx;
 
140
        int     lxi, rxi;
 
141
        
 
142
        /* clip X */
 
143
        lx = l->x;
 
144
        if (lx < 0)
 
145
            lx = 0;
 
146
        rx = r->x;
 
147
        if (pixman_fixed_to_int (rx) >= width)
 
148
            rx = pixman_int_to_fixed (width);
 
149
        
 
150
        /* Skip empty (or backwards) sections */
 
151
        if (rx > lx)
 
152
        {
 
153
            int lxs, rxs;
 
154
            
 
155
            /* Find pixel bounds for span. */
 
156
            lxi = pixman_fixed_to_int (lx);
 
157
            rxi = pixman_fixed_to_int (rx);
 
158
            
 
159
            /* Sample coverage for edge pixels */
 
160
            lxs = RenderSamplesX (lx, 8);
 
161
            rxs = RenderSamplesX (rx, 8);
 
162
            
 
163
            /* Add coverage across row */
 
164
            if (lxi == rxi)
 
165
            {
 
166
                WRITE(ap +lxi, clip255 (READ(ap + lxi) + rxs - lxs));
 
167
            }
 
168
            else
 
169
            {
 
170
                WRITE(ap + lxi, clip255 (READ(ap + lxi) + N_X_FRAC(8) - lxs));
 
171
                
 
172
                /* Move forward so that lxi/rxi is the pixel span */
 
173
                lxi++;
 
174
                
 
175
                /* Don't bother trying to optimize the fill unless
 
176
                 * the span is longer than 4 pixels. */
 
177
                if (rxi - lxi > 4)
 
178
                {
 
179
                    if (fill_start < 0)
 
180
                    {
 
181
                        fill_start = lxi;
 
182
                        fill_end = rxi;
 
183
                        fill_size++;
 
184
                    }
 
185
                    else
 
186
                    {
 
187
                        if (lxi >= fill_end || rxi < fill_start)
 
188
                        {
 
189
                            /* We're beyond what we saved, just fill it */
 
190
                            add_saturate_8 (ap + fill_start,
 
191
                                            fill_size * N_X_FRAC(8),
 
192
                                            fill_end - fill_start);
 
193
                            fill_start = lxi;
 
194
                            fill_end = rxi;
 
195
                            fill_size = 1;
 
196
                        }
 
197
                        else
 
198
                        {
 
199
                            /* Update fill_start */
 
200
                            if (lxi > fill_start)
 
201
                            {
 
202
                                add_saturate_8 (ap + fill_start,
 
203
                                                fill_size * N_X_FRAC(8),
 
204
                                                lxi - fill_start);
 
205
                                fill_start = lxi;
 
206
                            }
 
207
                            else if (lxi < fill_start)
 
208
                            {
 
209
                                add_saturate_8 (ap + lxi, N_X_FRAC(8),
 
210
                                                fill_start - lxi);
 
211
                            }
 
212
                            
 
213
                            /* Update fill_end */
 
214
                            if (rxi < fill_end)
 
215
                            {
 
216
                                add_saturate_8 (ap + rxi,
 
217
                                                fill_size * N_X_FRAC(8),
 
218
                                                fill_end - rxi);
 
219
                                fill_end = rxi;
 
220
                            }
 
221
                            else if (fill_end < rxi)
 
222
                            {
 
223
                                add_saturate_8 (ap + fill_end,
 
224
                                                N_X_FRAC(8),
 
225
                                                rxi - fill_end);
 
226
                            }
 
227
                            fill_size++;
 
228
                        }
 
229
                    }
 
230
                }
 
231
                else
 
232
                {
 
233
                    add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi);
 
234
                }
 
235
                
 
236
                /* Do not add in a 0 alpha here. This check is
 
237
                 * necessary to avoid a buffer overrun, (when rx
 
238
                 * is exactly on a pixel boundary). */
 
239
                if (rxs)
 
240
                    WRITE(ap + rxi, clip255 (READ(ap + rxi) + rxs));
 
241
            }
 
242
        }
 
243
        
 
244
        if (y == b) {
 
245
            /* We're done, make sure we clean up any remaining fill. */
 
246
            if (fill_start != fill_end) {
 
247
                if (fill_size == N_Y_FRAC(8))
 
248
                {
 
249
                    MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start);
 
250
                }
 
251
                else
 
252
                {
 
253
                    add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
 
254
                                    fill_end - fill_start);
 
255
                }
 
256
            }
 
257
            break;
 
258
        }
 
259
        
 
260
        if (pixman_fixed_frac (y) != Y_FRAC_LAST(8))
 
261
        {
 
262
            RenderEdgeStepSmall (l);
 
263
            RenderEdgeStepSmall (r);
 
264
            y += STEP_Y_SMALL(8);
 
265
        }
 
266
        else
 
267
        {
 
268
            RenderEdgeStepBig (l);
 
269
            RenderEdgeStepBig (r);
 
270
            y += STEP_Y_BIG(8);
 
271
            if (fill_start != fill_end)
 
272
            {
 
273
                if (fill_size == N_Y_FRAC(8))
 
274
                {
 
275
                    MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start);
 
276
                }
 
277
                else
 
278
                {
 
279
                    add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
 
280
                                    fill_end - fill_start);
 
281
                }
 
282
                fill_start = fill_end = -1;
 
283
                fill_size = 0;
 
284
            }
 
285
            line += stride;
 
286
        }
 
287
    }
 
288
}
 
289
 
 
290
#ifndef PIXMAN_FB_ACCESSORS
 
291
static
 
292
#endif
 
293
void
 
294
PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
 
295
                        pixman_edge_t   *l,
 
296
                        pixman_edge_t   *r,
 
297
                        pixman_fixed_t  t,
 
298
                        pixman_fixed_t  b)
 
299
{
 
300
    switch (PIXMAN_FORMAT_BPP (image->bits.format))
 
301
    {
 
302
    case 1:
 
303
        fbRasterizeEdges1 (image, l, r, t, b);
 
304
        break;
 
305
    case 4:
 
306
        fbRasterizeEdges4 (image, l, r, t, b);
 
307
        break;
 
308
    case 8:
 
309
        fbRasterizeEdges8 (image, l, r, t, b);
 
310
        break;
 
311
    }
 
312
}
 
313
 
 
314
#ifndef PIXMAN_FB_ACCESSORS
 
315
 
 
316
void
 
317
pixman_rasterize_edges (pixman_image_t *image,
 
318
                        pixman_edge_t   *l,
 
319
                        pixman_edge_t   *r,
 
320
                        pixman_fixed_t  t,
 
321
                        pixman_fixed_t  b)
 
322
{
 
323
    if (image->common.read_func || image->common.write_func)
 
324
        pixman_rasterize_edges_accessors (image, l, r, t, b);
 
325
    else
 
326
        pixman_rasterize_edges_no_accessors (image, l, r, t, b);
 
327
}
 
328
 
 
329
#endif