diff options
Diffstat (limited to 'libs/pixman-0.40.0/pixman/pixman-bits-image.c')
-rw-r--r-- | libs/pixman-0.40.0/pixman/pixman-bits-image.c | 1379 |
1 files changed, 0 insertions, 1379 deletions
diff --git a/libs/pixman-0.40.0/pixman/pixman-bits-image.c b/libs/pixman-0.40.0/pixman/pixman-bits-image.c deleted file mode 100644 index 4cfabe3..0000000 --- a/libs/pixman-0.40.0/pixman/pixman-bits-image.c +++ /dev/null @@ -1,1379 +0,0 @@ -/* - * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. - * 2005 Lars Knoll & Zack Rusin, Trolltech - * 2008 Aaron Plattner, NVIDIA Corporation - * Copyright © 2000 SuSE, Inc. - * Copyright © 2007, 2009 Red Hat, Inc. - * Copyright © 2008 André Tupinambá <andrelrt@gmail.com> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "pixman-private.h" -#include "pixman-combine32.h" -#include "pixman-inlines.h" -#include "dither/blue-noise-64x64.h" - -/* Fetch functions */ - -static force_inline void -fetch_pixel_no_alpha_32 (bits_image_t *image, - int x, int y, pixman_bool_t check_bounds, - void *out) -{ - uint32_t *ret = out; - - if (check_bounds && - (x < 0 || x >= image->width || y < 0 || y >= image->height)) - *ret = 0; - else - *ret = image->fetch_pixel_32 (image, x, y); -} - -static force_inline void -fetch_pixel_no_alpha_float (bits_image_t *image, - int x, int y, pixman_bool_t check_bounds, - void *out) -{ - argb_t *ret = out; - - if (check_bounds && - (x < 0 || x >= image->width || y < 0 || y >= image->height)) - ret->a = ret->r = ret->g = ret->b = 0.f; - else - *ret = image->fetch_pixel_float (image, x, y); -} - -typedef void (* get_pixel_t) (bits_image_t *image, - int x, int y, pixman_bool_t check_bounds, void *out); - -static force_inline void -bits_image_fetch_pixel_nearest (bits_image_t *image, - pixman_fixed_t x, - pixman_fixed_t y, - get_pixel_t get_pixel, - void *out) -{ - int x0 = pixman_fixed_to_int (x - pixman_fixed_e); - int y0 = pixman_fixed_to_int (y - pixman_fixed_e); - - if (image->common.repeat != PIXMAN_REPEAT_NONE) - { - repeat (image->common.repeat, &x0, image->width); - repeat (image->common.repeat, &y0, image->height); - - get_pixel (image, x0, y0, FALSE, out); - } - else - { - get_pixel (image, x0, y0, TRUE, out); - } -} - -static force_inline void -bits_image_fetch_pixel_bilinear_32 (bits_image_t *image, - pixman_fixed_t x, - pixman_fixed_t y, - get_pixel_t get_pixel, - void *out) -{ - pixman_repeat_t repeat_mode = image->common.repeat; - int width = image->width; - int height = image->height; - int x1, y1, x2, y2; - uint32_t tl, tr, bl, br; - int32_t distx, disty; - uint32_t *ret = out; - - x1 = x - pixman_fixed_1 / 2; - y1 = y - pixman_fixed_1 / 2; - - distx = pixman_fixed_to_bilinear_weight (x1); - disty = pixman_fixed_to_bilinear_weight (y1); - - x1 = pixman_fixed_to_int (x1); - y1 = pixman_fixed_to_int (y1); - x2 = x1 + 1; - y2 = y1 + 1; - - if (repeat_mode != PIXMAN_REPEAT_NONE) - { - repeat (repeat_mode, &x1, width); - repeat (repeat_mode, &y1, height); - repeat (repeat_mode, &x2, width); - repeat (repeat_mode, &y2, height); - - get_pixel (image, x1, y1, FALSE, &tl); - get_pixel (image, x2, y1, FALSE, &tr); - get_pixel (image, x1, y2, FALSE, &bl); - get_pixel (image, x2, y2, FALSE, &br); - } - else - { - get_pixel (image, x1, y1, TRUE, &tl); - get_pixel (image, x2, y1, TRUE, &tr); - get_pixel (image, x1, y2, TRUE, &bl); - get_pixel (image, x2, y2, TRUE, &br); - } - - *ret = bilinear_interpolation (tl, tr, bl, br, distx, disty); -} - -static force_inline void -bits_image_fetch_pixel_bilinear_float (bits_image_t *image, - pixman_fixed_t x, - pixman_fixed_t y, - get_pixel_t get_pixel, - void *out) -{ - pixman_repeat_t repeat_mode = image->common.repeat; - int width = image->width; - int height = image->height; - int x1, y1, x2, y2; - argb_t tl, tr, bl, br; - float distx, disty; - argb_t *ret = out; - - x1 = x - pixman_fixed_1 / 2; - y1 = y - pixman_fixed_1 / 2; - - distx = ((float)pixman_fixed_fraction(x1)) / 65536.f; - disty = ((float)pixman_fixed_fraction(y1)) / 65536.f; - - x1 = pixman_fixed_to_int (x1); - y1 = pixman_fixed_to_int (y1); - x2 = x1 + 1; - y2 = y1 + 1; - - if (repeat_mode != PIXMAN_REPEAT_NONE) - { - repeat (repeat_mode, &x1, width); - repeat (repeat_mode, &y1, height); - repeat (repeat_mode, &x2, width); - repeat (repeat_mode, &y2, height); - - get_pixel (image, x1, y1, FALSE, &tl); - get_pixel (image, x2, y1, FALSE, &tr); - get_pixel (image, x1, y2, FALSE, &bl); - get_pixel (image, x2, y2, FALSE, &br); - } - else - { - get_pixel (image, x1, y1, TRUE, &tl); - get_pixel (image, x2, y1, TRUE, &tr); - get_pixel (image, x1, y2, TRUE, &bl); - get_pixel (image, x2, y2, TRUE, &br); - } - - *ret = bilinear_interpolation_float (tl, tr, bl, br, distx, disty); -} - -static force_inline void accum_32(unsigned int *satot, unsigned int *srtot, - unsigned int *sgtot, unsigned int *sbtot, - const void *p, pixman_fixed_t f) -{ - uint32_t pixel = *(uint32_t *)p; - - *srtot += (int)RED_8 (pixel) * f; - *sgtot += (int)GREEN_8 (pixel) * f; - *sbtot += (int)BLUE_8 (pixel) * f; - *satot += (int)ALPHA_8 (pixel) * f; -} - -static force_inline void reduce_32(unsigned int satot, unsigned int srtot, - unsigned int sgtot, unsigned int sbtot, - void *p) -{ - uint32_t *ret = p; - - satot = (satot + 0x8000) >> 16; - srtot = (srtot + 0x8000) >> 16; - sgtot = (sgtot + 0x8000) >> 16; - sbtot = (sbtot + 0x8000) >> 16; - - satot = CLIP (satot, 0, 0xff); - srtot = CLIP (srtot, 0, 0xff); - sgtot = CLIP (sgtot, 0, 0xff); - sbtot = CLIP (sbtot, 0, 0xff); - - *ret = ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); -} - -static force_inline void accum_float(unsigned int *satot, unsigned int *srtot, - unsigned int *sgtot, unsigned int *sbtot, - const void *p, pixman_fixed_t f) -{ - const argb_t *pixel = p; - - *satot += pixel->a * f; - *srtot += pixel->r * f; - *sgtot += pixel->g * f; - *sbtot += pixel->b * f; -} - -static force_inline void reduce_float(unsigned int satot, unsigned int srtot, - unsigned int sgtot, unsigned int sbtot, - void *p) -{ - argb_t *ret = p; - - ret->a = CLIP (satot / 65536.f, 0.f, 1.f); - ret->r = CLIP (srtot / 65536.f, 0.f, 1.f); - ret->g = CLIP (sgtot / 65536.f, 0.f, 1.f); - ret->b = CLIP (sbtot / 65536.f, 0.f, 1.f); -} - -typedef void (* accumulate_pixel_t) (unsigned int *satot, unsigned int *srtot, - unsigned int *sgtot, unsigned int *sbtot, - const void *pixel, pixman_fixed_t f); - -typedef void (* reduce_pixel_t) (unsigned int satot, unsigned int srtot, - unsigned int sgtot, unsigned int sbtot, - void *out); - -static force_inline void -bits_image_fetch_pixel_convolution (bits_image_t *image, - pixman_fixed_t x, - pixman_fixed_t y, - get_pixel_t get_pixel, - void *out, - accumulate_pixel_t accum, - reduce_pixel_t reduce) -{ - pixman_fixed_t *params = image->common.filter_params; - int x_off = (params[0] - pixman_fixed_1) >> 1; - int y_off = (params[1] - pixman_fixed_1) >> 1; - int32_t cwidth = pixman_fixed_to_int (params[0]); - int32_t cheight = pixman_fixed_to_int (params[1]); - int32_t i, j, x1, x2, y1, y2; - pixman_repeat_t repeat_mode = image->common.repeat; - int width = image->width; - int height = image->height; - unsigned int srtot, sgtot, sbtot, satot; - - params += 2; - - x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); - y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); - x2 = x1 + cwidth; - y2 = y1 + cheight; - - srtot = sgtot = sbtot = satot = 0; - - for (i = y1; i < y2; ++i) - { - for (j = x1; j < x2; ++j) - { - int rx = j; - int ry = i; - - pixman_fixed_t f = *params; - - if (f) - { - /* Must be big enough to hold a argb_t */ - argb_t pixel; - - if (repeat_mode != PIXMAN_REPEAT_NONE) - { - repeat (repeat_mode, &rx, width); - repeat (repeat_mode, &ry, height); - - get_pixel (image, rx, ry, FALSE, &pixel); - } - else - { - get_pixel (image, rx, ry, TRUE, &pixel); - } - - accum (&satot, &srtot, &sgtot, &sbtot, &pixel, f); - } - - params++; - } - } - - reduce (satot, srtot, sgtot, sbtot, out); -} - -static void -bits_image_fetch_pixel_separable_convolution (bits_image_t *image, - pixman_fixed_t x, - pixman_fixed_t y, - get_pixel_t get_pixel, - void *out, - accumulate_pixel_t accum, - reduce_pixel_t reduce) -{ - pixman_fixed_t *params = image->common.filter_params; - pixman_repeat_t repeat_mode = image->common.repeat; - int width = image->width; - int height = image->height; - int cwidth = pixman_fixed_to_int (params[0]); - int cheight = pixman_fixed_to_int (params[1]); - int x_phase_bits = pixman_fixed_to_int (params[2]); - int y_phase_bits = pixman_fixed_to_int (params[3]); - int x_phase_shift = 16 - x_phase_bits; - int y_phase_shift = 16 - y_phase_bits; - int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; - int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; - pixman_fixed_t *y_params; - unsigned int srtot, sgtot, sbtot, satot; - int32_t x1, x2, y1, y2; - int32_t px, py; - int i, j; - - /* Round x and y to the middle of the closest phase before continuing. This - * ensures that the convolution matrix is aligned right, since it was - * positioned relative to a particular phase (and not relative to whatever - * exact fraction we happen to get here). - */ - x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); - y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); - - px = (x & 0xffff) >> x_phase_shift; - py = (y & 0xffff) >> y_phase_shift; - - y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; - - x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); - y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); - x2 = x1 + cwidth; - y2 = y1 + cheight; - - srtot = sgtot = sbtot = satot = 0; - - for (i = y1; i < y2; ++i) - { - pixman_fixed_48_16_t fy = *y_params++; - pixman_fixed_t *x_params = params + 4 + px * cwidth; - - if (fy) - { - for (j = x1; j < x2; ++j) - { - pixman_fixed_t fx = *x_params++; - int rx = j; - int ry = i; - - if (fx) - { - /* Must be big enough to hold a argb_t */ - argb_t pixel; - pixman_fixed_t f; - - if (repeat_mode != PIXMAN_REPEAT_NONE) - { - repeat (repeat_mode, &rx, width); - repeat (repeat_mode, &ry, height); - - get_pixel (image, rx, ry, FALSE, &pixel); - } - else - { - get_pixel (image, rx, ry, TRUE, &pixel); - } - - f = (fy * fx + 0x8000) >> 16; - - accum(&satot, &srtot, &sgtot, &sbtot, &pixel, f); - } - } - } - } - - - reduce(satot, srtot, sgtot, sbtot, out); -} - -static force_inline void -bits_image_fetch_pixel_filtered (bits_image_t *image, - pixman_bool_t wide, - pixman_fixed_t x, - pixman_fixed_t y, - get_pixel_t get_pixel, - void *out) -{ - switch (image->common.filter) - { - case PIXMAN_FILTER_NEAREST: - case PIXMAN_FILTER_FAST: - bits_image_fetch_pixel_nearest (image, x, y, get_pixel, out); - break; - - case PIXMAN_FILTER_BILINEAR: - case PIXMAN_FILTER_GOOD: - case PIXMAN_FILTER_BEST: - if (wide) - bits_image_fetch_pixel_bilinear_float (image, x, y, get_pixel, out); - else - bits_image_fetch_pixel_bilinear_32 (image, x, y, get_pixel, out); - break; - - case PIXMAN_FILTER_CONVOLUTION: - if (wide) - { - bits_image_fetch_pixel_convolution (image, x, y, - get_pixel, out, - accum_float, - reduce_float); - } - else - { - bits_image_fetch_pixel_convolution (image, x, y, - get_pixel, out, - accum_32, reduce_32); - } - break; - - case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: - if (wide) - { - bits_image_fetch_pixel_separable_convolution (image, x, y, - get_pixel, out, - accum_float, - reduce_float); - } - else - { - bits_image_fetch_pixel_separable_convolution (image, x, y, - get_pixel, out, - accum_32, reduce_32); - } - break; - - default: - assert (0); - break; - } -} - -static uint32_t * -__bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, - pixman_bool_t wide, - const uint32_t * mask) -{ - pixman_image_t *image = iter->image; - int offset = iter->x; - int line = iter->y++; - int width = iter->width; - uint32_t * buffer = iter->buffer; - - pixman_fixed_t x, y; - pixman_fixed_t ux, uy; - pixman_vector_t v; - int i; - get_pixel_t get_pixel = - wide ? fetch_pixel_no_alpha_float : fetch_pixel_no_alpha_32; - - /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; - v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; - v.vector[2] = pixman_fixed_1; - - if (image->common.transform) - { - if (!pixman_transform_point_3d (image->common.transform, &v)) - return iter->buffer; - - ux = image->common.transform->matrix[0][0]; - uy = image->common.transform->matrix[1][0]; - } - else - { - ux = pixman_fixed_1; - uy = 0; - } - - x = v.vector[0]; - y = v.vector[1]; - - for (i = 0; i < width; ++i) - { - if (!mask || mask[i]) - { - bits_image_fetch_pixel_filtered ( - &image->bits, wide, x, y, get_pixel, buffer); - } - - x += ux; - y += uy; - buffer += wide ? 4 : 1; - } - - return iter->buffer; -} - -static uint32_t * -bits_image_fetch_affine_no_alpha_32 (pixman_iter_t *iter, - const uint32_t *mask) -{ - return __bits_image_fetch_affine_no_alpha(iter, FALSE, mask); -} - -static uint32_t * -bits_image_fetch_affine_no_alpha_float (pixman_iter_t *iter, - const uint32_t *mask) -{ - return __bits_image_fetch_affine_no_alpha(iter, TRUE, mask); -} - -/* General fetcher */ -static force_inline void -fetch_pixel_general_32 (bits_image_t *image, - int x, int y, pixman_bool_t check_bounds, - void *out) -{ - uint32_t pixel, *ret = out; - - if (check_bounds && - (x < 0 || x >= image->width || y < 0 || y >= image->height)) - { - *ret = 0; - return; - } - - pixel = image->fetch_pixel_32 (image, x, y); - - if (image->common.alpha_map) - { - uint32_t pixel_a; - - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - if (x < 0 || x >= image->common.alpha_map->width || - y < 0 || y >= image->common.alpha_map->height) - { - pixel_a = 0; - } - else - { - pixel_a = image->common.alpha_map->fetch_pixel_32 ( - image->common.alpha_map, x, y); - - pixel_a = ALPHA_8 (pixel_a); - } - - pixel &= 0x00ffffff; - pixel |= (pixel_a << 24); - } - - *ret = pixel; -} - -static force_inline void -fetch_pixel_general_float (bits_image_t *image, - int x, int y, pixman_bool_t check_bounds, - void *out) -{ - argb_t *ret = out; - - if (check_bounds && - (x < 0 || x >= image->width || y < 0 || y >= image->height)) - { - ret->a = ret->r = ret->g = ret->b = 0; - return; - } - - *ret = image->fetch_pixel_float (image, x, y); - - if (image->common.alpha_map) - { - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - if (x < 0 || x >= image->common.alpha_map->width || - y < 0 || y >= image->common.alpha_map->height) - { - ret->a = 0.f; - } - else - { - argb_t alpha; - - alpha = image->common.alpha_map->fetch_pixel_float ( - image->common.alpha_map, x, y); - - ret->a = alpha.a; - } - } -} - -static uint32_t * -__bits_image_fetch_general (pixman_iter_t *iter, - pixman_bool_t wide, - const uint32_t *mask) -{ - pixman_image_t *image = iter->image; - int offset = iter->x; - int line = iter->y++; - int width = iter->width; - uint32_t * buffer = iter->buffer; - get_pixel_t get_pixel = - wide ? fetch_pixel_general_float : fetch_pixel_general_32; - - pixman_fixed_t x, y, w; - pixman_fixed_t ux, uy, uw; - pixman_vector_t v; - int i; - - /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; - v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; - v.vector[2] = pixman_fixed_1; - - if (image->common.transform) - { - if (!pixman_transform_point_3d (image->common.transform, &v)) - return buffer; - - ux = image->common.transform->matrix[0][0]; - uy = image->common.transform->matrix[1][0]; - uw = image->common.transform->matrix[2][0]; - } - else - { - ux = pixman_fixed_1; - uy = 0; - uw = 0; - } - - x = v.vector[0]; - y = v.vector[1]; - w = v.vector[2]; - - for (i = 0; i < width; ++i) - { - pixman_fixed_t x0, y0; - - if (!mask || mask[i]) - { - if (w != 0) - { - x0 = ((uint64_t)x << 16) / w; - y0 = ((uint64_t)y << 16) / w; - } - else - { - x0 = 0; - y0 = 0; - } - - bits_image_fetch_pixel_filtered ( - &image->bits, wide, x0, y0, get_pixel, buffer); - } - - x += ux; - y += uy; - w += uw; - buffer += wide ? 4 : 1; - } - - return iter->buffer; -} - -static uint32_t * -bits_image_fetch_general_32 (pixman_iter_t *iter, - const uint32_t *mask) -{ - return __bits_image_fetch_general(iter, FALSE, mask); -} - -static uint32_t * -bits_image_fetch_general_float (pixman_iter_t *iter, - const uint32_t *mask) -{ - return __bits_image_fetch_general(iter, TRUE, mask); -} - -static void -replicate_pixel_32 (bits_image_t * bits, - int x, - int y, - int width, - uint32_t * buffer) -{ - uint32_t color; - uint32_t *end; - - color = bits->fetch_pixel_32 (bits, x, y); - - end = buffer + width; - while (buffer < end) - *(buffer++) = color; -} - -static void -replicate_pixel_float (bits_image_t * bits, - int x, - int y, - int width, - uint32_t * b) -{ - argb_t color; - argb_t *buffer = (argb_t *)b; - argb_t *end; - - color = bits->fetch_pixel_float (bits, x, y); - - end = buffer + width; - while (buffer < end) - *(buffer++) = color; -} - -static void -bits_image_fetch_untransformed_repeat_none (bits_image_t *image, - pixman_bool_t wide, - int x, - int y, - int width, - uint32_t * buffer) -{ - uint32_t w; - - if (y < 0 || y >= image->height) - { - memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); - return; - } - - if (x < 0) - { - w = MIN (width, -x); - - memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); - - width -= w; - buffer += w * (wide? 4 : 1); - x += w; - } - - if (x < image->width) - { - w = MIN (width, image->width - x); - - if (wide) - image->fetch_scanline_float (image, x, y, w, buffer, NULL); - else - image->fetch_scanline_32 (image, x, y, w, buffer, NULL); - - width -= w; - buffer += w * (wide? 4 : 1); - x += w; - } - - memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); -} - -static void -bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, - pixman_bool_t wide, - int x, - int y, - int width, - uint32_t * buffer) -{ - uint32_t w; - - while (y < 0) - y += image->height; - - while (y >= image->height) - y -= image->height; - - if (image->width == 1) - { - if (wide) - replicate_pixel_float (image, 0, y, width, buffer); - else - replicate_pixel_32 (image, 0, y, width, buffer); - - return; - } - - while (width) - { - while (x < 0) - x += image->width; - while (x >= image->width) - x -= image->width; - - w = MIN (width, image->width - x); - - if (wide) - image->fetch_scanline_float (image, x, y, w, buffer, NULL); - else - image->fetch_scanline_32 (image, x, y, w, buffer, NULL); - - buffer += w * (wide? 4 : 1); - x += w; - width -= w; - } -} - -static uint32_t * -bits_image_fetch_untransformed_32 (pixman_iter_t * iter, - const uint32_t *mask) -{ - pixman_image_t *image = iter->image; - int x = iter->x; - int y = iter->y; - int width = iter->width; - uint32_t * buffer = iter->buffer; - - if (image->common.repeat == PIXMAN_REPEAT_NONE) - { - bits_image_fetch_untransformed_repeat_none ( - &image->bits, FALSE, x, y, width, buffer); - } - else - { - bits_image_fetch_untransformed_repeat_normal ( - &image->bits, FALSE, x, y, width, buffer); - } - - iter->y++; - return buffer; -} - -static uint32_t * -bits_image_fetch_untransformed_float (pixman_iter_t * iter, - const uint32_t *mask) -{ - pixman_image_t *image = iter->image; - int x = iter->x; - int y = iter->y; - int width = iter->width; - uint32_t * buffer = iter->buffer; - - if (image->common.repeat == PIXMAN_REPEAT_NONE) - { - bits_image_fetch_untransformed_repeat_none ( - &image->bits, TRUE, x, y, width, buffer); - } - else - { - bits_image_fetch_untransformed_repeat_normal ( - &image->bits, TRUE, x, y, width, buffer); - } - - iter->y++; - return buffer; -} - -typedef struct -{ - pixman_format_code_t format; - uint32_t flags; - pixman_iter_get_scanline_t get_scanline_32; - pixman_iter_get_scanline_t get_scanline_float; -} fetcher_info_t; - -static const fetcher_info_t fetcher_info[] = -{ - { PIXMAN_any, - (FAST_PATH_NO_ALPHA_MAP | - FAST_PATH_ID_TRANSFORM | - FAST_PATH_NO_CONVOLUTION_FILTER | - FAST_PATH_NO_PAD_REPEAT | - FAST_PATH_NO_REFLECT_REPEAT), - bits_image_fetch_untransformed_32, - bits_image_fetch_untransformed_float - }, - - /* Affine, no alpha */ - { PIXMAN_any, - (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM), - bits_image_fetch_affine_no_alpha_32, - bits_image_fetch_affine_no_alpha_float, - }, - - /* General */ - { PIXMAN_any, - 0, - bits_image_fetch_general_32, - bits_image_fetch_general_float, - }, - - { PIXMAN_null }, -}; - -static void -bits_image_property_changed (pixman_image_t *image) -{ - _pixman_bits_image_setup_accessors (&image->bits); -} - -void -_pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) -{ - pixman_format_code_t format = image->common.extended_format_code; - uint32_t flags = image->common.flags; - const fetcher_info_t *info; - - for (info = fetcher_info; info->format != PIXMAN_null; ++info) - { - if ((info->format == format || info->format == PIXMAN_any) && - (info->flags & flags) == info->flags) - { - if (iter->iter_flags & ITER_NARROW) - { - iter->get_scanline = info->get_scanline_32; - } - else - { - iter->get_scanline = info->get_scanline_float; - } - return; - } - } - - /* Just in case we somehow didn't find a scanline function */ - iter->get_scanline = _pixman_iter_get_scanline_noop; -} - -static uint32_t * -dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) -{ - pixman_image_t *image = iter->image; - int x = iter->x; - int y = iter->y; - int width = iter->width; - uint32_t * buffer = iter->buffer; - - image->bits.fetch_scanline_32 (&image->bits, x, y, width, buffer, mask); - if (image->common.alpha_map) - { - uint32_t *alpha; - - if ((alpha = malloc (width * sizeof (uint32_t)))) - { - int i; - - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - image->common.alpha_map->fetch_scanline_32 ( - image->common.alpha_map, x, y, width, alpha, mask); - - for (i = 0; i < width; ++i) - { - buffer[i] &= ~0xff000000; - buffer[i] |= (alpha[i] & 0xff000000); - } - - free (alpha); - } - } - - return iter->buffer; -} - -static uint32_t * -dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) -{ - bits_image_t * image = &iter->image->bits; - int x = iter->x; - int y = iter->y; - int width = iter->width; - argb_t * buffer = (argb_t *)iter->buffer; - - image->fetch_scanline_float ( - image, x, y, width, (uint32_t *)buffer, mask); - if (image->common.alpha_map) - { - argb_t *alpha; - - if ((alpha = malloc (width * sizeof (argb_t)))) - { - int i; - - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - image->common.alpha_map->fetch_scanline_float ( - image->common.alpha_map, x, y, width, (uint32_t *)alpha, mask); - - for (i = 0; i < width; ++i) - buffer[i].a = alpha[i].a; - - free (alpha); - } - } - - return iter->buffer; -} - -static void -dest_write_back_narrow (pixman_iter_t *iter) -{ - bits_image_t * image = &iter->image->bits; - int x = iter->x; - int y = iter->y; - int width = iter->width; - const uint32_t *buffer = iter->buffer; - - image->store_scanline_32 (image, x, y, width, buffer); - - if (image->common.alpha_map) - { - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - image->common.alpha_map->store_scanline_32 ( - image->common.alpha_map, x, y, width, buffer); - } - - iter->y++; -} - -static const float -dither_factor_blue_noise_64 (int x, int y) -{ - float m = dither_blue_noise_64x64[((y & 0x3f) << 6) | (x & 0x3f)]; - return m * (1. / 4096.f) + (1. / 8192.f); -} - -static const float -dither_factor_bayer_8 (int x, int y) -{ - uint32_t m; - - y ^= x; - - /* Compute reverse(interleave(xor(x mod n, y mod n), x mod n)) - * Here n = 8 and `mod n` is the bottom 3 bits. - */ - m = ((y & 0x1) << 5) | ((x & 0x1) << 4) | - ((y & 0x2) << 2) | ((x & 0x2) << 1) | - ((y & 0x4) >> 1) | ((x & 0x4) >> 2); - - /* m is in range [0, 63]. We scale it to [0, 63.0f/64.0f], then - * shift it to to [1.0f/128.0f, 127.0f/128.0f] so that 0 < d < 1. - * This ensures exact values are not changed by dithering. - */ - return (float)(m) * (1 / 64.0f) + (1.0f / 128.0f); -} - -typedef float (* dither_factor_t)(int x, int y); - -static force_inline float -dither_apply_channel (float f, float d, float s) -{ - /* float_to_unorm splits the [0, 1] segment in (1 << n_bits) - * subsections of equal length; however unorm_to_float does not - * map to the center of those sections. In fact, pixel value u is - * mapped to: - * - * u u u 1 - * -------------- = ---------- + -------------- * ---------- - * 2^n_bits - 1 2^n_bits 2^n_bits - 1 2^n_bits - * - * Hence if f = u / (2^n_bits - 1) is exactly representable on a - * n_bits palette, all the numbers between - * - * u - * ---------- = f - f * 2^n_bits = f + (0 - f) * 2^n_bits - * 2^n_bits - * - * and - * - * u + 1 - * ---------- = f - (f - 1) * 2^n_bits = f + (1 - f) * 2^n_bits - * 2^n_bits - * - * are also mapped back to u. - * - * Hence the following calculation ensures that we add as much - * noise as possible without perturbing values which are exactly - * representable in the target colorspace. Note that this corresponds to - * mixing the original color with noise with a ratio of `1 / 2^n_bits`. - */ - return f + (d - f) * s; -} - -static force_inline float -dither_compute_scale (int n_bits) -{ - // No dithering for wide formats - if (n_bits == 0 || n_bits >= 32) - return 0.f; - - return 1.f / (float)(1 << n_bits); -} - -static const uint32_t * -dither_apply_ordered (pixman_iter_t *iter, dither_factor_t factor) -{ - bits_image_t *image = &iter->image->bits; - int x = iter->x + image->dither_offset_x; - int y = iter->y + image->dither_offset_y; - int width = iter->width; - argb_t *buffer = (argb_t *)iter->buffer; - - pixman_format_code_t format = image->format; - int a_size = PIXMAN_FORMAT_A (format); - int r_size = PIXMAN_FORMAT_R (format); - int g_size = PIXMAN_FORMAT_G (format); - int b_size = PIXMAN_FORMAT_B (format); - - float a_scale = dither_compute_scale (a_size); - float r_scale = dither_compute_scale (r_size); - float g_scale = dither_compute_scale (g_size); - float b_scale = dither_compute_scale (b_size); - - int i; - float d; - - for (i = 0; i < width; ++i) - { - d = factor (x + i, y); - - buffer->a = dither_apply_channel (buffer->a, d, a_scale); - buffer->r = dither_apply_channel (buffer->r, d, r_scale); - buffer->g = dither_apply_channel (buffer->g, d, g_scale); - buffer->b = dither_apply_channel (buffer->b, d, b_scale); - - buffer++; - } - - return iter->buffer; -} - -static void -dest_write_back_wide (pixman_iter_t *iter) -{ - bits_image_t * image = &iter->image->bits; - int x = iter->x; - int y = iter->y; - int width = iter->width; - const uint32_t *buffer = iter->buffer; - - switch (image->dither) - { - case PIXMAN_DITHER_NONE: - break; - - case PIXMAN_DITHER_GOOD: - case PIXMAN_DITHER_BEST: - case PIXMAN_DITHER_ORDERED_BLUE_NOISE_64: - buffer = dither_apply_ordered (iter, dither_factor_blue_noise_64); - break; - - case PIXMAN_DITHER_FAST: - case PIXMAN_DITHER_ORDERED_BAYER_8: - buffer = dither_apply_ordered (iter, dither_factor_bayer_8); - break; - } - - image->store_scanline_float (image, x, y, width, buffer); - - if (image->common.alpha_map) - { - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - image->common.alpha_map->store_scanline_float ( - image->common.alpha_map, x, y, width, buffer); - } - - iter->y++; -} - -void -_pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) -{ - if (iter->iter_flags & ITER_NARROW) - { - if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == - (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) - { - iter->get_scanline = _pixman_iter_get_scanline_noop; - } - else - { - iter->get_scanline = dest_get_scanline_narrow; - } - - iter->write_back = dest_write_back_narrow; - } - else - { - iter->get_scanline = dest_get_scanline_wide; - iter->write_back = dest_write_back_wide; - } -} - -static uint32_t * -create_bits (pixman_format_code_t format, - int width, - int height, - int * rowstride_bytes, - pixman_bool_t clear) -{ - int stride; - size_t buf_size; - int bpp; - - /* what follows is a long-winded way, avoiding any possibility of integer - * overflows, of saying: - * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); - */ - - bpp = PIXMAN_FORMAT_BPP (format); - if (_pixman_multiply_overflows_int (width, bpp)) - return NULL; - - stride = width * bpp; - if (_pixman_addition_overflows_int (stride, 0x1f)) - return NULL; - - stride += 0x1f; - stride >>= 5; - - stride *= sizeof (uint32_t); - - if (_pixman_multiply_overflows_size (height, stride)) - return NULL; - - buf_size = (size_t)height * stride; - - if (rowstride_bytes) - *rowstride_bytes = stride; - - if (clear) - return calloc (buf_size, 1); - else - return malloc (buf_size); -} - -pixman_bool_t -_pixman_bits_image_init (pixman_image_t * image, - pixman_format_code_t format, - int width, - int height, - uint32_t * bits, - int rowstride, - pixman_bool_t clear) -{ - uint32_t *free_me = NULL; - - if (PIXMAN_FORMAT_BPP (format) == 128) - return_val_if_fail(!(rowstride % 4), FALSE); - - if (!bits && width && height) - { - int rowstride_bytes; - - free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); - - if (!bits) - return FALSE; - - rowstride = rowstride_bytes / (int) sizeof (uint32_t); - } - - _pixman_image_init (image); - - image->type = BITS; - image->bits.format = format; - image->bits.width = width; - image->bits.height = height; - image->bits.bits = bits; - image->bits.free_me = free_me; - image->bits.dither = PIXMAN_DITHER_NONE; - image->bits.dither_offset_x = 0; - image->bits.dither_offset_y = 0; - image->bits.read_func = NULL; - image->bits.write_func = NULL; - image->bits.rowstride = rowstride; - image->bits.indexed = NULL; - - image->common.property_changed = bits_image_property_changed; - - _pixman_image_reset_clip_region (image); - - return TRUE; -} - -static pixman_image_t * -create_bits_image_internal (pixman_format_code_t format, - int width, - int height, - uint32_t * bits, - int rowstride_bytes, - pixman_bool_t clear) -{ - pixman_image_t *image; - - /* must be a whole number of uint32_t's - */ - return_val_if_fail ( - bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); - - return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); - - image = _pixman_image_allocate (); - - if (!image) - return NULL; - - if (!_pixman_bits_image_init (image, format, width, height, bits, - rowstride_bytes / (int) sizeof (uint32_t), - clear)) - { - free (image); - return NULL; - } - - return image; -} - -/* If bits is NULL, a buffer will be allocated and initialized to 0 */ -PIXMAN_EXPORT pixman_image_t * -pixman_image_create_bits (pixman_format_code_t format, - int width, - int height, - uint32_t * bits, - int rowstride_bytes) -{ - return create_bits_image_internal ( - format, width, height, bits, rowstride_bytes, TRUE); -} - - -/* If bits is NULL, a buffer will be allocated and _not_ initialized */ -PIXMAN_EXPORT pixman_image_t * -pixman_image_create_bits_no_clear (pixman_format_code_t format, - int width, - int height, - uint32_t * bits, - int rowstride_bytes) -{ - return create_bits_image_internal ( - format, width, height, bits, rowstride_bytes, FALSE); -} |