1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-edge.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,385 @@ 1.4 +/* 1.5 + * Copyright © 2004 Keith Packard 1.6 + * 1.7 + * Permission to use, copy, modify, distribute, and sell this software and its 1.8 + * documentation for any purpose is hereby granted without fee, provided that 1.9 + * the above copyright notice appear in all copies and that both that 1.10 + * copyright notice and this permission notice appear in supporting 1.11 + * documentation, and that the name of Keith Packard not be used in 1.12 + * advertising or publicity pertaining to distribution of the software without 1.13 + * specific, written prior permission. Keith Packard makes no 1.14 + * representations about the suitability of this software for any purpose. It 1.15 + * is provided "as is" without express or implied warranty. 1.16 + * 1.17 + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1.18 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1.19 + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1.20 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1.21 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1.22 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1.23 + * PERFORMANCE OF THIS SOFTWARE. 1.24 + */ 1.25 + 1.26 +#ifdef HAVE_CONFIG_H 1.27 +#include <config.h> 1.28 +#endif 1.29 + 1.30 +#include <string.h> 1.31 + 1.32 +#include "pixman-private.h" 1.33 +#include "pixman-accessor.h" 1.34 + 1.35 +/* 1.36 + * Step across a small sample grid gap 1.37 + */ 1.38 +#define RENDER_EDGE_STEP_SMALL(edge) \ 1.39 + { \ 1.40 + edge->x += edge->stepx_small; \ 1.41 + edge->e += edge->dx_small; \ 1.42 + if (edge->e > 0) \ 1.43 + { \ 1.44 + edge->e -= edge->dy; \ 1.45 + edge->x += edge->signdx; \ 1.46 + } \ 1.47 + } 1.48 + 1.49 +/* 1.50 + * Step across a large sample grid gap 1.51 + */ 1.52 +#define RENDER_EDGE_STEP_BIG(edge) \ 1.53 + { \ 1.54 + edge->x += edge->stepx_big; \ 1.55 + edge->e += edge->dx_big; \ 1.56 + if (edge->e > 0) \ 1.57 + { \ 1.58 + edge->e -= edge->dy; \ 1.59 + edge->x += edge->signdx; \ 1.60 + } \ 1.61 + } 1.62 + 1.63 +#ifdef PIXMAN_FB_ACCESSORS 1.64 +#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors 1.65 +#else 1.66 +#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors 1.67 +#endif 1.68 + 1.69 +/* 1.70 + * 4 bit alpha 1.71 + */ 1.72 + 1.73 +#define N_BITS 4 1.74 +#define RASTERIZE_EDGES rasterize_edges_4 1.75 + 1.76 +#ifndef WORDS_BIGENDIAN 1.77 +#define SHIFT_4(o) ((o) << 2) 1.78 +#else 1.79 +#define SHIFT_4(o) ((1 - (o)) << 2) 1.80 +#endif 1.81 + 1.82 +#define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf) 1.83 +#define PUT_4(x, o, v) \ 1.84 + (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o))) 1.85 + 1.86 +#define DEFINE_ALPHA(line, x) \ 1.87 + uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \ 1.88 + int __ao = (x) & 1 1.89 + 1.90 +#define STEP_ALPHA ((__ap += __ao), (__ao ^= 1)) 1.91 + 1.92 +#define ADD_ALPHA(a) \ 1.93 + { \ 1.94 + uint8_t __o = READ (image, __ap); \ 1.95 + uint8_t __a = (a) + GET_4 (__o, __ao); \ 1.96 + WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \ 1.97 + } 1.98 + 1.99 +#include "pixman-edge-imp.h" 1.100 + 1.101 +#undef ADD_ALPHA 1.102 +#undef STEP_ALPHA 1.103 +#undef DEFINE_ALPHA 1.104 +#undef RASTERIZE_EDGES 1.105 +#undef N_BITS 1.106 + 1.107 + 1.108 +/* 1.109 + * 1 bit alpha 1.110 + */ 1.111 + 1.112 +#define N_BITS 1 1.113 +#define RASTERIZE_EDGES rasterize_edges_1 1.114 + 1.115 +#include "pixman-edge-imp.h" 1.116 + 1.117 +#undef RASTERIZE_EDGES 1.118 +#undef N_BITS 1.119 + 1.120 +/* 1.121 + * 8 bit alpha 1.122 + */ 1.123 + 1.124 +static force_inline uint8_t 1.125 +clip255 (int x) 1.126 +{ 1.127 + if (x > 255) 1.128 + return 255; 1.129 + 1.130 + return x; 1.131 +} 1.132 + 1.133 +#define ADD_SATURATE_8(buf, val, length) \ 1.134 + do \ 1.135 + { \ 1.136 + int i__ = (length); \ 1.137 + uint8_t *buf__ = (buf); \ 1.138 + int val__ = (val); \ 1.139 + \ 1.140 + while (i__--) \ 1.141 + { \ 1.142 + WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \ 1.143 + (buf__)++; \ 1.144 + } \ 1.145 + } while (0) 1.146 + 1.147 +/* 1.148 + * We want to detect the case where we add the same value to a long 1.149 + * span of pixels. The triangles on the end are filled in while we 1.150 + * count how many sub-pixel scanlines contribute to the middle section. 1.151 + * 1.152 + * +--------------------------+ 1.153 + * fill_height =| \ / 1.154 + * +------------------+ 1.155 + * |================| 1.156 + * fill_start fill_end 1.157 + */ 1.158 +static void 1.159 +rasterize_edges_8 (pixman_image_t *image, 1.160 + pixman_edge_t * l, 1.161 + pixman_edge_t * r, 1.162 + pixman_fixed_t t, 1.163 + pixman_fixed_t b) 1.164 +{ 1.165 + pixman_fixed_t y = t; 1.166 + uint32_t *line; 1.167 + int fill_start = -1, fill_end = -1; 1.168 + int fill_size = 0; 1.169 + uint32_t *buf = (image)->bits.bits; 1.170 + int stride = (image)->bits.rowstride; 1.171 + int width = (image)->bits.width; 1.172 + 1.173 + line = buf + pixman_fixed_to_int (y) * stride; 1.174 + 1.175 + for (;;) 1.176 + { 1.177 + uint8_t *ap = (uint8_t *) line; 1.178 + pixman_fixed_t lx, rx; 1.179 + int lxi, rxi; 1.180 + 1.181 + /* clip X */ 1.182 + lx = l->x; 1.183 + if (lx < 0) 1.184 + lx = 0; 1.185 + 1.186 + rx = r->x; 1.187 + 1.188 + if (pixman_fixed_to_int (rx) >= width) 1.189 + { 1.190 + /* Use the last pixel of the scanline, covered 100%. 1.191 + * We can't use the first pixel following the scanline, 1.192 + * because accessing it could result in a buffer overrun. 1.193 + */ 1.194 + rx = pixman_int_to_fixed (width) - 1; 1.195 + } 1.196 + 1.197 + /* Skip empty (or backwards) sections */ 1.198 + if (rx > lx) 1.199 + { 1.200 + int lxs, rxs; 1.201 + 1.202 + /* Find pixel bounds for span. */ 1.203 + lxi = pixman_fixed_to_int (lx); 1.204 + rxi = pixman_fixed_to_int (rx); 1.205 + 1.206 + /* Sample coverage for edge pixels */ 1.207 + lxs = RENDER_SAMPLES_X (lx, 8); 1.208 + rxs = RENDER_SAMPLES_X (rx, 8); 1.209 + 1.210 + /* Add coverage across row */ 1.211 + if (lxi == rxi) 1.212 + { 1.213 + WRITE (image, ap + lxi, 1.214 + clip255 (READ (image, ap + lxi) + rxs - lxs)); 1.215 + } 1.216 + else 1.217 + { 1.218 + WRITE (image, ap + lxi, 1.219 + clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs)); 1.220 + 1.221 + /* Move forward so that lxi/rxi is the pixel span */ 1.222 + lxi++; 1.223 + 1.224 + /* Don't bother trying to optimize the fill unless 1.225 + * the span is longer than 4 pixels. */ 1.226 + if (rxi - lxi > 4) 1.227 + { 1.228 + if (fill_start < 0) 1.229 + { 1.230 + fill_start = lxi; 1.231 + fill_end = rxi; 1.232 + fill_size++; 1.233 + } 1.234 + else 1.235 + { 1.236 + if (lxi >= fill_end || rxi < fill_start) 1.237 + { 1.238 + /* We're beyond what we saved, just fill it */ 1.239 + ADD_SATURATE_8 (ap + fill_start, 1.240 + fill_size * N_X_FRAC (8), 1.241 + fill_end - fill_start); 1.242 + fill_start = lxi; 1.243 + fill_end = rxi; 1.244 + fill_size = 1; 1.245 + } 1.246 + else 1.247 + { 1.248 + /* Update fill_start */ 1.249 + if (lxi > fill_start) 1.250 + { 1.251 + ADD_SATURATE_8 (ap + fill_start, 1.252 + fill_size * N_X_FRAC (8), 1.253 + lxi - fill_start); 1.254 + fill_start = lxi; 1.255 + } 1.256 + else if (lxi < fill_start) 1.257 + { 1.258 + ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), 1.259 + fill_start - lxi); 1.260 + } 1.261 + 1.262 + /* Update fill_end */ 1.263 + if (rxi < fill_end) 1.264 + { 1.265 + ADD_SATURATE_8 (ap + rxi, 1.266 + fill_size * N_X_FRAC (8), 1.267 + fill_end - rxi); 1.268 + fill_end = rxi; 1.269 + } 1.270 + else if (fill_end < rxi) 1.271 + { 1.272 + ADD_SATURATE_8 (ap + fill_end, 1.273 + N_X_FRAC (8), 1.274 + rxi - fill_end); 1.275 + } 1.276 + fill_size++; 1.277 + } 1.278 + } 1.279 + } 1.280 + else 1.281 + { 1.282 + ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi); 1.283 + } 1.284 + 1.285 + WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs)); 1.286 + } 1.287 + } 1.288 + 1.289 + if (y == b) 1.290 + { 1.291 + /* We're done, make sure we clean up any remaining fill. */ 1.292 + if (fill_start != fill_end) 1.293 + { 1.294 + if (fill_size == N_Y_FRAC (8)) 1.295 + { 1.296 + MEMSET_WRAPPED (image, ap + fill_start, 1.297 + 0xff, fill_end - fill_start); 1.298 + } 1.299 + else 1.300 + { 1.301 + ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8), 1.302 + fill_end - fill_start); 1.303 + } 1.304 + } 1.305 + break; 1.306 + } 1.307 + 1.308 + if (pixman_fixed_frac (y) != Y_FRAC_LAST (8)) 1.309 + { 1.310 + RENDER_EDGE_STEP_SMALL (l); 1.311 + RENDER_EDGE_STEP_SMALL (r); 1.312 + y += STEP_Y_SMALL (8); 1.313 + } 1.314 + else 1.315 + { 1.316 + RENDER_EDGE_STEP_BIG (l); 1.317 + RENDER_EDGE_STEP_BIG (r); 1.318 + y += STEP_Y_BIG (8); 1.319 + if (fill_start != fill_end) 1.320 + { 1.321 + if (fill_size == N_Y_FRAC (8)) 1.322 + { 1.323 + MEMSET_WRAPPED (image, ap + fill_start, 1.324 + 0xff, fill_end - fill_start); 1.325 + } 1.326 + else 1.327 + { 1.328 + ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8), 1.329 + fill_end - fill_start); 1.330 + } 1.331 + 1.332 + fill_start = fill_end = -1; 1.333 + fill_size = 0; 1.334 + } 1.335 + 1.336 + line += stride; 1.337 + } 1.338 + } 1.339 +} 1.340 + 1.341 +#ifndef PIXMAN_FB_ACCESSORS 1.342 +static 1.343 +#endif 1.344 +void 1.345 +PIXMAN_RASTERIZE_EDGES (pixman_image_t *image, 1.346 + pixman_edge_t * l, 1.347 + pixman_edge_t * r, 1.348 + pixman_fixed_t t, 1.349 + pixman_fixed_t b) 1.350 +{ 1.351 + switch (PIXMAN_FORMAT_BPP (image->bits.format)) 1.352 + { 1.353 + case 1: 1.354 + rasterize_edges_1 (image, l, r, t, b); 1.355 + break; 1.356 + 1.357 + case 4: 1.358 + rasterize_edges_4 (image, l, r, t, b); 1.359 + break; 1.360 + 1.361 + case 8: 1.362 + rasterize_edges_8 (image, l, r, t, b); 1.363 + break; 1.364 + 1.365 + default: 1.366 + break; 1.367 + } 1.368 +} 1.369 + 1.370 +#ifndef PIXMAN_FB_ACCESSORS 1.371 + 1.372 +PIXMAN_EXPORT void 1.373 +pixman_rasterize_edges (pixman_image_t *image, 1.374 + pixman_edge_t * l, 1.375 + pixman_edge_t * r, 1.376 + pixman_fixed_t t, 1.377 + pixman_fixed_t b) 1.378 +{ 1.379 + return_if_fail (image->type == BITS); 1.380 + return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A); 1.381 + 1.382 + if (image->bits.read_func || image->bits.write_func) 1.383 + pixman_rasterize_edges_accessors (image, l, r, t, b); 1.384 + else 1.385 + pixman_rasterize_edges_no_accessors (image, l, r, t, b); 1.386 +} 1.387 + 1.388 +#endif