4
* Copyright © 2004 Keith Packard
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.
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.
27
#include "pixman-private.h"
29
#ifdef PIXMAN_FB_ACCESSORS
30
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
32
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
40
#define rasterizeEdges fbRasterizeEdges4
42
#if BITMAP_BIT_ORDER == LSBFirst
43
#define Shift4(o) ((o) << 2)
45
#define Shift4(o) ((1-(o)) << 2)
48
#define Get4(x,o) (((x) >> Shift4(o)) & 0xf)
49
#define Put4(x,o,v) (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
51
#define DefineAlpha(line,x) \
52
uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
55
#define StepAlpha ((__ap += __ao), (__ao ^= 1))
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)))); \
63
#include "pixman-edge-imp.h"
77
#define rasterizeEdges fbRasterizeEdges1
79
#include "pixman-edge-imp.h"
91
if (x > 255) return 255;
95
#define add_saturate_8(buf,val,length) \
98
uint8_t *buf__ = (buf); \
103
WRITE((buf__), clip255 (READ((buf__)) + (val__))); \
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.
113
* +--------------------------+
115
* +------------------+
117
* fill_start fill_end
120
fbRasterizeEdges8 (pixman_image_t *image,
126
pixman_fixed_t y = t;
128
int fill_start = -1, fill_end = -1;
130
uint32_t *buf = (image)->bits.bits;
131
int32_t stride = (image)->bits.rowstride;
132
uint32_t width = (image)->bits.width;
134
line = buf + pixman_fixed_to_int (y) * stride;
138
uint8_t *ap = (uint8_t *) line;
139
pixman_fixed_t lx, rx;
147
if (pixman_fixed_to_int (rx) >= width)
148
rx = pixman_int_to_fixed (width);
150
/* Skip empty (or backwards) sections */
155
/* Find pixel bounds for span. */
156
lxi = pixman_fixed_to_int (lx);
157
rxi = pixman_fixed_to_int (rx);
159
/* Sample coverage for edge pixels */
160
lxs = RenderSamplesX (lx, 8);
161
rxs = RenderSamplesX (rx, 8);
163
/* Add coverage across row */
166
WRITE(ap +lxi, clip255 (READ(ap + lxi) + rxs - lxs));
170
WRITE(ap + lxi, clip255 (READ(ap + lxi) + N_X_FRAC(8) - lxs));
172
/* Move forward so that lxi/rxi is the pixel span */
175
/* Don't bother trying to optimize the fill unless
176
* the span is longer than 4 pixels. */
187
if (lxi >= fill_end || rxi < fill_start)
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);
199
/* Update fill_start */
200
if (lxi > fill_start)
202
add_saturate_8 (ap + fill_start,
203
fill_size * N_X_FRAC(8),
207
else if (lxi < fill_start)
209
add_saturate_8 (ap + lxi, N_X_FRAC(8),
213
/* Update fill_end */
216
add_saturate_8 (ap + rxi,
217
fill_size * N_X_FRAC(8),
221
else if (fill_end < rxi)
223
add_saturate_8 (ap + fill_end,
233
add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi);
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). */
240
WRITE(ap + rxi, clip255 (READ(ap + rxi) + rxs));
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))
249
MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start);
253
add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
254
fill_end - fill_start);
260
if (pixman_fixed_frac (y) != Y_FRAC_LAST(8))
262
RenderEdgeStepSmall (l);
263
RenderEdgeStepSmall (r);
264
y += STEP_Y_SMALL(8);
268
RenderEdgeStepBig (l);
269
RenderEdgeStepBig (r);
271
if (fill_start != fill_end)
273
if (fill_size == N_Y_FRAC(8))
275
MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start);
279
add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
280
fill_end - fill_start);
282
fill_start = fill_end = -1;
290
#ifndef PIXMAN_FB_ACCESSORS
294
PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
300
switch (PIXMAN_FORMAT_BPP (image->bits.format))
303
fbRasterizeEdges1 (image, l, r, t, b);
306
fbRasterizeEdges4 (image, l, r, t, b);
309
fbRasterizeEdges8 (image, l, r, t, b);
314
#ifndef PIXMAN_FB_ACCESSORS
317
pixman_rasterize_edges (pixman_image_t *image,
323
if (image->common.read_func || image->common.write_func)
324
pixman_rasterize_edges_accessors (image, l, r, t, b);
326
pixman_rasterize_edges_no_accessors (image, l, r, t, b);