beta-0.89.2
[luatex.git] / source / libs / pixman / pixman-src / pixman / pixman-edge.c
blobad6dfc4cfaf97db27e69210d77344ec7c984a24c
1 /*
2 * Copyright © 2004 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <string.h>
29 #include "pixman-private.h"
30 #include "pixman-accessor.h"
33 * Step across a small sample grid gap
35 #define RENDER_EDGE_STEP_SMALL(edge) \
36 { \
37 edge->x += edge->stepx_small; \
38 edge->e += edge->dx_small; \
39 if (edge->e > 0) \
40 { \
41 edge->e -= edge->dy; \
42 edge->x += edge->signdx; \
43 } \
47 * Step across a large sample grid gap
49 #define RENDER_EDGE_STEP_BIG(edge) \
50 { \
51 edge->x += edge->stepx_big; \
52 edge->e += edge->dx_big; \
53 if (edge->e > 0) \
54 { \
55 edge->e -= edge->dy; \
56 edge->x += edge->signdx; \
57 } \
60 #ifdef PIXMAN_FB_ACCESSORS
61 #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
62 #else
63 #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
64 #endif
67 * 4 bit alpha
70 #define N_BITS 4
71 #define RASTERIZE_EDGES rasterize_edges_4
73 #ifndef WORDS_BIGENDIAN
74 #define SHIFT_4(o) ((o) << 2)
75 #else
76 #define SHIFT_4(o) ((1 - (o)) << 2)
77 #endif
79 #define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf)
80 #define PUT_4(x, o, v) \
81 (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
83 #define DEFINE_ALPHA(line, x) \
84 uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
85 int __ao = (x) & 1
87 #define STEP_ALPHA ((__ap += __ao), (__ao ^= 1))
89 #define ADD_ALPHA(a) \
90 { \
91 uint8_t __o = READ (image, __ap); \
92 uint8_t __a = (a) + GET_4 (__o, __ao); \
93 WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
96 #include "pixman-edge-imp.h"
98 #undef ADD_ALPHA
99 #undef STEP_ALPHA
100 #undef DEFINE_ALPHA
101 #undef RASTERIZE_EDGES
102 #undef N_BITS
106 * 1 bit alpha
109 #define N_BITS 1
110 #define RASTERIZE_EDGES rasterize_edges_1
112 #include "pixman-edge-imp.h"
114 #undef RASTERIZE_EDGES
115 #undef N_BITS
118 * 8 bit alpha
121 static force_inline uint8_t
122 clip255 (int x)
124 if (x > 255)
125 return 255;
127 return x;
130 #define ADD_SATURATE_8(buf, val, length) \
131 do \
133 int i__ = (length); \
134 uint8_t *buf__ = (buf); \
135 int val__ = (val); \
137 while (i__--) \
139 WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
140 (buf__)++; \
142 } while (0)
145 * We want to detect the case where we add the same value to a long
146 * span of pixels. The triangles on the end are filled in while we
147 * count how many sub-pixel scanlines contribute to the middle section.
149 * +--------------------------+
150 * fill_height =| \ /
151 * +------------------+
152 * |================|
153 * fill_start fill_end
155 static void
156 rasterize_edges_8 (pixman_image_t *image,
157 pixman_edge_t * l,
158 pixman_edge_t * r,
159 pixman_fixed_t t,
160 pixman_fixed_t b)
162 pixman_fixed_t y = t;
163 uint32_t *line;
164 int fill_start = -1, fill_end = -1;
165 int fill_size = 0;
166 uint32_t *buf = (image)->bits.bits;
167 int stride = (image)->bits.rowstride;
168 int width = (image)->bits.width;
170 line = buf + pixman_fixed_to_int (y) * stride;
172 for (;;)
174 uint8_t *ap = (uint8_t *) line;
175 pixman_fixed_t lx, rx;
176 int lxi, rxi;
178 /* clip X */
179 lx = l->x;
180 if (lx < 0)
181 lx = 0;
183 rx = r->x;
185 if (pixman_fixed_to_int (rx) >= width)
187 /* Use the last pixel of the scanline, covered 100%.
188 * We can't use the first pixel following the scanline,
189 * because accessing it could result in a buffer overrun.
191 rx = pixman_int_to_fixed (width) - 1;
194 /* Skip empty (or backwards) sections */
195 if (rx > lx)
197 int lxs, rxs;
199 /* Find pixel bounds for span. */
200 lxi = pixman_fixed_to_int (lx);
201 rxi = pixman_fixed_to_int (rx);
203 /* Sample coverage for edge pixels */
204 lxs = RENDER_SAMPLES_X (lx, 8);
205 rxs = RENDER_SAMPLES_X (rx, 8);
207 /* Add coverage across row */
208 if (lxi == rxi)
210 WRITE (image, ap + lxi,
211 clip255 (READ (image, ap + lxi) + rxs - lxs));
213 else
215 WRITE (image, ap + lxi,
216 clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
218 /* Move forward so that lxi/rxi is the pixel span */
219 lxi++;
221 /* Don't bother trying to optimize the fill unless
222 * the span is longer than 4 pixels. */
223 if (rxi - lxi > 4)
225 if (fill_start < 0)
227 fill_start = lxi;
228 fill_end = rxi;
229 fill_size++;
231 else
233 if (lxi >= fill_end || rxi < fill_start)
235 /* We're beyond what we saved, just fill it */
236 ADD_SATURATE_8 (ap + fill_start,
237 fill_size * N_X_FRAC (8),
238 fill_end - fill_start);
239 fill_start = lxi;
240 fill_end = rxi;
241 fill_size = 1;
243 else
245 /* Update fill_start */
246 if (lxi > fill_start)
248 ADD_SATURATE_8 (ap + fill_start,
249 fill_size * N_X_FRAC (8),
250 lxi - fill_start);
251 fill_start = lxi;
253 else if (lxi < fill_start)
255 ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
256 fill_start - lxi);
259 /* Update fill_end */
260 if (rxi < fill_end)
262 ADD_SATURATE_8 (ap + rxi,
263 fill_size * N_X_FRAC (8),
264 fill_end - rxi);
265 fill_end = rxi;
267 else if (fill_end < rxi)
269 ADD_SATURATE_8 (ap + fill_end,
270 N_X_FRAC (8),
271 rxi - fill_end);
273 fill_size++;
277 else
279 ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
282 WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
286 if (y == b)
288 /* We're done, make sure we clean up any remaining fill. */
289 if (fill_start != fill_end)
291 if (fill_size == N_Y_FRAC (8))
293 MEMSET_WRAPPED (image, ap + fill_start,
294 0xff, fill_end - fill_start);
296 else
298 ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
299 fill_end - fill_start);
302 break;
305 if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
307 RENDER_EDGE_STEP_SMALL (l);
308 RENDER_EDGE_STEP_SMALL (r);
309 y += STEP_Y_SMALL (8);
311 else
313 RENDER_EDGE_STEP_BIG (l);
314 RENDER_EDGE_STEP_BIG (r);
315 y += STEP_Y_BIG (8);
316 if (fill_start != fill_end)
318 if (fill_size == N_Y_FRAC (8))
320 MEMSET_WRAPPED (image, ap + fill_start,
321 0xff, fill_end - fill_start);
323 else
325 ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
326 fill_end - fill_start);
329 fill_start = fill_end = -1;
330 fill_size = 0;
333 line += stride;
338 #ifndef PIXMAN_FB_ACCESSORS
339 static
340 #endif
341 void
342 PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
343 pixman_edge_t * l,
344 pixman_edge_t * r,
345 pixman_fixed_t t,
346 pixman_fixed_t b)
348 switch (PIXMAN_FORMAT_BPP (image->bits.format))
350 case 1:
351 rasterize_edges_1 (image, l, r, t, b);
352 break;
354 case 4:
355 rasterize_edges_4 (image, l, r, t, b);
356 break;
358 case 8:
359 rasterize_edges_8 (image, l, r, t, b);
360 break;
362 default:
363 break;
367 #ifndef PIXMAN_FB_ACCESSORS
369 PIXMAN_EXPORT void
370 pixman_rasterize_edges (pixman_image_t *image,
371 pixman_edge_t * l,
372 pixman_edge_t * r,
373 pixman_fixed_t t,
374 pixman_fixed_t b)
376 return_if_fail (image->type == BITS);
377 return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
379 if (image->bits.read_func || image->bits.write_func)
380 pixman_rasterize_edges_accessors (image, l, r, t, b);
381 else
382 pixman_rasterize_edges_no_accessors (image, l, r, t, b);
385 #endif