gfx/cairo/libpixman/src/pixman-bits-image.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /*
michael@0 2 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
michael@0 3 * 2005 Lars Knoll & Zack Rusin, Trolltech
michael@0 4 * 2008 Aaron Plattner, NVIDIA Corporation
michael@0 5 * Copyright © 2000 SuSE, Inc.
michael@0 6 * Copyright © 2007, 2009 Red Hat, Inc.
michael@0 7 * Copyright © 2008 André Tupinambá <andrelrt@gmail.com>
michael@0 8 *
michael@0 9 * Permission to use, copy, modify, distribute, and sell this software and its
michael@0 10 * documentation for any purpose is hereby granted without fee, provided that
michael@0 11 * the above copyright notice appear in all copies and that both that
michael@0 12 * copyright notice and this permission notice appear in supporting
michael@0 13 * documentation, and that the name of Keith Packard not be used in
michael@0 14 * advertising or publicity pertaining to distribution of the software without
michael@0 15 * specific, written prior permission. Keith Packard makes no
michael@0 16 * representations about the suitability of this software for any purpose. It
michael@0 17 * is provided "as is" without express or implied warranty.
michael@0 18 *
michael@0 19 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
michael@0 20 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
michael@0 21 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
michael@0 22 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
michael@0 23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
michael@0 24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
michael@0 25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
michael@0 26 * SOFTWARE.
michael@0 27 */
michael@0 28
michael@0 29 #ifdef HAVE_CONFIG_H
michael@0 30 #include <config.h>
michael@0 31 #endif
michael@0 32 #include <stdio.h>
michael@0 33 #include <stdlib.h>
michael@0 34 #include <string.h>
michael@0 35 #include "pixman-private.h"
michael@0 36 #include "pixman-combine32.h"
michael@0 37 #include "pixman-inlines.h"
michael@0 38
michael@0 39 static uint32_t *
michael@0 40 _pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
michael@0 41 const uint32_t *mask)
michael@0 42 {
michael@0 43 pixman_iter_get_scanline_t fetch_32 = iter->data;
michael@0 44 uint32_t *buffer = iter->buffer;
michael@0 45
michael@0 46 fetch_32 (iter, NULL);
michael@0 47
michael@0 48 pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
michael@0 49
michael@0 50 return iter->buffer;
michael@0 51 }
michael@0 52
michael@0 53 /* Fetch functions */
michael@0 54
michael@0 55 static force_inline uint32_t
michael@0 56 fetch_pixel_no_alpha (bits_image_t *image,
michael@0 57 int x, int y, pixman_bool_t check_bounds)
michael@0 58 {
michael@0 59 if (check_bounds &&
michael@0 60 (x < 0 || x >= image->width || y < 0 || y >= image->height))
michael@0 61 {
michael@0 62 return 0;
michael@0 63 }
michael@0 64
michael@0 65 return image->fetch_pixel_32 (image, x, y);
michael@0 66 }
michael@0 67
michael@0 68 typedef uint32_t (* get_pixel_t) (bits_image_t *image,
michael@0 69 int x, int y, pixman_bool_t check_bounds);
michael@0 70
michael@0 71 static force_inline uint32_t
michael@0 72 bits_image_fetch_pixel_nearest (bits_image_t *image,
michael@0 73 pixman_fixed_t x,
michael@0 74 pixman_fixed_t y,
michael@0 75 get_pixel_t get_pixel)
michael@0 76 {
michael@0 77 int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
michael@0 78 int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
michael@0 79
michael@0 80 if (image->common.repeat != PIXMAN_REPEAT_NONE)
michael@0 81 {
michael@0 82 repeat (image->common.repeat, &x0, image->width);
michael@0 83 repeat (image->common.repeat, &y0, image->height);
michael@0 84
michael@0 85 return get_pixel (image, x0, y0, FALSE);
michael@0 86 }
michael@0 87 else
michael@0 88 {
michael@0 89 return get_pixel (image, x0, y0, TRUE);
michael@0 90 }
michael@0 91 }
michael@0 92
michael@0 93 static force_inline uint32_t
michael@0 94 bits_image_fetch_pixel_bilinear (bits_image_t *image,
michael@0 95 pixman_fixed_t x,
michael@0 96 pixman_fixed_t y,
michael@0 97 get_pixel_t get_pixel)
michael@0 98 {
michael@0 99 pixman_repeat_t repeat_mode = image->common.repeat;
michael@0 100 int width = image->width;
michael@0 101 int height = image->height;
michael@0 102 int x1, y1, x2, y2;
michael@0 103 uint32_t tl, tr, bl, br;
michael@0 104 int32_t distx, disty;
michael@0 105
michael@0 106 x1 = x - pixman_fixed_1 / 2;
michael@0 107 y1 = y - pixman_fixed_1 / 2;
michael@0 108
michael@0 109 distx = pixman_fixed_to_bilinear_weight (x1);
michael@0 110 disty = pixman_fixed_to_bilinear_weight (y1);
michael@0 111
michael@0 112 x1 = pixman_fixed_to_int (x1);
michael@0 113 y1 = pixman_fixed_to_int (y1);
michael@0 114 x2 = x1 + 1;
michael@0 115 y2 = y1 + 1;
michael@0 116
michael@0 117 if (repeat_mode != PIXMAN_REPEAT_NONE)
michael@0 118 {
michael@0 119 repeat (repeat_mode, &x1, width);
michael@0 120 repeat (repeat_mode, &y1, height);
michael@0 121 repeat (repeat_mode, &x2, width);
michael@0 122 repeat (repeat_mode, &y2, height);
michael@0 123
michael@0 124 tl = get_pixel (image, x1, y1, FALSE);
michael@0 125 bl = get_pixel (image, x1, y2, FALSE);
michael@0 126 tr = get_pixel (image, x2, y1, FALSE);
michael@0 127 br = get_pixel (image, x2, y2, FALSE);
michael@0 128 }
michael@0 129 else
michael@0 130 {
michael@0 131 tl = get_pixel (image, x1, y1, TRUE);
michael@0 132 tr = get_pixel (image, x2, y1, TRUE);
michael@0 133 bl = get_pixel (image, x1, y2, TRUE);
michael@0 134 br = get_pixel (image, x2, y2, TRUE);
michael@0 135 }
michael@0 136
michael@0 137 return bilinear_interpolation (tl, tr, bl, br, distx, disty);
michael@0 138 }
michael@0 139
michael@0 140 static uint32_t *
michael@0 141 bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
michael@0 142 const uint32_t *mask)
michael@0 143 {
michael@0 144
michael@0 145 pixman_image_t * ima = iter->image;
michael@0 146 int offset = iter->x;
michael@0 147 int line = iter->y++;
michael@0 148 int width = iter->width;
michael@0 149 uint32_t * buffer = iter->buffer;
michael@0 150
michael@0 151 bits_image_t *bits = &ima->bits;
michael@0 152 pixman_fixed_t x_top, x_bottom, x;
michael@0 153 pixman_fixed_t ux_top, ux_bottom, ux;
michael@0 154 pixman_vector_t v;
michael@0 155 uint32_t top_mask, bottom_mask;
michael@0 156 uint32_t *top_row;
michael@0 157 uint32_t *bottom_row;
michael@0 158 uint32_t *end;
michael@0 159 uint32_t zero[2] = { 0, 0 };
michael@0 160 uint32_t one = 1;
michael@0 161 int y, y1, y2;
michael@0 162 int disty;
michael@0 163 int mask_inc;
michael@0 164 int w;
michael@0 165
michael@0 166 /* reference point is the center of the pixel */
michael@0 167 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
michael@0 168 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
michael@0 169 v.vector[2] = pixman_fixed_1;
michael@0 170
michael@0 171 if (!pixman_transform_point_3d (bits->common.transform, &v))
michael@0 172 return iter->buffer;
michael@0 173
michael@0 174 ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
michael@0 175 x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
michael@0 176
michael@0 177 y = v.vector[1] - pixman_fixed_1/2;
michael@0 178 disty = pixman_fixed_to_bilinear_weight (y);
michael@0 179
michael@0 180 /* Load the pointers to the first and second lines from the source
michael@0 181 * image that bilinear code must read.
michael@0 182 *
michael@0 183 * The main trick in this code is about the check if any line are
michael@0 184 * outside of the image;
michael@0 185 *
michael@0 186 * When I realize that a line (any one) is outside, I change
michael@0 187 * the pointer to a dummy area with zeros. Once I change this, I
michael@0 188 * must be sure the pointer will not change, so I set the
michael@0 189 * variables to each pointer increments inside the loop.
michael@0 190 */
michael@0 191 y1 = pixman_fixed_to_int (y);
michael@0 192 y2 = y1 + 1;
michael@0 193
michael@0 194 if (y1 < 0 || y1 >= bits->height)
michael@0 195 {
michael@0 196 top_row = zero;
michael@0 197 x_top = 0;
michael@0 198 ux_top = 0;
michael@0 199 }
michael@0 200 else
michael@0 201 {
michael@0 202 top_row = bits->bits + y1 * bits->rowstride;
michael@0 203 x_top = x;
michael@0 204 ux_top = ux;
michael@0 205 }
michael@0 206
michael@0 207 if (y2 < 0 || y2 >= bits->height)
michael@0 208 {
michael@0 209 bottom_row = zero;
michael@0 210 x_bottom = 0;
michael@0 211 ux_bottom = 0;
michael@0 212 }
michael@0 213 else
michael@0 214 {
michael@0 215 bottom_row = bits->bits + y2 * bits->rowstride;
michael@0 216 x_bottom = x;
michael@0 217 ux_bottom = ux;
michael@0 218 }
michael@0 219
michael@0 220 /* Instead of checking whether the operation uses the mast in
michael@0 221 * each loop iteration, verify this only once and prepare the
michael@0 222 * variables to make the code smaller inside the loop.
michael@0 223 */
michael@0 224 if (!mask)
michael@0 225 {
michael@0 226 mask_inc = 0;
michael@0 227 mask = &one;
michael@0 228 }
michael@0 229 else
michael@0 230 {
michael@0 231 /* If have a mask, prepare the variables to check it */
michael@0 232 mask_inc = 1;
michael@0 233 }
michael@0 234
michael@0 235 /* If both are zero, then the whole thing is zero */
michael@0 236 if (top_row == zero && bottom_row == zero)
michael@0 237 {
michael@0 238 memset (buffer, 0, width * sizeof (uint32_t));
michael@0 239 return iter->buffer;
michael@0 240 }
michael@0 241 else if (bits->format == PIXMAN_x8r8g8b8)
michael@0 242 {
michael@0 243 if (top_row == zero)
michael@0 244 {
michael@0 245 top_mask = 0;
michael@0 246 bottom_mask = 0xff000000;
michael@0 247 }
michael@0 248 else if (bottom_row == zero)
michael@0 249 {
michael@0 250 top_mask = 0xff000000;
michael@0 251 bottom_mask = 0;
michael@0 252 }
michael@0 253 else
michael@0 254 {
michael@0 255 top_mask = 0xff000000;
michael@0 256 bottom_mask = 0xff000000;
michael@0 257 }
michael@0 258 }
michael@0 259 else
michael@0 260 {
michael@0 261 top_mask = 0;
michael@0 262 bottom_mask = 0;
michael@0 263 }
michael@0 264
michael@0 265 end = buffer + width;
michael@0 266
michael@0 267 /* Zero fill to the left of the image */
michael@0 268 while (buffer < end && x < pixman_fixed_minus_1)
michael@0 269 {
michael@0 270 *buffer++ = 0;
michael@0 271 x += ux;
michael@0 272 x_top += ux_top;
michael@0 273 x_bottom += ux_bottom;
michael@0 274 mask += mask_inc;
michael@0 275 }
michael@0 276
michael@0 277 /* Left edge
michael@0 278 */
michael@0 279 while (buffer < end && x < 0)
michael@0 280 {
michael@0 281 uint32_t tr, br;
michael@0 282 int32_t distx;
michael@0 283
michael@0 284 tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
michael@0 285 br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
michael@0 286
michael@0 287 distx = pixman_fixed_to_bilinear_weight (x);
michael@0 288
michael@0 289 *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
michael@0 290
michael@0 291 x += ux;
michael@0 292 x_top += ux_top;
michael@0 293 x_bottom += ux_bottom;
michael@0 294 mask += mask_inc;
michael@0 295 }
michael@0 296
michael@0 297 /* Main part */
michael@0 298 w = pixman_int_to_fixed (bits->width - 1);
michael@0 299
michael@0 300 while (buffer < end && x < w)
michael@0 301 {
michael@0 302 if (*mask)
michael@0 303 {
michael@0 304 uint32_t tl, tr, bl, br;
michael@0 305 int32_t distx;
michael@0 306
michael@0 307 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
michael@0 308 tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
michael@0 309 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
michael@0 310 br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
michael@0 311
michael@0 312 distx = pixman_fixed_to_bilinear_weight (x);
michael@0 313
michael@0 314 *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
michael@0 315 }
michael@0 316
michael@0 317 buffer++;
michael@0 318 x += ux;
michael@0 319 x_top += ux_top;
michael@0 320 x_bottom += ux_bottom;
michael@0 321 mask += mask_inc;
michael@0 322 }
michael@0 323
michael@0 324 /* Right Edge */
michael@0 325 w = pixman_int_to_fixed (bits->width);
michael@0 326 while (buffer < end && x < w)
michael@0 327 {
michael@0 328 if (*mask)
michael@0 329 {
michael@0 330 uint32_t tl, bl;
michael@0 331 int32_t distx;
michael@0 332
michael@0 333 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
michael@0 334 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
michael@0 335
michael@0 336 distx = pixman_fixed_to_bilinear_weight (x);
michael@0 337
michael@0 338 *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
michael@0 339 }
michael@0 340
michael@0 341 buffer++;
michael@0 342 x += ux;
michael@0 343 x_top += ux_top;
michael@0 344 x_bottom += ux_bottom;
michael@0 345 mask += mask_inc;
michael@0 346 }
michael@0 347
michael@0 348 /* Zero fill to the left of the image */
michael@0 349 while (buffer < end)
michael@0 350 *buffer++ = 0;
michael@0 351
michael@0 352 return iter->buffer;
michael@0 353 }
michael@0 354
michael@0 355 static force_inline uint32_t
michael@0 356 bits_image_fetch_pixel_convolution (bits_image_t *image,
michael@0 357 pixman_fixed_t x,
michael@0 358 pixman_fixed_t y,
michael@0 359 get_pixel_t get_pixel)
michael@0 360 {
michael@0 361 pixman_fixed_t *params = image->common.filter_params;
michael@0 362 int x_off = (params[0] - pixman_fixed_1) >> 1;
michael@0 363 int y_off = (params[1] - pixman_fixed_1) >> 1;
michael@0 364 int32_t cwidth = pixman_fixed_to_int (params[0]);
michael@0 365 int32_t cheight = pixman_fixed_to_int (params[1]);
michael@0 366 int32_t i, j, x1, x2, y1, y2;
michael@0 367 pixman_repeat_t repeat_mode = image->common.repeat;
michael@0 368 int width = image->width;
michael@0 369 int height = image->height;
michael@0 370 int srtot, sgtot, sbtot, satot;
michael@0 371
michael@0 372 params += 2;
michael@0 373
michael@0 374 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
michael@0 375 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
michael@0 376 x2 = x1 + cwidth;
michael@0 377 y2 = y1 + cheight;
michael@0 378
michael@0 379 srtot = sgtot = sbtot = satot = 0;
michael@0 380
michael@0 381 for (i = y1; i < y2; ++i)
michael@0 382 {
michael@0 383 for (j = x1; j < x2; ++j)
michael@0 384 {
michael@0 385 int rx = j;
michael@0 386 int ry = i;
michael@0 387
michael@0 388 pixman_fixed_t f = *params;
michael@0 389
michael@0 390 if (f)
michael@0 391 {
michael@0 392 uint32_t pixel;
michael@0 393
michael@0 394 if (repeat_mode != PIXMAN_REPEAT_NONE)
michael@0 395 {
michael@0 396 repeat (repeat_mode, &rx, width);
michael@0 397 repeat (repeat_mode, &ry, height);
michael@0 398
michael@0 399 pixel = get_pixel (image, rx, ry, FALSE);
michael@0 400 }
michael@0 401 else
michael@0 402 {
michael@0 403 pixel = get_pixel (image, rx, ry, TRUE);
michael@0 404 }
michael@0 405
michael@0 406 srtot += (int)RED_8 (pixel) * f;
michael@0 407 sgtot += (int)GREEN_8 (pixel) * f;
michael@0 408 sbtot += (int)BLUE_8 (pixel) * f;
michael@0 409 satot += (int)ALPHA_8 (pixel) * f;
michael@0 410 }
michael@0 411
michael@0 412 params++;
michael@0 413 }
michael@0 414 }
michael@0 415
michael@0 416 satot = (satot + 0x8000) >> 16;
michael@0 417 srtot = (srtot + 0x8000) >> 16;
michael@0 418 sgtot = (sgtot + 0x8000) >> 16;
michael@0 419 sbtot = (sbtot + 0x8000) >> 16;
michael@0 420
michael@0 421 satot = CLIP (satot, 0, 0xff);
michael@0 422 srtot = CLIP (srtot, 0, 0xff);
michael@0 423 sgtot = CLIP (sgtot, 0, 0xff);
michael@0 424 sbtot = CLIP (sbtot, 0, 0xff);
michael@0 425
michael@0 426 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
michael@0 427 }
michael@0 428
michael@0 429 static uint32_t
michael@0 430 bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
michael@0 431 pixman_fixed_t x,
michael@0 432 pixman_fixed_t y,
michael@0 433 get_pixel_t get_pixel)
michael@0 434 {
michael@0 435 pixman_fixed_t *params = image->common.filter_params;
michael@0 436 pixman_repeat_t repeat_mode = image->common.repeat;
michael@0 437 int width = image->width;
michael@0 438 int height = image->height;
michael@0 439 int cwidth = pixman_fixed_to_int (params[0]);
michael@0 440 int cheight = pixman_fixed_to_int (params[1]);
michael@0 441 int x_phase_bits = pixman_fixed_to_int (params[2]);
michael@0 442 int y_phase_bits = pixman_fixed_to_int (params[3]);
michael@0 443 int x_phase_shift = 16 - x_phase_bits;
michael@0 444 int y_phase_shift = 16 - y_phase_bits;
michael@0 445 int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
michael@0 446 int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
michael@0 447 pixman_fixed_t *y_params;
michael@0 448 int srtot, sgtot, sbtot, satot;
michael@0 449 int32_t x1, x2, y1, y2;
michael@0 450 int32_t px, py;
michael@0 451 int i, j;
michael@0 452
michael@0 453 /* Round x and y to the middle of the closest phase before continuing. This
michael@0 454 * ensures that the convolution matrix is aligned right, since it was
michael@0 455 * positioned relative to a particular phase (and not relative to whatever
michael@0 456 * exact fraction we happen to get here).
michael@0 457 */
michael@0 458 x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
michael@0 459 y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
michael@0 460
michael@0 461 px = (x & 0xffff) >> x_phase_shift;
michael@0 462 py = (y & 0xffff) >> y_phase_shift;
michael@0 463
michael@0 464 y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
michael@0 465
michael@0 466 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
michael@0 467 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
michael@0 468 x2 = x1 + cwidth;
michael@0 469 y2 = y1 + cheight;
michael@0 470
michael@0 471 srtot = sgtot = sbtot = satot = 0;
michael@0 472
michael@0 473 for (i = y1; i < y2; ++i)
michael@0 474 {
michael@0 475 pixman_fixed_48_16_t fy = *y_params++;
michael@0 476 pixman_fixed_t *x_params = params + 4 + px * cwidth;
michael@0 477
michael@0 478 if (fy)
michael@0 479 {
michael@0 480 for (j = x1; j < x2; ++j)
michael@0 481 {
michael@0 482 pixman_fixed_t fx = *x_params++;
michael@0 483 int rx = j;
michael@0 484 int ry = i;
michael@0 485
michael@0 486 if (fx)
michael@0 487 {
michael@0 488 pixman_fixed_t f;
michael@0 489 uint32_t pixel;
michael@0 490
michael@0 491 if (repeat_mode != PIXMAN_REPEAT_NONE)
michael@0 492 {
michael@0 493 repeat (repeat_mode, &rx, width);
michael@0 494 repeat (repeat_mode, &ry, height);
michael@0 495
michael@0 496 pixel = get_pixel (image, rx, ry, FALSE);
michael@0 497 }
michael@0 498 else
michael@0 499 {
michael@0 500 pixel = get_pixel (image, rx, ry, TRUE);
michael@0 501 }
michael@0 502
michael@0 503 f = (fy * fx + 0x8000) >> 16;
michael@0 504
michael@0 505 srtot += (int)RED_8 (pixel) * f;
michael@0 506 sgtot += (int)GREEN_8 (pixel) * f;
michael@0 507 sbtot += (int)BLUE_8 (pixel) * f;
michael@0 508 satot += (int)ALPHA_8 (pixel) * f;
michael@0 509 }
michael@0 510 }
michael@0 511 }
michael@0 512 }
michael@0 513
michael@0 514 satot = (satot + 0x8000) >> 16;
michael@0 515 srtot = (srtot + 0x8000) >> 16;
michael@0 516 sgtot = (sgtot + 0x8000) >> 16;
michael@0 517 sbtot = (sbtot + 0x8000) >> 16;
michael@0 518
michael@0 519 satot = CLIP (satot, 0, 0xff);
michael@0 520 srtot = CLIP (srtot, 0, 0xff);
michael@0 521 sgtot = CLIP (sgtot, 0, 0xff);
michael@0 522 sbtot = CLIP (sbtot, 0, 0xff);
michael@0 523
michael@0 524 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
michael@0 525 }
michael@0 526
michael@0 527 static force_inline uint32_t
michael@0 528 bits_image_fetch_pixel_filtered (bits_image_t *image,
michael@0 529 pixman_fixed_t x,
michael@0 530 pixman_fixed_t y,
michael@0 531 get_pixel_t get_pixel)
michael@0 532 {
michael@0 533 switch (image->common.filter)
michael@0 534 {
michael@0 535 case PIXMAN_FILTER_NEAREST:
michael@0 536 case PIXMAN_FILTER_FAST:
michael@0 537 return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
michael@0 538 break;
michael@0 539
michael@0 540 case PIXMAN_FILTER_BILINEAR:
michael@0 541 case PIXMAN_FILTER_GOOD:
michael@0 542 case PIXMAN_FILTER_BEST:
michael@0 543 return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
michael@0 544 break;
michael@0 545
michael@0 546 case PIXMAN_FILTER_CONVOLUTION:
michael@0 547 return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
michael@0 548 break;
michael@0 549
michael@0 550 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
michael@0 551 return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
michael@0 552 break;
michael@0 553
michael@0 554 default:
michael@0 555 break;
michael@0 556 }
michael@0 557
michael@0 558 return 0;
michael@0 559 }
michael@0 560
michael@0 561 static uint32_t *
michael@0 562 bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
michael@0 563 const uint32_t * mask)
michael@0 564 {
michael@0 565 pixman_image_t *image = iter->image;
michael@0 566 int offset = iter->x;
michael@0 567 int line = iter->y++;
michael@0 568 int width = iter->width;
michael@0 569 uint32_t * buffer = iter->buffer;
michael@0 570
michael@0 571 pixman_fixed_t x, y;
michael@0 572 pixman_fixed_t ux, uy;
michael@0 573 pixman_vector_t v;
michael@0 574 int i;
michael@0 575
michael@0 576 /* reference point is the center of the pixel */
michael@0 577 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
michael@0 578 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
michael@0 579 v.vector[2] = pixman_fixed_1;
michael@0 580
michael@0 581 if (image->common.transform)
michael@0 582 {
michael@0 583 if (!pixman_transform_point_3d (image->common.transform, &v))
michael@0 584 return iter->buffer;
michael@0 585
michael@0 586 ux = image->common.transform->matrix[0][0];
michael@0 587 uy = image->common.transform->matrix[1][0];
michael@0 588 }
michael@0 589 else
michael@0 590 {
michael@0 591 ux = pixman_fixed_1;
michael@0 592 uy = 0;
michael@0 593 }
michael@0 594
michael@0 595 x = v.vector[0];
michael@0 596 y = v.vector[1];
michael@0 597
michael@0 598 for (i = 0; i < width; ++i)
michael@0 599 {
michael@0 600 if (!mask || mask[i])
michael@0 601 {
michael@0 602 buffer[i] = bits_image_fetch_pixel_filtered (
michael@0 603 &image->bits, x, y, fetch_pixel_no_alpha);
michael@0 604 }
michael@0 605
michael@0 606 x += ux;
michael@0 607 y += uy;
michael@0 608 }
michael@0 609
michael@0 610 return buffer;
michael@0 611 }
michael@0 612
michael@0 613 /* General fetcher */
michael@0 614 static force_inline uint32_t
michael@0 615 fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
michael@0 616 {
michael@0 617 uint32_t pixel;
michael@0 618
michael@0 619 if (check_bounds &&
michael@0 620 (x < 0 || x >= image->width || y < 0 || y >= image->height))
michael@0 621 {
michael@0 622 return 0;
michael@0 623 }
michael@0 624
michael@0 625 pixel = image->fetch_pixel_32 (image, x, y);
michael@0 626
michael@0 627 if (image->common.alpha_map)
michael@0 628 {
michael@0 629 uint32_t pixel_a;
michael@0 630
michael@0 631 x -= image->common.alpha_origin_x;
michael@0 632 y -= image->common.alpha_origin_y;
michael@0 633
michael@0 634 if (x < 0 || x >= image->common.alpha_map->width ||
michael@0 635 y < 0 || y >= image->common.alpha_map->height)
michael@0 636 {
michael@0 637 pixel_a = 0;
michael@0 638 }
michael@0 639 else
michael@0 640 {
michael@0 641 pixel_a = image->common.alpha_map->fetch_pixel_32 (
michael@0 642 image->common.alpha_map, x, y);
michael@0 643
michael@0 644 pixel_a = ALPHA_8 (pixel_a);
michael@0 645 }
michael@0 646
michael@0 647 pixel &= 0x00ffffff;
michael@0 648 pixel |= (pixel_a << 24);
michael@0 649 }
michael@0 650
michael@0 651 return pixel;
michael@0 652 }
michael@0 653
michael@0 654 static uint32_t *
michael@0 655 bits_image_fetch_general (pixman_iter_t *iter,
michael@0 656 const uint32_t *mask)
michael@0 657 {
michael@0 658 pixman_image_t *image = iter->image;
michael@0 659 int offset = iter->x;
michael@0 660 int line = iter->y++;
michael@0 661 int width = iter->width;
michael@0 662 uint32_t * buffer = iter->buffer;
michael@0 663
michael@0 664 pixman_fixed_t x, y, w;
michael@0 665 pixman_fixed_t ux, uy, uw;
michael@0 666 pixman_vector_t v;
michael@0 667 int i;
michael@0 668
michael@0 669 /* reference point is the center of the pixel */
michael@0 670 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
michael@0 671 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
michael@0 672 v.vector[2] = pixman_fixed_1;
michael@0 673
michael@0 674 if (image->common.transform)
michael@0 675 {
michael@0 676 if (!pixman_transform_point_3d (image->common.transform, &v))
michael@0 677 return buffer;
michael@0 678
michael@0 679 ux = image->common.transform->matrix[0][0];
michael@0 680 uy = image->common.transform->matrix[1][0];
michael@0 681 uw = image->common.transform->matrix[2][0];
michael@0 682 }
michael@0 683 else
michael@0 684 {
michael@0 685 ux = pixman_fixed_1;
michael@0 686 uy = 0;
michael@0 687 uw = 0;
michael@0 688 }
michael@0 689
michael@0 690 x = v.vector[0];
michael@0 691 y = v.vector[1];
michael@0 692 w = v.vector[2];
michael@0 693
michael@0 694 for (i = 0; i < width; ++i)
michael@0 695 {
michael@0 696 pixman_fixed_t x0, y0;
michael@0 697
michael@0 698 if (!mask || mask[i])
michael@0 699 {
michael@0 700 if (w != 0)
michael@0 701 {
michael@0 702 x0 = ((pixman_fixed_48_16_t)x << 16) / w;
michael@0 703 y0 = ((pixman_fixed_48_16_t)y << 16) / w;
michael@0 704 }
michael@0 705 else
michael@0 706 {
michael@0 707 x0 = 0;
michael@0 708 y0 = 0;
michael@0 709 }
michael@0 710
michael@0 711 buffer[i] = bits_image_fetch_pixel_filtered (
michael@0 712 &image->bits, x0, y0, fetch_pixel_general);
michael@0 713 }
michael@0 714
michael@0 715 x += ux;
michael@0 716 y += uy;
michael@0 717 w += uw;
michael@0 718 }
michael@0 719
michael@0 720 return buffer;
michael@0 721 }
michael@0 722
michael@0 723 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
michael@0 724
michael@0 725 static force_inline void
michael@0 726 bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
michael@0 727 int offset,
michael@0 728 int line,
michael@0 729 int width,
michael@0 730 uint32_t * buffer,
michael@0 731 const uint32_t * mask,
michael@0 732
michael@0 733 convert_pixel_t convert_pixel,
michael@0 734 pixman_format_code_t format,
michael@0 735 pixman_repeat_t repeat_mode)
michael@0 736 {
michael@0 737 bits_image_t *bits = &image->bits;
michael@0 738 pixman_fixed_t *params = image->common.filter_params;
michael@0 739 int cwidth = pixman_fixed_to_int (params[0]);
michael@0 740 int cheight = pixman_fixed_to_int (params[1]);
michael@0 741 int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
michael@0 742 int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
michael@0 743 int x_phase_bits = pixman_fixed_to_int (params[2]);
michael@0 744 int y_phase_bits = pixman_fixed_to_int (params[3]);
michael@0 745 int x_phase_shift = 16 - x_phase_bits;
michael@0 746 int y_phase_shift = 16 - y_phase_bits;
michael@0 747 pixman_fixed_t vx, vy;
michael@0 748 pixman_fixed_t ux, uy;
michael@0 749 pixman_vector_t v;
michael@0 750 int k;
michael@0 751
michael@0 752 /* reference point is the center of the pixel */
michael@0 753 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
michael@0 754 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
michael@0 755 v.vector[2] = pixman_fixed_1;
michael@0 756
michael@0 757 if (!pixman_transform_point_3d (image->common.transform, &v))
michael@0 758 return;
michael@0 759
michael@0 760 ux = image->common.transform->matrix[0][0];
michael@0 761 uy = image->common.transform->matrix[1][0];
michael@0 762
michael@0 763 vx = v.vector[0];
michael@0 764 vy = v.vector[1];
michael@0 765
michael@0 766 for (k = 0; k < width; ++k)
michael@0 767 {
michael@0 768 pixman_fixed_t *y_params;
michael@0 769 int satot, srtot, sgtot, sbtot;
michael@0 770 pixman_fixed_t x, y;
michael@0 771 int32_t x1, x2, y1, y2;
michael@0 772 int32_t px, py;
michael@0 773 int i, j;
michael@0 774
michael@0 775 if (mask && !mask[k])
michael@0 776 goto next;
michael@0 777
michael@0 778 /* Round x and y to the middle of the closest phase before continuing. This
michael@0 779 * ensures that the convolution matrix is aligned right, since it was
michael@0 780 * positioned relative to a particular phase (and not relative to whatever
michael@0 781 * exact fraction we happen to get here).
michael@0 782 */
michael@0 783 x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
michael@0 784 y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
michael@0 785
michael@0 786 px = (x & 0xffff) >> x_phase_shift;
michael@0 787 py = (y & 0xffff) >> y_phase_shift;
michael@0 788
michael@0 789 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
michael@0 790 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
michael@0 791 x2 = x1 + cwidth;
michael@0 792 y2 = y1 + cheight;
michael@0 793
michael@0 794 satot = srtot = sgtot = sbtot = 0;
michael@0 795
michael@0 796 y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
michael@0 797
michael@0 798 for (i = y1; i < y2; ++i)
michael@0 799 {
michael@0 800 pixman_fixed_t fy = *y_params++;
michael@0 801
michael@0 802 if (fy)
michael@0 803 {
michael@0 804 pixman_fixed_t *x_params = params + 4 + px * cwidth;
michael@0 805
michael@0 806 for (j = x1; j < x2; ++j)
michael@0 807 {
michael@0 808 pixman_fixed_t fx = *x_params++;
michael@0 809 int rx = j;
michael@0 810 int ry = i;
michael@0 811
michael@0 812 if (fx)
michael@0 813 {
michael@0 814 pixman_fixed_t f;
michael@0 815 uint32_t pixel, mask;
michael@0 816 uint8_t *row;
michael@0 817
michael@0 818 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
michael@0 819
michael@0 820 if (repeat_mode != PIXMAN_REPEAT_NONE)
michael@0 821 {
michael@0 822 repeat (repeat_mode, &rx, bits->width);
michael@0 823 repeat (repeat_mode, &ry, bits->height);
michael@0 824
michael@0 825 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
michael@0 826 pixel = convert_pixel (row, rx) | mask;
michael@0 827 }
michael@0 828 else
michael@0 829 {
michael@0 830 if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
michael@0 831 {
michael@0 832 pixel = 0;
michael@0 833 }
michael@0 834 else
michael@0 835 {
michael@0 836 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
michael@0 837 pixel = convert_pixel (row, rx) | mask;
michael@0 838 }
michael@0 839 }
michael@0 840
michael@0 841 f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
michael@0 842 srtot += (int)RED_8 (pixel) * f;
michael@0 843 sgtot += (int)GREEN_8 (pixel) * f;
michael@0 844 sbtot += (int)BLUE_8 (pixel) * f;
michael@0 845 satot += (int)ALPHA_8 (pixel) * f;
michael@0 846 }
michael@0 847 }
michael@0 848 }
michael@0 849 }
michael@0 850
michael@0 851 satot = (satot + 0x8000) >> 16;
michael@0 852 srtot = (srtot + 0x8000) >> 16;
michael@0 853 sgtot = (sgtot + 0x8000) >> 16;
michael@0 854 sbtot = (sbtot + 0x8000) >> 16;
michael@0 855
michael@0 856 satot = CLIP (satot, 0, 0xff);
michael@0 857 srtot = CLIP (srtot, 0, 0xff);
michael@0 858 sgtot = CLIP (sgtot, 0, 0xff);
michael@0 859 sbtot = CLIP (sbtot, 0, 0xff);
michael@0 860
michael@0 861 buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
michael@0 862
michael@0 863 next:
michael@0 864 vx += ux;
michael@0 865 vy += uy;
michael@0 866 }
michael@0 867 }
michael@0 868
michael@0 869 static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
michael@0 870
michael@0 871 static force_inline void
michael@0 872 bits_image_fetch_bilinear_affine (pixman_image_t * image,
michael@0 873 int offset,
michael@0 874 int line,
michael@0 875 int width,
michael@0 876 uint32_t * buffer,
michael@0 877 const uint32_t * mask,
michael@0 878
michael@0 879 convert_pixel_t convert_pixel,
michael@0 880 pixman_format_code_t format,
michael@0 881 pixman_repeat_t repeat_mode)
michael@0 882 {
michael@0 883 pixman_fixed_t x, y;
michael@0 884 pixman_fixed_t ux, uy;
michael@0 885 pixman_vector_t v;
michael@0 886 bits_image_t *bits = &image->bits;
michael@0 887 int i;
michael@0 888
michael@0 889 /* reference point is the center of the pixel */
michael@0 890 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
michael@0 891 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
michael@0 892 v.vector[2] = pixman_fixed_1;
michael@0 893
michael@0 894 if (!pixman_transform_point_3d (image->common.transform, &v))
michael@0 895 return;
michael@0 896
michael@0 897 ux = image->common.transform->matrix[0][0];
michael@0 898 uy = image->common.transform->matrix[1][0];
michael@0 899
michael@0 900 x = v.vector[0];
michael@0 901 y = v.vector[1];
michael@0 902
michael@0 903 for (i = 0; i < width; ++i)
michael@0 904 {
michael@0 905 int x1, y1, x2, y2;
michael@0 906 uint32_t tl, tr, bl, br;
michael@0 907 int32_t distx, disty;
michael@0 908 int width = image->bits.width;
michael@0 909 int height = image->bits.height;
michael@0 910 const uint8_t *row1;
michael@0 911 const uint8_t *row2;
michael@0 912
michael@0 913 if (mask && !mask[i])
michael@0 914 goto next;
michael@0 915
michael@0 916 x1 = x - pixman_fixed_1 / 2;
michael@0 917 y1 = y - pixman_fixed_1 / 2;
michael@0 918
michael@0 919 distx = pixman_fixed_to_bilinear_weight (x1);
michael@0 920 disty = pixman_fixed_to_bilinear_weight (y1);
michael@0 921
michael@0 922 y1 = pixman_fixed_to_int (y1);
michael@0 923 y2 = y1 + 1;
michael@0 924 x1 = pixman_fixed_to_int (x1);
michael@0 925 x2 = x1 + 1;
michael@0 926
michael@0 927 if (repeat_mode != PIXMAN_REPEAT_NONE)
michael@0 928 {
michael@0 929 uint32_t mask;
michael@0 930
michael@0 931 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
michael@0 932
michael@0 933 repeat (repeat_mode, &x1, width);
michael@0 934 repeat (repeat_mode, &y1, height);
michael@0 935 repeat (repeat_mode, &x2, width);
michael@0 936 repeat (repeat_mode, &y2, height);
michael@0 937
michael@0 938 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
michael@0 939 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
michael@0 940
michael@0 941 tl = convert_pixel (row1, x1) | mask;
michael@0 942 tr = convert_pixel (row1, x2) | mask;
michael@0 943 bl = convert_pixel (row2, x1) | mask;
michael@0 944 br = convert_pixel (row2, x2) | mask;
michael@0 945 }
michael@0 946 else
michael@0 947 {
michael@0 948 uint32_t mask1, mask2;
michael@0 949 int bpp;
michael@0 950
michael@0 951 /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
michael@0 952 * which means if you use it in expressions, those
michael@0 953 * expressions become unsigned themselves. Since
michael@0 954 * the variables below can be negative in some cases,
michael@0 955 * that will lead to crashes on 64 bit architectures.
michael@0 956 *
michael@0 957 * So this line makes sure bpp is signed
michael@0 958 */
michael@0 959 bpp = PIXMAN_FORMAT_BPP (format);
michael@0 960
michael@0 961 if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
michael@0 962 {
michael@0 963 buffer[i] = 0;
michael@0 964 goto next;
michael@0 965 }
michael@0 966
michael@0 967 if (y2 == 0)
michael@0 968 {
michael@0 969 row1 = zero;
michael@0 970 mask1 = 0;
michael@0 971 }
michael@0 972 else
michael@0 973 {
michael@0 974 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
michael@0 975 row1 += bpp / 8 * x1;
michael@0 976
michael@0 977 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
michael@0 978 }
michael@0 979
michael@0 980 if (y1 == height - 1)
michael@0 981 {
michael@0 982 row2 = zero;
michael@0 983 mask2 = 0;
michael@0 984 }
michael@0 985 else
michael@0 986 {
michael@0 987 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
michael@0 988 row2 += bpp / 8 * x1;
michael@0 989
michael@0 990 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
michael@0 991 }
michael@0 992
michael@0 993 if (x2 == 0)
michael@0 994 {
michael@0 995 tl = 0;
michael@0 996 bl = 0;
michael@0 997 }
michael@0 998 else
michael@0 999 {
michael@0 1000 tl = convert_pixel (row1, 0) | mask1;
michael@0 1001 bl = convert_pixel (row2, 0) | mask2;
michael@0 1002 }
michael@0 1003
michael@0 1004 if (x1 == width - 1)
michael@0 1005 {
michael@0 1006 tr = 0;
michael@0 1007 br = 0;
michael@0 1008 }
michael@0 1009 else
michael@0 1010 {
michael@0 1011 tr = convert_pixel (row1, 1) | mask1;
michael@0 1012 br = convert_pixel (row2, 1) | mask2;
michael@0 1013 }
michael@0 1014 }
michael@0 1015
michael@0 1016 buffer[i] = bilinear_interpolation (
michael@0 1017 tl, tr, bl, br, distx, disty);
michael@0 1018
michael@0 1019 next:
michael@0 1020 x += ux;
michael@0 1021 y += uy;
michael@0 1022 }
michael@0 1023 }
michael@0 1024
michael@0 1025 static force_inline void
michael@0 1026 bits_image_fetch_nearest_affine (pixman_image_t * image,
michael@0 1027 int offset,
michael@0 1028 int line,
michael@0 1029 int width,
michael@0 1030 uint32_t * buffer,
michael@0 1031 const uint32_t * mask,
michael@0 1032
michael@0 1033 convert_pixel_t convert_pixel,
michael@0 1034 pixman_format_code_t format,
michael@0 1035 pixman_repeat_t repeat_mode)
michael@0 1036 {
michael@0 1037 pixman_fixed_t x, y;
michael@0 1038 pixman_fixed_t ux, uy;
michael@0 1039 pixman_vector_t v;
michael@0 1040 bits_image_t *bits = &image->bits;
michael@0 1041 int i;
michael@0 1042
michael@0 1043 /* reference point is the center of the pixel */
michael@0 1044 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
michael@0 1045 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
michael@0 1046 v.vector[2] = pixman_fixed_1;
michael@0 1047
michael@0 1048 if (!pixman_transform_point_3d (image->common.transform, &v))
michael@0 1049 return;
michael@0 1050
michael@0 1051 ux = image->common.transform->matrix[0][0];
michael@0 1052 uy = image->common.transform->matrix[1][0];
michael@0 1053
michael@0 1054 x = v.vector[0];
michael@0 1055 y = v.vector[1];
michael@0 1056
michael@0 1057 for (i = 0; i < width; ++i)
michael@0 1058 {
michael@0 1059 int width, height, x0, y0;
michael@0 1060 const uint8_t *row;
michael@0 1061
michael@0 1062 if (mask && !mask[i])
michael@0 1063 goto next;
michael@0 1064
michael@0 1065 width = image->bits.width;
michael@0 1066 height = image->bits.height;
michael@0 1067 x0 = pixman_fixed_to_int (x - pixman_fixed_e);
michael@0 1068 y0 = pixman_fixed_to_int (y - pixman_fixed_e);
michael@0 1069
michael@0 1070 if (repeat_mode == PIXMAN_REPEAT_NONE &&
michael@0 1071 (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
michael@0 1072 {
michael@0 1073 buffer[i] = 0;
michael@0 1074 }
michael@0 1075 else
michael@0 1076 {
michael@0 1077 uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
michael@0 1078
michael@0 1079 if (repeat_mode != PIXMAN_REPEAT_NONE)
michael@0 1080 {
michael@0 1081 repeat (repeat_mode, &x0, width);
michael@0 1082 repeat (repeat_mode, &y0, height);
michael@0 1083 }
michael@0 1084
michael@0 1085 row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
michael@0 1086
michael@0 1087 buffer[i] = convert_pixel (row, x0) | mask;
michael@0 1088 }
michael@0 1089
michael@0 1090 next:
michael@0 1091 x += ux;
michael@0 1092 y += uy;
michael@0 1093 }
michael@0 1094 }
michael@0 1095
michael@0 1096 static force_inline uint32_t
michael@0 1097 convert_a8r8g8b8 (const uint8_t *row, int x)
michael@0 1098 {
michael@0 1099 return *(((uint32_t *)row) + x);
michael@0 1100 }
michael@0 1101
michael@0 1102 static force_inline uint32_t
michael@0 1103 convert_x8r8g8b8 (const uint8_t *row, int x)
michael@0 1104 {
michael@0 1105 return *(((uint32_t *)row) + x);
michael@0 1106 }
michael@0 1107
michael@0 1108 static force_inline uint32_t
michael@0 1109 convert_a8 (const uint8_t *row, int x)
michael@0 1110 {
michael@0 1111 return *(row + x) << 24;
michael@0 1112 }
michael@0 1113
michael@0 1114 static force_inline uint32_t
michael@0 1115 convert_r5g6b5 (const uint8_t *row, int x)
michael@0 1116 {
michael@0 1117 return convert_0565_to_0888 (*((uint16_t *)row + x));
michael@0 1118 }
michael@0 1119
michael@0 1120 #define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \
michael@0 1121 static uint32_t * \
michael@0 1122 bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \
michael@0 1123 const uint32_t * mask) \
michael@0 1124 { \
michael@0 1125 bits_image_fetch_separable_convolution_affine ( \
michael@0 1126 iter->image, \
michael@0 1127 iter->x, iter->y++, \
michael@0 1128 iter->width, \
michael@0 1129 iter->buffer, mask, \
michael@0 1130 convert_ ## format, \
michael@0 1131 PIXMAN_ ## format, \
michael@0 1132 repeat_mode); \
michael@0 1133 \
michael@0 1134 return iter->buffer; \
michael@0 1135 }
michael@0 1136
michael@0 1137 #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \
michael@0 1138 static uint32_t * \
michael@0 1139 bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \
michael@0 1140 const uint32_t * mask) \
michael@0 1141 { \
michael@0 1142 bits_image_fetch_bilinear_affine (iter->image, \
michael@0 1143 iter->x, iter->y++, \
michael@0 1144 iter->width, \
michael@0 1145 iter->buffer, mask, \
michael@0 1146 convert_ ## format, \
michael@0 1147 PIXMAN_ ## format, \
michael@0 1148 repeat_mode); \
michael@0 1149 return iter->buffer; \
michael@0 1150 }
michael@0 1151
michael@0 1152 #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \
michael@0 1153 static uint32_t * \
michael@0 1154 bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \
michael@0 1155 const uint32_t * mask) \
michael@0 1156 { \
michael@0 1157 bits_image_fetch_nearest_affine (iter->image, \
michael@0 1158 iter->x, iter->y++, \
michael@0 1159 iter->width, \
michael@0 1160 iter->buffer, mask, \
michael@0 1161 convert_ ## format, \
michael@0 1162 PIXMAN_ ## format, \
michael@0 1163 repeat_mode); \
michael@0 1164 return iter->buffer; \
michael@0 1165 }
michael@0 1166
michael@0 1167 #define MAKE_FETCHERS(name, format, repeat_mode) \
michael@0 1168 MAKE_NEAREST_FETCHER (name, format, repeat_mode) \
michael@0 1169 MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \
michael@0 1170 MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
michael@0 1171
michael@0 1172 MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
michael@0 1173 MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
michael@0 1174 MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
michael@0 1175 MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL)
michael@0 1176 MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD)
michael@0 1177 MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE)
michael@0 1178 MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
michael@0 1179 MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL)
michael@0 1180 MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD)
michael@0 1181 MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE)
michael@0 1182 MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT)
michael@0 1183 MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL)
michael@0 1184 MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD)
michael@0 1185 MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE)
michael@0 1186 MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
michael@0 1187 MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
michael@0 1188
michael@0 1189 static void
michael@0 1190 replicate_pixel_32 (bits_image_t * bits,
michael@0 1191 int x,
michael@0 1192 int y,
michael@0 1193 int width,
michael@0 1194 uint32_t * buffer)
michael@0 1195 {
michael@0 1196 uint32_t color;
michael@0 1197 uint32_t *end;
michael@0 1198
michael@0 1199 color = bits->fetch_pixel_32 (bits, x, y);
michael@0 1200
michael@0 1201 end = buffer + width;
michael@0 1202 while (buffer < end)
michael@0 1203 *(buffer++) = color;
michael@0 1204 }
michael@0 1205
michael@0 1206 static void
michael@0 1207 replicate_pixel_float (bits_image_t * bits,
michael@0 1208 int x,
michael@0 1209 int y,
michael@0 1210 int width,
michael@0 1211 uint32_t * b)
michael@0 1212 {
michael@0 1213 argb_t color;
michael@0 1214 argb_t *buffer = (argb_t *)b;
michael@0 1215 argb_t *end;
michael@0 1216
michael@0 1217 color = bits->fetch_pixel_float (bits, x, y);
michael@0 1218
michael@0 1219 end = buffer + width;
michael@0 1220 while (buffer < end)
michael@0 1221 *(buffer++) = color;
michael@0 1222 }
michael@0 1223
michael@0 1224 static void
michael@0 1225 bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
michael@0 1226 pixman_bool_t wide,
michael@0 1227 int x,
michael@0 1228 int y,
michael@0 1229 int width,
michael@0 1230 uint32_t * buffer)
michael@0 1231 {
michael@0 1232 uint32_t w;
michael@0 1233
michael@0 1234 if (y < 0 || y >= image->height)
michael@0 1235 {
michael@0 1236 memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
michael@0 1237 return;
michael@0 1238 }
michael@0 1239
michael@0 1240 if (x < 0)
michael@0 1241 {
michael@0 1242 w = MIN (width, -x);
michael@0 1243
michael@0 1244 memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
michael@0 1245
michael@0 1246 width -= w;
michael@0 1247 buffer += w * (wide? 4 : 1);
michael@0 1248 x += w;
michael@0 1249 }
michael@0 1250
michael@0 1251 if (x < image->width)
michael@0 1252 {
michael@0 1253 w = MIN (width, image->width - x);
michael@0 1254
michael@0 1255 if (wide)
michael@0 1256 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
michael@0 1257 else
michael@0 1258 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
michael@0 1259
michael@0 1260 width -= w;
michael@0 1261 buffer += w * (wide? 4 : 1);
michael@0 1262 x += w;
michael@0 1263 }
michael@0 1264
michael@0 1265 memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
michael@0 1266 }
michael@0 1267
michael@0 1268 static void
michael@0 1269 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
michael@0 1270 pixman_bool_t wide,
michael@0 1271 int x,
michael@0 1272 int y,
michael@0 1273 int width,
michael@0 1274 uint32_t * buffer)
michael@0 1275 {
michael@0 1276 uint32_t w;
michael@0 1277
michael@0 1278 while (y < 0)
michael@0 1279 y += image->height;
michael@0 1280
michael@0 1281 while (y >= image->height)
michael@0 1282 y -= image->height;
michael@0 1283
michael@0 1284 if (image->width == 1)
michael@0 1285 {
michael@0 1286 if (wide)
michael@0 1287 replicate_pixel_float (image, 0, y, width, buffer);
michael@0 1288 else
michael@0 1289 replicate_pixel_32 (image, 0, y, width, buffer);
michael@0 1290
michael@0 1291 return;
michael@0 1292 }
michael@0 1293
michael@0 1294 while (width)
michael@0 1295 {
michael@0 1296 while (x < 0)
michael@0 1297 x += image->width;
michael@0 1298 while (x >= image->width)
michael@0 1299 x -= image->width;
michael@0 1300
michael@0 1301 w = MIN (width, image->width - x);
michael@0 1302
michael@0 1303 if (wide)
michael@0 1304 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
michael@0 1305 else
michael@0 1306 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
michael@0 1307
michael@0 1308 buffer += w * (wide? 4 : 1);
michael@0 1309 x += w;
michael@0 1310 width -= w;
michael@0 1311 }
michael@0 1312 }
michael@0 1313
michael@0 1314 static uint32_t *
michael@0 1315 bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
michael@0 1316 const uint32_t *mask)
michael@0 1317 {
michael@0 1318 pixman_image_t *image = iter->image;
michael@0 1319 int x = iter->x;
michael@0 1320 int y = iter->y;
michael@0 1321 int width = iter->width;
michael@0 1322 uint32_t * buffer = iter->buffer;
michael@0 1323
michael@0 1324 if (image->common.repeat == PIXMAN_REPEAT_NONE)
michael@0 1325 {
michael@0 1326 bits_image_fetch_untransformed_repeat_none (
michael@0 1327 &image->bits, FALSE, x, y, width, buffer);
michael@0 1328 }
michael@0 1329 else
michael@0 1330 {
michael@0 1331 bits_image_fetch_untransformed_repeat_normal (
michael@0 1332 &image->bits, FALSE, x, y, width, buffer);
michael@0 1333 }
michael@0 1334
michael@0 1335 iter->y++;
michael@0 1336 return buffer;
michael@0 1337 }
michael@0 1338
michael@0 1339 static uint32_t *
michael@0 1340 bits_image_fetch_untransformed_float (pixman_iter_t * iter,
michael@0 1341 const uint32_t *mask)
michael@0 1342 {
michael@0 1343 pixman_image_t *image = iter->image;
michael@0 1344 int x = iter->x;
michael@0 1345 int y = iter->y;
michael@0 1346 int width = iter->width;
michael@0 1347 uint32_t * buffer = iter->buffer;
michael@0 1348
michael@0 1349 if (image->common.repeat == PIXMAN_REPEAT_NONE)
michael@0 1350 {
michael@0 1351 bits_image_fetch_untransformed_repeat_none (
michael@0 1352 &image->bits, TRUE, x, y, width, buffer);
michael@0 1353 }
michael@0 1354 else
michael@0 1355 {
michael@0 1356 bits_image_fetch_untransformed_repeat_normal (
michael@0 1357 &image->bits, TRUE, x, y, width, buffer);
michael@0 1358 }
michael@0 1359
michael@0 1360 iter->y++;
michael@0 1361 return buffer;
michael@0 1362 }
michael@0 1363
michael@0 1364 typedef struct
michael@0 1365 {
michael@0 1366 pixman_format_code_t format;
michael@0 1367 uint32_t flags;
michael@0 1368 pixman_iter_get_scanline_t get_scanline_32;
michael@0 1369 pixman_iter_get_scanline_t get_scanline_float;
michael@0 1370 } fetcher_info_t;
michael@0 1371
michael@0 1372 static const fetcher_info_t fetcher_info[] =
michael@0 1373 {
michael@0 1374 { PIXMAN_any,
michael@0 1375 (FAST_PATH_NO_ALPHA_MAP |
michael@0 1376 FAST_PATH_ID_TRANSFORM |
michael@0 1377 FAST_PATH_NO_CONVOLUTION_FILTER |
michael@0 1378 FAST_PATH_NO_PAD_REPEAT |
michael@0 1379 FAST_PATH_NO_REFLECT_REPEAT),
michael@0 1380 bits_image_fetch_untransformed_32,
michael@0 1381 bits_image_fetch_untransformed_float
michael@0 1382 },
michael@0 1383
michael@0 1384 #define FAST_BILINEAR_FLAGS \
michael@0 1385 (FAST_PATH_NO_ALPHA_MAP | \
michael@0 1386 FAST_PATH_NO_ACCESSORS | \
michael@0 1387 FAST_PATH_HAS_TRANSFORM | \
michael@0 1388 FAST_PATH_AFFINE_TRANSFORM | \
michael@0 1389 FAST_PATH_X_UNIT_POSITIVE | \
michael@0 1390 FAST_PATH_Y_UNIT_ZERO | \
michael@0 1391 FAST_PATH_NONE_REPEAT | \
michael@0 1392 FAST_PATH_BILINEAR_FILTER)
michael@0 1393
michael@0 1394 { PIXMAN_a8r8g8b8,
michael@0 1395 FAST_BILINEAR_FLAGS,
michael@0 1396 bits_image_fetch_bilinear_no_repeat_8888,
michael@0 1397 _pixman_image_get_scanline_generic_float
michael@0 1398 },
michael@0 1399
michael@0 1400 { PIXMAN_x8r8g8b8,
michael@0 1401 FAST_BILINEAR_FLAGS,
michael@0 1402 bits_image_fetch_bilinear_no_repeat_8888,
michael@0 1403 _pixman_image_get_scanline_generic_float
michael@0 1404 },
michael@0 1405
michael@0 1406 #define GENERAL_BILINEAR_FLAGS \
michael@0 1407 (FAST_PATH_NO_ALPHA_MAP | \
michael@0 1408 FAST_PATH_NO_ACCESSORS | \
michael@0 1409 FAST_PATH_HAS_TRANSFORM | \
michael@0 1410 FAST_PATH_AFFINE_TRANSFORM | \
michael@0 1411 FAST_PATH_BILINEAR_FILTER)
michael@0 1412
michael@0 1413 #define GENERAL_NEAREST_FLAGS \
michael@0 1414 (FAST_PATH_NO_ALPHA_MAP | \
michael@0 1415 FAST_PATH_NO_ACCESSORS | \
michael@0 1416 FAST_PATH_HAS_TRANSFORM | \
michael@0 1417 FAST_PATH_AFFINE_TRANSFORM | \
michael@0 1418 FAST_PATH_NEAREST_FILTER)
michael@0 1419
michael@0 1420 #define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \
michael@0 1421 (FAST_PATH_NO_ALPHA_MAP | \
michael@0 1422 FAST_PATH_NO_ACCESSORS | \
michael@0 1423 FAST_PATH_HAS_TRANSFORM | \
michael@0 1424 FAST_PATH_AFFINE_TRANSFORM | \
michael@0 1425 FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
michael@0 1426
michael@0 1427 #define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
michael@0 1428 { PIXMAN_ ## format, \
michael@0 1429 GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
michael@0 1430 bits_image_fetch_separable_convolution_affine_ ## name, \
michael@0 1431 _pixman_image_get_scanline_generic_float \
michael@0 1432 },
michael@0 1433
michael@0 1434 #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
michael@0 1435 { PIXMAN_ ## format, \
michael@0 1436 GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
michael@0 1437 bits_image_fetch_bilinear_affine_ ## name, \
michael@0 1438 _pixman_image_get_scanline_generic_float \
michael@0 1439 },
michael@0 1440
michael@0 1441 #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \
michael@0 1442 { PIXMAN_ ## format, \
michael@0 1443 GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
michael@0 1444 bits_image_fetch_nearest_affine_ ## name, \
michael@0 1445 _pixman_image_get_scanline_generic_float \
michael@0 1446 },
michael@0 1447
michael@0 1448 #define AFFINE_FAST_PATHS(name, format, repeat) \
michael@0 1449 SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
michael@0 1450 BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
michael@0 1451 NEAREST_AFFINE_FAST_PATH(name, format, repeat)
michael@0 1452
michael@0 1453 AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
michael@0 1454 AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
michael@0 1455 AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
michael@0 1456 AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
michael@0 1457 AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
michael@0 1458 AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
michael@0 1459 AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
michael@0 1460 AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
michael@0 1461 AFFINE_FAST_PATHS (pad_a8, a8, PAD)
michael@0 1462 AFFINE_FAST_PATHS (none_a8, a8, NONE)
michael@0 1463 AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
michael@0 1464 AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
michael@0 1465 AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
michael@0 1466 AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
michael@0 1467 AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
michael@0 1468 AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
michael@0 1469
michael@0 1470 /* Affine, no alpha */
michael@0 1471 { PIXMAN_any,
michael@0 1472 (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
michael@0 1473 bits_image_fetch_affine_no_alpha,
michael@0 1474 _pixman_image_get_scanline_generic_float
michael@0 1475 },
michael@0 1476
michael@0 1477 /* General */
michael@0 1478 { PIXMAN_any,
michael@0 1479 0,
michael@0 1480 bits_image_fetch_general,
michael@0 1481 _pixman_image_get_scanline_generic_float
michael@0 1482 },
michael@0 1483
michael@0 1484 { PIXMAN_null },
michael@0 1485 };
michael@0 1486
michael@0 1487 static void
michael@0 1488 bits_image_property_changed (pixman_image_t *image)
michael@0 1489 {
michael@0 1490 _pixman_bits_image_setup_accessors (&image->bits);
michael@0 1491 }
michael@0 1492
michael@0 1493 void
michael@0 1494 _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
michael@0 1495 {
michael@0 1496 pixman_format_code_t format = image->common.extended_format_code;
michael@0 1497 uint32_t flags = image->common.flags;
michael@0 1498 const fetcher_info_t *info;
michael@0 1499
michael@0 1500 for (info = fetcher_info; info->format != PIXMAN_null; ++info)
michael@0 1501 {
michael@0 1502 if ((info->format == format || info->format == PIXMAN_any) &&
michael@0 1503 (info->flags & flags) == info->flags)
michael@0 1504 {
michael@0 1505 if (iter->iter_flags & ITER_NARROW)
michael@0 1506 {
michael@0 1507 iter->get_scanline = info->get_scanline_32;
michael@0 1508 }
michael@0 1509 else
michael@0 1510 {
michael@0 1511 iter->data = info->get_scanline_32;
michael@0 1512 iter->get_scanline = info->get_scanline_float;
michael@0 1513 }
michael@0 1514 return;
michael@0 1515 }
michael@0 1516 }
michael@0 1517
michael@0 1518 /* Just in case we somehow didn't find a scanline function */
michael@0 1519 iter->get_scanline = _pixman_iter_get_scanline_noop;
michael@0 1520 }
michael@0 1521
michael@0 1522 static uint32_t *
michael@0 1523 dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
michael@0 1524 {
michael@0 1525 pixman_image_t *image = iter->image;
michael@0 1526 int x = iter->x;
michael@0 1527 int y = iter->y;
michael@0 1528 int width = iter->width;
michael@0 1529 uint32_t * buffer = iter->buffer;
michael@0 1530
michael@0 1531 image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask);
michael@0 1532
michael@0 1533 return iter->buffer;
michael@0 1534 }
michael@0 1535
michael@0 1536 static uint32_t *
michael@0 1537 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
michael@0 1538 {
michael@0 1539 pixman_image_t *image = iter->image;
michael@0 1540 int x = iter->x;
michael@0 1541 int y = iter->y;
michael@0 1542 int width = iter->width;
michael@0 1543 uint32_t * buffer = iter->buffer;
michael@0 1544
michael@0 1545 image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
michael@0 1546 if (image->common.alpha_map)
michael@0 1547 {
michael@0 1548 uint32_t *alpha;
michael@0 1549
michael@0 1550 if ((alpha = malloc (width * sizeof (uint32_t))))
michael@0 1551 {
michael@0 1552 int i;
michael@0 1553
michael@0 1554 x -= image->common.alpha_origin_x;
michael@0 1555 y -= image->common.alpha_origin_y;
michael@0 1556
michael@0 1557 image->common.alpha_map->fetch_scanline_32 (
michael@0 1558 (pixman_image_t *)image->common.alpha_map,
michael@0 1559 x, y, width, alpha, mask);
michael@0 1560
michael@0 1561 for (i = 0; i < width; ++i)
michael@0 1562 {
michael@0 1563 buffer[i] &= ~0xff000000;
michael@0 1564 buffer[i] |= (alpha[i] & 0xff000000);
michael@0 1565 }
michael@0 1566
michael@0 1567 free (alpha);
michael@0 1568 }
michael@0 1569 }
michael@0 1570
michael@0 1571 return iter->buffer;
michael@0 1572 }
michael@0 1573
michael@0 1574 static uint32_t *
michael@0 1575 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
michael@0 1576 {
michael@0 1577 bits_image_t * image = &iter->image->bits;
michael@0 1578 int x = iter->x;
michael@0 1579 int y = iter->y;
michael@0 1580 int width = iter->width;
michael@0 1581 argb_t * buffer = (argb_t *)iter->buffer;
michael@0 1582
michael@0 1583 image->fetch_scanline_float (
michael@0 1584 (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
michael@0 1585 if (image->common.alpha_map)
michael@0 1586 {
michael@0 1587 argb_t *alpha;
michael@0 1588
michael@0 1589 if ((alpha = malloc (width * sizeof (argb_t))))
michael@0 1590 {
michael@0 1591 int i;
michael@0 1592
michael@0 1593 x -= image->common.alpha_origin_x;
michael@0 1594 y -= image->common.alpha_origin_y;
michael@0 1595
michael@0 1596 image->common.alpha_map->fetch_scanline_float (
michael@0 1597 (pixman_image_t *)image->common.alpha_map,
michael@0 1598 x, y, width, (uint32_t *)alpha, mask);
michael@0 1599
michael@0 1600 for (i = 0; i < width; ++i)
michael@0 1601 buffer[i].a = alpha[i].a;
michael@0 1602
michael@0 1603 free (alpha);
michael@0 1604 }
michael@0 1605 }
michael@0 1606
michael@0 1607 return iter->buffer;
michael@0 1608 }
michael@0 1609
michael@0 1610 static void
michael@0 1611 dest_write_back_16 (pixman_iter_t *iter)
michael@0 1612 {
michael@0 1613 bits_image_t * image = &iter->image->bits;
michael@0 1614 int x = iter->x;
michael@0 1615 int y = iter->y;
michael@0 1616 int width = iter->width;
michael@0 1617 const uint32_t *buffer = iter->buffer;
michael@0 1618
michael@0 1619 image->store_scanline_16 (image, x, y, width, buffer);
michael@0 1620
michael@0 1621 iter->y++;
michael@0 1622 }
michael@0 1623
michael@0 1624 static void
michael@0 1625 dest_write_back_narrow (pixman_iter_t *iter)
michael@0 1626 {
michael@0 1627 bits_image_t * image = &iter->image->bits;
michael@0 1628 int x = iter->x;
michael@0 1629 int y = iter->y;
michael@0 1630 int width = iter->width;
michael@0 1631 const uint32_t *buffer = iter->buffer;
michael@0 1632
michael@0 1633 image->store_scanline_32 (image, x, y, width, buffer);
michael@0 1634
michael@0 1635 if (image->common.alpha_map)
michael@0 1636 {
michael@0 1637 x -= image->common.alpha_origin_x;
michael@0 1638 y -= image->common.alpha_origin_y;
michael@0 1639
michael@0 1640 image->common.alpha_map->store_scanline_32 (
michael@0 1641 image->common.alpha_map, x, y, width, buffer);
michael@0 1642 }
michael@0 1643
michael@0 1644 iter->y++;
michael@0 1645 }
michael@0 1646
michael@0 1647 static void
michael@0 1648 dest_write_back_wide (pixman_iter_t *iter)
michael@0 1649 {
michael@0 1650 bits_image_t * image = &iter->image->bits;
michael@0 1651 int x = iter->x;
michael@0 1652 int y = iter->y;
michael@0 1653 int width = iter->width;
michael@0 1654 const uint32_t *buffer = iter->buffer;
michael@0 1655
michael@0 1656 image->store_scanline_float (image, x, y, width, buffer);
michael@0 1657
michael@0 1658 if (image->common.alpha_map)
michael@0 1659 {
michael@0 1660 x -= image->common.alpha_origin_x;
michael@0 1661 y -= image->common.alpha_origin_y;
michael@0 1662
michael@0 1663 image->common.alpha_map->store_scanline_float (
michael@0 1664 image->common.alpha_map, x, y, width, buffer);
michael@0 1665 }
michael@0 1666
michael@0 1667 iter->y++;
michael@0 1668 }
michael@0 1669
michael@0 1670 void
michael@0 1671 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
michael@0 1672 {
michael@0 1673 if (iter->iter_flags & ITER_16)
michael@0 1674 {
michael@0 1675 if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
michael@0 1676 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
michael@0 1677 {
michael@0 1678 iter->get_scanline = _pixman_iter_get_scanline_noop;
michael@0 1679 }
michael@0 1680 else
michael@0 1681 {
michael@0 1682 iter->get_scanline = dest_get_scanline_16;
michael@0 1683 }
michael@0 1684 iter->write_back = dest_write_back_16;
michael@0 1685 }
michael@0 1686 else if (iter->iter_flags & ITER_NARROW)
michael@0 1687 {
michael@0 1688 if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
michael@0 1689 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
michael@0 1690 {
michael@0 1691 iter->get_scanline = _pixman_iter_get_scanline_noop;
michael@0 1692 }
michael@0 1693 else
michael@0 1694 {
michael@0 1695 iter->get_scanline = dest_get_scanline_narrow;
michael@0 1696 }
michael@0 1697
michael@0 1698 iter->write_back = dest_write_back_narrow;
michael@0 1699 }
michael@0 1700 else
michael@0 1701 {
michael@0 1702 iter->get_scanline = dest_get_scanline_wide;
michael@0 1703 iter->write_back = dest_write_back_wide;
michael@0 1704 }
michael@0 1705 }
michael@0 1706
michael@0 1707 static uint32_t *
michael@0 1708 create_bits (pixman_format_code_t format,
michael@0 1709 int width,
michael@0 1710 int height,
michael@0 1711 int * rowstride_bytes,
michael@0 1712 pixman_bool_t clear)
michael@0 1713 {
michael@0 1714 int stride;
michael@0 1715 size_t buf_size;
michael@0 1716 int bpp;
michael@0 1717
michael@0 1718 /* what follows is a long-winded way, avoiding any possibility of integer
michael@0 1719 * overflows, of saying:
michael@0 1720 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
michael@0 1721 */
michael@0 1722
michael@0 1723 bpp = PIXMAN_FORMAT_BPP (format);
michael@0 1724 if (_pixman_multiply_overflows_int (width, bpp))
michael@0 1725 return NULL;
michael@0 1726
michael@0 1727 stride = width * bpp;
michael@0 1728 if (_pixman_addition_overflows_int (stride, 0x1f))
michael@0 1729 return NULL;
michael@0 1730
michael@0 1731 stride += 0x1f;
michael@0 1732 stride >>= 5;
michael@0 1733
michael@0 1734 stride *= sizeof (uint32_t);
michael@0 1735
michael@0 1736 if (_pixman_multiply_overflows_size (height, stride))
michael@0 1737 return NULL;
michael@0 1738
michael@0 1739 buf_size = height * stride;
michael@0 1740
michael@0 1741 if (rowstride_bytes)
michael@0 1742 *rowstride_bytes = stride;
michael@0 1743
michael@0 1744 if (clear)
michael@0 1745 return calloc (buf_size, 1);
michael@0 1746 else
michael@0 1747 return malloc (buf_size);
michael@0 1748 }
michael@0 1749
michael@0 1750 pixman_bool_t
michael@0 1751 _pixman_bits_image_init (pixman_image_t * image,
michael@0 1752 pixman_format_code_t format,
michael@0 1753 int width,
michael@0 1754 int height,
michael@0 1755 uint32_t * bits,
michael@0 1756 int rowstride,
michael@0 1757 pixman_bool_t clear)
michael@0 1758 {
michael@0 1759 uint32_t *free_me = NULL;
michael@0 1760
michael@0 1761 if (!bits && width && height)
michael@0 1762 {
michael@0 1763 int rowstride_bytes;
michael@0 1764
michael@0 1765 free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
michael@0 1766
michael@0 1767 if (!bits)
michael@0 1768 return FALSE;
michael@0 1769
michael@0 1770 rowstride = rowstride_bytes / (int) sizeof (uint32_t);
michael@0 1771 }
michael@0 1772
michael@0 1773 _pixman_image_init (image);
michael@0 1774
michael@0 1775 image->type = BITS;
michael@0 1776 image->bits.format = format;
michael@0 1777 image->bits.width = width;
michael@0 1778 image->bits.height = height;
michael@0 1779 image->bits.bits = bits;
michael@0 1780 image->bits.free_me = free_me;
michael@0 1781 image->bits.read_func = NULL;
michael@0 1782 image->bits.write_func = NULL;
michael@0 1783 image->bits.rowstride = rowstride;
michael@0 1784 image->bits.indexed = NULL;
michael@0 1785
michael@0 1786 image->common.property_changed = bits_image_property_changed;
michael@0 1787
michael@0 1788 _pixman_image_reset_clip_region (image);
michael@0 1789
michael@0 1790 return TRUE;
michael@0 1791 }
michael@0 1792
michael@0 1793 static pixman_image_t *
michael@0 1794 create_bits_image_internal (pixman_format_code_t format,
michael@0 1795 int width,
michael@0 1796 int height,
michael@0 1797 uint32_t * bits,
michael@0 1798 int rowstride_bytes,
michael@0 1799 pixman_bool_t clear)
michael@0 1800 {
michael@0 1801 pixman_image_t *image;
michael@0 1802
michael@0 1803 /* must be a whole number of uint32_t's
michael@0 1804 */
michael@0 1805 return_val_if_fail (
michael@0 1806 bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
michael@0 1807
michael@0 1808 return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
michael@0 1809
michael@0 1810 image = _pixman_image_allocate ();
michael@0 1811
michael@0 1812 if (!image)
michael@0 1813 return NULL;
michael@0 1814
michael@0 1815 if (!_pixman_bits_image_init (image, format, width, height, bits,
michael@0 1816 rowstride_bytes / (int) sizeof (uint32_t),
michael@0 1817 clear))
michael@0 1818 {
michael@0 1819 free (image);
michael@0 1820 return NULL;
michael@0 1821 }
michael@0 1822
michael@0 1823 return image;
michael@0 1824 }
michael@0 1825
michael@0 1826 /* If bits is NULL, a buffer will be allocated and initialized to 0 */
michael@0 1827 PIXMAN_EXPORT pixman_image_t *
michael@0 1828 pixman_image_create_bits (pixman_format_code_t format,
michael@0 1829 int width,
michael@0 1830 int height,
michael@0 1831 uint32_t * bits,
michael@0 1832 int rowstride_bytes)
michael@0 1833 {
michael@0 1834 return create_bits_image_internal (
michael@0 1835 format, width, height, bits, rowstride_bytes, TRUE);
michael@0 1836 }
michael@0 1837
michael@0 1838
michael@0 1839 /* If bits is NULL, a buffer will be allocated and _not_ initialized */
michael@0 1840 PIXMAN_EXPORT pixman_image_t *
michael@0 1841 pixman_image_create_bits_no_clear (pixman_format_code_t format,
michael@0 1842 int width,
michael@0 1843 int height,
michael@0 1844 uint32_t * bits,
michael@0 1845 int rowstride_bytes)
michael@0 1846 {
michael@0 1847 return create_bits_image_internal (
michael@0 1848 format, width, height, bits, rowstride_bytes, FALSE);
michael@0 1849 }

mercurial