summaryrefslogtreecommitdiff
path: root/image/xcb_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'image/xcb_image.c')
-rw-r--r--image/xcb_image.c1009
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;
-}