diff options
Diffstat (limited to 'image/xcb_image.c')
-rw-r--r-- | image/xcb_image.c | 1009 |
1 files changed, 0 insertions, 1009 deletions
diff --git a/image/xcb_image.c b/image/xcb_image.c deleted file mode 100644 index 413bdc5..0000000 --- a/image/xcb_image.c +++ /dev/null @@ -1,1009 +0,0 @@ -/* Copyright © 2007 Bart Massey - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the names of the authors or their - * institutions shall not be used in advertising or otherwise to promote the - * sale, use or other dealings in this Software without prior written - * authorization from the authors. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <xcb/xcb.h> -#include <xcb/shm.h> -#include "../aux/xcb_aux.h" -#include "../aux/xcb_bitops.h" -#include "xcb_image.h" -#define BUILD -#include "xcb_pixel.h" - - -static xcb_format_t * -find_format_by_depth (const xcb_setup_t *setup, uint8_t depth) -{ - xcb_format_t *fmt = xcb_setup_pixmap_formats(setup); - xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup); - for(; fmt != fmtend; ++fmt) - if(fmt->depth == depth) - return fmt; - return 0; -} - - -static xcb_image_format_t -effective_format(xcb_image_format_t format, uint8_t bpp) -{ - if (format == XCB_IMAGE_FORMAT_Z_PIXMAP && bpp != 1) - return format; - return XCB_IMAGE_FORMAT_XY_PIXMAP; -} - - -static int -format_valid (uint8_t depth, uint8_t bpp, uint8_t unit, - xcb_image_format_t format, uint8_t xpad) -{ - xcb_image_format_t ef = effective_format(format, bpp); - if (depth > bpp) - return 0; - switch(ef) { - case XCB_IMAGE_FORMAT_XY_PIXMAP: - switch(unit) { - case 8: - case 16: - case 32: - break; - default: - return 0; - } - if (xpad < bpp) - return 0; - switch (xpad) { - case 8: - case 16: - case 32: - break; - default: - return 0; - } - break; - case XCB_IMAGE_FORMAT_Z_PIXMAP: - switch (bpp) { - case 4: - if (unit != 8) - return 0; - break; - case 8: - case 16: - case 24: - case 32: - if (unit != bpp) - return 0; - break; - default: - return 0; - } - break; - default: - return 0; - } - return 1; -} - - -static int -image_format_valid (xcb_image_t *image) { - return format_valid(image->depth, - image->bpp, - image->unit, - image->format, - image->scanline_pad); -} - - -void -xcb_image_annotate (xcb_image_t *image) -{ - xcb_image_format_t ef = effective_format(image->format, image->bpp); - switch (ef) { - case XCB_IMAGE_FORMAT_XY_PIXMAP: - image->stride = xcb_roundup(image->width, image->scanline_pad) >> 3; - image->size = image->height * image->stride * image->depth; - break; - case XCB_IMAGE_FORMAT_Z_PIXMAP: - image->stride = xcb_roundup((uint32_t)image->width * - (uint32_t)image->bpp, - image->scanline_pad) >> 3; - image->size = image->height * image->stride; - break; - default: - assert(0); - } -} - - -xcb_image_t * -xcb_image_create_native (xcb_connection_t * c, - uint16_t width, - uint16_t height, - xcb_image_format_t format, - uint8_t depth, - void * base, - uint32_t bytes, - uint8_t * data) -{ - const xcb_setup_t * setup = xcb_get_setup(c); - xcb_format_t * fmt; - xcb_image_format_t ef = format; - - if (ef == XCB_IMAGE_FORMAT_Z_PIXMAP && depth == 1) - ef = XCB_IMAGE_FORMAT_XY_PIXMAP; - switch (ef) { - case XCB_IMAGE_FORMAT_XY_BITMAP: - if (depth != 1) - return 0; - /* fall through */ - case XCB_IMAGE_FORMAT_XY_PIXMAP: - if (depth > 1) { - fmt = find_format_by_depth(setup, depth); - if (!fmt) - return 0; - } - return xcb_image_create(width, height, format, - setup->bitmap_format_scanline_pad, - depth, depth, setup->bitmap_format_scanline_unit, - setup->image_byte_order, - setup->bitmap_format_bit_order, - base, bytes, data); - case XCB_IMAGE_FORMAT_Z_PIXMAP: - fmt = find_format_by_depth(setup, depth); - if (!fmt) - return 0; - return xcb_image_create(width, height, format, - fmt->scanline_pad, - fmt->depth, fmt->bits_per_pixel, 0, - setup->image_byte_order, - XCB_IMAGE_ORDER_MSB_FIRST, - base, bytes, data); - default: - assert(0); - } - assert(0); -} - - -xcb_image_t * -xcb_image_create (uint16_t width, - uint16_t height, - xcb_image_format_t format, - uint8_t xpad, - uint8_t depth, - uint8_t bpp, - uint8_t unit, - xcb_image_order_t byte_order, - xcb_image_order_t bit_order, - void * base, - uint32_t bytes, - uint8_t * data) -{ - xcb_image_t * image; - - if (unit == 0) { - switch (format) { - case XCB_IMAGE_FORMAT_XY_BITMAP: - case XCB_IMAGE_FORMAT_XY_PIXMAP: - unit = 32; - break; - case XCB_IMAGE_FORMAT_Z_PIXMAP: - if (bpp == 1) { - unit = 32; - break; - } - if (bpp < 8) { - unit = 8; - break; - } - unit = bpp; - break; - } - } - if (!format_valid(depth, bpp, unit, format, xpad)) - return 0; - image = malloc(sizeof(*image)); - if (image == 0) - return 0; - image->width = width; - image->height = height; - image->format = format; - image->scanline_pad = xpad; - image->depth = depth; - image->bpp = bpp; - image->unit = unit; - image->plane_mask = xcb_mask(depth); - image->byte_order = byte_order; - image->bit_order = bit_order; - xcb_image_annotate(image); - - /* - * Ways this function can be called: - * * with data: we fail if bytes isn't - * large enough, else leave well enough alone. - * * with base and !data: if bytes is zero, we - * default; otherwise we fail if bytes isn't - * large enough, else fill in data - * * with !base and !data: we malloc storage - * for the data, save that address as the base, - * and fail if malloc does. - * - * When successful, we establish the invariant that data - * points at sufficient storage that may have been - * supplied, and base is set iff it should be - * auto-freed when the image is destroyed. - * - * Except as a special case when base = 0 && data == 0 && - * bytes == ~0 we just return the image structure and let - * the caller deal with getting the allocation right. - */ - if (!base && !data && bytes == ~0) { - image->base = 0; - image->data = 0; - return image; - } - if (!base && data && bytes == 0) - bytes = image->size; - image->base = base; - image->data = data; - if (!image->data) { - if (image->base) { - image->data = image->base; - } else { - bytes = image->size; - image->base = malloc(bytes); - image->data = image->base; - } - } - if (!image->data || bytes < image->size) { - free(image); - return 0; - } - return image; -} - - -void -xcb_image_destroy (xcb_image_t *image) -{ - if (image->base) - free (image->base); - free (image); -} - - -xcb_image_t * -xcb_image_get (xcb_connection_t * conn, - xcb_drawable_t draw, - int16_t x, - int16_t y, - uint16_t width, - uint16_t height, - uint32_t plane_mask, - xcb_image_format_t format) -{ - xcb_get_image_cookie_t image_cookie; - xcb_get_image_reply_t * imrep; - xcb_image_t * image = 0; - uint32_t bytes; - uint8_t * data; - - image_cookie = xcb_get_image(conn, format, draw, x, y, - width, height, plane_mask); - imrep = xcb_get_image_reply(conn, image_cookie, 0); - if (!imrep) - return 0; - bytes = xcb_get_image_data_length(imrep); - data = xcb_get_image_data(imrep); - switch (format) { - case XCB_IMAGE_FORMAT_XY_PIXMAP: - plane_mask &= xcb_mask(imrep->depth); - if (plane_mask != xcb_mask(imrep->depth)) { - xcb_image_t * tmp_image = - xcb_image_create_native(conn, width, height, format, - imrep->depth, 0, 0, 0); - int i; - uint32_t rpm = plane_mask; - uint8_t * src_plane = image->data; - uint8_t * dst_plane = tmp_image->data; - uint32_t size = image->height * image->stride; - - if (!tmp_image) { - free(imrep); - return 0; - } - if (tmp_image->bit_order == XCB_IMAGE_ORDER_MSB_FIRST) - rpm = xcb_bit_reverse(plane_mask, imrep->depth); - for (i = 0; i < imrep->depth; i++) { - if (rpm & 1) { - memcpy(dst_plane, src_plane, size); - src_plane += size; - } else { - memset(dst_plane, 0, size); - } - dst_plane += size; - } - tmp_image->plane_mask = plane_mask; - image = tmp_image; - free(imrep); - break; - } - /* fall through */ - case XCB_IMAGE_FORMAT_Z_PIXMAP: - image = xcb_image_create_native(conn, width, height, format, - imrep->depth, imrep, bytes, data); - if (!image) { - free(imrep); - return 0; - } - break; - default: - assert(0); - } - assert(bytes == image->size); - return image; -} - - -xcb_image_t * -xcb_image_native (xcb_connection_t * c, - xcb_image_t * image, - int convert) -{ - xcb_image_t * tmp_image = 0; - const xcb_setup_t * setup = xcb_get_setup(c); - xcb_format_t * fmt = 0; - xcb_image_format_t ef = effective_format(image->format, image->bpp); - uint8_t bpp = 1; - - if (image->depth > 1 || ef == XCB_IMAGE_FORMAT_Z_PIXMAP) { - fmt = find_format_by_depth(setup, image->depth); - /* XXX For now, we don't do depth conversions, even - for xy-pixmaps */ - if (!fmt) - return 0; - bpp = fmt->bits_per_pixel; - } - switch (ef) { - case XCB_IMAGE_FORMAT_XY_PIXMAP: - if (setup->bitmap_format_scanline_unit != image->unit || - setup->bitmap_format_scanline_pad != image->scanline_pad || - setup->image_byte_order != image->byte_order || - setup->bitmap_format_bit_order != image->bit_order || - bpp != image->bpp) { - if (!convert) - return 0; - tmp_image = - xcb_image_create(image->width, image->height, image->format, - setup->bitmap_format_scanline_pad, - image->depth, bpp, - setup->bitmap_format_scanline_unit, - setup->image_byte_order, - setup->bitmap_format_bit_order, - 0, 0, 0); - if (!tmp_image) - return 0; - } - break; - case XCB_IMAGE_FORMAT_Z_PIXMAP: - if (fmt->scanline_pad != image->scanline_pad || - setup->image_byte_order != image->byte_order || - bpp != image->bpp) { - if (!convert) - return 0; - tmp_image = - xcb_image_create(image->width, image->height, image->format, - fmt->scanline_pad, - image->depth, bpp, 0, - setup->image_byte_order, - XCB_IMAGE_ORDER_MSB_FIRST, - 0, 0, 0); - if (!tmp_image) - return 0; - } - break; - default: - assert(0); - } - if (tmp_image) { - if (!xcb_image_convert(image, tmp_image)) { - xcb_image_destroy(tmp_image); - return 0; - } - image = tmp_image; - } - return image; -} - - -xcb_void_cookie_t -xcb_image_put (xcb_connection_t * conn, - xcb_drawable_t draw, - xcb_gcontext_t gc, - xcb_image_t * image, - int16_t x, - int16_t y, - uint8_t left_pad) -{ - return xcb_put_image(conn, image->format, draw, gc, - image->width, image->height, - x, y, left_pad, - image->depth, - image->size, - image->data); -} - - - -/* - * Shm stuff - */ - -xcb_image_t * -xcb_image_shm_put (xcb_connection_t * conn, - xcb_drawable_t draw, - xcb_gcontext_t gc, - xcb_image_t * image, - xcb_shm_segment_info_t shminfo, - int16_t src_x, - int16_t src_y, - int16_t dest_x, - int16_t dest_y, - uint16_t src_width, - uint16_t src_height, - uint8_t send_event) -{ - if (!xcb_image_native(conn, image, 0)) - return 0; - if (!shminfo.shmaddr) - return 0; - xcb_shm_put_image(conn, draw, gc, - image->width, image->height, - src_x, src_y, src_width, src_height, - dest_x, dest_y, - image->depth, image->format, - send_event, - shminfo.shmseg, - image->data - shminfo.shmaddr); - return image; -} - - -int -xcb_image_shm_get (xcb_connection_t * conn, - xcb_drawable_t draw, - xcb_image_t * image, - xcb_shm_segment_info_t shminfo, - int16_t x, - int16_t y, - uint32_t plane_mask) -{ - xcb_shm_get_image_reply_t * setup; - xcb_shm_get_image_cookie_t cookie; - xcb_generic_error_t * err = 0; - - if (!shminfo.shmaddr) - return 0; - cookie = xcb_shm_get_image(conn, draw, - x, y, - image->width, image->height, - plane_mask, - image->format, - shminfo.shmseg, - image->data - shminfo.shmaddr); - setup = xcb_shm_get_image_reply(conn, cookie, &err); - if (err) { - fprintf(stderr, "ShmGetImageReply error %d\n", (int)err->error_code); - free(err); - return 0; - } else { - free (setup); - return 1; - } -} - - -static uint32_t -xy_image_byte (xcb_image_t *image, uint32_t x) -{ - x >>= 3; - if (image->byte_order == image->bit_order) - return x; - switch (image->unit) { - default: - case 8: - return x; - case 16: - return x ^ 1; - case 32: - return x ^ 3; - } -} - -static uint32_t -xy_image_bit (xcb_image_t *image, uint32_t x) -{ - x &= 7; - if (image->bit_order == XCB_IMAGE_ORDER_MSB_FIRST) - x = 7 - x; - return x; -} - -/* GetPixel/PutPixel */ - -/* XXX this is the most hideously done cut-and-paste - to below. Any bugs fixed there should be fixed here - and vice versa. */ -void -xcb_image_put_pixel (xcb_image_t *image, - uint32_t x, - uint32_t y, - uint32_t pixel) -{ - uint8_t *row; - - if (x > image->width || y > image->height) - return; - row = image->data + (y * image->stride); - switch (effective_format(image->format, image->bpp)) { - case XCB_IMAGE_FORMAT_XY_BITMAP: - case XCB_IMAGE_FORMAT_XY_PIXMAP: - /* block */ { - int p; - uint32_t plane_mask = image->plane_mask; - uint8_t * plane = row; - uint32_t byte = xy_image_byte(image, x); - uint32_t bit = xy_image_bit(image,x); - uint8_t mask = 1 << bit; - - for (p = image->bpp - 1; p >= 0; p--) { - if ((plane_mask >> p) & 1) { - uint8_t * bp = plane + byte; - uint8_t this_bit = ((pixel >> p) & 1) << bit; - *bp = (*bp & ~mask) | this_bit; - } - plane += image->stride * image->height; - } - } - break; - case XCB_IMAGE_FORMAT_Z_PIXMAP: - switch (image->bpp) { - uint32_t mask; - case 4: - mask = 0xf; - pixel &= 0xf; - if ((x & 1) == - (image->byte_order == XCB_IMAGE_ORDER_MSB_FIRST)) { - pixel <<= 4; - mask <<= 4; - } - row[x >> 1] = (row[x >> 1] & ~mask) | pixel; - break; - case 8: - row[x] = pixel; - break; - case 16: - switch (image->byte_order) { - case XCB_IMAGE_ORDER_LSB_FIRST: - row[x << 1] = pixel; - row[(x << 1) + 1] = pixel >> 8; - break; - case XCB_IMAGE_ORDER_MSB_FIRST: - row[x << 1] = pixel >> 8; - row[(x << 1) + 1] = pixel; - break; - } - break; - case 24: - switch (image->byte_order) { - case XCB_IMAGE_ORDER_LSB_FIRST: - row[x * 3] = pixel; - row[x * 3 + 1] = pixel >> 8; - row[x * 3 + 2] = pixel >> 16; - break; - case XCB_IMAGE_ORDER_MSB_FIRST: - row[x * 3] = pixel >> 16; - row[x * 3 + 1] = pixel >> 8; - row[x * 3 + 2] = pixel; - break; - } - break; - case 32: - switch (image->byte_order) { - case XCB_IMAGE_ORDER_LSB_FIRST: - row[x << 2] = pixel; - row[(x << 2) + 1] = pixel >> 8; - row[(x << 2) + 2] = pixel >> 16; - row[(x << 2) + 3] = pixel >> 24; - break; - case XCB_IMAGE_ORDER_MSB_FIRST: - row[x << 2] = pixel >> 24; - row[(x << 2) + 1] = pixel >> 16; - row[(x << 2) + 2] = pixel >> 8; - row[(x << 2) + 3] = pixel; - break; - } - break; - default: - assert(0); - } - break; - default: - assert(0); - } -} - - -/* XXX this is the most hideously done cut-and-paste - from above. Any bugs fixed there should be fixed here - and vice versa. */ -uint32_t -xcb_image_get_pixel (xcb_image_t *image, - uint32_t x, - uint32_t y) -{ - uint32_t pixel = 0; - uint8_t *row; - - assert(x < image->width && y < image->height); - row = image->data + (y * image->stride); - switch (effective_format(image->format, image->bpp)) { - case XCB_IMAGE_FORMAT_XY_BITMAP: - case XCB_IMAGE_FORMAT_XY_PIXMAP: - /* block */ { - int p; - uint32_t plane_mask = image->plane_mask; - uint8_t * plane = row; - uint32_t byte = xy_image_byte(image, x); - uint32_t bit = xy_image_bit(image,x); - - for (p = image->bpp - 1; p >= 0; p--) { - pixel <<= 1; - if ((plane_mask >> p) & 1) { - uint8_t * bp = plane + byte; - pixel |= (*bp >> bit) & 1; - } - plane += image->stride * image->height; - } - } - return pixel; - case XCB_IMAGE_FORMAT_Z_PIXMAP: - switch (image->bpp) { - case 4: - if ((x & 1) == (image->byte_order == XCB_IMAGE_ORDER_MSB_FIRST)) - return row[x >> 1] >> 4; - return row[x >> 1] & 0xf; - case 8: - return row[x]; - case 16: - switch (image->byte_order) { - case XCB_IMAGE_ORDER_LSB_FIRST: - pixel = row[x << 1]; - pixel |= row[(x << 1) + 1] << 8; - break; - case XCB_IMAGE_ORDER_MSB_FIRST: - pixel = row[x << 1] << 8; - pixel |= row[(x << 1) + 1]; - break; - } - break; - case 24: - switch (image->byte_order) { - case XCB_IMAGE_ORDER_LSB_FIRST: - pixel = row[x * 3]; - pixel |= row[x * 3 + 1] << 8; - pixel |= row[x * 3 + 2] << 16; - break; - case XCB_IMAGE_ORDER_MSB_FIRST: - pixel = row[x * 3] << 16; - pixel |= row[x * 3 + 1] << 8; - pixel |= row[x * 3 + 2]; - break; - } - break; - case 32: - switch (image->byte_order) { - case XCB_IMAGE_ORDER_LSB_FIRST: - pixel = row[x << 2]; - pixel |= row[(x << 2) + 1] << 8; - pixel |= row[(x << 2) + 2] << 16; - pixel |= row[(x << 2) + 3] << 24; - break; - case XCB_IMAGE_ORDER_MSB_FIRST: - pixel = row[x << 2] << 24; - pixel |= row[(x << 2) + 1] << 16; - pixel |= row[(x << 2) + 2] << 8; - pixel |= row[(x << 2) + 3]; - break; - } - break; - default: - assert(0); - } - return pixel; - default: - assert(0); - } -} - - -xcb_image_t * -xcb_image_create_from_bitmap_data (uint8_t * data, - uint32_t width, - uint32_t height) -{ - return xcb_image_create(width, height, XCB_IMAGE_FORMAT_XY_PIXMAP, - 8, 1, 1, 8, - XCB_IMAGE_ORDER_LSB_FIRST, - XCB_IMAGE_ORDER_LSB_FIRST, - 0, 0, data); -} - - -/* - * (Adapted from libX11.) - * - * xcb_create_pixmap_from_bitmap_data: Routine to make a pixmap of - * given depth from user supplied bitmap data. - * D is any drawable on the same screen that the pixmap will be used in. - * Data is a pointer to the bit data, and - * width & height give the size in bits of the pixmap. - * - * The following format is assumed for data: - * - * format=XY (will use XYPixmap for depth 1 and XYBitmap for larger) - * bit_order=LSBFirst - * padding=8 - * bitmap_unit=8 - */ -xcb_pixmap_t -xcb_create_pixmap_from_bitmap_data (xcb_connection_t * display, - xcb_drawable_t d, - uint8_t * data, - uint32_t width, - uint32_t height, - uint32_t depth, - uint32_t fg, - uint32_t bg, - xcb_gcontext_t * gcp) -{ - xcb_pixmap_t pix; - xcb_image_t * image; - xcb_image_t * final_image; - xcb_gcontext_t gc; - uint32_t mask = 0; - xcb_params_gc_t gcv; - - image = xcb_image_create_from_bitmap_data(data, width, height); - if (!image) - return 0; - if (depth > 1) - image->format = XCB_IMAGE_FORMAT_XY_BITMAP; - final_image = xcb_image_native(display, image, 1); - if (!final_image) { - xcb_image_destroy(image); - return 0; - } - pix = xcb_generate_id(display); - xcb_create_pixmap(display, depth, pix, d, width, height); - gc = xcb_generate_id(display); - XCB_AUX_ADD_PARAM(&mask, &gcv, foreground, fg); - XCB_AUX_ADD_PARAM(&mask, &gcv, background, bg); - xcb_aux_create_gc(display, gc, pix, mask, &gcv); - xcb_image_put(display, pix, gc, final_image, 0, 0, 0); - if (final_image != image) - xcb_image_destroy(final_image); - xcb_image_destroy(image); - if (gcp) - *gcp = gc; - else - xcb_free_gc(display, gc); - return pix; -} - - -/* Thanks to Keith Packard <keithp@keithp.com> for this code */ -static void -swap_image(uint8_t * src, - uint32_t src_stride, - uint8_t * dst, - uint32_t dst_stride, - uint32_t height, - uint32_t byteswap, - int bitswap, - int nibbleswap) -{ - while (height--) { - uint32_t s; - - for (s = 0; s < src_stride; s++) { - uint8_t b; - uint32_t d = s ^ byteswap; - - if (d > dst_stride) - continue; - - b = src[s]; - if (bitswap) - b = xcb_bit_reverse(b, 8); - if (nibbleswap) - b = (b << 4) | (b >> 4); - dst[d] = b; - } - src += src_stride; - dst += dst_stride; - } -} - -/* Which order are bytes in (low two bits), given - * code which accesses an image one byte at a time - */ -static uint32_t -byte_order(xcb_image_t *i) -{ - uint32_t flip = i->byte_order == XCB_IMAGE_ORDER_MSB_FIRST; - - switch (i->bpp) { - default: - case 8: - return 0; - case 16: - return flip; - case 32: - return flip | (flip << 1); - } -} - -static uint32_t -bit_order(xcb_image_t *i) -{ - uint32_t flip = i->byte_order != i->bit_order; - - switch (i->unit) { - default: - case 8: - return 0; - case 16: - return flip; - case 32: - return flip | (flip << 1); - } -} - -/* Convert from one byte order to another by flipping the - * low two bits of the byte index along a scanline - */ -static uint32_t -conversion_byte_swap(xcb_image_t *src, xcb_image_t *dst) -{ - xcb_image_format_t ef = effective_format(src->format, src->bpp); - - /* src_ef == dst_ef in all callers of this function */ - if (ef == XCB_IMAGE_FORMAT_XY_PIXMAP) { - return bit_order(src) ^ bit_order(dst); - } else { - /* src_bpp == dst_bpp in all callers of this function */ - return byte_order(src) ^ byte_order(dst); - } -} - -xcb_image_t * -xcb_image_convert (xcb_image_t * src, - xcb_image_t * dst) -{ - xcb_image_format_t ef = effective_format(src->format, src->bpp); - - /* Things will go horribly wrong here if a bad - image is passed in, so we check some things - up front just to be nice. */ - assert(image_format_valid(src)); - assert(image_format_valid(dst)); - - /* images must be the same size - * (yes, we could copy a sub-set) - */ - if (src->width != dst->width || - src->height != dst->height) - return 0; - - if (ef == effective_format(dst->format, dst->bpp) && - src->bpp == dst->bpp) - { - if (src->unit == dst->unit && - src->scanline_pad == dst->scanline_pad && - src->byte_order == dst->byte_order && - (ef == XCB_IMAGE_FORMAT_Z_PIXMAP || - src->bit_order == dst->bit_order)) { - memcpy(dst->data, src->data, src->size); - } else { - int bitswap = 0; - int nibbleswap = 0; - uint32_t byteswap = conversion_byte_swap(src, dst); - uint32_t height = src->height;; - - if (ef == XCB_IMAGE_FORMAT_Z_PIXMAP) { - if (src->bpp == 4 && src->byte_order != dst->byte_order) - nibbleswap = 1; - } else { - if (src->bit_order != dst->bit_order) - bitswap = 1; - height *= src->depth; - } - swap_image (src->data, src->stride, dst->data, dst->stride, - height, byteswap, bitswap, nibbleswap); - } - } - else - { - uint32_t x; - uint32_t y; - /* General case: Slow pixel copy. Should we optimize - Z24<->Z32 copies of either endianness? */ - for (y = 0; y < src->height; y++) { - for (x = 0; x < src->width; x++) { - uint32_t pixel = xcb_image_get_pixel(src, x, y); - xcb_image_put_pixel(dst, x, y, pixel); - } - } - } - return dst; -} - -xcb_image_t * -xcb_image_subimage(xcb_image_t * image, - uint32_t x, - uint32_t y, - uint32_t width, - uint32_t height, - void * base, - uint32_t bytes, - uint8_t * data) -{ - int i, j; - xcb_image_t * result; - - if (x + width > image->width) - return 0; - if (y + height > image->height) - return 0; - result = xcb_image_create(width, height, image->format, - image->scanline_pad, image->depth, - image->bpp, image->unit, image->byte_order, - image->bit_order, - base, bytes, data); - if (!result) - return 0; - /* XXX FIXME For now, lose on performance. Sorry. */ - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - uint32_t pixel = xcb_image_get_pixel(image, x + i, y + j); - xcb_image_put_pixel(result, i, j, pixel); - } - } - return result; -} |