1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-bits-image.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1849 @@ 1.4 +/* 1.5 + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 1.6 + * 2005 Lars Knoll & Zack Rusin, Trolltech 1.7 + * 2008 Aaron Plattner, NVIDIA Corporation 1.8 + * Copyright © 2000 SuSE, Inc. 1.9 + * Copyright © 2007, 2009 Red Hat, Inc. 1.10 + * Copyright © 2008 André Tupinambá <andrelrt@gmail.com> 1.11 + * 1.12 + * Permission to use, copy, modify, distribute, and sell this software and its 1.13 + * documentation for any purpose is hereby granted without fee, provided that 1.14 + * the above copyright notice appear in all copies and that both that 1.15 + * copyright notice and this permission notice appear in supporting 1.16 + * documentation, and that the name of Keith Packard not be used in 1.17 + * advertising or publicity pertaining to distribution of the software without 1.18 + * specific, written prior permission. Keith Packard makes no 1.19 + * representations about the suitability of this software for any purpose. It 1.20 + * is provided "as is" without express or implied warranty. 1.21 + * 1.22 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 1.23 + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.24 + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 1.25 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.26 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 1.27 + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 1.28 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1.29 + * SOFTWARE. 1.30 + */ 1.31 + 1.32 +#ifdef HAVE_CONFIG_H 1.33 +#include <config.h> 1.34 +#endif 1.35 +#include <stdio.h> 1.36 +#include <stdlib.h> 1.37 +#include <string.h> 1.38 +#include "pixman-private.h" 1.39 +#include "pixman-combine32.h" 1.40 +#include "pixman-inlines.h" 1.41 + 1.42 +static uint32_t * 1.43 +_pixman_image_get_scanline_generic_float (pixman_iter_t * iter, 1.44 + const uint32_t *mask) 1.45 +{ 1.46 + pixman_iter_get_scanline_t fetch_32 = iter->data; 1.47 + uint32_t *buffer = iter->buffer; 1.48 + 1.49 + fetch_32 (iter, NULL); 1.50 + 1.51 + pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); 1.52 + 1.53 + return iter->buffer; 1.54 +} 1.55 + 1.56 +/* Fetch functions */ 1.57 + 1.58 +static force_inline uint32_t 1.59 +fetch_pixel_no_alpha (bits_image_t *image, 1.60 + int x, int y, pixman_bool_t check_bounds) 1.61 +{ 1.62 + if (check_bounds && 1.63 + (x < 0 || x >= image->width || y < 0 || y >= image->height)) 1.64 + { 1.65 + return 0; 1.66 + } 1.67 + 1.68 + return image->fetch_pixel_32 (image, x, y); 1.69 +} 1.70 + 1.71 +typedef uint32_t (* get_pixel_t) (bits_image_t *image, 1.72 + int x, int y, pixman_bool_t check_bounds); 1.73 + 1.74 +static force_inline uint32_t 1.75 +bits_image_fetch_pixel_nearest (bits_image_t *image, 1.76 + pixman_fixed_t x, 1.77 + pixman_fixed_t y, 1.78 + get_pixel_t get_pixel) 1.79 +{ 1.80 + int x0 = pixman_fixed_to_int (x - pixman_fixed_e); 1.81 + int y0 = pixman_fixed_to_int (y - pixman_fixed_e); 1.82 + 1.83 + if (image->common.repeat != PIXMAN_REPEAT_NONE) 1.84 + { 1.85 + repeat (image->common.repeat, &x0, image->width); 1.86 + repeat (image->common.repeat, &y0, image->height); 1.87 + 1.88 + return get_pixel (image, x0, y0, FALSE); 1.89 + } 1.90 + else 1.91 + { 1.92 + return get_pixel (image, x0, y0, TRUE); 1.93 + } 1.94 +} 1.95 + 1.96 +static force_inline uint32_t 1.97 +bits_image_fetch_pixel_bilinear (bits_image_t *image, 1.98 + pixman_fixed_t x, 1.99 + pixman_fixed_t y, 1.100 + get_pixel_t get_pixel) 1.101 +{ 1.102 + pixman_repeat_t repeat_mode = image->common.repeat; 1.103 + int width = image->width; 1.104 + int height = image->height; 1.105 + int x1, y1, x2, y2; 1.106 + uint32_t tl, tr, bl, br; 1.107 + int32_t distx, disty; 1.108 + 1.109 + x1 = x - pixman_fixed_1 / 2; 1.110 + y1 = y - pixman_fixed_1 / 2; 1.111 + 1.112 + distx = pixman_fixed_to_bilinear_weight (x1); 1.113 + disty = pixman_fixed_to_bilinear_weight (y1); 1.114 + 1.115 + x1 = pixman_fixed_to_int (x1); 1.116 + y1 = pixman_fixed_to_int (y1); 1.117 + x2 = x1 + 1; 1.118 + y2 = y1 + 1; 1.119 + 1.120 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.121 + { 1.122 + repeat (repeat_mode, &x1, width); 1.123 + repeat (repeat_mode, &y1, height); 1.124 + repeat (repeat_mode, &x2, width); 1.125 + repeat (repeat_mode, &y2, height); 1.126 + 1.127 + tl = get_pixel (image, x1, y1, FALSE); 1.128 + bl = get_pixel (image, x1, y2, FALSE); 1.129 + tr = get_pixel (image, x2, y1, FALSE); 1.130 + br = get_pixel (image, x2, y2, FALSE); 1.131 + } 1.132 + else 1.133 + { 1.134 + tl = get_pixel (image, x1, y1, TRUE); 1.135 + tr = get_pixel (image, x2, y1, TRUE); 1.136 + bl = get_pixel (image, x1, y2, TRUE); 1.137 + br = get_pixel (image, x2, y2, TRUE); 1.138 + } 1.139 + 1.140 + return bilinear_interpolation (tl, tr, bl, br, distx, disty); 1.141 +} 1.142 + 1.143 +static uint32_t * 1.144 +bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter, 1.145 + const uint32_t *mask) 1.146 +{ 1.147 + 1.148 + pixman_image_t * ima = iter->image; 1.149 + int offset = iter->x; 1.150 + int line = iter->y++; 1.151 + int width = iter->width; 1.152 + uint32_t * buffer = iter->buffer; 1.153 + 1.154 + bits_image_t *bits = &ima->bits; 1.155 + pixman_fixed_t x_top, x_bottom, x; 1.156 + pixman_fixed_t ux_top, ux_bottom, ux; 1.157 + pixman_vector_t v; 1.158 + uint32_t top_mask, bottom_mask; 1.159 + uint32_t *top_row; 1.160 + uint32_t *bottom_row; 1.161 + uint32_t *end; 1.162 + uint32_t zero[2] = { 0, 0 }; 1.163 + uint32_t one = 1; 1.164 + int y, y1, y2; 1.165 + int disty; 1.166 + int mask_inc; 1.167 + int w; 1.168 + 1.169 + /* reference point is the center of the pixel */ 1.170 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1.171 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1.172 + v.vector[2] = pixman_fixed_1; 1.173 + 1.174 + if (!pixman_transform_point_3d (bits->common.transform, &v)) 1.175 + return iter->buffer; 1.176 + 1.177 + ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0]; 1.178 + x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2; 1.179 + 1.180 + y = v.vector[1] - pixman_fixed_1/2; 1.181 + disty = pixman_fixed_to_bilinear_weight (y); 1.182 + 1.183 + /* Load the pointers to the first and second lines from the source 1.184 + * image that bilinear code must read. 1.185 + * 1.186 + * The main trick in this code is about the check if any line are 1.187 + * outside of the image; 1.188 + * 1.189 + * When I realize that a line (any one) is outside, I change 1.190 + * the pointer to a dummy area with zeros. Once I change this, I 1.191 + * must be sure the pointer will not change, so I set the 1.192 + * variables to each pointer increments inside the loop. 1.193 + */ 1.194 + y1 = pixman_fixed_to_int (y); 1.195 + y2 = y1 + 1; 1.196 + 1.197 + if (y1 < 0 || y1 >= bits->height) 1.198 + { 1.199 + top_row = zero; 1.200 + x_top = 0; 1.201 + ux_top = 0; 1.202 + } 1.203 + else 1.204 + { 1.205 + top_row = bits->bits + y1 * bits->rowstride; 1.206 + x_top = x; 1.207 + ux_top = ux; 1.208 + } 1.209 + 1.210 + if (y2 < 0 || y2 >= bits->height) 1.211 + { 1.212 + bottom_row = zero; 1.213 + x_bottom = 0; 1.214 + ux_bottom = 0; 1.215 + } 1.216 + else 1.217 + { 1.218 + bottom_row = bits->bits + y2 * bits->rowstride; 1.219 + x_bottom = x; 1.220 + ux_bottom = ux; 1.221 + } 1.222 + 1.223 + /* Instead of checking whether the operation uses the mast in 1.224 + * each loop iteration, verify this only once and prepare the 1.225 + * variables to make the code smaller inside the loop. 1.226 + */ 1.227 + if (!mask) 1.228 + { 1.229 + mask_inc = 0; 1.230 + mask = &one; 1.231 + } 1.232 + else 1.233 + { 1.234 + /* If have a mask, prepare the variables to check it */ 1.235 + mask_inc = 1; 1.236 + } 1.237 + 1.238 + /* If both are zero, then the whole thing is zero */ 1.239 + if (top_row == zero && bottom_row == zero) 1.240 + { 1.241 + memset (buffer, 0, width * sizeof (uint32_t)); 1.242 + return iter->buffer; 1.243 + } 1.244 + else if (bits->format == PIXMAN_x8r8g8b8) 1.245 + { 1.246 + if (top_row == zero) 1.247 + { 1.248 + top_mask = 0; 1.249 + bottom_mask = 0xff000000; 1.250 + } 1.251 + else if (bottom_row == zero) 1.252 + { 1.253 + top_mask = 0xff000000; 1.254 + bottom_mask = 0; 1.255 + } 1.256 + else 1.257 + { 1.258 + top_mask = 0xff000000; 1.259 + bottom_mask = 0xff000000; 1.260 + } 1.261 + } 1.262 + else 1.263 + { 1.264 + top_mask = 0; 1.265 + bottom_mask = 0; 1.266 + } 1.267 + 1.268 + end = buffer + width; 1.269 + 1.270 + /* Zero fill to the left of the image */ 1.271 + while (buffer < end && x < pixman_fixed_minus_1) 1.272 + { 1.273 + *buffer++ = 0; 1.274 + x += ux; 1.275 + x_top += ux_top; 1.276 + x_bottom += ux_bottom; 1.277 + mask += mask_inc; 1.278 + } 1.279 + 1.280 + /* Left edge 1.281 + */ 1.282 + while (buffer < end && x < 0) 1.283 + { 1.284 + uint32_t tr, br; 1.285 + int32_t distx; 1.286 + 1.287 + tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask; 1.288 + br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; 1.289 + 1.290 + distx = pixman_fixed_to_bilinear_weight (x); 1.291 + 1.292 + *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty); 1.293 + 1.294 + x += ux; 1.295 + x_top += ux_top; 1.296 + x_bottom += ux_bottom; 1.297 + mask += mask_inc; 1.298 + } 1.299 + 1.300 + /* Main part */ 1.301 + w = pixman_int_to_fixed (bits->width - 1); 1.302 + 1.303 + while (buffer < end && x < w) 1.304 + { 1.305 + if (*mask) 1.306 + { 1.307 + uint32_t tl, tr, bl, br; 1.308 + int32_t distx; 1.309 + 1.310 + tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; 1.311 + tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask; 1.312 + bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; 1.313 + br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; 1.314 + 1.315 + distx = pixman_fixed_to_bilinear_weight (x); 1.316 + 1.317 + *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty); 1.318 + } 1.319 + 1.320 + buffer++; 1.321 + x += ux; 1.322 + x_top += ux_top; 1.323 + x_bottom += ux_bottom; 1.324 + mask += mask_inc; 1.325 + } 1.326 + 1.327 + /* Right Edge */ 1.328 + w = pixman_int_to_fixed (bits->width); 1.329 + while (buffer < end && x < w) 1.330 + { 1.331 + if (*mask) 1.332 + { 1.333 + uint32_t tl, bl; 1.334 + int32_t distx; 1.335 + 1.336 + tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; 1.337 + bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; 1.338 + 1.339 + distx = pixman_fixed_to_bilinear_weight (x); 1.340 + 1.341 + *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty); 1.342 + } 1.343 + 1.344 + buffer++; 1.345 + x += ux; 1.346 + x_top += ux_top; 1.347 + x_bottom += ux_bottom; 1.348 + mask += mask_inc; 1.349 + } 1.350 + 1.351 + /* Zero fill to the left of the image */ 1.352 + while (buffer < end) 1.353 + *buffer++ = 0; 1.354 + 1.355 + return iter->buffer; 1.356 +} 1.357 + 1.358 +static force_inline uint32_t 1.359 +bits_image_fetch_pixel_convolution (bits_image_t *image, 1.360 + pixman_fixed_t x, 1.361 + pixman_fixed_t y, 1.362 + get_pixel_t get_pixel) 1.363 +{ 1.364 + pixman_fixed_t *params = image->common.filter_params; 1.365 + int x_off = (params[0] - pixman_fixed_1) >> 1; 1.366 + int y_off = (params[1] - pixman_fixed_1) >> 1; 1.367 + int32_t cwidth = pixman_fixed_to_int (params[0]); 1.368 + int32_t cheight = pixman_fixed_to_int (params[1]); 1.369 + int32_t i, j, x1, x2, y1, y2; 1.370 + pixman_repeat_t repeat_mode = image->common.repeat; 1.371 + int width = image->width; 1.372 + int height = image->height; 1.373 + int srtot, sgtot, sbtot, satot; 1.374 + 1.375 + params += 2; 1.376 + 1.377 + x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); 1.378 + y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); 1.379 + x2 = x1 + cwidth; 1.380 + y2 = y1 + cheight; 1.381 + 1.382 + srtot = sgtot = sbtot = satot = 0; 1.383 + 1.384 + for (i = y1; i < y2; ++i) 1.385 + { 1.386 + for (j = x1; j < x2; ++j) 1.387 + { 1.388 + int rx = j; 1.389 + int ry = i; 1.390 + 1.391 + pixman_fixed_t f = *params; 1.392 + 1.393 + if (f) 1.394 + { 1.395 + uint32_t pixel; 1.396 + 1.397 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.398 + { 1.399 + repeat (repeat_mode, &rx, width); 1.400 + repeat (repeat_mode, &ry, height); 1.401 + 1.402 + pixel = get_pixel (image, rx, ry, FALSE); 1.403 + } 1.404 + else 1.405 + { 1.406 + pixel = get_pixel (image, rx, ry, TRUE); 1.407 + } 1.408 + 1.409 + srtot += (int)RED_8 (pixel) * f; 1.410 + sgtot += (int)GREEN_8 (pixel) * f; 1.411 + sbtot += (int)BLUE_8 (pixel) * f; 1.412 + satot += (int)ALPHA_8 (pixel) * f; 1.413 + } 1.414 + 1.415 + params++; 1.416 + } 1.417 + } 1.418 + 1.419 + satot = (satot + 0x8000) >> 16; 1.420 + srtot = (srtot + 0x8000) >> 16; 1.421 + sgtot = (sgtot + 0x8000) >> 16; 1.422 + sbtot = (sbtot + 0x8000) >> 16; 1.423 + 1.424 + satot = CLIP (satot, 0, 0xff); 1.425 + srtot = CLIP (srtot, 0, 0xff); 1.426 + sgtot = CLIP (sgtot, 0, 0xff); 1.427 + sbtot = CLIP (sbtot, 0, 0xff); 1.428 + 1.429 + return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); 1.430 +} 1.431 + 1.432 +static uint32_t 1.433 +bits_image_fetch_pixel_separable_convolution (bits_image_t *image, 1.434 + pixman_fixed_t x, 1.435 + pixman_fixed_t y, 1.436 + get_pixel_t get_pixel) 1.437 +{ 1.438 + pixman_fixed_t *params = image->common.filter_params; 1.439 + pixman_repeat_t repeat_mode = image->common.repeat; 1.440 + int width = image->width; 1.441 + int height = image->height; 1.442 + int cwidth = pixman_fixed_to_int (params[0]); 1.443 + int cheight = pixman_fixed_to_int (params[1]); 1.444 + int x_phase_bits = pixman_fixed_to_int (params[2]); 1.445 + int y_phase_bits = pixman_fixed_to_int (params[3]); 1.446 + int x_phase_shift = 16 - x_phase_bits; 1.447 + int y_phase_shift = 16 - y_phase_bits; 1.448 + int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; 1.449 + int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; 1.450 + pixman_fixed_t *y_params; 1.451 + int srtot, sgtot, sbtot, satot; 1.452 + int32_t x1, x2, y1, y2; 1.453 + int32_t px, py; 1.454 + int i, j; 1.455 + 1.456 + /* Round x and y to the middle of the closest phase before continuing. This 1.457 + * ensures that the convolution matrix is aligned right, since it was 1.458 + * positioned relative to a particular phase (and not relative to whatever 1.459 + * exact fraction we happen to get here). 1.460 + */ 1.461 + x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); 1.462 + y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); 1.463 + 1.464 + px = (x & 0xffff) >> x_phase_shift; 1.465 + py = (y & 0xffff) >> y_phase_shift; 1.466 + 1.467 + y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; 1.468 + 1.469 + x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); 1.470 + y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); 1.471 + x2 = x1 + cwidth; 1.472 + y2 = y1 + cheight; 1.473 + 1.474 + srtot = sgtot = sbtot = satot = 0; 1.475 + 1.476 + for (i = y1; i < y2; ++i) 1.477 + { 1.478 + pixman_fixed_48_16_t fy = *y_params++; 1.479 + pixman_fixed_t *x_params = params + 4 + px * cwidth; 1.480 + 1.481 + if (fy) 1.482 + { 1.483 + for (j = x1; j < x2; ++j) 1.484 + { 1.485 + pixman_fixed_t fx = *x_params++; 1.486 + int rx = j; 1.487 + int ry = i; 1.488 + 1.489 + if (fx) 1.490 + { 1.491 + pixman_fixed_t f; 1.492 + uint32_t pixel; 1.493 + 1.494 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.495 + { 1.496 + repeat (repeat_mode, &rx, width); 1.497 + repeat (repeat_mode, &ry, height); 1.498 + 1.499 + pixel = get_pixel (image, rx, ry, FALSE); 1.500 + } 1.501 + else 1.502 + { 1.503 + pixel = get_pixel (image, rx, ry, TRUE); 1.504 + } 1.505 + 1.506 + f = (fy * fx + 0x8000) >> 16; 1.507 + 1.508 + srtot += (int)RED_8 (pixel) * f; 1.509 + sgtot += (int)GREEN_8 (pixel) * f; 1.510 + sbtot += (int)BLUE_8 (pixel) * f; 1.511 + satot += (int)ALPHA_8 (pixel) * f; 1.512 + } 1.513 + } 1.514 + } 1.515 + } 1.516 + 1.517 + satot = (satot + 0x8000) >> 16; 1.518 + srtot = (srtot + 0x8000) >> 16; 1.519 + sgtot = (sgtot + 0x8000) >> 16; 1.520 + sbtot = (sbtot + 0x8000) >> 16; 1.521 + 1.522 + satot = CLIP (satot, 0, 0xff); 1.523 + srtot = CLIP (srtot, 0, 0xff); 1.524 + sgtot = CLIP (sgtot, 0, 0xff); 1.525 + sbtot = CLIP (sbtot, 0, 0xff); 1.526 + 1.527 + return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); 1.528 +} 1.529 + 1.530 +static force_inline uint32_t 1.531 +bits_image_fetch_pixel_filtered (bits_image_t *image, 1.532 + pixman_fixed_t x, 1.533 + pixman_fixed_t y, 1.534 + get_pixel_t get_pixel) 1.535 +{ 1.536 + switch (image->common.filter) 1.537 + { 1.538 + case PIXMAN_FILTER_NEAREST: 1.539 + case PIXMAN_FILTER_FAST: 1.540 + return bits_image_fetch_pixel_nearest (image, x, y, get_pixel); 1.541 + break; 1.542 + 1.543 + case PIXMAN_FILTER_BILINEAR: 1.544 + case PIXMAN_FILTER_GOOD: 1.545 + case PIXMAN_FILTER_BEST: 1.546 + return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel); 1.547 + break; 1.548 + 1.549 + case PIXMAN_FILTER_CONVOLUTION: 1.550 + return bits_image_fetch_pixel_convolution (image, x, y, get_pixel); 1.551 + break; 1.552 + 1.553 + case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: 1.554 + return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel); 1.555 + break; 1.556 + 1.557 + default: 1.558 + break; 1.559 + } 1.560 + 1.561 + return 0; 1.562 +} 1.563 + 1.564 +static uint32_t * 1.565 +bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, 1.566 + const uint32_t * mask) 1.567 +{ 1.568 + pixman_image_t *image = iter->image; 1.569 + int offset = iter->x; 1.570 + int line = iter->y++; 1.571 + int width = iter->width; 1.572 + uint32_t * buffer = iter->buffer; 1.573 + 1.574 + pixman_fixed_t x, y; 1.575 + pixman_fixed_t ux, uy; 1.576 + pixman_vector_t v; 1.577 + int i; 1.578 + 1.579 + /* reference point is the center of the pixel */ 1.580 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1.581 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1.582 + v.vector[2] = pixman_fixed_1; 1.583 + 1.584 + if (image->common.transform) 1.585 + { 1.586 + if (!pixman_transform_point_3d (image->common.transform, &v)) 1.587 + return iter->buffer; 1.588 + 1.589 + ux = image->common.transform->matrix[0][0]; 1.590 + uy = image->common.transform->matrix[1][0]; 1.591 + } 1.592 + else 1.593 + { 1.594 + ux = pixman_fixed_1; 1.595 + uy = 0; 1.596 + } 1.597 + 1.598 + x = v.vector[0]; 1.599 + y = v.vector[1]; 1.600 + 1.601 + for (i = 0; i < width; ++i) 1.602 + { 1.603 + if (!mask || mask[i]) 1.604 + { 1.605 + buffer[i] = bits_image_fetch_pixel_filtered ( 1.606 + &image->bits, x, y, fetch_pixel_no_alpha); 1.607 + } 1.608 + 1.609 + x += ux; 1.610 + y += uy; 1.611 + } 1.612 + 1.613 + return buffer; 1.614 +} 1.615 + 1.616 +/* General fetcher */ 1.617 +static force_inline uint32_t 1.618 +fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) 1.619 +{ 1.620 + uint32_t pixel; 1.621 + 1.622 + if (check_bounds && 1.623 + (x < 0 || x >= image->width || y < 0 || y >= image->height)) 1.624 + { 1.625 + return 0; 1.626 + } 1.627 + 1.628 + pixel = image->fetch_pixel_32 (image, x, y); 1.629 + 1.630 + if (image->common.alpha_map) 1.631 + { 1.632 + uint32_t pixel_a; 1.633 + 1.634 + x -= image->common.alpha_origin_x; 1.635 + y -= image->common.alpha_origin_y; 1.636 + 1.637 + if (x < 0 || x >= image->common.alpha_map->width || 1.638 + y < 0 || y >= image->common.alpha_map->height) 1.639 + { 1.640 + pixel_a = 0; 1.641 + } 1.642 + else 1.643 + { 1.644 + pixel_a = image->common.alpha_map->fetch_pixel_32 ( 1.645 + image->common.alpha_map, x, y); 1.646 + 1.647 + pixel_a = ALPHA_8 (pixel_a); 1.648 + } 1.649 + 1.650 + pixel &= 0x00ffffff; 1.651 + pixel |= (pixel_a << 24); 1.652 + } 1.653 + 1.654 + return pixel; 1.655 +} 1.656 + 1.657 +static uint32_t * 1.658 +bits_image_fetch_general (pixman_iter_t *iter, 1.659 + const uint32_t *mask) 1.660 +{ 1.661 + pixman_image_t *image = iter->image; 1.662 + int offset = iter->x; 1.663 + int line = iter->y++; 1.664 + int width = iter->width; 1.665 + uint32_t * buffer = iter->buffer; 1.666 + 1.667 + pixman_fixed_t x, y, w; 1.668 + pixman_fixed_t ux, uy, uw; 1.669 + pixman_vector_t v; 1.670 + int i; 1.671 + 1.672 + /* reference point is the center of the pixel */ 1.673 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1.674 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1.675 + v.vector[2] = pixman_fixed_1; 1.676 + 1.677 + if (image->common.transform) 1.678 + { 1.679 + if (!pixman_transform_point_3d (image->common.transform, &v)) 1.680 + return buffer; 1.681 + 1.682 + ux = image->common.transform->matrix[0][0]; 1.683 + uy = image->common.transform->matrix[1][0]; 1.684 + uw = image->common.transform->matrix[2][0]; 1.685 + } 1.686 + else 1.687 + { 1.688 + ux = pixman_fixed_1; 1.689 + uy = 0; 1.690 + uw = 0; 1.691 + } 1.692 + 1.693 + x = v.vector[0]; 1.694 + y = v.vector[1]; 1.695 + w = v.vector[2]; 1.696 + 1.697 + for (i = 0; i < width; ++i) 1.698 + { 1.699 + pixman_fixed_t x0, y0; 1.700 + 1.701 + if (!mask || mask[i]) 1.702 + { 1.703 + if (w != 0) 1.704 + { 1.705 + x0 = ((pixman_fixed_48_16_t)x << 16) / w; 1.706 + y0 = ((pixman_fixed_48_16_t)y << 16) / w; 1.707 + } 1.708 + else 1.709 + { 1.710 + x0 = 0; 1.711 + y0 = 0; 1.712 + } 1.713 + 1.714 + buffer[i] = bits_image_fetch_pixel_filtered ( 1.715 + &image->bits, x0, y0, fetch_pixel_general); 1.716 + } 1.717 + 1.718 + x += ux; 1.719 + y += uy; 1.720 + w += uw; 1.721 + } 1.722 + 1.723 + return buffer; 1.724 +} 1.725 + 1.726 +typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x); 1.727 + 1.728 +static force_inline void 1.729 +bits_image_fetch_separable_convolution_affine (pixman_image_t * image, 1.730 + int offset, 1.731 + int line, 1.732 + int width, 1.733 + uint32_t * buffer, 1.734 + const uint32_t * mask, 1.735 + 1.736 + convert_pixel_t convert_pixel, 1.737 + pixman_format_code_t format, 1.738 + pixman_repeat_t repeat_mode) 1.739 +{ 1.740 + bits_image_t *bits = &image->bits; 1.741 + pixman_fixed_t *params = image->common.filter_params; 1.742 + int cwidth = pixman_fixed_to_int (params[0]); 1.743 + int cheight = pixman_fixed_to_int (params[1]); 1.744 + int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; 1.745 + int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; 1.746 + int x_phase_bits = pixman_fixed_to_int (params[2]); 1.747 + int y_phase_bits = pixman_fixed_to_int (params[3]); 1.748 + int x_phase_shift = 16 - x_phase_bits; 1.749 + int y_phase_shift = 16 - y_phase_bits; 1.750 + pixman_fixed_t vx, vy; 1.751 + pixman_fixed_t ux, uy; 1.752 + pixman_vector_t v; 1.753 + int k; 1.754 + 1.755 + /* reference point is the center of the pixel */ 1.756 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1.757 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1.758 + v.vector[2] = pixman_fixed_1; 1.759 + 1.760 + if (!pixman_transform_point_3d (image->common.transform, &v)) 1.761 + return; 1.762 + 1.763 + ux = image->common.transform->matrix[0][0]; 1.764 + uy = image->common.transform->matrix[1][0]; 1.765 + 1.766 + vx = v.vector[0]; 1.767 + vy = v.vector[1]; 1.768 + 1.769 + for (k = 0; k < width; ++k) 1.770 + { 1.771 + pixman_fixed_t *y_params; 1.772 + int satot, srtot, sgtot, sbtot; 1.773 + pixman_fixed_t x, y; 1.774 + int32_t x1, x2, y1, y2; 1.775 + int32_t px, py; 1.776 + int i, j; 1.777 + 1.778 + if (mask && !mask[k]) 1.779 + goto next; 1.780 + 1.781 + /* Round x and y to the middle of the closest phase before continuing. This 1.782 + * ensures that the convolution matrix is aligned right, since it was 1.783 + * positioned relative to a particular phase (and not relative to whatever 1.784 + * exact fraction we happen to get here). 1.785 + */ 1.786 + x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); 1.787 + y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); 1.788 + 1.789 + px = (x & 0xffff) >> x_phase_shift; 1.790 + py = (y & 0xffff) >> y_phase_shift; 1.791 + 1.792 + x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); 1.793 + y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); 1.794 + x2 = x1 + cwidth; 1.795 + y2 = y1 + cheight; 1.796 + 1.797 + satot = srtot = sgtot = sbtot = 0; 1.798 + 1.799 + y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; 1.800 + 1.801 + for (i = y1; i < y2; ++i) 1.802 + { 1.803 + pixman_fixed_t fy = *y_params++; 1.804 + 1.805 + if (fy) 1.806 + { 1.807 + pixman_fixed_t *x_params = params + 4 + px * cwidth; 1.808 + 1.809 + for (j = x1; j < x2; ++j) 1.810 + { 1.811 + pixman_fixed_t fx = *x_params++; 1.812 + int rx = j; 1.813 + int ry = i; 1.814 + 1.815 + if (fx) 1.816 + { 1.817 + pixman_fixed_t f; 1.818 + uint32_t pixel, mask; 1.819 + uint8_t *row; 1.820 + 1.821 + mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 1.822 + 1.823 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.824 + { 1.825 + repeat (repeat_mode, &rx, bits->width); 1.826 + repeat (repeat_mode, &ry, bits->height); 1.827 + 1.828 + row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; 1.829 + pixel = convert_pixel (row, rx) | mask; 1.830 + } 1.831 + else 1.832 + { 1.833 + if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height) 1.834 + { 1.835 + pixel = 0; 1.836 + } 1.837 + else 1.838 + { 1.839 + row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; 1.840 + pixel = convert_pixel (row, rx) | mask; 1.841 + } 1.842 + } 1.843 + 1.844 + f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16; 1.845 + srtot += (int)RED_8 (pixel) * f; 1.846 + sgtot += (int)GREEN_8 (pixel) * f; 1.847 + sbtot += (int)BLUE_8 (pixel) * f; 1.848 + satot += (int)ALPHA_8 (pixel) * f; 1.849 + } 1.850 + } 1.851 + } 1.852 + } 1.853 + 1.854 + satot = (satot + 0x8000) >> 16; 1.855 + srtot = (srtot + 0x8000) >> 16; 1.856 + sgtot = (sgtot + 0x8000) >> 16; 1.857 + sbtot = (sbtot + 0x8000) >> 16; 1.858 + 1.859 + satot = CLIP (satot, 0, 0xff); 1.860 + srtot = CLIP (srtot, 0, 0xff); 1.861 + sgtot = CLIP (sgtot, 0, 0xff); 1.862 + sbtot = CLIP (sbtot, 0, 0xff); 1.863 + 1.864 + buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0); 1.865 + 1.866 + next: 1.867 + vx += ux; 1.868 + vy += uy; 1.869 + } 1.870 +} 1.871 + 1.872 +static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 1.873 + 1.874 +static force_inline void 1.875 +bits_image_fetch_bilinear_affine (pixman_image_t * image, 1.876 + int offset, 1.877 + int line, 1.878 + int width, 1.879 + uint32_t * buffer, 1.880 + const uint32_t * mask, 1.881 + 1.882 + convert_pixel_t convert_pixel, 1.883 + pixman_format_code_t format, 1.884 + pixman_repeat_t repeat_mode) 1.885 +{ 1.886 + pixman_fixed_t x, y; 1.887 + pixman_fixed_t ux, uy; 1.888 + pixman_vector_t v; 1.889 + bits_image_t *bits = &image->bits; 1.890 + int i; 1.891 + 1.892 + /* reference point is the center of the pixel */ 1.893 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1.894 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1.895 + v.vector[2] = pixman_fixed_1; 1.896 + 1.897 + if (!pixman_transform_point_3d (image->common.transform, &v)) 1.898 + return; 1.899 + 1.900 + ux = image->common.transform->matrix[0][0]; 1.901 + uy = image->common.transform->matrix[1][0]; 1.902 + 1.903 + x = v.vector[0]; 1.904 + y = v.vector[1]; 1.905 + 1.906 + for (i = 0; i < width; ++i) 1.907 + { 1.908 + int x1, y1, x2, y2; 1.909 + uint32_t tl, tr, bl, br; 1.910 + int32_t distx, disty; 1.911 + int width = image->bits.width; 1.912 + int height = image->bits.height; 1.913 + const uint8_t *row1; 1.914 + const uint8_t *row2; 1.915 + 1.916 + if (mask && !mask[i]) 1.917 + goto next; 1.918 + 1.919 + x1 = x - pixman_fixed_1 / 2; 1.920 + y1 = y - pixman_fixed_1 / 2; 1.921 + 1.922 + distx = pixman_fixed_to_bilinear_weight (x1); 1.923 + disty = pixman_fixed_to_bilinear_weight (y1); 1.924 + 1.925 + y1 = pixman_fixed_to_int (y1); 1.926 + y2 = y1 + 1; 1.927 + x1 = pixman_fixed_to_int (x1); 1.928 + x2 = x1 + 1; 1.929 + 1.930 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.931 + { 1.932 + uint32_t mask; 1.933 + 1.934 + mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 1.935 + 1.936 + repeat (repeat_mode, &x1, width); 1.937 + repeat (repeat_mode, &y1, height); 1.938 + repeat (repeat_mode, &x2, width); 1.939 + repeat (repeat_mode, &y2, height); 1.940 + 1.941 + row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; 1.942 + row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; 1.943 + 1.944 + tl = convert_pixel (row1, x1) | mask; 1.945 + tr = convert_pixel (row1, x2) | mask; 1.946 + bl = convert_pixel (row2, x1) | mask; 1.947 + br = convert_pixel (row2, x2) | mask; 1.948 + } 1.949 + else 1.950 + { 1.951 + uint32_t mask1, mask2; 1.952 + int bpp; 1.953 + 1.954 + /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value, 1.955 + * which means if you use it in expressions, those 1.956 + * expressions become unsigned themselves. Since 1.957 + * the variables below can be negative in some cases, 1.958 + * that will lead to crashes on 64 bit architectures. 1.959 + * 1.960 + * So this line makes sure bpp is signed 1.961 + */ 1.962 + bpp = PIXMAN_FORMAT_BPP (format); 1.963 + 1.964 + if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0) 1.965 + { 1.966 + buffer[i] = 0; 1.967 + goto next; 1.968 + } 1.969 + 1.970 + if (y2 == 0) 1.971 + { 1.972 + row1 = zero; 1.973 + mask1 = 0; 1.974 + } 1.975 + else 1.976 + { 1.977 + row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; 1.978 + row1 += bpp / 8 * x1; 1.979 + 1.980 + mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 1.981 + } 1.982 + 1.983 + if (y1 == height - 1) 1.984 + { 1.985 + row2 = zero; 1.986 + mask2 = 0; 1.987 + } 1.988 + else 1.989 + { 1.990 + row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; 1.991 + row2 += bpp / 8 * x1; 1.992 + 1.993 + mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 1.994 + } 1.995 + 1.996 + if (x2 == 0) 1.997 + { 1.998 + tl = 0; 1.999 + bl = 0; 1.1000 + } 1.1001 + else 1.1002 + { 1.1003 + tl = convert_pixel (row1, 0) | mask1; 1.1004 + bl = convert_pixel (row2, 0) | mask2; 1.1005 + } 1.1006 + 1.1007 + if (x1 == width - 1) 1.1008 + { 1.1009 + tr = 0; 1.1010 + br = 0; 1.1011 + } 1.1012 + else 1.1013 + { 1.1014 + tr = convert_pixel (row1, 1) | mask1; 1.1015 + br = convert_pixel (row2, 1) | mask2; 1.1016 + } 1.1017 + } 1.1018 + 1.1019 + buffer[i] = bilinear_interpolation ( 1.1020 + tl, tr, bl, br, distx, disty); 1.1021 + 1.1022 + next: 1.1023 + x += ux; 1.1024 + y += uy; 1.1025 + } 1.1026 +} 1.1027 + 1.1028 +static force_inline void 1.1029 +bits_image_fetch_nearest_affine (pixman_image_t * image, 1.1030 + int offset, 1.1031 + int line, 1.1032 + int width, 1.1033 + uint32_t * buffer, 1.1034 + const uint32_t * mask, 1.1035 + 1.1036 + convert_pixel_t convert_pixel, 1.1037 + pixman_format_code_t format, 1.1038 + pixman_repeat_t repeat_mode) 1.1039 +{ 1.1040 + pixman_fixed_t x, y; 1.1041 + pixman_fixed_t ux, uy; 1.1042 + pixman_vector_t v; 1.1043 + bits_image_t *bits = &image->bits; 1.1044 + int i; 1.1045 + 1.1046 + /* reference point is the center of the pixel */ 1.1047 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; 1.1048 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; 1.1049 + v.vector[2] = pixman_fixed_1; 1.1050 + 1.1051 + if (!pixman_transform_point_3d (image->common.transform, &v)) 1.1052 + return; 1.1053 + 1.1054 + ux = image->common.transform->matrix[0][0]; 1.1055 + uy = image->common.transform->matrix[1][0]; 1.1056 + 1.1057 + x = v.vector[0]; 1.1058 + y = v.vector[1]; 1.1059 + 1.1060 + for (i = 0; i < width; ++i) 1.1061 + { 1.1062 + int width, height, x0, y0; 1.1063 + const uint8_t *row; 1.1064 + 1.1065 + if (mask && !mask[i]) 1.1066 + goto next; 1.1067 + 1.1068 + width = image->bits.width; 1.1069 + height = image->bits.height; 1.1070 + x0 = pixman_fixed_to_int (x - pixman_fixed_e); 1.1071 + y0 = pixman_fixed_to_int (y - pixman_fixed_e); 1.1072 + 1.1073 + if (repeat_mode == PIXMAN_REPEAT_NONE && 1.1074 + (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width)) 1.1075 + { 1.1076 + buffer[i] = 0; 1.1077 + } 1.1078 + else 1.1079 + { 1.1080 + uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; 1.1081 + 1.1082 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.1083 + { 1.1084 + repeat (repeat_mode, &x0, width); 1.1085 + repeat (repeat_mode, &y0, height); 1.1086 + } 1.1087 + 1.1088 + row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0; 1.1089 + 1.1090 + buffer[i] = convert_pixel (row, x0) | mask; 1.1091 + } 1.1092 + 1.1093 + next: 1.1094 + x += ux; 1.1095 + y += uy; 1.1096 + } 1.1097 +} 1.1098 + 1.1099 +static force_inline uint32_t 1.1100 +convert_a8r8g8b8 (const uint8_t *row, int x) 1.1101 +{ 1.1102 + return *(((uint32_t *)row) + x); 1.1103 +} 1.1104 + 1.1105 +static force_inline uint32_t 1.1106 +convert_x8r8g8b8 (const uint8_t *row, int x) 1.1107 +{ 1.1108 + return *(((uint32_t *)row) + x); 1.1109 +} 1.1110 + 1.1111 +static force_inline uint32_t 1.1112 +convert_a8 (const uint8_t *row, int x) 1.1113 +{ 1.1114 + return *(row + x) << 24; 1.1115 +} 1.1116 + 1.1117 +static force_inline uint32_t 1.1118 +convert_r5g6b5 (const uint8_t *row, int x) 1.1119 +{ 1.1120 + return convert_0565_to_0888 (*((uint16_t *)row + x)); 1.1121 +} 1.1122 + 1.1123 +#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \ 1.1124 + static uint32_t * \ 1.1125 + bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \ 1.1126 + const uint32_t * mask) \ 1.1127 + { \ 1.1128 + bits_image_fetch_separable_convolution_affine ( \ 1.1129 + iter->image, \ 1.1130 + iter->x, iter->y++, \ 1.1131 + iter->width, \ 1.1132 + iter->buffer, mask, \ 1.1133 + convert_ ## format, \ 1.1134 + PIXMAN_ ## format, \ 1.1135 + repeat_mode); \ 1.1136 + \ 1.1137 + return iter->buffer; \ 1.1138 + } 1.1139 + 1.1140 +#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ 1.1141 + static uint32_t * \ 1.1142 + bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ 1.1143 + const uint32_t * mask) \ 1.1144 + { \ 1.1145 + bits_image_fetch_bilinear_affine (iter->image, \ 1.1146 + iter->x, iter->y++, \ 1.1147 + iter->width, \ 1.1148 + iter->buffer, mask, \ 1.1149 + convert_ ## format, \ 1.1150 + PIXMAN_ ## format, \ 1.1151 + repeat_mode); \ 1.1152 + return iter->buffer; \ 1.1153 + } 1.1154 + 1.1155 +#define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \ 1.1156 + static uint32_t * \ 1.1157 + bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \ 1.1158 + const uint32_t * mask) \ 1.1159 + { \ 1.1160 + bits_image_fetch_nearest_affine (iter->image, \ 1.1161 + iter->x, iter->y++, \ 1.1162 + iter->width, \ 1.1163 + iter->buffer, mask, \ 1.1164 + convert_ ## format, \ 1.1165 + PIXMAN_ ## format, \ 1.1166 + repeat_mode); \ 1.1167 + return iter->buffer; \ 1.1168 + } 1.1169 + 1.1170 +#define MAKE_FETCHERS(name, format, repeat_mode) \ 1.1171 + MAKE_NEAREST_FETCHER (name, format, repeat_mode) \ 1.1172 + MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \ 1.1173 + MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode) 1.1174 + 1.1175 +MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD) 1.1176 +MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE) 1.1177 +MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT) 1.1178 +MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL) 1.1179 +MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD) 1.1180 +MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE) 1.1181 +MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT) 1.1182 +MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL) 1.1183 +MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD) 1.1184 +MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE) 1.1185 +MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT) 1.1186 +MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL) 1.1187 +MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD) 1.1188 +MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE) 1.1189 +MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT) 1.1190 +MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL) 1.1191 + 1.1192 +static void 1.1193 +replicate_pixel_32 (bits_image_t * bits, 1.1194 + int x, 1.1195 + int y, 1.1196 + int width, 1.1197 + uint32_t * buffer) 1.1198 +{ 1.1199 + uint32_t color; 1.1200 + uint32_t *end; 1.1201 + 1.1202 + color = bits->fetch_pixel_32 (bits, x, y); 1.1203 + 1.1204 + end = buffer + width; 1.1205 + while (buffer < end) 1.1206 + *(buffer++) = color; 1.1207 +} 1.1208 + 1.1209 +static void 1.1210 +replicate_pixel_float (bits_image_t * bits, 1.1211 + int x, 1.1212 + int y, 1.1213 + int width, 1.1214 + uint32_t * b) 1.1215 +{ 1.1216 + argb_t color; 1.1217 + argb_t *buffer = (argb_t *)b; 1.1218 + argb_t *end; 1.1219 + 1.1220 + color = bits->fetch_pixel_float (bits, x, y); 1.1221 + 1.1222 + end = buffer + width; 1.1223 + while (buffer < end) 1.1224 + *(buffer++) = color; 1.1225 +} 1.1226 + 1.1227 +static void 1.1228 +bits_image_fetch_untransformed_repeat_none (bits_image_t *image, 1.1229 + pixman_bool_t wide, 1.1230 + int x, 1.1231 + int y, 1.1232 + int width, 1.1233 + uint32_t * buffer) 1.1234 +{ 1.1235 + uint32_t w; 1.1236 + 1.1237 + if (y < 0 || y >= image->height) 1.1238 + { 1.1239 + memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); 1.1240 + return; 1.1241 + } 1.1242 + 1.1243 + if (x < 0) 1.1244 + { 1.1245 + w = MIN (width, -x); 1.1246 + 1.1247 + memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); 1.1248 + 1.1249 + width -= w; 1.1250 + buffer += w * (wide? 4 : 1); 1.1251 + x += w; 1.1252 + } 1.1253 + 1.1254 + if (x < image->width) 1.1255 + { 1.1256 + w = MIN (width, image->width - x); 1.1257 + 1.1258 + if (wide) 1.1259 + image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); 1.1260 + else 1.1261 + image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); 1.1262 + 1.1263 + width -= w; 1.1264 + buffer += w * (wide? 4 : 1); 1.1265 + x += w; 1.1266 + } 1.1267 + 1.1268 + memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); 1.1269 +} 1.1270 + 1.1271 +static void 1.1272 +bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, 1.1273 + pixman_bool_t wide, 1.1274 + int x, 1.1275 + int y, 1.1276 + int width, 1.1277 + uint32_t * buffer) 1.1278 +{ 1.1279 + uint32_t w; 1.1280 + 1.1281 + while (y < 0) 1.1282 + y += image->height; 1.1283 + 1.1284 + while (y >= image->height) 1.1285 + y -= image->height; 1.1286 + 1.1287 + if (image->width == 1) 1.1288 + { 1.1289 + if (wide) 1.1290 + replicate_pixel_float (image, 0, y, width, buffer); 1.1291 + else 1.1292 + replicate_pixel_32 (image, 0, y, width, buffer); 1.1293 + 1.1294 + return; 1.1295 + } 1.1296 + 1.1297 + while (width) 1.1298 + { 1.1299 + while (x < 0) 1.1300 + x += image->width; 1.1301 + while (x >= image->width) 1.1302 + x -= image->width; 1.1303 + 1.1304 + w = MIN (width, image->width - x); 1.1305 + 1.1306 + if (wide) 1.1307 + image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); 1.1308 + else 1.1309 + image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); 1.1310 + 1.1311 + buffer += w * (wide? 4 : 1); 1.1312 + x += w; 1.1313 + width -= w; 1.1314 + } 1.1315 +} 1.1316 + 1.1317 +static uint32_t * 1.1318 +bits_image_fetch_untransformed_32 (pixman_iter_t * iter, 1.1319 + const uint32_t *mask) 1.1320 +{ 1.1321 + pixman_image_t *image = iter->image; 1.1322 + int x = iter->x; 1.1323 + int y = iter->y; 1.1324 + int width = iter->width; 1.1325 + uint32_t * buffer = iter->buffer; 1.1326 + 1.1327 + if (image->common.repeat == PIXMAN_REPEAT_NONE) 1.1328 + { 1.1329 + bits_image_fetch_untransformed_repeat_none ( 1.1330 + &image->bits, FALSE, x, y, width, buffer); 1.1331 + } 1.1332 + else 1.1333 + { 1.1334 + bits_image_fetch_untransformed_repeat_normal ( 1.1335 + &image->bits, FALSE, x, y, width, buffer); 1.1336 + } 1.1337 + 1.1338 + iter->y++; 1.1339 + return buffer; 1.1340 +} 1.1341 + 1.1342 +static uint32_t * 1.1343 +bits_image_fetch_untransformed_float (pixman_iter_t * iter, 1.1344 + const uint32_t *mask) 1.1345 +{ 1.1346 + pixman_image_t *image = iter->image; 1.1347 + int x = iter->x; 1.1348 + int y = iter->y; 1.1349 + int width = iter->width; 1.1350 + uint32_t * buffer = iter->buffer; 1.1351 + 1.1352 + if (image->common.repeat == PIXMAN_REPEAT_NONE) 1.1353 + { 1.1354 + bits_image_fetch_untransformed_repeat_none ( 1.1355 + &image->bits, TRUE, x, y, width, buffer); 1.1356 + } 1.1357 + else 1.1358 + { 1.1359 + bits_image_fetch_untransformed_repeat_normal ( 1.1360 + &image->bits, TRUE, x, y, width, buffer); 1.1361 + } 1.1362 + 1.1363 + iter->y++; 1.1364 + return buffer; 1.1365 +} 1.1366 + 1.1367 +typedef struct 1.1368 +{ 1.1369 + pixman_format_code_t format; 1.1370 + uint32_t flags; 1.1371 + pixman_iter_get_scanline_t get_scanline_32; 1.1372 + pixman_iter_get_scanline_t get_scanline_float; 1.1373 +} fetcher_info_t; 1.1374 + 1.1375 +static const fetcher_info_t fetcher_info[] = 1.1376 +{ 1.1377 + { PIXMAN_any, 1.1378 + (FAST_PATH_NO_ALPHA_MAP | 1.1379 + FAST_PATH_ID_TRANSFORM | 1.1380 + FAST_PATH_NO_CONVOLUTION_FILTER | 1.1381 + FAST_PATH_NO_PAD_REPEAT | 1.1382 + FAST_PATH_NO_REFLECT_REPEAT), 1.1383 + bits_image_fetch_untransformed_32, 1.1384 + bits_image_fetch_untransformed_float 1.1385 + }, 1.1386 + 1.1387 +#define FAST_BILINEAR_FLAGS \ 1.1388 + (FAST_PATH_NO_ALPHA_MAP | \ 1.1389 + FAST_PATH_NO_ACCESSORS | \ 1.1390 + FAST_PATH_HAS_TRANSFORM | \ 1.1391 + FAST_PATH_AFFINE_TRANSFORM | \ 1.1392 + FAST_PATH_X_UNIT_POSITIVE | \ 1.1393 + FAST_PATH_Y_UNIT_ZERO | \ 1.1394 + FAST_PATH_NONE_REPEAT | \ 1.1395 + FAST_PATH_BILINEAR_FILTER) 1.1396 + 1.1397 + { PIXMAN_a8r8g8b8, 1.1398 + FAST_BILINEAR_FLAGS, 1.1399 + bits_image_fetch_bilinear_no_repeat_8888, 1.1400 + _pixman_image_get_scanline_generic_float 1.1401 + }, 1.1402 + 1.1403 + { PIXMAN_x8r8g8b8, 1.1404 + FAST_BILINEAR_FLAGS, 1.1405 + bits_image_fetch_bilinear_no_repeat_8888, 1.1406 + _pixman_image_get_scanline_generic_float 1.1407 + }, 1.1408 + 1.1409 +#define GENERAL_BILINEAR_FLAGS \ 1.1410 + (FAST_PATH_NO_ALPHA_MAP | \ 1.1411 + FAST_PATH_NO_ACCESSORS | \ 1.1412 + FAST_PATH_HAS_TRANSFORM | \ 1.1413 + FAST_PATH_AFFINE_TRANSFORM | \ 1.1414 + FAST_PATH_BILINEAR_FILTER) 1.1415 + 1.1416 +#define GENERAL_NEAREST_FLAGS \ 1.1417 + (FAST_PATH_NO_ALPHA_MAP | \ 1.1418 + FAST_PATH_NO_ACCESSORS | \ 1.1419 + FAST_PATH_HAS_TRANSFORM | \ 1.1420 + FAST_PATH_AFFINE_TRANSFORM | \ 1.1421 + FAST_PATH_NEAREST_FILTER) 1.1422 + 1.1423 +#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \ 1.1424 + (FAST_PATH_NO_ALPHA_MAP | \ 1.1425 + FAST_PATH_NO_ACCESSORS | \ 1.1426 + FAST_PATH_HAS_TRANSFORM | \ 1.1427 + FAST_PATH_AFFINE_TRANSFORM | \ 1.1428 + FAST_PATH_SEPARABLE_CONVOLUTION_FILTER) 1.1429 + 1.1430 +#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ 1.1431 + { PIXMAN_ ## format, \ 1.1432 + GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ 1.1433 + bits_image_fetch_separable_convolution_affine_ ## name, \ 1.1434 + _pixman_image_get_scanline_generic_float \ 1.1435 + }, 1.1436 + 1.1437 +#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ 1.1438 + { PIXMAN_ ## format, \ 1.1439 + GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ 1.1440 + bits_image_fetch_bilinear_affine_ ## name, \ 1.1441 + _pixman_image_get_scanline_generic_float \ 1.1442 + }, 1.1443 + 1.1444 +#define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \ 1.1445 + { PIXMAN_ ## format, \ 1.1446 + GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ 1.1447 + bits_image_fetch_nearest_affine_ ## name, \ 1.1448 + _pixman_image_get_scanline_generic_float \ 1.1449 + }, 1.1450 + 1.1451 +#define AFFINE_FAST_PATHS(name, format, repeat) \ 1.1452 + SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ 1.1453 + BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ 1.1454 + NEAREST_AFFINE_FAST_PATH(name, format, repeat) 1.1455 + 1.1456 + AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD) 1.1457 + AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE) 1.1458 + AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT) 1.1459 + AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL) 1.1460 + AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD) 1.1461 + AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE) 1.1462 + AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT) 1.1463 + AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL) 1.1464 + AFFINE_FAST_PATHS (pad_a8, a8, PAD) 1.1465 + AFFINE_FAST_PATHS (none_a8, a8, NONE) 1.1466 + AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT) 1.1467 + AFFINE_FAST_PATHS (normal_a8, a8, NORMAL) 1.1468 + AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD) 1.1469 + AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE) 1.1470 + AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT) 1.1471 + AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL) 1.1472 + 1.1473 + /* Affine, no alpha */ 1.1474 + { PIXMAN_any, 1.1475 + (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM), 1.1476 + bits_image_fetch_affine_no_alpha, 1.1477 + _pixman_image_get_scanline_generic_float 1.1478 + }, 1.1479 + 1.1480 + /* General */ 1.1481 + { PIXMAN_any, 1.1482 + 0, 1.1483 + bits_image_fetch_general, 1.1484 + _pixman_image_get_scanline_generic_float 1.1485 + }, 1.1486 + 1.1487 + { PIXMAN_null }, 1.1488 +}; 1.1489 + 1.1490 +static void 1.1491 +bits_image_property_changed (pixman_image_t *image) 1.1492 +{ 1.1493 + _pixman_bits_image_setup_accessors (&image->bits); 1.1494 +} 1.1495 + 1.1496 +void 1.1497 +_pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) 1.1498 +{ 1.1499 + pixman_format_code_t format = image->common.extended_format_code; 1.1500 + uint32_t flags = image->common.flags; 1.1501 + const fetcher_info_t *info; 1.1502 + 1.1503 + for (info = fetcher_info; info->format != PIXMAN_null; ++info) 1.1504 + { 1.1505 + if ((info->format == format || info->format == PIXMAN_any) && 1.1506 + (info->flags & flags) == info->flags) 1.1507 + { 1.1508 + if (iter->iter_flags & ITER_NARROW) 1.1509 + { 1.1510 + iter->get_scanline = info->get_scanline_32; 1.1511 + } 1.1512 + else 1.1513 + { 1.1514 + iter->data = info->get_scanline_32; 1.1515 + iter->get_scanline = info->get_scanline_float; 1.1516 + } 1.1517 + return; 1.1518 + } 1.1519 + } 1.1520 + 1.1521 + /* Just in case we somehow didn't find a scanline function */ 1.1522 + iter->get_scanline = _pixman_iter_get_scanline_noop; 1.1523 +} 1.1524 + 1.1525 +static uint32_t * 1.1526 +dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask) 1.1527 +{ 1.1528 + pixman_image_t *image = iter->image; 1.1529 + int x = iter->x; 1.1530 + int y = iter->y; 1.1531 + int width = iter->width; 1.1532 + uint32_t * buffer = iter->buffer; 1.1533 + 1.1534 + image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask); 1.1535 + 1.1536 + return iter->buffer; 1.1537 +} 1.1538 + 1.1539 +static uint32_t * 1.1540 +dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) 1.1541 +{ 1.1542 + pixman_image_t *image = iter->image; 1.1543 + int x = iter->x; 1.1544 + int y = iter->y; 1.1545 + int width = iter->width; 1.1546 + uint32_t * buffer = iter->buffer; 1.1547 + 1.1548 + image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask); 1.1549 + if (image->common.alpha_map) 1.1550 + { 1.1551 + uint32_t *alpha; 1.1552 + 1.1553 + if ((alpha = malloc (width * sizeof (uint32_t)))) 1.1554 + { 1.1555 + int i; 1.1556 + 1.1557 + x -= image->common.alpha_origin_x; 1.1558 + y -= image->common.alpha_origin_y; 1.1559 + 1.1560 + image->common.alpha_map->fetch_scanline_32 ( 1.1561 + (pixman_image_t *)image->common.alpha_map, 1.1562 + x, y, width, alpha, mask); 1.1563 + 1.1564 + for (i = 0; i < width; ++i) 1.1565 + { 1.1566 + buffer[i] &= ~0xff000000; 1.1567 + buffer[i] |= (alpha[i] & 0xff000000); 1.1568 + } 1.1569 + 1.1570 + free (alpha); 1.1571 + } 1.1572 + } 1.1573 + 1.1574 + return iter->buffer; 1.1575 +} 1.1576 + 1.1577 +static uint32_t * 1.1578 +dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) 1.1579 +{ 1.1580 + bits_image_t * image = &iter->image->bits; 1.1581 + int x = iter->x; 1.1582 + int y = iter->y; 1.1583 + int width = iter->width; 1.1584 + argb_t * buffer = (argb_t *)iter->buffer; 1.1585 + 1.1586 + image->fetch_scanline_float ( 1.1587 + (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask); 1.1588 + if (image->common.alpha_map) 1.1589 + { 1.1590 + argb_t *alpha; 1.1591 + 1.1592 + if ((alpha = malloc (width * sizeof (argb_t)))) 1.1593 + { 1.1594 + int i; 1.1595 + 1.1596 + x -= image->common.alpha_origin_x; 1.1597 + y -= image->common.alpha_origin_y; 1.1598 + 1.1599 + image->common.alpha_map->fetch_scanline_float ( 1.1600 + (pixman_image_t *)image->common.alpha_map, 1.1601 + x, y, width, (uint32_t *)alpha, mask); 1.1602 + 1.1603 + for (i = 0; i < width; ++i) 1.1604 + buffer[i].a = alpha[i].a; 1.1605 + 1.1606 + free (alpha); 1.1607 + } 1.1608 + } 1.1609 + 1.1610 + return iter->buffer; 1.1611 +} 1.1612 + 1.1613 +static void 1.1614 +dest_write_back_16 (pixman_iter_t *iter) 1.1615 +{ 1.1616 + bits_image_t * image = &iter->image->bits; 1.1617 + int x = iter->x; 1.1618 + int y = iter->y; 1.1619 + int width = iter->width; 1.1620 + const uint32_t *buffer = iter->buffer; 1.1621 + 1.1622 + image->store_scanline_16 (image, x, y, width, buffer); 1.1623 + 1.1624 + iter->y++; 1.1625 +} 1.1626 + 1.1627 +static void 1.1628 +dest_write_back_narrow (pixman_iter_t *iter) 1.1629 +{ 1.1630 + bits_image_t * image = &iter->image->bits; 1.1631 + int x = iter->x; 1.1632 + int y = iter->y; 1.1633 + int width = iter->width; 1.1634 + const uint32_t *buffer = iter->buffer; 1.1635 + 1.1636 + image->store_scanline_32 (image, x, y, width, buffer); 1.1637 + 1.1638 + if (image->common.alpha_map) 1.1639 + { 1.1640 + x -= image->common.alpha_origin_x; 1.1641 + y -= image->common.alpha_origin_y; 1.1642 + 1.1643 + image->common.alpha_map->store_scanline_32 ( 1.1644 + image->common.alpha_map, x, y, width, buffer); 1.1645 + } 1.1646 + 1.1647 + iter->y++; 1.1648 +} 1.1649 + 1.1650 +static void 1.1651 +dest_write_back_wide (pixman_iter_t *iter) 1.1652 +{ 1.1653 + bits_image_t * image = &iter->image->bits; 1.1654 + int x = iter->x; 1.1655 + int y = iter->y; 1.1656 + int width = iter->width; 1.1657 + const uint32_t *buffer = iter->buffer; 1.1658 + 1.1659 + image->store_scanline_float (image, x, y, width, buffer); 1.1660 + 1.1661 + if (image->common.alpha_map) 1.1662 + { 1.1663 + x -= image->common.alpha_origin_x; 1.1664 + y -= image->common.alpha_origin_y; 1.1665 + 1.1666 + image->common.alpha_map->store_scanline_float ( 1.1667 + image->common.alpha_map, x, y, width, buffer); 1.1668 + } 1.1669 + 1.1670 + iter->y++; 1.1671 +} 1.1672 + 1.1673 +void 1.1674 +_pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) 1.1675 +{ 1.1676 + if (iter->iter_flags & ITER_16) 1.1677 + { 1.1678 + if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == 1.1679 + (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) 1.1680 + { 1.1681 + iter->get_scanline = _pixman_iter_get_scanline_noop; 1.1682 + } 1.1683 + else 1.1684 + { 1.1685 + iter->get_scanline = dest_get_scanline_16; 1.1686 + } 1.1687 + iter->write_back = dest_write_back_16; 1.1688 + } 1.1689 + else if (iter->iter_flags & ITER_NARROW) 1.1690 + { 1.1691 + if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == 1.1692 + (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) 1.1693 + { 1.1694 + iter->get_scanline = _pixman_iter_get_scanline_noop; 1.1695 + } 1.1696 + else 1.1697 + { 1.1698 + iter->get_scanline = dest_get_scanline_narrow; 1.1699 + } 1.1700 + 1.1701 + iter->write_back = dest_write_back_narrow; 1.1702 + } 1.1703 + else 1.1704 + { 1.1705 + iter->get_scanline = dest_get_scanline_wide; 1.1706 + iter->write_back = dest_write_back_wide; 1.1707 + } 1.1708 +} 1.1709 + 1.1710 +static uint32_t * 1.1711 +create_bits (pixman_format_code_t format, 1.1712 + int width, 1.1713 + int height, 1.1714 + int * rowstride_bytes, 1.1715 + pixman_bool_t clear) 1.1716 +{ 1.1717 + int stride; 1.1718 + size_t buf_size; 1.1719 + int bpp; 1.1720 + 1.1721 + /* what follows is a long-winded way, avoiding any possibility of integer 1.1722 + * overflows, of saying: 1.1723 + * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); 1.1724 + */ 1.1725 + 1.1726 + bpp = PIXMAN_FORMAT_BPP (format); 1.1727 + if (_pixman_multiply_overflows_int (width, bpp)) 1.1728 + return NULL; 1.1729 + 1.1730 + stride = width * bpp; 1.1731 + if (_pixman_addition_overflows_int (stride, 0x1f)) 1.1732 + return NULL; 1.1733 + 1.1734 + stride += 0x1f; 1.1735 + stride >>= 5; 1.1736 + 1.1737 + stride *= sizeof (uint32_t); 1.1738 + 1.1739 + if (_pixman_multiply_overflows_size (height, stride)) 1.1740 + return NULL; 1.1741 + 1.1742 + buf_size = height * stride; 1.1743 + 1.1744 + if (rowstride_bytes) 1.1745 + *rowstride_bytes = stride; 1.1746 + 1.1747 + if (clear) 1.1748 + return calloc (buf_size, 1); 1.1749 + else 1.1750 + return malloc (buf_size); 1.1751 +} 1.1752 + 1.1753 +pixman_bool_t 1.1754 +_pixman_bits_image_init (pixman_image_t * image, 1.1755 + pixman_format_code_t format, 1.1756 + int width, 1.1757 + int height, 1.1758 + uint32_t * bits, 1.1759 + int rowstride, 1.1760 + pixman_bool_t clear) 1.1761 +{ 1.1762 + uint32_t *free_me = NULL; 1.1763 + 1.1764 + if (!bits && width && height) 1.1765 + { 1.1766 + int rowstride_bytes; 1.1767 + 1.1768 + free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); 1.1769 + 1.1770 + if (!bits) 1.1771 + return FALSE; 1.1772 + 1.1773 + rowstride = rowstride_bytes / (int) sizeof (uint32_t); 1.1774 + } 1.1775 + 1.1776 + _pixman_image_init (image); 1.1777 + 1.1778 + image->type = BITS; 1.1779 + image->bits.format = format; 1.1780 + image->bits.width = width; 1.1781 + image->bits.height = height; 1.1782 + image->bits.bits = bits; 1.1783 + image->bits.free_me = free_me; 1.1784 + image->bits.read_func = NULL; 1.1785 + image->bits.write_func = NULL; 1.1786 + image->bits.rowstride = rowstride; 1.1787 + image->bits.indexed = NULL; 1.1788 + 1.1789 + image->common.property_changed = bits_image_property_changed; 1.1790 + 1.1791 + _pixman_image_reset_clip_region (image); 1.1792 + 1.1793 + return TRUE; 1.1794 +} 1.1795 + 1.1796 +static pixman_image_t * 1.1797 +create_bits_image_internal (pixman_format_code_t format, 1.1798 + int width, 1.1799 + int height, 1.1800 + uint32_t * bits, 1.1801 + int rowstride_bytes, 1.1802 + pixman_bool_t clear) 1.1803 +{ 1.1804 + pixman_image_t *image; 1.1805 + 1.1806 + /* must be a whole number of uint32_t's 1.1807 + */ 1.1808 + return_val_if_fail ( 1.1809 + bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); 1.1810 + 1.1811 + return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); 1.1812 + 1.1813 + image = _pixman_image_allocate (); 1.1814 + 1.1815 + if (!image) 1.1816 + return NULL; 1.1817 + 1.1818 + if (!_pixman_bits_image_init (image, format, width, height, bits, 1.1819 + rowstride_bytes / (int) sizeof (uint32_t), 1.1820 + clear)) 1.1821 + { 1.1822 + free (image); 1.1823 + return NULL; 1.1824 + } 1.1825 + 1.1826 + return image; 1.1827 +} 1.1828 + 1.1829 +/* If bits is NULL, a buffer will be allocated and initialized to 0 */ 1.1830 +PIXMAN_EXPORT pixman_image_t * 1.1831 +pixman_image_create_bits (pixman_format_code_t format, 1.1832 + int width, 1.1833 + int height, 1.1834 + uint32_t * bits, 1.1835 + int rowstride_bytes) 1.1836 +{ 1.1837 + return create_bits_image_internal ( 1.1838 + format, width, height, bits, rowstride_bytes, TRUE); 1.1839 +} 1.1840 + 1.1841 + 1.1842 +/* If bits is NULL, a buffer will be allocated and _not_ initialized */ 1.1843 +PIXMAN_EXPORT pixman_image_t * 1.1844 +pixman_image_create_bits_no_clear (pixman_format_code_t format, 1.1845 + int width, 1.1846 + int height, 1.1847 + uint32_t * bits, 1.1848 + int rowstride_bytes) 1.1849 +{ 1.1850 + return create_bits_image_internal ( 1.1851 + format, width, height, bits, rowstride_bytes, FALSE); 1.1852 +}