[Spice-devel] [PATCH spice-gtk] use common submodule
Marc-André Lureau
marcandre.lureau at gmail.com
Wed Mar 14 18:20:00 PDT 2012
---
.gitmodules | 3 +
common | 1 +
common/.gitignore | 8 -
common/Makefile.am | 55 -
common/canvas_base.c | 3426 ----------------------------------------
common/canvas_base.h | 316 ----
common/canvas_utils.c | 307 ----
common/canvas_utils.h | 72 -
common/demarshallers.h | 28 -
common/draw.h | 274 ----
common/gdi_canvas.c | 1870 ----------------------
common/gdi_canvas.h | 39 -
common/gl_canvas.c | 909 -----------
common/gl_canvas.h | 37 -
common/gl_utils.h | 105 --
common/glc.c | 1521 ------------------
common/glc.c.save | 1413 -----------------
common/glc.h | 159 --
common/lines.c | 3618 -------------------------------------------
common/lines.h | 130 --
common/lz.c | 738 ---------
common/lz.h | 76 -
common/lz_common.h | 62 -
common/lz_compress_tmpl.c | 526 -------
common/lz_config.h | 48 -
common/lz_decompress_tmpl.c | 323 ----
common/macros.h | 30 -
common/marshaller.c | 614 --------
common/marshaller.h | 66 -
common/marshallers.h | 74 -
common/mem.c | 243 ---
common/mem.h | 129 --
common/messages.h | 550 -------
common/mutex.h | 35 -
common/ogl_ctx.c | 254 ---
common/ogl_ctx.h | 31 -
common/pixman_utils.c | 1614 -------------------
common/pixman_utils.h | 128 --
common/quic.c | 1706 --------------------
common/quic.h | 66 -
common/quic_config.h | 51 -
common/quic_family_tmpl.c | 115 --
common/quic_rgb_tmpl.c | 763 ---------
common/quic_tmpl.c | 633 --------
common/rect.h | 115 --
common/region.c | 893 -----------
common/region.h | 63 -
common/ring.h | 153 --
common/rop3.c | 657 --------
common/rop3.h | 34 -
common/ssl_verify.c | 477 ------
common/ssl_verify.h | 59 -
common/sw_canvas.c | 1321 ----------------
common/sw_canvas.h | 58 -
configure.ac | 2 +
gtk/Makefile.am | 8 +-
gtk/decode.h | 1 +
gtk/spice-channel-priv.h | 5 +-
58 files changed, 15 insertions(+), 26997 deletions(-)
create mode 160000 common
delete mode 100644 common/.gitignore
delete mode 100644 common/Makefile.am
delete mode 100644 common/canvas_base.c
delete mode 100644 common/canvas_base.h
delete mode 100644 common/canvas_utils.c
delete mode 100644 common/canvas_utils.h
delete mode 100644 common/demarshallers.h
delete mode 100644 common/draw.h
delete mode 100644 common/gdi_canvas.c
delete mode 100644 common/gdi_canvas.h
delete mode 100644 common/gl_canvas.c
delete mode 100644 common/gl_canvas.h
delete mode 100644 common/gl_utils.h
delete mode 100644 common/glc.c
delete mode 100644 common/glc.c.save
delete mode 100644 common/glc.h
delete mode 100644 common/lines.c
delete mode 100644 common/lines.h
delete mode 100644 common/lz.c
delete mode 100644 common/lz.h
delete mode 100644 common/lz_common.h
delete mode 100644 common/lz_compress_tmpl.c
delete mode 100644 common/lz_config.h
delete mode 100644 common/lz_decompress_tmpl.c
delete mode 100644 common/macros.h
delete mode 100644 common/marshaller.c
delete mode 100644 common/marshaller.h
delete mode 100644 common/marshallers.h
delete mode 100644 common/mem.c
delete mode 100644 common/mem.h
delete mode 100644 common/messages.h
delete mode 100644 common/mutex.h
delete mode 100644 common/ogl_ctx.c
delete mode 100644 common/ogl_ctx.h
delete mode 100644 common/pixman_utils.c
delete mode 100644 common/pixman_utils.h
delete mode 100644 common/quic.c
delete mode 100644 common/quic.h
delete mode 100644 common/quic_config.h
delete mode 100644 common/quic_family_tmpl.c
delete mode 100644 common/quic_rgb_tmpl.c
delete mode 100644 common/quic_tmpl.c
delete mode 100644 common/rect.h
delete mode 100644 common/region.c
delete mode 100644 common/region.h
delete mode 100644 common/ring.h
delete mode 100644 common/rop3.c
delete mode 100644 common/rop3.h
delete mode 100644 common/ssl_verify.c
delete mode 100644 common/ssl_verify.h
delete mode 100644 common/sw_canvas.c
delete mode 100644 common/sw_canvas.h
diff --git a/.gitmodules b/.gitmodules
index f7de75d..6981ae4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "spice-protocol"]
path = spice-protocol
url = ../spice-protocol
+[submodule "common"]
+ path = common
+ url = ../spice-common
diff --git a/common b/common
new file mode 160000
index 0000000..0da9c0d
--- /dev/null
+++ b/common
@@ -0,0 +1 @@
+Subproject commit 0da9c0d6ac4d709e00dd92b744cdd9f1bd1ca7de
diff --git a/common/.gitignore b/common/.gitignore
deleted file mode 100644
index 07491dd..0000000
--- a/common/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-*.la
-*.lo
-*.loT
-*.o
-.deps
-.libs
-Makefile
-Makefile.in
diff --git a/common/Makefile.am b/common/Makefile.am
deleted file mode 100644
index 17e36a3..0000000
--- a/common/Makefile.am
+++ /dev/null
@@ -1,55 +0,0 @@
-NULL =
-
-COMMON_SRCS = \
- sw_canvas.h \
- sw_canvas.c \
- pixman_utils.h \
- pixman_utils.c \
- canvas_base.h \
- canvas_base.c \
- canvas_utils.h \
- canvas_utils.c \
- demarshallers.h \
- draw.h \
- gdi_canvas.h \
- gdi_canvas.c \
- gl_canvas.h \
- gl_canvas.c \
- glc.h \
- glc.c \
- gl_utils.h \
- lz_common.h \
- mutex.h \
- ogl_ctx.h \
- ogl_ctx.c \
- quic.h \
- quic.c \
- quic_config.h \
- rect.h \
- region.h \
- region.c \
- ring.h \
- rop3.h \
- rop3.c \
- lines.h \
- lines.c \
- lz.c \
- lz_compress_tmpl.c \
- lz_config.h \
- lz_decompress_tmpl.c \
- lz.h \
- marshaller.h \
- marshaller.c \
- marshallers.h \
- messages.h \
- mem.h \
- mem.c \
- quic_family_tmpl.c \
- quic_rgb_tmpl.c \
- quic_tmpl.c \
- ssl_verify.h \
- ssl_verify.c \
- $(NULL)
-
-EXTRA_DIST = $(COMMON_SRCS)
-
diff --git a/common/canvas_base.c b/common/canvas_base.c
deleted file mode 100644
index 46a0cdd..0000000
--- a/common/canvas_base.c
+++ /dev/null
@@ -1,3426 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <math.h>
-
-#include <spice/macros.h>
-#include "quic.h"
-#include "lz.h"
-#include "canvas_base.h"
-#include "pixman_utils.h"
-#include "canvas_utils.h"
-#include "rect.h"
-#include "lines.h"
-#include "rop3.h"
-#include "mem.h"
-
-#include "mutex.h"
-
-#ifndef spice_return_if_fail
-#define spice_return_if_fail(x) if (!(x)) { \
- fprintf(stderr, "(%s:%d) %s: condition %s failed\n", __FILE__, __LINE__, __FUNCTION__, #x); \
- return; \
-}
-#endif
-
-#ifndef spice_return_val_if_fail
-#define spice_return_val_if_fail(x, val) if (!(x)) { \
- fprintf(stderr, "(%s:%d) %s: condition %s failed\n", __FILE__, __LINE__, __FUNCTION__, #x); \
- return (val); \
-}
-#endif
-
-#ifndef spice_warn_if_reached
-#define spice_warn_if_reached() do { \
- fprintf(stderr, "(%s:%d) %s: should not be reached", __FILE__, __LINE__, __FUNCTION__); \
-}while(0)
-#endif
-
-#ifndef spice_warning
-#define spice_warning(x) do { \
- fprintf(stderr, "(%s:%d) %s: warning %s", __FILE__, __LINE__, __FUNCTION__, (x)); \
-} while(0)
-#endif
-
-#ifndef spice_critical
-#define spice_critical(x) do { \
- fprintf(stderr, "(%s:%d) %s: CRITICAL %s", __FILE__, __LINE__, __FUNCTION__, (x)); \
-} while(0)
-#endif
-
-#define ROUND(_x) ((int)floor((_x) + 0.5))
-
-#define IS_IMAGE_LOSSY(descriptor) \
- (((descriptor)->type == SPICE_IMAGE_TYPE_JPEG) || \
- ((descriptor)->type == SPICE_IMAGE_TYPE_JPEG_ALPHA))
-
- static inline int fix_to_int(SPICE_FIXED28_4 fixed)
-{
- int val, rem;
-
- rem = fixed & 0x0f;
- val = fixed >> 4;
- if (rem > 8) {
- val++;
- }
- return val;
-}
-
- static inline SPICE_FIXED28_4 int_to_fix(int v)
-{
- return v << 4;
-}
-
-static inline double fix_to_double(SPICE_FIXED28_4 fixed)
-{
- return (double)(fixed & 0x0f) / 0x0f + (fixed >> 4);
-}
-
-static inline uint16_t rgb_32_to_16_555(uint32_t color)
-{
- return
- (((color) >> 3) & 0x001f) |
- (((color) >> 6) & 0x03e0) |
- (((color) >> 9) & 0x7c00);
-}
-static inline uint16_t rgb_32_to_16_565(uint32_t color)
-{
- return
- (((color) >> 3) & 0x001f) |
- (((color) >> 5) & 0x07e0) |
- (((color) >> 8) & 0xf800);
-}
-
-static inline uint32_t canvas_16bpp_to_32bpp(uint32_t color)
-{
- uint32_t ret;
-
- ret = ((color & 0x001f) << 3) | ((color & 0x001c) >> 2);
- ret |= ((color & 0x03e0) << 6) | ((color & 0x0380) << 1);
- ret |= ((color & 0x7c00) << 9) | ((color & 0x7000) << 4);
-
- return ret;
-}
-#if defined(WIN32) && defined(GDI_CANVAS)
-static HDC create_compatible_dc()
-{
- HDC dc = CreateCompatibleDC(NULL);
-
- spice_return_val_if_fail(dc != NULL, NULL);
-
- return dc;
-}
-
-#endif
-
-typedef struct LzData {
- LzUsrContext usr;
- LzContext *lz;
- LzDecodeUsrData decode_data;
- jmp_buf jmp_env;
- char message_buf[512];
-} LzData;
-
-typedef struct GlzData {
- SpiceGlzDecoder *decoder;
- LzDecodeUsrData decode_data;
-} GlzData;
-
-typedef struct QuicData {
- QuicUsrContext usr;
- QuicContext *quic;
- jmp_buf jmp_env;
- char message_buf[512];
- SpiceChunks *chunks;
- uint32_t current_chunk;
-} QuicData;
-
-typedef struct CanvasBase {
- SpiceCanvas parent;
- uint32_t color_shift;
- uint32_t color_mask;
- QuicData quic_data;
-
- uint32_t format;
- int width;
- int height;
- pixman_region32_t canvas_region;
-
-#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
- SpiceImageCache *bits_cache;
-#endif
-#ifdef SW_CANVAS_CACHE
- SpicePaletteCache *palette_cache;
-#endif
-#ifdef WIN32
- HDC dc;
-#endif
-
- SpiceImageSurfaces *surfaces;
-
- LzData lz_data;
- GlzData glz_data;
- SpiceJpegDecoder* jpeg;
- SpiceZlibDecoder* zlib;
-
- void *usr_data;
- spice_destroy_fn_t usr_data_destroy;
-} CanvasBase;
-
-typedef enum {
- ROP_INPUT_SRC,
- ROP_INPUT_BRUSH,
- ROP_INPUT_DEST
-} ROPInput;
-
-static SpiceROP ropd_descriptor_to_rop(int desc,
- ROPInput src_input,
- ROPInput dest_input)
-{
- int old;
- int invert_masks[] = {
- SPICE_ROPD_INVERS_SRC,
- SPICE_ROPD_INVERS_BRUSH,
- SPICE_ROPD_INVERS_DEST
- };
-
- old = desc;
-
- desc &= ~(SPICE_ROPD_INVERS_SRC | SPICE_ROPD_INVERS_DEST);
- if (old & invert_masks[src_input]) {
- desc |= SPICE_ROPD_INVERS_SRC;
- }
-
- if (old & invert_masks[dest_input]) {
- desc |= SPICE_ROPD_INVERS_DEST;
- }
-
- if (desc & SPICE_ROPD_OP_PUT) {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_RES) {
- return SPICE_ROP_COPY;
- }
- return SPICE_ROP_COPY_INVERTED;
- } else {
- if (desc & SPICE_ROPD_INVERS_RES) {
- return SPICE_ROP_COPY_INVERTED;
- }
- return SPICE_ROP_COPY;
- }
- } else if (desc & SPICE_ROPD_OP_OR) {
-
- if (desc & SPICE_ROPD_INVERS_RES) {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !(!src or !dest) == src and dest*/
- return SPICE_ROP_AND;
- } else {
- /* ! (!src or dest) = src and !dest*/
- return SPICE_ROP_AND_REVERSE;
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !(src or !dest) == !src and dest */
- return SPICE_ROP_AND_INVERTED;
- } else {
- /* !(src or dest) */
- return SPICE_ROP_NOR;
- }
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !src or !dest == !(src and dest)*/
- return SPICE_ROP_NAND;
- } else {
- /* !src or dest */
- return SPICE_ROP_OR_INVERTED;
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* src or !dest */
- return SPICE_ROP_OR_REVERSE;
- } else {
- /* src or dest */
- return SPICE_ROP_OR;
- }
- }
- }
-
- } else if (desc & SPICE_ROPD_OP_AND) {
-
- if (desc & SPICE_ROPD_INVERS_RES) {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !(!src and !dest) == src or dest*/
- return SPICE_ROP_OR;
- } else {
- /* ! (!src and dest) = src or !dest*/
- return SPICE_ROP_OR_REVERSE;
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !(src and !dest) == !src or dest */
- return SPICE_ROP_OR_INVERTED;
- } else {
- /* !(src and dest) */
- return SPICE_ROP_NAND;
- }
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !src and !dest == !(src or dest)*/
- return SPICE_ROP_NOR;
- } else {
- /* !src and dest */
- return SPICE_ROP_AND_INVERTED;
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* src and !dest */
- return SPICE_ROP_AND_REVERSE;
- } else {
- /* src and dest */
- return SPICE_ROP_AND;
- }
- }
- }
-
- } else if (desc & SPICE_ROPD_OP_XOR) {
-
- if (desc & SPICE_ROPD_INVERS_RES) {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !(!src xor !dest) == !src xor dest */
- return SPICE_ROP_EQUIV;
- } else {
- /* ! (!src xor dest) = src xor dest*/
- return SPICE_ROP_XOR;
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !(src xor !dest) == src xor dest */
- return SPICE_ROP_XOR;
- } else {
- /* !(src xor dest) */
- return SPICE_ROP_EQUIV;
- }
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_SRC) {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* !src xor !dest == src xor dest */
- return SPICE_ROP_XOR;
- } else {
- /* !src xor dest */
- return SPICE_ROP_EQUIV;
- }
- } else {
- if (desc & SPICE_ROPD_INVERS_DEST) {
- /* src xor !dest */
- return SPICE_ROP_EQUIV;
- } else {
- /* src xor dest */
- return SPICE_ROP_XOR;
- }
- }
- }
-
- } else if (desc & SPICE_ROPD_OP_BLACKNESS) {
- return SPICE_ROP_CLEAR;
- } else if (desc & SPICE_ROPD_OP_WHITENESS) {
- return SPICE_ROP_SET;
- } else if (desc & SPICE_ROPD_OP_INVERS) {
- return SPICE_ROP_INVERT;
- }
- return SPICE_ROP_COPY;
-}
-
-//#define DEBUG_DUMP_COMPRESS
-#ifdef DEBUG_DUMP_COMPRESS
-static void dump_surface(pixman_image_t *surface, int cache);
-#endif
-
-
-static pixman_format_code_t canvas_get_target_format(CanvasBase *canvas,
- int source_has_alpha)
-{
- pixman_format_code_t format;
-
- /* Convert to target surface format */
- format = spice_surface_format_to_pixman (canvas->format);
-
- if (source_has_alpha) {
- /* Even though the destination has no alpha, we make the source
- * remember there are alpha bits instead of throwing away this
- * information. The results are the same if alpha is not
- * interpreted, and if need to interpret alpha, don't use
- * conversion to target format.
- * This is needed for instance when doing the final
- * canvas_get_target_format() in canvas_get_image_internal
- * as otherwise we wouldn't know if the bitmap source
- * really had alpha.
- */
- if (format == PIXMAN_x8r8g8b8) {
- format = PIXMAN_a8r8g8b8;
- }
- } else { /* !source_has_alpha */
- /* If the source doesn't have alpha, but the destination has,
- don't convert to alpha, since that would just do an unnecessary
- copy to fill the alpha bytes with 0xff which is not expected if
- we just use the raw bits, (and handled implicitly by pixman if
- we're interpreting data) */
- if (format == PIXMAN_a8r8g8b8) {
- format = PIXMAN_x8r8g8b8;
- }
- }
-
- return format;
-}
-
-static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceImage *image,
- int invers, int want_original)
-{
- pixman_image_t *surface = NULL;
- QuicData *quic_data = &canvas->quic_data;
- QuicImageType type, as_type;
- pixman_format_code_t pixman_format;
- uint8_t *dest;
- int stride;
- int width;
- int height;
-
- if (setjmp(quic_data->jmp_env)) {
- pixman_image_unref(surface);
- spice_warning(quic_data->message_buf);
- return NULL;
- }
-
- quic_data->chunks = image->u.quic.data;
- quic_data->current_chunk = 0;
-
- if (quic_decode_begin(quic_data->quic,
- (uint32_t *)image->u.quic.data->chunk[0].data,
- image->u.quic.data->chunk[0].len >> 2,
- &type, &width, &height) == QUIC_ERROR) {
- spice_warning("quic decode begin failed");
- return NULL;
- }
-
- switch (type) {
- case QUIC_IMAGE_TYPE_RGBA:
- as_type = QUIC_IMAGE_TYPE_RGBA;
- pixman_format = PIXMAN_a8r8g8b8;
- break;
- case QUIC_IMAGE_TYPE_RGB32:
- case QUIC_IMAGE_TYPE_RGB24:
- as_type = QUIC_IMAGE_TYPE_RGB32;
- pixman_format = PIXMAN_x8r8g8b8;
- break;
- case QUIC_IMAGE_TYPE_RGB16:
- if (!want_original &&
- (canvas->format == SPICE_SURFACE_FMT_32_xRGB ||
- canvas->format == SPICE_SURFACE_FMT_32_ARGB)) {
- as_type = QUIC_IMAGE_TYPE_RGB32;
- pixman_format = PIXMAN_x8r8g8b8;
- } else {
- as_type = QUIC_IMAGE_TYPE_RGB16;
- pixman_format = PIXMAN_x1r5g5b5;
- }
- break;
- case QUIC_IMAGE_TYPE_INVALID:
- case QUIC_IMAGE_TYPE_GRAY:
- default:
- spice_warn_if_reached();
- return NULL;
- }
-
- spice_return_val_if_fail((uint32_t)width == image->descriptor.width, NULL);
- spice_return_val_if_fail((uint32_t)height == image->descriptor.height, NULL);
-
- surface = surface_create(
-#ifdef WIN32
- canvas->dc,
-#endif
- pixman_format,
- width, height, FALSE);
-
- spice_return_val_if_fail(surface != NULL, NULL);
-
- dest = (uint8_t *)pixman_image_get_data(surface);
- stride = pixman_image_get_stride(surface);
- if (quic_decode(quic_data->quic, as_type,
- dest, stride) == QUIC_ERROR) {
- pixman_image_unref(surface);
- spice_warning("quic decode failed");
- return NULL;
- }
-
- if (invers) {
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride) {
- uint32_t *pix;
- uint32_t *end_pix;
-
- pix = (uint32_t *)dest;
- end_pix = pix + width;
- for (; pix < end_pix; pix++) {
- *pix ^= 0xffffffff;
- }
- }
- }
-
-#ifdef DEBUG_DUMP_COMPRESS
- dump_surface(surface, 0);
-#endif
- return surface;
-}
-
-
-//#define DUMP_JPEG
-#ifdef DUMP_JPEG
-static int jpeg_id = 0;
-static void dump_jpeg(uint8_t* data, int data_size)
-{
- char file_str[200];
- uint32_t id = ++jpeg_id;
-
-#ifdef WIN32
- sprintf(file_str, "c:\\tmp\\spice_dump\\%u.jpg", id);
-#else
- sprintf(file_str, "/tmp/spice_dump/%u.jpg", id);
-#endif
-
- FILE *f = fopen(file_str, "wb");
- if (!f) {
- return;
- }
-
- fwrite(data, 1, data_size, f);
- fclose(f);
-}
-#endif
-
-static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceImage *image, int invers)
-{
- pixman_image_t *surface = NULL;
- int stride;
- int width;
- int height;
- uint8_t *dest;
-
- spice_return_val_if_fail(image->u.jpeg.data->num_chunks == 1, NULL);
- canvas->jpeg->ops->begin_decode(canvas->jpeg, image->u.jpeg.data->chunk[0].data, image->u.jpeg.data->chunk[0].len,
- &width, &height);
- spice_return_val_if_fail((uint32_t)width == image->descriptor.width, NULL);
- spice_return_val_if_fail((uint32_t)height == image->descriptor.height, NULL);
-
- surface = surface_create(
-#ifdef WIN32
- canvas->dc,
-#endif
- PIXMAN_x8r8g8b8,
- width, height, FALSE);
- if (surface == NULL) {
- spice_warning("create surface failed");
- return NULL;
- }
-
- dest = (uint8_t *)pixman_image_get_data(surface);
- stride = pixman_image_get_stride(surface);
-
- canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT);
-
- if (invers) {
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride) {
- uint32_t *pix;
- uint32_t *end_pix;
-
- pix = (uint32_t *)dest;
- end_pix = pix + width;
- for (; pix < end_pix; pix++) {
- *pix ^= 0x00ffffff;
- }
- }
- }
-#ifdef DUMP_JPEG
- dump_jpeg(image->u.jpeg.data, image->u.jpeg.data_size);
-#endif
- return surface;
-}
-
-static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas,
- SpiceImage *image, int invers)
-{
- pixman_image_t *surface = NULL;
- int stride;
- int width;
- int height;
- uint8_t *dest;
- int alpha_top_down = FALSE;
- LzData *lz_data = &canvas->lz_data;
- LzImageType lz_alpha_type;
- uint8_t *comp_alpha_buf = NULL;
- uint8_t *decomp_alpha_buf = NULL;
- int alpha_size;
- int lz_alpha_width, lz_alpha_height, n_comp_pixels, lz_alpha_top_down;
-
- spice_return_val_if_fail(image->u.jpeg_alpha.data->num_chunks == 1, NULL);
- canvas->jpeg->ops->begin_decode(canvas->jpeg,
- image->u.jpeg_alpha.data->chunk[0].data,
- image->u.jpeg_alpha.jpeg_size,
- &width, &height);
- spice_return_val_if_fail((uint32_t)width == image->descriptor.width, NULL);
- spice_return_val_if_fail((uint32_t)height == image->descriptor.height, NULL);
-
- if (image->u.jpeg_alpha.flags & SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN) {
- alpha_top_down = TRUE;
- }
-
-#ifdef WIN32
- lz_data->decode_data.dc = canvas->dc;
-#endif
- surface = alloc_lz_image_surface(&lz_data->decode_data, PIXMAN_a8r8g8b8,
- width, height, width*height, alpha_top_down);
-
- if (surface == NULL) {
- spice_warning("create surface failed");
- return NULL;
- }
-
- dest = (uint8_t *)pixman_image_get_data(surface);
- stride = pixman_image_get_stride(surface);
-
- canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT);
-
- comp_alpha_buf = image->u.jpeg_alpha.data->chunk[0].data + image->u.jpeg_alpha.jpeg_size;
- alpha_size = image->u.jpeg_alpha.data_size - image->u.jpeg_alpha.jpeg_size;
-
- lz_decode_begin(lz_data->lz, comp_alpha_buf, alpha_size, &lz_alpha_type,
- &lz_alpha_width, &lz_alpha_height, &n_comp_pixels,
- &lz_alpha_top_down, NULL);
- spice_return_val_if_fail(lz_alpha_type == LZ_IMAGE_TYPE_XXXA, NULL);
- spice_return_val_if_fail(!!lz_alpha_top_down == !!alpha_top_down, NULL);
- spice_return_val_if_fail(lz_alpha_width == width, NULL);
- spice_return_val_if_fail(lz_alpha_height == height, NULL);
- spice_return_val_if_fail(n_comp_pixels == width * height, NULL);
-
- if (!alpha_top_down) {
- decomp_alpha_buf = dest + stride * (height - 1);
- } else {
- decomp_alpha_buf = dest;
- }
- lz_decode(lz_data->lz, LZ_IMAGE_TYPE_XXXA, decomp_alpha_buf);
-
- if (invers) {
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride) {
- uint32_t *pix;
- uint32_t *end_pix;
-
- pix = (uint32_t *)dest;
- end_pix = pix + width;
- for (; pix < end_pix; pix++) {
- *pix ^= 0x00ffffff;
- }
- }
- }
-#ifdef DUMP_JPEG
- dump_jpeg(image->u.jpeg_alpha.data, image->u.jpeg_alpha.jpeg_size);
-#endif
- return surface;
-}
-
-static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap* bitmap,
- SpicePalette *palette, int want_original)
-{
- uint8_t* src;
- pixman_image_t *image;
- pixman_format_code_t format;
-
- spice_chunks_linearize(bitmap->data);
-
- src = bitmap->data->chunk[0].data;
-
- if (want_original) {
- format = spice_bitmap_format_to_pixman(bitmap->format, canvas->format);
- } else {
- format = canvas_get_target_format(canvas,
- bitmap->format == SPICE_BITMAP_FMT_RGBA);
- }
-
- image = surface_create(
-#ifdef WIN32
- canvas->dc,
-#endif
- format,
- bitmap->x, bitmap->y, FALSE);
- if (image == NULL) {
- spice_warning("create surface failed");
- return NULL;
- }
-
- spice_bitmap_convert_to_pixman(format, image,
- bitmap->format,
- bitmap->flags,
- bitmap->x, bitmap->y,
- src, bitmap->stride,
- canvas->format, palette);
- return image;
-}
-
-
-#ifdef SW_CANVAS_CACHE
-
-static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags)
-{
- SpicePalette *palette;
-
- if (flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE) {
- palette = canvas->palette_cache->ops->get(canvas->palette_cache, palette_id);
- } else {
- palette = base_palette;
- if (palette != NULL && flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME) {
- canvas->palette_cache->ops->put(canvas->palette_cache, palette);
- }
- }
- return palette;
-}
-
-static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags, int *free_palette)
-{
- SpicePalette *palette = canvas_get_palette(canvas, base_palette, palette_id, flags);
- SpicePalette *copy;
- uint32_t *now, *end;
- size_t size;
-
- if (canvas->format == SPICE_SURFACE_FMT_32_xRGB ||
- canvas->format == SPICE_SURFACE_FMT_32_ARGB) {
- return palette;
- }
-
- size = sizeof(SpicePalette) + palette->num_ents * 4;
- copy = (SpicePalette *)spice_malloc(size);
- memcpy(copy, palette, size);
-
- switch (canvas->format) {
- case SPICE_SURFACE_FMT_32_xRGB:
- case SPICE_SURFACE_FMT_32_ARGB:
- /* Won't happen */
- break;
- case SPICE_SURFACE_FMT_16_555:
- now = copy->ents;
- end = now + copy->num_ents;
- for (; now < end; now++) {
- *now = canvas_16bpp_to_32bpp(*now);
- }
- break;
- case SPICE_SURFACE_FMT_16_565:
- default:
- spice_warn_if_reached();
- return NULL;
- }
- *free_palette = TRUE;
- return copy;
-}
-
-static pixman_image_t *canvas_get_lz(CanvasBase *canvas, SpiceImage *image, int invers,
- int want_original)
-{
- LzData *lz_data = &canvas->lz_data;
- uint8_t *comp_buf = NULL;
- int comp_size;
- uint8_t *decomp_buf = NULL;
- uint8_t *src;
- pixman_format_code_t pixman_format;
- LzImageType type, as_type;
- SpicePalette *palette;
- int n_comp_pixels;
- int width;
- int height;
- int top_down;
- int stride;
- int free_palette;
-
- if (setjmp(lz_data->jmp_env)) {
- if (decomp_buf) {
- free(decomp_buf);
- }
- spice_warning(lz_data->message_buf);
- return NULL;
- }
-
- free_palette = FALSE;
- if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB) {
- spice_return_val_if_fail(image->u.lz_rgb.data->num_chunks == 1, NULL); /* TODO: Handle chunks */
- comp_buf = image->u.lz_rgb.data->chunk[0].data;
- comp_size = image->u.lz_rgb.data->chunk[0].len;
- palette = NULL;
- } else if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) {
- spice_return_val_if_fail(image->u.lz_plt.data->num_chunks == 1, NULL); /* TODO: Handle chunks */
- comp_buf = image->u.lz_plt.data->chunk[0].data;
- comp_size = image->u.lz_plt.data->chunk[0].len;
- palette = canvas_get_localized_palette(canvas, image->u.lz_plt.palette, image->u.lz_plt.palette_id, image->u.lz_plt.flags, &free_palette);
- } else {
- spice_warn_if_reached();
- return NULL;
- }
-
- lz_decode_begin(lz_data->lz, comp_buf, comp_size, &type,
- &width, &height, &n_comp_pixels, &top_down, palette);
-
- switch (type) {
- case LZ_IMAGE_TYPE_RGBA:
- as_type = LZ_IMAGE_TYPE_RGBA;
- pixman_format = PIXMAN_a8r8g8b8;
- break;
- case LZ_IMAGE_TYPE_RGB32:
- case LZ_IMAGE_TYPE_RGB24:
- case LZ_IMAGE_TYPE_PLT1_LE:
- case LZ_IMAGE_TYPE_PLT1_BE:
- case LZ_IMAGE_TYPE_PLT4_LE:
- case LZ_IMAGE_TYPE_PLT4_BE:
- case LZ_IMAGE_TYPE_PLT8:
- as_type = LZ_IMAGE_TYPE_RGB32;
- pixman_format = PIXMAN_x8r8g8b8;
- break;
- case LZ_IMAGE_TYPE_RGB16:
- if (!want_original &&
- (canvas->format == SPICE_SURFACE_FMT_32_xRGB ||
- canvas->format == SPICE_SURFACE_FMT_32_ARGB)) {
- as_type = LZ_IMAGE_TYPE_RGB32;
- pixman_format = PIXMAN_x8r8g8b8;
- } else {
- as_type = LZ_IMAGE_TYPE_RGB16;
- pixman_format = PIXMAN_x1r5g5b5;
- }
- break;
- default:
- spice_warn_if_reached();
- return NULL;
- }
-
- spice_return_val_if_fail((unsigned)width == image->descriptor.width, NULL);
- spice_return_val_if_fail((unsigned)height == image->descriptor.height, NULL);
-
- spice_return_val_if_fail((image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) || (n_comp_pixels == width * height), NULL);
-#ifdef WIN32
- lz_data->decode_data.dc = canvas->dc;
-#endif
-
-
- alloc_lz_image_surface(&lz_data->decode_data, pixman_format,
- width, height, n_comp_pixels, top_down);
-
- src = (uint8_t *)pixman_image_get_data(lz_data->decode_data.out_surface);
-
- stride = (n_comp_pixels / height) * 4;
- if (!top_down) {
- stride = -stride;
- decomp_buf = src + stride * (height - 1);
- } else {
- decomp_buf = src;
- }
-
- lz_decode(lz_data->lz, as_type, decomp_buf);
-
- if (invers) {
- uint8_t *line = src;
- uint8_t *end = src + height * stride;
- for (; line != end; line += stride) {
- uint32_t *pix;
- uint32_t *end_pix;
-
- pix = (uint32_t *)line;
- end_pix = pix + width;
- for (; pix < end_pix; pix++) {
- *pix ^= 0xffffffff;
- }
- }
- }
-
- if (free_palette) {
- free(palette);
- }
-
- return lz_data->decode_data.out_surface;
-}
-
-static pixman_image_t *canvas_get_glz_rgb_common(CanvasBase *canvas, uint8_t *data,
- int want_original)
-{
- spice_return_val_if_fail(canvas->glz_data.decoder != NULL, NULL);
-
- canvas->glz_data.decoder->ops->decode(canvas->glz_data.decoder,
- data, NULL,
- &canvas->glz_data.decode_data);
-
- /* global_decode calls alloc_lz_image, which sets canvas->glz_data.surface */
- return (canvas->glz_data.decode_data.out_surface);
-}
-
-// don't handle plts since bitmaps with plt can be decoded globally to RGB32 (because
-// same byte sequence can be transformed to different RGB pixels by different plts)
-static pixman_image_t *canvas_get_glz(CanvasBase *canvas, SpiceImage *image,
- int want_original)
-{
- spice_return_val_if_fail(image->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB, NULL);
-#ifdef WIN32
- canvas->glz_data.decode_data.dc = canvas->dc;
-#endif
-
- spice_return_val_if_fail(image->u.lz_rgb.data->num_chunks == 1, NULL); /* TODO: Handle chunks */
- return canvas_get_glz_rgb_common(canvas, image->u.lz_rgb.data->chunk[0].data, want_original);
-}
-
-static pixman_image_t *canvas_get_zlib_glz_rgb(CanvasBase *canvas, SpiceImage *image,
- int want_original)
-{
- uint8_t *glz_data;
- pixman_image_t *surface;
-
- spice_return_val_if_fail(canvas->zlib != NULL, NULL);
-
- spice_return_val_if_fail(image->u.zlib_glz.data->num_chunks == 1, NULL); /* TODO: Handle chunks */
- glz_data = (uint8_t*)spice_malloc(image->u.zlib_glz.glz_data_size);
- canvas->zlib->ops->decode(canvas->zlib, image->u.zlib_glz.data->chunk[0].data,
- image->u.zlib_glz.data->chunk[0].len,
- glz_data, image->u.zlib_glz.glz_data_size);
- surface = canvas_get_glz_rgb_common(canvas, glz_data, want_original);
- free(glz_data);
- return surface;
-}
-
-//#define DEBUG_DUMP_BITMAP
-
-#ifdef DEBUG_DUMP_BITMAP
-static void dump_bitmap(SpiceBitmap *bitmap, SpicePalette *palette)
-{
- uint8_t* data = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data);
- static uint32_t file_id = 0;
- uint32_t i, j;
- char file_str[200];
- uint32_t id = ++file_id;
-
-#ifdef WIN32
- sprintf(file_str, "c:\\tmp\\spice_dump\\%u.%ubpp", id, bitmap->format);
-#else
- sprintf(file_str, "/tmp/spice_dump/%u.%ubpp", id, bitmap->format);
-#endif
- FILE *f = fopen(file_str, "wb");
- if (!f) {
- return;
- }
-
- fprintf(f, "%d\n", bitmap->format); // 1_LE,1_BE,....
- fprintf(f, "%d %d\n", bitmap->x, bitmap->y); // width and height
- fprintf(f, "%d\n", palette->num_ents); // #plt entries
- for (i = 0; i < palette->num_ents; i++) {
- fwrite(&(palette->ents[i]), 4, 1, f);
- }
- fprintf(f, "\n");
-
- for (i = 0; i < bitmap->y; i++, data += bitmap->stride) {
- uint8_t *now = data;
- for (j = 0; j < bitmap->x; j++) {
- fwrite(now, 1, 1, f);
- now++;
- }
- }
-}
-
-#endif
-
-static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap,
- int want_original)
-{
- pixman_image_t* surface;
- SpicePalette *palette;
-
- palette = canvas_get_palette(canvas, bitmap->palette, bitmap->palette_id, bitmap->flags);
-#ifdef DEBUG_DUMP_BITMAP
- if (palette) {
- dump_bitmap(bitmap, palette);
- }
-#endif
-
- surface = canvas_bitmap_to_surface(canvas, bitmap, palette, want_original);
-
- if (palette && (bitmap->flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
- canvas->palette_cache->ops->release(canvas->palette_cache, palette);
- }
-
- return surface;
-}
-
-#else
-
-
-static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap,
- int want_original)
-{
- SpicePalette *palette;
-
- if (!bitmap->palette) {
- return canvas_bitmap_to_surface(canvas, bitmap, NULL, want_original);
- }
- palette = (SpicePalette *)SPICE_GET_ADDRESS(bitmap->palette);
- return canvas_bitmap_to_surface(canvas, bitmap, palette, want_original);
-}
-
-#endif
-
-
-
-// caution: defining DEBUG_DUMP_SURFACE will dump both cached & non-cached
-// images to disk. it will reduce performance dramatically & eat
-// disk space rapidly. use it only for debugging.
-//#define DEBUG_DUMP_SURFACE
-
-#if defined(DEBUG_DUMP_SURFACE) || defined(DEBUG_DUMP_COMPRESS)
-
-static void dump_surface(pixman_image_t *surface, int cache)
-{
- static uint32_t file_id = 0;
- int i, j;
- char file_str[200];
- int depth = pixman_image_get_depth(surface);
-
- if (depth != 24 && depth != 32) {
- return;
- }
-
- uint8_t *data = (uint8_t *)pixman_image_get_data(surface);
- int width = pixman_image_get_width(surface);
- int height = pixman_image_get_height(surface);
- int stride = pixman_image_surface_get_stride(surface);
-
- uint32_t id = ++file_id;
-#ifdef WIN32
- sprintf(file_str, "c:\\tmp\\spice_dump\\%d\\%u.ppm", cache, id);
-#else
- sprintf(file_str, "/tmp/spice_dump/%u.ppm", id);
-#endif
- FILE *f = fopen(file_str, "wb");
- if (!f) {
- return;
- }
- fprintf(f, "P6\n");
- fprintf(f, "%d %d\n", width, height);
- fprintf(f, "#spicec dump\n");
- fprintf(f, "255\n");
- for (i = 0; i < height; i++, data += stride) {
- uint8_t *now = data;
- for (j = 0; j < width; j++) {
- fwrite(&now[2], 1, 1, f);
- fwrite(&now[1], 1, 1, f);
- fwrite(&now[0], 1, 1, f);
- now += 4;
- }
- }
- fclose(f);
-}
-
-#endif
-
-static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SpiceImage *image)
-{
- if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
- SpiceSurface *surface = &image->u.surface;
- return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id);
- }
- return NULL;
-}
-
-static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SpiceImage *image)
-{
- if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
- SpiceSurface *surface = &image->u.surface;
- return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id);
- }
- return NULL;
-}
-
-#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
-
-//#define DEBUG_LZ
-
-/* If real get is FALSE, then only do whatever is needed but don't return an image. For instance,
- * if we need to read it to cache it we do.
- *
- * This generally converts the image to the right type for the canvas.
- * However, if want_original is set the real source format is returned, and
- * you have to be able to handle any image format. This is useful to avoid
- * e.g. losing alpha when blending a argb32 image on a rgb16 surface.
- */
-static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image,
- int want_original, int real_get)
-{
- SpiceImageDescriptor *descriptor = &image->descriptor;
- pixman_image_t *surface, *converted;
- pixman_format_code_t wanted_format, surface_format;
- int saved_want_original;
-
- /* When touching, only really allocate if we need to cache, or
- * if we're loading a GLZ stream (since those need inter-thread communication
- * to happen which breaks if we don't. */
- if (!real_get &&
- !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME) &&
-#ifdef SW_CANVAS_CACHE
- !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) &&
-#endif
- (descriptor->type != SPICE_IMAGE_TYPE_GLZ_RGB) &&
- (descriptor->type != SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB)) {
- return NULL;
- }
-
- saved_want_original = want_original;
- if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME
-#ifdef SW_CANVAS_CACHE
- || descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME
-#endif
- ) {
- want_original = TRUE;
- }
-
- switch (descriptor->type) {
- case SPICE_IMAGE_TYPE_QUIC: {
- surface = canvas_get_quic(canvas, image, 0, want_original);
- break;
- }
-#if defined(SW_CANVAS_CACHE)
- case SPICE_IMAGE_TYPE_LZ_PLT: {
- surface = canvas_get_lz(canvas, image, 0, want_original);
- break;
- }
- case SPICE_IMAGE_TYPE_LZ_RGB: {
- surface = canvas_get_lz(canvas, image, 0, want_original);
- break;
- }
-#endif
- case SPICE_IMAGE_TYPE_JPEG: {
- surface = canvas_get_jpeg(canvas, image, 0);
- break;
- }
- case SPICE_IMAGE_TYPE_JPEG_ALPHA: {
- surface = canvas_get_jpeg_alpha(canvas, image, 0);
- break;
- }
-#if defined(SW_CANVAS_CACHE)
- case SPICE_IMAGE_TYPE_GLZ_RGB: {
- surface = canvas_get_glz(canvas, image, want_original);
- break;
- }
- case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: {
- surface = canvas_get_zlib_glz_rgb(canvas, image, want_original);
- break;
- }
-#endif
- case SPICE_IMAGE_TYPE_FROM_CACHE:
- surface = canvas->bits_cache->ops->get(canvas->bits_cache, descriptor->id);
- break;
-#ifdef SW_CANVAS_CACHE
- case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS:
- surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, descriptor->id);
- break;
-#endif
- case SPICE_IMAGE_TYPE_BITMAP: {
- surface = canvas_get_bits(canvas, &image->u.bitmap, want_original);
- break;
- }
- default:
- spice_warn_if_reached();
- return NULL;
- }
-
- spice_return_val_if_fail(surface != NULL, NULL);
- surface_format = spice_pixman_image_get_format(surface);
-
- if (descriptor->flags & SPICE_IMAGE_FLAGS_HIGH_BITS_SET &&
- descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE &&
-#ifdef SW_CANVAS_CACHE
- descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS &&
-#endif
- surface_format == PIXMAN_x8r8g8b8) {
- spice_pixman_fill_rect_rop(surface,
- 0, 0,
- pixman_image_get_width(surface),
- pixman_image_get_height(surface),
- 0xff000000U, SPICE_ROP_OR);
- }
-
- if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME &&
-#ifdef SW_CANVAS_CACHE
- descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS &&
-#endif
- descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE ) {
-#ifdef SW_CANVAS_CACHE
- if (!IS_IMAGE_LOSSY(descriptor)) {
- canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface);
- } else {
- canvas->bits_cache->ops->put_lossy(canvas->bits_cache, descriptor->id, surface);
- }
-#else
- canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface);
-#endif
-#ifdef DEBUG_DUMP_SURFACE
- dump_surface(surface, 1);
-#endif
-#ifdef SW_CANVAS_CACHE
- } else if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) {
- if (IS_IMAGE_LOSSY(descriptor)) {
- spice_warning("invalid cache replace request: the image is lossy");
- return NULL;
- }
- canvas->bits_cache->ops->replace_lossy(canvas->bits_cache, descriptor->id, surface);
-#ifdef DEBUG_DUMP_SURFACE
- dump_surface(surface, 1);
-#endif
-#endif
-#ifdef DEBUG_DUMP_SURFACE
- } else if (descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE
-#ifdef SW_CANVAS_CACHE
- && descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS
-#endif
- ) {
-
- dump_surface(surface, 0);
-#endif
- }
-
- if (!real_get) {
- pixman_image_unref(surface);
- return NULL;
- }
-
- if (!saved_want_original) {
- /* Conversion to canvas format was requested, but maybe it didn't
- happen above (due to save/load to cache for instance, or
- maybe the reader didn't support conversion).
- If so we convert here. */
-
- wanted_format = canvas_get_target_format(canvas,
- surface_format == PIXMAN_a8r8g8b8);
-
- if (surface_format != wanted_format) {
- converted = surface_create(
-#ifdef WIN32
- canvas->dc,
-#endif
- wanted_format,
- pixman_image_get_width(surface),
- pixman_image_get_height(surface),
- TRUE);
- pixman_image_composite32 (PIXMAN_OP_SRC,
- surface, NULL, converted,
- 0, 0,
- 0, 0,
- 0, 0,
- pixman_image_get_width(surface),
- pixman_image_get_height(surface));
- pixman_image_unref (surface);
- surface = converted;
- }
- }
-
- return surface;
-}
-
-#else
-
-static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image,
- int want_original, int real_get)
-{
- SpiceImageDescriptor *descriptor = &image->descriptor;
- pixman_format_code_t format;
-
- /* When touching, never load image. */
- if (!real_get) {
- return NULL;
- }
-
- switch (descriptor->type) {
- case SPICE_IMAGE_TYPE_QUIC: {
- return canvas_get_quic(canvas, image, 0);
- }
- case SPICE_IMAGE_TYPE_BITMAP: {
- return canvas_get_bits(canvas, &image->u.bitmap, want_original, &format);
- }
- default:
- spice_warn_if_reached();
- return NULL;
- }
-
- return NULL;
-}
-
-#endif
-
-static SpiceCanvas *canvas_get_surface_mask(CanvasBase *canvas, SpiceImage *image)
-{
- return canvas_get_surface_mask_internal(canvas, image);
-}
-
-static SpiceCanvas *canvas_get_surface(CanvasBase *canvas, SpiceImage *image)
-{
- return canvas_get_surface_internal(canvas, image);
-}
-
-static pixman_image_t *canvas_get_image(CanvasBase *canvas, SpiceImage *image,
- int want_original)
-{
- return canvas_get_image_internal(canvas, image, want_original, TRUE);
-}
-
-static void canvas_touch_image(CanvasBase *canvas, SpiceImage *image)
-{
- canvas_get_image_internal(canvas, image, TRUE, FALSE);
-}
-
-static pixman_image_t* canvas_get_image_from_self(SpiceCanvas *canvas,
- int x, int y,
- int32_t width, int32_t height)
-{
- CanvasBase *canvas_base = (CanvasBase *)canvas;
- pixman_image_t *surface;
- uint8_t *dest;
- int dest_stride;
- SpiceRect area;
-
- surface = pixman_image_create_bits(spice_surface_format_to_pixman (canvas_base->format),
- width, height, NULL, 0);
- spice_return_val_if_fail(surface != NULL, NULL);
-
- dest = (uint8_t *)pixman_image_get_data(surface);
- dest_stride = pixman_image_get_stride(surface);
-
- area.left = x;
- area.top = y;
- area.right = x + width;
- area.bottom = y + height;
-
- canvas->ops->read_bits(canvas, dest, dest_stride, &area);
-
- return surface;
-}
-
-static inline uint8_t revers_bits(uint8_t byte)
-{
- uint8_t ret = 0;
- int i;
-
- for (i = 0; i < 4; i++) {
- int shift = 7 - i * 2;
- ret |= (byte & (1 << i)) << shift;
- ret |= (byte & (0x80 >> i)) >> shift;
- }
- return ret;
-}
-
-static pixman_image_t *canvas_get_bitmap_mask(CanvasBase *canvas, SpiceBitmap* bitmap, int invers)
-{
- pixman_image_t *surface;
- uint8_t *src_line;
- uint8_t *end_line;
- uint8_t *dest_line;
- int src_stride;
- int line_size;
- int dest_stride;
-
- surface = surface_create(
-#ifdef WIN32
- canvas->dc,
-#endif
- PIXMAN_a1, bitmap->x, bitmap->y, TRUE);
- spice_return_val_if_fail(surface != NULL, NULL);
-
- spice_chunks_linearize(bitmap->data);
- src_line = bitmap->data->chunk[0].data;
- src_stride = bitmap->stride;
- end_line = src_line + (bitmap->y * src_stride);
- line_size = SPICE_ALIGN(bitmap->x, 8) >> 3;
-
- dest_stride = pixman_image_get_stride(surface);
- dest_line = (uint8_t *)pixman_image_get_data(surface);
-#if defined(GL_CANVAS)
- if ((bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
-#else
- if (!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
-#endif
- spice_return_val_if_fail(bitmap->y > 0, NULL);
- dest_line += dest_stride * ((int)bitmap->y - 1);
- dest_stride = -dest_stride;
- }
-
- if (invers) {
- switch (bitmap->format) {
-#if defined(GL_CANVAS) || defined(GDI_CANVAS)
- case SPICE_BITMAP_FMT_1BIT_BE:
-#else
- case SPICE_BITMAP_FMT_1BIT_LE:
-#endif
- for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) {
- uint8_t *dest = dest_line;
- uint8_t *now = src_line;
- uint8_t *end = now + line_size;
- while (now < end) {
- *(dest++) = ~*(now++);
- }
- }
- break;
-#if defined(GL_CANVAS) || defined(GDI_CANVAS)
- case SPICE_BITMAP_FMT_1BIT_LE:
-#else
- case SPICE_BITMAP_FMT_1BIT_BE:
-#endif
- for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) {
- uint8_t *dest = dest_line;
- uint8_t *now = src_line;
- uint8_t *end = now + line_size;
-
- while (now < end) {
- *(dest++) = ~revers_bits(*(now++));
- }
- }
- break;
- default:
- pixman_image_unref(surface);
- surface = NULL;
- spice_warn_if_reached();
- return NULL;
- }
- } else {
- switch (bitmap->format) {
-#if defined(GL_CANVAS) || defined(GDI_CANVAS)
- case SPICE_BITMAP_FMT_1BIT_BE:
-#else
- case SPICE_BITMAP_FMT_1BIT_LE:
-#endif
- for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) {
- memcpy(dest_line, src_line, line_size);
- }
- break;
-#if defined(GL_CANVAS) || defined(GDI_CANVAS)
- case SPICE_BITMAP_FMT_1BIT_LE:
-#else
- case SPICE_BITMAP_FMT_1BIT_BE:
-#endif
- for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) {
- uint8_t *dest = dest_line;
- uint8_t *now = src_line;
- uint8_t *end = now + line_size;
-
- while (now < end) {
- *(dest++) = revers_bits(*(now++));
- }
- }
- break;
- default:
- pixman_image_unref(surface);
- surface = NULL;
- spice_warn_if_reached();
- return NULL;
- }
- }
- return surface;
-}
-
-static inline pixman_image_t *canvas_A1_invers(pixman_image_t *src_surf)
-{
- int width = pixman_image_get_width(src_surf);
- int height = pixman_image_get_height(src_surf);
- pixman_image_t * invers;
- uint8_t *src_line, *end_line, *dest_line;
- int src_stride, line_size, dest_stride;
-
- spice_return_val_if_fail(pixman_image_get_depth(src_surf) == 1, NULL);
-
- invers = pixman_image_create_bits(PIXMAN_a1, width, height, NULL, 0);
- spice_return_val_if_fail(invers != NULL, NULL);
-
- src_line = (uint8_t *)pixman_image_get_data(src_surf);
- src_stride = pixman_image_get_stride(src_surf);
- end_line = src_line + (height * src_stride);
- line_size = SPICE_ALIGN(width, 8) >> 3;
- dest_line = (uint8_t *)pixman_image_get_data(invers);
- dest_stride = pixman_image_get_stride(invers);
-
- for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) {
- uint8_t *dest = dest_line;
- uint8_t *now = src_line;
- uint8_t *end = now + line_size;
- while (now < end) {
- *(dest++) = ~*(now++);
- }
- }
- return invers;
-}
-
-static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int *needs_invert_out)
-{
- SpiceImage *image;
- pixman_image_t *surface;
- int need_invers;
- int is_invers;
- int cache_me;
-
- if (needs_invert_out) {
- *needs_invert_out = 0;
- }
-
- image = mask->bitmap;
- need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS;
-
-#ifdef SW_CANVAS_CACHE
- cache_me = image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME;
-#else
- cache_me = 0;
-#endif
-
- switch (image->descriptor.type) {
- case SPICE_IMAGE_TYPE_BITMAP: {
- is_invers = need_invers && !cache_me;
- surface = canvas_get_bitmap_mask(canvas, &image->u.bitmap, is_invers);
- break;
- }
-#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
- case SPICE_IMAGE_TYPE_FROM_CACHE:
- surface = canvas->bits_cache->ops->get(canvas->bits_cache, image->descriptor.id);
- is_invers = 0;
- break;
-#endif
-#ifdef SW_CANVAS_CACHE
- case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS:
- surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, image->descriptor.id);
- is_invers = 0;
- break;
-#endif
- default:
- spice_warn_if_reached();
- return NULL;
- }
-
-#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
- if (cache_me) {
- canvas->bits_cache->ops->put(canvas->bits_cache, image->descriptor.id, surface);
- }
-
- if (need_invers && !is_invers) { // surface is in cache
- if (needs_invert_out != NULL) {
- *needs_invert_out = TRUE;
- } else {
- pixman_image_t *inv_surf;
- inv_surf = canvas_A1_invers(surface);
- pixman_image_unref(surface);
- surface = inv_surf;
- }
- }
-#endif
- return surface;
-}
-
-static inline void canvas_raster_glyph_box(const SpiceRasterGlyph *glyph, SpiceRect *r)
-{
- spice_return_if_fail(r != NULL);
-
- r->top = glyph->render_pos.y + glyph->glyph_origin.y;
- r->bottom = r->top + glyph->height;
- r->left = glyph->render_pos.x + glyph->glyph_origin.x;
- r->right = r->left + glyph->width;
-}
-
-#ifdef GL_CANVAS
-static inline void __canvas_put_bits(uint8_t *dest, int offset, uint8_t val, int n)
-{
- uint8_t mask;
- int now;
-
- dest = dest + (offset >> 3);
- offset &= 0x07;
- now = MIN(8 - offset, n);
-
- mask = ~((1 << (8 - now)) - 1);
- mask >>= offset;
- *dest = ((val >> offset) & mask) | *dest;
-
- if ((n = n - now)) {
- mask = ~((1 << (8 - n)) - 1);
- dest++;
- *dest = ((val << now) & mask) | *dest;
- }
-}
-
-#else
-static inline void __canvas_put_bits(uint8_t *dest, int offset, uint8_t val, int n)
-{
- uint8_t mask;
- int now;
-
- dest = dest + (offset >> 3);
- offset &= 0x07;
-
- now = MIN(8 - offset, n);
-
- mask = (1 << now) - 1;
- mask <<= offset;
- val = revers_bits(val);
- *dest = ((val << offset) & mask) | *dest;
-
- if ((n = n - now)) {
- mask = (1 << n) - 1;
- dest++;
- *dest = ((val >> now) & mask) | *dest;
- }
-}
-
-#endif
-
-static inline void canvas_put_bits(uint8_t *dest, int dest_offset, uint8_t *src, int n)
-{
- while (n) {
- int now = MIN(n, 8);
-
- n -= now;
- __canvas_put_bits(dest, dest_offset, *src, now);
- dest_offset += now;
- src++;
- }
-}
-
-static void canvas_put_glyph_bits(SpiceRasterGlyph *glyph, int bpp, uint8_t *dest, int dest_stride,
- SpiceRect *bounds)
-{
- SpiceRect glyph_box;
- uint8_t *src;
- int lines;
- int width;
-
- //todo: support SPICE_STRING_FLAGS_RASTER_TOP_DOWN
- canvas_raster_glyph_box(glyph, &glyph_box);
- spice_return_if_fail(glyph_box.top >= bounds->top && glyph_box.bottom <= bounds->bottom);
- spice_return_if_fail(glyph_box.left >= bounds->left && glyph_box.right <= bounds->right);
- rect_offset(&glyph_box, -bounds->left, -bounds->top);
-
- dest += glyph_box.top * dest_stride;
- src = glyph->data;
- lines = glyph_box.bottom - glyph_box.top;
- width = glyph_box.right - glyph_box.left;
- switch (bpp) {
- case 1: {
- int src_stride = SPICE_ALIGN(width, 8) >> 3;
- int i;
-
- src += src_stride * (lines);
- for (i = 0; i < lines; i++) {
- src -= src_stride;
- canvas_put_bits(dest, glyph_box.left, src, width);
- dest += dest_stride;
- }
- break;
- }
- case 4: {
- uint8_t *end;
- int src_stride = SPICE_ALIGN(width * 4, 8) >> 3;
-
- src += src_stride * lines;
- dest += glyph_box.left;
- end = dest + dest_stride * lines;
- for (; dest != end; dest += dest_stride) {
- int i = 0;
- uint8_t *now;
-
- src -= src_stride;
- now = src;
- while (i < (width & ~1)) {
- dest[i] = MAX(dest[i], *now & 0xf0);
- dest[i + 1] = MAX(dest[i + 1], *now << 4);
- i += 2;
- now++;
- }
- if (i < width) {
- dest[i] = MAX(dest[i], *now & 0xf0);
- now++;
- }
- }
- break;
- }
- case 8: {
- uint8_t *end;
- src += width * lines;
- dest += glyph_box.left;
- end = dest + dest_stride * lines;
- for (; dest != end; dest += dest_stride, src -= width) {
- int i;
-
- for (i = 0; i < width; i++) {
- dest[i] = MAX(dest[i], src[i]);
- }
- }
- break;
- }
- default:
- spice_warn_if_reached();
- return;
- }
-}
-
-static pixman_image_t *canvas_get_str_mask(CanvasBase *canvas, SpiceString *str, int bpp, SpicePoint *pos)
-{
- SpiceRasterGlyph *glyph;
- SpiceRect bounds;
- pixman_image_t *str_mask;
- uint8_t *dest;
- int dest_stride;
- int i;
-
- spice_return_val_if_fail(str->length > 0, NULL);
-
- glyph = str->glyphs[0];
- canvas_raster_glyph_box(glyph, &bounds);
-
- for (i = 1; i < str->length; i++) {
- SpiceRect glyph_box;
-
- canvas_raster_glyph_box(str->glyphs[i], &glyph_box);
- rect_union(&bounds, &glyph_box);
- }
-
- str_mask = pixman_image_create_bits((bpp == 1) ? PIXMAN_a1 : PIXMAN_a8,
- bounds.right - bounds.left,
- bounds.bottom - bounds.top, NULL, 0);
- spice_return_val_if_fail(str_mask != NULL, NULL);
-
- dest = (uint8_t *)pixman_image_get_data(str_mask);
- dest_stride = pixman_image_get_stride(str_mask);
- for (i = 0; i < str->length; i++) {
- glyph = str->glyphs[i];
-#if defined(GL_CANVAS)
- canvas_put_glyph_bits(glyph, bpp, dest + (bounds.bottom - bounds.top - 1) * dest_stride,
- -dest_stride, &bounds);
-#else
- canvas_put_glyph_bits(glyph, bpp, dest, dest_stride, &bounds);
-#endif
- }
-
- pos->x = bounds.left;
- pos->y = bounds.top;
- return str_mask;
-}
-
-static pixman_image_t *canvas_scale_surface(pixman_image_t *src, const SpiceRect *src_area, int width,
- int height, int scale_mode)
-{
- pixman_image_t *surface;
- pixman_transform_t transform;
- double sx, sy;
-
- surface = pixman_image_create_bits(spice_pixman_image_get_format (src),
- width, height, NULL, 0);
- spice_return_val_if_fail(surface != NULL, NULL);
-
- sx = (double)(src_area->right - src_area->left) / width;
- sy = (double)(src_area->bottom - src_area->top) / height;
-
- pixman_transform_init_scale(&transform, pixman_double_to_fixed(sx), pixman_double_to_fixed(sy));
-
- pixman_image_set_transform (src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- spice_return_val_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST, NULL);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, surface,
- ROUND(src_area->left / sx), ROUND (src_area->top / sy),
- 0, 0, /* mask */
- 0, 0, /* dst */
- width, height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- return surface;
-}
-
-ATTR_PRINTF(2, 3) static void quic_usr_error(QuicUsrContext *usr, const char *fmt, ...)
-{
- QuicData *usr_data = (QuicData *)usr;
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
- va_end(ap);
-
- longjmp(usr_data->jmp_env, 1);
-}
-
-ATTR_PRINTF(2, 3) static void quic_usr_warn(QuicUsrContext *usr, const char *fmt, ...)
-{
- QuicData *usr_data = (QuicData *)usr;
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
- va_end(ap);
-}
-
-static void *quic_usr_malloc(QuicUsrContext *usr, int size)
-{
- return spice_malloc(size);
-}
-
-static void quic_usr_free(QuicUsrContext *usr, void *ptr)
-{
- free(ptr);
-}
-
-ATTR_PRINTF(2, 3) static void lz_usr_warn(LzUsrContext *usr, const char *fmt, ...)
-{
- LzData *usr_data = (LzData *)usr;
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
- va_end(ap);
-}
-
-ATTR_PRINTF(2, 3) static void lz_usr_error(LzUsrContext *usr, const char *fmt, ...)
-{
- LzData *usr_data = (LzData *)usr;
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
- va_end(ap);
-
- longjmp(usr_data->jmp_env, 1);
-}
-
-static void *lz_usr_malloc(LzUsrContext *usr, int size)
-{
- return spice_malloc(size);
-}
-
-static void lz_usr_free(LzUsrContext *usr, void *ptr)
-{
- free(ptr);
-}
-
-static int lz_usr_more_space(LzUsrContext *usr, uint8_t **io_ptr)
-{
- return 0;
-}
-
-static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines)
-{
- return 0;
-}
-
-static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed)
-{
- QuicData *quic_data = (QuicData *)usr;
-
- if (quic_data->current_chunk == quic_data->chunks->num_chunks -1) {
- return 0;
- }
- quic_data->current_chunk++;
-
- *io_ptr = (uint32_t *)quic_data->chunks->chunk[quic_data->current_chunk].data;
- return quic_data->chunks->chunk[quic_data->current_chunk].len >> 2;
-}
-
-
-static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines)
-{
- return 0;
-}
-
-static void canvas_base_destroy(CanvasBase *canvas)
-{
- quic_destroy(canvas->quic_data.quic);
- lz_destroy(canvas->lz_data.lz);
-#ifdef GDI_CANVAS
- DeleteDC(canvas->dc);
-#endif
-
- if (canvas->usr_data && canvas->usr_data_destroy) {
- canvas->usr_data_destroy (canvas->usr_data);
- canvas->usr_data = NULL;
- }
-}
-
-/* This is kind of lame, but it protects against multiple
- instances of these functions. We really should stop including
- canvas_base.c and build it separately instead */
-#ifdef CANVAS_SINGLE_INSTANCE
-
-void spice_canvas_set_usr_data(SpiceCanvas *spice_canvas,
- void *data,
- spice_destroy_fn_t destroy_fn)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- if (canvas->usr_data && canvas->usr_data_destroy) {
- canvas->usr_data_destroy (canvas->usr_data);
- }
- canvas->usr_data = data;
- canvas->usr_data_destroy = destroy_fn;
-}
-
-void *spice_canvas_get_usr_data(SpiceCanvas *spice_canvas)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- return canvas->usr_data;
-}
-#endif
-
-
-static void canvas_clip_pixman(CanvasBase *canvas,
- pixman_region32_t *dest_region,
- SpiceClip *clip)
-{
- pixman_region32_intersect(dest_region, dest_region, &canvas->canvas_region);
-
- switch (clip->type) {
- case SPICE_CLIP_TYPE_NONE:
- break;
- case SPICE_CLIP_TYPE_RECTS: {
- uint32_t n = clip->rects->num_rects;
- SpiceRect *now = clip->rects->rects;
-
- pixman_region32_t clip;
-
- if (spice_pixman_region32_init_rects(&clip, now, n)) {
- pixman_region32_intersect(dest_region, dest_region, &clip);
- pixman_region32_fini(&clip);
- }
-
- break;
- }
- default:
- spice_warn_if_reached();
- return;
- }
-}
-
-static void canvas_mask_pixman(CanvasBase *canvas,
- pixman_region32_t *dest_region,
- SpiceQMask *mask, int x, int y)
-{
- SpiceCanvas *surface_canvas;
- pixman_image_t *image, *subimage;
- int needs_invert;
- pixman_region32_t mask_region;
- uint32_t *mask_data;
- int mask_x, mask_y;
- int mask_width, mask_height, mask_stride;
- pixman_box32_t extents;
-
- if (!mask->bitmap) {
- return;
- }
-
- surface_canvas = canvas_get_surface_mask(canvas, mask->bitmap);
- if (surface_canvas) {
- needs_invert = mask->flags & SPICE_MASK_FLAGS_INVERS;
- image = surface_canvas->ops->get_image(surface_canvas);
- } else {
- needs_invert = FALSE;
- image = canvas_get_mask(canvas,
- mask,
- &needs_invert);
- }
-
- mask_data = pixman_image_get_data(image);
- mask_width = pixman_image_get_width(image);
- mask_height = pixman_image_get_height(image);
- mask_stride = pixman_image_get_stride(image);
-
- mask_x = mask->pos.x;
- mask_y = mask->pos.y;
-
- /* We need to subset the area of the mask that we turn into a region,
- because a cached mask may be much larger than what is used for
- the clip operation. */
- extents = *pixman_region32_extents(dest_region);
-
- /* convert from destination pixels to mask pixels */
- extents.x1 -= x - mask_x;
- extents.y1 -= y - mask_y;
- extents.x2 -= x - mask_x;
- extents.y2 -= y - mask_y;
-
- /* clip to mask size */
- if (extents.x1 < 0) {
- extents.x1 = 0;
- }
- if (extents.x2 >= mask_width) {
- extents.x2 = mask_width;
- }
- if (extents.x2 < extents.x1) {
- extents.x2 = extents.x1;
- }
- if (extents.y1 < 0) {
- extents.y1 = 0;
- }
- if (extents.y2 >= mask_height) {
- extents.y2 = mask_height;
- }
- if (extents.y2 < extents.y1) {
- extents.y2 = extents.y1;
- }
-
- /* round down X to even 32 pixels (i.e. uint32_t) */
- extents.x1 = extents.x1 & ~(0x1f);
-
- mask_data = (uint32_t *)((uint8_t *)mask_data + mask_stride * extents.y1 + extents.x1 / 32);
- mask_x -= extents.x1;
- mask_y -= extents.y1;
- mask_width = extents.x2 - extents.x1;
- mask_height = extents.y2 - extents.y1;
-
- subimage = pixman_image_create_bits(PIXMAN_a1, mask_width, mask_height,
- mask_data, mask_stride);
- pixman_region32_init_from_image(&mask_region,
- subimage);
- pixman_image_unref(subimage);
-
- if (needs_invert) {
- pixman_box32_t rect;
-
- rect.x1 = rect.y1 = 0;
- rect.x2 = mask_width;
- rect.y2 = mask_height;
-
- pixman_region32_inverse(&mask_region, &mask_region, &rect);
- }
-
- pixman_region32_translate(&mask_region,
- -mask_x + x, -mask_y + y);
-
- pixman_region32_intersect(dest_region, dest_region, &mask_region);
- pixman_region32_fini(&mask_region);
-
- pixman_image_unref(image);
-}
-
-static void draw_brush(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceBrush *brush,
- SpiceROP rop)
-{
- CanvasBase *canvas_base = (CanvasBase *)canvas;
- uint32_t color;
- SpicePattern *pattern;
- pixman_image_t *tile;
- int offset_x, offset_y;
- pixman_box32_t *rects;
- int n_rects;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- switch (brush->type) {
- case SPICE_BRUSH_TYPE_SOLID:
- color = brush->u.color;
- if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_solid_rects(canvas, rects, n_rects, color);
- } else {
- canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, color, rop);
- }
- break;
- case SPICE_BRUSH_TYPE_PATTERN: {
- SpiceCanvas *surface_canvas;
-
- pattern = &brush->u.pattern;
- offset_x = pattern->pos.x;
- offset_y = pattern->pos.y;
-
- surface_canvas = canvas_get_surface(canvas_base, pattern->pat);
- if (surface_canvas) {
- if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_tiled_rects_from_surface(canvas, rects, n_rects, surface_canvas,
- offset_x, offset_y);
- } else {
- canvas->ops->fill_tiled_rects_rop_from_surface(canvas, rects, n_rects,
- surface_canvas, offset_x, offset_y,
- rop);
- }
- } else {
- tile = canvas_get_image(canvas_base, pattern->pat, FALSE);
- spice_return_if_fail(tile != NULL);
-
- if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_tiled_rects(canvas, rects, n_rects, tile, offset_x, offset_y);
- } else {
- canvas->ops->fill_tiled_rects_rop(canvas, rects, n_rects,
- tile, offset_x, offset_y, rop);
- }
- pixman_image_unref(tile);
- }
- break;
- }
- case SPICE_BRUSH_TYPE_NONE:
- /* Still need to do *something* here, because rop could be e.g invert dest */
- canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, 0, rop);
- break;
- default:
- spice_warn_if_reached();
- return;
- }
-}
-
-/* If we're exiting early we may still have to load an image in case
- it has to be cached or something */
-static void touch_brush(CanvasBase *canvas, SpiceBrush *brush)
-{
- SpicePattern *pattern;
-
- if (brush->type == SPICE_BRUSH_TYPE_PATTERN) {
- pattern = &brush->u.pattern;
- canvas_touch_image(canvas, pattern->pat);
- }
-}
-
-static void canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- SpiceROP rop;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &fill->mask,
- bbox->left, bbox->top);
-
- rop = ropd_descriptor_to_rop(fill->rop_descriptor,
- ROP_INPUT_BRUSH,
- ROP_INPUT_DEST);
-
- if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) {
- touch_brush(canvas, &fill->brush);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- draw_brush(spice_canvas, &dest_region, &fill->brush, rop);
-
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- SpiceCanvas *surface_canvas;
- pixman_image_t *src_image;
- SpiceROP rop;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, ©->mask,
- bbox->left, bbox->top);
-
- rop = ropd_descriptor_to_rop(copy->rop_descriptor,
- ROP_INPUT_SRC,
- ROP_INPUT_DEST);
-
- if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) {
- canvas_touch_image(canvas, copy->src_bitmap);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- surface_canvas = canvas_get_surface(canvas, copy->src_bitmap);
- if (surface_canvas) {
- if (rect_is_same_size(bbox, ©->src_area)) {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- bbox->left - copy->src_area.left,
- bbox->top - copy->src_area.top);
- } else {
- spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- bbox->left - copy->src_area.left,
- bbox->top - copy->src_area.top,
- rop);
- }
- } else {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- copy->src_area.left,
- copy->src_area.top,
- copy->src_area.right - copy->src_area.left,
- copy->src_area.bottom - copy->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- copy->scale_mode);
- } else {
- spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- copy->src_area.left,
- copy->src_area.top,
- copy->src_area.right - copy->src_area.left,
- copy->src_area.bottom - copy->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- copy->scale_mode,
- rop);
- }
- }
- } else {
- src_image = canvas_get_image(canvas, copy->src_bitmap, FALSE);
- spice_return_if_fail(src_image != NULL);
-
- if (rect_is_same_size(bbox, ©->src_area)) {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->blit_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - copy->src_area.left,
- bbox->top - copy->src_area.top);
- } else {
- spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region,
- src_image,
- bbox->left - copy->src_area.left,
- bbox->top - copy->src_area.top,
- rop);
- }
- } else {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->scale_image(spice_canvas, &dest_region,
- src_image,
- copy->src_area.left,
- copy->src_area.top,
- copy->src_area.right - copy->src_area.left,
- copy->src_area.bottom - copy->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- copy->scale_mode);
- } else {
- spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region,
- src_image,
- copy->src_area.left,
- copy->src_area.top,
- copy->src_area.right - copy->src_area.left,
- copy->src_area.bottom - copy->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- copy->scale_mode,
- rop);
- }
- }
- pixman_image_unref(src_image);
- }
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- SpiceCanvas *surface_canvas;
- pixman_image_t *src_image;
- pixman_region32_t dest_region;
- uint32_t transparent_color;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
-
- if (pixman_region32_n_rects (&dest_region) == 0) {
- canvas_touch_image(canvas, transparent->src_bitmap);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- switch (canvas->format) {
- case SPICE_SURFACE_FMT_32_xRGB:
- case SPICE_SURFACE_FMT_32_ARGB:
- transparent_color = transparent->true_color;
- break;
- case SPICE_SURFACE_FMT_16_555:
- transparent_color = rgb_32_to_16_555(transparent->true_color);
- break;
- case SPICE_SURFACE_FMT_16_565:
- transparent_color = rgb_32_to_16_565(transparent->true_color);
- break;
- default:
- transparent_color = 0;
- }
-
- surface_canvas = canvas_get_surface(canvas, transparent->src_bitmap);
- if (surface_canvas) {
- if (rect_is_same_size(bbox, &transparent->src_area)) {
- spice_canvas->ops->colorkey_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- bbox->left - transparent->src_area.left,
- bbox->top - transparent->src_area.top,
- transparent_color);
- } else {
- spice_canvas->ops->colorkey_scale_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- transparent->src_area.left,
- transparent->src_area.top,
- transparent->src_area.right - transparent->src_area.left,
- transparent->src_area.bottom - transparent->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- transparent_color);
- }
- } else {
- src_image = canvas_get_image(canvas, transparent->src_bitmap, FALSE);
- spice_return_if_fail(src_image != NULL);
-
- if (rect_is_same_size(bbox, &transparent->src_area)) {
- spice_canvas->ops->colorkey_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - transparent->src_area.left,
- bbox->top - transparent->src_area.top,
- transparent_color);
- } else {
- spice_canvas->ops->colorkey_scale_image(spice_canvas, &dest_region,
- src_image,
- transparent->src_area.left,
- transparent->src_area.top,
- transparent->src_area.right - transparent->src_area.left,
- transparent->src_area.bottom - transparent->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- transparent_color);
- }
- pixman_image_unref(src_image);
- }
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- SpiceCanvas *surface_canvas;
- pixman_image_t *src_image;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
-
- if (alpha_blend->alpha == 0 ||
- !pixman_region32_not_empty(&dest_region)) {
- canvas_touch_image(canvas, alpha_blend->src_bitmap);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- surface_canvas = canvas_get_surface(canvas, alpha_blend->src_bitmap);
- if (surface_canvas) {
- if (rect_is_same_size(bbox, &alpha_blend->src_area)) {
- spice_canvas->ops->blend_image_from_surface(spice_canvas, &dest_region,
- alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA,
- surface_canvas,
- alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA,
- alpha_blend->src_area.left,
- alpha_blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- alpha_blend->alpha);
- } else {
- spice_canvas->ops->blend_scale_image_from_surface(spice_canvas, &dest_region,
- alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA,
- surface_canvas,
- alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA,
- alpha_blend->src_area.left,
- alpha_blend->src_area.top,
- alpha_blend->src_area.right - alpha_blend->src_area.left,
- alpha_blend->src_area.bottom - alpha_blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- SPICE_IMAGE_SCALE_MODE_NEAREST,
- alpha_blend->alpha);
- }
- } else {
- src_image = canvas_get_image(canvas, alpha_blend->src_bitmap, TRUE);
- spice_return_if_fail(src_image != NULL);
-
- if (rect_is_same_size(bbox, &alpha_blend->src_area)) {
- spice_canvas->ops->blend_image(spice_canvas, &dest_region,
- alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA,
- src_image,
- alpha_blend->src_area.left,
- alpha_blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- alpha_blend->alpha);
- } else {
- spice_canvas->ops->blend_scale_image(spice_canvas, &dest_region,
- alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA,
- src_image,
- alpha_blend->src_area.left,
- alpha_blend->src_area.top,
- alpha_blend->src_area.right - alpha_blend->src_area.left,
- alpha_blend->src_area.bottom - alpha_blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- SPICE_IMAGE_SCALE_MODE_NEAREST,
- alpha_blend->alpha);
- }
-
- pixman_image_unref(src_image);
- }
-
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_image_t *src_image;
- pixman_region32_t dest_region;
- SpiceCanvas *surface_canvas;
- SpiceROP rop;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &opaque->mask,
- bbox->left, bbox->top);
-
- rop = ropd_descriptor_to_rop(opaque->rop_descriptor,
- ROP_INPUT_BRUSH,
- ROP_INPUT_SRC);
-
- if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) {
- canvas_touch_image(canvas, opaque->src_bitmap);
- touch_brush(canvas, &opaque->brush);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- surface_canvas = canvas_get_surface(canvas, opaque->src_bitmap);
- if (surface_canvas) {
- if (rect_is_same_size(bbox, &opaque->src_area)) {
- spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- bbox->left - opaque->src_area.left,
- bbox->top - opaque->src_area.top);
- } else {
- spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- opaque->src_area.left,
- opaque->src_area.top,
- opaque->src_area.right - opaque->src_area.left,
- opaque->src_area.bottom - opaque->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- opaque->scale_mode);
- }
- } else {
- src_image = canvas_get_image(canvas, opaque->src_bitmap, FALSE);
- spice_return_if_fail(src_image != NULL);
-
- if (rect_is_same_size(bbox, &opaque->src_area)) {
- spice_canvas->ops->blit_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - opaque->src_area.left,
- bbox->top - opaque->src_area.top);
- } else {
- spice_canvas->ops->scale_image(spice_canvas, &dest_region,
- src_image,
- opaque->src_area.left,
- opaque->src_area.top,
- opaque->src_area.right - opaque->src_area.left,
- opaque->src_area.bottom - opaque->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- opaque->scale_mode);
- }
- pixman_image_unref(src_image);
- }
-
- draw_brush(spice_canvas, &dest_region, &opaque->brush, rop);
-
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- SpiceCanvas *surface_canvas;
- pixman_image_t *src_image;
- pixman_region32_t dest_region;
- SpiceROP rop;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &blend->mask,
- bbox->left, bbox->top);
-
- rop = ropd_descriptor_to_rop(blend->rop_descriptor,
- ROP_INPUT_SRC,
- ROP_INPUT_DEST);
-
- if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) {
- canvas_touch_image(canvas, blend->src_bitmap);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- surface_canvas = canvas_get_surface(canvas, blend->src_bitmap);
- if (surface_canvas) {
- if (rect_is_same_size(bbox, &blend->src_area)) {
- if (rop == SPICE_ROP_COPY)
- spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- bbox->left - blend->src_area.left,
- bbox->top - blend->src_area.top);
- else
- spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- bbox->left - blend->src_area.left,
- bbox->top - blend->src_area.top,
- rop);
- } else {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- blend->src_area.left,
- blend->src_area.top,
- blend->src_area.right - blend->src_area.left,
- blend->src_area.bottom - blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- blend->scale_mode);
- } else {
- spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region,
- surface_canvas,
- blend->src_area.left,
- blend->src_area.top,
- blend->src_area.right - blend->src_area.left,
- blend->src_area.bottom - blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- blend->scale_mode, rop);
- }
- }
- } else {
- src_image = canvas_get_image(canvas, blend->src_bitmap, FALSE);
- spice_return_if_fail(src_image != NULL);
-
- if (rect_is_same_size(bbox, &blend->src_area)) {
- if (rop == SPICE_ROP_COPY)
- spice_canvas->ops->blit_image(spice_canvas, &dest_region,
- src_image,
- bbox->left - blend->src_area.left,
- bbox->top - blend->src_area.top);
- else
- spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region,
- src_image,
- bbox->left - blend->src_area.left,
- bbox->top - blend->src_area.top,
- rop);
- } else {
- if (rop == SPICE_ROP_COPY) {
- spice_canvas->ops->scale_image(spice_canvas, &dest_region,
- src_image,
- blend->src_area.left,
- blend->src_area.top,
- blend->src_area.right - blend->src_area.left,
- blend->src_area.bottom - blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- blend->scale_mode);
- } else {
- spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region,
- src_image,
- blend->src_area.left,
- blend->src_area.top,
- blend->src_area.right - blend->src_area.left,
- blend->src_area.bottom - blend->src_area.top,
- bbox->left,
- bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top,
- blend->scale_mode, rop);
- }
- }
- pixman_image_unref(src_image);
- }
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- pixman_box32_t *rects;
- int n_rects;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &blackness->mask,
- bbox->left, bbox->top);
-
- if (!pixman_region32_not_empty(&dest_region)) {
- pixman_region32_fini (&dest_region);
- return;
- }
-
- rects = pixman_region32_rectangles(&dest_region, &n_rects);
-
- spice_canvas->ops->fill_solid_rects(spice_canvas, rects, n_rects, 0x000000);
-
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- pixman_box32_t *rects;
- int n_rects;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &whiteness->mask,
- bbox->left, bbox->top);
-
- if (!pixman_region32_not_empty(&dest_region)) {
- pixman_region32_fini(&dest_region);
- return;
- }
-
- rects = pixman_region32_rectangles(&dest_region, &n_rects);
- spice_canvas->ops->fill_solid_rects(spice_canvas, rects, n_rects, 0xffffffff);
-
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- pixman_box32_t *rects;
- int n_rects;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &invers->mask,
- bbox->left, bbox->top);
-
- if (!pixman_region32_not_empty(&dest_region)) {
- pixman_region32_fini(&dest_region);
- return;
- }
-
- rects = pixman_region32_rectangles(&dest_region, &n_rects);
- spice_canvas->ops->fill_solid_rects_rop(spice_canvas, rects, n_rects, 0x00000000,
- SPICE_ROP_INVERT);
-
- pixman_region32_fini(&dest_region);
-}
-
-typedef struct {
- lineGC base;
- SpiceCanvas *canvas;
- pixman_region32_t dest_region;
- SpiceROP fore_rop;
- SpiceROP back_rop;
- int solid;
- uint32_t color;
- int use_surface_canvas;
- union {
- SpiceCanvas *surface_canvas;
- pixman_image_t *tile;
- };
- int tile_offset_x;
- int tile_offset_y;
-} StrokeGC;
-
-static void stroke_fill_spans(lineGC * pGC,
- int num_spans,
- SpicePoint *points,
- int *widths,
- int sorted,
- int foreground)
-{
- SpiceCanvas *canvas;
- StrokeGC *strokeGC;
- int i;
- SpiceROP rop;
-
- strokeGC = (StrokeGC *)pGC;
- canvas = strokeGC->canvas;
-
- num_spans = spice_canvas_clip_spans(&strokeGC->dest_region,
- points, widths, num_spans,
- points, widths, sorted);
-
- if (foreground) {
- rop = strokeGC->fore_rop;
- } else {
- rop = strokeGC->back_rop;
- }
-
- if (strokeGC->solid) {
- if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_solid_spans(canvas, points, widths, num_spans,
- strokeGC->color);
- } else {
- for (i = 0; i < num_spans; i++) {
- pixman_box32_t r;
- r.x1 = points[i].x;
- r.y1 = points[i].y;
- r.x2 = points[i].x + widths[i];
- r.y2 = r.y1 + 1;
- canvas->ops->fill_solid_rects_rop(canvas, &r, 1,
- strokeGC->color, rop);
- }
- }
- } else {
- if (rop == SPICE_ROP_COPY) {
- for (i = 0; i < num_spans; i++) {
- pixman_box32_t r;
- r.x1 = points[i].x;
- r.y1 = points[i].y;
- r.x2 = points[i].x + widths[i];
- r.y2 = r.y1 + 1;
- canvas->ops->fill_tiled_rects(canvas, &r, 1,
- strokeGC->tile,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y);
- }
- } else {
- for (i = 0; i < num_spans; i++) {
- pixman_box32_t r;
- r.x1 = points[i].x;
- r.y1 = points[i].y;
- r.x2 = points[i].x + widths[i];
- r.y2 = r.y1 + 1;
- canvas->ops->fill_tiled_rects_rop(canvas, &r, 1,
- strokeGC->tile,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y, rop);
- }
- }
- }
-}
-
-static void stroke_fill_rects(lineGC * pGC,
- int num_rects,
- pixman_rectangle32_t *rects,
- int foreground)
-{
- SpiceCanvas *canvas;
- pixman_region32_t area;
- pixman_box32_t *boxes;
- StrokeGC *strokeGC;
- SpiceROP rop;
- int i;
- pixman_box32_t *area_rects;
- int n_area_rects;
-
- strokeGC = (StrokeGC *)pGC;
- canvas = strokeGC->canvas;
-
- if (foreground) {
- rop = strokeGC->fore_rop;
- } else {
- rop = strokeGC->back_rop;
- }
-
- /* TODO: We can optimize this for more common cases where
- dest is one rect */
-
- boxes = spice_new(pixman_box32_t, num_rects);
- for (i = 0; i < num_rects; i++) {
- boxes[i].x1 = rects[i].x;
- boxes[i].y1 = rects[i].y;
- boxes[i].x2 = rects[i].x + rects[i].width;
- boxes[i].y2 = rects[i].y + rects[i].height;
- }
- pixman_region32_init_rects(&area, boxes, num_rects);
- pixman_region32_intersect(&area, &area, &strokeGC->dest_region);
- free(boxes);
-
- area_rects = pixman_region32_rectangles(&area, &n_area_rects);
-
- if (strokeGC->solid) {
- if (rop == SPICE_ROP_COPY) {
- canvas->ops->fill_solid_rects(canvas, area_rects, n_area_rects,
- strokeGC->color);
- } else {
- canvas->ops->fill_solid_rects_rop(canvas, area_rects, n_area_rects,
- strokeGC->color, rop);
- }
- } else {
- if (rop == SPICE_ROP_COPY) {
- if (strokeGC->use_surface_canvas) {
- canvas->ops->fill_tiled_rects_from_surface(canvas, area_rects, n_area_rects,
- strokeGC->surface_canvas,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y);
- } else {
- canvas->ops->fill_tiled_rects(canvas, area_rects, n_area_rects,
- strokeGC->tile,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y);
- }
- } else {
- if (strokeGC->use_surface_canvas) {
- canvas->ops->fill_tiled_rects_rop_from_surface(canvas, area_rects, n_area_rects,
- strokeGC->surface_canvas,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y,
- rop);
- } else {
- canvas->ops->fill_tiled_rects_rop(canvas, area_rects, n_area_rects,
- strokeGC->tile,
- strokeGC->tile_offset_x,
- strokeGC->tile_offset_y,
- rop);
- }
- }
- }
-
- pixman_region32_fini(&area);
-}
-
-typedef struct {
- SpicePoint *points;
- int num_points;
- int size;
-} StrokeLines;
-
-static void stroke_lines_init(StrokeLines *lines)
-{
- lines->points = spice_new(SpicePoint, 10);
- lines->size = 10;
- lines->num_points = 0;
-}
-
-static void stroke_lines_free(StrokeLines *lines)
-{
- free(lines->points);
-}
-
-static void stroke_lines_append(StrokeLines *lines,
- int x, int y)
-{
- if (lines->num_points == lines->size) {
- lines->size *= 2;
- lines->points = spice_renew(SpicePoint, lines->points, lines->size);
- }
- lines->points[lines->num_points].x = x;
- lines->points[lines->num_points].y = y;
- lines->num_points++;
-}
-
-static void stroke_lines_append_fix(StrokeLines *lines,
- SpicePointFix *point)
-{
- stroke_lines_append(lines,
- fix_to_int(point->x),
- fix_to_int(point->y));
-}
-
-static inline int64_t dot(SPICE_FIXED28_4 x1,
- SPICE_FIXED28_4 y1,
- SPICE_FIXED28_4 x2,
- SPICE_FIXED28_4 y2)
-{
- return (((int64_t)x1) *((int64_t)x2) +
- ((int64_t)y1) *((int64_t)y2)) >> 4;
-}
-
-static inline int64_t dot2(SPICE_FIXED28_4 x,
- SPICE_FIXED28_4 y)
-{
- return (((int64_t)x) *((int64_t)x) +
- ((int64_t)y) *((int64_t)y)) >> 4;
-}
-
-static void subdivide_bezier(StrokeLines *lines,
- SpicePointFix point0,
- SpicePointFix point1,
- SpicePointFix point2,
- SpicePointFix point3)
-{
- int64_t A2, B2, C2, AB, CB, h1, h2;
-
- A2 = dot2(point1.x - point0.x,
- point1.y - point0.y);
- B2 = dot2(point3.x - point0.x,
- point3.y - point0.y);
- C2 = dot2(point2.x - point3.x,
- point2.y - point3.y);
-
- AB = dot(point1.x - point0.x,
- point1.y - point0.y,
- point3.x - point0.x,
- point3.y - point0.y);
-
- CB = dot(point2.x - point3.x,
- point2.y - point3.y,
- point0.x - point3.x,
- point0.y - point3.y);
-
- h1 = (A2*B2 - AB*AB) >> 3;
- h2 = (C2*B2 - CB*CB) >> 3;
-
- if (h1 < B2 && h2 < B2) {
- /* deviation squared less than half a pixel, use straight line */
- stroke_lines_append_fix(lines, &point3);
- } else {
- SpicePointFix point01, point23, point12, point012, point123, point0123;
-
- point01.x = (point0.x + point1.x) / 2;
- point01.y = (point0.y + point1.y) / 2;
- point12.x = (point1.x + point2.x) / 2;
- point12.y = (point1.y + point2.y) / 2;
- point23.x = (point2.x + point3.x) / 2;
- point23.y = (point2.y + point3.y) / 2;
- point012.x = (point01.x + point12.x) / 2;
- point012.y = (point01.y + point12.y) / 2;
- point123.x = (point12.x + point23.x) / 2;
- point123.y = (point12.y + point23.y) / 2;
- point0123.x = (point012.x + point123.x) / 2;
- point0123.y = (point012.y + point123.y) / 2;
-
- subdivide_bezier(lines, point0, point01, point012, point0123);
- subdivide_bezier(lines, point0123, point123, point23, point3);
- }
-}
-
-static void stroke_lines_append_bezier(StrokeLines *lines,
- SpicePointFix *point1,
- SpicePointFix *point2,
- SpicePointFix *point3)
-{
- SpicePointFix point0;
-
- point0.x = int_to_fix(lines->points[lines->num_points-1].x);
- point0.y = int_to_fix(lines->points[lines->num_points-1].y);
-
- subdivide_bezier(lines, point0, *point1, *point2, *point3);
-}
-
-static void stroke_lines_draw(StrokeLines *lines,
- lineGC *gc,
- int dashed)
-{
- if (lines->num_points != 0) {
- if (dashed) {
- spice_canvas_zero_dash_line(gc, CoordModeOrigin,
- lines->num_points, lines->points);
- } else {
- spice_canvas_zero_line(gc, CoordModeOrigin,
- lines->num_points, lines->points);
- }
- lines->num_points = 0;
- }
-}
-
-
-static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
- SpiceClip *clip, SpiceStroke *stroke)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- SpiceCanvas *surface_canvas = NULL;
- StrokeGC gc = { { 0 } };
- lineGCOps ops = {
- stroke_fill_spans,
- stroke_fill_rects
- };
- StrokeLines lines;
- unsigned int i;
- int dashed;
-
- pixman_region32_init_rect(&gc.dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &gc.dest_region, clip);
-
- if (!pixman_region32_not_empty(&gc.dest_region)) {
- touch_brush(canvas, &stroke->brush);
- pixman_region32_fini(&gc.dest_region);
- return;
- }
-
- gc.canvas = spice_canvas;
- gc.fore_rop = ropd_descriptor_to_rop(stroke->fore_mode,
- ROP_INPUT_BRUSH,
- ROP_INPUT_DEST);
- gc.back_rop = ropd_descriptor_to_rop(stroke->back_mode,
- ROP_INPUT_BRUSH,
- ROP_INPUT_DEST);
-
- gc.base.width = canvas->width;
- gc.base.height = canvas->height;
- gc.base.alu = gc.fore_rop;
- gc.base.lineWidth = 0;
-
- /* dash */
- gc.base.dashOffset = 0;
- gc.base.dash = NULL;
- gc.base.numInDashList = 0;
- gc.base.lineStyle = LineSolid;
- /* win32 cosmetic lines are endpoint-exclusive, so use CapNotLast */
- gc.base.capStyle = CapNotLast;
- gc.base.joinStyle = JoinMiter;
- gc.base.ops = &ops;
-
- dashed = 0;
- if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) {
- SPICE_FIXED28_4 *style = stroke->attr.style;
- int nseg;
-
- dashed = 1;
-
- nseg = stroke->attr.style_nseg;
-
- /* To truly handle back_mode we should use LineDoubleDash here
- and treat !foreground as back_rop using the same brush.
- However, using the same brush for that seems wrong.
- The old cairo backend was stroking the non-dashed line with
- rop_mode before enabling dashes for the foreground which is
- not right either. The gl an gdi backend don't use back_mode
- at all */
- gc.base.lineStyle = LineOnOffDash;
- gc.base.dash = (unsigned char *)spice_malloc(nseg);
- gc.base.numInDashList = nseg;
-
- if (stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP) {
- gc.base.dash[stroke->attr.style_nseg - 1] = fix_to_int(style[0]);
- for (i = 0; i < (unsigned int)(stroke->attr.style_nseg - 1); i++) {
- gc.base.dash[i] = fix_to_int(style[i+1]);
- }
- gc.base.dashOffset = gc.base.dash[0];
- } else {
- for (i = 0; i < stroke->attr.style_nseg; i++) {
- gc.base.dash[i] = fix_to_int(style[i]);
- }
- }
- }
-
- switch (stroke->brush.type) {
- case SPICE_BRUSH_TYPE_NONE:
- gc.solid = TRUE;
- gc.color = 0;
- break;
- case SPICE_BRUSH_TYPE_SOLID:
- gc.solid = TRUE;
- gc.color = stroke->brush.u.color;
- break;
- case SPICE_BRUSH_TYPE_PATTERN:
- gc.solid = FALSE;
- surface_canvas = canvas_get_surface(canvas,
- stroke->brush.u.pattern.pat);
- if (surface_canvas) {
- gc.use_surface_canvas = TRUE;
- gc.surface_canvas = surface_canvas;
- } else {
- gc.use_surface_canvas = FALSE;
- gc.tile = canvas_get_image(canvas,
- stroke->brush.u.pattern.pat,
- FALSE);
- }
- gc.tile_offset_x = stroke->brush.u.pattern.pos.x;
- gc.tile_offset_y = stroke->brush.u.pattern.pos.y;
- break;
- default:
- spice_warn_if_reached();
- return;
- }
-
- stroke_lines_init(&lines);
-
- for (i = 0; i < stroke->path->num_segments; i++) {
- SpicePathSeg *seg = stroke->path->segments[i];
- SpicePointFix* point, *end_point;
-
- point = seg->points;
- end_point = point + seg->count;
-
- if (seg->flags & SPICE_PATH_BEGIN) {
- stroke_lines_draw(&lines, (lineGC *)&gc, dashed);
- stroke_lines_append_fix(&lines, point);
- point++;
- }
-
- if (seg->flags & SPICE_PATH_BEZIER) {
- spice_return_if_fail((point - end_point) % 3 == 0);
- for (; point + 2 < end_point; point += 3) {
- stroke_lines_append_bezier(&lines,
- &point[0],
- &point[1],
- &point[2]);
- }
- } else
- {
- for (; point < end_point; point++) {
- stroke_lines_append_fix(&lines, point);
- }
- }
- if (seg->flags & SPICE_PATH_END) {
- if (seg->flags & SPICE_PATH_CLOSE) {
- stroke_lines_append(&lines,
- lines.points[0].x, lines.points[0].y);
- }
- stroke_lines_draw(&lines, (lineGC *)&gc, dashed);
- }
- }
-
- stroke_lines_draw(&lines, (lineGC *)&gc, dashed);
-
- if (gc.base.dash) {
- free(gc.base.dash);
- }
- stroke_lines_free(&lines);
-
- if (!gc.solid && gc.tile && !surface_canvas) {
- pixman_image_unref(gc.tile);
- }
-
- pixman_region32_fini(&gc.dest_region);
-}
-
-
-//need surfaces handling here !!!
-static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
- SpiceClip *clip, SpiceRop3 *rop3)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- SpiceCanvas *surface_canvas;
- pixman_region32_t dest_region;
- pixman_image_t *d;
- pixman_image_t *s;
- SpicePoint src_pos;
- int width;
- int heigth;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
- canvas_mask_pixman(canvas, &dest_region, &rop3->mask,
- bbox->left, bbox->top);
-
- width = bbox->right - bbox->left;
- heigth = bbox->bottom - bbox->top;
-
- d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, heigth);
- surface_canvas = canvas_get_surface(canvas, rop3->src_bitmap);
- if (surface_canvas) {
- s = surface_canvas->ops->get_image(surface_canvas);
- } else {
- s = canvas_get_image(canvas, rop3->src_bitmap, FALSE);
- }
-
- if (!rect_is_same_size(bbox, &rop3->src_area)) {
- pixman_image_t *scaled_s = canvas_scale_surface(s, &rop3->src_area, width, heigth,
- rop3->scale_mode);
- pixman_image_unref(s);
- s = scaled_s;
- src_pos.x = 0;
- src_pos.y = 0;
- } else {
- src_pos.x = rop3->src_area.left;
- src_pos.y = rop3->src_area.top;
- }
- if (pixman_image_get_width(s) - src_pos.x < width ||
- pixman_image_get_height(s) - src_pos.y < heigth) {
- spice_critical("bad src bitmap size");
- return;
- }
- if (rop3->brush.type == SPICE_BRUSH_TYPE_PATTERN) {
- SpiceCanvas *_surface_canvas;
- pixman_image_t *p;
-
- _surface_canvas = canvas_get_surface(canvas, rop3->brush.u.pattern.pat);
- if (_surface_canvas) {
- p = _surface_canvas->ops->get_image(_surface_canvas);
- } else {
- p = canvas_get_image(canvas, rop3->brush.u.pattern.pat, FALSE);
- }
- SpicePoint pat_pos;
-
- pat_pos.x = (bbox->left - rop3->brush.u.pattern.pos.x) % pixman_image_get_width(p);
- pat_pos.y = (bbox->top - rop3->brush.u.pattern.pos.y) % pixman_image_get_height(p);
- do_rop3_with_pattern(rop3->rop3, d, s, &src_pos, p, &pat_pos);
- pixman_image_unref(p);
- } else {
- do_rop3_with_color(rop3->rop3, d, s, &src_pos, rop3->brush.u.color);
- }
- pixman_image_unref(s);
-
- spice_canvas->ops->blit_image(spice_canvas, &dest_region, d,
- bbox->left,
- bbox->top);
-
- pixman_image_unref(d);
-
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_t dest_region;
- int dx, dy;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(canvas, &dest_region, clip);
-
- dx = bbox->left - src_pos->x;
- dy = bbox->top - src_pos->y;
-
- if (dx != 0 || dy != 0) {
- pixman_region32_t src_region;
-
- /* Clip so we don't read outside canvas */
- pixman_region32_init_rect(&src_region,
- dx, dy,
- canvas->width,
- canvas->height);
- pixman_region32_intersect(&dest_region, &dest_region, &src_region);
- pixman_region32_fini(&src_region);
-
- spice_canvas->ops->copy_region(spice_canvas, &dest_region, dx, dy);
- }
-
- pixman_region32_fini(&dest_region);
-}
-
-
-
-static void canvas_base_group_start(SpiceCanvas *spice_canvas, QRegion *region)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_fini(&canvas->canvas_region);
-
- /* Make sure we always clip to canvas size */
- pixman_region32_init_rect(&canvas->canvas_region,
- 0, 0,
- canvas->width,
- canvas->height);
-
- pixman_region32_intersect(&canvas->canvas_region, &canvas->canvas_region, region);
-}
-
-static void canvas_base_group_end(SpiceCanvas *spice_canvas)
-{
- CanvasBase *canvas = (CanvasBase *)spice_canvas;
- pixman_region32_fini(&canvas->canvas_region);
- pixman_region32_init_rect(&canvas->canvas_region,
- 0, 0,
- canvas->width,
- canvas->height);
-}
-
-
-static void unimplemented_op(SpiceCanvas *canvas)
-{
- spice_critical("unimplemented canvas operation");
-}
-
-inline static void canvas_base_init_ops(SpiceCanvasOps *ops)
-{
- void **ops_cast;
- unsigned i;
-
- ops_cast = (void **)ops;
- for (i = 0; i < sizeof(SpiceCanvasOps) / sizeof(void *); i++) {
- ops_cast[i] = (void *) unimplemented_op;
- }
-
- ops->draw_fill = canvas_draw_fill;
- ops->draw_copy = canvas_draw_copy;
- ops->draw_opaque = canvas_draw_opaque;
- ops->copy_bits = canvas_copy_bits;
- ops->draw_blend = canvas_draw_blend;
- ops->draw_blackness = canvas_draw_blackness;
- ops->draw_whiteness = canvas_draw_whiteness;
- ops->draw_invers = canvas_draw_invers;
- ops->draw_transparent = canvas_draw_transparent;
- ops->draw_alpha_blend = canvas_draw_alpha_blend;
- ops->draw_stroke = canvas_draw_stroke;
- ops->draw_rop3 = canvas_draw_rop3;
- ops->group_start = canvas_base_group_start;
- ops->group_end = canvas_base_group_end;
-}
-
-static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
- int width, int height, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- canvas->parent.ops = ops;
- canvas->quic_data.usr.error = quic_usr_error;
- canvas->quic_data.usr.warn = quic_usr_warn;
- canvas->quic_data.usr.info = quic_usr_warn;
- canvas->quic_data.usr.malloc = quic_usr_malloc;
- canvas->quic_data.usr.free = quic_usr_free;
- canvas->quic_data.usr.more_space = quic_usr_more_space;
- canvas->quic_data.usr.more_lines = quic_usr_more_lines;
- if (!(canvas->quic_data.quic = quic_create(&canvas->quic_data.usr))) {
- return 0;
- }
-
- canvas->lz_data.usr.error = lz_usr_error;
- canvas->lz_data.usr.warn = lz_usr_warn;
- canvas->lz_data.usr.info = lz_usr_warn;
- canvas->lz_data.usr.malloc = lz_usr_malloc;
- canvas->lz_data.usr.free = lz_usr_free;
- canvas->lz_data.usr.more_space = lz_usr_more_space;
- canvas->lz_data.usr.more_lines = lz_usr_more_lines;
- if (!(canvas->lz_data.lz = lz_create(&canvas->lz_data.usr))) {
- return 0;
- }
-
- canvas->surfaces = surfaces;
- canvas->glz_data.decoder = glz_decoder;
- canvas->jpeg = jpeg_decoder;
- canvas->zlib = zlib_decoder;
-
- canvas->format = format;
-
- /* TODO: This is all wrong now */
- if (SPICE_SURFACE_FMT_DEPTH(format) == 16) {
- canvas->color_shift = 5;
- canvas->color_mask = 0x1f;
- } else {
- canvas->color_shift = 8;
- canvas->color_mask = 0xff;
- }
-
- canvas->width = width;
- canvas->height = height;
- pixman_region32_init_rect(&canvas->canvas_region,
- 0, 0,
- canvas->width,
- canvas->height);
-
-#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
- canvas->bits_cache = bits_cache;
-#endif
-#ifdef SW_CANVAS_CACHE
- canvas->palette_cache = palette_cache;
-#endif
-
-#ifdef WIN32
- canvas->dc = NULL;
-#endif
-
-#ifdef GDI_CANVAS
- canvas->dc = create_compatible_dc();
- if (!canvas->dc) {
- lz_destroy(canvas->lz_data.lz);
- return 0;
- }
-#endif
- return 1;
-}
diff --git a/common/canvas_base.h b/common/canvas_base.h
deleted file mode 100644
index bea041f..0000000
--- a/common/canvas_base.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_CANVAS_BASE
-#define _H_CANVAS_BASE
-
-
-#include "pixman_utils.h"
-#include "lz.h"
-#include "region.h"
-#include "draw.h"
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-typedef void (*spice_destroy_fn_t)(void *data);
-
-typedef struct _SpiceImageCache SpiceImageCache;
-typedef struct _SpiceImageSurfaces SpiceImageSurfaces;
-typedef struct _SpicePaletteCache SpicePaletteCache;
-typedef struct _SpiceGlzDecoder SpiceGlzDecoder;
-typedef struct _SpiceJpegDecoder SpiceJpegDecoder;
-typedef struct _SpiceZlibDecoder SpiceZlibDecoder;
-typedef struct _SpiceCanvas SpiceCanvas;
-
-typedef struct {
- void (*put)(SpiceImageCache *cache,
- uint64_t id,
- pixman_image_t *surface);
- pixman_image_t *(*get)(SpiceImageCache *cache,
- uint64_t id);
-#ifdef SW_CANVAS_CACHE
- void (*put_lossy)(SpiceImageCache *cache,
- uint64_t id,
- pixman_image_t *surface);
- void (*replace_lossy)(SpiceImageCache *cache,
- uint64_t id,
- pixman_image_t *surface);
- pixman_image_t *(*get_lossless)(SpiceImageCache *cache,
- uint64_t id);
-#endif
-} SpiceImageCacheOps;
-
-struct _SpiceImageCache {
- SpiceImageCacheOps *ops;
-};
-
-typedef struct {
- SpiceCanvas *(*get)(SpiceImageSurfaces *surfaces,
- uint32_t surface_id);
-} SpiceImageSurfacesOps;
-
-struct _SpiceImageSurfaces {
- SpiceImageSurfacesOps *ops;
-};
-
-typedef struct {
- void (*put)(SpicePaletteCache *cache,
- SpicePalette *palette);
- SpicePalette *(*get)(SpicePaletteCache *cache,
- uint64_t id);
- void (*release)(SpicePaletteCache *cache,
- SpicePalette *palette);
-} SpicePaletteCacheOps;
-
-struct _SpicePaletteCache {
- SpicePaletteCacheOps *ops;
-};
-
-typedef struct {
- void (*decode)(SpiceGlzDecoder *decoder,
- uint8_t *data,
- SpicePalette *plt,
- void *usr_data);
-} SpiceGlzDecoderOps;
-
-struct _SpiceGlzDecoder {
- SpiceGlzDecoderOps *ops;
-};
-
-
-typedef struct SpiceJpegDecoderOps {
- void (*begin_decode)(SpiceJpegDecoder *decoder,
- uint8_t* data,
- int data_size,
- int* out_width,
- int* out_height);
- void (*decode)(SpiceJpegDecoder *decoder,
- uint8_t* dest,
- int stride,
- int format);
-} SpiceJpegDecoderOps;
-
-struct _SpiceJpegDecoder {
- SpiceJpegDecoderOps *ops;
-};
-
-typedef struct {
- void (*decode)(SpiceZlibDecoder *decoder,
- uint8_t *data,
- int data_size,
- uint8_t *dest,
- int dest_size);
-} SpiceZlibDecoderOps;
-
-struct _SpiceZlibDecoder {
- SpiceZlibDecoderOps *ops;
-};
-
-typedef struct {
- void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill);
- void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy);
- void (*draw_opaque)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque);
- void (*copy_bits)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos);
- void (*draw_text)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text);
- void (*draw_stroke)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke);
- void (*draw_rop3)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3);
- void (*draw_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend);
- void (*draw_blackness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness);
- void (*draw_whiteness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness);
- void (*draw_invers)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers);
- void (*draw_transparent)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent);
- void (*draw_alpha_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend);
- void (*put_image)(SpiceCanvas *canvas,
-#ifdef WIN32
- HDC dc,
-#endif
- const SpiceRect *dest, const uint8_t *src_data,
- uint32_t src_width, uint32_t src_height, int src_stride,
- const QRegion *clip);
- void (*clear)(SpiceCanvas *canvas);
- void (*read_bits)(SpiceCanvas *canvas, uint8_t *dest, int dest_stride, const SpiceRect *area);
- void (*group_start)(SpiceCanvas *canvas, QRegion *region);
- void (*group_end)(SpiceCanvas *canvas);
- void (*destroy)(SpiceCanvas *canvas);
-
- /* Implementation vfuncs */
- void (*fill_solid_spans)(SpiceCanvas *canvas,
- SpicePoint *points,
- int *widths,
- int n_spans,
- uint32_t color);
- void (*fill_solid_rects)(SpiceCanvas *canvas,
- pixman_box32_t *rects,
- int n_rects,
- uint32_t color);
- void (*fill_solid_rects_rop)(SpiceCanvas *canvas,
- pixman_box32_t *rects,
- int n_rects,
- uint32_t color,
- SpiceROP rop);
- void (*fill_tiled_rects)(SpiceCanvas *canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y);
- void (*fill_tiled_rects_from_surface)(SpiceCanvas *canvas,
- pixman_box32_t *rects,
- int n_rects,
- SpiceCanvas *tile,
- int offset_x, int offset_y);
- void (*fill_tiled_rects_rop)(SpiceCanvas *canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y,
- SpiceROP rop);
- void (*fill_tiled_rects_rop_from_surface)(SpiceCanvas *canvas,
- pixman_box32_t *rects,
- int n_rects,
- SpiceCanvas *tile,
- int offset_x, int offset_y,
- SpiceROP rop);
- void (*blit_image)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y);
- void (*blit_image_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceCanvas *src_image,
- int offset_x, int offset_y);
- void (*blit_image_rop)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- SpiceROP rop);
- void (*blit_image_rop_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceCanvas *src_image,
- int offset_x, int offset_y,
- SpiceROP rop);
- void (*scale_image)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode);
- void (*scale_image_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceCanvas *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode);
- void (*scale_image_rop)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop);
- void (*scale_image_rop_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceCanvas *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop);
- void (*blend_image)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src_image,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha);
- void (*blend_image_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- SpiceCanvas *src_image,
- int src_has_alpha,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha);
- void (*blend_scale_image)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha);
- void (*blend_scale_image_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- SpiceCanvas *src_image,
- int src_has_alpha,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha);
- void (*colorkey_image)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- uint32_t transparent_color);
- void (*colorkey_image_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceCanvas *src_image,
- int offset_x, int offset_y,
- uint32_t transparent_color);
- void (*colorkey_scale_image)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color);
- void (*colorkey_scale_image_from_surface)(SpiceCanvas *canvas,
- pixman_region32_t *region,
- SpiceCanvas *src_image,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color);
- void (*copy_region)(SpiceCanvas *canvas,
- pixman_region32_t *dest_region,
- int dx, int dy);
- pixman_image_t *(*get_image)(SpiceCanvas *canvas);
-} SpiceCanvasOps;
-
-void spice_canvas_set_usr_data(SpiceCanvas *canvas, void *data, spice_destroy_fn_t destroy_fn);
-void *spice_canvas_get_usr_data(SpiceCanvas *canvas);
-
-struct _SpiceCanvas {
- SpiceCanvasOps *ops;
-};
-
-#endif
diff --git a/common/canvas_utils.c b/common/canvas_utils.c
deleted file mode 100644
index 743c86c..0000000
--- a/common/canvas_utils.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "canvas_utils.h"
-
-#include <spice/macros.h>
-
-#ifdef __GNUC__
-#include <stdlib.h>
-#include <stdio.h>
-#endif
-#include "mem.h"
-
-#ifdef WIN32
-static int gdi_handlers = 0;
-#endif
-
-#ifndef ASSERT
-#define ASSERT(x) if (!(x)) { \
- printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \
- abort(); \
-}
-#endif
-
-
-#ifndef CANVAS_ERROR
-#define CANVAS_ERROR(format, ...) { \
- printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__); \
- abort(); \
-}
-#endif
-
-static void release_data(pixman_image_t *image, void *release_data)
-{
- PixmanData *data = (PixmanData *)release_data;
-
-#ifdef WIN32
- if (data->bitmap) {
- DeleteObject((HBITMAP)data->bitmap);
- CloseHandle(data->mutex);
- gdi_handlers--;
- }
-#endif
- if (data->data) {
- free(data->data);
- }
-
- free(data);
-}
-
-static PixmanData *
-pixman_image_add_data(pixman_image_t *image)
-{
- PixmanData *data;
-
- data = (PixmanData *)pixman_image_get_destroy_data(image);
- if (data == NULL) {
- data = (PixmanData *)calloc(1, sizeof(PixmanData));
- if (data == NULL) {
- CANVAS_ERROR("out of memory");
- }
- pixman_image_set_destroy_function(image,
- release_data,
- data);
- }
-
- return data;
-}
-
-void
-spice_pixman_image_set_format(pixman_image_t *image,
- pixman_format_code_t format)
-{
- PixmanData *data;
-
- data = pixman_image_add_data(image);
- data->format = format;
-}
-
-pixman_format_code_t
-spice_pixman_image_get_format(pixman_image_t *image)
-{
- PixmanData *data;
-
- data = (PixmanData *)pixman_image_get_destroy_data(image);
- if (data != NULL &&
- data->format != 0)
- return data->format;
-
- CANVAS_ERROR("Unknown pixman image type");
-}
-
-static inline pixman_image_t *__surface_create_stride(pixman_format_code_t format, int width, int height,
- int stride)
-{
- uint8_t *data;
- uint8_t *stride_data;
- pixman_image_t *surface;
- PixmanData *pixman_data;
-
- data = (uint8_t *)spice_malloc_n(abs(stride), height);
- if (stride < 0) {
- stride_data = data + (-stride) * (height - 1);
- } else {
- stride_data = data;
- }
-
- surface = pixman_image_create_bits(format, width, height, (uint32_t *)stride_data, stride);
-
- if (surface == NULL) {
- free(data);
- CANVAS_ERROR("create surface failed, out of memory");
- }
-
- pixman_data = pixman_image_add_data(surface);
- pixman_data->data = data;
- pixman_data->format = format;
-
- return surface;
-}
-
-#ifdef WIN32
-pixman_image_t *surface_create(HDC dc, pixman_format_code_t format,
- int width, int height, int top_down)
-#else
-pixman_image_t * surface_create(pixman_format_code_t format, int width, int height, int top_down)
-#endif
-{
-#ifdef WIN32
- /*
- * Windows xp allow only 10,000 of gdi handlers, considering the fact that
- * we limit here the number to 5000, we dont use atomic operations to sync
- * this calculation against the other canvases (in case of multiple
- * monitors), in worst case there will be little more than 5000 gdi
- * handlers.
- */
- if (dc && gdi_handlers < 5000) {
- uint8_t *data;
- uint8_t *src;
- struct {
- BITMAPINFO inf;
- RGBQUAD palette[255];
- } bitmap_info;
- int nstride;
- pixman_image_t *surface;
- PixmanData *pixman_data;
- HBITMAP bitmap;
- HANDLE mutex;
-
- memset(&bitmap_info, 0, sizeof(bitmap_info));
- bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
- bitmap_info.inf.bmiHeader.biWidth = width;
-
- bitmap_info.inf.bmiHeader.biHeight = (!top_down) ? height : -height;
-
- bitmap_info.inf.bmiHeader.biPlanes = 1;
- switch (format) {
- case PIXMAN_a8r8g8b8:
- case PIXMAN_x8r8g8b8:
- bitmap_info.inf.bmiHeader.biBitCount = 32;
- nstride = width * 4;
- break;
- case PIXMAN_x1r5g5b5:
- case PIXMAN_r5g6b5:
- bitmap_info.inf.bmiHeader.biBitCount = 16;
- nstride = SPICE_ALIGN(width * 2, 4);
- break;
- case PIXMAN_a8:
- bitmap_info.inf.bmiHeader.biBitCount = 8;
- nstride = SPICE_ALIGN(width, 4);
- break;
- case PIXMAN_a1:
- bitmap_info.inf.bmiHeader.biBitCount = 1;
- nstride = SPICE_ALIGN(width, 32) / 8;
- break;
- default:
- CANVAS_ERROR("invalid format");
- }
-
- bitmap_info.inf.bmiHeader.biCompression = BI_RGB;
-
- mutex = CreateMutex(NULL, 0, NULL);
- if (!mutex) {
- CANVAS_ERROR("Unable to CreateMutex");
- }
-
- bitmap = CreateDIBSection(dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0);
- if (!bitmap) {
- CloseHandle(mutex);
- CANVAS_ERROR("Unable to CreateDIBSection");
- }
-
- if (top_down) {
- src = data;
- } else {
- src = data + nstride * (height - 1);
- nstride = -nstride;
- }
-
- surface = pixman_image_create_bits(format, width, height, (uint32_t *)src, nstride);
- if (surface == NULL) {
- CloseHandle(mutex);
- DeleteObject(bitmap);
- CANVAS_ERROR("create surface failed, out of memory");
- }
- pixman_data = pixman_image_add_data(surface);
- pixman_data->format = format;
- pixman_data->bitmap = bitmap;
- pixman_data->mutex = mutex;
- gdi_handlers++;
- return surface;
- } else {
-#endif
- if (top_down) {
- pixman_image_t *surface;
- PixmanData *data;
-
- surface = pixman_image_create_bits(format, width, height, NULL, 0);
- data = pixman_image_add_data(surface);
- data->format = format;
- return surface;
- } else {
- // NOTE: we assume here that the lz decoders always decode to RGB32.
- int stride = 0;
- switch (format) {
- case PIXMAN_a8r8g8b8:
- case PIXMAN_x8r8g8b8:
- stride = width * 4;
- break;
- case PIXMAN_x1r5g5b5:
- case PIXMAN_r5g6b5:
- stride = SPICE_ALIGN(width * 2, 4);
- break;
- case PIXMAN_a8:
- stride = SPICE_ALIGN(width, 4);
- break;
- case PIXMAN_a1:
- stride = SPICE_ALIGN(width, 32) / 8;
- break;
- default:
- CANVAS_ERROR("invalid format");
- }
- stride = -stride;
- return __surface_create_stride(format, width, height, stride);
- }
-#ifdef WIN32
-}
-
-#endif
-}
-
-#ifdef WIN32
-pixman_image_t *surface_create_stride(HDC dc, pixman_format_code_t format, int width, int height,
- int stride)
-#else
-pixman_image_t *surface_create_stride(pixman_format_code_t format, int width, int height,
- int stride)
-#endif
-{
-#ifdef WIN32
- if (dc) {
- if (abs(stride) == (width * 4)) {
- return surface_create(dc, format, width, height, (stride > 0));
- }
- }
-#endif
-
- return __surface_create_stride(format, width, height, stride);
-}
-
-pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data,
- pixman_format_code_t pixman_format, int width,
- int height, int gross_pixels, int top_down)
-{
- int stride;
- pixman_image_t *surface = NULL;
-
- stride = (gross_pixels / height) * (PIXMAN_FORMAT_BPP (pixman_format) / 8);
-
- if (!top_down) {
- stride = -stride;
- }
-
- surface = surface_create_stride(
-#ifdef WIN32
- canvas_data->dc,
-#endif
- pixman_format, width, height, stride);
- canvas_data->out_surface = surface;
- return surface;
-}
-
diff --git a/common/canvas_utils.h b/common/canvas_utils.h
deleted file mode 100644
index fe66f85..0000000
--- a/common/canvas_utils.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_CANVAS_UTILS
-#define _H_CANVAS_UTILS
-
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-#include <spice/types.h>
-
-#include "pixman_utils.h"
-#include "lz.h"
-
-typedef struct PixmanData {
-#ifdef WIN32
- HBITMAP bitmap;
- HANDLE mutex;
-#endif
- uint8_t *data;
- pixman_format_code_t format;
-} PixmanData;
-
-void spice_pixman_image_set_format(pixman_image_t *image,
- pixman_format_code_t format);
-pixman_format_code_t spice_pixman_image_get_format(pixman_image_t *image);
-
-
-#ifdef WIN32
-pixman_image_t *surface_create(HDC dc, pixman_format_code_t format,
- int width, int height, int top_down);
-#else
-pixman_image_t *surface_create(pixman_format_code_t format, int width, int height, int top_down);
-#endif
-
-#ifdef WIN32
-pixman_image_t *surface_create_stride(HDC dc, pixman_format_code_t format, int width, int height,
- int stride);
-#else
-pixman_image_t *surface_create_stride(pixman_format_code_t format, int width, int height,
- int stride);
-#endif
-
-
-typedef struct LzDecodeUsrData {
-#ifdef WIN32
- HDC dc;
-#endif
- pixman_image_t *out_surface;
-} LzDecodeUsrData;
-
-
-pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data,
- pixman_format_code_t pixman_format, int width,
- int height, int gross_pixels, int top_down);
-#endif
diff --git a/common/demarshallers.h b/common/demarshallers.h
deleted file mode 100644
index fc2f75a..0000000
--- a/common/demarshallers.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- Copyright (C) 2010 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef _H_DEMARSHAL
-#define _H_DEMARSHAL
-
-typedef void (*message_destructor_t)(uint8_t *message);
-typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor,
- size_t *size_out, message_destructor_t *free_message);
-
-spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type);
-spice_parse_channel_func_t spice_get_server_channel_parser1(uint32_t channel, unsigned int *max_message_type);
-
-#endif
-
diff --git a/common/draw.h b/common/draw.h
deleted file mode 100644
index 994aebb..0000000
--- a/common/draw.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- * Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _H_SPICE_DRAW
-#define _H_SPICE_DRAW
-
-#include <spice/types.h>
-#include <spice/enums.h>
-#include "mem.h"
-
-#define SPICE_GET_ADDRESS(addr) ((void *)(uintptr_t)(addr))
-#define SPICE_SET_ADDRESS(addr, val) ((addr) = (unsigned long)(val))
-
-typedef int32_t SPICE_FIXED28_4;
-typedef uint64_t SPICE_ADDRESS;
-
-typedef struct SpicePointFix {
- SPICE_FIXED28_4 x;
- SPICE_FIXED28_4 y;
-} SpicePointFix;
-
-typedef struct SpicePoint {
- int32_t x;
- int32_t y;
-} SpicePoint;
-
-typedef struct SpicePoint16 {
- int16_t x;
- int16_t y;
-} SpicePoint16;
-
-typedef struct SpiceRect {
- int32_t left;
- int32_t top;
- int32_t right;
- int32_t bottom;
-} SpiceRect;
-
-typedef struct SpicePathSeg {
- uint32_t flags;
- uint32_t count;
- SpicePointFix points[0];
-} SpicePathSeg;
-
-typedef struct SpicePath {
- uint32_t num_segments;
- SpicePathSeg *segments[0];
-} SpicePath;
-
-typedef struct SpiceClipRects {
- uint32_t num_rects;
- SpiceRect rects[0];
-} SpiceClipRects;
-
-typedef struct SpiceClip {
- uint32_t type;
- SpiceClipRects *rects;
-} SpiceClip;
-
-typedef struct SpicePalette {
- uint64_t unique;
- uint16_t num_ents;
- uint32_t ents[0];
-} SpicePalette;
-
-#define SPICE_SURFACE_FMT_DEPTH(_d) ((_d) & 0x3f)
-
-typedef struct SpiceImageDescriptor {
- uint64_t id;
- uint8_t type;
- uint8_t flags;
- uint32_t width;
- uint32_t height;
-} SpiceImageDescriptor;
-
-typedef struct SpiceBitmap {
- uint8_t format;
- uint8_t flags;
- uint32_t x;
- uint32_t y;
- uint32_t stride;
- SpicePalette *palette;
- uint64_t palette_id;
- SpiceChunks *data;
-} SpiceBitmap;
-
-typedef struct SpiceSurface {
- uint32_t surface_id;
-} SpiceSurface;
-
-typedef struct SpiceQUICData {
- uint32_t data_size;
- SpiceChunks *data;
-} SpiceQUICData, SpiceLZRGBData, SpiceJPEGData;
-
-typedef struct SpiceLZPLTData {
- uint8_t flags;
- uint32_t data_size;
- SpicePalette *palette;
- uint64_t palette_id;
- SpiceChunks *data;
-} SpiceLZPLTData;
-
-typedef struct SpiceZlibGlzRGBData {
- uint32_t glz_data_size;
- uint32_t data_size;
- SpiceChunks *data;
-} SpiceZlibGlzRGBData;
-
-typedef struct SpiceJPEGAlphaData {
- uint8_t flags;
- uint32_t jpeg_size;
- uint32_t data_size;
- SpiceChunks *data;
-} SpiceJPEGAlphaData;
-
-
-typedef struct SpiceImage {
- SpiceImageDescriptor descriptor;
- union {
- SpiceBitmap bitmap;
- SpiceQUICData quic;
- SpiceSurface surface;
- SpiceLZRGBData lz_rgb;
- SpiceLZPLTData lz_plt;
- SpiceJPEGData jpeg;
- SpiceZlibGlzRGBData zlib_glz;
- SpiceJPEGAlphaData jpeg_alpha;
- } u;
-} SpiceImage;
-
-typedef struct SpicePattern {
- SpiceImage *pat;
- SpicePoint pos;
-} SpicePattern;
-
-typedef struct SpiceBrush {
- uint32_t type;
- union {
- uint32_t color;
- SpicePattern pattern;
- } u;
-} SpiceBrush;
-
-typedef struct SpiceQMask {
- uint8_t flags;
- SpicePoint pos;
- SpiceImage *bitmap;
-} SpiceQMask;
-
-typedef struct SpiceFill {
- SpiceBrush brush;
- uint16_t rop_descriptor;
- SpiceQMask mask;
-} SpiceFill;
-
-typedef struct SpiceOpaque {
- SpiceImage *src_bitmap;
- SpiceRect src_area;
- SpiceBrush brush;
- uint16_t rop_descriptor;
- uint8_t scale_mode;
- SpiceQMask mask;
-} SpiceOpaque;
-
-typedef struct SpiceCopy {
- SpiceImage *src_bitmap;
- SpiceRect src_area;
- uint16_t rop_descriptor;
- uint8_t scale_mode;
- SpiceQMask mask;
-} SpiceCopy, SpiceBlend;
-
-typedef struct SpiceTransparent {
- SpiceImage *src_bitmap;
- SpiceRect src_area;
- uint32_t src_color;
- uint32_t true_color;
-} SpiceTransparent;
-
-typedef struct SpiceAlphaBlend {
- uint16_t alpha_flags;
- uint8_t alpha;
- SpiceImage *src_bitmap;
- SpiceRect src_area;
-} SpiceAlphaBlend;
-
-typedef struct SpiceRop3 {
- SpiceImage *src_bitmap;
- SpiceRect src_area;
- SpiceBrush brush;
- uint8_t rop3;
- uint8_t scale_mode;
- SpiceQMask mask;
-} SpiceRop3;
-
-typedef struct SpiceBlackness {
- SpiceQMask mask;
-} SpiceBlackness, SpiceInvers, SpiceWhiteness;
-
-typedef struct SpiceLineAttr {
- uint8_t flags;
- uint8_t style_nseg;
- SPICE_FIXED28_4 *style;
-} SpiceLineAttr;
-
-typedef struct SpiceStroke {
- SpicePath *path;
- SpiceLineAttr attr;
- SpiceBrush brush;
- uint16_t fore_mode;
- uint16_t back_mode;
-} SpiceStroke;
-
-typedef struct SpiceRasterGlyph {
- SpicePoint render_pos;
- SpicePoint glyph_origin;
- uint16_t width;
- uint16_t height;
- uint8_t data[0];
-} SpiceRasterGlyph;
-
-typedef struct SpiceString {
- uint16_t length;
- uint16_t flags;
- SpiceRasterGlyph *glyphs[0];
-} SpiceString;
-
-typedef struct SpiceText {
- SpiceString *str;
- SpiceRect back_area;
- SpiceBrush fore_brush;
- SpiceBrush back_brush;
- uint16_t fore_mode;
- uint16_t back_mode;
-} SpiceText;
-
-typedef struct SpiceCursorHeader {
- uint64_t unique;
- uint16_t type;
- uint16_t width;
- uint16_t height;
- uint16_t hot_spot_x;
- uint16_t hot_spot_y;
-} SpiceCursorHeader;
-
-#endif /* _H_SPICE_DRAW */
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
deleted file mode 100644
index a11ba90..0000000
--- a/common/gdi_canvas.c
+++ /dev/null
@@ -1,1870 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <windows.h>
-#include <wingdi.h>
-#include "gdi_canvas.h"
-#define GDI_CANVAS
-#include "canvas_base.c"
-#include "rop3.h"
-#include "rect.h"
-#include "region.h"
-#include "threads.h"
-
-typedef struct GdiCanvas GdiCanvas;
-
-struct GdiCanvas {
- CanvasBase base;
- HDC dc;
- RecurciveMutex* lock;
-};
-
-
-struct BitmapData {
- HBITMAP hbitmap;
- HBITMAP prev_hbitmap;
- SpicePoint pos;
- uint8_t flags;
- HDC dc;
- int cache;
- int from_surface;
-};
-
-#define _rop3_brush 0xf0
-#define _rop3_src 0xcc
-#define _rop3_dest 0xaa
-
-uint32_t raster_ops[] = {
- 0x00000042,
- 0x00010289,
- 0x00020C89,
- 0x000300AA,
- 0x00040C88,
- 0x000500A9,
- 0x00060865,
- 0x000702C5,
- 0x00080F08,
- 0x00090245,
- 0x000A0329,
- 0x000B0B2A,
- 0x000C0324,
- 0x000D0B25,
- 0x000E08A5,
- 0x000F0001,
- 0x00100C85,
- 0x001100A6,
- 0x00120868,
- 0x001302C8,
- 0x00140869,
- 0x001502C9,
- 0x00165CCA,
- 0x00171D54,
- 0x00180D59,
- 0x00191CC8,
- 0x001A06C5,
- 0x001B0768,
- 0x001C06CA,
- 0x001D0766,
- 0x001E01A5,
- 0x001F0385,
- 0x00200F09,
- 0x00210248,
- 0x00220326,
- 0x00230B24,
- 0x00240D55,
- 0x00251CC5,
- 0x002606C8,
- 0x00271868,
- 0x00280369,
- 0x002916CA,
- 0x002A0CC9,
- 0x002B1D58,
- 0x002C0784,
- 0x002D060A,
- 0x002E064A,
- 0x002F0E2A,
- 0x0030032A,
- 0x00310B28,
- 0x00320688,
- 0x00330008,
- 0x003406C4,
- 0x00351864,
- 0x003601A8,
- 0x00370388,
- 0x0038078A, // PSDPoax
- 0x00390604, // SPDnox
- 0x003A0644, // SPDSxox
- 0x003B0E24, // SPDnoan
- 0x003C004A, // PSx
- 0x003D18A4, // SPDSonox
- 0x003E1B24, // SPDSnaox
- 0x003F00EA, // PSan
- 0x00400F0A, // PSDnaa
- 0x00410249, // DPSxon
- 0x00420D5D, // SDxPDxa
- 0x00431CC4, // SPDSanaxn
- 0x00440328, // SDna SRCERASE
- 0x00450B29, // DPSnaon
- 0x004606C6, // DSPDaox
- 0x0047076A, // PSDPxaxn
- 0x00480368, // SDPxa
- 0x004916C5, // PDSPDaoxxn
- 0x004A0789, // DPSDoax
- 0x004B0605, // PDSnox
- 0x004C0CC8, // SDPana
- 0x004D1954, // SSPxDSxoxn
- 0x004E0645, // PDSPxox
- 0x004F0E25, // PDSnoan
- 0x00500325, // PDna
- 0x00510B26, // DSPnaon
- 0x005206C9, // DPSDaox
- 0x00530764, // SPDSxaxn
- 0x005408A9, // DPSonon
- 0x00550009, // Dn DSTINVERT
- 0x005601A9, // DPSox
- 0x00570389, // DPSoan
- 0x00580785, // PDSPoax
- 0x00590609, // DPSnox
- 0x005A0049, // DPx PATINVERT
- 0x005B18A9, // DPSDonox
- 0x005C0649, // DPSDxox
- 0x005D0E29, // DPSnoan
- 0x005E1B29, // DPSDnaox
- 0x005F00E9, // DPan
- 0x00600365, // PDSxa
- 0x006116C6, // DSPDSaoxxn
- 0x00620786, // DSPDoax
- 0x00630608, // SDPnox
- 0x00640788, // SDPSoax
- 0x00650606, // DSPnox
- 0x00660046, // DSx SRCINVERT
- 0x006718A8, // SDPSonox
- 0x006858A6, // DSPDSonoxxn
- 0x00690145, // PDSxxn
- 0x006A01E9, // DPSax
- 0x006B178A, // PSDPSoaxxn
- 0x006C01E8, // SDPax
- 0x006D1785, // PDSPDoaxxn
- 0x006E1E28, // SDPSnoax
- 0x006F0C65, // PDSxnan
- 0x00700CC5, // PDSana
- 0x00711D5C, // SSDxPDxaxn
- 0x00720648, // SDPSxox
- 0x00730E28, // SDPnoan
- 0x00740646, // DSPDxox
- 0x00750E26, // DSPnoan
- 0x00761B28, // SDPSnaox
- 0x007700E6, // DSan
- 0x007801E5, // PDSax
- 0x00791786, // DSPDSoaxxn
- 0x007A1E29, // DPSDnoax
- 0x007B0C68, // SDPxnan
- 0x007C1E24, // SPDSnoax
- 0x007D0C69, // DPSxnan
- 0x007E0955, // SPxDSxo
- 0x007F03C9, // DPSaan
- 0x008003E9, // DPSaa
- 0x00810975, // SPxDSxon
- 0x00820C49, // DPSxna
- 0x00831E04, // SPDSnoaxn
- 0x00840C48, // SDPxna
- 0x00851E05, // PDSPnoaxn
- 0x008617A6, // DSPDSoaxx
- 0x008701C5, // PDSaxn
- 0x008800C6, // DSa SRCAND
- 0x00891B08, // SDPSnaoxn
- 0x008A0E06, // DSPnoa
- 0x008B0666, // DSPDxoxn
- 0x008C0E08, // SDPnoa
- 0x008D0668, // SDPSxoxn
- 0x008E1D7C, // SSDxPDxax
- 0x008F0CE5, // PDSanan
- 0x00900C45, // PDSxna
- 0x00911E08, // SDPSnoaxn
- 0x009217A9, // DPSDPoaxx
- 0x009301C4, // SPDaxn
- 0x009417AA, // PSDPSoaxx
- 0x009501C9, // DPSaxn
- 0x00960169, // DPSxx
- 0x0097588A, // PSDPSonoxx
- 0x00981888, // SDPSonoxn
- 0x00990066, // DSxn
- 0x009A0709, // DPSnax
- 0x009B07A8, // SDPSoaxn
- 0x009C0704, // SPDnax
- 0x009D07A6, // DSPDoaxn
- 0x009E16E6, // DSPDSaoxx
- 0x009F0345, // PDSxan
- 0x00A000C9, // DPa
- 0x00A11B05, // PDSPnaoxn
- 0x00A20E09, // DPSnoa
- 0x00A30669, // DPSDxoxn
- 0x00A41885, // PDSPonoxn
- 0x00A50065, // PDxn
- 0x00A60706, // DSPnax
- 0x00A707A5, // PDSPoaxn
- 0x00A803A9, // DPSoa
- 0x00A90189, // DPSoxn
- 0x00AA0029, // D
- 0x00AB0889, // DPSono
- 0x00AC0744, // SPDSxax
- 0x00AD06E9, // DPSDaoxn
- 0x00AE0B06, // DSPnao
- 0x00AF0229, // DPno
- 0x00B00E05, // PDSnoa
- 0x00B10665, // PDSPxoxn
- 0x00B21974, // SSPxDSxox
- 0x00B30CE8, // SDPanan
- 0x00B4070A, // PSDnax
- 0x00B507A9, // DPSDoaxn
- 0x00B616E9, // DPSDPaoxx
- 0x00B70348, // SDPxan
- 0x00B8074A, // PSDPxax
- 0x00B906E6, // DSPDaoxn
- 0x00BA0B09, // DPSnao
- 0x00BB0226, // DSno MERGEPAINT
- 0x00BC1CE4, // SPDSanax
- 0x00BD0D7D, // SDxPDxan
- 0x00BE0269, // DPSxo
- 0x00BF08C9, // DPSano
- 0x00C000CA, // PSa MERGECOPY
- 0x00C11B04, // SPDSnaoxn
- 0x00C21884, // SPDSonoxn
- 0x00C3006A, // PSxn
- 0x00C40E04, // SPDnoa
- 0x00C50664, // SPDSxoxn
- 0x00C60708, // SDPnax
- 0x00C707AA, // PSDPoaxn
- 0x00C803A8, // SDPoa
- 0x00C90184, // SPDoxn
- 0x00CA0749, // DPSDxax
- 0x00CB06E4, // SPDSaoxn
- 0x00CC0020, // S SRCCOPY
- 0x00CD0888, // SDPono
- 0x00CE0B08, // SDPnao
- 0x00CF0224, // SPno
- 0x00D00E0A, // PSDnoa
- 0x00D1066A, // PSDPxoxn
- 0x00D20705, // PDSnax
- 0x00D307A4, // SPDSoaxn
- 0x00D41D78, // SSPxPDxax
- 0x00D50CE9, // DPSanan
- 0x00D616EA, // PSDPSaoxx
- 0x00D70349, // DPSxan
- 0x00D80745, // PDSPxax
- 0x00D906E8, // SDPSaoxn
- 0x00DA1CE9, // DPSDanax
- 0x00DB0D75, // SPxDSxan
- 0x00DC0B04, // SPDnao
- 0x00DD0228, // SDno
- 0x00DE0268, // SDPxo
- 0x00DF08C8, // SDPano
- 0x00E003A5, // PDSoa
- 0x00E10185, // PDSoxn
- 0x00E20746, // DSPDxax
- 0x00E306EA, // PSDPaoxn
- 0x00E40748, // SDPSxax
- 0x00E506E5, // PDSPaoxn
- 0x00E61CE8, // SDPSanax
- 0x00E70D79, // SPxPDxan
- 0x00E81D74, // SSPxDSxax
- 0x00E95CE6, // DSPDSanaxxn
- 0x00EA02E9, // DPSao
- 0x00EB0849, // DPSxno
- 0x00EC02E8, // SDPao
- 0x00ED0848, // SDPxno
- 0x00EE0086, // DSo SRCPAINT
- 0x00EF0A08, // SDPnoo
- 0x00F00021, // P PATCOPY
- 0x00F10885, // PDSono
- 0x00F20B05, // PDSnao
- 0x00F3022A, // PSno
- 0x00F40B0A, // PSDnao
- 0x00F50225, // PDno
- 0x00F60265, // PDSxo
- 0x00F708C5, // PDSano
- 0x00F802E5, // PDSao
- 0x00F90845, // PDSxno
- 0x00FA0089, // DPo
- 0x00FB0A09, // DPSnoo PATPAINT
- 0x00FC008A, // PSo
- 0x00FD0A0A, // PSDnoo
- 0x00FE02A9, // DPSoo
- 0x00FF0062 // 1 WHITENESS
-};
-
-static void set_path(GdiCanvas *canvas, SpicePath *s)
-{
- unsigned int i;
-
- for (i = 0; i < s->num_segments; i++) {
- SpicePathSeg* seg = s->segments[0];
- SpicePointFix* point = seg->points;
- SpicePointFix* end_point = point + seg->count;
-
- if (seg->flags & SPICE_PATH_BEGIN) {
- BeginPath(canvas->dc);
- if (!MoveToEx(canvas->dc, (int)fix_to_double(point->x), (int)fix_to_double(point->y),
- NULL)) {
- spice_critical("MoveToEx failed");
- return;
- }
- point++;
- }
-
- if (seg->flags & SPICE_PATH_BEZIER) {
- spice_return_if_fail((point - end_point) % 3 == 0);
- for (; point + 2 < end_point; point += 3) {
- POINT points[3];
-
- points[0].x = (int)fix_to_double(point[0].x);
- points[0].y = (int)fix_to_double(point[0].y);
- points[1].x = (int)fix_to_double(point[1].x);
- points[1].y = (int)fix_to_double(point[1].y);
- points[2].x = (int)fix_to_double(point[2].x);
- points[2].y = (int)fix_to_double(point[2].y);
- if (!PolyBezierTo(canvas->dc, points, 3)) {
- spice_critical("PolyBezierTo failed");
- return;
- }
- }
- } else {
- for (; point < end_point; point++) {
- if (!LineTo(canvas->dc, (int)fix_to_double(point->x),
- (int)fix_to_double(point->y))) {
- spice_critical("LineTo failed");
- }
- }
- }
-
- if (seg->flags & SPICE_PATH_END) {
-
- if (seg->flags & SPICE_PATH_CLOSE) {
- if (!CloseFigure(canvas->dc)) {
- spice_critical("CloseFigure failed");
- }
- }
-
- if (!EndPath(canvas->dc)) {
- spice_critical("EndPath failed");
- }
- }
-
- }
-}
-
-static void set_scale_mode(GdiCanvas *canvas, uint8_t scale_mode)
-{
- if (scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE) {
- SetStretchBltMode(canvas->dc, HALFTONE);
- } else if (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) {
- SetStretchBltMode(canvas->dc, COLORONCOLOR);
- } else {
- spice_critical("Unknown ScaleMode");
- }
-}
-
-static void set_clip(GdiCanvas *canvas, SpiceClip *clip)
-{
- switch (clip->type) {
- case SPICE_CLIP_TYPE_NONE:
- if (SelectClipRgn(canvas->dc, NULL) == ERROR) {
- spice_critical("SelectClipRgn failed");
- }
- break;
- case SPICE_CLIP_TYPE_RECTS: {
- uint32_t n = clip->rects->num_rects;
-
- SpiceRect *now = clip->rects->rects;
- SpiceRect *end = now + n;
-
- if (now < end) {
- HRGN main_hrgn;
-
- main_hrgn = CreateRectRgn(now->left, now->top, now->right, now->bottom);
- if (!main_hrgn) {
- return;
- }
- now++;
- for (; now < end; now++) {
- HRGN combaine_hrgn;
- combaine_hrgn = CreateRectRgn(now->left, now->top, now->right,
- now->bottom);
- if (!combaine_hrgn) {
- spice_critical("Unable to CreateRectRgn");
- DeleteObject(main_hrgn);
- return;
- }
- if (CombineRgn(main_hrgn, main_hrgn, combaine_hrgn, RGN_OR) == ERROR) {
- spice_critical("Unable to CombineRgn");
- DeleteObject(combaine_hrgn);
- return;
- }
- DeleteObject(combaine_hrgn);
- }
- if (SelectClipRgn(canvas->dc, main_hrgn) == ERROR) {
- spice_critical("Unable to SelectClipRgn");
- }
- DeleteObject(main_hrgn);
- }
- break;
- }
- default:
- spice_warn_if_reached();
- return;
- }
-}
-
-static void copy_bitmap(const uint8_t *src_image, int height, int src_stride,
- uint8_t *dest_bitmap, int dest_stride)
-{
- int copy_width = MIN(dest_stride, src_stride);
- int y = 0;
-
- spice_return_if_fail(dest_stride >= 0 && src_stride >= 0);
-
- while (y < height) {
- memcpy(dest_bitmap, src_image, copy_width);
- src_image += src_stride;
- dest_bitmap += dest_stride;
- y++;
- }
-}
-
-static void copy_bitmap_alpha(const uint8_t *src_alpha, int height, int width, int src_stride,
- uint8_t *dest_bitmap, int dest_stride, int alpha_bits_size)
-{
- int y = 0;
- uint8_t i_offset;
- int i_count = 0;
- int i = 0;
- int width_div_stride;
-
- width_div_stride = width / src_stride;
-
- if (alpha_bits_size == 1) {
- i_offset = 1;
- } else {
- i_offset = 8;
- }
-
-
- while (y < height) {
- int x;
-
- for (x = 0; x < width; ++x) {
- uint8_t alphaval;
- double alpha;
-
- alphaval = src_alpha[i];
- alphaval = alphaval >> (i_count * i_offset);
- alphaval &= ((uint8_t)0xff >> (8 - i_offset));
- alphaval = ((255 * alphaval) / ((uint8_t)0xff >> (8 - i_offset)));
-
- dest_bitmap[x * 4 + 3] = alphaval;
- alpha = (double)alphaval / 0xff;
- dest_bitmap[x * 4 + 2] = (uint8_t)(alpha * dest_bitmap[x * 4 + 2]);
- dest_bitmap[x * 4 + 1] = (uint8_t)(alpha * dest_bitmap[x * 4 + 1]);
- dest_bitmap[x * 4] = (uint8_t)(alpha * dest_bitmap[x * 4]);
-
- i_count++;
- if (i_count == (8 / i_offset)) {
- i++;
- i_count = 0;
- }
- }
-
- dest_bitmap += width * 4;
- i = 0;
- src_alpha += src_stride;
- i_count = 0;
- y++;
- }
-}
-
-static uint8_t *create_bitmap(HBITMAP *bitmap, HBITMAP *prev_bitmap, HDC *dc,
- const uint8_t *bitmap_data, int width, int height,
- int stride, int bits, int rotate)
-{
- uint8_t *data;
- const uint8_t *src_data;
- uint32_t nstride;
- struct {
- BITMAPINFO inf;
- RGBQUAD palette[255];
- } bitmap_info;
-
- memset(&bitmap_info, 0, sizeof(bitmap_info));
- bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
- bitmap_info.inf.bmiHeader.biWidth = width;
- if (stride < 0) {
- bitmap_info.inf.bmiHeader.biHeight = height;
- } else {
- bitmap_info.inf.bmiHeader.biHeight = -height;
- }
-
- if (rotate) {
- bitmap_info.inf.bmiHeader.biHeight = -bitmap_info.inf.bmiHeader.biHeight;
- }
-
- bitmap_info.inf.bmiHeader.biPlanes = 1;
- bitmap_info.inf.bmiHeader.biBitCount = bits;
- bitmap_info.inf.bmiHeader.biCompression = BI_RGB;
-
- *dc = create_compatible_dc();
- if (!*dc) {
- spice_critical("create_compatible_dc() failed");
- return NULL;
- }
-
- *bitmap = CreateDIBSection(*dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0);
- if (!*bitmap) {
- spice_critical("Unable to CreateDIBSection");
- DeleteDC(*dc);
- return NULL;
- }
- *prev_bitmap = (HBITMAP)SelectObject(*dc, *bitmap);
-
- if (stride < 0) {
- src_data = bitmap_data - (height - 1) * -stride;
- } else {
- src_data = bitmap_data;
- }
-
- switch (bits) {
- case 1:
- nstride = SPICE_ALIGN(width, 32) / 8;
- break;
- case 8:
- nstride = SPICE_ALIGN(width, 4);
- break;
- case 16:
- nstride = SPICE_ALIGN(width * 2, 4);
- break;
- case 32:
- nstride = width * 4;
- break;
- default:
- spice_warn_if_reached();
- return;
- }
-
- if (bitmap_data) {
- if (stride < 0) {
- copy_bitmap(src_data, height, -stride, data, nstride);
- } else {
- copy_bitmap(src_data, height, stride, data, nstride);
- }
- }
-
- return data;
-}
-
-static uint8_t *create_bitmap_from_pixman(HBITMAP *bitmap, HBITMAP *prev_bitmap, HDC *dc,
- pixman_image_t *surface, int rotate)
-{
- return create_bitmap(bitmap, prev_bitmap, dc,
- (uint8_t*)pixman_image_get_data(surface),
- pixman_image_get_width(surface),
- pixman_image_get_height(surface),
- pixman_image_get_stride(surface),
- spice_pixman_image_get_bpp(surface),
- rotate);
-}
-
-
-static void release_bitmap(HDC dc, HBITMAP bitmap, HBITMAP prev_bitmap, int cache)
-{
- bitmap = (HBITMAP)SelectObject(dc, prev_bitmap);
- if (!cache) {
- DeleteObject(bitmap);
- }
- DeleteDC(dc);
-}
-
-static inline uint8_t get_converted_color(uint8_t color)
-{
- uint8_t msb;
-
- msb = color & 0xE0;
- msb = msb >> 5;
- color |= msb;
- return color;
-}
-
-static inline COLORREF get_color_ref(GdiCanvas *canvas, uint32_t color)
-{
- int shift = canvas->base.color_shift == 8 ? 0 : 3;
- uint8_t r, g, b;
-
- b = (color & canvas->base.color_mask);
- color >>= canvas->base.color_shift;
- g = (color & canvas->base.color_mask);
- color >>= canvas->base.color_shift;
- r = (color & canvas->base.color_mask);
- if (shift) {
- r = get_converted_color(r << shift);
- g = get_converted_color(g << shift);
- b = get_converted_color(b << shift);
- }
- return RGB(r, g, b);
-}
-
-static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush, RecurciveMutex **brush_lock)
-{
- HBRUSH hbrush;
-
- *brush_lock = NULL;
-
- switch (brush->type) {
- case SPICE_BRUSH_TYPE_SOLID:
- if (!(hbrush = CreateSolidBrush(get_color_ref(canvas, brush->u.color)))) {
- spice_critical("CreateSolidBrush failed");
- return NULL;
- }
- return hbrush;
- case SPICE_BRUSH_TYPE_PATTERN: {
- GdiCanvas *gdi_surface = NULL;
- HBRUSH hbrush;
- pixman_image_t *surface = NULL;
- HDC dc;
- HBITMAP bitmap;
- HBITMAP prev_bitmap;
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat);
- if (gdi_surface) {
- bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP);
- if (!bitmap) {
- spice_critical("GetCurrentObject failed");
- return NULL;
- }
- *brush_lock = gdi_surface->lock;
- } else {
- surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE);
- if (!create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, surface, 0)) {
- spice_critical("create_bitmap failed");
- return NULL;
- }
- }
-
- if (!(hbrush = CreatePatternBrush(bitmap))) {
- spice_critical("CreatePatternBrush failed");
- return NULL;
- }
-
- if (!gdi_surface) {
- release_bitmap(dc, bitmap, prev_bitmap, 0);
- pixman_image_unref(surface);
- }
- return hbrush;
- }
- case SPICE_BRUSH_TYPE_NONE:
- return NULL;
- default:
- spice_warn_if_reached();
- return NULL;
- }
-}
-
-static HBRUSH set_brush(HDC dc, HBRUSH hbrush, SpiceBrush *brush)
-{
- switch (brush->type) {
- case SPICE_BRUSH_TYPE_SOLID: {
- return (HBRUSH)SelectObject(dc, hbrush);
- }
- case SPICE_BRUSH_TYPE_PATTERN: {
- HBRUSH prev_hbrush;
- prev_hbrush = (HBRUSH)SelectObject(dc, hbrush);
- if (!SetBrushOrgEx(dc, brush->u.pattern.pos.x, brush->u.pattern.pos.y, NULL)) {
- spice_critical("SetBrushOrgEx failed");
- return NULL;
- }
- return prev_hbrush;
- }
- default:
- spice_warn_if_reached();
- return NULL;
- }
-}
-
-static void unset_brush(HDC dc, HBRUSH prev_hbrush)
-{
- if (!prev_hbrush) {
- return;
- }
- prev_hbrush = (HBRUSH)SelectObject(dc, prev_hbrush);
- DeleteObject(prev_hbrush);
-}
-
-uint8_t calc_rop3(uint16_t rop3_bits, int brush)
-{
- uint8_t rop3 = 0;
- uint8_t rop3_src = _rop3_src;
- uint8_t rop3_dest = _rop3_dest;
- uint8_t rop3_brush = _rop3_brush;
- uint8_t rop3_src_brush;
-
- if (rop3_bits & SPICE_ROPD_INVERS_SRC) {
- rop3_src = ~rop3_src;
- }
- if (rop3_bits & SPICE_ROPD_INVERS_BRUSH) {
- rop3_brush = ~rop3_brush;
- }
- if (rop3_bits & SPICE_ROPD_INVERS_DEST) {
- rop3_dest = ~rop3_dest;
- }
-
- if (brush) {
- rop3_src_brush = rop3_brush;
- } else {
- rop3_src_brush = rop3_src;
- }
-
- if (rop3_bits & SPICE_ROPD_OP_PUT) {
- rop3 = rop3_src_brush;
- }
- if (rop3_bits & SPICE_ROPD_OP_OR) {
- rop3 = rop3_src_brush | rop3_dest;
- }
- if (rop3_bits & SPICE_ROPD_OP_AND) {
- rop3 = rop3_src_brush & rop3_dest;
- }
- if (rop3_bits & SPICE_ROPD_OP_XOR) {
- rop3 = rop3_src_brush ^ rop3_dest;
- }
- if (rop3_bits & SPICE_ROPD_INVERS_RES) {
- rop3 = ~rop3_dest;
- }
-
- if (rop3_bits & SPICE_ROPD_OP_BLACKNESS || rop3_bits & SPICE_ROPD_OP_WHITENESS ||
- rop3_bits & SPICE_ROPD_OP_INVERS) {
- spice_warn_if_reached("invalid rop3 type");
- return 0;
- }
- return rop3;
-}
-
-uint8_t calc_rop3_src_brush(uint16_t rop3_bits)
-{
- uint8_t rop3 = 0;
- uint8_t rop3_src = _rop3_src;
- uint8_t rop3_brush = _rop3_brush;
-
- if (rop3_bits & SPICE_ROPD_INVERS_SRC) {
- rop3_src = ~rop3_src;
- }
- if (rop3_bits & SPICE_ROPD_INVERS_BRUSH) {
- rop3_brush = ~rop3_brush;
- }
-
- if (rop3_bits & SPICE_ROPD_OP_OR) {
- rop3 = rop3_src | rop3_brush;
- }
- if (rop3_bits & SPICE_ROPD_OP_AND) {
- rop3 = rop3_src & rop3_brush;
- }
- if (rop3_bits & SPICE_ROPD_OP_XOR) {
- rop3 = rop3_src ^ rop3_brush;
- }
-
- return rop3;
-}
-
-static struct BitmapData get_mask_bitmap(struct GdiCanvas *canvas, struct SpiceQMask *mask)
-{
- GdiCanvas *gdi_surface;
- pixman_image_t *surface;
- struct BitmapData bitmap;
- PixmanData *pixman_data;
-
- bitmap.hbitmap = NULL;
- if (!mask->bitmap) {
- return bitmap;
- }
-
- gdi_surface = (GdiCanvas *)canvas_get_surface_mask(&canvas->base, mask->bitmap);
- if (gdi_surface) {
- HBITMAP _bitmap;
-
- _bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP);
- if (!_bitmap) {
- spice_critical("GetCurrentObject failed");
- return bitmap;
- }
- bitmap.dc = gdi_surface->dc;
- bitmap.hbitmap = _bitmap;
- bitmap.prev_hbitmap = (HBITMAP)0;
- bitmap.cache = 0;
- bitmap.from_surface = 1;
- } else {
-
- if (!(surface = canvas_get_mask(&canvas->base, mask, NULL))) {
- return bitmap;
- }
-
- pixman_data = (PixmanData *)pixman_image_get_destroy_data (surface);
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- bitmap.dc = create_compatible_dc();
- bitmap.prev_hbitmap = (HBITMAP)SelectObject(bitmap.dc, pixman_data->bitmap);
- bitmap.hbitmap = pixman_data->bitmap;
- ReleaseMutex(pixman_data->mutex);
- bitmap.cache = 1;
- } else if (!create_bitmap_from_pixman(&bitmap.hbitmap, &bitmap.prev_hbitmap, &bitmap.dc,
- surface, 0)) {
- bitmap.hbitmap = NULL;
- } else {
- bitmap.cache = 0;
- }
-
- bitmap.from_surface = 0;
- }
-
- bitmap.flags = mask->flags;
- bitmap.pos = mask->pos;
-
- return bitmap;
-}
-
-static void gdi_draw_bitmap(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
- HDC src_dc, struct BitmapData *bitmapmask, uint32_t rop3_val)
-{
- uint32_t rast_oper;
-
- rast_oper = raster_ops[rop3_val];
-
- if (!bitmapmask || !bitmapmask->hbitmap) {
- if ((dest->right - dest->left) == (src->right - src->left) &&
- (dest->bottom - dest->top) == (src->bottom - src->top)) {
- if (!BitBlt(dest_dc, dest->left, dest->top, dest->right - dest->left,
- dest->bottom - dest->top, src_dc, src->left, src->top, rast_oper)) {
- spice_critical("BitBlt failed");
- return;
- }
- } else {
- if (!StretchBlt(dest_dc, dest->left, dest->top, dest->right - dest->left,
- dest->bottom - dest->top, src_dc, src->left, src->top,
- src->right - src->left, src->bottom - src->top, rast_oper)) {
- spice_critical("StretchBlt failed");
- return;
- }
- }
- } else {
- rast_oper = MAKEROP4(rast_oper, raster_ops[_rop3_dest]);
-
- if (!MaskBlt(dest_dc, dest->left, dest->top, dest->right - dest->left,
- dest->bottom - dest->top, src_dc, src->left, src->top,
- bitmapmask->hbitmap, bitmapmask->pos.x, bitmapmask->pos.y,
- rast_oper)) {
- spice_critical("MaskBlt failed");
- return;
- }
- }
-}
-
-static void gdi_draw_bitmap_redrop(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
- HDC src_dc, struct BitmapData *bitmapmask,
- uint16_t rop, int brush)
-{
- uint32_t rop3_val;
-
- rop3_val = calc_rop3(rop, brush);
- gdi_draw_bitmap(dest_dc, src, dest, src_dc, bitmapmask, rop3_val);
-}
-
-static void free_mask(struct BitmapData *bitmap)
-{
- if (bitmap->hbitmap) {
- if (!bitmap->from_surface) {
- release_bitmap(bitmap->dc, bitmap->hbitmap, bitmap->prev_hbitmap, bitmap->cache);
- }
- }
-}
-
-static void draw_str_mask_bitmap(struct GdiCanvas *canvas,
- SpiceString *str, int n, SpiceRect *dest,
- SpiceRect *src, SpiceBrush *brush)
-{
- pixman_image_t *surface;
- struct BitmapData bitmap;
- SpicePoint pos;
- int dest_stride;
- uint8_t *bitmap_data;
- HBRUSH prev_hbrush;
- HBRUSH hbrush;
- RecurciveMutex *brush_lock;
-
- bitmap.hbitmap = (HBITMAP)1;
- if (!(surface = canvas_get_str_mask(&canvas->base, str, n, &pos))) {
- spice_critical("unable to canvas_get_str_mask");
- return;
- }
-
- bitmap.from_surface = 0;
- bitmap.cache = 0;
- bitmap_data = create_bitmap(&bitmap.hbitmap, &bitmap.prev_hbitmap,
- &bitmap.dc, NULL,
- pixman_image_get_width(surface),
- pixman_image_get_height(surface),
- pixman_image_get_stride(surface), 32, 0);
-
- if (!bitmap_data) {
- return;
- }
-
- bitmap.flags = 0;
- bitmap.pos.x = 0;
- bitmap.pos.y = 0;
-
- dest->left = pos.x;
- dest->top = pos.y;
- dest->right = pos.x + pixman_image_get_width(surface);
- dest->bottom = pos.y + pixman_image_get_height(surface);
- src->left = 0;
- src->top = 0;
- src->right = pixman_image_get_width(surface);
- src->bottom = pixman_image_get_height(surface);
-
- dest_stride = pixman_image_get_width(surface);
- switch (n) {
- case 1:
- dest_stride = dest_stride / 8;
- break;
- case 4:
- dest_stride = dest_stride / 2;
- break;
- case 32:
- dest_stride = dest_stride * 4;
- break;
- default:
- spice_warn_if_reached();
- return;
- }
- dest_stride = dest_stride + 3;
- dest_stride = dest_stride & ~3;
-
- hbrush = get_brush(canvas, brush, &brush_lock);
- prev_hbrush = set_brush(bitmap.dc, hbrush, brush);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush);
- } else {
- gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush);
- }
-
- unset_brush(bitmap.dc, prev_hbrush);
-
- copy_bitmap_alpha((uint8_t *)pixman_image_get_data(surface),
- pixman_image_get_height(surface),
- pixman_image_get_width(surface),
- pixman_image_get_stride(surface),
- bitmap_data, dest_stride, n);
-
- BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
-
- RecurciveLock lock(*canvas->lock);
- AlphaBlend(canvas->dc, dest->left, dest->top, dest->right - dest->left,
- dest->bottom - dest->top, bitmap.dc, src->left, src->top,
- src->right - src->left, src->bottom - src->top, bf);
-
- free_mask(&bitmap);
-}
-
-static void gdi_draw_image(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
- pixman_image_t *image, struct BitmapData *bitmapmask, uint16_t rop,
- int rotate)
-{
- HDC dc;
- HBITMAP bitmap;
- HBITMAP prev_bitmap;
-
- create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate);
-
- gdi_draw_bitmap_redrop(dest_dc, src, dest, dc, bitmapmask, rop, 0);
-
- release_bitmap(dc, bitmap, prev_bitmap, 0);
-}
-
-static void gdi_draw_image_rop3(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
- pixman_image_t *image, struct BitmapData *bitmapmask, uint8_t rop3,
- int rotate)
-{
- HDC dc;
- HBITMAP bitmap;
- HBITMAP prev_bitmap;
-
- create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate);
-
- gdi_draw_bitmap(dest_dc, src, dest, dc, bitmapmask, rop3);
-
- release_bitmap(dc, bitmap, prev_bitmap, 0);
-}
-
-static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- HBRUSH prev_hbrush;
- HBRUSH brush;
- struct BitmapData bitmapmask;
- RecurciveMutex *brush_lock;
-
- RecurciveLock lock(*canvas->lock);
-
- brush = get_brush(canvas, &fill->brush, &brush_lock);
- spice_return_if_fail(brush != NULL);
-
- bitmapmask = get_mask_bitmap(canvas, &fill->mask);
-
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, brush, &fill->brush);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask,
- fill->rop_descriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE);
- } else {
- gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask,
- fill->rop_descriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE);
- }
-
- free_mask(&bitmapmask);
- unset_brush(canvas->dc, prev_hbrush);
-}
-
-static void gdi_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- GdiCanvas *gdi_surface;
- pixman_image_t *surface;
- struct BitmapData bitmapmask;
- PixmanData *pixman_data;
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, copy->src_bitmap);
- if (gdi_surface) {
- RecurciveLock lock(*canvas->lock);
- RecurciveLock s_lock(*gdi_surface->lock);
- bitmapmask = get_mask_bitmap(canvas, ©->mask);
- set_scale_mode(canvas, copy->scale_mode);
- set_clip(canvas, clip);
- gdi_draw_bitmap_redrop(canvas->dc, ©->src_area, bbox, gdi_surface->dc,
- &bitmapmask, copy->rop_descriptor, 0);
- } else {
- surface = canvas_get_image(&canvas->base, copy->src_bitmap, FALSE);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- RecurciveLock lock(*canvas->lock);
- bitmapmask = get_mask_bitmap(canvas, ©->mask);
- set_scale_mode(canvas, copy->scale_mode);
- set_clip(canvas, clip);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_redrop(canvas->dc, ©->src_area, bbox, dc,
- &bitmapmask, copy->rop_descriptor, 0);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- gdi_draw_image(canvas->dc, ©->src_area, bbox, surface, &bitmapmask,
- copy->rop_descriptor, 0);
- }
-
- pixman_image_unref(surface);
-
- }
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_put_image(SpiceCanvas *spice_canvas, HDC dc, const SpiceRect *dest, const uint8_t *src_data,
- uint32_t src_width, uint32_t src_height, int src_stride,
- const QRegion *clip)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- SpiceRect src;
- src.top = 0;
- src.bottom = src_height;
- src.left = 0;
- src.right = src_width;
- int num_rects;
- pixman_box32_t *rects;
-
- RecurciveLock lock(*canvas->lock);
- set_scale_mode(canvas, SPICE_IMAGE_SCALE_MODE_NEAREST);
- if (clip) {
- rects = pixman_region32_rectangles((pixman_region32_t*)clip, &num_rects);
- if (num_rects == 0) {
- return;
- } else {
- HRGN main_hrgn;
- int i;
-
- main_hrgn = CreateRectRgn(rects[0].x1, rects[0].y1, rects[0].x2,
- rects[0].y2);
- if (!main_hrgn) {
- return;
- }
-
- for (i = 1; i < num_rects; i++) {
- HRGN combaine_hrgn;
-
- combaine_hrgn = CreateRectRgn(rects[i].x1, rects[i].y1,
- rects[i].x2,
- rects[i].y2);
- if (!combaine_hrgn) {
- spice_critical("CreateRectRgn failed");
- DeleteObject(main_hrgn);
- return;
- }
- if (!CombineRgn(main_hrgn, main_hrgn, combaine_hrgn, RGN_OR)) {
- spice_critical("CombineRgn failed in put_image");
- return;
- }
- DeleteObject(combaine_hrgn);
- }
- if (SelectClipRgn(canvas->dc, main_hrgn) == ERROR) {
- spice_critical("SelectClipRgn failed in put_image");
- DeleteObject(main_hrgn);
- return;
- }
- DeleteObject(main_hrgn);
- }
- } else {
- SelectClipRgn(canvas->dc, NULL);
- }
-
- if (dc) {
- gdi_draw_bitmap_redrop(canvas->dc, &src, dest, dc,
- NULL, SPICE_ROPD_OP_PUT, 0);
- } else {
- pixman_image_t *image = pixman_image_create_bits(PIXMAN_a8r8g8b8, src_width, src_height,
- (uint32_t *)src_data, src_stride);
- gdi_draw_image(canvas->dc, &src, dest, image, NULL, SPICE_ROPD_OP_PUT, 0);
- pixman_image_unref(image);
- }
-}
-
-static void gdi_draw_bitmap_transparent(GdiCanvas *canvas, HDC dest_dc, const SpiceRect *src,
- const SpiceRect *dest, HDC src_dc, uint32_t color)
-{
- TransparentBlt(dest_dc, dest->left, dest->top, dest->right - dest->left,
- dest->bottom - dest->top, src_dc, src->left, src->top,
- src->right - src->left, src->bottom - src->top,
- RGB(((uint8_t*)&color)[2], ((uint8_t*)&color)[1], ((uint8_t*)&color)[0]));
-}
-
-static void gdi_draw_image_transparent(GdiCanvas *canvas, HDC dest_dc, const SpiceRect *src,
- const SpiceRect *dest, pixman_image_t *image,
- uint32_t color, int rotate)
-{
- HDC dc;
- HBITMAP bitmap;
- HBITMAP prev_bitmap;
-
- create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate);
-
- gdi_draw_bitmap_transparent(canvas, dest_dc, src, dest, dc, color);
-
- release_bitmap(dc, bitmap, prev_bitmap, 0);
-}
-
-static void gdi_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip,
- SpiceTransparent* transparent)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- GdiCanvas *gdi_surface;
- pixman_image_t *surface;
- PixmanData *pixman_data;
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, transparent->src_bitmap);
- if (gdi_surface) {
- RecurciveLock lock(*canvas->lock);
- RecurciveLock s_lock(*gdi_surface->lock);
- set_clip(canvas, clip);
- gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox,
- gdi_surface->dc, transparent->true_color);
- } else {
- surface = canvas_get_image(&canvas->base, transparent->src_bitmap, FALSE);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
- RecurciveLock lock(*canvas->lock);
- set_clip(canvas, clip);
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, dc,
- transparent->true_color);
-
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- gdi_draw_image_transparent(canvas, canvas->dc, &transparent->src_area, bbox, surface,
- transparent->true_color, 0);
- }
-
- pixman_image_unref(surface);
- }
-}
-
-static void gdi_draw_bitmap_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
- HDC src_dc, uint8_t alpha, int use_bitmap_alpha)
-{
- BLENDFUNCTION bf;
-
- bf.BlendOp = AC_SRC_OVER;
- bf.BlendFlags = 0;
- bf.SourceConstantAlpha = alpha;
-
- if (use_bitmap_alpha) {
- bf.AlphaFormat = AC_SRC_ALPHA;
- } else {
- bf.AlphaFormat = 0;
- }
-
- if (!AlphaBlend(dest_dc, dest->left, dest->top, dest->right - dest->left,
- dest->bottom - dest->top, src_dc, src->left, src->top,
- src->right - src->left, src->bottom - src->top, bf)) {
- spice_critical("AlphaBlend failed");
- return;
- }
-}
-
-static void gdi_draw_image_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest,
- pixman_image_t *image, uint8_t alpha,
- int rotate, int use_bitmap_alpha)
-{
- HDC dc;
- HBITMAP bitmap;
- HBITMAP prev_bitmap;
-
- create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate);
-
- gdi_draw_bitmap_alpha(dest_dc, src, dest, dc, alpha, use_bitmap_alpha);
-
- release_bitmap(dc, bitmap, prev_bitmap, 0);
-}
-
-static void gdi_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- GdiCanvas *gdi_surface;
- pixman_image_t *surface;
- PixmanData *pixman_data;
- int use_bitmap_alpha;
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, alpha_blend->src_bitmap);
- if (gdi_surface) {
- RecurciveLock lock(*canvas->lock);
- RecurciveLock s_lock(*gdi_surface->lock);
- set_clip(canvas, clip);
- use_bitmap_alpha = alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA;
- gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, gdi_surface->dc,
- alpha_blend->alpha, use_bitmap_alpha);
- } else {
- surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap, TRUE);
- use_bitmap_alpha = pixman_image_get_depth(surface) == 32;
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- RecurciveLock lock(*canvas->lock);
- set_clip(canvas, clip);
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, dc, alpha_blend->alpha,
- use_bitmap_alpha);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- gdi_draw_image_alpha(canvas->dc, &alpha_blend->src_area, bbox, surface,
- alpha_blend->alpha, 0, use_bitmap_alpha);
- }
-
- pixman_image_unref(surface);
- }
-}
-
-static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque)
-{
- GdiCanvas *gdi_surface;
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- pixman_image_t *surface;
- struct BitmapData bitmapmask;
- PixmanData *pixman_data;
- HBRUSH prev_hbrush;
- HBRUSH hbrush;
- uint8_t rop3;
- RecurciveMutex *brush_lock;
-
- rop3 = calc_rop3_src_brush(opaque->rop_descriptor);
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, opaque->src_bitmap);
- if (gdi_surface) {
- RecurciveLock lock(*canvas->lock);
- RecurciveLock s_lock(*gdi_surface->lock);
- bitmapmask = get_mask_bitmap(canvas, &opaque->mask);
- hbrush = get_brush(canvas, &opaque->brush, &brush_lock);
- set_scale_mode(canvas, opaque->scale_mode);
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3);
- } else {
- gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3);
- }
- unset_brush(canvas->dc, prev_hbrush);
- } else {
- surface = canvas_get_image(&canvas->base, opaque->src_bitmap, FALSE);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- RecurciveLock lock(*canvas->lock);
- bitmapmask = get_mask_bitmap(canvas, &opaque->mask);
- hbrush = get_brush(canvas, &opaque->brush, &brush_lock);
- set_scale_mode(canvas, opaque->scale_mode);
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3);
- } else {
- gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3);
- }
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, surface, &bitmapmask, rop3, 0);
- } else {
- gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, surface, &bitmapmask, rop3, 0);
- }
- }
- unset_brush(canvas->dc, prev_hbrush);
- pixman_image_unref(surface);
- }
-
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend)
-{
- GdiCanvas *gdi_surface;
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- pixman_image_t *surface;
- struct BitmapData bitmapmask;
- PixmanData *pixman_data;
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, blend->src_bitmap);
- if (gdi_surface) {
- RecurciveLock lock(*canvas->lock);
- RecurciveLock s_lock(*gdi_surface->lock);
- bitmapmask = get_mask_bitmap(canvas, &blend->mask);
- set_scale_mode(canvas, blend->scale_mode);
- set_clip(canvas, clip);
- gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, gdi_surface->dc,
- &bitmapmask, blend->rop_descriptor, 0);
- } else {
- surface = canvas_get_image(&canvas->base, blend->src_bitmap, FALSE);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
-
- RecurciveLock lock(*canvas->lock);
- bitmapmask = get_mask_bitmap(canvas, &blend->mask);
- set_scale_mode(canvas, blend->scale_mode);
- set_clip(canvas, clip);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, dc,
- &bitmapmask, blend->rop_descriptor, 0);
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- gdi_draw_image(canvas->dc, &blend->src_area, bbox, surface,
- &bitmapmask, blend->rop_descriptor, 0);
- }
-
- pixman_image_unref(surface);
- }
-
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- struct BitmapData bitmapmask;
-
- RecurciveLock lock(*canvas->lock);
- bitmapmask = get_mask_bitmap(canvas, &blackness->mask);
- set_clip(canvas, clip);
- gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x0);
-
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- struct BitmapData bitmapmask;
-
- RecurciveLock lock(*canvas->lock);
- bitmapmask = get_mask_bitmap(canvas, &invers->mask);
- set_clip(canvas, clip);
- gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x55);
-
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- struct BitmapData bitmapmask;
-
- RecurciveLock lock(*canvas->lock);
- bitmapmask = get_mask_bitmap(canvas, &whiteness->mask);
- set_clip(canvas, clip);
- gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0xff);
-
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3)
-{
- GdiCanvas *gdi_surface;
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- pixman_image_t *surface;
- struct BitmapData bitmapmask;
- HBRUSH prev_hbrush;
- HBRUSH hbrush;
- PixmanData *pixman_data;
- RecurciveMutex *brush_lock;
-
- gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, rop3->src_bitmap);
- if (gdi_surface) {
- RecurciveLock lock(*canvas->lock);
- RecurciveLock s_lock(*gdi_surface->lock);
- hbrush = get_brush(canvas, &rop3->brush, &brush_lock);
- bitmapmask = get_mask_bitmap(canvas, &rop3->mask);
- set_scale_mode(canvas, rop3->scale_mode);
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc,
- &bitmapmask, rop3->rop3);
- } else {
- gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc,
- &bitmapmask, rop3->rop3);
- }
- unset_brush(canvas->dc, prev_hbrush);
- } else {
- surface = canvas_get_image(&canvas->base, rop3->src_bitmap, FALSE);
- pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface);
- RecurciveLock lock(*canvas->lock);
- hbrush = get_brush(canvas, &rop3->brush, &brush_lock);
- bitmapmask = get_mask_bitmap(canvas, &rop3->mask);
- set_scale_mode(canvas, rop3->scale_mode);
- set_clip(canvas, clip);
- prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush);
-
- if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) {
- HDC dc;
- HBITMAP prev_bitmap;
-
- dc = create_compatible_dc();
- prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc,
- &bitmapmask, rop3->rop3);
- } else {
- gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc,
- &bitmapmask, rop3->rop3);
- }
- SelectObject(dc, prev_bitmap);
- DeleteObject(dc);
- ReleaseMutex(pixman_data->mutex);
- } else {
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, surface, &bitmapmask, rop3->rop3, 0);
- } else {
- gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, surface, &bitmapmask, rop3->rop3, 0);
- }
- }
-
- unset_brush(canvas->dc, prev_hbrush);
- pixman_image_unref(surface);
- }
-
- free_mask(&bitmapmask);
-}
-
-static void gdi_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- RecurciveLock lock(*canvas->lock);
-
- set_clip(canvas, clip);
-
- BitBlt(canvas->dc, bbox->left, bbox->top, bbox->right - bbox->left,
- bbox->bottom - bbox->top, canvas->dc, src_pos->x, src_pos->y, SRCCOPY);
-}
-
-static void gdi_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- SpiceString *str;
- RecurciveMutex *brush_lock;
-
- RecurciveLock lock(*canvas->lock);
- set_clip(canvas, clip);
- lock.unlock();
-
- if (!rect_is_empty(&text->back_area)) {
- HBRUSH prev_hbrush;
- HBRUSH hbrush;
-
- RecurciveLock lock(*canvas->lock);
- hbrush = get_brush(canvas, &text->back_brush, &brush_lock);
- prev_hbrush = set_brush(canvas->dc, hbrush, &text->back_brush);
- if (brush_lock) {
- RecurciveLock b_lock(*brush_lock);
- gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL,
- text->back_mode, 1);
- } else {
- gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL,
- text->back_mode, 1);
- }
- unset_brush(canvas->dc, prev_hbrush);
- }
-
- str = (SpiceString *)SPICE_GET_ADDRESS(text->str);
-
- if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
- SpiceRect dest;
- SpiceRect src;
-
- draw_str_mask_bitmap(canvas, str, 1, &dest, &src, &text->fore_brush);
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
- SpiceRect dest;
- SpiceRect src;
-
- draw_str_mask_bitmap(canvas, str, 4, &dest, &src, &text->fore_brush);
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) {
- spice_warning("untested path A8 glyphs, doing nothing");
- if (0) {
- SpiceRect dest;
- SpiceRect src;
-
- draw_str_mask_bitmap(canvas, str, 8, &dest, &src, &text->fore_brush);
- }
- } else {
- spice_warning("untested path vector glyphs, doing nothing");
- if (0) {
- }
- }
-}
-
-static uint32_t *gdi_get_userstyle(GdiCanvas *canvas, uint8_t nseg, SPICE_FIXED28_4* style, int start_is_gap)
-{
- double offset = 0;
- uint32_t *local_style;
- int i;
-
- spice_return_val_if_fail(nseg != 0, NULL);
-
- local_style = spice_new(uint32_t , nseg);
-
- if (start_is_gap) {
- offset = (uint32_t)fix_to_double(*style);
- local_style[nseg - 1] = (uint32_t)fix_to_double(*style);
- style++;
-
- for (i = 0; i < nseg - 1; i++, style++) {
- local_style[i] = (uint32_t)fix_to_double(*style);
- }
- } else {
- for (i = 0; i < nseg; i++, style++) {
- local_style[i] = (uint32_t)fix_to_double(*style);
- }
- }
-
- return local_style;
-}
-
-static void gdi_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- HPEN hpen;
- HPEN prev_hpen;
- LOGBRUSH logbrush;
- uint32_t *user_style = NULL;
- pixman_image_t *surface = NULL;
-
- if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) {
- surface = canvas_get_image(&canvas->base, stroke->brush.u.pattern.pat, FALSE);
- }
-
- RecurciveLock lock(*canvas->lock);
- set_clip(canvas, clip);
-
- switch (stroke->fore_mode) {
- case SPICE_ROPD_OP_WHITENESS:
- SetROP2(canvas->dc, R2_WHITE); //0
- break;
- case SPICE_ROPD_OP_BLACKNESS:
- SetROP2(canvas->dc, R2_BLACK); //1
- break;
- case SPICE_ROPD_OP_INVERS:
- SetROP2(canvas->dc, R2_NOT); //Dn
- break;
- case SPICE_ROPD_OP_PUT:
- SetROP2(canvas->dc, R2_COPYPEN); //P
- break;
- case SPICE_ROPD_OP_OR:
- SetROP2(canvas->dc, R2_MERGEPEN); //DPo
- break;
- case SPICE_ROPD_OP_XOR:
- SetROP2(canvas->dc, R2_XORPEN); //DPx
- break;
- case SPICE_ROPD_OP_AND:
- SetROP2(canvas->dc, R2_MASKPEN); //DPa
- break;
- case SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_PUT: //Pn
- SetROP2(canvas->dc, R2_NOTCOPYPEN);
- break;
- case SPICE_ROPD_OP_XOR | SPICE_ROPD_INVERS_RES:
- SetROP2(canvas->dc, R2_NOTXORPEN); //DPxn
- break;
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_RES:
- SetROP2(canvas->dc, R2_NOTMERGEPEN); //DPon
- break;
- case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_RES:
- SetROP2(canvas->dc, R2_NOTMASKPEN); //DPan
- break;
- case SPICE_ROPD_INVERS_DEST | SPICE_ROPD_OP_AND:
- SetROP2(canvas->dc, R2_MASKPENNOT); //PDna
- break;
- case SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_AND:
- SetROP2(canvas->dc, R2_MASKNOTPEN); //DPna
- break;
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_BRUSH:
- SetROP2(canvas->dc, R2_MERGENOTPEN); //DPno
- break;
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_DEST:
- SetROP2(canvas->dc, R2_MERGEPENNOT); //PDno
- break;
- default:
- SetROP2(canvas->dc, R2_NOP); //D
- }
-
-
- if (stroke->brush.type == SPICE_BRUSH_TYPE_SOLID) {
- logbrush.lbStyle = BS_SOLID | DIB_RGB_COLORS;
- logbrush.lbHatch = 0;
- logbrush.lbColor = get_color_ref(canvas, stroke->brush.u.color);
- } else if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) {
-#if 0
- struct {
- BITMAPINFO inf;
- RGBQUAD palette[255];
- } bitmap_info;
- GdiImage image;
-#endif
-#if 0
- spice_return_if_fail(surface != NULL)
- surface_to_image(surface, &image);
-
- memset(&bitmap_info, 0, sizeof(bitmap_info));
- bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
- bitmap_info.inf.bmiHeader.biWidth = image.width;
- if (image.stride < 0) {
- bitmap_info.inf.bmiHeader.biHeight = image.height;
- } else {
- bitmap_info.inf.bmiHeader.biHeight = -image.height;
- }
- bitmap_info.inf.bmiHeader.biPlanes = 1;
- bitmap_info.inf.bmiHeader.biBitCount = 32;
- bitmap_info.inf.bmiHeader.biCompression = BI_RGB;
-
- if (image.stride < 0) {
- logbrush.lbHatch = (LONG)GlobalAlloc(GMEM_MOVEABLE,
- image.height * -image.stride + sizeof(BITMAPINFO));
- if (!logbrush.lbHatch) {
- spice_critical("GlobalAlloc failed");
- return;
- }
- copy_bitmap(image.pixels - (image.height - 1) * -image.stride,
- image.height, -image.stride,
- (uint8_t *)logbrush.lbHatch, image.width);
- } else {
- logbrush.lbHatch = (LONG)GlobalAlloc(GMEM_MOVEABLE,
- image.height * image.stride + sizeof(BITMAPINFO));
- if (!logbrush.lbHatch) {
- spice_critical("GlobalAlloc failed");
- return;
- }
- copy_bitmap(image.pixels, image.height, image.stride,
- (uint8_t *)logbrush.lbHatch, image.width);
- }
-
- memcpy((void *)logbrush.lbHatch, &bitmap_info.inf, sizeof(BITMAPINFO));
-
- logbrush.lbStyle = BS_DIBPATTERN | DIB_RGB_COLORS;
- logbrush.lbColor = 0;
-#endif
- pixman_image_unref(surface);
- }
-
- if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) {
- user_style = gdi_get_userstyle(canvas, stroke->attr.style_nseg,
- stroke->attr.style,
- !!(stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP));
- hpen = ExtCreatePen(PS_COSMETIC | PS_USERSTYLE,
- 1,
- &logbrush, stroke->attr.style_nseg, (DWORD *)user_style);
- } else {
- hpen = ExtCreatePen(PS_COSMETIC,
- 1,
- &logbrush, 0, NULL);
- }
- prev_hpen = (HPEN)SelectObject(canvas->dc, hpen);
-
- set_path(canvas, stroke->path);
-
- StrokePath(canvas->dc);
-
- SelectObject(canvas->dc, prev_hpen);
- DeleteObject(hpen);
-
-#if 0
- if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) {
- GlobalFree((HGLOBAL)logbrush.lbHatch);
- }
-#endif
-
- if (user_style) {
- free(user_style);
- }
-}
-
-static void gdi_canvas_clear(SpiceCanvas *spice_canvas)
-{
-}
-
-static void gdi_canvas_destroy(SpiceCanvas *spice_canvas)
-{
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- if (!canvas) {
- return;
- }
- canvas_base_destroy(&canvas->base);
- free(canvas);
-}
-
-static int need_init = 1;
-static SpiceCanvasOps gdi_canvas_ops;
-
-SpiceCanvas *gdi_canvas_create(int width, int height,
- HDC dc, RecurciveMutex* lock, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- GdiCanvas *canvas;
- int init_ok;
-
- if (need_init) {
- return NULL;
- }
- canvas = spice_new0(GdiCanvas, 1);
- init_ok = canvas_base_init(&canvas->base, &gdi_canvas_ops,
- width, height, format
-#ifdef SW_CANVAS_CACHE
- ,bits_cache
- ,palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder);
- canvas->dc = dc;
- canvas->lock = lock;
- return (SpiceCanvas *)canvas;
-}
-
-void gdi_canvas_init() //unsafe global function
-{
- if (!need_init) {
- return;
- }
- need_init = 0;
-
- canvas_base_init_ops(&gdi_canvas_ops);
- gdi_canvas_ops.draw_fill = gdi_canvas_draw_fill;
- gdi_canvas_ops.draw_copy = gdi_canvas_draw_copy;
- gdi_canvas_ops.draw_opaque = gdi_canvas_draw_opaque;
- gdi_canvas_ops.copy_bits = gdi_canvas_copy_bits;
- gdi_canvas_ops.draw_text = gdi_canvas_draw_text;
- gdi_canvas_ops.draw_stroke = gdi_canvas_draw_stroke;
- gdi_canvas_ops.draw_rop3 = gdi_canvas_draw_rop3;
- gdi_canvas_ops.draw_blend = gdi_canvas_draw_blend;
- gdi_canvas_ops.draw_blackness = gdi_canvas_draw_blackness;
- gdi_canvas_ops.draw_whiteness = gdi_canvas_draw_whiteness;
- gdi_canvas_ops.draw_invers = gdi_canvas_draw_invers;
- gdi_canvas_ops.draw_transparent = gdi_canvas_draw_transparent;
- gdi_canvas_ops.draw_alpha_blend = gdi_canvas_draw_alpha_blend;
- gdi_canvas_ops.put_image = gdi_canvas_put_image;
- gdi_canvas_ops.clear = gdi_canvas_clear;
- gdi_canvas_ops.destroy = gdi_canvas_destroy;
-
- rop3_init();
-}
-
diff --git a/common/gdi_canvas.h b/common/gdi_canvas.h
deleted file mode 100644
index b3d4b15..0000000
--- a/common/gdi_canvas.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H__GDI_CANVAS
-#define _H__GDI_CANVAS
-
-#include <stdint.h>
-
-#include "pixman_utils.h"
-#include "canvas_base.h"
-#include "region.h"
-
-SpiceCanvas *gdi_canvas_create(int width, int height,
- HDC dc, class RecurciveMutex *lock, uint32_t format,
- SpiceImageCache *bits_cache,
- SpicePaletteCache *palette_cache,
- SpiceImageSurfaces *surfaces,
- SpiceGlzDecoder *glz_decoder,
- SpiceJpegDecoder *jpeg_decoder,
- SpiceZlibDecoder *zlib_decoder);
-
-void gdi_canvas_init();
-
-#endif
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
deleted file mode 100644
index 9baf7e8..0000000
--- a/common/gl_canvas.c
+++ /dev/null
@@ -1,909 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "gl_canvas.h"
-#include "quic.h"
-#include "rop3.h"
-#include "region.h"
-
-#define GL_CANVAS
-#include "canvas_base.c"
-
-typedef struct GLCanvas GLCanvas;
-
-struct GLCanvas {
- CanvasBase base;
- GLCCtx glc;
- void *private_data;
- int private_data_size;
- int textures_lost;
-};
-
-static inline uint8_t *copy_opposite_image(GLCanvas *canvas, void *data, int stride, int height)
-{
- uint8_t *ret_data = (uint8_t *)data;
- uint8_t *dest;
- uint8_t *src;
- int i;
-
- if (!canvas->private_data) {
- canvas->private_data = spice_malloc_n(height, stride);
- if (!canvas->private_data) {
- return ret_data;
- }
- canvas->private_data_size = stride * height;
- }
-
- if (canvas->private_data_size < (stride * height)) {
- free(canvas->private_data);
- canvas->private_data = spice_malloc_n(height, stride);
- if (!canvas->private_data) {
- return ret_data;
- }
- canvas->private_data_size = stride * height;
- }
-
- dest = (uint8_t *)canvas->private_data;
- src = (uint8_t *)data + (height - 1) * stride;
-
- for (i = 0; i < height; ++i) {
- memcpy(dest, src, stride);
- dest += stride;
- src -= stride;
- }
- return (uint8_t *)canvas->private_data;
-}
-
-static pixman_image_t *canvas_surf_to_trans_surf(GLCImage *image,
- uint32_t trans_color)
-{
- int width = image->width;
- int height = image->height;
- uint8_t *src_line;
- uint8_t *end_src_line;
- int src_stride;
- uint8_t *dest_line;
- int dest_stride;
- pixman_image_t *ret;
- int i;
-
- ret = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, NULL, 0);
- if (ret == NULL) {
- spice_critical("create surface failed");
- return NULL;
- }
-
- src_line = image->pixels;
- src_stride = image->stride;
- end_src_line = src_line + src_stride * height;
-
- dest_line = (uint8_t *)pixman_image_get_data(ret);
- dest_stride = pixman_image_get_stride(ret);
-
- for (; src_line < end_src_line; src_line += src_stride, dest_line += dest_stride) {
- for (i = 0; i < width; i++) {
- if ((((uint32_t*)src_line)[i] & 0x00ffffff) == trans_color) {
- ((uint32_t*)dest_line)[i] = 0;
- } else {
- ((uint32_t*)dest_line)[i] = (((uint32_t*)src_line)[i]) | 0xff000000;
- }
- }
- }
-
- return ret;
-}
-
-static GLCPath get_path(GLCanvas *canvas, SpicePath *s)
-{
- GLCPath path = glc_path_create(canvas->glc);
- int i;
-
- for (i = 0; i < s->num_segments; i++) {
- SpicePathSeg* seg = s->segments[i];
- SpicePointFix* point = seg->points;
- SpicePointFix* end_point = point + seg->count;
-
- if (seg->flags & SPICE_PATH_BEGIN) {
- glc_path_move_to(path, fix_to_double(point->x), fix_to_double(point->y));
- point++;
- }
-
- if (seg->flags & SPICE_PATH_BEZIER) {
- spice_return_val_if_fail((point - end_point) % 3 == 0, path);
- for (; point + 2 < end_point; point += 3) {
- glc_path_curve_to(path,
- fix_to_double(point[0].x), fix_to_double(point[0].y),
- fix_to_double(point[1].x), fix_to_double(point[1].y),
- fix_to_double(point[2].x), fix_to_double(point[2].y));
- }
- } else {
- for (; point < end_point; point++) {
- glc_path_line_to(path, fix_to_double(point->x), fix_to_double(point->y));
- }
- }
- if (seg->flags & SPICE_PATH_END) {
- if (seg->flags & SPICE_PATH_CLOSE) {
- glc_path_close(path);
- }
- }
- }
-
- return path;
-}
-
-#define SET_GLC_RECT(dest, src) { \
- (dest)->x = (src)->left; \
- (dest)->y = (src)->top; \
- (dest)->width = (src)->right - (src)->left; \
- (dest)->height = (src)->bottom - (src)->top; \
-}
-
-#define SET_GLC_BOX(dest, src) { \
- (dest)->x = (src)->x1; \
- (dest)->y = (src)->y1; \
- (dest)->width = (src)->x2 - (src)->x1; \
- (dest)->height = (src)->y2 - (src)->y1; \
-}
-
-static void set_clip(GLCanvas *canvas, SpiceRect *bbox, SpiceClip *clip)
-{
- GLCRect rect;
- glc_clip_reset(canvas->glc);
-
- switch (clip->type) {
- case SPICE_CLIP_TYPE_NONE:
- break;
- case SPICE_CLIP_TYPE_RECTS: {
- uint32_t n = clip->rects->num_rects;
- SpiceRect *now = clip->rects->rects;
- SpiceRect *end = now + n;
-
- if (n == 0) {
- rect.x = rect.y = 0;
- rect.width = rect.height = 0;
- glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET);
- break;
- } else {
- SET_GLC_RECT(&rect, now);
- glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET);
- }
-
- for (now++; now < end; now++) {
- SET_GLC_RECT(&rect, now);
- glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_OR);
- }
- break;
- }
- default:
- spice_warn_if_reached();
- return;
- }
-}
-
-static void set_mask(GLCanvas *canvas, SpiceQMask *mask, int x, int y)
-{
- pixman_image_t *image;
-
- if (!(image = canvas_get_mask(&canvas->base, mask, NULL))) {
- glc_clear_mask(canvas->glc, GLC_MASK_A);
- return;
- }
-
-
- glc_set_mask(canvas->glc, x - mask->pos.x, y - mask->pos.y,
- pixman_image_get_width(image),
- pixman_image_get_height(image),
- pixman_image_get_stride(image),
- (uint8_t *)pixman_image_get_data(image), GLC_MASK_A);
-}
-
-static inline void surface_to_image(GLCanvas *canvas, pixman_image_t *surface, GLCImage *image,
- int ignore_stride)
-{
- int depth = pixman_image_get_depth(surface);
-
- spice_return_if_fail(depth == 32 || depth == 24);
- image->format = (depth == 24) ? GLC_IMAGE_RGB32 : GLC_IMAGE_ARGB32;
- image->width = pixman_image_get_width(surface);
- image->height = pixman_image_get_height(surface);
- image->stride = pixman_image_get_stride(surface);
- image->pixels = (uint8_t *)pixman_image_get_data(surface);
- image->pallet = NULL;
- if (ignore_stride) {
- return;
- }
- if (image->stride < 0) {
- image->stride = -image->stride;
- image->pixels = image->pixels - (image->height - 1) * image->stride;
- } else {
- image->pixels = copy_opposite_image(canvas, image->pixels, image->stride, image->height);
- }
-}
-
-static void set_brush(GLCanvas *canvas, SpiceBrush *brush)
-{
- switch (brush->type) {
- case SPICE_BRUSH_TYPE_SOLID: {
- uint32_t color = brush->u.color;
- double r, g, b;
-
- b = (double)(color & canvas->base.color_mask) / canvas->base.color_mask;
- color >>= canvas->base.color_shift;
- g = (double)(color & canvas->base.color_mask) / canvas->base.color_mask;
- color >>= canvas->base.color_shift;
- r = (double)(color & canvas->base.color_mask) / canvas->base.color_mask;
- glc_set_rgb(canvas->glc, r, g, b);
- break;
- }
- case SPICE_BRUSH_TYPE_PATTERN: {
- GLCImage image;
- GLCPattern pattern;
- pixman_image_t *surface;
-
- surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE);
- surface_to_image(canvas, surface, &image, 0);
-
- pattern = glc_pattern_create(canvas->glc, -brush->u.pattern.pos.x,
- -brush->u.pattern.pos.y, &image);
-
- glc_set_pattern(canvas->glc, pattern);
- glc_pattern_destroy(pattern);
- pixman_image_unref (surface);
- }
- case SPICE_BRUSH_TYPE_NONE:
- return;
- default:
- spice_warn_if_reached();
- return;
- }
-}
-
-static void set_op(GLCanvas *canvas, uint16_t rop_decriptor)
-{
- GLCOp op;
-
- switch (rop_decriptor) {
- case SPICE_ROPD_OP_PUT:
- op = GLC_OP_COPY;
- break;
- case SPICE_ROPD_OP_XOR:
- op = GLC_OP_XOR;
- break;
- case SPICE_ROPD_OP_BLACKNESS:
- op = GLC_OP_CLEAR;
- break;
- case SPICE_ROPD_OP_WHITENESS:
- op = GLC_OP_SET;
- break;
- case SPICE_ROPD_OP_PUT | SPICE_ROPD_INVERS_BRUSH:
- case SPICE_ROPD_OP_PUT | SPICE_ROPD_INVERS_SRC:
- op = GLC_OP_COPY_INVERTED;
- break;
- case SPICE_ROPD_OP_INVERS:
- op = GLC_OP_INVERT;
- break;
- case SPICE_ROPD_OP_AND:
- op = GLC_OP_AND;
- break;
- case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_RES:
- op = GLC_OP_NAND;
- break;
- case SPICE_ROPD_OP_OR:
- op = GLC_OP_OR;
- break;
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_RES:
- op = GLC_OP_NOR;
- break;
- case SPICE_ROPD_OP_XOR | SPICE_ROPD_INVERS_RES:
- op = GLC_OP_EQUIV;
- break;
- case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_DEST:
- op = GLC_OP_AND_REVERSE;
- break;
- case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_BRUSH:
- case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_SRC:
- op = GLC_OP_AND_INVERTED;
- break;
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_DEST:
- op = GLC_OP_OR_REVERSE;
- break;
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_BRUSH:
- case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_SRC:
- op = GLC_OP_OR_INVERTED;
- break;
- default:
- spice_warning("GLC_OP_NOOP");
- op = GLC_OP_NOOP;
- }
- glc_set_op(canvas->glc, op);
-}
-
-static void gl_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- GLCRect rect;
- set_clip(canvas, bbox, clip);
- set_mask(canvas, &fill->mask, bbox->left, bbox->top);
- set_brush(canvas, &fill->brush);
- set_op(canvas, fill->rop_descriptor);
- SET_GLC_RECT(&rect, bbox);
-
- glc_fill_rect(canvas->glc, &rect);
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- pixman_image_t *surface;
- GLCRecti src;
- GLCRecti dest;
- GLCImage image;
-
- set_clip(canvas, bbox, clip);
- set_mask(canvas, ©->mask, bbox->left, bbox->top);
- set_op(canvas, copy->rop_descriptor);
-
- //todo: optimize get_image (use ogl conversion + remove unnecessary copy of 32bpp)
- surface = canvas_get_image(&canvas->base, copy->src_bitmap, FALSE);
- surface_to_image(canvas, surface, &image, 0);
- SET_GLC_RECT(&dest, bbox);
- SET_GLC_RECT(&src, ©->src_area);
- glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1);
-
- pixman_image_unref(surface);
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- pixman_image_t *surface;
- GLCRecti src;
- GLCRecti dest;
- GLCRect fill_rect;
- GLCImage image;
-
- set_clip(canvas, bbox, clip);
- set_mask(canvas, &opaque->mask, bbox->left, bbox->top);
-
- glc_set_op(canvas->glc, (opaque->rop_descriptor & SPICE_ROPD_INVERS_SRC) ? GLC_OP_COPY_INVERTED :
- GLC_OP_COPY);
- surface = canvas_get_image(&canvas->base, opaque->src_bitmap, FALSE);
- surface_to_image(canvas, surface, &image, 0);
- SET_GLC_RECT(&dest, bbox);
- SET_GLC_RECT(&src, &opaque->src_area);
- glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1);
- pixman_image_unref(surface);
-
- set_brush(canvas, &opaque->brush);
- set_op(canvas, opaque->rop_descriptor & ~SPICE_ROPD_INVERS_SRC);
- SET_GLC_RECT(&fill_rect, bbox);
- glc_fill_rect(canvas->glc, &fill_rect);
-
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend *alpha_blend)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- pixman_image_t *surface;
- GLCRecti src;
- GLCRecti dest;
- GLCImage image;
-
- set_clip(canvas, bbox, clip);
- glc_clear_mask(canvas->glc, GLC_MASK_A);
- glc_set_op(canvas->glc, GLC_OP_COPY);
-
- surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap, FALSE);
- surface_to_image(canvas, surface, &image, 0);
- SET_GLC_RECT(&dest, bbox);
- SET_GLC_RECT(&src, &alpha_blend->src_area);
- glc_draw_image(canvas->glc, &dest, &src, &image, 0, (double)alpha_blend->alpha / 0xff);
-
- pixman_image_unref(surface);
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- pixman_image_t *surface;
- GLCRecti src;
- GLCRecti dest;
- GLCImage image;
-
- set_clip(canvas, bbox, clip);
- set_mask(canvas, &blend->mask, bbox->left, bbox->top);
- set_op(canvas, blend->rop_descriptor);
-
- surface = canvas_get_image(&canvas->base, blend->src_bitmap, FALSE);
- SET_GLC_RECT(&dest, bbox);
- SET_GLC_RECT(&src, &blend->src_area);
- surface_to_image(canvas, surface, &image, 0);
- glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1);
-
- pixman_image_unref(surface);
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent *transparent)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- pixman_image_t *surface;
- pixman_image_t *trans_surf;
- GLCImage image;
- GLCRecti src;
- GLCRecti dest;
-
- set_clip(canvas, bbox, clip);
- glc_clear_mask(canvas->glc, GLC_MASK_A);
- glc_set_op(canvas->glc, GLC_OP_COPY);
-
- surface = canvas_get_image(&canvas->base, transparent->src_bitmap, FALSE);
- surface_to_image(canvas, surface, &image, 0);
-
- trans_surf = canvas_surf_to_trans_surf(&image, transparent->true_color);
- pixman_image_unref(surface);
-
- surface_to_image(canvas, trans_surf, &image, 1);
- SET_GLC_RECT(&dest, bbox);
- SET_GLC_RECT(&src, &transparent->src_area);
- glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1);
-
- pixman_image_unref(trans_surf);
- glc_flush(canvas->glc);
-}
-
-static inline void fill_common(GLCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceQMask * mask, GLCOp op)
-{
- GLCRect rect;
-
- set_clip(canvas, bbox, clip);
- set_mask(canvas, mask, bbox->left, bbox->top);
- glc_set_op(canvas->glc, op);
- SET_GLC_RECT(&rect, bbox);
- glc_fill_rect(canvas->glc, &rect);
-}
-
-static void gl_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- fill_common(canvas, bbox, clip, &whiteness->mask, GLC_OP_SET);
-}
-
-static void gl_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- fill_common(canvas, bbox, clip, &blackness->mask, GLC_OP_CLEAR);
-}
-
-static void gl_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- fill_common(canvas, bbox, clip, &invers->mask, GLC_OP_INVERT);
-}
-
-static void gl_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- pixman_image_t *d;
- pixman_image_t *s;
- GLCImage image;
- SpicePoint src_pos;
- uint8_t *data_opp;
- int src_stride;
-
- set_clip(canvas, bbox, clip);
- set_mask(canvas, &rop3->mask, bbox->left, bbox->top);
-
- glc_set_op(canvas->glc, GLC_OP_COPY);
-
- image.format = GLC_IMAGE_RGB32;
- image.width = bbox->right - bbox->left;
- image.height = bbox->bottom - bbox->top;
-
- image.pallet = NULL;
-
- d = pixman_image_create_bits(PIXMAN_x8r8g8b8, image.width, image.height, NULL, 0);
- if (d == NULL) {
- spice_critical("create surface failed");
- return;
- }
- image.pixels = (uint8_t *)pixman_image_get_data(d);
- image.stride = pixman_image_get_stride(d);
-
- glc_read_pixels(canvas->glc, bbox->left, bbox->top, &image);
- data_opp = copy_opposite_image(canvas, image.pixels,
- image.stride,
- pixman_image_get_height(d));
- memcpy(image.pixels, data_opp,
- image.stride * pixman_image_get_height(d));
-
- s = canvas_get_image(&canvas->base, rop3->src_bitmap, FALSE);
- src_stride = pixman_image_get_stride(s);
- if (src_stride > 0) {
- data_opp = copy_opposite_image(canvas, (uint8_t *)pixman_image_get_data(s),
- src_stride, pixman_image_get_height(s));
- memcpy((uint8_t *)pixman_image_get_data(s), data_opp,
- src_stride * pixman_image_get_height(s));
- }
-
- if (!rect_is_same_size(bbox, &rop3->src_area)) {
- pixman_image_t *scaled_s = canvas_scale_surface(s, &rop3->src_area, image.width,
- image.height, rop3->scale_mode);
- pixman_image_unref(s);
- s = scaled_s;
- src_pos.x = 0;
- src_pos.y = 0;
- } else {
- src_pos.x = rop3->src_area.left;
- src_pos.y = rop3->src_area.top;
- }
-
- if (pixman_image_get_width(s) - src_pos.x < image.width ||
- pixman_image_get_height(s) - src_pos.y < image.height) {
- spice_critical("bad src bitmap size");
- return;
- }
-
- if (rop3->brush.type == SPICE_BRUSH_TYPE_PATTERN) {
- pixman_image_t *p = canvas_get_image(&canvas->base, rop3->brush.u.pattern.pat, FALSE);
- SpicePoint pat_pos;
-
- pat_pos.x = (bbox->left - rop3->brush.u.pattern.pos.x) % pixman_image_get_width(p);
-
- pat_pos.y = (bbox->top - rop3->brush.u.pattern.pos.y) % pixman_image_get_height(p);
-
- //for now (bottom-top)
- if (pat_pos.y < 0) {
- pat_pos.y = pixman_image_get_height(p) + pat_pos.y;
- }
- pat_pos.y = (image.height + pat_pos.y) % pixman_image_get_height(p);
- pat_pos.y = pixman_image_get_height(p) - pat_pos.y;
-
- do_rop3_with_pattern(rop3->rop3, d, s, &src_pos, p, &pat_pos);
- pixman_image_unref(p);
- } else {
- uint32_t color = (canvas->base.color_shift) == 8 ? rop3->brush.u.color :
- canvas_16bpp_to_32bpp(rop3->brush.u.color);
- do_rop3_with_color(rop3->rop3, d, s, &src_pos, color);
- }
-
- pixman_image_unref(s);
-
- GLCRecti dest;
- GLCRecti src;
- dest.x = bbox->left;
- dest.y = bbox->top;
-
- image.pixels = copy_opposite_image(canvas, image.pixels, pixman_image_get_stride(d),
- pixman_image_get_height(d));
-
- src.x = src.y = 0;
- dest.width = src.width = image.width;
- dest.height = src.height = image.height;
- glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1);
- pixman_image_unref(d);
-}
-
-static void gl_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- GLCPath path;
-
- set_clip(canvas, bbox, clip);
- glc_clear_mask(canvas->glc, GLC_MASK_A);
- set_op(canvas, stroke->fore_mode);
- set_brush(canvas, &stroke->brush);
-
- if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) {
- spice_warning("SPICE_LINE_FLAGS_STYLED");
- }
- glc_set_line_width(canvas->glc, 1.0);
-
- path = get_path(canvas, stroke->path);
- glc_stroke_path(canvas->glc, path);
- glc_path_destroy(path);
-}
-
-static void gl_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- GLCRect rect;
- SpiceString *str;
-
- set_clip(canvas, bbox, clip);
- glc_clear_mask(canvas->glc, GLC_MASK_A);
-
- if (!rect_is_empty(&text->back_area)) {
- set_brush(canvas, &text->back_brush);
- set_op(canvas, text->back_mode);
- SET_GLC_RECT(&rect, bbox);
- glc_fill_rect(canvas->glc, &rect);
- }
-
- str = (SpiceString *)SPICE_GET_ADDRESS(text->str);
- set_brush(canvas, &text->fore_brush);
- set_op(canvas, text->fore_mode);
- if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
- SpicePoint pos;
- pixman_image_t *mask = canvas_get_str_mask(&canvas->base, str, 1, &pos);
- _glc_fill_mask(canvas->glc, pos.x, pos.y,
- pixman_image_get_width(mask),
- pixman_image_get_height(mask),
- pixman_image_get_stride(mask),
- (uint8_t *)pixman_image_get_data(mask));
- pixman_image_unref(mask);
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
- SpicePoint pos;
- pixman_image_t *mask = canvas_get_str_mask(&canvas->base, str, 4, &pos);
- glc_fill_alpha(canvas->glc, pos.x, pos.y,
- pixman_image_get_width(mask),
- pixman_image_get_height(mask),
- pixman_image_get_stride(mask),
- (uint8_t *)pixman_image_get_data(mask));
-
- pixman_image_unref(mask);
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) {
- spice_warning("untested path A8 glyphs, doing nothing");
- if (0) {
- SpicePoint pos;
- pixman_image_t *mask = canvas_get_str_mask(&canvas->base, str, 8, &pos);
- glc_fill_alpha(canvas->glc, pos.x, pos.y,
- pixman_image_get_width(mask),
- pixman_image_get_height(mask),
- pixman_image_get_stride(mask),
- (uint8_t *)pixman_image_get_data(mask));
- pixman_image_unref(mask);
- }
- } else {
- spice_warning("untested path vector glyphs, doing nothing");
- if (0) {
- //draw_vector_str(canvas, str, &text->fore_brush, text->fore_mode);
- }
- }
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_clear(SpiceCanvas *spice_canvas)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- glc_clear(canvas->glc);
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- set_clip(canvas, bbox, clip);
- glc_clear_mask(canvas->glc, GLC_MASK_A);
- glc_set_op(canvas->glc, GLC_OP_COPY);
- glc_copy_pixels(canvas->glc, bbox->left, bbox->top, src_pos->x, src_pos->y,
- bbox->right - bbox->left, bbox->bottom - bbox->top);
-}
-
-static void gl_canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest, int dest_stride, const SpiceRect *area)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- GLCImage image;
-
- spice_return_if_fail(dest_stride > 0);
-
- image.format = GLC_IMAGE_RGB32;
- image.height = area->bottom - area->top;
- image.width = area->right - area->left;
- image.pixels = dest;
- image.stride = dest_stride;
- glc_read_pixels(canvas->glc, area->left, area->top, &image);
-}
-
-static void gl_canvas_group_start(SpiceCanvas *spice_canvas, QRegion *region)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- GLCRect *glc_rects;
- GLCRect *now, *end;
- int num_rect;
- pixman_box32_t *rects;
-
- canvas_base_group_start(spice_canvas, region);
-
- rects = pixman_region32_rectangles(region, &num_rect);
-
- glc_rects = spice_new(GLCRect, num_rect);
- now = glc_rects;
- end = glc_rects + num_rect;
-
- for (; now < end; now++, rects++) {
- SET_GLC_BOX(now, rects);
- }
- glc_mask_rects(canvas->glc, num_rect, glc_rects, GLC_MASK_B);
-
- free(glc_rects);
-}
-
-static void gl_canvas_put_image(SpiceCanvas *spice_canvas, const SpiceRect *dest, const uint8_t *src_data,
- uint32_t src_width, uint32_t src_height, int src_stride,
- const QRegion *clip)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- GLCRecti src;
- GLCRecti gldest;
- GLCImage image;
- uint32_t i;
-
- spice_return_if_fail(src_stride <= 0)
-
- glc_clip_reset(canvas->glc);
-
- if (clip) {
- int num_rects;
- pixman_box32_t *rects = pixman_region32_rectangles((pixman_region32_t *)clip,
- &num_rects);
- GLCRect rect;
- if (num_rects == 0) {
- rect.x = rect.y = rect.width = rect.height = 0;
- glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET);
- } else {
- SET_GLC_BOX(&rect, rects);
- glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET);
- for (i = 1; i < num_rects; i++) {
- SET_GLC_BOX(&rect, rects + i);
- glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_OR);
- }
- }
- }
-
- SET_GLC_RECT(&gldest, dest);
- src.x = src.y = 0;
- src.width = src_width;
- src.height = src_height;
-
- image.format = GLC_IMAGE_RGB32;
- image.width = src_width;
- image.height = src_height;
- src_stride = -src_stride;
- image.stride = src_stride;
- image.pixels = (uint8_t *)src_data - (src_height - 1) * src_stride;
- image.pallet = NULL;
- glc_draw_image(canvas->glc, &gldest, &src, &image, 0, 1);
-
- glc_flush(canvas->glc);
-}
-
-static void gl_canvas_group_end(SpiceCanvas *spice_canvas)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
-
- canvas_base_group_end(spice_canvas);
- glc_clear_mask(canvas->glc, GLC_MASK_B);
-}
-
-static int need_init = 1;
-static SpiceCanvasOps gl_canvas_ops;
-
-SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- GLCanvas *canvas;
- int init_ok;
-
- if (need_init) {
- return NULL;
- }
- canvas = spice_new0(GLCanvas, 1);
-
- if (!(canvas->glc = glc_create(width, height))) {
- goto error_1;
- }
- canvas->private_data = NULL;
- init_ok = canvas_base_init(&canvas->base, &gl_canvas_ops,
- width, height, format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
- if (!init_ok) {
- goto error_2;
- }
-
- return (SpiceCanvas *)canvas;
-
-error_2:
- glc_destroy(canvas->glc, 0);
-error_1:
- free(canvas);
-
- return NULL;
-}
-
-void gl_canvas_set_textures_lost(SpiceCanvas *spice_canvas,
- int textures_lost)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
-
- canvas->textures_lost = textures_lost;
-}
-
-static void gl_canvas_destroy(SpiceCanvas *spice_canvas)
-{
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
-
- if (!canvas) {
- return;
- }
- canvas_base_destroy(&canvas->base);
- glc_destroy(canvas->glc, canvas->textures_lost);
- if (canvas->private_data) {
- free(canvas->private_data);
- }
- free(canvas);
-}
-
-void gl_canvas_init() //unsafe global function
-{
- if (!need_init) {
- return;
- }
- need_init = 0;
-
- canvas_base_init_ops(&gl_canvas_ops);
- gl_canvas_ops.draw_fill = gl_canvas_draw_fill;
- gl_canvas_ops.draw_copy = gl_canvas_draw_copy;
- gl_canvas_ops.draw_opaque = gl_canvas_draw_opaque;
- gl_canvas_ops.copy_bits = gl_canvas_copy_bits;
- gl_canvas_ops.draw_text = gl_canvas_draw_text;
- gl_canvas_ops.draw_stroke = gl_canvas_draw_stroke;
- gl_canvas_ops.draw_rop3 = gl_canvas_draw_rop3;
- gl_canvas_ops.draw_blend = gl_canvas_draw_blend;
- gl_canvas_ops.draw_blackness = gl_canvas_draw_blackness;
- gl_canvas_ops.draw_whiteness = gl_canvas_draw_whiteness;
- gl_canvas_ops.draw_invers = gl_canvas_draw_invers;
- gl_canvas_ops.draw_transparent = gl_canvas_draw_transparent;
- gl_canvas_ops.draw_alpha_blend = gl_canvas_draw_alpha_blend;
- gl_canvas_ops.put_image = gl_canvas_put_image;
- gl_canvas_ops.clear = gl_canvas_clear;
- gl_canvas_ops.read_bits = gl_canvas_read_bits;
- gl_canvas_ops.group_start = gl_canvas_group_start;
- gl_canvas_ops.group_end = gl_canvas_group_end;
- gl_canvas_ops.destroy = gl_canvas_destroy;
-
- rop3_init();
-}
diff --git a/common/gl_canvas.h b/common/gl_canvas.h
deleted file mode 100644
index d7125e6..0000000
--- a/common/gl_canvas.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "glc.h"
-#include "canvas_base.h"
-#include "region.h"
-
-SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- );
-void gl_canvas_set_textures_lost(SpiceCanvas *canvas, int textures_lost);
-void gl_canvas_init();
-
diff --git a/common/gl_utils.h b/common/gl_utils.h
deleted file mode 100644
index eecff26..0000000
--- a/common/gl_utils.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
-
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#ifndef GL_UTILS_H
-#define GL_UTILS_H
-
-#ifdef RED_DEBUG
-#define GLC_ERROR_TEST_FLUSH { \
- GLenum gl_err; glFlush(); \
- if ((gl_err = glGetError()) != GL_NO_ERROR) { \
- printf("%s[%d]: opengl error: %s\n", __FUNCTION__, __LINE__, \
- gluErrorString(gl_err)); \
- abort(); \
- } \
-}
-
-#define GLC_ERROR_TEST_FINISH { \
- GLenum gl_err; glFinish(); \
- if ((gl_err = glGetError()) != GL_NO_ERROR) { \
- printf("%s[%d]: opengl error: %s\n", __FUNCTION__, __LINE__, \
- gluErrorString(gl_err)); \
- abort(); \
- } \
-}
-#else
-#define GLC_ERROR_TEST_FLUSH ;
-
-#define GLC_ERROR_TEST_FINISH ;
-#endif
-
-#ifdef WIN32
-static inline int find_msb(uint32_t val)
-{
- uint32_t r;
- __asm {
- bsr eax, val
- jnz found
- mov eax, -1
-
-found:
- mov r, eax
- }
- return r + 1;
-}
-
-#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-static inline int find_msb(unsigned int val)
-{
- int ret;
-
- asm ("bsrl %1,%0\n\t"
- "jnz 1f\n\t"
- "movl $-1,%0\n"
- "1:"
- : "=r"(ret) : "r"(val));
- return ret + 1;
-}
-
-#else
-static inline int find_msb(unsigned int val)
-{
- signed char index = 31;
-
- if(val == 0) {
- return 0;
- }
-
- do {
- if(val & 0x80000000) {
- break;
- }
- val <<= 1;
- } while(--index >= 0);
-
- return index+1;
-}
-
-#endif
-
-static inline int gl_get_to_power_two(unsigned int val)
-{
- if ((val & (val - 1)) == 0) {
- return val;
- }
- return 1 << find_msb(val);
-}
-
-#endif
diff --git a/common/glc.c b/common/glc.c
deleted file mode 100644
index e4263cd..0000000
--- a/common/glc.c
+++ /dev/null
@@ -1,1521 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
-
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <spice/macros.h>
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include <GL/glext.h>
-
-#ifdef WIN32
-#include "glext.h"
-#include "wglext.h"
-#endif
-
-#include "mem.h"
-#include "glc.h"
-#include "gl_utils.h"
-
-#define ASSERT(x) if (!(x)) {printf("%s: assert failed %s\n", __FUNCTION__, #x); abort();}
-
-#define WARN_ONCE(x) { \
- static int warn = TRUE; \
- if (warn) { \
- printf x; \
- warn = FALSE; \
- } \
-}
-
-#define TESS_VERTEX_ALLOC_BUNCH 20
-
-typedef struct InternaCtx InternaCtx;
-typedef struct InternalPat {
- InternaCtx *owner;
- int refs;
- GLuint texture;
- int x_orign;
- int y_orign;
- int width;
- int height;
-} InternalPat;
-
-typedef struct Pathpath {
- int start_point;
- int num_segments;
-} Path;
-
-enum {
- GLC_PATH_SEG_LINES,
- GLC_PATH_SEG_BEIZER,
-};
-
-//todo: flatten cache
-typedef struct PathSegment {
- int type;
- int count;
-} PathSegment;
-
-typedef struct PathPoint {
- double x;
- double y;
- double z;
-} PathPoint;
-
-typedef GLdouble Vertex[3];
-
-typedef struct InternalPath {
- InternaCtx *owner;
-
- Path *paths;
- int paths_size;
- int paths_pos;
-
- PathSegment *segments;
- int segments_size;
- int segments_pos;
-
- PathPoint *points;
- int points_size;
- int points_pos;
-
- Path *current_path;
- PathSegment *current_segment;
-} InternalPath;
-
-typedef struct TassVertex TassVertex;
-struct TassVertex {
- PathPoint point;
- TassVertex *list_link;
- TassVertex *next;
-};
-
-typedef struct TassVertexBuf TassVertexBuf;
-struct TassVertexBuf {
- TassVertexBuf *next;
- TassVertex vertexs[0];
-};
-
-#define USE_LINE_ANTIALIAS 0
-
-typedef struct LineDash {
- double *dashes;
- int num_dashes;
- double offset;
- int cur_dash;
- double dash_pos;
-} LineDash;
-
-enum {
- GLC_STROKE_NONACTIVE,
- GLC_STROKE_FIRST,
- GLC_STROKE_ACTIVE,
-};
-
-typedef struct PathStroke {
- double x;
- double y;
- int state;
-} PathStroke;
-
-struct InternaCtx {
- int draw_mode;
- int stencil_refs;
- int stencil_mask;
- int width;
- int height;
- GLfloat line_width;
- LineDash line_dash;
- PathStroke path_stroke;
- InternalPat *pat;
- int max_texture_size;
- GLUtesselator* tesselator;
- TassVertex *free_tess_vertex;
- TassVertex *used_tess_vertex;
- TassVertexBuf *vertex_bufs;
- int private_tex_width;
- int private_tex_height;
- GLuint private_tex;
-#ifdef WIN32
- PFNGLBLENDEQUATIONPROC glBlendEquation;
-#endif
-};
-
-#define Y(y) -(y)
-#define VERTEX2(x, y) glVertex2d(x, Y(y))
-
-static void fill_rect(InternaCtx *ctx, void *rect);
-static void fill_path(InternaCtx *ctx, void *path);
-static void fill_mask(InternaCtx *ctx, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *bitmap);
-static void set_pat(InternaCtx *ctx, InternalPat *pat);
-
-static inline void set_raster_pos(InternaCtx *ctx, int x, int y)
-{
- if (x >= 0 && y >= 0 && x < ctx->width && y < ctx->height) {
- glRasterPos2i(x, Y(y));
- return;
- }
- glRasterPos2i(0, 0);
- glBitmap(0, 0, 0, 0, (GLfloat)x, (GLfloat)Y(y), NULL);
-}
-
-static TassVertex *alloc_tess_vertex(InternaCtx *ctx)
-{
- TassVertex *vertex;
-
- if (!ctx->free_tess_vertex) {
- TassVertexBuf *buf;
- int i;
-
- buf = (TassVertexBuf *)spice_malloc(sizeof(TassVertexBuf) +
- sizeof(TassVertex) * TESS_VERTEX_ALLOC_BUNCH);
- buf->next = ctx->vertex_bufs;
- ctx->vertex_bufs = buf;
- for (i = 0; i < TESS_VERTEX_ALLOC_BUNCH; i++) {
- buf->vertexs[i].point.z = 0;
- buf->vertexs[i].next = ctx->free_tess_vertex;
- ctx->free_tess_vertex = &buf->vertexs[i];
- }
- }
-
- vertex = ctx->free_tess_vertex;
- ctx->free_tess_vertex = vertex->next;
- vertex->next = ctx->used_tess_vertex;
- ctx->used_tess_vertex = vertex;
- return vertex;
-}
-
-static void reset_tass_vertex(InternaCtx *ctx)
-{
- TassVertex *vertex;
- while ((vertex = ctx->used_tess_vertex)) {
- ctx->used_tess_vertex = vertex->next;
- vertex->next = ctx->free_tess_vertex;
- ctx->free_tess_vertex = vertex;
- }
-}
-
-static void free_tass_vertex_bufs(InternaCtx *ctx)
-{
- TassVertexBuf *buf;
-
- ctx->used_tess_vertex = NULL;
- ctx->free_tess_vertex = NULL;
- while ((buf = ctx->vertex_bufs)) {
- ctx->vertex_bufs = buf->next;
- free(buf);
- }
-}
-
-//naive bezier flattener
-static TassVertex *bezier_flattener(InternaCtx *ctx, PathPoint *points)
-{
- double ax, bx, cx;
- double ay, by, cy;
- const int num_points = 30;
- double dt;
- int i;
-
- TassVertex *vertex_list = NULL;
- TassVertex *curr_vertex;
-
- for (i = 0; i < num_points - 2; i++) {
- TassVertex *vertex;
-
- vertex = alloc_tess_vertex(ctx);
- vertex->list_link = vertex_list;
- vertex_list = vertex;
- }
-
- curr_vertex = vertex_list;
-
- cx = 3.0 * (points[1].x - points[0].x);
- bx = 3.0 * (points[2].x - points[1].x) - cx;
- ax = points[3].x - points[0].x - cx - bx;
-
- cy = 3.0 * (points[1].y - points[0].y);
- by = 3.0 * (points[2].y - points[1].y) - cy;
- ay = points[3].y - points[0].y - cy - by;
-
- dt = 1.0 / (num_points - 1);
-
- for (i = 1; i < num_points - 1; i++, curr_vertex = curr_vertex->list_link) {
- double tSquared, tCubed;
- double t;
- t = i * dt;
-
- tSquared = t * t;
- tCubed = tSquared * t;
-
- curr_vertex->point.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + points[0].x;
- curr_vertex->point.y = (ay * tCubed) + (by * tSquared) + (cy * t) + points[0].y;
- }
-
- return vertex_list;
-}
-
-#define MORE_X(path, Type, name) { \
- Type *name; \
- \
- name = spice_new0(Type, path->name##_size * 2); \
- memcpy(name, path->name, sizeof(*name) * path->name##_size); \
- free(path->name); \
- path->name = name; \
- path->name##_size *= 2; \
-}
-
-static void more_points(InternalPath *path)
-{
- MORE_X(path, PathPoint, points);
-}
-
-static void more_segments(InternalPath *path)
-{
- MORE_X(path, PathSegment, segments);
-}
-
-static void more_paths(InternalPath *path)
-{
- MORE_X(path, Path, paths);
-}
-
-static inline void put_point(InternalPath *path, double x, double y)
-{
- path->points[path->points_pos].x = x;
- path->points[path->points_pos].y = Y(y + 0.5);
- path->points[path->points_pos++].z = 0;
-}
-
-void glc_path_move_to(GLCPath path, double x, double y)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
-
- if (internal->current_segment) {
- internal->current_segment = NULL;
- internal->current_path = NULL;
- if (internal->points_pos == internal->points_size) {
- more_points(internal);
- }
- internal->points_pos++;
- }
- internal->points[internal->points_pos - 1].x = x;
- internal->points[internal->points_pos - 1].y = Y(y + 0.5);
- internal->points[internal->points_pos - 1].z = 0;
-}
-
-static void add_segment_common(InternalPath *internal, int type, int num_points)
-{
- if (internal->points_size - internal->points_pos < num_points) {
- more_points(internal);
- }
-
- if (internal->current_segment) {
- if (internal->current_segment->type == type) {
- internal->current_segment->count++;
- return;
- }
- if (internal->segments_pos == internal->segments_size) {
- more_segments(internal);
- }
- internal->current_segment = &internal->segments[internal->segments_pos++];
- internal->current_segment->type = type;
- internal->current_segment->count = 1;
- internal->current_path->num_segments++;
- return;
- }
-
- if (internal->paths_pos == internal->paths_size) {
- more_paths(internal);
- }
-
- if (internal->segments_pos == internal->segments_size) {
- more_segments(internal);
- }
-
- internal->current_path = &internal->paths[internal->paths_pos++];
- internal->current_path->start_point = internal->points_pos - 1;
- internal->current_path->num_segments = 1;
- internal->current_segment = &internal->segments[internal->segments_pos++];
- internal->current_segment->type = type;
- internal->current_segment->count = 1;
-}
-
-void glc_path_line_to(GLCPath path, double x, double y)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
-
- add_segment_common(internal, GLC_PATH_SEG_LINES, 1);
- put_point(internal, x, y);
-}
-
-void glc_path_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y,
- double p3_x, double p3_y)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
-
- add_segment_common(internal, GLC_PATH_SEG_BEIZER, 3);
- put_point(internal, p1_x, p1_y);
- put_point(internal, p2_x, p2_y);
- put_point(internal, p3_x, p3_y);
-}
-
-void glc_path_close(GLCPath path)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
- if (!internal->current_path) {
- return;
- }
- PathPoint *end_point = &internal->points[internal->current_path->start_point];
- glc_path_line_to(path, end_point->x, Y(end_point->y));
- glc_path_move_to(path, end_point->x, Y(end_point->y));
-}
-
-void glc_path_cleare(GLCPath path)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
- internal->paths_pos = internal->segments_pos = 0;
- internal->current_segment = NULL;
- internal->current_path = NULL;
-
- internal->points[0].x = 0;
- internal->points[0].y = 0;
- internal->points_pos = 1;
-}
-
-GLCPath glc_path_create(GLCCtx glc)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPath *path;
-
- ASSERT(ctx);
- path = spice_new0(InternalPath, 1);
- path->paths_size = 2;
- path->paths = spice_new(Path, path->paths_size);
-
- path->segments_size = 4;
- path->segments = spice_new(PathSegment, path->segments_size);
-
- path->points_size = 20;
- path->points = spice_new(PathPoint, path->points_size);
-
- path->owner = ctx;
- path->points_pos = 1;
- return path;
-}
-
-void glc_path_destroy(GLCPath path)
-{
- InternalPath *internal = (InternalPath *)path;
-
- if (!path) {
- return;
- }
-
- free(internal->points);
- free(internal->segments);
- free(internal->paths);
- free(internal);
-}
-
-static inline void unref_pat(InternalPat *pat)
-{
- if (!pat) {
- return;
- }
- ASSERT(pat->refs > 0);
- if (--pat->refs == 0) {
- glFinish();
- glDeleteTextures(1, &pat->texture);
- free(pat);
- }
- GLC_ERROR_TEST_FLUSH;
-}
-
-static inline InternalPat *ref_pat(InternalPat *pat)
-{
- pat->refs++;
- return pat;
-}
-
-static void scale(uint32_t *dest, uint32_t dest_width, uint32_t dest_height,
- uint32_t *src, uint32_t src_width, uint32_t src_height, int src_stride)
-{
- double x_scale = (double)src_width / dest_width;
- double y_scale = (double)src_height / dest_height;
- uint32_t i;
- uint32_t j;
- int prev_row = -1;
-
- for (i = 0; i < dest_height; i++) {
- int row = (int)(y_scale * i);
- if (row == prev_row) {
- memcpy(dest, dest - dest_width, dest_width * sizeof(uint32_t));
- dest += dest_width;
- continue;
- }
- for (j = 0; j < dest_width; j++) {
- int col = (int)(x_scale * j);
- *(dest++) = *(src + col);
- }
- prev_row = row;
- src = (uint32_t *)((uint8_t *)src + src_stride);
- }
-}
-
-static inline void init_pattern(InternalPat *pat, int x_orign, int y_orign, const GLCImage *image)
-{
- InternaCtx *ctx = pat->owner;
- uint32_t *tmp_pixmap = NULL;
- int width;
- int height;
- int width2;
- int height2;
-
- const int pix_bytes = 4;
-
- ASSERT(image->format == GLC_IMAGE_RGB32); //for now
-
- width = image->width;
- height = image->height;
- width2 = gl_get_to_power_two(width);
- height2 = gl_get_to_power_two(height);
-
- ASSERT(width > 0 && height > 0);
- ASSERT(width > 0 && width <= pat->owner->max_texture_size);
- ASSERT(height > 0 && height <= pat->owner->max_texture_size);
-
- if (width2 != width || height2 != height) {
- tmp_pixmap = (uint32_t *)spice_malloc(width2 * height2 * sizeof(uint32_t));
- scale(tmp_pixmap, width2, height2, (uint32_t *)image->pixels, width, height, image->stride);
- }
-
- glBindTexture(GL_TEXTURE_2D, pat->texture);
-
- //glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- if (tmp_pixmap) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, width2);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, width2, height2, 0, GL_BGRA, GL_UNSIGNED_BYTE,
- tmp_pixmap);
- free(tmp_pixmap);
- } else {
- ASSERT(image->stride % pix_bytes == 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, image->stride / pix_bytes);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
- image->pixels);
- }
-
- GLC_ERROR_TEST_FLUSH;
- pat->x_orign = x_orign % width;
- pat->y_orign = y_orign % height;
- pat->width = width;
- pat->height = height;
-
- if (ctx->pat == pat) {
- set_pat(pat->owner, pat);
- } else if (ctx->pat) {
- glBindTexture(GL_TEXTURE_2D, ctx->pat->texture);
- }
-}
-
-GLCPattern glc_pattern_create(GLCCtx glc, int x_orign, int y_orign, const GLCImage *image)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPat *pat;
-
- ASSERT(ctx && image);
-
- pat = spice_new0(InternalPat, 1);
- pat->refs = 1;
- pat->owner = ctx;
- glGenTextures(1, &pat->texture);
- init_pattern(pat, x_orign, y_orign, image);
- return pat;
-}
-
-void glc_pattern_set(GLCPattern pattern, int x_orign, int y_orign, const GLCImage *image)
-{
- InternalPat *pat = (InternalPat *)pattern;
- ASSERT(pat && pat->owner);
-
- glFinish();
- init_pattern(pat, x_orign, y_orign, image);
-}
-
-void glc_pattern_destroy(GLCPattern pat)
-{
- unref_pat((InternalPat *)pat);
- GLC_ERROR_TEST_FLUSH;
-}
-
-static void set_pat(InternaCtx *ctx, InternalPat *pat)
-{
- pat = ref_pat(pat);
- unref_pat(ctx->pat);
- ctx->pat = pat;
-
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, pat->texture);
-
- GLfloat s_gen_params[] = { (GLfloat)1.0 / pat->width, 0, 0, 0 };
- GLfloat t_gen_params[] = { 0, (GLfloat)1.0 / (GLfloat)pat->height, 0, 0 };
- glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen_params);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen_params);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glTranslatef((float)pat->x_orign / pat->width, (float)Y(pat->y_orign) / pat->height, 0);
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_set_pattern(GLCCtx glc, GLCPattern pattern)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPat *pat = (InternalPat *)pattern;
-
- ASSERT(ctx && pat && pat->owner == ctx);
- set_pat(ctx, pat);
-}
-
-void glc_set_rgb(GLCCtx glc, double red, double green, double blue)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
-
- glDisable(GL_TEXTURE_2D);
- unref_pat(ctx->pat);
- ctx->pat = NULL;
- glColor4d(red, green, blue, 1);
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_set_op(GLCCtx glc, GLCOp op)
-{
- if (op == GL_COPY) {
- glDisable(GL_COLOR_LOGIC_OP);
- return;
- }
- glLogicOp(op);
- glEnable(GL_COLOR_LOGIC_OP);
-}
-
-void glc_set_line_width(GLCCtx glc, double width)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- ctx->line_width = (GLfloat)width;
- if (ctx->line_width > 0) {
- glLineWidth(ctx->line_width);
- } else {
- ctx->line_width = 0;
- }
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_set_line_dash(GLCCtx glc, const double *dashes, int num_dashes, double offset)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- if (dashes && num_dashes >= 0 && offset >= 0) {
- ctx->line_dash.dashes = spice_new(double, num_dashes);
- memcpy(ctx->line_dash.dashes, dashes, sizeof(double) * num_dashes);
- ctx->line_dash.num_dashes = num_dashes;
- ctx->line_dash.offset = offset;
- ctx->line_dash.cur_dash = offset ? -1 : 0;
- ctx->line_dash.dash_pos = 0;
- } else {
- free(ctx->line_dash.dashes);
- memset(&ctx->line_dash, 0, sizeof(ctx->line_dash));
- }
-}
-
-void glc_set_fill_mode(GLCCtx glc, GLCFillMode fill_mode)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- int mode;
- switch (fill_mode) {
- case GLC_FILL_MODE_WINDING_ODD:
- mode = GLU_TESS_WINDING_ODD;
- break;
- case GLC_FILL_MODE_WINDING_NONZERO:
- mode = GLU_TESS_WINDING_NONZERO;
- break;
- default:
- //warn
- return;
- }
- gluTessProperty(ctx->tesselator, GLU_TESS_WINDING_RULE, mode);
-}
-
-static inline void add_stencil_client(InternaCtx *ctx)
-{
- if (!ctx->stencil_refs) {
- glEnable(GL_STENCIL_TEST);
- }
- ctx->stencil_refs++;
-}
-
-static inline void remove_stencil_client(InternaCtx *ctx)
-{
- ctx->stencil_refs--;
- if (!ctx->stencil_refs) {
- glDisable(GL_STENCIL_TEST);
- }
-}
-
-void glc_set_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap, GLCMaskID id)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08;
- ASSERT(ctx && bitmap);
- ASSERT(id == GLC_MASK_A || id == GLC_MASK_B);
-
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
-
- glDisable(GL_BLEND);
-
- if (!(ctx->stencil_mask & mask)) {
- add_stencil_client(ctx);
- ctx->stencil_mask |= mask;
- }
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- ctx->draw_mode = FALSE;
- glStencilMask(mask);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, mask, mask);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- fill_mask(ctx, x_dest, y_dest, width, height, stride, bitmap);
-}
-
-void glc_mask_rects(GLCCtx glc, int num_rect, GLCRect *rects, GLCMaskID id)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08;
- GLCRect *end;
- ASSERT(ctx && rects);
- ASSERT(id == GLC_MASK_A || id == GLC_MASK_B);
-
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
-
- glDisable(GL_BLEND);
-
- if (!(ctx->stencil_mask & mask)) {
- add_stencil_client(ctx);
- ctx->stencil_mask |= mask;
- }
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- ctx->draw_mode = FALSE;
- glStencilMask(mask);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, mask, mask);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- end = rects + num_rect;
- for (; rects < end; rects++) {
- fill_rect(ctx, rects);
- }
-}
-
-void glc_clear_mask(GLCCtx glc, GLCMaskID id)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08;
- ASSERT(ctx);
- ASSERT(id == GLC_MASK_A || id == GLC_MASK_B);
-
- if ((ctx->stencil_mask & mask)) {
- ctx->stencil_mask &= ~mask;
- remove_stencil_client(ctx);
- }
-}
-
-void glc_clip_reset(GLCCtx glc)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- if (!(ctx->stencil_mask & 0x03)) {
- return;
- }
- remove_stencil_client(ctx);
- ctx->stencil_mask &= ~0x03;
- glStencilMask(0x03);
- glClear(GL_STENCIL_BUFFER_BIT);
- GLC_ERROR_TEST_FLUSH;
-}
-
-static void clip_common(InternaCtx *ctx, GLCClipOp op, void (*fill_func)(InternaCtx *, void *),
- void *data)
-{
- int stencil_val;
-
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
- glDisable(GL_BLEND);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- ctx->draw_mode = FALSE;
-
- if (op == GLC_CLIP_OP_SET) {
- glc_clip_reset(ctx);
- add_stencil_client(ctx);
- ctx->stencil_mask |= 0x01;
- } else if (!(ctx->stencil_mask & 0x03)) {
- GLCRect area;
- if (op == GLC_CLIP_OP_OR) {
- return;
- }
- area.x = area.y = 0;
- area.width = ctx->width;
- area.height = ctx->height;
- clip_common(ctx, GLC_CLIP_OP_SET, fill_rect, &area);
- }
- glStencilMask(0x03);
- switch (op) {
- case GLC_CLIP_OP_SET:
- case GLC_CLIP_OP_OR:
- stencil_val = ctx->stencil_mask & 0x03;
- glStencilFunc(GL_ALWAYS, stencil_val, stencil_val);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- fill_func(ctx, data);
- break;
- case GLC_CLIP_OP_AND: {
- int clear_mask;
- stencil_val = ctx->stencil_mask & 0x03;
- glStencilFunc(GL_EQUAL, stencil_val, stencil_val);
- if (stencil_val == 0x01) {
- glStencilOp(GL_ZERO, GL_INCR, GL_INCR);
- stencil_val = 0x02;
- clear_mask = 0x01;
- } else {
- glStencilOp(GL_ZERO, GL_DECR, GL_DECR);
- stencil_val = 0x01;
- clear_mask = 0x02;
- }
- fill_func(ctx, data);
-
- glStencilMask(clear_mask);
- glClear(GL_STENCIL_BUFFER_BIT);
- ctx->stencil_mask = (ctx->stencil_mask & ~clear_mask) | stencil_val;
- break;
- }
- case GLC_CLIP_OP_EXCLUDE:
- stencil_val = ctx->stencil_mask & 0x03;
- glStencilFunc(GL_EQUAL, stencil_val, stencil_val);
- glStencilOp(GL_KEEP, GL_ZERO, GL_ZERO);
- fill_func(ctx, data);
- break;
- }
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_clip_rect(GLCCtx glc, const GLCRect *rect, GLCClipOp op)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && rect);
- clip_common(ctx, op, fill_rect, (void *)rect);
-}
-
-void glc_clip_path(GLCCtx glc, GLCPath path, GLCClipOp op)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && path);
- clip_common(ctx, op, fill_path, path);
-}
-
-typedef struct FillMaskInfo {
- int x_dest;
- int y_dest;
- int width;
- int height;
- int stride;
- const uint8_t *bitmap;
-} FillMaskInfo;
-
-static void __fill_mask(InternaCtx *ctx, void *data)
-{
- FillMaskInfo *info = (FillMaskInfo *)data;
- fill_mask(ctx, info->x_dest, info->y_dest, info->width, info->height, info->stride,
- info->bitmap);
-}
-
-void glc_clip_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap, GLCClipOp op)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- FillMaskInfo mask_info;
-
- ASSERT(ctx && bitmap);
- mask_info.x_dest = x_dest;
- mask_info.y_dest = y_dest;
- mask_info.width = width;
- mask_info.height = height;
- mask_info.stride = stride;
- mask_info.bitmap = bitmap;
- clip_common(ctx, op, __fill_mask, &mask_info);
-}
-
-static inline void start_draw(InternaCtx *ctx)
-{
- if (ctx->draw_mode) {
- return;
- }
- ctx->draw_mode = TRUE;
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilFunc(GL_EQUAL, ctx->stencil_mask, ctx->stencil_mask);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- if (ctx->pat) {
- glEnable(GL_TEXTURE_2D);
- } else {
- glDisable(GL_TEXTURE_2D);
- }
- GLC_ERROR_TEST_FLUSH;
-}
-
-static void fill_rect(InternaCtx *ctx, void *r)
-{
- GLCRect *rect = (GLCRect *)r;
- glRectd(rect->x, Y(rect->y), rect->x + rect->width, Y(rect->y + rect->height));
- /*glBegin(GL_POLYGON);
- VERTEX2(rect->x, rect->y);
- VERTEX2 (rect->x + rect->width, rect->y);
- VERTEX2 (rect->x + rect->width, rect->y + rect->height);
- VERTEX2 (rect->x , rect->y + rect->height);
- glEnd();*/
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_fill_rect(GLCCtx glc, const GLCRect *rect)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- GLCRect *r = (GLCRect *)rect; // to avoid bugs in gcc older than 4.3
-
- ASSERT(ctx);
- start_draw(ctx);
- fill_rect(ctx, (void *)r);
- GLC_ERROR_TEST_FLUSH;
-}
-
-static void fill_path(InternaCtx *ctx, void *p)
-{
- InternalPath *path = (InternalPath *)p;
-
- PathPoint *current_point = path->points;
- PathSegment *current_segment = path->segments;
- Path *current_path = path->paths;
- Path *end_path = current_path + path->paths_pos;
- reset_tass_vertex(ctx);
- gluTessBeginPolygon(ctx->tesselator, ctx);
- for (; current_path < end_path; current_path++) {
- gluTessBeginContour(ctx->tesselator);
- PathSegment *end_segment = current_segment + current_path->num_segments;
- gluTessVertex(ctx->tesselator, (GLdouble *)current_point, current_point);
- current_point++;
- for (; current_segment < end_segment; current_segment++) {
- PathPoint *end_point;
- if (current_segment->type == GLC_PATH_SEG_BEIZER) {
- end_point = current_point + current_segment->count * 3;
- for (; current_point < end_point; current_point += 3) {
- TassVertex *vertex = bezier_flattener(ctx, current_point - 1);
- while (vertex) {
- gluTessVertex(ctx->tesselator, (GLdouble *)&vertex->point,
- (GLdouble *)&vertex->point);
- vertex = vertex->list_link;
- }
- gluTessVertex(ctx->tesselator, (GLdouble *)¤t_point[2],
- (GLdouble *)¤t_point[2]);
- }
- } else {
- ASSERT(current_segment->type == GLC_PATH_SEG_LINES);
- end_point = current_point + current_segment->count;
- for (; current_point < end_point; current_point++) {
- gluTessVertex(ctx->tesselator, (GLdouble *)current_point,
- (GLdouble *)current_point);
- }
- }
- }
- gluTessEndContour(ctx->tesselator);
- }
- gluTessEndPolygon(ctx->tesselator);
-}
-
-void glc_fill_path(GLCCtx glc, GLCPath path_ref)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && path_ref);
- start_draw(ctx);
- fill_path(ctx, path_ref);
-}
-
-static void fill_mask(InternaCtx *ctx, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap)
-{
- set_raster_pos(ctx, x_dest, y_dest + height);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8);
- glBitmap(width, height, 0, 0, 0, 0, bitmap);
-}
-
-void _glc_fill_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *bitmap)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && bitmap);
- start_draw(ctx);
- if (ctx->pat) {
- WARN_ONCE(("%s: unimplemented fill mask with pattern\n", __FUNCTION__));
- }
- fill_mask(ctx, x_dest, y_dest, width, height, stride, bitmap);
-}
-
-void glc_fill_alpha(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *alpha_mask)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- GLCRect r;
-
- ASSERT(ctx);
- start_draw(ctx);
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
- set_raster_pos(ctx, x_dest, y_dest + height);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
- glPixelZoom(1, 1);
- glDrawPixels(width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_mask);
-
- r.x = x_dest;
- r.y = y_dest;
- r.width = width;
- r.height = height;
-
- //todo: support color/texture alpah vals (GL_MODULATE)
- glEnable(GL_BLEND);
- glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- fill_rect(ctx, &r);
- glDisable(GL_BLEND);
-}
-
-void glc_stroke_rect(GLCCtx glc, const GLCRect *rect)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- if (ctx->line_width == 0) {
- return;
- }
-
- start_draw(ctx);
-
- glBegin(GL_LINES);
- VERTEX2(rect->x, rect->y + 0.5);
- VERTEX2(rect->x + rect->width, rect->y + 0.5);
- VERTEX2(rect->x + rect->width - 0.5, rect->y);
- VERTEX2(rect->x + rect->width - 0.5, rect->y + rect->height);
- VERTEX2(rect->x + rect->width, rect->y + rect->height - 0.5);
- VERTEX2(rect->x, rect->y + rect->height - 0.5);
- VERTEX2(rect->x + 0.5, rect->y + rect->height);
- VERTEX2(rect->x + 0.5, rect->y);
- glEnd();
- GLC_ERROR_TEST_FLUSH;
-}
-
-static void glc_stroke_line(double x1, double y1, double x2, double y2, double width)
-{
- double ax, ay, bx, by, cx, cy, dx, dy;
- double norm, tx;
-
- if (width == 1 || y1 == y2 || x1 == x2) {
- glBegin(GL_LINES);
- glVertex2d(x1, y1);
- glVertex2d(x2, y2);
- glEnd();
- return;
- }
- norm = (x1 - x2) / (y2 - y1);
- tx = width / (2 * sqrt(1 + norm * norm));
- ax = x1 + tx;
- ay = y1 + norm * (ax - x1);
- bx = x2 + tx;
- by = y2 + norm * (bx - x2);
- cx = x2 - tx;
- cy = y2 + norm * (cx - x2);
- dx = x1 - tx;
- dy = y1 + norm * (dx - x1);
- glBegin(GL_POLYGON);
- glVertex2d(ax, ay);
- glVertex2d(bx, by);
- glVertex2d(cx, cy);
- glVertex2d(dx, dy);
- glEnd();
-}
-
-static double glc_stroke_line_dash(double x1, double y1, double x2, double y2,
- double width, LineDash *dash)
-{
- double ax, ay, bx, by;
- double mx, my, len;
- double dash_len, total = 0;
-
- len = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
- if (!dash->dashes || !dash->num_dashes) {
- glc_stroke_line(x1, y1, x2, y2, width);
- return len;
- }
- mx = (x2 - x1) / len;
- my = (y2 - y1) / len;
- ax = x1;
- ay = y1;
- while (total < len) {
- if (dash->cur_dash >= 0) {
- dash_len = dash->dashes[dash->cur_dash % dash->num_dashes] - dash->dash_pos;
- } else {
- dash_len = dash->offset - dash->dash_pos;
- }
- total += dash_len;
- if (total < len) {
- bx = x1 + mx * total;
- by = y1 + my * total;
- dash->dash_pos = 0;
- } else {
- bx = x2;
- by = y2;
- dash->dash_pos = dash->dashes[dash->cur_dash % dash->num_dashes] - (total - len);
- }
- if (dash->cur_dash % 2 == 0) {
- glc_stroke_line(ax, ay, bx, by, width);
- }
- if (dash->dash_pos == 0) {
- dash->cur_dash = (dash->cur_dash + 1) % (2 * dash->num_dashes);
- }
- ax = bx;
- ay = by;
- }
- return len;
-}
-
-static void glc_vertex2d(InternaCtx *ctx, double x, double y)
-{
- double len;
- if (ctx->path_stroke.state == GLC_STROKE_ACTIVE) {
- len = glc_stroke_line_dash(ctx->path_stroke.x, ctx->path_stroke.y, x, y,
- ctx->line_width, &ctx->line_dash);
- ctx->path_stroke.x = x;
- ctx->path_stroke.y = y;
- } else if (ctx->path_stroke.state == GLC_STROKE_FIRST) {
- ctx->path_stroke.x = x;
- ctx->path_stroke.y = y;
- ctx->path_stroke.state = GLC_STROKE_ACTIVE;
- } else {
- ASSERT(ctx->path_stroke.state == GLC_STROKE_NONACTIVE);
- //error
- }
-}
-
-static void glc_begin_path(InternaCtx *ctx)
-{
- ctx->path_stroke.state = GLC_STROKE_FIRST;
- ctx->line_dash.cur_dash = ctx->line_dash.offset ? -1 : 0;
- ctx->line_dash.dash_pos = 0;
-}
-
-static void glc_end_path(InternaCtx *ctx)
-{
- ctx->path_stroke.state = GLC_STROKE_NONACTIVE;
-}
-
-void glc_stroke_path(GLCCtx glc, GLCPath path_ref)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPath *path = (InternalPath *)path_ref;
-
- ASSERT(ctx && path);
- if (ctx->line_width == 0) {
- return;
- }
- start_draw(ctx);
-
- reset_tass_vertex(ctx);
- PathPoint *current_point = path->points;
- PathSegment *current_segment = path->segments;
- Path *current_path = path->paths;
- Path *end_path = current_path + path->paths_pos;
- for (; current_path < end_path; current_path++) {
- glc_begin_path(ctx);
- PathSegment *end_segment = current_segment + current_path->num_segments;
- glc_vertex2d(ctx, current_point->x, current_point->y);
- current_point++;
- for (; current_segment < end_segment; current_segment++) {
- PathPoint *end_point;
- if (current_segment->type == GLC_PATH_SEG_BEIZER) {
- end_point = current_point + current_segment->count * 3;
- for (; current_point < end_point; current_point += 3) {
- TassVertex *vertex = bezier_flattener(ctx, current_point - 1);
- while (vertex) {
- glc_vertex2d(ctx, vertex->point.x, vertex->point.y);
- vertex = vertex->list_link;
- }
- glc_vertex2d(ctx, current_point[2].x, current_point[2].y);
- }
- } else {
- ASSERT(current_segment->type == GLC_PATH_SEG_LINES);
- end_point = current_point + current_segment->count;
- for (; current_point < end_point; current_point++) {
- glc_vertex2d(ctx, current_point->x, current_point->y);
- }
- }
- }
- glc_end_path(ctx);
- }
-}
-
-void glc_draw_image(GLCCtx glc, const GLCRecti *dest, const GLCRecti *src, const GLCImage *image,
- int scale_mode, double alpha)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint8_t *pixels;
- const int pix_bytes = 4;
-
- ASSERT(ctx && image);
- ASSERT(src->width > 0 && src->height > 0);
-
- ASSERT(image->format == GLC_IMAGE_RGB32 || image->format == GLC_IMAGE_ARGB32); //for now
- start_draw(ctx);
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
- set_raster_pos(ctx, dest->x, dest->y + dest->height);
-
- if (dest->width == src->width && src->height == dest->height) {
- glPixelZoom(1, 1);
- } else {
- glPixelZoom((float)dest->width / src->width, (float)dest->height / src->height);
- }
-
- pixels = image->pixels + src->x * 4 + (image->height - (src->y + src->height)) * image->stride;
- if (image->format == GLC_IMAGE_ARGB32 || alpha != 1) {
- glPixelTransferf(GL_ALPHA_SCALE, (GLfloat)alpha);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- }
- ASSERT(image->stride % pix_bytes == 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, image->stride / pix_bytes);
- glDrawPixels(src->width, src->height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
-
- if (image->format == GLC_IMAGE_ARGB32 || alpha != 1) {
- glDisable(GL_BLEND);
- }
-
- if (ctx->pat) {
- glEnable(GL_TEXTURE_2D);
- }
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_copy_pixels(GLCCtx glc, int x_dest, int y_dest, int x_src, int y_src, int width,
- int height)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- int recreate = 0;
-
- ASSERT(ctx);
-#ifdef USE_COPY_PIXELS
- start_draw(ctx);
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
- set_raster_pos(ctx, x_dest, y_dest + height);
- glPixelZoom(1, 1);
- glCopyPixels(x_src, ctx->height - (y_src + height), width, height, GL_COLOR);
- if (ctx->pat) {
- glEnable(GL_TEXTURE_2D);
- }
-#else
- int width2 = gl_get_to_power_two(width);
- int height2 = gl_get_to_power_two(height);
-
- start_draw(ctx);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- if (width2 > ctx->private_tex_width) {
- ctx->private_tex_width = width2;
- recreate = 1;
- }
- if (height2 > ctx->private_tex_height) {
- ctx->private_tex_height = height2;
- recreate = 1;
- }
- if (recreate) {
- glDeleteTextures(1, &ctx->private_tex);
- glGenTextures(1, &ctx->private_tex);
- glBindTexture(GL_TEXTURE_2D, ctx->private_tex);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- ctx->private_tex_width = gl_get_to_power_two(width);
- ctx->private_tex_height = gl_get_to_power_two(height);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, ctx->private_tex_width,
- ctx->private_tex_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
- }
- ASSERT(ctx->private_tex);
- glBindTexture(GL_TEXTURE_2D, ctx->private_tex);
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x_src, ctx->height - (y_src + height),
- width2, height2, 0);
-
- GLfloat s_gen_params[] = { (GLfloat)1.0 / width2, 0, 0, 0 };
- GLfloat t_gen_params[] = { 0, (GLfloat)1.0 / height2, 0, 0 };
- glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen_params);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen_params);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glTranslatef((float)-x_dest / width2, (float)-Y(y_dest + height) / height2, 0);
-
- glRecti(x_dest, Y(y_dest), x_dest + width, Y(y_dest + height));
- glFlush();
- if (!ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- } else {
- set_pat(ctx, ctx->pat);
- }
-#endif
- GLC_ERROR_TEST_FLUSH;
-}
-
-void glc_read_pixels(GLCCtx glc, int x, int y, GLCImage *image)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && image);
- ASSERT(image->format == GLC_IMAGE_RGB32); //for now
- ASSERT((image->stride % 4) == 0); //for now
- glPixelStorei(GL_PACK_ROW_LENGTH, image->stride / 4);
- glReadPixels(x, ctx->height - (y + image->height), image->width, image->height,
- GL_BGRA, GL_UNSIGNED_BYTE, image->pixels);
-}
-
-void glc_clear(GLCCtx glc)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void glc_flush(GLCCtx glc)
-{
- glFlush();
-
- GLC_ERROR_TEST_FLUSH;
-}
-
-static void tessellation_combine(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4],
- GLdouble **data_out, void *usr_data)
-{
- TassVertex *vertex;
-
- vertex = alloc_tess_vertex((InternaCtx *)usr_data);
- vertex->point.x = coords[0];
- vertex->point.y = coords[1];
- //vertex->point.z = coords[2];
- *data_out = (GLdouble *)&vertex->point;
-}
-
-static void tessellation_error(GLenum errorCode)
-{
- printf("%s: %s\n", __FUNCTION__, gluErrorString(errorCode));
-}
-
-#ifdef WIN32
-#define TESS_CALL_BACK_TYPE void(CALLBACK *)()
-#else
-#define TESS_CALL_BACK_TYPE void(*)()
-#endif
-
-static int init(InternaCtx *ctx, int width, int height)
-{
-#ifdef WIN32
- if (!(ctx->glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation"))) {
- return FALSE;
- }
-#endif
- ctx->width = width;
- ctx->height = height;
- ctx->line_width = 1;
-
- glClearColor(0, 0, 0, 0);
- glClearStencil(0);
-
- if (!(ctx->tesselator = gluNewTess())) {
- return FALSE;
- }
-
- glGenTextures(1, &ctx->private_tex);
- glBindTexture(GL_TEXTURE_2D, ctx->private_tex);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, gl_get_to_power_two(width),
- gl_get_to_power_two(height), 0,
- GL_BGRA, GL_UNSIGNED_BYTE, NULL);
- ctx->private_tex_width = gl_get_to_power_two(width);
- ctx->private_tex_height = gl_get_to_power_two(height);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, width, 0, height, -1, 1);
-
- gluTessProperty(ctx->tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
- gluTessCallback(ctx->tesselator, GLU_BEGIN, (TESS_CALL_BACK_TYPE)glBegin);
- gluTessCallback(ctx->tesselator, GLU_VERTEX, (TESS_CALL_BACK_TYPE)glVertex3dv);
- gluTessCallback(ctx->tesselator, GLU_END, (TESS_CALL_BACK_TYPE)glEnd);
- gluTessCallback(ctx->tesselator, GLU_TESS_COMBINE_DATA,
- (TESS_CALL_BACK_TYPE)tessellation_combine);
- gluTessCallback(ctx->tesselator, GLU_TESS_ERROR, (TESS_CALL_BACK_TYPE)tessellation_error);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0, (GLfloat)height, 0);
-
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
-
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
- glPixelTransferf(GL_ALPHA_BIAS, 0);
-#ifdef WIN32
- ctx->glBlendEquation(GL_FUNC_ADD);
-#else
- glBlendEquation(GL_FUNC_ADD);
-#endif
-
- glStencilMask(0xff);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- return TRUE;
-}
-
-GLCCtx glc_create(int width, int height)
-{
- InternaCtx *ctx;
-
- ASSERT(sizeof(PathPoint) == sizeof(Vertex));
-
- ctx = spice_new0(InternaCtx, 1);
- if (!init(ctx, width, height)) {
- free(ctx);
- return NULL;
- }
- return ctx;
-}
-
-/*
- * In glx video mode change the textures will be destroyed, therefore
- * if we will try to glDeleteTextures() them we might get seagfault.
- * (this why we use the textures_lost parameter)
- */
-void glc_destroy(GLCCtx glc, int textures_lost)
-{
- InternaCtx *ctx;
-
- if (!(ctx = (InternaCtx *)glc)) {
- return;
- }
-
- if (!textures_lost) {
- unref_pat(ctx->pat);
- ctx->pat = NULL;
- if (ctx->private_tex) {
- glDeleteTextures(1, &ctx->private_tex);
- }
- }
-
- free_tass_vertex_bufs(ctx);
- free(ctx->line_dash.dashes);
- free(ctx);
- GLC_ERROR_TEST_FINISH;
-}
-
-/*
- todo:
- 1. test double vs float in gl calls
- 2. int vs flat raster position
- 3. pixels stride vs bytes stride
- 4. improve non power of two.
- glGetString(GL_EXTENSIONS);
- ARB_texture_non_power_of_two
- ARB_texture_rectangle
- GL_TEXTURE_RECTANGLE_ARB
- 5. scale
- 6. origin
- 7. fonts
- 8. support more image formats
- 9. use GLCImage in mask ops?
-*/
-
diff --git a/common/glc.c.save b/common/glc.c.save
deleted file mode 100644
index 1958110..0000000
--- a/common/glc.c.save
+++ /dev/null
@@ -1,1413 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-#ifdef WIN32
-#include "glext.h"
-#include "wglext.h"
-#endif
-
-#include "glc.h"
-
-#define TRUE 1
-#define FALSE 0
-
-#define ASSERT(x) if (!(x)) {printf("%s: assert failed %s\n", __FUNCTION__, #x); for (;;);}
-
-#define GLC_ERROR_TETS { \
- GLenum gl_err; glFlush(); \
- if ((gl_err = glGetError()) != GL_NO_ERROR) { \
- printf("%s[%d]: opengl error: %s\n", __FUNCTION__, __LINE__, gluErrorString(gl_err)); \
- for(;;); \
- } \
-}
-
-#define WARN_ONCE(x) { \
- static int warn = TRUE; \
- if (warn) { \
- printf x; \
- warn = FALSE; \
- } \
-}
-
-#define TESS_VERTEX_ALLOC_BUNCH 20
-
-typedef struct InternaCtx InternaCtx;
-typedef struct InternalPat {
- InternaCtx *owner;
- int refs;
- GLuint texture;
- int x_orign;
- int y_orign;
- int width;
- int height;
-} InternalPat;
-
-typedef struct Pathpath {
- int start_point;
- int num_segments;
-} Path;
-
-enum {
- GLC_PATH_SEG_LINES,
- GLC_PATH_SEG_BEIZER,
-};
-
-//todo: flatten cache
-typedef struct PathSegment {
- int type;
- int count;
-} PathSegment;
-
-typedef struct PathPoint {
- double x;
- double y;
- double z;
-} PathPoint;
-
-typedef GLdouble Vertex[3];
-
-typedef struct InternalPath {
- InternaCtx *owner;
-
- Path *paths;
- int paths_size;
- int paths_pos;
-
- PathSegment *segments;
- int segments_size;
- int segments_pos;
-
- PathPoint *points;
- int points_size;
- int points_pos;
-
- Path *current_path;
- PathSegment *current_segment;
-
-} InternalPath;
-
-typedef struct TassVertex TassVertex;
-struct TassVertex {
- PathPoint point;
- TassVertex *list_link;
- TassVertex *next;
-};
-
-typedef struct TassVertexBuf TassVertexBuf;
-struct TassVertexBuf {
- TassVertexBuf *next;
- TassVertex vertexs[0];
-};
-
-struct InternaCtx {
- int draw_mode;
- int stencil_refs;
- int stencil_mask;
- int width;
- int height;
- GLfloat line_width;
- InternalPat *pat;
- int max_texture_size;
- GLUtesselator* tesselator;
- TassVertex *free_tess_vertex;
- TassVertex *used_tess_vertex;
- TassVertexBuf *vertex_bufs;
-#ifdef WIN32
- PFNGLBLENDEQUATIONPROC glBlendEquation;
-#endif
-};
-
-#define Y(y) -(y)
-#define VERTEX2(x, y) glVertex2d(x, Y(y))
-
-static void fill_rect(InternaCtx *ctx, void *rect);
-static void fill_path(InternaCtx *ctx, void *path);
-static void fill_mask(InternaCtx *ctx, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *bitmap);
-static void set_pat(InternaCtx *ctx, InternalPat *pat);
-
-static inline void *zmalloc(size_t size)
-{
- return calloc(1, size);
-}
-
-static inline void set_raster_pos(InternaCtx *ctx, int x, int y)
-{
- if (x >= 0 && y >= 0 && x < ctx->width && y < ctx->height) {
- glRasterPos2i(x, Y(y));
- return;
- }
- glRasterPos2i(0, 0);
- glBitmap(0, 0, 0, 0, (GLfloat)x, (GLfloat)Y(y), NULL);
-}
-
-static TassVertex *alloc_tess_vertex(InternaCtx *ctx)
-{
- TassVertex *vertex;
-
- if (!ctx->free_tess_vertex) {
- TassVertexBuf *buf;
- int i;
-
- if (!(buf = (TassVertexBuf *)malloc(sizeof(TassVertexBuf) +
- sizeof(TassVertex) * TESS_VERTEX_ALLOC_BUNCH))) {
- //warn
- return NULL;
- }
- buf->next = ctx->vertex_bufs;
- ctx->vertex_bufs = buf;
- for (i = 0; i < TESS_VERTEX_ALLOC_BUNCH; i++) {
- buf->vertexs[i].point.z = 0;
- buf->vertexs[i].next = ctx->free_tess_vertex;
- ctx->free_tess_vertex = &buf->vertexs[i];
- }
- }
-
- vertex = ctx->free_tess_vertex;
- ctx->free_tess_vertex = vertex->next;
- vertex->next = ctx->used_tess_vertex;
- ctx->used_tess_vertex = vertex;
- return vertex;
-}
-
-static void reset_tass_vertex(InternaCtx *ctx)
-{
- TassVertex *vertex;
- while ((vertex = ctx->used_tess_vertex)) {
- ctx->used_tess_vertex = vertex->next;
- vertex->next = ctx->free_tess_vertex;
- ctx->free_tess_vertex = vertex;
- }
-}
-
-static void free_tass_vertex_bufs(InternaCtx *ctx)
-{
- TassVertexBuf *buf;
-
- ctx->used_tess_vertex = NULL;
- ctx->free_tess_vertex = NULL;
- while ((buf = ctx->vertex_bufs)) {
- ctx->vertex_bufs = buf->next;
- free(buf);
- }
-}
-
-//naiev bezier flattener
-static TassVertex *bezier_flattener(InternaCtx *ctx, PathPoint *points)
-{
- double ax, bx, cx;
- double ay, by, cy;
- const int num_points = 30;
- double dt;
- int i;
-
- TassVertex *vertex_list = NULL;
- TassVertex *curr_vertex;
-
- for (i = 0; i < num_points - 2; i++) {
- TassVertex *vertex;
-
- if (!(vertex = alloc_tess_vertex(ctx))) {
- //warn
- return NULL;
- }
- vertex->list_link = vertex_list;
- vertex_list = vertex;
- }
-
- curr_vertex = vertex_list;
-
- cx = 3.0 * (points[1].x - points[0].x);
- bx = 3.0 * (points[2].x - points[1].x) - cx;
- ax = points[3].x - points[0].x - cx - bx;
-
- cy = 3.0 * (points[1].y - points[0].y);
- by = 3.0 * (points[2].y - points[1].y) - cy;
- ay = points[3].y - points[0].y - cy - by;
-
- dt = 1.0 / ( num_points - 1 );
-
- for( i = 1; i < num_points - 1; i++, curr_vertex = curr_vertex->list_link) {
- double tSquared, tCubed;
- double t;
- t = i * dt;
-
- tSquared = t * t;
- tCubed = tSquared * t;
-
- curr_vertex->point.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + points[0].x;
- curr_vertex->point.y = (ay * tCubed) + (by * tSquared) + (cy * t) + points[0].y;
- }
-
- return vertex_list;
-}
-
-#define MORE_X(path, Type, name) {\
- Type *name;\
- \
- if (!(name = (Type *)zmalloc(sizeof(*name) * path->name##_size * 2))) {\
- return FALSE;\
- }\
- memcpy(name, path->name, sizeof(*name) * path->name##_size);\
- free(path->name);\
- path->name = name;\
- path->name##_size *= 2;\
- return TRUE;\
-}
-
-static int more_points(InternalPath *path)
-{
- MORE_X(path, PathPoint, points);
-}
-
-static int more_segments(InternalPath *path)
-{
- MORE_X(path, PathSegment, segments);
-}
-
-static int more_paths(InternalPath *path)
-{
- MORE_X(path, Path, paths);
-}
-
-static inline void put_point(InternalPath *path, double x, double y)
-{
- path->points[path->points_pos].x = x;
- path->points[path->points_pos++].y = Y(y + 0.5);
- path->points[path->points_pos].z = 0;
-}
-
-void glc_path_move_to(GLCPath path, double x, double y)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
-
- if (internal->current_segment) {
- internal->current_segment = NULL;
- internal->current_path = NULL;
- if (internal->points_pos == internal->points_size && !more_points(internal)) {
- //warn
- return;
- }
- internal->points_pos++;
- }
- internal->points[internal->points_pos - 1].x = x;
- internal->points[internal->points_pos - 1].y = Y(y + 0.5);
- internal->points[internal->points_pos - 1].z = 0;
-}
-
-static int add_segment_common(InternalPath *internal, int type, int num_points)
-{
- if (internal->points_size - internal->points_pos < num_points && !more_points(internal)) {
- //warn
- return FALSE;
- }
-
- if (internal->current_segment) {
- if (internal->current_segment->type == type) {
- internal->current_segment->count++;
- return TRUE;
- }
- if (internal->segments_pos == internal->segments_size && !more_segments(internal)) {
- //warn
- return FALSE;
- }
- internal->current_segment = &internal->segments[internal->segments_pos++];
- internal->current_segment->type = type;
- internal->current_segment->count = 1;
- internal->current_path->num_segments++;
- return TRUE;
- }
-
- if (internal->paths_pos == internal->paths_size && !more_paths(internal)) {
- //warn
- return FALSE;
- }
-
- if (internal->segments_pos == internal->segments_size && !more_segments(internal)) {
- //warn
- return FALSE;
- }
-
- internal->current_path = &internal->paths[internal->paths_pos++];
- internal->current_path->start_point = internal->points_pos - 1;
- internal->current_path->num_segments = 1;
- internal->current_segment = &internal->segments[internal->segments_pos++];
- internal->current_segment->type = type;
- internal->current_segment->count = 1;
- return TRUE;
-}
-
-void glc_path_line_to(GLCPath path, double x, double y)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
-
- if (!add_segment_common(internal, GLC_PATH_SEG_LINES, 1)) {
- return;
- }
- put_point(internal, x, y);
-}
-
-void glc_path_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y,
- double p3_x, double p3_y)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
-
- if (!add_segment_common(internal, GLC_PATH_SEG_BEIZER, 3)) {
- return;
- }
- put_point(internal, p1_x, p1_y);
- put_point(internal, p2_x, p2_y);
- put_point(internal, p3_x, p3_y);
-}
-
-void glc_path_close(GLCPath path)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
- if (!internal->current_path) {
- return;
- }
- PathPoint *end_point = &internal->points[internal->current_path->start_point];
- glc_path_line_to(path, end_point->x, Y(end_point->y));
- glc_path_move_to(path, end_point->x, Y(end_point->y));
-}
-
-void glc_path_cleare(GLCPath path)
-{
- InternalPath *internal = (InternalPath *)path;
-
- ASSERT(internal);
- internal->paths_pos = internal->segments_pos = 0;
- internal->current_segment = NULL;
- internal->current_path = NULL;
-
- internal->points[0].x = 0;
- internal->points[0].y = 0;
- internal->points_pos = 1;
-}
-
-GLCPath glc_path_create(GLCCtx glc)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPath *path;
-
- ASSERT(ctx);
- if (!(path = (InternalPath *)zmalloc(sizeof(*path)))) {
- return NULL;
- }
-
- path->paths = (Path *)malloc(sizeof(*path->paths) * (path->paths_size = 2));
- if (!path->paths) {
- goto error_1;
- }
-
- path->segments = (PathSegment *)malloc(sizeof(*path->segments) * (path->segments_size = 4));
- if (!path->segments) {
- goto error_2;
- }
-
- path->points = (PathPoint *)malloc(sizeof(*path->points) * (path->points_size = 20));
- if (!path->points) {
- goto error_3;
- }
-
- path->owner = ctx;
- path->points_pos = 1;
- return path;
-
-error_3:
- free(path->segments);
-
-error_2:
- free(path->paths);
-
-error_1:
- free(path);
-
- return NULL;
-}
-
-void glc_path_destroy(GLCPath path)
-{
- InternalPath *internal = (InternalPath *)path;
-
- if (!path) {
- return;
- }
-
- free(internal->points);
- free(internal->segments);
- free(internal->paths);
- free(internal);
-}
-
-static inline void unref_pat(InternalPat *pat)
-{
- if (!pat) {
- return;
- }
- ASSERT(pat->refs > 0);
- if (--pat->refs == 0) {
- glFinish();
- glDeleteTextures(1, &pat->texture);
- free(pat);
- }
- GLC_ERROR_TETS;
-}
-
-static inline InternalPat *ref_pat(InternalPat *pat)
-{
- pat->refs++;
- return pat;
-}
-
-#ifdef WIN32
-static inline int find_msb(uint32_t val)
-{
- uint32_t r;
- __asm {
- bsr eax, val
- jnz found
- mov eax, -1
-
- found:
- mov r, eax
- }
- return r + 1;
-}
-#else
-static inline int find_msb(uint32_t val)
-{
- int ret;
-
- asm("bsrl %1,%0\n\t"
- "jnz 1f\n\t"
- "movl $-1,%0\n"
- "1:"
- : "=r"(ret) : "r"(val));
- return ret + 1;
-}
-#endif
-
-static int to_pwoer_two(uint32_t val)
-{
- if ((val & (val - 1)) == 0) {
- return val;
- }
- return 1 << find_msb(val);
-}
-
-static void scale(uint32_t *dest, uint32_t dest_width, uint32_t dest_height,
- uint32_t *src, uint32_t src_width, uint32_t src_height, int src_stride)
-{
- double x_scale = (double)src_width / dest_width;
- double y_scale = (double)src_height / dest_height;
- uint32_t i;
- uint32_t j;
- int prev_row = -1;
-
- for (i = 0; i < dest_height; i++) {
- int row = (int)(y_scale * i);
- if (row == prev_row) {
- memcpy(dest, dest - dest_width, dest_width * sizeof(uint32_t));
- dest += dest_width;
- continue;
- }
- for (j = 0; j < dest_width; j++) {
- int col = (int)(x_scale * j);
- *(dest++) = *(src + col);
- }
- prev_row = row;
- src = (uint32_t *)((uint8_t *)src + src_stride);
- }
-}
-
-static inline void init_pattern(InternalPat *pat, int x_orign, int y_orign, const GLCImage *image)
-{
- InternaCtx *ctx = pat->owner;
- uint32_t *tmp_pixmap = NULL;
- int width;
- int height;
- int width2;
- int height2;
-
- const int pix_bytes = 4;
-
- ASSERT(image->format == GLC_IMAGE_RGB32); //for now
-
- width = image->width;
- height = image->height;
- width2 = to_pwoer_two(width);
- height2 = to_pwoer_two(height);
-
- ASSERT(width > 0 && height > 0);
- ASSERT(width > 0 && width <= pat->owner->max_texture_size);
- ASSERT(height > 0 && height <= pat->owner->max_texture_size);
-
- if (width2 != width || height2 != height) {
- if (!(tmp_pixmap = (uint32_t *)malloc(width2 * height2 * sizeof(uint32_t)))) {
- //warn
- return;
- }
- scale(tmp_pixmap, width2, height2, (uint32_t *)image->pixels, width, height, image->stride);
- }
-
- glBindTexture(GL_TEXTURE_2D, pat->texture);
-
- //glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- if (tmp_pixmap) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, width2);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, width2, height2, 0, GL_BGRA, GL_UNSIGNED_BYTE,
- tmp_pixmap);
- free(tmp_pixmap);
- } else {
- ASSERT(image->stride % pix_bytes == 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, image->stride / pix_bytes);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
- image->pixels);
- }
-
- GLC_ERROR_TETS;
- pat->x_orign = x_orign % width;
- pat->y_orign = y_orign % height;
- pat->width = width;
- pat->height = height;
-
- if (ctx->pat == pat) {
- set_pat(pat->owner, pat);
- } else if (ctx->pat) {
- glBindTexture(GL_TEXTURE_2D, ctx->pat->texture);
- }
-}
-
-GLCPattern glc_pattern_create(GLCCtx glc, int x_orign, int y_orign, const GLCImage *image)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPat *pat;
-
- ASSERT(ctx && image);
-
- if (!(pat = (InternalPat *)zmalloc(sizeof(*pat)))) {
- return NULL;
- }
- pat->refs = 1;
- pat->owner = ctx;
- glGenTextures(1, &pat->texture);
- init_pattern(pat, x_orign, y_orign, image);
- return pat;
-}
-
-void glc_pattern_set(GLCPattern pattern, int x_orign, int y_orign, const GLCImage *image)
-{
- InternalPat *pat = (InternalPat *)pattern;
- ASSERT(pat && pat->owner);
-
- glFinish();
- init_pattern(pat, x_orign, y_orign, image);
-}
-
-void glc_pattern_destroy(GLCPattern pat)
-{
- unref_pat((InternalPat *)pat);
- GLC_ERROR_TETS;
-}
-
-static void set_pat(InternaCtx *ctx, InternalPat *pat)
-{
- pat = ref_pat(pat);
- unref_pat(ctx->pat);
- ctx->pat = pat;
-
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, pat->texture);
-
- GLfloat s_gen_params[] = { (GLfloat)1.0 / pat->width, 0, 0, 0 };
- GLfloat t_gen_params[] = { 0, (GLfloat)1.0 / (GLfloat)pat->height, 0, 0 };
- glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen_params);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen_params);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glTranslatef((float)pat->x_orign / pat->width, (float)Y(pat->y_orign) / pat->height, 0);
- GLC_ERROR_TETS;
-}
-
-void glc_set_pattern(GLCCtx glc, GLCPattern pattern)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPat *pat = (InternalPat *)pattern;
-
- ASSERT(ctx && pat && pat->owner == ctx);
- set_pat(ctx, pat);
-}
-
-void glc_set_rgb(GLCCtx glc, double red, double green, double blue)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
-
- glDisable(GL_TEXTURE_2D);
- unref_pat(ctx->pat);
- ctx->pat = NULL;
- glColor4d(red, green, blue, 1);
- GLC_ERROR_TETS;
-}
-
-void glc_set_op(GLCCtx glc, GLCOp op)
-{
- if (op == GL_COPY) {
- glDisable(GL_COLOR_LOGIC_OP);
- return;
- }
- glLogicOp(op);
- glEnable(GL_COLOR_LOGIC_OP);
-}
-
-void glc_set_line_width(GLCCtx glc, double width)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- ctx->line_width = (GLfloat)width;
- if (ctx->line_width > 0) {
- glLineWidth(ctx->line_width);
- } else {
- ctx->line_width = 0;
- }
- GLC_ERROR_TETS;
-}
-
-void glc_set_fill_mode(GLCCtx glc, GLCFillMode fill_mode)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- int mode;
- switch (fill_mode) {
- case GLC_FILL_MODE_WINDING_ODD:
- mode = GLU_TESS_WINDING_ODD;
- break;
- case GLC_FILL_MODE_WINDING_NONZERO:
- mode = GLU_TESS_WINDING_NONZERO;
- break;
- default:
- //warn
- return;
- }
- gluTessProperty(ctx->tesselator, GLU_TESS_WINDING_RULE, mode);
-}
-
-static inline void add_stencil_client(InternaCtx *ctx)
-{
- if (!ctx->stencil_refs) {
- glEnable(GL_STENCIL_TEST);
- }
- ctx->stencil_refs++;
-}
-
-static inline void remove_stencil_client(InternaCtx *ctx)
-{
- ctx->stencil_refs--;
- if (!ctx->stencil_refs) {
- glDisable(GL_STENCIL_TEST);
- }
-}
-
-void glc_set_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap, GLCMaskID id)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08;
- ASSERT(ctx && bitmap);
- ASSERT(id == GLC_MASK_A || id == GLC_MASK_B);
-
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
-
- glDisable(GL_BLEND);
-
- if (!(ctx->stencil_mask & mask)) {
- add_stencil_client(ctx);
- ctx->stencil_mask |= mask;
- }
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- ctx->draw_mode = FALSE;
- glStencilMask(mask);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, mask, mask);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- fill_mask(ctx, x_dest, y_dest, width, height, stride, bitmap);
-}
-
-
-void glc_mask_rects(GLCCtx glc, int num_rect, GLCRect *rects, GLCMaskID id)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08;
- GLCRect *end;
- ASSERT(ctx && rects);
- ASSERT(id == GLC_MASK_A || id == GLC_MASK_B);
-
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
-
- glDisable(GL_BLEND);
-
- if (!(ctx->stencil_mask & mask)) {
- add_stencil_client(ctx);
- ctx->stencil_mask |= mask;
- }
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- ctx->draw_mode = FALSE;
- glStencilMask(mask);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, mask, mask);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- end = rects + num_rect;
- for (; rects < end; rects++) {
- fill_rect(ctx, rects);
- }
-}
-
-void glc_clear_mask(GLCCtx glc, GLCMaskID id)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08;
- ASSERT(ctx);
- ASSERT(id == GLC_MASK_A || id == GLC_MASK_B);
-
- if ((ctx->stencil_mask & mask)) {
- ctx->stencil_mask &= ~mask;
- remove_stencil_client(ctx);
- }
-}
-
-void glc_clip_reset(GLCCtx glc)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- if (!(ctx->stencil_mask & 0x03)) {
- return;
- }
- remove_stencil_client(ctx);
- ctx->stencil_mask &= ~0x03;
- glStencilMask(0x03);
- glClear(GL_STENCIL_BUFFER_BIT);
- GLC_ERROR_TETS;
-}
-
-static void clip_common(InternaCtx *ctx, GLCClipOp op, void (*fill_func)(InternaCtx *, void *),
- void *data)
-{
- int stencil_val;
-
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
- glDisable(GL_BLEND);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- ctx->draw_mode = FALSE;
-
- if (op == GLC_CLIP_OP_SET) {
- glc_clip_reset(ctx);
- add_stencil_client(ctx);
- ctx->stencil_mask |= 0x01;
- } else if (!(ctx->stencil_mask & 0x03)) {
- GLCRect area;
- if (op == GLC_CLIP_OP_OR) {
- return;
- }
- area.x = area.y = 0;
- area.width= ctx->width;
- area.height = ctx->height;
- clip_common(ctx, GLC_CLIP_OP_SET, fill_rect, &area);
- }
- glStencilMask(0x03);
- switch (op) {
- case GLC_CLIP_OP_SET:
- case GLC_CLIP_OP_OR:
- stencil_val = ctx->stencil_mask & 0x03;
- glStencilFunc(GL_ALWAYS, stencil_val, stencil_val);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- fill_func(ctx, data);
- break;
- case GLC_CLIP_OP_AND: {
- int clear_mask;
- stencil_val = ctx->stencil_mask & 0x03;
- glStencilFunc(GL_EQUAL, stencil_val, stencil_val);
- if (stencil_val == 0x01) {
- glStencilOp(GL_ZERO, GL_INCR, GL_INCR);
- stencil_val = 0x02;
- clear_mask = 0x01;
- } else {
- glStencilOp(GL_ZERO, GL_DECR, GL_DECR);
- stencil_val = 0x01;
- clear_mask = 0x02;
- }
- fill_func(ctx, data);
-
- glStencilMask(clear_mask);
- glClear(GL_STENCIL_BUFFER_BIT);
- ctx->stencil_mask = (ctx->stencil_mask & ~clear_mask) |stencil_val;
- break;
- }
- case GLC_CLIP_OP_EXCLUDE:
- stencil_val = ctx->stencil_mask & 0x03;
- glStencilFunc(GL_EQUAL, stencil_val, stencil_val);
- glStencilOp(GL_KEEP, GL_ZERO, GL_ZERO);
- fill_func(ctx, data);
- break;
- }
- GLC_ERROR_TETS;
-}
-
-void glc_clip_rect(GLCCtx glc, const GLCRect *rect, GLCClipOp op)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && rect);
- clip_common(ctx, op, fill_rect, (void *)rect);
-}
-
-void glc_clip_path(GLCCtx glc, GLCPath path, GLCClipOp op)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && path);
- clip_common(ctx, op, fill_path, path);
-}
-
-typedef struct FillMaskInfo {
- int x_dest;
- int y_dest;
- int width;
- int height;
- int stride;
- const uint8_t *bitmap;
-} FillMaskInfo;
-
-static void __fill_mask(InternaCtx *ctx, void *data)
-{
- FillMaskInfo *info = (FillMaskInfo *)data;
- fill_mask(ctx, info->x_dest, info->y_dest, info->width, info->height, info->stride,
- info->bitmap);
-}
-
-void glc_clip_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap, GLCClipOp op)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- FillMaskInfo mask_info;
-
- ASSERT(ctx && bitmap);
- mask_info.x_dest = x_dest;
- mask_info.y_dest = y_dest;
- mask_info.width = width;
- mask_info.height = height;
- mask_info.stride = stride;
- mask_info.bitmap = bitmap;
- clip_common(ctx, op, __fill_mask, &mask_info);
-}
-
-static inline void start_draw(InternaCtx *ctx)
-{
- if (ctx->draw_mode) {
- return;
- }
- ctx->draw_mode = TRUE;
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilFunc(GL_EQUAL, ctx->stencil_mask, ctx->stencil_mask);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- if (ctx->pat) {
- glEnable(GL_TEXTURE_2D);
- } else {
- glDisable(GL_TEXTURE_2D);
- }
- GLC_ERROR_TETS;
-}
-
-static void fill_rect(InternaCtx *ctx, void *r)
-{
- GLCRect *rect = (GLCRect *)r;
- glRectd(rect->x, Y(rect->y), rect->x + rect->width, Y(rect->y + rect->height));
- /*glBegin(GL_POLYGON);
- VERTEX2(rect->x, rect->y);
- VERTEX2 (rect->x + rect->width, rect->y);
- VERTEX2 (rect->x + rect->width, rect->y + rect->height);
- VERTEX2 (rect->x , rect->y + rect->height);
- glEnd();*/
- GLC_ERROR_TETS;
-}
-
-void glc_fill_rect(GLCCtx glc, const GLCRect *rect)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- start_draw(ctx);
- fill_rect(ctx, (void *)rect);
- GLC_ERROR_TETS;
-}
-
-static void fill_path(InternaCtx *ctx, void *p)
-{
- InternalPath *path = (InternalPath *)p;
-
- PathPoint *current_point = path->points;
- PathSegment *current_segment = path->segments;
- Path *current_path = path->paths;
- Path *end_path = current_path + path->paths_pos;
- reset_tass_vertex(ctx);
- gluTessBeginPolygon(ctx->tesselator, ctx);
- for (; current_path < end_path; current_path++) {
- gluTessBeginContour(ctx->tesselator);
- PathSegment *end_segment = current_segment + current_path->num_segments;
- gluTessVertex(ctx->tesselator, (GLdouble *)current_point, current_point);
- current_point++;
- for (; current_segment < end_segment; current_segment++) {
- PathPoint *end_point;
- if (current_segment->type == GLC_PATH_SEG_BEIZER) {
- end_point = current_point + current_segment->count * 3;
- for (; current_point < end_point; current_point += 3) {
- TassVertex *vertex = bezier_flattener(ctx, current_point - 1);
- while (vertex) {
- gluTessVertex(ctx->tesselator, (GLdouble *)&vertex->point,
- (GLdouble *)&vertex->point);
- vertex = vertex->list_link;
- }
- gluTessVertex(ctx->tesselator, (GLdouble *)¤t_point[2],
- (GLdouble *)¤t_point[2]);
- }
- } else {
- ASSERT(current_segment->type == GLC_PATH_SEG_LINES);
- end_point = current_point + current_segment->count;
- for (; current_point < end_point; current_point++) {
- gluTessVertex(ctx->tesselator, (GLdouble *)current_point ,
- (GLdouble *)current_point);
- }
- }
- }
- gluTessEndContour(ctx->tesselator);
- }
- gluTessEndPolygon(ctx->tesselator);
-}
-
-void glc_fill_path(GLCCtx glc, GLCPath path_ref)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && path_ref);
- start_draw(ctx);
- fill_path(ctx, path_ref);
-}
-
-static void fill_mask(InternaCtx *ctx, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap)
-{
- set_raster_pos(ctx, x_dest, y_dest + height);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8);
- glBitmap(width, height, 0, 0, 0, 0, bitmap);
-}
-
-void _glc_fill_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *bitmap)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && bitmap);
- start_draw(ctx);
- if (ctx->pat) {
- WARN_ONCE(("%s: unimplemented fill mask with pattern\n", __FUNCTION__));
- }
- fill_mask(ctx, x_dest, y_dest, width, height, stride, bitmap);
-}
-
-void glc_fill_alpha(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *alpha_mask)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- GLCRect r;
-
- ASSERT(ctx);
- start_draw(ctx);
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
- set_raster_pos(ctx, x_dest, y_dest + height);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
- glPixelZoom(1, 1);
- glDrawPixels(width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_mask);
-
- r.x = x_dest;
- r.y = y_dest;
- r.width = width;
- r.height = height;
-
- //todo: support color/texture alpah vals (GL_MODULATE)
- glEnable(GL_BLEND);
- glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- fill_rect(ctx, &r);
- glDisable(GL_BLEND);
-}
-
-void glc_stroke_rect(GLCCtx glc, const GLCRect *rect)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- if (ctx->line_width == 0) {
- return;
- }
-
- start_draw(ctx);
-
- glBegin(GL_LINES);
- VERTEX2 (rect->x , rect->y + 0.5);
- VERTEX2 (rect->x + rect->width, rect->y + 0.5);
- glEnd();
-
- glBegin(GL_LINES);
- VERTEX2 (rect->x + rect->width - 0.5, rect->y);
- VERTEX2 (rect->x + rect->width - 0.5, rect->y + rect->height);
- glEnd();
-
- glBegin(GL_LINES);
- VERTEX2 (rect->x + rect->width, rect->y + rect->height - 0.5);
- VERTEX2 (rect->x, rect->y + rect->height - 0.5);
- glEnd();
-
- glBegin(GL_LINES);
- VERTEX2(rect->x + 0.5, rect->y + rect->height);
- VERTEX2(rect->x + 0.5 , rect->y);
- glEnd();
- GLC_ERROR_TETS;
-}
-
-void glc_stroke_path(GLCCtx glc, GLCPath path_ref)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- InternalPath *path = (InternalPath *)path_ref;
-
- ASSERT(ctx && path);
- if (ctx->line_width == 0) {
- return;
- }
- start_draw(ctx);
-
- reset_tass_vertex(ctx);
- PathPoint *current_point = path->points;
- PathSegment *current_segment = path->segments;
- Path *current_path = path->paths;
- Path *end_path = current_path + path->paths_pos;
- for (; current_path < end_path; current_path++) {
- glBegin(GL_LINE_STRIP);
- PathSegment *end_segment = current_segment + current_path->num_segments;
- glVertex2d(current_point->x , current_point->y);
- current_point++;
- for (; current_segment < end_segment; current_segment++) {
- PathPoint *end_point;
- if (current_segment->type == GLC_PATH_SEG_BEIZER) {
- end_point = current_point + current_segment->count * 3;
- for (; current_point < end_point; current_point += 3) {
- TassVertex *vertex = bezier_flattener(ctx, current_point - 1);
- while (vertex) {
- glVertex2d(vertex->point.x, vertex->point.y);
- vertex = vertex->list_link;
- }
- glVertex2d(current_point[2].x , current_point[2].y);
- }
- } else {
- ASSERT(current_segment->type == GLC_PATH_SEG_LINES);
- end_point = current_point + current_segment->count;
- for (; current_point < end_point; current_point++) {
- glVertex2d(current_point->x , current_point->y);
- }
- }
- }
- glEnd();
- }
-}
-
-void glc_draw_image(GLCCtx glc, const GLCRecti *dest, const GLCRecti *src, const GLCImage *image,
- int scale_mode, double alpha)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- uint8_t *pixels;
- const int pix_bytes = 4;
-
- ASSERT(ctx && image);
- ASSERT(src->width > 0 && src->height > 0);
-
- ASSERT(image->format == GLC_IMAGE_RGB32 || image->format == GLC_IMAGE_ARGB32); //for now
- start_draw(ctx);
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
- set_raster_pos(ctx, dest->x, dest->y + dest->height);
-
- if (dest->width == src->width && src->height == dest->height) {
- glPixelZoom(1, 1);
- } else {
- glPixelZoom((float)dest->width / src->width, (float)dest->height / src->height);
- }
-
- pixels = image->pixels + src->x * 4 + (image->height - (src->y + src->height)) * image->stride;
- if (image->format == GLC_IMAGE_ARGB32 || alpha != 1) {
- glPixelTransferf(GL_ALPHA_SCALE, (GLfloat)alpha);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- }
- ASSERT(image->stride % pix_bytes == 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, image->stride / pix_bytes);
- glDrawPixels(src->width, src->height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
-
- if (image->format == GLC_IMAGE_ARGB32 || alpha != 1) {
- glDisable(GL_BLEND);
- }
-
- if (ctx->pat) {
- glEnable(GL_TEXTURE_2D);
- }
- GLC_ERROR_TETS;
-}
-
-void glc_copy_pixels(GLCCtx glc, int x_dest, int y_dest, int x_src, int y_src, int width,
- int height)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
- ASSERT(ctx);
-#ifdef USE_COPY_PIXELS
- start_draw(ctx);
- if (ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- }
- set_raster_pos(ctx, x_dest, y_dest + height);
- glPixelZoom(1, 1);
- glCopyPixels(x_src, ctx->height - (y_src + height), width, height, GL_COLOR);
- if (ctx->pat) {
- glEnable(GL_TEXTURE_2D);
- }
-#else
- GLuint texture;
- int width2 = to_pwoer_two(width);
- int height2 = to_pwoer_two(height);
-
- start_draw(ctx);
- glEnable(GL_TEXTURE_2D);
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x_src, ctx->height - (y_src + height),
- width2, height2, 0);
-
- GLfloat s_gen_params[] = { (GLfloat)1.0 / width2, 0, 0, 0 };
- GLfloat t_gen_params[] = { 0, (GLfloat)1.0 / height2, 0, 0 };
- glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen_params);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen_params);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glTranslatef((float)-x_dest / width2, (float)-Y(y_dest + height) / height2, 0);
-
- glRecti(x_dest, Y(y_dest), x_dest + width, Y(y_dest + height));
- glFinish();
- glDeleteTextures(1, &texture);
- if (!ctx->pat) {
- glDisable(GL_TEXTURE_2D);
- } else {
- set_pat(ctx, ctx->pat);
- }
-#endif
- GLC_ERROR_TETS;
-}
-
-void glc_read_pixels(GLCCtx glc, int x, int y, GLCImage *image)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx && image);
- ASSERT(image->format == GLC_IMAGE_RGB32); //for now
- ASSERT((image->stride % 4) == 0); //for now
- glPixelStorei(GL_PACK_ROW_LENGTH, image->stride / 4);
- glReadPixels(x, ctx->height - (y + image->height), image->width, image->height,
- GL_BGRA, GL_UNSIGNED_BYTE, image->pixels);
-}
-
-void glc_clear(GLCCtx glc)
-{
- InternaCtx *ctx = (InternaCtx *)glc;
-
- ASSERT(ctx);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void glc_flush(GLCCtx glc)
-{
- glFlush();
-
- GLC_ERROR_TETS;
-}
-
-static void tessellation_combine(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4],
- GLdouble **data_out, void *usr_data)
-{
- TassVertex *vertex;
-
- if (!(vertex = alloc_tess_vertex((InternaCtx *)usr_data))) {
- *data_out = NULL;
- return;
- }
- vertex->point.x = coords[0];
- vertex->point.y = coords[1];
- //vertex->point.z = coords[2];
- *data_out = (GLdouble *)&vertex->point;
-}
-
-static void tessellation_error(GLenum errorCode)
-{
- printf ("%s: %s\n", __FUNCTION__, gluErrorString(errorCode));
-}
-
-#ifdef WIN32
-#define TESS_CALL_BACK_TYPE void (CALLBACK *)()
-#else
-#define TESS_CALL_BACK_TYPE void (*)()
-#endif
-
-static int init(InternaCtx *ctx, int width, int height)
-{
-#ifdef WIN32
- if (!(ctx->glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation"))) {
- return FALSE;
- }
-#endif
- ctx->width = width;
- ctx->height = height;
- ctx->line_width = 1;
-
- glClearColor(0, 0, 0, 0);
- glClearStencil(0);
-
- if (!(ctx->tesselator = gluNewTess())) {
- return FALSE;
- }
-
- glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, width, 0, height, -1, 1);
-
- gluTessProperty(ctx->tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
- gluTessCallback(ctx->tesselator, GLU_BEGIN, (TESS_CALL_BACK_TYPE)glBegin);
- gluTessCallback(ctx->tesselator, GLU_VERTEX, (TESS_CALL_BACK_TYPE)glVertex3dv);
- gluTessCallback(ctx->tesselator, GLU_END, (TESS_CALL_BACK_TYPE)glEnd);
- gluTessCallback(ctx->tesselator, GLU_TESS_COMBINE_DATA, (TESS_CALL_BACK_TYPE)tessellation_combine);
- gluTessCallback(ctx->tesselator, GLU_TESS_ERROR, (TESS_CALL_BACK_TYPE)tessellation_error);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0, (GLfloat)height, 0);
-
- glGetIntegerv( GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
-
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
- glPixelTransferf(GL_ALPHA_BIAS, 0);
-#ifdef WIN32
- ctx->glBlendEquation(GL_FUNC_ADD);
-#else
- glBlendEquation(GL_FUNC_ADD);
-#endif
-
- glStencilMask(0xff);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- return TRUE;
-}
-
-GLCCtx glc_create(int width, int height)
-{
- InternaCtx *ctx;
-
- ASSERT(sizeof(PathPoint) == sizeof(Vertex));
-
- if (!(ctx = (InternaCtx *)zmalloc(sizeof(*ctx)))) {
- return NULL;
- }
-
- if (!init(ctx, width, height)) {
- free(ctx);
- return NULL;
- }
- return ctx;
-}
-
-void glc_destroy(GLCCtx glc)
-{
- InternaCtx *ctx;
-
- if (!(ctx = (InternaCtx *)glc)) {
- return;
- }
-
- unref_pat(ctx->pat);
- free_tass_vertex_bufs(ctx);
- free(ctx);
-}
-
-/*
- todo:
- 1. test double vs float in gl calls
- 2. int vs flat raster position
- 3. pixels stride vs bytes stride
- 4. improve non power of two.
- glGetString(GL_EXTENSIONS);
- ARB_texture_non_power_of_two
- ARB_texture_rectangle
- GL_TEXTURE_RECTANGLE_ARB
- 5. scale
- 6. origin
- 7. fonts
- 8. support more image formats
- 9. use GLCImage in mask ops?
-*/
-
diff --git a/common/glc.h b/common/glc.h
deleted file mode 100644
index a6b8579..0000000
--- a/common/glc.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
-
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#ifndef _H_GL_CANVASE
-#define _H_GL_CANVASE
-
-#include <stdint.h>
-
-typedef void * GLCCtx;
-typedef void * GLCPattern;
-typedef void * GLCPath;
-
-typedef struct GLCRect {
- double x;
- double y;
- double width;
- double height;
-} GLCRect;
-
-typedef struct GLCRecti {
- int x;
- int y;
- int width;
- int height;
-} GLCRecti;
-
-typedef enum {
- GLC_IMAGE_RGB32,
- GLC_IMAGE_ARGB32,
-} GLCImageFormat;
-
-typedef struct GLCPImage {
- GLCImageFormat format;
- int width;
- int height;
- int stride;
- uint8_t *pixels;
- uint32_t *pallet;
-} GLCImage;
-
-GLCPattern glc_pattern_create(GLCCtx glc, int x_orign, int y_orign, const GLCImage *image);
-void glc_pattern_set(GLCPattern pattern, int x_orign, int y_orign, const GLCImage *image);
-void glc_pattern_destroy(GLCPattern pattern);
-
-void glc_path_move_to(GLCPath path, double x, double y);
-void glc_path_line_to(GLCPath path, double x, double y);
-void glc_path_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y,
- double p3_x, double p3_y);
-void glc_path_rel_move_to(GLCPath path, double x, double y);
-void glc_path_rel_line_to(GLCPath path, double x, double y);
-void glc_path_rel_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y,
- double p3_x, double p3_y);
-void glc_path_close(GLCPath path);
-
-void glc_path_cleare(GLCPath);
-GLCPath glc_path_create(GLCCtx glc);
-void glc_path_destroy(GLCPath path);
-
-void glc_set_rgb(GLCCtx glc, double red, double green, double blue);
-void glc_set_rgba(GLCCtx glc, double red, double green, double blue, double alpha);
-void glc_set_pattern(GLCCtx glc, GLCPattern pattern);
-
-typedef enum {
- GLC_OP_CLEAR = 0x1500,
- GLC_OP_SET = 0x150F,
- GLC_OP_COPY = 0x1503,
- GLC_OP_COPY_INVERTED = 0x150C,
- GLC_OP_NOOP = 0x1505,
- GLC_OP_INVERT = 0x150A,
- GLC_OP_AND = 0x1501,
- GLC_OP_NAND = 0x150E,
- GLC_OP_OR = 0x1507,
- GLC_OP_NOR = 0x1508,
- GLC_OP_XOR = 0x1506,
- GLC_OP_EQUIV = 0x1509,
- GLC_OP_AND_REVERSE = 0x1502,
- GLC_OP_AND_INVERTED = 0x1504,
- GLC_OP_OR_REVERSE = 0x150B,
- GLC_OP_OR_INVERTED = 0x150D,
-} GLCOp;
-
-void glc_set_op(GLCCtx glc, GLCOp op);
-void glc_set_alpha_factor(GLCCtx glc, double alpah);
-
-typedef enum {
- GLC_FILL_MODE_WINDING_ODD,
- GLC_FILL_MODE_WINDING_NONZERO,
-} GLCFillMode;
-
-void glc_set_fill_mode(GLCCtx glc, GLCFillMode mode);
-void glc_set_line_width(GLCCtx glc, double width);
-void glc_set_line_end_cap(GLCCtx glc, int style);
-void glc_set_line_join(GLCCtx glc, int style);
-void glc_set_miter_limit(GLCCtx glc, int limit);
-void glc_set_line_dash(GLCCtx glc, const double *dashes, int num_dashes, double offset);
-
-typedef enum {
- GLC_MASK_A,
- GLC_MASK_B,
-} GLCMaskID;
-
-void glc_set_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height,
- int stride, const uint8_t *bitmap, GLCMaskID id);
-void glc_mask_rects(GLCCtx glc, int num_rect, GLCRect *rects, GLCMaskID id);
-void glc_clear_mask(GLCCtx glc, GLCMaskID id);
-
-typedef enum {
- GLC_CLIP_OP_SET,
- GLC_CLIP_OP_OR,
- GLC_CLIP_OP_AND,
- GLC_CLIP_OP_EXCLUDE,
-} GLCClipOp;
-
-void glc_clip_rect(GLCCtx glc, const GLCRect *rect, GLCClipOp op);
-void glc_clip_path(GLCCtx glc, GLCPath path, GLCClipOp op);
-void glc_clip_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *bitmap, GLCClipOp op);
-void glc_clip_reset(GLCCtx glc);
-
-void glc_fill_rect(GLCCtx glc, const GLCRect *rect);
-void glc_fill_path(GLCCtx glc, GLCPath path);
-void _glc_fill_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *bitmap);
-void glc_fill_alpha(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride,
- const uint8_t *alpha_mask);
-
-void glc_stroke_rect(GLCCtx glc, const GLCRect *rect);
-void glc_stroke_path(GLCCtx glc, GLCPath path);
-
-void glc_draw_image(GLCCtx glc, const GLCRecti *dest, const GLCRecti *src, const GLCImage *image,
- int scale_mode, double alpha);
-
-void glc_copy_pixels(GLCCtx glc, int x_dest, int y_dest, int x_src, int y_src, int width,
- int height);
-void glc_read_pixels(GLCCtx glc, int x, int y, GLCImage *image);
-
-void glc_flush(GLCCtx glc);
-void glc_clear(GLCCtx glc);
-GLCCtx glc_create(int width, int height);
-void glc_destroy(GLCCtx glc, int textures_lost);
-
-#endif
diff --git a/common/lines.c b/common/lines.c
deleted file mode 100644
index ee52a46..0000000
--- a/common/lines.c
+++ /dev/null
@@ -1,3618 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/***********************************************************
-
-Copyright 1989, 1998 The Open Group
-
-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.
-
-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
-OPEN GROUP 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 name of The Open Group 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 Open Group.
-
-
-Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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.
-
-******************************************************************/
-
-
-#include <stdio.h>
-#include <spice/macros.h>
-#ifdef _XOPEN_SOURCE
-#include <math.h>
-#else
-#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
-#include <math.h>
-#undef _XOPEN_SOURCE
-#endif
-#include "lines.h"
-#include "mem.h"
-
-#define xalloc(i) spice_malloc(i)
-#define xrealloc(a,b) spice_realloc(a,b)
-#define xfree(i) free(i)
-
-typedef unsigned int CARD32;
-typedef int Boolean;
-typedef pixman_rectangle32_t xRectangle;
-typedef SpicePoint DDXPointRec;
-typedef DDXPointRec *DDXPointPtr;
-typedef struct lineGC *GCPtr;
-
-/* largest positive value that can fit into a component of a point.
- * Assumes that the point structure is {type x, y;} where type is
- * a signed type.
- */
-#define MAX_COORDINATE 2147483647
-#define MIN_COORDINATE -2147483647
-
-#define miZeroLine spice_canvas_zero_line
-#define miZeroDashLine spice_canvas_zero_dash_line
-#define miWideDash spice_canvas_wide_dash_line
-#define miWideLine spice_canvas_wide_line
-
-static inline int
-ICEIL (double x)
-{
- int _cTmp = (int)x;
- return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp + 1;
-}
-
-typedef struct {
- int count; /* number of spans */
- DDXPointPtr points; /* pointer to list of start points */
- int *widths; /* pointer to list of widths */
-} Spans;
-
-typedef struct {
- int size; /* Total number of *Spans allocated */
- int count; /* Number of *Spans actually in group */
- Spans *group; /* List of Spans */
- int ymin, ymax; /* Min, max y values encountered */
-} SpanGroup;
-
-/* Initialize SpanGroup. MUST BE DONE before use. */
-static void miInitSpanGroup (SpanGroup * /*spanGroup */
- );
-
-/* Add a Spans to a SpanGroup. The spans MUST BE in y-sorted order */
-static void miAppendSpans (SpanGroup * /*spanGroup */ ,
- SpanGroup * /*otherGroup */ ,
- Spans * /*spans */
- );
-
-/* Paint a span group, insuring that each pixel is painted at most once */
-static void miFillUniqueSpanGroup (GCPtr /*pGC */ ,
- SpanGroup * /*spanGroup */ ,
- Boolean /* foreground */
- );
-
-/* Free up data in a span group. MUST BE DONE or you'll suffer memory leaks */
-static void miFreeSpanGroup (SpanGroup * /*spanGroup */
- );
-
-/* Rops which must use span groups */
-#define miSpansCarefulRop(rop) (((rop) & 0xc) == 0x8 || ((rop) & 0x3) == 0x2)
-#define miSpansEasyRop(rop) (!miSpansCarefulRop(rop))
-
-/*
- * Public definitions used for configuring basic pixelization aspects
- * of the sample implementation line-drawing routines provided in
- * {mfb,mi,cfb*} at run-time.
- */
-
-#define XDECREASING 4
-#define YDECREASING 2
-#define YMAJOR 1
-
-#define OCTANT1 (1 << (YDECREASING))
-#define OCTANT2 (1 << (YDECREASING|YMAJOR))
-#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR))
-#define OCTANT4 (1 << (XDECREASING|YDECREASING))
-#define OCTANT5 (1 << (XDECREASING))
-#define OCTANT6 (1 << (XDECREASING|YMAJOR))
-#define OCTANT7 (1 << (YMAJOR))
-#define OCTANT8 (1 << (0))
-
-#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8)
-
-#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5)
-
-/*
- * Devices can configure the rendering of routines in mi, mfb, and cfb*
- * by specifying a thin line bias to be applied to a particular screen
- * using the following function. The bias parameter is an OR'ing of
- * the appropriate OCTANT constants defined above to indicate which
- * octants to bias a line to prefer an axial step when the Bresenham
- * error term is exactly zero. The octants are mapped as follows:
- *
- * \ | /
- * \ 3 | 2 /
- * \ | /
- * 4 \ | / 1
- * \|/
- * -----------
- * /|\
- * 5 / | \ 8
- * / | \
- * / 6 | 7 \
- * / | \
- *
- * For more information, see "Ambiguities in Incremental Line Rastering,"
- * Jack E. Bresenham, IEEE CG&A, May 1987.
- */
-
-/*
- * Private definitions needed for drawing thin (zero width) lines
- * Used by the mi, mfb, and all cfb* components.
- */
-
-#define X_AXIS 0
-#define Y_AXIS 1
-
-#define OUT_LEFT 0x08
-#define OUT_RIGHT 0x04
-#define OUT_ABOVE 0x02
-#define OUT_BELOW 0x01
-
-#define OUTCODES(_result, _x, _y, _pbox) \
- if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \
- else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \
- if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \
- else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW;
-
-#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \
-{\
- if (x < xmin) outcode |= OUT_LEFT;\
- if (x > xmax) outcode |= OUT_RIGHT;\
- if (y < ymin) outcode |= OUT_ABOVE;\
- if (y > ymax) outcode |= OUT_BELOW;\
-}
-
-#define SWAPINT(i, j) \
-{ int _t = i; i = j; j = _t; }
-
-#define SWAPPT(i, j) \
-{ DDXPointRec _t; _t = i; i = j; j = _t; }
-
-#define SWAPINT_PAIR(x1, y1, x2, y2)\
-{ int t = x1; x1 = x2; x2 = t;\
- t = y1; y1 = y2; y2 = t;\
-}
-
-#define miGetZeroLineBias(_pScreen) (DEFAULTZEROLINEBIAS)
-
-#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \
- (_octant) = 0; \
- (_sx) = (_SX); \
- if (((_adx) = (_x2) - (_x1)) < 0) { \
- (_adx) = -(_adx); \
- (_sx = -(_sx)); \
- (_octant) |= XDECREASING; \
- } \
- (_sy) = (_SY); \
- if (((_ady) = (_y2) - (_y1)) < 0) { \
- (_ady) = -(_ady); \
- (_sy = -(_sy)); \
- (_octant) |= YDECREASING; \
- }
-
-#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR)
-
-#define FIXUP_ERROR(_e, _octant, _bias) \
- (_e) -= (((_bias) >> (_octant)) & 1)
-
-#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR))
-#define IsYMajorOctant(_octant) ((_octant) & YMAJOR)
-#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING)
-#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING)
-
-static int miZeroClipLine (int /*xmin */ ,
- int /*ymin */ ,
- int /*xmax */ ,
- int /*ymax */ ,
- int * /*new_x1 */ ,
- int * /*new_y1 */ ,
- int * /*new_x2 */ ,
- int * /*new_y2 */ ,
- unsigned int /*adx */ ,
- unsigned int /*ady */ ,
- int * /*pt1_clipped */ ,
- int * /*pt2_clipped */ ,
- int /*octant */ ,
- unsigned int /*bias */ ,
- int /*oc1 */ ,
- int /*oc2 */
- );
-
-/*
- * interface data to span-merging polygon filler
- */
-
-typedef struct _SpanData {
- SpanGroup fgGroup, bgGroup;
-} SpanDataRec, *SpanDataPtr;
-
-#define AppendSpanGroup(pGC, foreground, spanPtr, spanData) { \
- SpanGroup *group, *othergroup = NULL; \
- if (foreground) \
- { \
- group = &spanData->fgGroup; \
- if (pGC->lineStyle == LineDoubleDash) \
- othergroup = &spanData->bgGroup; \
- } \
- else \
- { \
- group = &spanData->bgGroup; \
- othergroup = &spanData->fgGroup; \
- } \
- miAppendSpans (group, othergroup, spanPtr); \
-}
-
-/*
- * Polygon edge description for integer wide-line routines
- */
-
-typedef struct _PolyEdge {
- int height; /* number of scanlines to process */
- int x; /* starting x coordinate */
- int stepx; /* fixed integral dx */
- int signdx; /* variable dx sign */
- int e; /* initial error term */
- int dy;
- int dx;
-} PolyEdgeRec, *PolyEdgePtr;
-
-#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */
-
-/*
- * types for general polygon routines
- */
-
-typedef struct _PolyVertex {
- double x, y;
-} PolyVertexRec, *PolyVertexPtr;
-
-typedef struct _PolySlope {
- int dx, dy;
- double k; /* x0 * dy - y0 * dx */
-} PolySlopeRec, *PolySlopePtr;
-
-/*
- * Line face description for caps/joins
- */
-
-typedef struct _LineFace {
- double xa, ya;
- int dx, dy;
- int x, y;
- double k;
-} LineFaceRec, *LineFacePtr;
-
-/*
- * macros for polygon fillers
- */
-
-#define MIPOLYRELOADLEFT if (!left_height && left_count) { \
- left_height = left->height; \
- left_x = left->x; \
- left_stepx = left->stepx; \
- left_signdx = left->signdx; \
- left_e = left->e; \
- left_dy = left->dy; \
- left_dx = left->dx; \
- --left_count; \
- ++left; \
- }
-
-#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \
- right_height = right->height; \
- right_x = right->x; \
- right_stepx = right->stepx; \
- right_signdx = right->signdx; \
- right_e = right->e; \
- right_dy = right->dy; \
- right_dx = right->dx; \
- --right_count; \
- ++right; \
- }
-
-#define MIPOLYSTEPLEFT left_x += left_stepx; \
- left_e += left_dx; \
- if (left_e > 0) \
- { \
- left_x += left_signdx; \
- left_e -= left_dy; \
- }
-
-#define MIPOLYSTEPRIGHT right_x += right_stepx; \
- right_e += right_dx; \
- if (right_e > 0) \
- { \
- right_x += right_signdx; \
- right_e -= right_dy; \
- }
-
-static void miRoundJoinClip (LineFacePtr /*pLeft */ ,
- LineFacePtr /*pRight */ ,
- PolyEdgePtr /*edge1 */ ,
- PolyEdgePtr /*edge2 */ ,
- int * /*y1 */ ,
- int * /*y2 */ ,
- Boolean * /*left1 */ ,
- Boolean * /*left2 */
- );
-
-static int miRoundCapClip (LineFacePtr /*face */ ,
- Boolean /*isInt */ ,
- PolyEdgePtr /*edge */ ,
- Boolean * /*leftEdge */
- );
-
-static int miPolyBuildEdge (double x0, double y0, double k, int dx, int dy,
- int xi, int yi, int left, PolyEdgePtr edge);
-static int miPolyBuildPoly (PolyVertexPtr vertices, PolySlopePtr slopes,
- int count, int xi, int yi, PolyEdgePtr left,
- PolyEdgePtr right, int *pnleft, int *pnright, int *h);
-
-
-static void
-miStepDash (int dist, /* distance to step */
- int *pDashIndex, /* current dash */
- unsigned char *pDash, /* dash list */
- int numInDashList, /* total length of dash list */
- int *pDashOffset /* offset into current dash */
- )
-{
- int dashIndex, dashOffset;
- int totallen;
- int i;
-
- dashIndex = *pDashIndex;
- dashOffset = *pDashOffset;
- if (dist < pDash[dashIndex] - dashOffset) {
- *pDashOffset = dashOffset + dist;
- return;
- }
- dist -= pDash[dashIndex] - dashOffset;
- if (++dashIndex == numInDashList)
- dashIndex = 0;
- totallen = 0;
- for (i = 0; i < numInDashList; i++)
- totallen += pDash[i];
- if (totallen <= dist)
- dist = dist % totallen;
- while (dist >= pDash[dashIndex]) {
- dist -= pDash[dashIndex];
- if (++dashIndex == numInDashList)
- dashIndex = 0;
- }
- *pDashIndex = dashIndex;
- *pDashOffset = dist;
-}
-
-/*
-
-These routines maintain lists of Spans, in order to implement the
-``touch-each-pixel-once'' rules of wide lines and arcs.
-
-Written by Joel McCormack, Summer 1989.
-
-*/
-
-
-static void
-miInitSpanGroup (SpanGroup * spanGroup)
-{
- spanGroup->size = 0;
- spanGroup->count = 0;
- spanGroup->group = NULL;
- spanGroup->ymin = MAX_COORDINATE;
- spanGroup->ymax = MIN_COORDINATE;
-} /* InitSpanGroup */
-
-#define YMIN(spans) (spans->points[0].y)
-#define YMAX(spans) (spans->points[spans->count-1].y)
-
-static void
-miSubtractSpans (SpanGroup * spanGroup, Spans * sub)
-{
- int i, subCount, spansCount;
- int ymin, ymax, xmin, xmax;
- Spans *spans;
- DDXPointPtr subPt, spansPt;
- int *subWid, *spansWid;
- int extra;
-
- ymin = YMIN (sub);
- ymax = YMAX (sub);
- spans = spanGroup->group;
- for (i = spanGroup->count; i; i--, spans++) {
- if (YMIN (spans) <= ymax && ymin <= YMAX (spans)) {
- subCount = sub->count;
- subPt = sub->points;
- subWid = sub->widths;
- spansCount = spans->count;
- spansPt = spans->points;
- spansWid = spans->widths;
- extra = 0;
- for (;;) {
- while (spansCount && spansPt->y < subPt->y) {
- spansPt++;
- spansWid++;
- spansCount--;
- }
- if (!spansCount)
- break;
- while (subCount && subPt->y < spansPt->y) {
- subPt++;
- subWid++;
- subCount--;
- }
- if (!subCount)
- break;
- if (subPt->y == spansPt->y) {
- xmin = subPt->x;
- xmax = xmin + *subWid;
- if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) {
- ;
- } else if (xmin <= spansPt->x) {
- if (xmax >= spansPt->x + *spansWid) {
- memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1));
- memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1));
- spansPt--;
- spansWid--;
- spans->count--;
- extra++;
- } else {
- *spansWid = *spansWid - (xmax - spansPt->x);
- spansPt->x = xmax;
- }
- } else {
- if (xmax >= spansPt->x + *spansWid) {
- *spansWid = xmin - spansPt->x;
- } else {
- if (!extra) {
- DDXPointPtr newPt;
- int *newwid;
-
-#define EXTRA 8
- newPt =
- (DDXPointPtr) xrealloc (spans->points,
- (spans->count +
- EXTRA) * sizeof (DDXPointRec));
- if (!newPt)
- break;
- spansPt = newPt + (spansPt - spans->points);
- spans->points = newPt;
- newwid =
- (int *) xrealloc (spans->widths,
- (spans->count + EXTRA) * sizeof (int));
- if (!newwid)
- break;
- spansWid = newwid + (spansWid - spans->widths);
- spans->widths = newwid;
- extra = EXTRA;
- }
- memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount));
- memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount));
- spans->count++;
- extra--;
- *spansWid = xmin - spansPt->x;
- spansWid++;
- spansPt++;
- *spansWid = *spansWid - (xmax - spansPt->x);
- spansPt->x = xmax;
- }
- }
- }
- spansPt++;
- spansWid++;
- spansCount--;
- }
- }
- }
-}
-
-static void
-miAppendSpans (SpanGroup * spanGroup, SpanGroup * otherGroup, Spans * spans)
-{
- int ymin, ymax;
- int spansCount;
-
- spansCount = spans->count;
- if (spansCount > 0) {
- if (spanGroup->size == spanGroup->count) {
- spanGroup->size = (spanGroup->size + 8) * 2;
- spanGroup->group = (Spans *)
- xrealloc (spanGroup->group, sizeof (Spans) * spanGroup->size);
- }
-
- spanGroup->group[spanGroup->count] = *spans;
- (spanGroup->count)++;
- ymin = spans->points[0].y;
- if (ymin < spanGroup->ymin)
- spanGroup->ymin = ymin;
- ymax = spans->points[spansCount - 1].y;
- if (ymax > spanGroup->ymax)
- spanGroup->ymax = ymax;
- if (otherGroup && otherGroup->ymin < ymax && ymin < otherGroup->ymax) {
- miSubtractSpans (otherGroup, spans);
- }
- } else {
- xfree (spans->points);
- xfree (spans->widths);
- }
-} /* AppendSpans */
-
-static void
-miFreeSpanGroup (SpanGroup * spanGroup)
-{
- if (spanGroup->group != NULL)
- xfree (spanGroup->group);
-}
-
-static void
-QuickSortSpansX (DDXPointRec points[], int widths[], int numSpans)
-{
- int x;
- int i, j, m;
- DDXPointPtr r;
-
-/* Always called with numSpans > 1 */
-/* Sorts only by x, as all y should be the same */
-
-#define ExchangeSpans(a, b) \
-{ \
- DDXPointRec tpt; \
- int tw; \
- \
- tpt = points[a]; points[a] = points[b]; points[b] = tpt; \
- tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
-}
-
- do {
- if (numSpans < 9) {
- /* Do insertion sort */
- int xprev;
-
- xprev = points[0].x;
- i = 1;
- do { /* while i != numSpans */
- x = points[i].x;
- if (xprev > x) {
- /* points[i] is out of order. Move into proper location. */
- DDXPointRec tpt;
- int tw, k;
-
- for (j = 0; x >= points[j].x; j++) {
- }
- tpt = points[i];
- tw = widths[i];
- for (k = i; k != j; k--) {
- points[k] = points[k - 1];
- widths[k] = widths[k - 1];
- }
- points[j] = tpt;
- widths[j] = tw;
- x = points[i].x;
- } /* if out of order */
- xprev = x;
- i++;
- } while (i != numSpans);
- return;
- }
-
- /* Choose partition element, stick in location 0 */
- m = numSpans / 2;
- if (points[m].x > points[0].x)
- ExchangeSpans (m, 0);
- if (points[m].x > points[numSpans - 1].x)
- ExchangeSpans (m, numSpans - 1);
- if (points[m].x > points[0].x)
- ExchangeSpans (m, 0);
- x = points[0].x;
-
- /* Partition array */
- i = 0;
- j = numSpans;
- do {
- r = &(points[i]);
- do {
- r++;
- i++;
- } while (i != numSpans && r->x < x);
- r = &(points[j]);
- do {
- r--;
- j--;
- } while (x < r->x);
- if (i < j)
- ExchangeSpans (i, j);
- } while (i < j);
-
- /* Move partition element back to middle */
- ExchangeSpans (0, j);
-
- /* Recurse */
- if (numSpans - j - 1 > 1)
- QuickSortSpansX (&points[j + 1], &widths[j + 1], numSpans - j - 1);
- numSpans = j;
- } while (numSpans > 1);
-} /* QuickSortSpans */
-
-
-static int
-UniquifySpansX (Spans * spans, DDXPointRec * newPoints, int *newWidths)
-{
- int newx1, newx2, oldpt, i, y;
- DDXPointRec *oldPoints;
- int *oldWidths;
- int *startNewWidths;
-
-/* Always called with numSpans > 1 */
-/* Uniquify the spans, and stash them into newPoints and newWidths. Return the
- number of unique spans. */
-
-
- startNewWidths = newWidths;
-
- oldPoints = spans->points;
- oldWidths = spans->widths;
-
- y = oldPoints->y;
- newx1 = oldPoints->x;
- newx2 = newx1 + *oldWidths;
-
- for (i = spans->count - 1; i != 0; i--) {
- oldPoints++;
- oldWidths++;
- oldpt = oldPoints->x;
- if (oldpt > newx2) {
- /* Write current span, start a new one */
- newPoints->x = newx1;
- newPoints->y = y;
- *newWidths = newx2 - newx1;
- newPoints++;
- newWidths++;
- newx1 = oldpt;
- newx2 = oldpt + *oldWidths;
- } else {
- /* extend current span, if old extends beyond new */
- oldpt = oldpt + *oldWidths;
- if (oldpt > newx2)
- newx2 = oldpt;
- }
- } /* for */
-
- /* Write final span */
- newPoints->x = newx1;
- *newWidths = newx2 - newx1;
- newPoints->y = y;
-
- return (newWidths - startNewWidths) + 1;
-} /* UniquifySpansX */
-
-static void
-miDisposeSpanGroup (SpanGroup * spanGroup)
-{
- int i;
- Spans *spans;
-
- for (i = 0; i < spanGroup->count; i++) {
- spans = spanGroup->group + i;
- xfree (spans->points);
- xfree (spans->widths);
- }
-}
-
-static void
-miFillUniqueSpanGroup (GCPtr pGC, SpanGroup * spanGroup, Boolean foreground)
-{
- int i;
- Spans *spans;
- Spans *yspans;
- int *ysizes;
- int ymin, ylength;
-
- /* Outgoing spans for one big call to FillSpans */
- DDXPointPtr points;
- int *widths;
- int count;
-
- if (spanGroup->count == 0)
- return;
-
- if (spanGroup->count == 1) {
- /* Already should be sorted, unique */
- spans = spanGroup->group;
- (*pGC->ops->FillSpans)
- (pGC, spans->count, spans->points, spans->widths, TRUE, foreground);
- xfree (spans->points);
- xfree (spans->widths);
- } else {
- /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */
- /* This seems to be the fastest thing to do. I've tried sorting on
- both x and y at the same time rather than creating into all those
- y buckets, but it was somewhat slower. */
-
- ymin = spanGroup->ymin;
- ylength = spanGroup->ymax - ymin + 1;
-
- /* Allocate Spans for y buckets */
- yspans = (Spans*)xalloc (ylength * sizeof (Spans));
- ysizes = (int *)xalloc (ylength * sizeof (int));
-
- if (!yspans || !ysizes) {
- if (yspans)
- xfree (yspans);
- if (ysizes)
- xfree (ysizes);
- miDisposeSpanGroup (spanGroup);
- return;
- }
-
- for (i = 0; i != ylength; i++) {
- ysizes[i] = 0;
- yspans[i].count = 0;
- yspans[i].points = NULL;
- yspans[i].widths = NULL;
- }
-
- /* Go through every single span and put it into the correct bucket */
- count = 0;
- for (i = 0, spans = spanGroup->group; i != spanGroup->count; i++, spans++) {
- int index;
- int j;
-
- for (j = 0, points = spans->points, widths = spans->widths;
- j != spans->count; j++, points++, widths++) {
- index = points->y - ymin;
- if (index >= 0 && index < ylength) {
- Spans *newspans = &(yspans[index]);
- if (newspans->count == ysizes[index]) {
- DDXPointPtr newpoints;
- int *newwidths;
- ysizes[index] = (ysizes[index] + 8) * 2;
- newpoints = (DDXPointPtr) xrealloc (newspans->points,
- ysizes[index] * sizeof (DDXPointRec));
- newwidths = (int *) xrealloc (newspans->widths,
- ysizes[index] * sizeof (int));
- if (!newpoints || !newwidths) {
- int i;
-
- for (i = 0; i < ylength; i++) {
- xfree (yspans[i].points);
- xfree (yspans[i].widths);
- }
- xfree (yspans);
- xfree (ysizes);
- miDisposeSpanGroup (spanGroup);
- return;
- }
- newspans->points = newpoints;
- newspans->widths = newwidths;
- }
- newspans->points[newspans->count] = *points;
- newspans->widths[newspans->count] = *widths;
- (newspans->count)++;
- } /* if y value of span in range */
- } /* for j through spans */
- count += spans->count;
- xfree (spans->points);
- spans->points = NULL;
- xfree (spans->widths);
- spans->widths = NULL;
- } /* for i thorough Spans */
-
- /* Now sort by x and uniquify each bucket into the final array */
- points = (DDXPointRec*)xalloc (count * sizeof (DDXPointRec));
- widths = (int *)xalloc (count * sizeof (int));
- if (!points || !widths) {
- int i;
-
- for (i = 0; i < ylength; i++) {
- xfree (yspans[i].points);
- xfree (yspans[i].widths);
- }
- xfree (yspans);
- xfree (ysizes);
- if (points)
- xfree (points);
- if (widths)
- xfree (widths);
- return;
- }
- count = 0;
- for (i = 0; i != ylength; i++) {
- int ycount = yspans[i].count;
- if (ycount > 0) {
- if (ycount > 1) {
- QuickSortSpansX (yspans[i].points, yspans[i].widths, ycount);
- count += UniquifySpansX (&(yspans[i]), &(points[count]), &(widths[count]));
- } else {
- points[count] = yspans[i].points[0];
- widths[count] = yspans[i].widths[0];
- count++;
- }
- xfree (yspans[i].points);
- xfree (yspans[i].widths);
- }
- }
-
- (*pGC->ops->FillSpans) (pGC, count, points, widths, TRUE, foreground);
- xfree (points);
- xfree (widths);
- xfree (yspans);
- xfree (ysizes); /* use (DE)xalloc for these? */
- }
-
- spanGroup->count = 0;
- spanGroup->ymin = MAX_COORDINATE;
- spanGroup->ymax = MIN_COORDINATE;
-}
-
-/*
-
-The bresenham error equation used in the mi/mfb/cfb line routines is:
-
- e = error
- dx = difference in raw X coordinates
- dy = difference in raw Y coordinates
- M = # of steps in X direction
- N = # of steps in Y direction
- B = 0 to prefer diagonal steps in a given octant,
- 1 to prefer axial steps in a given octant
-
- For X major lines:
- e = 2Mdy - 2Ndx - dx - B
- -2dx <= e < 0
-
- For Y major lines:
- e = 2Ndx - 2Mdy - dy - B
- -2dy <= e < 0
-
-At the start of the line, we have taken 0 X steps and 0 Y steps,
-so M = 0 and N = 0:
-
- X major e = 2Mdy - 2Ndx - dx - B
- = -dx - B
-
- Y major e = 2Ndx - 2Mdy - dy - B
- = -dy - B
-
-At the end of the line, we have taken dx X steps and dy Y steps,
-so M = dx and N = dy:
-
- X major e = 2Mdy - 2Ndx - dx - B
- = 2dxdy - 2dydx - dx - B
- = -dx - B
- Y major e = 2Ndx - 2Mdy - dy - B
- = 2dydx - 2dxdy - dy - B
- = -dy - B
-
-Thus, the error term is the same at the start and end of the line.
-
-Let us consider clipping an X coordinate. There are 4 cases which
-represent the two independent cases of clipping the start vs. the
-end of the line and an X major vs. a Y major line. In any of these
-cases, we know the number of X steps (M) and we wish to find the
-number of Y steps (N). Thus, we will solve our error term equation.
-If we are clipping the start of the line, we will find the smallest
-N that satisfies our error term inequality. If we are clipping the
-end of the line, we will find the largest number of Y steps that
-satisfies the inequality. In that case, since we are representing
-the Y steps as (dy - N), we will actually want to solve for the
-smallest N in that equation.
-
-Case 1: X major, starting X coordinate moved by M steps
-
- -2dx <= 2Mdy - 2Ndx - dx - B < 0
- 2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B
- 2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx
- N <= (2Mdy + dx - B) / 2dx
-
-Since we are trying to find the smallest N that satisfies these
-equations, we should use the > inequality to find the smallest:
-
- N = floor((2Mdy - dx - B) / 2dx) + 1
- = floor((2Mdy - dx - B + 2dx) / 2dx)
- = floor((2Mdy + dx - B) / 2dx)
-
-Case 1b: X major, ending X coordinate moved to M steps
-
-Same derivations as Case 1, but we want the largest N that satisfies
-the equations, so we use the <= inequality:
-
- N = floor((2Mdy + dx - B) / 2dx)
-
-Case 2: X major, ending X coordinate moved by M steps
-
- -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
- -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
- -2dx <= 2Ndx - 2Mdy - dx - B < 0
- 2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B
- 2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx
- N >= (2Mdy - dx + B) / 2dx
-
-Since we are trying to find the highest number of Y steps that
-satisfies these equations, we need to find the smallest N, so
-we should use the >= inequality to find the smallest:
-
- N = ceiling((2Mdy - dx + B) / 2dx)
- = floor((2Mdy - dx + B + 2dx - 1) / 2dx)
- = floor((2Mdy + dx + B - 1) / 2dx)
-
-Case 2b: X major, starting X coordinate moved to M steps from end
-
-Same derivations as Case 2, but we want the smallest number of Y
-steps, so we want the highest N, so we use the < inequality:
-
- N = ceiling((2Mdy + dx + B) / 2dx) - 1
- = floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1
- = floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx)
- = floor((2Mdy + dx + B - 1) / 2dx)
-
-Case 3: Y major, starting X coordinate moved by M steps
-
- -2dy <= 2Ndx - 2Mdy - dy - B < 0
- 2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B
- 2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx
- N >= (2Mdy - dy + B) / 2dx
-
-Since we are trying to find the smallest N that satisfies these
-equations, we should use the >= inequality to find the smallest:
-
- N = ceiling((2Mdy - dy + B) / 2dx)
- = floor((2Mdy - dy + B + 2dx - 1) / 2dx)
- = floor((2Mdy - dy + B - 1) / 2dx) + 1
-
-Case 3b: Y major, ending X coordinate moved to M steps
-
-Same derivations as Case 3, but we want the largest N that satisfies
-the equations, so we use the < inequality:
-
- N = ceiling((2Mdy + dy + B) / 2dx) - 1
- = floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1
- = floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx)
- = floor((2Mdy + dy + B - 1) / 2dx)
-
-Case 4: Y major, ending X coordinate moved by M steps
-
- -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
- -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
- -2dy <= 2Mdy - 2Ndx - dy - B < 0
- 2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B
- 2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx
- N <= (2Mdy + dy - B) / 2dx
-
-Since we are trying to find the highest number of Y steps that
-satisfies these equations, we need to find the smallest N, so
-we should use the > inequality to find the smallest:
-
- N = floor((2Mdy - dy - B) / 2dx) + 1
-
-Case 4b: Y major, starting X coordinate moved to M steps from end
-
-Same analysis as Case 4, but we want the smallest number of Y steps
-which means the largest N, so we use the <= inequality:
-
- N = floor((2Mdy + dy - B) / 2dx)
-
-Now let's try the Y coordinates, we have the same 4 cases.
-
-Case 5: X major, starting Y coordinate moved by N steps
-
- -2dx <= 2Mdy - 2Ndx - dx - B < 0
- 2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B
- 2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy
- M >= (2Ndx - dx + B) / 2dy
-
-Since we are trying to find the smallest M, we use the >= inequality:
-
- M = ceiling((2Ndx - dx + B) / 2dy)
- = floor((2Ndx - dx + B + 2dy - 1) / 2dy)
- = floor((2Ndx - dx + B - 1) / 2dy) + 1
-
-Case 5b: X major, ending Y coordinate moved to N steps
-
-Same derivations as Case 5, but we want the largest M that satisfies
-the equations, so we use the < inequality:
-
- M = ceiling((2Ndx + dx + B) / 2dy) - 1
- = floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1
- = floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy)
- = floor((2Ndx + dx + B - 1) / 2dy)
-
-Case 6: X major, ending Y coordinate moved by N steps
-
- -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
- -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
- -2dx <= 2Ndx - 2Mdy - dx - B < 0
- 2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B
- 2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy
- M <= (2Ndx + dx - B) / 2dy
-
-Largest # of X steps means smallest M, so use the > inequality:
-
- M = floor((2Ndx - dx - B) / 2dy) + 1
-
-Case 6b: X major, starting Y coordinate moved to N steps from end
-
-Same derivations as Case 6, but we want the smallest # of X steps
-which means the largest M, so use the <= inequality:
-
- M = floor((2Ndx + dx - B) / 2dy)
-
-Case 7: Y major, starting Y coordinate moved by N steps
-
- -2dy <= 2Ndx - 2Mdy - dy - B < 0
- 2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B
- 2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy
- M <= (2Ndx + dy - B) / 2dy
-
-To find the smallest M, use the > inequality:
-
- M = floor((2Ndx - dy - B) / 2dy) + 1
- = floor((2Ndx - dy - B + 2dy) / 2dy)
- = floor((2Ndx + dy - B) / 2dy)
-
-Case 7b: Y major, ending Y coordinate moved to N steps
-
-Same derivations as Case 7, but we want the largest M that satisfies
-the equations, so use the <= inequality:
-
- M = floor((2Ndx + dy - B) / 2dy)
-
-Case 8: Y major, ending Y coordinate moved by N steps
-
- -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
- -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
- -2dy <= 2Mdy - 2Ndx - dy - B < 0
- 2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B
- 2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy
- M >= (2Ndx - dy + B) / 2dy
-
-To find the highest X steps, find the smallest M, use the >= inequality:
-
- M = ceiling((2Ndx - dy + B) / 2dy)
- = floor((2Ndx - dy + B + 2dy - 1) / 2dy)
- = floor((2Ndx + dy + B - 1) / 2dy)
-
-Case 8b: Y major, starting Y coordinate moved to N steps from the end
-
-Same derivations as Case 8, but we want to find the smallest # of X
-steps which means the largest M, so we use the < inequality:
-
- M = ceiling((2Ndx + dy + B) / 2dy) - 1
- = floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1
- = floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy)
- = floor((2Ndx + dy + B - 1) / 2dy)
-
-So, our equations are:
-
- 1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx)
- 1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx)
- 2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx)
- 2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx)
-
- 3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1
- 3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx)
- 4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1
- 4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx)
-
- 5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1
- 5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy)
- 6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1
- 6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy)
-
- 7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy)
- 7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy)
- 8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy)
- 8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy)
-
-We have the following constraints on all of the above terms:
-
- 0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine
- 0 <= dx/dy <= 2^16 - 1
- 0 <= B <= 1
-
-The floor in all of the above equations can be accomplished with a
-simple C divide operation provided that both numerator and denominator
-are positive.
-
-Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0
-and moving a Y coordinate implies dy != 0, we know that the denominators
-are all > 0.
-
-For all lines, (-B) and (B-1) are both either 0 or -1, depending on the
-bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1
-or > 0 to prove that the numerators are positive (or zero).
-
-For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the
-constraints, the first four equations all have numerators >= 0.
-
-For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy
-So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy
-or (2Mdy + dy) > 0. So all of their numerators are >= 0.
-
-For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx)
->= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0.
-
-For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators
-are > 0.
-
-To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This
-is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1)
- <= 2^16 * (2^16 - 1) + (2^16 - 1)
- <= 2^32 - 2^16 + 2^16 - 1
- <= 2^32 - 1
-Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of
-the numerator is therefore (2^32 - 1), which does not overflow an unsigned
-32 bit variable.
-
-*/
-
-/* Bit codes for the terms of the 16 clipping equations defined below. */
-
-#define T_2NDX (1 << 0)
-#define T_2MDY (0) /* implicit term */
-#define T_DXNOTY (1 << 1)
-#define T_DYNOTX (0) /* implicit term */
-#define T_SUBDXORY (1 << 2)
-#define T_ADDDX (T_DXNOTY) /* composite term */
-#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */
-#define T_ADDDY (T_DYNOTX) /* composite term */
-#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */
-#define T_BIASSUBONE (1 << 3)
-#define T_SUBBIAS (0) /* implicit term */
-#define T_DIV2DX (1 << 4)
-#define T_DIV2DY (0) /* implicit term */
-#define T_ADDONE (1 << 5)
-
-/* Bit masks defining the 16 equations used in miZeroClipLine. */
-
-#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX)
-#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX)
-#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
-#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
-
-#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE)
-#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX)
-#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE)
-#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX)
-
-#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE)
-#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY)
-#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE)
-#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY)
-
-#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY)
-#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY)
-#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
-#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
-
-/* miZeroClipLine
- *
- * returns: 1 for partially clipped line
- * -1 for completely clipped line
- *
- */
-static int
-miZeroClipLine (int xmin, int ymin, int xmax, int ymax,
- int *new_x1, int *new_y1, int *new_x2, int *new_y2,
- unsigned int adx, unsigned int ady,
- int *pt1_clipped, int *pt2_clipped, int octant, unsigned int bias, int oc1, int oc2)
-{
- int swapped = 0;
- int clipDone = 0;
- CARD32 utmp = 0;
- int clip1, clip2;
- int x1, y1, x2, y2;
- int x1_orig, y1_orig, x2_orig, y2_orig;
- int xmajor;
- int negslope = 0, anchorval = 0;
- unsigned int eqn = 0;
-
- x1 = x1_orig = *new_x1;
- y1 = y1_orig = *new_y1;
- x2 = x2_orig = *new_x2;
- y2 = y2_orig = *new_y2;
-
- clip1 = 0;
- clip2 = 0;
-
- xmajor = IsXMajorOctant (octant);
- bias = ((bias >> octant) & 1);
-
- while (1) {
- if ((oc1 & oc2) != 0) { /* trivial reject */
- clipDone = -1;
- clip1 = oc1;
- clip2 = oc2;
- break;
- } else if ((oc1 | oc2) == 0) { /* trivial accept */
- clipDone = 1;
- if (swapped) {
- SWAPINT_PAIR (x1, y1, x2, y2);
- SWAPINT (clip1, clip2);
- }
- break;
- } else { /* have to clip */
-
- /* only clip one point at a time */
- if (oc1 == 0) {
- SWAPINT_PAIR (x1, y1, x2, y2);
- SWAPINT_PAIR (x1_orig, y1_orig, x2_orig, y2_orig);
- SWAPINT (oc1, oc2);
- SWAPINT (clip1, clip2);
- swapped = !swapped;
- }
-
- clip1 |= oc1;
- if (oc1 & OUT_LEFT) {
- negslope = IsYDecreasingOctant (octant);
- utmp = xmin - x1_orig;
- if (utmp <= 32767) { /* clip based on near endpt */
- if (xmajor)
- eqn = (swapped) ? EQN2 : EQN1;
- else
- eqn = (swapped) ? EQN4 : EQN3;
- anchorval = y1_orig;
- } else { /* clip based on far endpt */
-
- utmp = x2_orig - xmin;
- if (xmajor)
- eqn = (swapped) ? EQN1B : EQN2B;
- else
- eqn = (swapped) ? EQN3B : EQN4B;
- anchorval = y2_orig;
- negslope = !negslope;
- }
- x1 = xmin;
- } else if (oc1 & OUT_ABOVE) {
- negslope = IsXDecreasingOctant (octant);
- utmp = ymin - y1_orig;
- if (utmp <= 32767) { /* clip based on near endpt */
- if (xmajor)
- eqn = (swapped) ? EQN6 : EQN5;
- else
- eqn = (swapped) ? EQN8 : EQN7;
- anchorval = x1_orig;
- } else { /* clip based on far endpt */
-
- utmp = y2_orig - ymin;
- if (xmajor)
- eqn = (swapped) ? EQN5B : EQN6B;
- else
- eqn = (swapped) ? EQN7B : EQN8B;
- anchorval = x2_orig;
- negslope = !negslope;
- }
- y1 = ymin;
- } else if (oc1 & OUT_RIGHT) {
- negslope = IsYDecreasingOctant (octant);
- utmp = x1_orig - xmax;
- if (utmp <= 32767) { /* clip based on near endpt */
- if (xmajor)
- eqn = (swapped) ? EQN2 : EQN1;
- else
- eqn = (swapped) ? EQN4 : EQN3;
- anchorval = y1_orig;
- } else { /* clip based on far endpt */
-
- /*
- * Technically since the equations can handle
- * utmp == 32768, this overflow code isn't
- * needed since X11 protocol can't generate
- * a line which goes more than 32768 pixels
- * to the right of a clip rectangle.
- */
- utmp = xmax - x2_orig;
- if (xmajor)
- eqn = (swapped) ? EQN1B : EQN2B;
- else
- eqn = (swapped) ? EQN3B : EQN4B;
- anchorval = y2_orig;
- negslope = !negslope;
- }
- x1 = xmax;
- } else if (oc1 & OUT_BELOW) {
- negslope = IsXDecreasingOctant (octant);
- utmp = y1_orig - ymax;
- if (utmp <= 32767) { /* clip based on near endpt */
- if (xmajor)
- eqn = (swapped) ? EQN6 : EQN5;
- else
- eqn = (swapped) ? EQN8 : EQN7;
- anchorval = x1_orig;
- } else { /* clip based on far endpt */
-
- /*
- * Technically since the equations can handle
- * utmp == 32768, this overflow code isn't
- * needed since X11 protocol can't generate
- * a line which goes more than 32768 pixels
- * below the bottom of a clip rectangle.
- */
- utmp = ymax - y2_orig;
- if (xmajor)
- eqn = (swapped) ? EQN5B : EQN6B;
- else
- eqn = (swapped) ? EQN7B : EQN8B;
- anchorval = x2_orig;
- negslope = !negslope;
- }
- y1 = ymax;
- }
-
- if (swapped)
- negslope = !negslope;
-
- utmp <<= 1; /* utmp = 2N or 2M */
- if (eqn & T_2NDX)
- utmp = (utmp * adx);
- else /* (eqn & T_2MDY) */
- utmp = (utmp * ady);
- if (eqn & T_DXNOTY)
- if (eqn & T_SUBDXORY)
- utmp -= adx;
- else
- utmp += adx;
- else /* (eqn & T_DYNOTX) */ if (eqn & T_SUBDXORY)
- utmp -= ady;
- else
- utmp += ady;
- if (eqn & T_BIASSUBONE)
- utmp += bias - 1;
- else /* (eqn & T_SUBBIAS) */
- utmp -= bias;
- if (eqn & T_DIV2DX)
- utmp /= (adx << 1);
- else /* (eqn & T_DIV2DY) */
- utmp /= (ady << 1);
- if (eqn & T_ADDONE)
- utmp++;
-
- if (negslope)
- utmp = (uint32_t)(-(int32_t)utmp);
-
- if (eqn & T_2NDX) /* We are calculating X steps */
- x1 = anchorval + utmp;
- else /* else, Y steps */
- y1 = anchorval + utmp;
-
- oc1 = 0;
- MIOUTCODES (oc1, x1, y1, xmin, ymin, xmax, ymax);
- }
- }
-
- *new_x1 = x1;
- *new_y1 = y1;
- *new_x2 = x2;
- *new_y2 = y2;
-
- *pt1_clipped = clip1;
- *pt2_clipped = clip2;
-
- return clipDone;
-}
-
-/* Draw lineSolid, fillStyle-independent zero width lines.
- *
- * Must keep X and Y coordinates in "ints" at least until after they're
- * translated and clipped to accomodate CoordModePrevious lines with very
- * large coordinates.
- *
- * Draws the same pixels regardless of sign(dx) or sign(dy).
- *
- * Ken Whaley
- *
- */
-
-#define MI_OUTPUT_POINT(xx, yy)\
-{\
- if ( !new_span && yy == current_y)\
- {\
- if (xx < spans->x)\
- spans->x = xx;\
- ++*widths;\
- }\
- else\
- {\
- ++Nspans;\
- ++spans;\
- ++widths;\
- spans->x = xx;\
- spans->y = yy;\
- *widths = 1;\
- current_y = yy;\
- new_span = FALSE;\
- }\
-}
-
-void
-miZeroLine (GCPtr pGC, int mode, /* Origin or Previous */
- int npt, /* number of points */
- DDXPointPtr pptInit)
-{
- int Nspans, current_y = 0;
- DDXPointPtr ppt;
- DDXPointPtr pspanInit, spans;
- int *pwidthInit, *widths, list_len;
- int xleft, ytop, xright, ybottom;
- int new_x1, new_y1, new_x2, new_y2;
- int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
- int oc1, oc2;
- int result;
- int pt1_clipped, pt2_clipped = 0;
- Boolean new_span;
- int signdx, signdy;
- int clipdx, clipdy;
- int width, height;
- int adx, ady;
- int octant;
- unsigned int bias = miGetZeroLineBias (screen);
- int e, e1, e2, e3; /* Bresenham error terms */
- int length; /* length of lines == # of pixels on major axis */
-
- xleft = 0;
- ytop = 0;
- xright = pGC->width - 1;
- ybottom = pGC->height - 1;
-
- /* it doesn't matter whether we're in drawable or screen coordinates,
- * FillSpans simply cannot take starting coordinates outside of the
- * range of a DDXPointRec component.
- */
- if (xright > MAX_COORDINATE)
- xright = MAX_COORDINATE;
- if (ybottom > MAX_COORDINATE)
- ybottom = MAX_COORDINATE;
-
- /* since we're clipping to the drawable's boundaries & coordinate
- * space boundaries, we're guaranteed that the larger of width/height
- * is the longest span we'll need to output
- */
- width = xright - xleft + 1;
- height = ybottom - ytop + 1;
- list_len = (height >= width) ? height : width;
- pspanInit = (DDXPointRec *)xalloc (list_len * sizeof (DDXPointRec));
- pwidthInit = (int *)xalloc (list_len * sizeof (int));
- if (!pspanInit || !pwidthInit)
- return;
-
- Nspans = 0;
- new_span = TRUE;
- spans = pspanInit - 1;
- widths = pwidthInit - 1;
- ppt = pptInit;
-
- xstart = ppt->x;
- ystart = ppt->y;
-
- /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
- * iteration logic
- */
- x2 = xstart;
- y2 = ystart;
- oc2 = 0;
- MIOUTCODES (oc2, x2, y2, xleft, ytop, xright, ybottom);
-
- while (--npt > 0) {
- if (Nspans > 0)
- (*pGC->ops->FillSpans) (pGC, Nspans, pspanInit, pwidthInit, FALSE, TRUE);
- Nspans = 0;
- new_span = TRUE;
- spans = pspanInit - 1;
- widths = pwidthInit - 1;
-
- x1 = x2;
- y1 = y2;
- oc1 = oc2;
- ++ppt;
-
- x2 = ppt->x;
- y2 = ppt->y;
- if (mode == CoordModePrevious) {
- x2 += x1;
- y2 += y1;
- }
-
- oc2 = 0;
- MIOUTCODES (oc2, x2, y2, xleft, ytop, xright, ybottom);
-
- CalcLineDeltas (x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
-
- if (adx > ady) {
- e1 = ady << 1;
- e2 = e1 - (adx << 1);
- e = e1 - adx;
- length = adx; /* don't draw endpoint in main loop */
-
- FIXUP_ERROR (e, octant, bias);
-
- new_x1 = x1;
- new_y1 = y1;
- new_x2 = x2;
- new_y2 = y2;
- pt1_clipped = 0;
- pt2_clipped = 0;
-
- if ((oc1 | oc2) != 0) {
- result = miZeroClipLine (xleft, ytop, xright, ybottom,
- &new_x1, &new_y1, &new_x2, &new_y2,
- adx, ady,
- &pt1_clipped, &pt2_clipped, octant, bias, oc1, oc2);
- if (result == -1)
- continue;
-
- length = abs (new_x2 - new_x1);
-
- /* if we've clipped the endpoint, always draw the full length
- * of the segment, because then the capstyle doesn't matter
- */
- if (pt2_clipped)
- length++;
-
- if (pt1_clipped) {
- /* must calculate new error terms */
- clipdx = abs (new_x1 - x1);
- clipdy = abs (new_y1 - y1);
- e += (clipdy * e2) + ((clipdx - clipdy) * e1);
- }
- }
-
- /* draw the segment */
-
- x = new_x1;
- y = new_y1;
-
- e3 = e2 - e1;
- e = e - e1;
-
- while (length--) {
- MI_OUTPUT_POINT (x, y);
- e += e1;
- if (e >= 0) {
- y += signdy;
- e += e3;
- }
- x += signdx;
- }
- } else { /* Y major line */
-
- e1 = adx << 1;
- e2 = e1 - (ady << 1);
- e = e1 - ady;
- length = ady; /* don't draw endpoint in main loop */
-
- SetYMajorOctant (octant);
- FIXUP_ERROR (e, octant, bias);
-
- new_x1 = x1;
- new_y1 = y1;
- new_x2 = x2;
- new_y2 = y2;
- pt1_clipped = 0;
- pt2_clipped = 0;
-
- if ((oc1 | oc2) != 0) {
- result = miZeroClipLine (xleft, ytop, xright, ybottom,
- &new_x1, &new_y1, &new_x2, &new_y2,
- adx, ady,
- &pt1_clipped, &pt2_clipped, octant, bias, oc1, oc2);
- if (result == -1)
- continue;
-
- length = abs (new_y2 - new_y1);
-
- /* if we've clipped the endpoint, always draw the full length
- * of the segment, because then the capstyle doesn't matter
- */
- if (pt2_clipped)
- length++;
-
- if (pt1_clipped) {
- /* must calculate new error terms */
- clipdx = abs (new_x1 - x1);
- clipdy = abs (new_y1 - y1);
- e += (clipdx * e2) + ((clipdy - clipdx) * e1);
- }
- }
-
- /* draw the segment */
-
- x = new_x1;
- y = new_y1;
-
- e3 = e2 - e1;
- e = e - e1;
-
- while (length--) {
- MI_OUTPUT_POINT (x, y);
- e += e1;
- if (e >= 0) {
- x += signdx;
- e += e3;
- }
- y += signdy;
- }
- }
- }
-
- /* only do the capnotlast check on the last segment
- * and only if the endpoint wasn't clipped. And then, if the last
- * point is the same as the first point, do not draw it, unless the
- * line is degenerate
- */
- if ((!pt2_clipped) && (pGC->capStyle != CapNotLast) &&
- (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) {
- MI_OUTPUT_POINT (x, y);
- }
-
- if (Nspans > 0)
- (*pGC->ops->FillSpans) (pGC, Nspans, pspanInit, pwidthInit, FALSE, TRUE);
-
- xfree (pwidthInit);
- xfree (pspanInit);
-}
-
-void
-miZeroDashLine (GCPtr pgc, int mode, int nptInit, /* number of points in polyline */
- DDXPointRec * pptInit /* points in the polyline */
- )
-{
- /* XXX kludge until real zero-width dash code is written */
- pgc->lineWidth = 1;
- miWideDash (pgc, mode, nptInit, pptInit);
- pgc->lineWidth = 0;
-}
-
-static void miLineArc (GCPtr pGC,
- Boolean foreground, SpanDataPtr spanData,
- LineFacePtr leftFace,
- LineFacePtr rightFace, double xorg, double yorg, Boolean isInt);
-
-
-/*
- * spans-based polygon filler
- */
-
-static void
-miFillPolyHelper (GCPtr pGC, Boolean foreground,
- SpanDataPtr spanData, int y, int overall_height,
- PolyEdgePtr left, PolyEdgePtr right, int left_count, int right_count)
-{
- int left_x = 0, left_e = 0;
- int left_stepx = 0;
- int left_signdx = 0;
- int left_dy = 0, left_dx = 0;
-
- int right_x = 0, right_e = 0;
- int right_stepx = 0;
- int right_signdx = 0;
- int right_dy = 0, right_dx = 0;
-
- int height = 0;
- int left_height = 0, right_height = 0;
-
- DDXPointPtr ppt;
- DDXPointPtr pptInit = NULL;
- int *pwidth;
- int *pwidthInit = NULL;
- int xorg;
- Spans spanRec;
-
- left_height = 0;
- right_height = 0;
-
- if (!spanData) {
- pptInit = (DDXPointRec *)xalloc (overall_height * sizeof (*ppt));
- if (!pptInit)
- return;
- pwidthInit = (int *)xalloc (overall_height * sizeof (*pwidth));
- if (!pwidthInit) {
- xfree (pptInit);
- return;
- }
- ppt = pptInit;
- pwidth = pwidthInit;
- } else {
- spanRec.points = (DDXPointRec *)xalloc (overall_height * sizeof (*ppt));
- if (!spanRec.points)
- return;
- spanRec.widths = (int *)xalloc (overall_height * sizeof (int));
- if (!spanRec.widths) {
- xfree (spanRec.points);
- return;
- }
- ppt = spanRec.points;
- pwidth = spanRec.widths;
- }
-
- xorg = 0;
- while ((left_count || left_height) && (right_count || right_height)) {
- MIPOLYRELOADLEFT MIPOLYRELOADRIGHT height = left_height;
- if (height > right_height)
- height = right_height;
-
- left_height -= height;
- right_height -= height;
-
- while (--height >= 0) {
- if (right_x >= left_x) {
- ppt->y = y;
- ppt->x = left_x + xorg;
- ppt++;
- *pwidth++ = right_x - left_x + 1;
- }
- y++;
-
- MIPOLYSTEPLEFT MIPOLYSTEPRIGHT}
- }
- if (!spanData) {
- (*pGC->ops->FillSpans) (pGC, ppt - pptInit, pptInit, pwidthInit, TRUE, foreground);
- xfree (pwidthInit);
- xfree (pptInit);
- } else {
- spanRec.count = ppt - spanRec.points;
- AppendSpanGroup (pGC, foreground, &spanRec, spanData)
- }
-}
-
-static void
-miFillRectPolyHelper (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, int x, int y, int w, int h)
-{
- DDXPointPtr ppt;
- int *pwidth;
- Spans spanRec;
- xRectangle rect;
-
- if (!spanData) {
- rect.x = x;
- rect.y = y;
- rect.width = w;
- rect.height = h;
- (*pGC->ops->FillRects) (pGC, 1, &rect, foreground);
- } else {
- spanRec.points = (DDXPointRec *)xalloc (h * sizeof (*ppt));
- if (!spanRec.points)
- return;
- spanRec.widths = (int *)xalloc (h * sizeof (int));
- if (!spanRec.widths) {
- xfree (spanRec.points);
- return;
- }
- ppt = spanRec.points;
- pwidth = spanRec.widths;
-
- while (h--) {
- ppt->x = x;
- ppt->y = y;
- ppt++;
- *pwidth++ = w;
- y++;
- }
- spanRec.count = ppt - spanRec.points;
- AppendSpanGroup (pGC, foreground, &spanRec, spanData)
- }
-}
-
-static int
-miPolyBuildEdge (double x0, double y0, double k, /* x0 * dy - y0 * dx */
- int dx, int dy, int xi, int yi, int left, PolyEdgePtr edge)
-{
- int x, y, e;
- int xady;
-
- if (dy < 0) {
- dy = -dy;
- dx = -dx;
- k = -k;
- }
-#ifdef NOTDEF
- {
- double realk, kerror;
- realk = x0 * dy - y0 * dx;
- kerror = Fabs (realk - k);
- if (kerror > .1)
- printf ("realk: %g k: %g\n", realk, k);
- }
-#endif
- y = ICEIL (y0);
- xady = ICEIL (k) + y * dx;
-
- if (xady <= 0)
- x = -(-xady / dy) - 1;
- else
- x = (xady - 1) / dy;
-
- e = xady - x * dy;
-
- if (dx >= 0) {
- edge->signdx = 1;
- edge->stepx = dx / dy;
- edge->dx = dx % dy;
- } else {
- edge->signdx = -1;
- edge->stepx = -(-dx / dy);
- edge->dx = -dx % dy;
- e = dy - e + 1;
- }
- edge->dy = dy;
- edge->x = x + left + xi;
- edge->e = e - dy; /* bias to compare against 0 instead of dy */
- return y + yi;
-}
-
-#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr)))
-
-static int
-miPolyBuildPoly (PolyVertexPtr vertices,
- PolySlopePtr slopes,
- int count,
- int xi,
- int yi, PolyEdgePtr left, PolyEdgePtr right, int *pnleft, int *pnright, int *h)
-{
- int top, bottom;
- double miny, maxy;
- int i;
- int j;
- int clockwise;
- int slopeoff;
- int s;
- int nright, nleft;
- int y, lasty = 0, bottomy, topy = 0;
-
- /* find the top of the polygon */
- maxy = miny = vertices[0].y;
- bottom = top = 0;
- for (i = 1; i < count; i++) {
- if (vertices[i].y < miny) {
- top = i;
- miny = vertices[i].y;
- }
- if (vertices[i].y >= maxy) {
- bottom = i;
- maxy = vertices[i].y;
- }
- }
- clockwise = 1;
- slopeoff = 0;
-
- i = top;
- j = StepAround (top, -1, count);
-
- if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) {
- clockwise = -1;
- slopeoff = -1;
- }
-
- bottomy = ICEIL (maxy) + yi;
-
- nright = 0;
-
- s = StepAround (top, slopeoff, count);
- i = top;
- while (i != bottom) {
- if (slopes[s].dy != 0) {
- y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
- slopes[s].k,
- slopes[s].dx, slopes[s].dy, xi, yi, 0, &right[nright]);
- if (nright != 0)
- right[nright - 1].height = y - lasty;
- else
- topy = y;
- nright++;
- lasty = y;
- }
-
- i = StepAround (i, clockwise, count);
- s = StepAround (s, clockwise, count);
- }
- if (nright != 0)
- right[nright - 1].height = bottomy - lasty;
-
- if (slopeoff == 0)
- slopeoff = -1;
- else
- slopeoff = 0;
-
- nleft = 0;
- s = StepAround (top, slopeoff, count);
- i = top;
- while (i != bottom) {
- if (slopes[s].dy != 0) {
- y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
- slopes[s].k, slopes[s].dx, slopes[s].dy, xi, yi, 1, &left[nleft]);
-
- if (nleft != 0)
- left[nleft - 1].height = y - lasty;
- nleft++;
- lasty = y;
- }
- i = StepAround (i, -clockwise, count);
- s = StepAround (s, -clockwise, count);
- }
- if (nleft != 0)
- left[nleft - 1].height = bottomy - lasty;
- *pnleft = nleft;
- *pnright = nright;
- *h = bottomy - topy;
- return topy;
-}
-
-static void
-miLineOnePoint (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, int x, int y)
-{
- DDXPointRec pt;
- int wid;
-
- wid = 1;
- pt.x = x;
- pt.y = y;
- (*pGC->ops->FillSpans) (pGC, 1, &pt, &wid, TRUE, foreground);
-}
-
-static void
-miLineJoin (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, LineFacePtr pLeft, LineFacePtr pRight)
-{
- double mx = 0, my = 0;
- double denom = 0.0;
- PolyVertexRec vertices[4];
- PolySlopeRec slopes[4];
- int edgecount;
- PolyEdgeRec left[4], right[4];
- int nleft, nright;
- int y, height;
- int swapslopes;
- int joinStyle = pGC->joinStyle;
- int lw = pGC->lineWidth;
-
- if (lw == 1 && !spanData) {
- /* See if one of the lines will draw the joining pixel */
- if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0))
- return;
- if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0))
- return;
- if (joinStyle != JoinRound) {
- denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy;
- if (denom == 0)
- return; /* no join to draw */
- }
- if (joinStyle != JoinMiter) {
- miLineOnePoint (pGC, foreground, spanData, pLeft->x, pLeft->y);
- return;
- }
- } else {
- if (joinStyle == JoinRound) {
- miLineArc (pGC, foreground, spanData, pLeft, pRight, (double) 0.0, (double) 0.0, TRUE);
- return;
- }
- denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy;
- if (denom == 0.0)
- return; /* no join to draw */
- }
-
- swapslopes = 0;
- if (denom > 0) {
- pLeft->xa = -pLeft->xa;
- pLeft->ya = -pLeft->ya;
- pLeft->dx = -pLeft->dx;
- pLeft->dy = -pLeft->dy;
- } else {
- swapslopes = 1;
- pRight->xa = -pRight->xa;
- pRight->ya = -pRight->ya;
- pRight->dx = -pRight->dx;
- pRight->dy = -pRight->dy;
- }
-
- vertices[0].x = pRight->xa;
- vertices[0].y = pRight->ya;
- slopes[0].dx = -pRight->dy;
- slopes[0].dy = pRight->dx;
- slopes[0].k = 0;
-
- vertices[1].x = 0;
- vertices[1].y = 0;
- slopes[1].dx = pLeft->dy;
- slopes[1].dy = -pLeft->dx;
- slopes[1].k = 0;
-
- vertices[2].x = pLeft->xa;
- vertices[2].y = pLeft->ya;
-
- if (joinStyle == JoinMiter) {
- my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
- pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx)) / denom;
- if (pLeft->dy != 0) {
- mx = pLeft->xa + (my - pLeft->ya) * (double) pLeft->dx / (double) pLeft->dy;
- } else {
- mx = pRight->xa + (my - pRight->ya) * (double) pRight->dx / (double) pRight->dy;
- }
- /* check miter limit */
- if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
- joinStyle = JoinBevel;
- }
-
- if (joinStyle == JoinMiter) {
- slopes[2].dx = pLeft->dx;
- slopes[2].dy = pLeft->dy;
- slopes[2].k = pLeft->k;
- if (swapslopes) {
- slopes[2].dx = -slopes[2].dx;
- slopes[2].dy = -slopes[2].dy;
- slopes[2].k = -slopes[2].k;
- }
- vertices[3].x = mx;
- vertices[3].y = my;
- slopes[3].dx = pRight->dx;
- slopes[3].dy = pRight->dy;
- slopes[3].k = pRight->k;
- if (swapslopes) {
- slopes[3].dx = -slopes[3].dx;
- slopes[3].dy = -slopes[3].dy;
- slopes[3].k = -slopes[3].k;
- }
- edgecount = 4;
- } else {
- double scale, dx, dy, adx, ady;
-
- adx = dx = pRight->xa - pLeft->xa;
- ady = dy = pRight->ya - pLeft->ya;
- if (adx < 0)
- adx = -adx;
- if (ady < 0)
- ady = -ady;
- scale = ady;
- if (adx > ady)
- scale = adx;
- slopes[2].dx = (int) ((dx * 65536) / scale);
- slopes[2].dy = (int) ((dy * 65536) / scale);
- slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
- (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
- edgecount = 3;
- }
-
- y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
- left, right, &nleft, &nright, &height);
- miFillPolyHelper (pGC, foreground, spanData, y, height, left, right, nleft, nright);
-}
-
-static int
-miLineArcI (GCPtr pGC, int xorg, int yorg, DDXPointPtr points, int *widths)
-{
- DDXPointPtr tpts, bpts;
- int *twids, *bwids;
- int x, y, e, ex, slw;
-
- tpts = points;
- twids = widths;
- slw = pGC->lineWidth;
- if (slw == 1) {
- tpts->x = xorg;
- tpts->y = yorg;
- *twids = 1;
- return 1;
- }
- bpts = tpts + slw;
- bwids = twids + slw;
- y = (slw >> 1) + 1;
- if (slw & 1)
- e = -((y << 2) + 3);
- else
- e = -(y << 3);
- ex = -4;
- x = 0;
- while (y) {
- e += (y << 3) - 4;
- while (e >= 0) {
- x++;
- e += (ex = -((x << 3) + 4));
- }
- y--;
- slw = (x << 1) + 1;
- if ((e == ex) && (slw > 1))
- slw--;
- tpts->x = xorg - x;
- tpts->y = yorg - y;
- tpts++;
- *twids++ = slw;
- if ((y != 0) && ((slw > 1) || (e != ex))) {
- bpts--;
- bpts->x = xorg - x;
- bpts->y = yorg + y;
- *--bwids = slw;
- }
- }
- return (pGC->lineWidth);
-}
-
-#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
- if (ybase == edgey) \
- { \
- if (edgeleft) \
- { \
- if (edge->x > xcl) \
- xcl = edge->x; \
- } \
- else \
- { \
- if (edge->x < xcr) \
- xcr = edge->x; \
- } \
- edgey++; \
- edge->x += edge->stepx; \
- edge->e += edge->dx; \
- if (edge->e > 0) \
- { \
- edge->x += edge->signdx; \
- edge->e -= edge->dy; \
- } \
- }
-
-static int
-miLineArcD (GCPtr pGC,
- double xorg,
- double yorg,
- DDXPointPtr points,
- int *widths,
- PolyEdgePtr edge1,
- int edgey1, Boolean edgeleft1, PolyEdgePtr edge2, int edgey2, Boolean edgeleft2)
-{
- DDXPointPtr pts;
- int *wids;
- double radius, x0, y0, el, er, yk, xlk, xrk, k;
- int xbase, ybase, y, boty, xl, xr, xcl, xcr;
- int ymin, ymax;
- Boolean edge1IsMin, edge2IsMin;
- int ymin1, ymin2;
-
- pts = points;
- wids = widths;
- xbase = (int)floor (xorg);
- x0 = xorg - xbase;
- ybase = ICEIL (yorg);
- y0 = yorg - ybase;
- xlk = x0 + x0 + 1.0;
- xrk = x0 + x0 - 1.0;
- yk = y0 + y0 - 1.0;
- radius = ((double) pGC->lineWidth) / 2.0;
- y = (int)floor (radius - y0 + 1.0);
- ybase -= y;
- ymin = ybase;
- ymax = 65536;
- edge1IsMin = FALSE;
- ymin1 = edgey1;
- if (edge1->dy >= 0) {
- if (!edge1->dy) {
- if (edgeleft1)
- edge1IsMin = TRUE;
- else
- ymax = edgey1;
- edgey1 = 65536;
- } else {
- if ((edge1->signdx < 0) == edgeleft1)
- edge1IsMin = TRUE;
- }
- }
- edge2IsMin = FALSE;
- ymin2 = edgey2;
- if (edge2->dy >= 0) {
- if (!edge2->dy) {
- if (edgeleft2)
- edge2IsMin = TRUE;
- else
- ymax = edgey2;
- edgey2 = 65536;
- } else {
- if ((edge2->signdx < 0) == edgeleft2)
- edge2IsMin = TRUE;
- }
- }
- if (edge1IsMin) {
- ymin = ymin1;
- if (edge2IsMin && ymin1 > ymin2)
- ymin = ymin2;
- } else if (edge2IsMin)
- ymin = ymin2;
- el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
- er = el + xrk;
- xl = 1;
- xr = 0;
- if (x0 < 0.5) {
- xl = 0;
- el -= xlk;
- }
- boty = (y0 < -0.5) ? 1 : 0;
- if (ybase + y - boty > ymax)
- boty = ymax - ybase - y;
- while (y > boty) {
- k = (y << 1) + yk;
- er += k;
- while (er > 0.0) {
- xr++;
- er += xrk - (xr << 1);
- }
- el += k;
- while (el >= 0.0) {
- xl--;
- el += (xl << 1) - xlk;
- }
- y--;
- ybase++;
- if (ybase < ymin)
- continue;
- xcl = xl + xbase;
- xcr = xr + xbase;
- CLIPSTEPEDGE (edgey1, edge1, edgeleft1);
- CLIPSTEPEDGE (edgey2, edge2, edgeleft2);
- if (xcr >= xcl) {
- pts->x = xcl;
- pts->y = ybase;
- pts++;
- *wids++ = xcr - xcl + 1;
- }
- }
- er = xrk - (xr << 1) - er;
- el = (xl << 1) - xlk - el;
- boty = (int)floor (-y0 - radius + 1.0);
- if (ybase + y - boty > ymax)
- boty = ymax - ybase - y;
- while (y > boty) {
- k = (y << 1) + yk;
- er -= k;
- while ((er >= 0.0) && (xr >= 0)) {
- xr--;
- er += xrk - (xr << 1);
- }
- el -= k;
- while ((el > 0.0) && (xl <= 0)) {
- xl++;
- el += (xl << 1) - xlk;
- }
- y--;
- ybase++;
- if (ybase < ymin)
- continue;
- xcl = xl + xbase;
- xcr = xr + xbase;
- CLIPSTEPEDGE (edgey1, edge1, edgeleft1);
- CLIPSTEPEDGE (edgey2, edge2, edgeleft2);
- if (xcr >= xcl) {
- pts->x = xcl;
- pts->y = ybase;
- pts++;
- *wids++ = xcr - xcl + 1;
- }
- }
- return (pts - points);
-}
-
-static int
-miRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Boolean * leftEdge)
-{
- int y;
- int dx, dy;
- double xa, ya;
- Boolean left;
-
- dx = -face->dy;
- dy = face->dx;
- xa = face->xa;
- ya = face->ya;
- left = 1;
- if (ya > 0) {
- ya = 0.0;
- xa = 0.0;
- }
- if (dy < 0 || (dy == 0 && dx > 0)) {
- dx = -dx;
- dy = -dy;
- left = !left;
- }
- if (dx == 0 && dy == 0)
- dy = 1;
- if (dy == 0) {
- y = ICEIL (face->ya) + face->y;
- edge->x = -32767;
- edge->stepx = 0;
- edge->signdx = 0;
- edge->e = -1;
- edge->dy = 0;
- edge->dx = 0;
- edge->height = 0;
- } else {
- y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge);
- edge->height = 32767;
- }
- *leftEdge = !left;
- return y;
-}
-
-static void
-miRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight,
- PolyEdgePtr edge1, PolyEdgePtr edge2, int *y1, int *y2, Boolean * left1, Boolean * left2)
-{
- double denom;
-
- denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy;
-
- if (denom >= 0) {
- pLeft->xa = -pLeft->xa;
- pLeft->ya = -pLeft->ya;
- } else {
- pRight->xa = -pRight->xa;
- pRight->ya = -pRight->ya;
- }
- *y1 = miRoundJoinFace (pLeft, edge1, left1);
- *y2 = miRoundJoinFace (pRight, edge2, left2);
-}
-
-static int
-miRoundCapClip (LineFacePtr face, Boolean isInt, PolyEdgePtr edge, Boolean * leftEdge)
-{
- int y;
- int dx, dy;
- double xa, ya, k;
- Boolean left;
-
- dx = -face->dy;
- dy = face->dx;
- xa = face->xa;
- ya = face->ya;
- k = 0.0;
- if (!isInt)
- k = face->k;
- left = 1;
- if (dy < 0 || (dy == 0 && dx > 0)) {
- dx = -dx;
- dy = -dy;
- xa = -xa;
- ya = -ya;
- left = !left;
- }
- if (dx == 0 && dy == 0)
- dy = 1;
- if (dy == 0) {
- y = ICEIL (face->ya) + face->y;
- edge->x = -32767;
- edge->stepx = 0;
- edge->signdx = 0;
- edge->e = -1;
- edge->dy = 0;
- edge->dx = 0;
- edge->height = 0;
- } else {
- y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge);
- edge->height = 32767;
- }
- *leftEdge = !left;
- return y;
-}
-
-static void
-miLineArc (GCPtr pGC,
- Boolean foreground,
- SpanDataPtr spanData,
- LineFacePtr leftFace, LineFacePtr rightFace, double xorg, double yorg, Boolean isInt)
-{
- DDXPointPtr points;
- int *widths;
- int xorgi = 0, yorgi = 0;
- Spans spanRec;
- int n;
- PolyEdgeRec edge1, edge2;
- int edgey1, edgey2;
- Boolean edgeleft1, edgeleft2;
-
- if (isInt) {
- xorgi = leftFace ? leftFace->x : rightFace->x;
- yorgi = leftFace ? leftFace->y : rightFace->y;
- }
- edgey1 = 65536;
- edgey2 = 65536;
- edge1.x = 0; /* not used, keep memory checkers happy */
- edge1.dy = -1;
- edge2.x = 0; /* not used, keep memory checkers happy */
- edge2.dy = -1;
- edgeleft1 = FALSE;
- edgeleft2 = FALSE;
- if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) &&
- ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) ||
- (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) {
- if (isInt) {
- xorg = (double) xorgi;
- yorg = (double) yorgi;
- }
- if (leftFace && rightFace) {
- miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
- &edgey1, &edgey2, &edgeleft1, &edgeleft2);
- } else if (leftFace) {
- edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
- } else if (rightFace) {
- edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
- }
- isInt = FALSE;
- }
- if (!spanData) {
- points = (DDXPointRec *)xalloc (sizeof (DDXPointRec) * pGC->lineWidth);
- if (!points)
- return;
- widths = (int *)xalloc (sizeof (int) * pGC->lineWidth);
- if (!widths) {
- xfree (points);
- return;
- }
- } else {
- points = (DDXPointRec *)xalloc (pGC->lineWidth * sizeof (DDXPointRec));
- if (!points)
- return;
- widths = (int *)xalloc (pGC->lineWidth * sizeof (int));
- if (!widths) {
- xfree (points);
- return;
- }
- spanRec.points = points;
- spanRec.widths = widths;
- }
- if (isInt)
- n = miLineArcI (pGC, xorgi, yorgi, points, widths);
- else
- n = miLineArcD (pGC, xorg, yorg, points, widths,
- &edge1, edgey1, edgeleft1, &edge2, edgey2, edgeleft2);
-
- if (!spanData) {
- (*pGC->ops->FillSpans) (pGC, n, points, widths, TRUE, foreground);
- xfree (widths);
- xfree (points);
- } else {
- spanRec.count = n;
- AppendSpanGroup (pGC, foreground, &spanRec, spanData)
- }
-}
-
-static void
-miLineProjectingCap (GCPtr pGC, Boolean foreground,
- SpanDataPtr spanData, LineFacePtr face, Boolean isLeft,
- double xorg, double yorg, Boolean isInt)
-{
- int xorgi = 0, yorgi = 0;
- int lw;
- PolyEdgeRec lefts[2], rights[2];
- int lefty, righty, topy, bottomy;
- PolyEdgePtr left, right;
- PolyEdgePtr top, bottom;
- double xa, ya;
- double k;
- double xap, yap;
- int dx, dy;
- double projectXoff, projectYoff;
- double maxy;
- int finaly;
-
- if (isInt) {
- xorgi = face->x;
- yorgi = face->y;
- }
- lw = pGC->lineWidth;
- dx = face->dx;
- dy = face->dy;
- k = face->k;
- if (dy == 0) {
- lefts[0].height = lw;
- lefts[0].x = xorgi;
- if (isLeft)
- lefts[0].x -= (lw >> 1);
- lefts[0].stepx = 0;
- lefts[0].signdx = 1;
- lefts[0].e = -lw;
- lefts[0].dx = 0;
- lefts[0].dy = lw;
- rights[0].height = lw;
- rights[0].x = xorgi;
- if (!isLeft)
- rights[0].x += ((lw + 1) >> 1);
- rights[0].stepx = 0;
- rights[0].signdx = 1;
- rights[0].e = -lw;
- rights[0].dx = 0;
- rights[0].dy = lw;
- miFillPolyHelper (pGC, foreground, spanData, yorgi - (lw >> 1), lw, lefts, rights, 1, 1);
- } else if (dx == 0) {
- if (dy < 0) {
- dy = -dy;
- isLeft = !isLeft;
- }
- topy = yorgi;
- bottomy = yorgi + dy;
- if (isLeft)
- topy -= (lw >> 1);
- else
- bottomy += (lw >> 1);
- lefts[0].height = bottomy - topy;
- lefts[0].x = xorgi - (lw >> 1);
- lefts[0].stepx = 0;
- lefts[0].signdx = 1;
- lefts[0].e = -dy;
- lefts[0].dx = dx;
- lefts[0].dy = dy;
-
- rights[0].height = bottomy - topy;
- rights[0].x = lefts[0].x + (lw - 1);
- rights[0].stepx = 0;
- rights[0].signdx = 1;
- rights[0].e = -dy;
- rights[0].dx = dx;
- rights[0].dy = dy;
- miFillPolyHelper (pGC, foreground, spanData, topy, bottomy - topy, lefts, rights, 1, 1);
- } else {
- xa = face->xa;
- ya = face->ya;
- projectXoff = -ya;
- projectYoff = xa;
- if (dx < 0) {
- right = &rights[1];
- left = &lefts[0];
- top = &rights[0];
- bottom = &lefts[1];
- } else {
- right = &rights[0];
- left = &lefts[1];
- top = &lefts[0];
- bottom = &rights[1];
- }
- if (isLeft) {
- righty = miPolyBuildEdge (xa, ya, k, dx, dy, xorgi, yorgi, 0, right);
-
- xa = -xa;
- ya = -ya;
- k = -k;
- lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
- k, dx, dy, xorgi, yorgi, 1, left);
- if (dx > 0) {
- ya = -ya;
- xa = -xa;
- }
- xap = xa - projectXoff;
- yap = ya - projectYoff;
- topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
- -dy, dx, xorgi, yorgi, dx > 0, top);
- bottomy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom);
- maxy = -ya;
- } else {
- righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
- k, dx, dy, xorgi, yorgi, 0, right);
-
- xa = -xa;
- ya = -ya;
- k = -k;
- lefty = miPolyBuildEdge (xa, ya, k, dx, dy, xorgi, yorgi, 1, left);
- if (dx > 0) {
- ya = -ya;
- xa = -xa;
- }
- xap = xa - projectXoff;
- yap = ya - projectYoff;
- topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top);
- bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
- -dy, dx, xorgi, xorgi, dx < 0, bottom);
- maxy = -ya + projectYoff;
- }
- finaly = ICEIL (maxy) + yorgi;
- if (dx < 0) {
- left->height = bottomy - lefty;
- right->height = finaly - righty;
- top->height = righty - topy;
- } else {
- right->height = bottomy - righty;
- left->height = finaly - lefty;
- top->height = lefty - topy;
- }
- bottom->height = finaly - bottomy;
- miFillPolyHelper (pGC, foreground, spanData, topy,
- bottom->height + bottomy - topy, lefts, rights, 2, 2);
- }
-}
-
-static void
-miWideSegment (GCPtr pGC,
- Boolean foreground,
- SpanDataPtr spanData,
- int x1,
- int y1,
- int x2,
- int y2,
- Boolean projectLeft, Boolean projectRight, LineFacePtr leftFace, LineFacePtr rightFace)
-{
- double l, L, r;
- double xa, ya;
- double projectXoff = 0.0, projectYoff = 0.0;
- double k;
- double maxy;
- int x, y;
- int dx, dy;
- int finaly;
- PolyEdgePtr left, right;
- PolyEdgePtr top, bottom;
- int lefty, righty, topy, bottomy;
- int signdx;
- PolyEdgeRec lefts[2], rights[2];
- LineFacePtr tface;
- int lw = pGC->lineWidth;
-
- /* draw top-to-bottom always */
- if (y2 < y1 || (y2 == y1 && x2 < x1)) {
- x = x1;
- x1 = x2;
- x2 = x;
-
- y = y1;
- y1 = y2;
- y2 = y;
-
- x = projectLeft;
- projectLeft = projectRight;
- projectRight = x;
-
- tface = leftFace;
- leftFace = rightFace;
- rightFace = tface;
- }
-
- dy = y2 - y1;
- signdx = 1;
- dx = x2 - x1;
- if (dx < 0)
- signdx = -1;
-
- leftFace->x = x1;
- leftFace->y = y1;
- leftFace->dx = dx;
- leftFace->dy = dy;
-
- rightFace->x = x2;
- rightFace->y = y2;
- rightFace->dx = -dx;
- rightFace->dy = -dy;
-
- if (dy == 0) {
- rightFace->xa = 0;
- rightFace->ya = (double) lw / 2.0;
- rightFace->k = -(double) (lw * dx) / 2.0;
- leftFace->xa = 0;
- leftFace->ya = -rightFace->ya;
- leftFace->k = rightFace->k;
- x = x1;
- if (projectLeft)
- x -= (lw >> 1);
- y = y1 - (lw >> 1);
- dx = x2 - x;
- if (projectRight)
- dx += ((lw + 1) >> 1);
- dy = lw;
- miFillRectPolyHelper (pGC, foreground, spanData, x, y, dx, dy);
- } else if (dx == 0) {
- leftFace->xa = (double) lw / 2.0;
- leftFace->ya = 0;
- leftFace->k = (double) (lw * dy) / 2.0;
- rightFace->xa = -leftFace->xa;
- rightFace->ya = 0;
- rightFace->k = leftFace->k;
- y = y1;
- if (projectLeft)
- y -= lw >> 1;
- x = x1 - (lw >> 1);
- dy = y2 - y;
- if (projectRight)
- dy += ((lw + 1) >> 1);
- dx = lw;
- miFillRectPolyHelper (pGC, foreground, spanData, x, y, dx, dy);
- } else {
- l = ((double) lw) / 2.0;
- L = hypot ((double) dx, (double) dy);
-
- if (dx < 0) {
- right = &rights[1];
- left = &lefts[0];
- top = &rights[0];
- bottom = &lefts[1];
- } else {
- right = &rights[0];
- left = &lefts[1];
- top = &lefts[0];
- bottom = &rights[1];
- }
- r = l / L;
-
- /* coord of upper bound at integral y */
- ya = -r * dx;
- xa = r * dy;
-
- if (projectLeft | projectRight) {
- projectXoff = -ya;
- projectYoff = xa;
- }
-
- /* xa * dy - ya * dx */
- k = l * L;
-
- leftFace->xa = xa;
- leftFace->ya = ya;
- leftFace->k = k;
- rightFace->xa = -xa;
- rightFace->ya = -ya;
- rightFace->k = k;
-
- if (projectLeft)
- righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
- k, dx, dy, x1, y1, 0, right);
- else
- righty = miPolyBuildEdge (xa, ya, k, dx, dy, x1, y1, 0, right);
-
- /* coord of lower bound at integral y */
- ya = -ya;
- xa = -xa;
-
- /* xa * dy - ya * dx */
- k = -k;
-
- if (projectLeft)
- lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
- k, dx, dy, x1, y1, 1, left);
- else
- lefty = miPolyBuildEdge (xa, ya, k, dx, dy, x1, y1, 1, left);
-
- /* coord of top face at integral y */
-
- if (signdx > 0) {
- ya = -ya;
- xa = -xa;
- }
-
- if (projectLeft) {
- double xap = xa - projectXoff;
- double yap = ya - projectYoff;
- topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, -dy, dx, x1, y1, dx > 0, top);
- } else
- topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top);
-
- /* coord of bottom face at integral y */
-
- if (projectRight) {
- double xap = xa + projectXoff;
- double yap = ya + projectYoff;
- bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
- -dy, dx, x2, y2, dx < 0, bottom);
- maxy = -ya + projectYoff;
- } else {
- bottomy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x2, y2, dx < 0, bottom);
- maxy = -ya;
- }
-
- finaly = ICEIL (maxy) + y2;
-
- if (dx < 0) {
- left->height = bottomy - lefty;
- right->height = finaly - righty;
- top->height = righty - topy;
- } else {
- right->height = bottomy - righty;
- left->height = finaly - lefty;
- top->height = lefty - topy;
- }
- bottom->height = finaly - bottomy;
- miFillPolyHelper (pGC, foreground, spanData, topy,
- bottom->height + bottomy - topy, lefts, rights, 2, 2);
- }
-}
-
-static SpanDataPtr
-miSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt)
-{
- if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop (pGC->alu))
- return (SpanDataPtr) NULL;
- if (pGC->lineStyle == LineDoubleDash)
- miInitSpanGroup (&spanData->bgGroup);
- miInitSpanGroup (&spanData->fgGroup);
- return spanData;
-}
-
-static void
-miCleanupSpanData (GCPtr pGC, SpanDataPtr spanData)
-{
- if (pGC->lineStyle == LineDoubleDash) {
- miFillUniqueSpanGroup (pGC, &spanData->bgGroup, FALSE);
- miFreeSpanGroup (&spanData->bgGroup);
- }
- miFillUniqueSpanGroup (pGC, &spanData->fgGroup, TRUE);
- miFreeSpanGroup (&spanData->fgGroup);
-}
-
-void
-miWideLine (GCPtr pGC, int mode, int npt, DDXPointPtr pPts)
-{
- int x1, y1, x2, y2;
- SpanDataRec spanDataRec;
- SpanDataPtr spanData;
- Boolean projectLeft, projectRight;
- LineFaceRec leftFace, rightFace, prevRightFace;
- LineFaceRec firstFace;
- int first;
- Boolean somethingDrawn = FALSE;
- Boolean selfJoin;
-
- spanData = miSetupSpanData (pGC, &spanDataRec, npt);
- x2 = pPts->x;
- y2 = pPts->y;
- first = TRUE;
- selfJoin = FALSE;
- if (npt > 1) {
- if (mode == CoordModePrevious) {
- int nptTmp;
- DDXPointPtr pPtsTmp;
-
- x1 = x2;
- y1 = y2;
- nptTmp = npt;
- pPtsTmp = pPts + 1;
- while (--nptTmp) {
- x1 += pPtsTmp->x;
- y1 += pPtsTmp->y;
- ++pPtsTmp;
- }
- if (x2 == x1 && y2 == y1)
- selfJoin = TRUE;
- } else if (x2 == pPts[npt - 1].x && y2 == pPts[npt - 1].y) {
- selfJoin = TRUE;
- }
- }
- projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
- projectRight = FALSE;
- while (--npt) {
- x1 = x2;
- y1 = y2;
- ++pPts;
- x2 = pPts->x;
- y2 = pPts->y;
- if (mode == CoordModePrevious) {
- x2 += x1;
- y2 += y1;
- }
- if (x1 != x2 || y1 != y2) {
- somethingDrawn = TRUE;
- if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin)
- projectRight = TRUE;
- miWideSegment (pGC, TRUE, spanData, x1, y1, x2, y2,
- projectLeft, projectRight, &leftFace, &rightFace);
- if (first) {
- if (selfJoin)
- firstFace = leftFace;
- else if (pGC->capStyle == CapRound) {
- if (pGC->lineWidth == 1 && !spanData)
- miLineOnePoint (pGC, TRUE, spanData, x1, y1);
- else
- miLineArc (pGC, TRUE, spanData,
- &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE);
- }
- } else {
- miLineJoin (pGC, TRUE, spanData, &leftFace, &prevRightFace);
- }
- prevRightFace = rightFace;
- first = FALSE;
- projectLeft = FALSE;
- }
- if (npt == 1 && somethingDrawn) {
- if (selfJoin)
- miLineJoin (pGC, TRUE, spanData, &firstFace, &rightFace);
- else if (pGC->capStyle == CapRound) {
- if (pGC->lineWidth == 1 && !spanData)
- miLineOnePoint (pGC, TRUE, spanData, x2, y2);
- else
- miLineArc (pGC, TRUE, spanData,
- (LineFacePtr) NULL, &rightFace, (double) 0.0, (double) 0.0, TRUE);
- }
- }
- }
- /* handle crock where all points are coincedent */
- if (!somethingDrawn) {
- projectLeft = pGC->capStyle == CapProjecting;
- miWideSegment (pGC, TRUE, spanData,
- x2, y2, x2, y2, projectLeft, projectLeft, &leftFace, &rightFace);
- if (pGC->capStyle == CapRound) {
- miLineArc (pGC, TRUE, spanData,
- &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE);
- rightFace.dx = -1; /* sleezy hack to make it work */
- miLineArc (pGC, TRUE, spanData,
- (LineFacePtr) NULL, &rightFace, (double) 0.0, (double) 0.0, TRUE);
- }
- }
- if (spanData)
- miCleanupSpanData (pGC, spanData);
-}
-
-#define V_TOP 0
-#define V_RIGHT 1
-#define V_BOTTOM 2
-#define V_LEFT 3
-
-static void
-miWideDashSegment (GCPtr pGC,
- SpanDataPtr spanData,
- int *pDashOffset,
- int *pDashIndex,
- int x1,
- int y1,
- int x2,
- int y2,
- Boolean projectLeft, Boolean projectRight, LineFacePtr leftFace, LineFacePtr rightFace)
-{
- int dashIndex, dashRemain;
- unsigned char *pDash;
- double L, l;
- double k;
- PolyVertexRec vertices[4];
- PolyVertexRec saveRight = { 0 }, saveBottom;
- PolySlopeRec slopes[4];
- PolyEdgeRec left[2], right[2];
- LineFaceRec lcapFace, rcapFace;
- int nleft, nright;
- int h;
- int y;
- int dy, dx;
- Boolean foreground;
- double LRemain;
- double r;
- double rdx, rdy;
- double dashDx, dashDy;
- double saveK = 0.0;
- Boolean first = TRUE;
- double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0;
-
- dx = x2 - x1;
- dy = y2 - y1;
- dashIndex = *pDashIndex;
- pDash = pGC->dash;
- dashRemain = pDash[dashIndex] - *pDashOffset;
-
- l = ((double) pGC->lineWidth) / 2.0;
- if (dx == 0) {
- L = dy;
- rdx = 0;
- rdy = l;
- if (dy < 0) {
- L = -dy;
- rdy = -l;
- }
- } else if (dy == 0) {
- L = dx;
- rdx = l;
- rdy = 0;
- if (dx < 0) {
- L = -dx;
- rdx = -l;
- }
- } else {
- L = hypot ((double) dx, (double) dy);
- r = l / L;
-
- rdx = r * dx;
- rdy = r * dy;
- }
- k = l * L;
- LRemain = L;
- /* All position comments are relative to a line with dx and dy > 0,
- * but the code does not depend on this */
- /* top */
- slopes[V_TOP].dx = dx;
- slopes[V_TOP].dy = dy;
- slopes[V_TOP].k = k;
- /* right */
- slopes[V_RIGHT].dx = -dy;
- slopes[V_RIGHT].dy = dx;
- slopes[V_RIGHT].k = 0;
- /* bottom */
- slopes[V_BOTTOM].dx = -dx;
- slopes[V_BOTTOM].dy = -dy;
- slopes[V_BOTTOM].k = k;
- /* left */
- slopes[V_LEFT].dx = dy;
- slopes[V_LEFT].dy = -dx;
- slopes[V_LEFT].k = 0;
-
- /* preload the start coordinates */
- vertices[V_RIGHT].x = vertices[V_TOP].x = rdy;
- vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx;
-
- vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy;
- vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx;
-
- if (projectLeft) {
- vertices[V_TOP].x -= rdx;
- vertices[V_TOP].y -= rdy;
-
- vertices[V_LEFT].x -= rdx;
- vertices[V_LEFT].y -= rdy;
-
- slopes[V_LEFT].k = rdx * dx + rdy * dy;
- }
-
- lcenterx = x1;
- lcentery = y1;
-
- if (pGC->capStyle == CapRound) {
- lcapFace.dx = dx;
- lcapFace.dy = dy;
- lcapFace.x = x1;
- lcapFace.y = y1;
-
- rcapFace.dx = -dx;
- rcapFace.dy = -dy;
- rcapFace.x = x1;
- rcapFace.y = y1;
- }
- while (LRemain > dashRemain) {
- dashDx = (dashRemain * dx) / L;
- dashDy = (dashRemain * dy) / L;
-
- rcenterx = lcenterx + dashDx;
- rcentery = lcentery + dashDy;
-
- vertices[V_RIGHT].x += dashDx;
- vertices[V_RIGHT].y += dashDy;
-
- vertices[V_BOTTOM].x += dashDx;
- vertices[V_BOTTOM].y += dashDy;
-
- slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy;
-
- if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) {
- if (pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapProjecting) {
- saveRight = vertices[V_RIGHT];
- saveBottom = vertices[V_BOTTOM];
- saveK = slopes[V_RIGHT].k;
-
- if (!first) {
- vertices[V_TOP].x -= rdx;
- vertices[V_TOP].y -= rdy;
-
- vertices[V_LEFT].x -= rdx;
- vertices[V_LEFT].y -= rdy;
-
- slopes[V_LEFT].k = vertices[V_LEFT].x *
- slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx;
- }
-
- vertices[V_RIGHT].x += rdx;
- vertices[V_RIGHT].y += rdy;
-
- vertices[V_BOTTOM].x += rdx;
- vertices[V_BOTTOM].y += rdy;
-
- slopes[V_RIGHT].k = vertices[V_RIGHT].x *
- slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx;
- }
- y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, left, right, &nleft, &nright, &h);
- foreground = (dashIndex & 1) == 0;
- miFillPolyHelper (pGC, foreground, spanData, y, h, left, right, nleft, nright);
-
- if (pGC->lineStyle == LineOnOffDash) {
- switch (pGC->capStyle) {
- case CapProjecting:
- vertices[V_BOTTOM] = saveBottom;
- vertices[V_RIGHT] = saveRight;
- slopes[V_RIGHT].k = saveK;
- break;
- case CapRound:
- if (!first) {
- if (dx < 0) {
- lcapFace.xa = -vertices[V_LEFT].x;
- lcapFace.ya = -vertices[V_LEFT].y;
- lcapFace.k = slopes[V_LEFT].k;
- } else {
- lcapFace.xa = vertices[V_TOP].x;
- lcapFace.ya = vertices[V_TOP].y;
- lcapFace.k = -slopes[V_LEFT].k;
- }
- miLineArc (pGC, foreground, spanData,
- &lcapFace, (LineFacePtr) NULL, lcenterx, lcentery, FALSE);
- }
- if (dx < 0) {
- rcapFace.xa = vertices[V_BOTTOM].x;
- rcapFace.ya = vertices[V_BOTTOM].y;
- rcapFace.k = slopes[V_RIGHT].k;
- } else {
- rcapFace.xa = -vertices[V_RIGHT].x;
- rcapFace.ya = -vertices[V_RIGHT].y;
- rcapFace.k = -slopes[V_RIGHT].k;
- }
- miLineArc (pGC, foreground, spanData,
- (LineFacePtr) NULL, &rcapFace, rcenterx, rcentery, FALSE);
- break;
- }
- }
- }
- LRemain -= dashRemain;
- ++dashIndex;
- if (dashIndex == pGC->numInDashList)
- dashIndex = 0;
- dashRemain = pDash[dashIndex];
-
- lcenterx = rcenterx;
- lcentery = rcentery;
-
- vertices[V_TOP] = vertices[V_RIGHT];
- vertices[V_LEFT] = vertices[V_BOTTOM];
- slopes[V_LEFT].k = -slopes[V_RIGHT].k;
- first = FALSE;
- }
-
- if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) {
- vertices[V_TOP].x -= dx;
- vertices[V_TOP].y -= dy;
-
- vertices[V_LEFT].x -= dx;
- vertices[V_LEFT].y -= dy;
-
- vertices[V_RIGHT].x = rdy;
- vertices[V_RIGHT].y = -rdx;
-
- vertices[V_BOTTOM].x = -rdy;
- vertices[V_BOTTOM].y = rdx;
-
-
- if (projectRight) {
- vertices[V_RIGHT].x += rdx;
- vertices[V_RIGHT].y += rdy;
-
- vertices[V_BOTTOM].x += rdx;
- vertices[V_BOTTOM].y += rdy;
- slopes[V_RIGHT].k = vertices[V_RIGHT].x *
- slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx;
- } else
- slopes[V_RIGHT].k = 0;
-
- if (!first && pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapProjecting) {
- vertices[V_TOP].x -= rdx;
- vertices[V_TOP].y -= rdy;
-
- vertices[V_LEFT].x -= rdx;
- vertices[V_LEFT].y -= rdy;
- slopes[V_LEFT].k = vertices[V_LEFT].x *
- slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx;
- } else
- slopes[V_LEFT].k += dx * dx + dy * dy;
-
-
- y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, left, right, &nleft, &nright, &h);
-
- foreground = (dashIndex & 1) == 0;
- miFillPolyHelper (pGC, foreground, spanData, y, h, left, right, nleft, nright);
- if (!first && pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapRound) {
- lcapFace.x = x2;
- lcapFace.y = y2;
- if (dx < 0) {
- lcapFace.xa = -vertices[V_LEFT].x;
- lcapFace.ya = -vertices[V_LEFT].y;
- lcapFace.k = slopes[V_LEFT].k;
- } else {
- lcapFace.xa = vertices[V_TOP].x;
- lcapFace.ya = vertices[V_TOP].y;
- lcapFace.k = -slopes[V_LEFT].k;
- }
- miLineArc (pGC, foreground, spanData,
- &lcapFace, (LineFacePtr) NULL, rcenterx, rcentery, FALSE);
- }
- }
- dashRemain = (int)(((double) dashRemain) - LRemain);
- if (dashRemain == 0) {
- dashIndex++;
- if (dashIndex == pGC->numInDashList)
- dashIndex = 0;
- dashRemain = pDash[dashIndex];
- }
-
- leftFace->x = x1;
- leftFace->y = y1;
- leftFace->dx = dx;
- leftFace->dy = dy;
- leftFace->xa = rdy;
- leftFace->ya = -rdx;
- leftFace->k = k;
-
- rightFace->x = x2;
- rightFace->y = y2;
- rightFace->dx = -dx;
- rightFace->dy = -dy;
- rightFace->xa = -rdy;
- rightFace->ya = rdx;
- rightFace->k = k;
-
- *pDashIndex = dashIndex;
- *pDashOffset = pDash[dashIndex] - dashRemain;
-}
-
-void
-miWideDash (GCPtr pGC, int mode, int npt, DDXPointPtr pPts)
-{
- int x1, y1, x2, y2;
- Boolean foreground;
- Boolean projectLeft, projectRight;
- LineFaceRec leftFace, rightFace, prevRightFace;
- LineFaceRec firstFace;
- int first;
- int dashIndex, dashOffset;
- int prevDashIndex;
- SpanDataRec spanDataRec;
- SpanDataPtr spanData;
- Boolean somethingDrawn = FALSE;
- Boolean selfJoin;
- Boolean endIsFg = FALSE, startIsFg = FALSE;
- Boolean firstIsFg = FALSE, prevIsFg = FALSE;
-
- if (npt == 0)
- return;
- spanData = miSetupSpanData (pGC, &spanDataRec, npt);
- x2 = pPts->x;
- y2 = pPts->y;
- first = TRUE;
- selfJoin = FALSE;
- if (mode == CoordModePrevious) {
- int nptTmp;
- DDXPointPtr pPtsTmp;
-
- x1 = x2;
- y1 = y2;
- nptTmp = npt;
- pPtsTmp = pPts + 1;
- while (--nptTmp) {
- x1 += pPtsTmp->x;
- y1 += pPtsTmp->y;
- ++pPtsTmp;
- }
- if (x2 == x1 && y2 == y1)
- selfJoin = TRUE;
- } else if (x2 == pPts[npt - 1].x && y2 == pPts[npt - 1].y) {
- selfJoin = TRUE;
- }
- projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
- projectRight = FALSE;
- dashIndex = 0;
- dashOffset = 0;
- miStepDash ((int) pGC->dashOffset, &dashIndex,
- pGC->dash, (int) pGC->numInDashList, &dashOffset);
- while (--npt) {
- x1 = x2;
- y1 = y2;
- ++pPts;
- x2 = pPts->x;
- y2 = pPts->y;
- if (mode == CoordModePrevious) {
- x2 += x1;
- y2 += y1;
- }
- if (x1 != x2 || y1 != y2) {
- somethingDrawn = TRUE;
- if (npt == 1 && pGC->capStyle == CapProjecting && (!selfJoin || !firstIsFg))
- projectRight = TRUE;
- prevDashIndex = dashIndex;
- miWideDashSegment (pGC, spanData, &dashOffset, &dashIndex,
- x1, y1, x2, y2, projectLeft, projectRight, &leftFace, &rightFace);
- startIsFg = !(prevDashIndex & 1);
- endIsFg = (dashIndex & 1) ^ (dashOffset != 0);
- if (pGC->lineStyle == LineDoubleDash || startIsFg) {
- foreground = startIsFg;
- if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) {
- if (first && selfJoin) {
- firstFace = leftFace;
- firstIsFg = startIsFg;
- } else if (pGC->capStyle == CapRound)
- miLineArc (pGC, foreground, spanData,
- &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE);
- } else {
- miLineJoin (pGC, foreground, spanData, &leftFace, &prevRightFace);
- }
- }
- prevRightFace = rightFace;
- prevIsFg = endIsFg;
- first = FALSE;
- projectLeft = FALSE;
- }
- if (npt == 1 && somethingDrawn) {
- if (pGC->lineStyle == LineDoubleDash || endIsFg) {
- foreground = endIsFg;
- if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) {
- miLineJoin (pGC, foreground, spanData, &firstFace, &rightFace);
- } else {
- if (pGC->capStyle == CapRound)
- miLineArc (pGC, foreground, spanData,
- (LineFacePtr) NULL, &rightFace,
- (double) 0.0, (double) 0.0, TRUE);
- }
- } else {
- /* glue a cap to the start of the line if
- * we're OnOffDash and ended on odd dash
- */
- if (selfJoin && firstIsFg) {
- foreground = TRUE;
- if (pGC->capStyle == CapProjecting)
- miLineProjectingCap (pGC, foreground, spanData,
- &firstFace, TRUE, (double) 0.0, (double) 0.0, TRUE);
- else if (pGC->capStyle == CapRound)
- miLineArc (pGC, foreground, spanData,
- &firstFace, (LineFacePtr) NULL,
- (double) 0.0, (double) 0.0, TRUE);
- }
- }
- }
- }
- /* handle crock where all points are coincident */
- if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) {
- /* not the same as endIsFg computation above */
- foreground = (dashIndex & 1) == 0;
- switch (pGC->capStyle) {
- case CapRound:
- miLineArc (pGC, foreground, spanData,
- (LineFacePtr) NULL, (LineFacePtr) NULL, (double) x2, (double) y2, FALSE);
- break;
- case CapProjecting:
- x1 = pGC->lineWidth;
- miFillRectPolyHelper (pGC, foreground, spanData,
- x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1);
- break;
- }
- }
- if (spanData)
- miCleanupSpanData (pGC, spanData);
-}
-
-#undef ExchangeSpans
-#define ExchangeSpans(a, b) \
-{ \
- DDXPointRec tpt; \
- int tw; \
- \
- tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
- tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
-}
-
-static void QuickSortSpans(
- DDXPointRec spans[],
- int widths[],
- int numSpans)
-{
- int y;
- int i, j, m;
- DDXPointPtr r;
-
- /* Always called with numSpans > 1 */
- /* Sorts only by y, doesn't bother to sort by x */
-
- do
- {
- if (numSpans < 9)
- {
- /* Do insertion sort */
- int yprev;
-
- yprev = spans[0].y;
- i = 1;
- do
- { /* while i != numSpans */
- y = spans[i].y;
- if (yprev > y)
- {
- /* spans[i] is out of order. Move into proper location. */
- DDXPointRec tpt;
- int tw, k;
-
- for (j = 0; y >= spans[j].y; j++) {}
- tpt = spans[i];
- tw = widths[i];
- for (k = i; k != j; k--)
- {
- spans[k] = spans[k-1];
- widths[k] = widths[k-1];
- }
- spans[j] = tpt;
- widths[j] = tw;
- y = spans[i].y;
- } /* if out of order */
- yprev = y;
- i++;
- } while (i != numSpans);
- return;
- }
-
- /* Choose partition element, stick in location 0 */
- m = numSpans / 2;
- if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
- if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
- if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
- y = spans[0].y;
-
- /* Partition array */
- i = 0;
- j = numSpans;
- do
- {
- r = &(spans[i]);
- do
- {
- r++;
- i++;
- } while (i != numSpans && r->y < y);
- r = &(spans[j]);
- do
- {
- r--;
- j--;
- } while (y < r->y);
- if (i < j)
- ExchangeSpans(i, j);
- } while (i < j);
-
- /* Move partition element back to middle */
- ExchangeSpans(0, j);
-
- /* Recurse */
- if (numSpans-j-1 > 1)
- QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
- numSpans = j;
- } while (numSpans > 1);
-}
-
-#define NextBand() \
-{ \
- clipy1 = pboxBandStart->y1; \
- clipy2 = pboxBandStart->y2; \
- pboxBandEnd = pboxBandStart + 1; \
- while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \
- pboxBandEnd++; \
- } \
- for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
-}
-
-/*
- Clip a list of scanlines to a region. The caller has allocated the
- space. FSorted is non-zero if the scanline origins are in ascending
- order.
- returns the number of new, clipped scanlines.
-*/
-
-int spice_canvas_clip_spans(pixman_region32_t *prgnDst,
- DDXPointPtr ppt,
- int *pwidth,
- int nspans,
- DDXPointPtr pptNew,
- int *pwidthNew,
- int fSorted)
-{
- DDXPointPtr pptLast;
- int *pwidthNewStart; /* the vengeance of Xerox! */
- int y, x1, x2;
- int numRects;
- pixman_box32_t *pboxBandStart;
-
- pptLast = ppt + nspans;
- pwidthNewStart = pwidthNew;
-
- pboxBandStart = pixman_region32_rectangles (prgnDst, &numRects);
-
- if (numRects == 1) {
- /* Do special fast code with clip boundaries in registers(?) */
- /* It doesn't pay much to make use of fSorted in this case,
- so we lump everything together. */
-
- int clipx1, clipx2, clipy1, clipy2;
-
- clipx1 = pboxBandStart->x1;
- clipy1 = pboxBandStart->y1;
- clipx2 = pboxBandStart->x2;
- clipy2 = pboxBandStart->y2;
-
- for (; ppt != pptLast; ppt++, pwidth++) {
- y = ppt->y;
- x1 = ppt->x;
- if (clipy1 <= y && y < clipy2) {
- x2 = x1 + *pwidth;
- if (x1 < clipx1)
- x1 = clipx1;
- if (x2 > clipx2)
- x2 = clipx2;
- if (x1 < x2) {
- /* part of span in clip rectangle */
- pptNew->x = x1;
- pptNew->y = y;
- *pwidthNew = x2 - x1;
- pptNew++;
- pwidthNew++;
- }
- }
- } /* end for */
- } else if (numRects != 0) {
- /* Have to clip against many boxes */
- pixman_box32_t *pboxBandEnd, *pbox, *pboxLast;
- int clipy1, clipy2;
-
- /* In this case, taking advantage of sorted spans gains more than
- the sorting costs. */
- if ((! fSorted) && (nspans > 1))
- QuickSortSpans(ppt, pwidth, nspans);
-
- pboxLast = pboxBandStart + numRects;
-
- NextBand();
-
- for (; ppt != pptLast; ) {
- y = ppt->y;
- if (y < clipy2) {
- /* span is in the current band */
- pbox = pboxBandStart;
- x1 = ppt->x;
- x2 = x1 + *pwidth;
- do { /* For each box in band */
- int newx1, newx2;
-
- newx1 = x1;
- newx2 = x2;
- if (newx1 < pbox->x1)
- newx1 = pbox->x1;
- if (newx2 > pbox->x2)
- newx2 = pbox->x2;
- if (newx1 < newx2) {
- /* Part of span in clip rectangle */
- pptNew->x = newx1;
- pptNew->y = y;
- *pwidthNew = newx2 - newx1;
- pptNew++;
- pwidthNew++;
- }
- pbox++;
- } while (pbox != pboxBandEnd);
- ppt++;
- pwidth++;
- } else {
- /* Move to next band, adjust ppt as needed */
- pboxBandStart = pboxBandEnd;
- if (pboxBandStart == pboxLast)
- break; /* We're completely done */
- NextBand();
- }
- }
- }
- return (pwidthNew - pwidthNewStart);
-}
diff --git a/common/lines.h b/common/lines.h
deleted file mode 100644
index 1d092f0..0000000
--- a/common/lines.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-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.
-
-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
-OPEN GROUP 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 name of The Open Group 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 Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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.
-
-******************************************************************/
-
-#ifndef LINES_H
-#define LINES_H
-
-#include <pixman_utils.h>
-#include <stdlib.h>
-#include <string.h>
-#include "draw.h"
-
-typedef struct lineGC lineGC;
-
-typedef struct {
- void (*FillSpans)(lineGC * pGC,
- int num_spans, SpicePoint * points, int *widths,
- int sorted, int foreground);
- void (*FillRects)(lineGC * pGC,
- int nun_rects, pixman_rectangle32_t * rects,
- int foreground);
-} lineGCOps;
-
-struct lineGC {
- int width;
- int height;
- unsigned char alu;
- unsigned short lineWidth;
- unsigned short dashOffset;
- unsigned short numInDashList;
- unsigned char *dash;
- unsigned int lineStyle:2;
- unsigned int capStyle:2;
- unsigned int joinStyle:2;
- lineGCOps *ops;
-};
-
-/* CoordinateMode for drawing routines */
-
-#define CoordModeOrigin 0 /* relative to the origin */
-#define CoordModePrevious 1 /* relative to previous point */
-
-/* LineStyle */
-
-#define LineSolid 0
-#define LineOnOffDash 1
-#define LineDoubleDash 2
-
-/* capStyle */
-
-#define CapNotLast 0
-#define CapButt 1
-#define CapRound 2
-#define CapProjecting 3
-
-/* joinStyle */
-
-#define JoinMiter 0
-#define JoinRound 1
-#define JoinBevel 2
-
-extern void spice_canvas_zero_line(lineGC *pgc,
- int mode,
- int num_points,
- SpicePoint * points);
-extern void spice_canvas_zero_dash_line(lineGC * pgc,
- int mode,
- int n_points,
- SpicePoint * points);
-extern void spice_canvas_wide_dash_line(lineGC * pGC,
- int mode,
- int num_points,
- SpicePoint * points);
-extern void spice_canvas_wide_line(lineGC *pGC,
- int mode,
- int num_points,
- SpicePoint * points);
-extern int spice_canvas_clip_spans(pixman_region32_t *clip_region,
- SpicePoint *points,
- int *widths,
- int num_spans,
- SpicePoint *new_points,
- int *new_widths,
- int sorted);
-
-#endif /* LINES_H */
diff --git a/common/lz.c b/common/lz.c
deleted file mode 100644
index d0d9511..0000000
--- a/common/lz.c
+++ /dev/null
@@ -1,738 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-
- Copyright 2009 Red Hat, Inc. and/or its affiliates.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-
- This file incorporates work covered by the following copyright and
- permission notice:
- Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya at kde.org)
-
- 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 OR COPYRIGHT HOLDERS
- 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.
-
-*/
-
-#include "lz.h"
-
-#define DEBUG
-
-#ifdef DEBUG
-
-#define ASSERT(usr, x) \
- if (!(x)) (usr)->error(usr, "%s: ASSERT %s failed\n", __FUNCTION__, #x);
-
-#else
-
-#define ASSERT(usr, x)
-
-#endif
-
-#define HASH_LOG 13
-#define HASH_SIZE (1 << HASH_LOG)
-#define HASH_MASK (HASH_SIZE - 1)
-
-
-typedef struct LzImageSegment LzImageSegment;
-struct LzImageSegment {
- uint8_t *lines;
- uint8_t *lines_end;
- unsigned int size_delta; // total size of the previous segments in units of
- // pixels for rgb and bytes for plt.
- LzImageSegment *next;
-};
-
-// TODO: pack?
-typedef struct HashEntry {
- LzImageSegment *image_seg;
- uint8_t *ref;
-} HashEntry;
-
-typedef struct Encoder {
- LzUsrContext *usr;
-
- LzImageType type;
- const SpicePalette *palette; // for decoding images with palettes to rgb
- int stride; // stride is in bytes. For rgb must be equal to
- // width*bytes_per_pix.
- // For palettes stride can be bigger than width/pixels_per_byte by 1 only if
- // width%pixels_per_byte != 0.
- int height;
- int width; // the original width (in pixels)
-
- LzImageSegment *head_image_segs;
- LzImageSegment *tail_image_segs;
- LzImageSegment *free_image_segs;
-
- // the dictionary hash table is composed (1) a pointer to the segment the word was found in
- // (2) a pointer to the first byte in the segment that matches the word
- HashEntry htab[HASH_SIZE];
-
- uint8_t *io_start;
- uint8_t *io_now;
- uint8_t *io_end;
- size_t io_bytes_count;
-
- uint8_t *io_last_copy; // pointer to the last byte in which copy count was written
-} Encoder;
-
-/****************************************************/
-/* functions for managing the pool of image segments*/
-/****************************************************/
-static INLINE LzImageSegment *lz_alloc_image_seg(Encoder *encoder);
-static void lz_reset_image_seg(Encoder *encoder);
-static int lz_read_image_segments(Encoder *encoder, uint8_t *first_lines,
- unsigned int num_first_lines);
-
-
-// return a free image segment if one exists. Make allocation if needed. adds it to the
-// tail of the image segments lists
-static INLINE LzImageSegment *lz_alloc_image_seg(Encoder *encoder)
-{
- LzImageSegment *ret;
-
- if (encoder->free_image_segs) {
- ret = encoder->free_image_segs;
- encoder->free_image_segs = ret->next;
- } else {
- if (!(ret = (LzImageSegment *)encoder->usr->malloc(encoder->usr, sizeof(*ret)))) {
- return NULL;
- }
- }
-
- ret->next = NULL;
- if (encoder->tail_image_segs) {
- encoder->tail_image_segs->next = ret;
- }
- encoder->tail_image_segs = ret;
-
- if (!encoder->head_image_segs) {
- encoder->head_image_segs = ret;
- }
-
- return ret;
-}
-
-// adding seg to the head of free segments (lz_reset_image_seg removes it from used ones)
-static INLINE void __lz_free_image_seg(Encoder *encoder, LzImageSegment *seg)
-{
- seg->next = encoder->free_image_segs;
- encoder->free_image_segs = seg;
-}
-
-// moves all the used image segments to the free pool
-static void lz_reset_image_seg(Encoder *encoder)
-{
- while (encoder->head_image_segs) {
- LzImageSegment *seg = encoder->head_image_segs;
- encoder->head_image_segs = seg->next;
- __lz_free_image_seg(encoder, seg);
- }
- encoder->tail_image_segs = NULL;
-}
-
-static void lz_dealloc_free_segments(Encoder *encoder)
-{
- while (encoder->free_image_segs) {
- LzImageSegment *seg = encoder->free_image_segs;
- encoder->free_image_segs = seg->next;
- encoder->usr->free(encoder->usr, seg);
- }
-}
-
-// return FALSE when operation fails (due to failure in allocation)
-static int lz_read_image_segments(Encoder *encoder, uint8_t *first_lines,
- unsigned int num_first_lines)
-{
- LzImageSegment *image_seg;
- uint32_t size_delta = 0;
- unsigned int num_lines = num_first_lines;
- uint8_t* lines = first_lines;
- int row;
-
- ASSERT(encoder->usr, !encoder->head_image_segs);
-
- image_seg = lz_alloc_image_seg(encoder);
- if (!image_seg) {
- goto error_1;
- }
-
- image_seg->lines = lines;
- image_seg->lines_end = lines + num_lines * encoder->stride;
- image_seg->size_delta = size_delta;
-
- size_delta += num_lines * encoder->stride / RGB_BYTES_PER_PIXEL[encoder->type];
-
- for (row = num_first_lines; row < encoder->height; row += num_lines) {
- num_lines = encoder->usr->more_lines(encoder->usr, &lines);
- if (num_lines <= 0) {
- encoder->usr->error(encoder->usr, "more lines failed\n");
- }
- image_seg = lz_alloc_image_seg(encoder);
-
- if (!image_seg) {
- goto error_1;
- }
-
- image_seg->lines = lines;
- image_seg->lines_end = lines + num_lines * encoder->stride;
- image_seg->size_delta = size_delta;
-
- size_delta += num_lines * encoder->stride / RGB_BYTES_PER_PIXEL[encoder->type];
- }
-
- return TRUE;
-error_1:
- lz_reset_image_seg(encoder);
- return FALSE;
-}
-
-/**************************************************************************
-* Handling encoding and decoding of a byte
-***************************************************************************/
-static INLINE int more_io_bytes(Encoder *encoder)
-{
- uint8_t *io_ptr;
- int num_io_bytes = encoder->usr->more_space(encoder->usr, &io_ptr);
- encoder->io_bytes_count += num_io_bytes;
- encoder->io_now = io_ptr;
- encoder->io_end = encoder->io_now + num_io_bytes;
- return num_io_bytes;
-}
-
-static INLINE void encode(Encoder *encoder, uint8_t byte)
-{
- if (encoder->io_now == encoder->io_end) {
- if (more_io_bytes(encoder) <= 0) {
- encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__);
- }
- ASSERT(encoder->usr, encoder->io_now);
- }
-
- ASSERT(encoder->usr, encoder->io_now < encoder->io_end);
- *(encoder->io_now++) = byte;
-}
-
-static INLINE void encode_32(Encoder *encoder, unsigned int word)
-{
- encode(encoder, (uint8_t)(word >> 24));
- encode(encoder, (uint8_t)(word >> 16) & 0x0000ff);
- encode(encoder, (uint8_t)(word >> 8) & 0x0000ff);
- encode(encoder, (uint8_t)(word & 0x0000ff));
-}
-
-static INLINE void encode_copy_count(Encoder *encoder, uint8_t copy_count)
-{
- encode(encoder, copy_count);
- encoder->io_last_copy = encoder->io_now - 1; // io_now cannot be the first byte of the buffer
-}
-
-static INLINE void update_copy_count(Encoder *encoder, uint8_t copy_count)
-{
- ASSERT(encoder->usr, encoder->io_last_copy);
- *(encoder->io_last_copy) = copy_count;
-}
-
-static INLINE void encode_level(Encoder *encoder, uint8_t level_code)
-{
- *(encoder->io_start) |= level_code;
-}
-
-// decrease the io ptr by 1
-static INLINE void compress_output_prev(Encoder *encoder)
-{
- // io_now cannot be the first byte of the buffer
- encoder->io_now--;
- // the function should be called only when copy count is written unnecessarily by lz_compress
- ASSERT(encoder->usr, encoder->io_now == encoder->io_last_copy)
-}
-
-static int encoder_reset(Encoder *encoder, uint8_t *io_ptr, uint8_t *io_ptr_end)
-{
- ASSERT(encoder->usr, io_ptr <= io_ptr_end);
- encoder->io_bytes_count = io_ptr_end - io_ptr;
- encoder->io_start = io_ptr;
- encoder->io_now = io_ptr;
- encoder->io_end = io_ptr_end;
- encoder->io_last_copy = NULL;
-
- return TRUE;
-}
-
-static INLINE uint8_t decode(Encoder *encoder)
-{
- if (encoder->io_now == encoder->io_end) {
- int num_io_bytes = more_io_bytes(encoder);
- if (num_io_bytes <= 0) {
- encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__);
- }
- ASSERT(encoder->usr, encoder->io_now);
- }
- ASSERT(encoder->usr, encoder->io_now < encoder->io_end);
- return *(encoder->io_now++);
-}
-
-static INLINE uint32_t decode_32(Encoder *encoder)
-{
- uint32_t word = 0;
- word |= decode(encoder);
- word <<= 8;
- word |= decode(encoder);
- word <<= 8;
- word |= decode(encoder);
- word <<= 8;
- word |= decode(encoder);
- return word;
-}
-
-static INLINE int is_io_to_decode_end(Encoder *encoder)
-{
- if (encoder->io_now != encoder->io_end) {
- return FALSE;
- } else {
- int num_io_bytes = more_io_bytes(encoder); //disable inline optimizations
- return (num_io_bytes <= 0);
- }
-}
-
-/*******************************************************************
-* intialization and finalization of lz
-********************************************************************/
-static int init_encoder(Encoder *encoder, LzUsrContext *usr)
-{
- encoder->usr = usr;
- encoder->free_image_segs = NULL;
- encoder->head_image_segs = NULL;
- encoder->tail_image_segs = NULL;
- return TRUE;
-}
-
-LzContext *lz_create(LzUsrContext *usr)
-{
- Encoder *encoder;
-
- if (!usr || !usr->error || !usr->warn || !usr->info || !usr->malloc ||
- !usr->free || !usr->more_space || !usr->more_lines) {
- return NULL;
- }
-
- if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) {
- return NULL;
- }
-
- if (!init_encoder(encoder, usr)) {
- usr->free(usr, encoder);
- return NULL;
- }
- return (LzContext *)encoder;
-}
-
-void lz_destroy(LzContext *lz)
-{
- Encoder *encoder = (Encoder *)lz;
-
- if (!lz) {
- return;
- }
-
- if (encoder->head_image_segs) {
- encoder->usr->error(encoder->usr, "%s: used_image_segments not empty\n", __FUNCTION__);
- lz_reset_image_seg(encoder);
- }
- lz_dealloc_free_segments(encoder);
-
- encoder->usr->free(encoder->usr, encoder);
-}
-
-/*******************************************************************
-* encoding and decoding the image
-********************************************************************/
-/*
- * Give hints to the compiler for branch prediction optimization.
- */
-#if defined(__GNUC__) && (__GNUC__ > 2)
-#define LZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
-#define LZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
-#else
-#define LZ_EXPECT_CONDITIONAL(c) (c)
-#define LZ_UNEXPECT_CONDITIONAL(c) (c)
-#endif
-
-
-#ifdef __GNUC__
-#define ATTR_PACKED __attribute__ ((__packed__))
-#else
-#define ATTR_PACKED
-#pragma pack(push)
-#pragma pack(1)
-#endif
-
-
-/* the palette images will be treated as one byte pixels. Their width should be transformed
- accordingly.
-*/
-typedef struct ATTR_PACKED one_byte_pixel_t {
- uint8_t a;
-} one_byte_pixel_t;
-
-typedef struct ATTR_PACKED rgb32_pixel_t {
- uint8_t b;
- uint8_t g;
- uint8_t r;
- uint8_t pad;
-} rgb32_pixel_t;
-
-typedef struct ATTR_PACKED rgb24_pixel_t {
- uint8_t b;
- uint8_t g;
- uint8_t r;
-} rgb24_pixel_t;
-
-typedef uint16_t rgb16_pixel_t;
-
-#ifndef __GNUC__
-#pragma pack(pop)
-#endif
-
-#undef ATTR_PACKED
-
-
-#define MAX_COPY 32
-#define MAX_LEN 264 /* 256 + 8 */
-#define BOUND_OFFSET 2
-#define LIMIT_OFFSET 6
-#define MIN_FILE_SIZE 4
-#define COMP_LEVEL_SIZE_LIMIT 65536
-
-// TODO: implemented lz2. should lz1 be an option (no RLE + distance limitation of MAX_DISTANCE)
-// TODO: I think MAX_FARDISTANCE can be changed easily to 2^29
-// (and maybe even more when pixel > byte).
-// i.e. we can support 512M Bytes/Pixels distance instead of only ~68K.
-#define MAX_DISTANCE 8191 // 2^13
-#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1) // ~2^16+2^13
-
-
-#define LZ_PLT
-#include "lz_compress_tmpl.c"
-#define LZ_PLT
-#include "lz_decompress_tmpl.c"
-
-#define LZ_PLT
-#define PLT8
-#define TO_RGB32
-#include "lz_decompress_tmpl.c"
-
-#define LZ_PLT
-#define PLT4_BE
-#define TO_RGB32
-#include "lz_decompress_tmpl.c"
-
-#define LZ_PLT
-#define PLT4_LE
-#define TO_RGB32
-#include "lz_decompress_tmpl.c"
-
-#define LZ_PLT
-#define PLT1_BE
-#define TO_RGB32
-#include "lz_decompress_tmpl.c"
-
-#define LZ_PLT
-#define PLT1_LE
-#define TO_RGB32
-#include "lz_decompress_tmpl.c"
-
-
-#define LZ_RGB16
-#include "lz_compress_tmpl.c"
-#define LZ_RGB16
-#include "lz_decompress_tmpl.c"
-#define LZ_RGB16
-#define TO_RGB32
-#include "lz_decompress_tmpl.c"
-
-#define LZ_RGB24
-#include "lz_compress_tmpl.c"
-#define LZ_RGB24
-#include "lz_decompress_tmpl.c"
-
-
-#define LZ_RGB32
-#include "lz_compress_tmpl.c"
-#define LZ_RGB32
-#include "lz_decompress_tmpl.c"
-
-#define LZ_RGB_ALPHA
-#include "lz_compress_tmpl.c"
-#define LZ_RGB_ALPHA
-#include "lz_decompress_tmpl.c"
-
-#undef LZ_UNEXPECT_CONDITIONAL
-#undef LZ_EXPECT_CONDITIONAL
-
-int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down,
- uint8_t *lines, unsigned int num_lines, int stride,
- uint8_t *io_ptr, unsigned int num_io_bytes)
-{
- Encoder *encoder = (Encoder *)lz;
- uint8_t *io_ptr_end = io_ptr + num_io_bytes;
-
- encoder->type = type;
- encoder->width = width;
- encoder->height = height;
- encoder->stride = stride;
-
- if (IS_IMAGE_TYPE_PLT[encoder->type]) {
- if (encoder->stride > (width / PLT_PIXELS_PER_BYTE[encoder->type])) {
- if (((width % PLT_PIXELS_PER_BYTE[encoder->type]) == 0) || (
- (encoder->stride - (width / PLT_PIXELS_PER_BYTE[encoder->type])) > 1)) {
- encoder->usr->error(encoder->usr, "stride overflows (plt)\n");
- }
- }
- } else {
- if (encoder->stride != width * RGB_BYTES_PER_PIXEL[encoder->type]) {
- encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb)\n");
- }
- }
-
- // assign the output buffer
- if (!encoder_reset(encoder, io_ptr, io_ptr_end)) {
- encoder->usr->error(encoder->usr, "lz encoder io reset failed\n");
- }
-
- // first read the list of the image segments
- if (!lz_read_image_segments(encoder, lines, num_lines)) {
- encoder->usr->error(encoder->usr, "lz encoder reading image segments failed\n");
- }
-
- encode_32(encoder, LZ_MAGIC);
- encode_32(encoder, LZ_VERSION);
- encode_32(encoder, type);
- encode_32(encoder, width);
- encode_32(encoder, height);
- encode_32(encoder, stride);
- encode_32(encoder, top_down); // TODO: maybe compress type and top_down to one byte
-
- switch (encoder->type) {
- case LZ_IMAGE_TYPE_PLT1_BE:
- case LZ_IMAGE_TYPE_PLT1_LE:
- case LZ_IMAGE_TYPE_PLT4_BE:
- case LZ_IMAGE_TYPE_PLT4_LE:
- case LZ_IMAGE_TYPE_PLT8:
- lz_plt_compress(encoder);
- break;
- case LZ_IMAGE_TYPE_RGB16:
- lz_rgb16_compress(encoder);
- break;
- case LZ_IMAGE_TYPE_RGB24:
- lz_rgb24_compress(encoder);
- break;
- case LZ_IMAGE_TYPE_RGB32:
- lz_rgb32_compress(encoder);
- break;
- case LZ_IMAGE_TYPE_RGBA:
- lz_rgb32_compress(encoder);
- lz_rgb_alpha_compress(encoder);
- break;
- case LZ_IMAGE_TYPE_XXXA:
- lz_rgb_alpha_compress(encoder);
- break;
- case LZ_IMAGE_TYPE_INVALID:
- default:
- encoder->usr->error(encoder->usr, "bad image type\n");
- }
-
- // move all the used segments to the free ones
- lz_reset_image_seg(encoder);
-
- encoder->io_bytes_count -= (encoder->io_end - encoder->io_now);
-
- return encoder->io_bytes_count;
-}
-
-/*
- initialize and read lz magic
-*/
-void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes,
- LzImageType *out_type, int *out_width, int *out_height,
- int *out_n_pixels, int *out_top_down, const SpicePalette *palette)
-{
- Encoder *encoder = (Encoder *)lz;
- uint8_t *io_ptr_end = io_ptr + num_io_bytes;
- uint32_t magic;
- uint32_t version;
-
- if (!encoder_reset(encoder, io_ptr, io_ptr_end)) {
- encoder->usr->error(encoder->usr, "io reset failed");
- }
-
- magic = decode_32(encoder);
- if (magic != LZ_MAGIC) {
- encoder->usr->error(encoder->usr, "bad magic\n");
- }
-
- version = decode_32(encoder);
- if (version != LZ_VERSION) {
- encoder->usr->error(encoder->usr, "bad version\n");
- }
-
- encoder->type = (LzImageType)decode_32(encoder);
- encoder->width = decode_32(encoder);
- encoder->height = decode_32(encoder);
- encoder->stride = decode_32(encoder);
- *out_top_down = decode_32(encoder);
-
- *out_width = encoder->width;
- *out_height = encoder->height;
-// *out_stride = encoder->stride;
- *out_type = encoder->type;
-
- // TODO: maybe instead of stride we can encode out_n_pixels
- // (if stride is not necessary in decoding).
- if (IS_IMAGE_TYPE_PLT[encoder->type]) {
- encoder->palette = palette;
- *out_n_pixels = encoder->stride * PLT_PIXELS_PER_BYTE[encoder->type] * encoder->height;
- } else {
- *out_n_pixels = encoder->width * encoder->height;
- }
-}
-
-void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf)
-{
- Encoder *encoder = (Encoder *)lz;
- size_t out_size = 0;
- size_t alpha_size = 0;
- size_t size = 0;
- if (IS_IMAGE_TYPE_PLT[encoder->type]) {
- if (to_type == encoder->type) {
- size = encoder->height * encoder->stride;
- out_size = lz_plt_decompress(encoder, (one_byte_pixel_t *)buf, size);
- } else if (to_type == LZ_IMAGE_TYPE_RGB32) {
- size = encoder->height * encoder->stride * PLT_PIXELS_PER_BYTE[encoder->type];
- if (!encoder->palette) {
- encoder->usr->error(encoder->usr,
- "a palette is missing (for bpp to rgb decoding)\n");
- }
- switch (encoder->type) {
- case LZ_IMAGE_TYPE_PLT1_BE:
- out_size = lz_plt1_be_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- break;
- case LZ_IMAGE_TYPE_PLT1_LE:
- out_size = lz_plt1_le_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- break;
- case LZ_IMAGE_TYPE_PLT4_BE:
- out_size = lz_plt4_be_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- break;
- case LZ_IMAGE_TYPE_PLT4_LE:
- out_size = lz_plt4_le_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- break;
- case LZ_IMAGE_TYPE_PLT8:
- out_size = lz_plt8_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- break;
- case LZ_IMAGE_TYPE_RGB16:
- case LZ_IMAGE_TYPE_RGB24:
- case LZ_IMAGE_TYPE_RGB32:
- case LZ_IMAGE_TYPE_RGBA:
- case LZ_IMAGE_TYPE_XXXA:
- case LZ_IMAGE_TYPE_INVALID:
- default:
- encoder->usr->error(encoder->usr, "bad image type\n");
- }
- } else {
- encoder->usr->error(encoder->usr, "unsupported output format\n");
- }
- } else {
- size = encoder->height * encoder->width;
- switch (encoder->type) {
- case LZ_IMAGE_TYPE_RGB16:
- if (encoder->type == to_type) {
- out_size = lz_rgb16_decompress(encoder, (rgb16_pixel_t *)buf, size);
- } else if (to_type == LZ_IMAGE_TYPE_RGB32) {
- out_size = lz_rgb16_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- } else {
- encoder->usr->error(encoder->usr, "unsupported output format\n");
- }
- break;
- case LZ_IMAGE_TYPE_RGB24:
- if (encoder->type == to_type) {
- out_size = lz_rgb24_decompress(encoder, (rgb24_pixel_t *)buf, size);
- } else if (to_type == LZ_IMAGE_TYPE_RGB32) {
- out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- } else {
- encoder->usr->error(encoder->usr, "unsupported output format\n");
- }
- break;
- case LZ_IMAGE_TYPE_RGB32:
- if (encoder->type == to_type) {
- out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- } else {
- encoder->usr->error(encoder->usr, "unsupported output format\n");
- }
- break;
- case LZ_IMAGE_TYPE_RGBA:
- if (encoder->type == to_type) {
- out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
- alpha_size = lz_rgb_alpha_decompress(encoder, (rgb32_pixel_t *)buf, size);
- ASSERT(encoder->usr, alpha_size == size);
- } else {
- encoder->usr->error(encoder->usr, "unsupported output format\n");
- }
- break;
- case LZ_IMAGE_TYPE_XXXA:
- if (encoder->type == to_type) {
- alpha_size = lz_rgb_alpha_decompress(encoder, (rgb32_pixel_t *)buf, size);
- out_size = alpha_size;
- } else {
- encoder->usr->error(encoder->usr, "unsupported output format\n");
- }
- break;
- case LZ_IMAGE_TYPE_PLT1_LE:
- case LZ_IMAGE_TYPE_PLT1_BE:
- case LZ_IMAGE_TYPE_PLT4_LE:
- case LZ_IMAGE_TYPE_PLT4_BE:
- case LZ_IMAGE_TYPE_PLT8:
- case LZ_IMAGE_TYPE_INVALID:
- default:
- encoder->usr->error(encoder->usr, "bad image type\n");
- }
- }
-
- ASSERT(encoder->usr, is_io_to_decode_end(encoder));
- ASSERT(encoder->usr, out_size == size);
-
- if (out_size != size) {
- encoder->usr->error(encoder->usr, "bad decode size\n");
- }
-}
-
diff --git a/common/lz.h b/common/lz.h
deleted file mode 100644
index a51ccc0..0000000
--- a/common/lz.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- dictionary compression for images based on fastlz (http://www.fastlz.org/)
- (Distributed under MIT license).
-*/
-#ifndef __LZ_H
-#define __LZ_H
-
-#include "lz_common.h"
-#include "lz_config.h"
-#include "draw.h"
-#include "macros.h"
-
-typedef void *LzContext;
-
-typedef struct LzUsrContext LzUsrContext;
-struct LzUsrContext {
- ATTR_PRINTF(2, 3) void (*error)(LzUsrContext *usr, const char *fmt, ...);
- ATTR_PRINTF(2, 3) void (*warn)(LzUsrContext *usr, const char *fmt, ...);
- ATTR_PRINTF(2, 3) void (*info)(LzUsrContext *usr, const char *fmt, ...);
- void *(*malloc)(LzUsrContext *usr, int size);
- void (*free)(LzUsrContext *usr, void *ptr);
- int (*more_space)(LzUsrContext *usr, uint8_t **io_ptr); // get the next chunk of the
- // compressed buffer. return
- // number of bytes in the chunk.
- int (*more_lines)(LzUsrContext *usr, uint8_t **lines); // get the next chunk of the
- // original image. If the image
- // is down to top, return it from
- // the last line to the first one
- // (stride should always be
- // positive)
-};
-
-/*
- assumes width is in pixels and stride is in bytes
- return: the number of bytes in the compressed data
-
- TODO : determine size limit for the first segment and each chunk. check validity
- of the segment or go to literal copy.
- TODO : currently support only rgb images in which width*bytes_per_pixel = stride OR
- palette images in which stride equals the min number of bytes to
- hold a line. stride is not necessary for now. just for sanity check.
- stride should be > 0
-*/
-int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down,
- uint8_t *lines, unsigned int num_lines, int stride,
- uint8_t *io_ptr, unsigned int num_io_bytes);
-
-/*
- prepare encoder and read lz magic.
- out_n_pixels number of compressed pixels. May differ from Width*height in plt1/4.
- Use it for allocation the decompressed buffer.
-
-*/
-void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes,
- LzImageType *out_type, int *out_width, int *out_height,
- int *out_n_pixels, int *out_top_down, const SpicePalette *palette);
-
-/*
- to_type = the image output type.
- We assume the buffer is consecutive. i.e. width = stride
-
- Important: if the image is plt1/4 and to_type is rgb32, the image
- will decompressed including the last bits in each line. This means buffer should be
- larger than width*height if needed and you should use stride to fix it.
- Note: If the image is down to top, set the stride in the sw surface to negative.
- use alloc_lz_image_surface create the surface.
-*/
-void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf);
-
-LzContext *lz_create(LzUsrContext *usr);
-
-void lz_destroy(LzContext *lz);
-
-
-#endif // __LZ_H
diff --git a/common/lz_common.h b/common/lz_common.h
deleted file mode 100644
index 34276af..0000000
--- a/common/lz_common.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
-
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-/*common header for encoder and decoder*/
-
-#ifndef _LZ_COMMON_H
-#define _LZ_COMMON_H
-
-//#define DEBUG
-
-/* change the max window size will require change in the encoding format*/
-#define LZ_MAX_WINDOW_SIZE (1 << 25)
-#define MAX_COPY 32
-
-typedef enum {
- LZ_IMAGE_TYPE_INVALID,
- LZ_IMAGE_TYPE_PLT1_LE,
- LZ_IMAGE_TYPE_PLT1_BE, // PLT stands for palette
- LZ_IMAGE_TYPE_PLT4_LE,
- LZ_IMAGE_TYPE_PLT4_BE,
- LZ_IMAGE_TYPE_PLT8,
- LZ_IMAGE_TYPE_RGB16,
- LZ_IMAGE_TYPE_RGB24,
- LZ_IMAGE_TYPE_RGB32,
- LZ_IMAGE_TYPE_RGBA,
- LZ_IMAGE_TYPE_XXXA
-} LzImageType;
-
-#define LZ_IMAGE_TYPE_MASK 0x0f
-#define LZ_IMAGE_TYPE_LOG 4 // number of bits required for coding the image type
-
-/* access to the arrays is based on the image types */
-static const int IS_IMAGE_TYPE_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
-static const int IS_IMAGE_TYPE_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
-static const int PLT_PIXELS_PER_BYTE[] = {0, 8, 8, 2, 2, 1};
-static const int RGB_BYTES_PER_PIXEL[] = {0, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4};
-
-
-#define LZ_MAGIC (*(uint32_t *)"LZ ")
-#define LZ_VERSION_MAJOR 1U
-#define LZ_VERSION_MINOR 1U
-#define LZ_VERSION ((LZ_VERSION_MAJOR << 16) | (LZ_VERSION_MINOR & 0xffff))
-
-
-#endif // _LZ_COMMON_H
diff --git a/common/lz_compress_tmpl.c b/common/lz_compress_tmpl.c
deleted file mode 100644
index 18d6697..0000000
--- a/common/lz_compress_tmpl.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-
- Copyright 2009 Red Hat, Inc. and/or its affiliates.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- This file incorporates work covered by the following copyright and
- permission notice:
- Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya at kde.org)
-
- 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 OR COPYRIGHT HOLDERS
- 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.
-
-*/
-
-#define DJB2_START 5381;
-#define DJB2_HASH(hash, c) (hash = ((hash << 5) + hash) ^ (c)) //|{hash = ((hash << 5) + hash) + c;}
-
-/*
- For each pixel type the following macros are defined:
- PIXEL : input type
- FNAME(name)
- ENCODE_PIXEL(encoder, pixel) : writing a pixel to the compressed buffer (byte by byte)
- SAME_PIXEL(pix1, pix2) : comparing two pixels
- HASH_FUNC(value, pix_ptr) : hash func of 3 consecutive pixels
-*/
-
-#ifdef LZ_PLT
-#define PIXEL one_byte_pixel_t
-#define FNAME(name) lz_plt_##name
-#define ENCODE_PIXEL(e, pix) encode(e, (pix).a) // gets the pixel and write only the needed bytes
- // from the pixel
-#define SAME_PIXEL(pix1, pix2) ((pix1).a == (pix2).a)
-#define HASH_FUNC(v, p) { \
- v = DJB2_START; \
- DJB2_HASH(v, p[0].a); \
- DJB2_HASH(v, p[1].a); \
- DJB2_HASH(v, p[2].a); \
- v &= HASH_MASK; \
- }
-#endif
-
-#ifdef LZ_RGB_ALPHA
-//#undef LZ_RGB_ALPHA
-#define PIXEL rgb32_pixel_t
-#define FNAME(name) lz_rgb_alpha_##name
-#define ENCODE_PIXEL(e, pix) {encode(e, (pix).pad);}
-#define SAME_PIXEL(pix1, pix2) ((pix1).pad == (pix2).pad)
-#define HASH_FUNC(v, p) { \
- v = DJB2_START; \
- DJB2_HASH(v, p[0].pad); \
- DJB2_HASH(v, p[1].pad); \
- DJB2_HASH(v, p[2].pad); \
- v &= HASH_MASK; \
- }
-#endif
-
-
-#ifdef LZ_RGB16
-#define PIXEL rgb16_pixel_t
-#define FNAME(name) lz_rgb16_##name
-#define GET_r(pix) (((pix) >> 10) & 0x1f)
-#define GET_g(pix) (((pix) >> 5) & 0x1f)
-#define GET_b(pix) ((pix) & 0x1f)
-#define ENCODE_PIXEL(e, pix) {encode(e, (pix) >> 8); encode(e, (pix) & 0xff);}
-
-#define HASH_FUNC(v, p) { \
- v = DJB2_START; \
- DJB2_HASH(v, p[0] & (0x00ff)); \
- DJB2_HASH(v, (p[0] >> 8) & (0x007f)); \
- DJB2_HASH(v, p[1]&(0x00ff)); \
- DJB2_HASH(v, (p[1] >> 8) & (0x007f)); \
- DJB2_HASH(v, p[2] & (0x00ff)); \
- DJB2_HASH(v, (p[2] >> 8) & (0x007f)); \
- v &= HASH_MASK; \
-}
-#endif
-
-#ifdef LZ_RGB24
-#define PIXEL rgb24_pixel_t
-#define FNAME(name) lz_rgb24_##name
-#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);}
-#endif
-
-#ifdef LZ_RGB32
-#define PIXEL rgb32_pixel_t
-#define FNAME(name) lz_rgb32_##name
-#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);}
-#endif
-
-
-#if defined(LZ_RGB24) || defined(LZ_RGB32)
-#define GET_r(pix) ((pix).r)
-#define GET_g(pix) ((pix).g)
-#define GET_b(pix) ((pix).b)
-#define HASH_FUNC(v, p) { \
- v = DJB2_START; \
- DJB2_HASH(v, p[0].r); \
- DJB2_HASH(v, p[0].g); \
- DJB2_HASH(v, p[0].b); \
- DJB2_HASH(v, p[1].r); \
- DJB2_HASH(v, p[1].g); \
- DJB2_HASH(v, p[1].b); \
- DJB2_HASH(v, p[2].r); \
- DJB2_HASH(v, p[2].g); \
- DJB2_HASH(v, p[2].b); \
- v &= HASH_MASK; \
- }
-#endif
-
-#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32)
-#define SAME_PIXEL(p1, p2) (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \
- GET_b(p1) == GET_b(p2))
-
-#endif
-
-#define PIXEL_ID(pix_ptr, seg_ptr) (pix_ptr - ((PIXEL *)seg_ptr->lines) + seg_ptr->size_delta)
-
-// when encoding, the ref can be in previous segment, and we should check that it doesn't
-// exceeds its bounds.
-// TODO: optimization: when only one chunk exists or when the reference is in the same segment,
-// don't make checks if we reach end of segments
-// TODO: optimize to continue match between segments?
-// TODO: check hash function
-// TODO: check times
-
-/* compresses one segment starting from 'from'.*/
-static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *from, int copied)
-{
- const PIXEL *ip = from;
- const PIXEL *ip_bound = (PIXEL *)(seg->lines_end) - BOUND_OFFSET;
- const PIXEL *ip_limit = (PIXEL *)(seg->lines_end) - LIMIT_OFFSET;
- HashEntry *hslot;
- int hval;
- int copy = copied;
-
- if (copy == 0) {
- encode_copy_count(encoder, MAX_COPY - 1);
- }
-
-
- while (LZ_EXPECT_CONDITIONAL(ip < ip_limit)) { // TODO: maybe change ip_limit and enabling
- // moving to the next seg
- const PIXEL *ref;
- const PIXEL *ref_limit;
- size_t distance;
-
- /* minimum match length */
-#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
- size_t len = 3;
-#elif defined(LZ_RGB16)
- size_t len = 2;
-#else
- size_t len = 1;
-#endif
- /* comparison starting-point */
- const PIXEL *anchor = ip;
-
-
-
- // TODO: RLE without checking if not first byte.
- // TODO: optimize comparisons
-
- /* check for a run */ // TODO for RGB we can use less pixels
- if (LZ_EXPECT_CONDITIONAL(ip > (PIXEL *)(seg->lines))) {
- if (SAME_PIXEL(ip[-1], ip[0]) && SAME_PIXEL(ip[0], ip[1]) && SAME_PIXEL(ip[1], ip[2])) {
- distance = 1;
- ip += 3;
- ref = anchor + 2;
- ref_limit = (PIXEL *)(seg->lines_end);
-#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32)
- len = 3;
-#endif
- goto match;
- }
- }
-
- /* find potential match */
- HASH_FUNC(hval, ip);
- hslot = encoder->htab + hval;
- ref = (PIXEL *)(hslot->ref);
- ref_limit = (PIXEL *)(hslot->image_seg->lines_end);
-
- /* calculate distance to the match */
- distance = PIXEL_ID(anchor, seg) - PIXEL_ID(ref, hslot->image_seg);
-
- /* update hash table */
- hslot->image_seg = seg;
- hslot->ref = (uint8_t *)anchor;
-
- /* is this a match? check the first 3 pixels */
- if (distance == 0 || (distance >= MAX_FARDISTANCE)) {
- goto literal;
- }
- /* check if the hval key identical*/
- // no need to check ref limit here because the word size in the htab is 3 pixels
- if (!SAME_PIXEL(*ref, *ip)) {
- ref++;
- ip++;
- goto literal;
- }
- ref++;
- ip++;
-
- /* minimum match length for rgb16 is 2 and for plt and alpha is 3 */
-#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_RGB16)
- if (!SAME_PIXEL(*ref, *ip)) {
- ref++;
- ip++;
- goto literal;
- }
- ref++;
- ip++;
-#endif
-
-#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
- if (!SAME_PIXEL(*ref, *ip)) {
- ref++;
- ip++;
- goto literal;
- }
- ref++;
- ip++;
-#endif
- /* far, needs at least 5-byte match */
- if (distance >= MAX_DISTANCE) {
-#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
- if (ref >= (ref_limit - 1)) {
- goto literal;
- }
-#else
- if (ref > (ref_limit - 1)) {
- goto literal;
- }
-#endif
- if (!SAME_PIXEL(*ref, *ip)) {
- ref++;
- ip++;
- goto literal;
- }
- ref++;
- ip++;
- len++;
-#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
- if (!SAME_PIXEL(*ref, *ip)) {
- ref++;
- ip++;
- goto literal;
- }
- ref++;
- ip++;
- len++;
-#endif
- }
-match: // RLE or dictionary (both are encoded by distance from ref (-1) and length)
-
- /* distance is biased */
- distance--;
-
- // ip is located now at the position of the second mismatch.
- // later it will be subtracted by 3
-
- if (!distance) {
- /* zero distance means a run */
- PIXEL x = *ref;
- while ((ip < ip_bound) && (ref < ref_limit)) { // TODO: maybe separate a run from
- // the same seg or from different
- // ones in order to spare
- // ref < ref_limit
- if (!SAME_PIXEL(*ref, x)) {
- ref++;
- break;
- } else {
- ref++;
- ip++;
- }
- }
- } else {
- // TODO: maybe separate a run from the same seg or from different ones in order
- // to spare ref < ref_limit and that way we can also perform 8 calls of
- // (ref++ != ip++) outside a loop
- for (;;) {
- while ((ip < ip_bound) && (ref < ref_limit)) {
- if (!SAME_PIXEL(*ref, *ip)) {
- ref++;
- ip++;
- break;
- } else {
- ref++;
- ip++;
- }
- }
- break;
- }
- }
-
- /* if we have copied something, adjust the copy count */
- if (copy) {
- /* copy is biased, '0' means 1 byte copy */
- update_copy_count(encoder, copy - 1);
- } else {
- /* back, to overwrite the copy count */
- compress_output_prev(encoder);
- }
-
- /* reset literal counter */
- copy = 0;
-
- /* length is biased, '1' means a match of 3 pixels for PLT and alpha*/
- /* for RGB 16 1 means 2 */
- /* for RGB24/32 1 means 1...*/
- ip -= 3;
- len = ip - anchor;
-#if defined(LZ_RGB16)
- len++;
-#elif defined(LZ_RGB24) || defined(LZ_RGB32)
- len += 2;
-#endif
- /* encode the match (like fastlz level 2)*/
- if (distance < MAX_DISTANCE) { // MAX_DISTANCE is 2^13 - 1
- // when copy is performed, the byte that holds the copy count is smaller than 32.
- // When there is a reference, the first byte is always larger then 32
-
- // 3 bits = length, 5 bits = 5 MSB of distance, 8 bits = 8 LSB of distance
- if (len < 7) {
- encode(encoder, (uint8_t)((len << 5) + (distance >> 8)));
- encode(encoder, (uint8_t)(distance & 255));
- } else { // more than 3 bits are needed for length
- // 3 bits 7, 5 bits = 5 MSB of distance, next bytes are 255 till we
- // receive a smaller number, last byte = 8 LSB of distance
- encode(encoder, (uint8_t)((7 << 5) + (distance >> 8)));
- for (len -= 7; len >= 255; len -= 255) {
- encode(encoder, 255);
- }
- encode(encoder, (uint8_t)len);
- encode(encoder, (uint8_t)(distance & 255));
- }
- } else {
- /* far away */
- if (len < 7) { // the max_far_distance is ~2^16+2^13 so two more bytes are needed
- // 3 bits = length, 5 bits = 5 MSB of MAX_DISTANCE, 8 bits = 8 LSB of MAX_DISTANCE,
- // 8 bits = 8 MSB distance-MAX_distance (smaller than 2^16),8 bits=8 LSB of
- // distance-MAX_distance
- distance -= MAX_DISTANCE;
- encode(encoder, (uint8_t)((len << 5) + 31));
- encode(encoder, (uint8_t)255);
- encode(encoder, (uint8_t)(distance >> 8));
- encode(encoder, (uint8_t)(distance & 255));
- } else {
- // same as before, but the first byte is followed by the left overs of len
- distance -= MAX_DISTANCE;
- encode(encoder, (uint8_t)((7 << 5) + 31));
- for (len -= 7; len >= 255; len -= 255) {
- encode(encoder, 255);
- }
- encode(encoder, (uint8_t)len);
- encode(encoder, 255);
- encode(encoder, (uint8_t)(distance >> 8));
- encode(encoder, (uint8_t)(distance & 255));
- }
- }
-
- /* update the hash at match boundary */
-#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32)
- if (ip > anchor) {
-#endif
- HASH_FUNC(hval, ip);
- encoder->htab[hval].ref = (uint8_t *)ip;
- ip++;
- encoder->htab[hval].image_seg = seg;
-#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32)
- } else {ip++;
- }
-#endif
-#if defined(LZ_RGB24) || defined(LZ_RGB32)
- if (ip > anchor) {
-#endif
- HASH_FUNC(hval, ip);
- encoder->htab[hval].ref = (uint8_t *)ip;
- ip++;
- encoder->htab[hval].image_seg = seg;
-#if defined(LZ_RGB24) || defined(LZ_RGB32)
- } else {ip++;
- }
-#endif
- /* assuming literal copy */
- encode_copy_count(encoder, MAX_COPY - 1);
- continue;
-
-literal:
- ENCODE_PIXEL(encoder, *anchor);
- anchor++;
- ip = anchor;
- copy++;
-
- if (LZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) {
- copy = 0;
- encode_copy_count(encoder, MAX_COPY - 1);
- }
- } // END LOOP (ip < ip_limit)
-
-
- /* left-over as literal copy */
- ip_bound++;
- while (ip <= ip_bound) {
- ENCODE_PIXEL(encoder, *ip);
- ip++;
- copy++;
- if (copy == MAX_COPY) {
- copy = 0;
- encode_copy_count(encoder, MAX_COPY - 1);
- }
- }
-
- /* if we have copied something, adjust the copy length */
- if (copy) {
- update_copy_count(encoder, copy - 1);
- } else {
- compress_output_prev(encoder); // in case we created a new buffer for copy, check that
- // red_worker could handle size that do not contain the
- // ne buffer
- }
-}
-
-
-/* initializes the hash table. if the file is very small, copies it.
- copies the first two pixels of the first segment, and sends the segments
- one by one to compress_seg.
- the number of bytes compressed are stored inside encoder.
- */
-static void FNAME(compress)(Encoder *encoder)
-{
- LzImageSegment *cur_seg = encoder->head_image_segs;
- HashEntry *hslot;
- PIXEL *ip;
-
- // fetch the first image segment that is not too small
- while (cur_seg && ((((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) < 4)) {
- // coping the segment
- if (cur_seg->lines != cur_seg->lines_end) {
- ip = (PIXEL *)cur_seg->lines;
- // Note: we assume MAX_COPY > 3
- encode_copy_count(encoder, (uint8_t)(
- (((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) - 1));
- while (ip < (PIXEL *)cur_seg->lines_end) {
- ENCODE_PIXEL(encoder, *ip);
- ip++;
- }
- }
- cur_seg = cur_seg->next;
- }
-
- if (!cur_seg) {
- return;
- }
-
- ip = (PIXEL *)cur_seg->lines;
-
- /* initialize hash table */
- for (hslot = encoder->htab; hslot < encoder->htab + HASH_SIZE; hslot++) {
- hslot->ref = (uint8_t*)ip;
- hslot->image_seg = cur_seg;
- }
-
- encode_copy_count(encoder, MAX_COPY - 1);
- ENCODE_PIXEL(encoder, *ip);
- ip++;
- ENCODE_PIXEL(encoder, *ip);
- ip++;
-
- // compressing the first segment
- FNAME(compress_seg)(encoder, cur_seg, ip, 2);
-
- // compressing the next segments
- for (cur_seg = cur_seg->next; cur_seg; cur_seg = cur_seg->next) {
- FNAME(compress_seg)(encoder, cur_seg, (PIXEL *)cur_seg->lines, 0);
- }
-}
-
-#undef FNAME
-#undef PIXEL_ID
-#undef PIXEL
-#undef ENCODE_PIXEL
-#undef SAME_PIXEL
-#undef LZ_READU16
-#undef HASH_FUNC
-#undef BYTES_TO_16
-#undef HASH_FUNC_16
-#undef GET_r
-#undef GET_g
-#undef GET_b
-#undef GET_CODE
-#undef LZ_PLT
-#undef LZ_RGB_ALPHA
-#undef LZ_RGB16
-#undef LZ_RGB24
-#undef LZ_RGB32
-#undef HASH_FUNC2
diff --git a/common/lz_config.h b/common/lz_config.h
deleted file mode 100644
index 439f413..0000000
--- a/common/lz_config.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
-
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#ifndef __LZ_CONFIG_H
-#define __LZ_CONFIG_H
-
-#include <spice/types.h>
-#include <spice/macros.h>
-
-#ifdef __GNUC__
-
-#include <string.h>
-
-#define INLINE inline
-
-#else
-
-#ifdef QXLDD
-#include <windef.h>
-#include "os_dep.h"
-#define INLINE _inline
-
-#else
-#include <stddef.h>
-#include <string.h>
-
-#define INLINE inline
-#endif // QXLDD
-
-#endif //__GNUC__
-#endif //__LZ_CONFIG_H
diff --git a/common/lz_decompress_tmpl.c b/common/lz_decompress_tmpl.c
deleted file mode 100644
index aa403f6..0000000
--- a/common/lz_decompress_tmpl.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-
- Copyright 2009 Red Hat, Inc. and/or its affiliates.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-
- This file incorporates work covered by the following copyright and
- permission notice:
- Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya at kde.org)
-
- 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 OR COPYRIGHT HOLDERS
- 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.
-
-*/
-
-// External defines: PLT, RGBX/PLTXX/ALPHA, TO_RGB32.
-// If PLT4/1 and TO_RGB32 are defined, we need CAST_PLT_DISTANCE (because then the number of
-// pixels differ from the units used in the compression)
-
-/*
- For each output pixel type the following macros are defined:
- OUT_PIXEL - the output pixel type
- COPY_PIXEL(p, out) - assigns the pixel to the place pointed by out and increases
- out. Used in RLE. Need special handling because in alpha we
- copy only the pad byte.
- COPY_REF_PIXEL(ref, out) - copies the pixel pointed by ref to the pixel pointed by out.
- Increases ref and out.
- COPY_COMP_PIXEL(encoder, out) - copies pixel from the compressed buffer to the decompressed
- buffer. Increases out.
-*/
-#if !defined(LZ_RGB_ALPHA)
-#define COPY_PIXEL(p, out) (*out++ = p)
-#define COPY_REF_PIXEL(ref, out) (*out++ = *ref++)
-#endif
-
-
-// decompressing plt to plt
-#ifdef LZ_PLT
-#ifndef TO_RGB32
-#define OUT_PIXEL one_byte_pixel_t
-#define FNAME(name) lz_plt_##name
-#define COPY_COMP_PIXEL(encoder, out) {out->a = decode(encoder); out++;}
-#else // TO_RGB32
-#define OUT_PIXEL rgb32_pixel_t
-#define COPY_PLT_ENTRY(ent, out) { \
- (out)->b = ent; \
- (out)->g = (ent >> 8); \
- (out)->r = (ent >> 16); \
- (out)->pad = 0; \
-}
-#ifdef PLT8
-#define FNAME(name) lz_plt8_to_rgb32_##name
-#define COPY_COMP_PIXEL(encoder, out) { \
- uint32_t rgb = encoder->palette->ents[decode(encoder)]; \
- COPY_PLT_ENTRY(rgb, out); \
- out++;}
-#elif defined(PLT4_BE)
-#define FNAME(name) lz_plt4_be_to_rgb32_##name
-#define COPY_COMP_PIXEL(encoder, out){ \
- uint8_t byte = decode(encoder); \
- uint32_t rgb = encoder->palette->ents[((byte >> 4) & 0x0f) % (encoder->palette->num_ents)]; \
- COPY_PLT_ENTRY(rgb, out); \
- out++; \
- rgb = encoder->palette->ents[(byte & 0x0f) % (encoder->palette->num_ents)]; \
- COPY_PLT_ENTRY(rgb, out); \
- out++; \
-}
-#define CAST_PLT_DISTANCE(dist) (dist*2)
-#elif defined(PLT4_LE)
-#define FNAME(name) lz_plt4_le_to_rgb32_##name
-#define COPY_COMP_PIXEL(encoder, out){ \
- uint8_t byte = decode(encoder); \
- uint32_t rgb = encoder->palette->ents[(byte & 0x0f) % (encoder->palette->num_ents)]; \
- COPY_PLT_ENTRY(rgb, out); \
- out++; \
- rgb = encoder->palette->ents[((byte >> 4) & 0x0f) % (encoder->palette->num_ents)]; \
- COPY_PLT_ENTRY(rgb, out); \
- out++; \
-}
-#define CAST_PLT_DISTANCE(dist) (dist*2)
-#elif defined(PLT1_BE) // TODO store palette entries for direct access
-#define FNAME(name) lz_plt1_be_to_rgb32_##name
-#define COPY_COMP_PIXEL(encoder, out){ \
- uint8_t byte = decode(encoder); \
- int i; \
- uint32_t fore = encoder->palette->ents[1]; \
- uint32_t back = encoder->palette->ents[0]; \
- for (i = 7; i >= 0; i--) \
- { \
- if ((byte >> i) & 1) { \
- COPY_PLT_ENTRY(fore, out); \
- } else { \
- COPY_PLT_ENTRY(back, out); \
- } \
- out++; \
- } \
-}
-#define CAST_PLT_DISTANCE(dist) (dist*8)
-#elif defined(PLT1_LE)
-#define FNAME(name) lz_plt1_le_to_rgb32_##name
-#define COPY_COMP_PIXEL(encoder, out){ \
- uint8_t byte = decode(encoder); \
- int i; \
- uint32_t fore = encoder->palette->ents[1]; \
- uint32_t back = encoder->palette->ents[0]; \
- for (i = 0; i < 8; i++) \
- { \
- if ((byte >> i) & 1) { \
- COPY_PLT_ENTRY(fore, out); \
- } else { \
- COPY_PLT_ENTRY(back, out); \
- } \
- out++; \
- } \
-}
-#define CAST_PLT_DISTANCE(dist) (dist*8)
-#endif // PLT Type
-#endif // TO_RGB32
-#endif
-
-#ifdef LZ_RGB16
-#ifndef TO_RGB32
-#define OUT_PIXEL rgb16_pixel_t
-#define FNAME(name) lz_rgb16_##name
-#define COPY_COMP_PIXEL(e, out) {*out = ((decode(e) << 8) | decode(e)); out++;}
-#else
-#define OUT_PIXEL rgb32_pixel_t
-#define FNAME(name) lz_rgb16_to_rgb32_##name
-#define COPY_COMP_PIXEL(e, out) { \
- out->r = decode(e); \
- out->b = decode(e); \
- out->g = (((out->r) << 6) | ((out->b) >> 2)) & ~0x07; \
- out->g |= (out->g >> 5); \
- out->r = ((out->r << 1) & ~0x07)| ((out->r >> 4) & 0x07); \
- out->b = (out->b << 3) | ((out->b >> 2) & 0x07); \
- out->pad = 0; \
- out++; \
-}
-#endif
-#endif
-
-#ifdef LZ_RGB24
-#define OUT_PIXEL rgb24_pixel_t
-#define FNAME(name) lz_rgb24_##name
-#define COPY_COMP_PIXEL(e, out) {out->b = decode(e); out->g = decode(e); out->r = decode(e); out++;}
-#endif
-
-#ifdef LZ_RGB32
-#define OUT_PIXEL rgb32_pixel_t
-#define FNAME(name) lz_rgb32_##name
-#define COPY_COMP_PIXEL(e, out) { \
- out->b = decode(e); \
- out->g = decode(e); \
- out->r = decode(e); \
- out->pad = 0; \
- out++; \
-}
-#endif
-
-#ifdef LZ_RGB_ALPHA
-#define OUT_PIXEL rgb32_pixel_t
-#define FNAME(name) lz_rgb_alpha_##name
-#define COPY_PIXEL(p, out) {out->pad = p.pad; out++;}
-#define COPY_REF_PIXEL(ref, out) {out->pad = ref->pad; out++; ref++;}
-#define COPY_COMP_PIXEL(e, out) {out->pad = decode(e); out++;}
-#endif
-
-// return num of bytes in out_buf
-static size_t FNAME(decompress)(Encoder *encoder, OUT_PIXEL *out_buf, int size)
-{
- OUT_PIXEL *op = out_buf;
- OUT_PIXEL *op_limit = out_buf + size;
- uint32_t ctrl = decode(encoder);
- int loop = TRUE;
-
- do {
- const OUT_PIXEL *ref = op;
- uint32_t len = ctrl >> 5;
- uint32_t ofs = (ctrl & 31) << 8; // 5 MSb of distance
-
- if (ctrl >= MAX_COPY) { // reference (dictionary/RLE)
- /* retrieving the reference and the match length */
-
- uint8_t code;
- len--;
- //ref -= ofs;
- if (len == 7 - 1) { // match length is bigger than 7
- do {
- code = decode(encoder);
- len += code;
- } while (code == 255); // remaining of len
- }
- code = decode(encoder);
- ofs += code;
-
- /* match from 16-bit distance */
- if (LZ_UNEXPECT_CONDITIONAL(code == 255)) {
- if (LZ_EXPECT_CONDITIONAL((ofs - code) == (31 << 8))) {
- ofs = decode(encoder) << 8;
- ofs += decode(encoder);
- ofs += MAX_DISTANCE;
- }
- }
-
-#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
- len += 3; // length is biased by 2 + 1 (fixing bias)
-#elif defined(LZ_RGB16)
- len += 2; // length is biased by 1 + 1 (fixing bias)
-#else
- len += 1;
-#endif
- ofs += 1; // offset is biased by 1 (fixing bias)
-
-#if defined(TO_RGB32)
-#if defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || defined(PLT1_LE)
- ofs = CAST_PLT_DISTANCE(ofs);
- len = CAST_PLT_DISTANCE(len);
-#endif
-#endif
- ref -= ofs;
-
- ASSERT(encoder->usr, op + len <= op_limit);
- ASSERT(encoder->usr, ref + len <= op_limit);
- ASSERT(encoder->usr, ref >= out_buf);
-
- // TODO: optimize by not calling loop at least 3 times when not PLT_TO_RGB32 (len is
- // always >=3). in PLT_TO_RGB32 len >= 3*number_of_pixels_per_byte
-
- /* copying the match*/
-
- if (ref == (op - 1)) { // run // TODO: this will never be called in PLT4/1_TO_RGB
- // because the number of pixel copied is larger
- // then one...
- /* optimize copy for a run */
- OUT_PIXEL b = *ref;
- for (; len; --len) {
- COPY_PIXEL(b, op);
- ASSERT(encoder->usr, op <= op_limit);
- }
- } else {
- for (; len; --len) {
- COPY_REF_PIXEL(ref, op);
- ASSERT(encoder->usr, op <= op_limit);
- }
- }
- } else { // copy
- ctrl++; // copy count is biased by 1
-#if defined(TO_RGB32) && (defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || \
- defined(PLT1_LE))
- ASSERT(encoder->usr, op + CAST_PLT_DISTANCE(ctrl) <= op_limit);
-#else
- ASSERT(encoder->usr, op + ctrl <= op_limit);
-#endif
- COPY_COMP_PIXEL(encoder, op);
-
- ASSERT(encoder->usr, op <= op_limit);
-
- for (--ctrl; ctrl; ctrl--) {
- COPY_COMP_PIXEL(encoder, op);
- ASSERT(encoder->usr, op <= op_limit);
- }
- }
-
- if (LZ_EXPECT_CONDITIONAL(op < op_limit)) {
- ctrl = decode(encoder);
- } else {
- loop = FALSE;
- }
- } while (LZ_EXPECT_CONDITIONAL(loop));
-
- return (op - out_buf);
-}
-
-#undef LZ_PLT
-#undef PLT8
-#undef PLT4_BE
-#undef PLT4_LE
-#undef PLT1_BE
-#undef PLT1_LE
-#undef LZ_RGB16
-#undef LZ_RGB24
-#undef LZ_RGB32
-#undef LZ_RGB_ALPHA
-#undef TO_RGB32
-#undef OUT_PIXEL
-#undef FNAME
-#undef COPY_PIXEL
-#undef COPY_REF_PIXEL
-#undef COPY_COMP_PIXEL
-#undef COPY_PLT_ENTRY
-#undef CAST_PLT_DISTANCE
-
diff --git a/common/macros.h b/common/macros.h
deleted file mode 100644
index 44a37e4..0000000
--- a/common/macros.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __MACROS_H
-#define __MACROS_H
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
-#define ATTR_PRINTF(a,b) \
- __attribute__((format(printf,a,b)))
-#else
-#define ATTR_PRINTF(a,b)
-#endif /* __GNUC__ */
-
-
-#endif /* __MACROS_H */
diff --git a/common/marshaller.c b/common/marshaller.c
deleted file mode 100644
index 57ca32e..0000000
--- a/common/marshaller.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2010 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "config.h"
-
-#include "marshaller.h"
-#include "mem.h"
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#ifdef WORDS_BIGENDIAN
-#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v)
-#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v)
-#define write_int16(ptr,v) (*((int16_t *)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v)))
-#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v)))
-#define write_int32(ptr,v) (*((int32_t *)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v)))
-#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v)))
-#define write_int64(ptr,v) (*((int64_t *)(ptr)) = SPICE_BYTESWAP64((uint64_t)(v)))
-#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = SPICE_BYTESWAP64((uint64_t)(v)))
-#else
-#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v)
-#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v)
-#define write_int16(ptr,v) (*((int16_t *)(ptr)) = v)
-#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = v)
-#define write_int32(ptr,v) (*((int32_t *)(ptr)) = v)
-#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = v)
-#define write_int64(ptr,v) (*((int64_t *)(ptr)) = v)
-#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = v)
-#endif
-
-typedef struct {
- uint8_t *data;
- size_t len;
- spice_marshaller_item_free_func free_data;
- void *opaque;
-} MarshallerItem;
-
-/* Try to fit in 4k page with 2*pointer-size overhead (next ptr and malloc size) */
-#define MARSHALLER_BUFFER_SIZE (4096 - sizeof(void *) * 2)
-
-typedef struct MarshallerBuffer MarshallerBuffer;
-struct MarshallerBuffer {
- MarshallerBuffer *next;
- uint8_t data[MARSHALLER_BUFFER_SIZE];
-};
-
-#define N_STATIC_ITEMS 4
-
-typedef struct SpiceMarshallerData SpiceMarshallerData;
-
-typedef struct {
- SpiceMarshaller *marshaller;
- int item_nr;
- int is_64bit;
- size_t offset;
-} MarshallerRef;
-
-struct SpiceMarshaller {
- size_t total_size;
- SpiceMarshallerData *data;
- SpiceMarshaller *next;
-
- MarshallerRef pointer_ref;
-
- int n_items;
- int items_size; /* number of items availible in items */
- MarshallerItem *items;
-
- MarshallerItem static_items[N_STATIC_ITEMS];
-};
-
-struct SpiceMarshallerData {
- size_t total_size;
- size_t base;
- SpiceMarshaller *marshallers;
- SpiceMarshaller *last_marshaller;
-
- size_t current_buffer_position;
- MarshallerBuffer *current_buffer;
- MarshallerItem *current_buffer_item;
- MarshallerBuffer *buffers;
-
- SpiceMarshaller static_marshaller;
- MarshallerBuffer static_buffer;
-};
-
-static void spice_marshaller_init(SpiceMarshaller *m,
- SpiceMarshallerData *data)
-{
- m->data = data;
- m->next = NULL;
- m->total_size = 0;
- m->pointer_ref.marshaller = NULL;
- m->n_items = 0;
- m->items_size = N_STATIC_ITEMS;
- m->items = m->static_items;
-}
-
-SpiceMarshaller *spice_marshaller_new(void)
-{
- SpiceMarshallerData *d;
- SpiceMarshaller *m;
-
- d = spice_new(SpiceMarshallerData, 1);
-
- d->last_marshaller = d->marshallers = &d->static_marshaller;
- d->total_size = 0;
- d->base = 0;
- d->buffers = &d->static_buffer;
- d->buffers->next = NULL;
- d->current_buffer = d->buffers;
- d->current_buffer_position = 0;
- d->current_buffer_item = NULL;
-
- m = &d->static_marshaller;
- spice_marshaller_init(m, d);
-
- return m;
-}
-
-static void free_item_data(SpiceMarshaller *m)
-{
- MarshallerItem *item;
- int i;
-
- /* Free all user data */
- for (i = 0; i < m->n_items; i++) {
- item = &m->items[i];
- if (item->free_data != NULL) {
- item->free_data(item->data, item->opaque);
- }
- }
-}
-
-static void free_items(SpiceMarshaller *m)
-{
- if (m->items != m->static_items) {
- free(m->items);
- }
-}
-
-void spice_marshaller_reset(SpiceMarshaller *m)
-{
- SpiceMarshaller *m2, *next;
- SpiceMarshallerData *d;
-
- /* Only supported for root marshaller */
- assert(m->data->marshallers == m);
-
- for (m2 = m; m2 != NULL; m2 = next) {
- next = m2->next;
- free_item_data(m2);
-
- /* Free non-root marshallers */
- if (m2 != m) {
- free_items(m2);
- free(m2);
- }
- }
-
- m->next = NULL;
- m->n_items = 0;
- m->total_size = 0;
-
- d = m->data;
- d->last_marshaller = d->marshallers;
- d->total_size = 0;
- d->base = 0;
- d->current_buffer_item = NULL;
- d->current_buffer = d->buffers;
- d->current_buffer_position = 0;
-}
-
-void spice_marshaller_destroy(SpiceMarshaller *m)
-{
- MarshallerBuffer *buf, *next;
- SpiceMarshallerData *d;
-
- /* Only supported for root marshaller */
- assert(m->data->marshallers == m);
-
- spice_marshaller_reset(m);
-
- free_items(m);
-
- d = m->data;
-
- buf = d->buffers->next;
- while (buf != NULL) {
- next = buf->next;
- free(buf);
- buf = next;
- }
-
- free(d);
-}
-
-static MarshallerItem *spice_marshaller_add_item(SpiceMarshaller *m)
-{
- MarshallerItem *item;
-
- if (m->n_items == m->items_size) {
- int items_size = m->items_size * 2;
-
- if (m->items == m->static_items) {
- m->items = spice_new(MarshallerItem, items_size);
- memcpy(m->items, m->static_items, sizeof(MarshallerItem) * m->n_items);
- } else {
- m->items = spice_renew(MarshallerItem, m->items, items_size);
- }
- m->items_size = items_size;
- }
- item = &m->items[m->n_items++];
- item->free_data = NULL;
-
- return item;
-}
-
-static size_t remaining_buffer_size(SpiceMarshallerData *d)
-{
- return MARSHALLER_BUFFER_SIZE - d->current_buffer_position;
-}
-
-uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size)
-{
- MarshallerItem *item;
- SpiceMarshallerData *d;
- uint8_t *res;
-
- if (size == 0) {
- return NULL;
- }
-
- d = m->data;
-
- /* Check current item */
- item = &m->items[m->n_items - 1];
- if (item == d->current_buffer_item &&
- remaining_buffer_size(d) >= size) {
- assert(m->n_items >= 1);
- /* We can piggy back on existing item+buffer */
- res = item->data + item->len;
- item->len += size;
- d->current_buffer_position += size;
- d->total_size += size;
- m->total_size += size;
- return res;
- }
-
- item = spice_marshaller_add_item(m);
-
- if (remaining_buffer_size(d) >= size) {
- /* Fits in current buffer */
- item->data = d->current_buffer->data + d->current_buffer_position;
- item->len = size;
- d->current_buffer_position += size;
- d->current_buffer_item = item;
- } else if (size > MARSHALLER_BUFFER_SIZE / 2) {
- /* Large item, allocate by itself */
- item->data = (uint8_t *)spice_malloc(size);
- item->len = size;
- item->free_data = (spice_marshaller_item_free_func)free;
- item->opaque = NULL;
- } else {
- /* Use next buffer */
- if (d->current_buffer->next == NULL) {
- d->current_buffer->next = spice_new(MarshallerBuffer, 1);
- d->current_buffer->next->next = NULL;
- }
- d->current_buffer = d->current_buffer->next;
- d->current_buffer_position = size;
- d->current_buffer_item = item;
- item->data = d->current_buffer->data;
- item->len = size;
- }
-
- d->total_size += size;
- m->total_size += size;
- return item->data;
-}
-
-void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size)
-{
- MarshallerItem *item;
-
- if (size == 0) {
- return;
- }
-
- item = &m->items[m->n_items - 1];
-
- assert(item->len >= size);
- item->len -= size;
-}
-
-uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size,
- spice_marshaller_item_free_func free_data, void *opaque)
-{
- MarshallerItem *item;
- SpiceMarshallerData *d;
-
- if (data == NULL || size == 0) {
- return NULL;
- }
-
- item = spice_marshaller_add_item(m);
- item->data = data;
- item->len = size;
- item->free_data = free_data;
- item->opaque = opaque;
-
- d = m->data;
- m->total_size += size;
- d->total_size += size;
-
- return data;
-}
-
-uint8_t *spice_marshaller_add(SpiceMarshaller *m, const uint8_t *data, size_t size)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, size);
- memcpy(ptr, data, size);
- return ptr;
-}
-
-uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, uint8_t *data, size_t size)
-{
- return spice_marshaller_add_ref_full(m, data, size, NULL, NULL);
-}
-
-void spice_marshaller_add_ref_chunks(SpiceMarshaller *m, SpiceChunks *chunks)
-{
- unsigned int i;
-
- for (i = 0; i < chunks->num_chunks; i++) {
- spice_marshaller_add_ref(m, chunks->chunk[i].data,
- chunks->chunk[i].len);
- }
-}
-
-SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m)
-{
- SpiceMarshallerData *d;
- SpiceMarshaller *m2;
-
- d = m->data;
-
- m2 = spice_new(SpiceMarshaller, 1);
- spice_marshaller_init(m2, d);
-
- d->last_marshaller->next = m2;
- d->last_marshaller = m2;
-
- return m2;
-}
-
-SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit)
-{
- SpiceMarshaller *m2;
- uint8_t *p;
- int size;
-
- size = is_64bit ? 8 : 4;
-
- p = spice_marshaller_reserve_space(m, size);
- memset(p, 0, size);
- m2 = spice_marshaller_get_submarshaller(m);
- m2->pointer_ref.marshaller = m;
- m2->pointer_ref.item_nr = m->n_items - 1;
- m2->pointer_ref.offset = m->items[m->n_items - 1].len - size;
- m2->pointer_ref.is_64bit = is_64bit;
-
- return m2;
-}
-
-static uint8_t *lookup_ref(MarshallerRef *ref)
-{
- MarshallerItem *item;
-
- item = &ref->marshaller->items[ref->item_nr];
- return item->data + ref->offset;
-}
-
-
-void spice_marshaller_set_base(SpiceMarshaller *m, size_t base)
-{
- /* Only supported for root marshaller */
- assert(m->data->marshallers == m);
-
- m->data->base = base;
-}
-
-uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip_bytes,
- size_t *len, int *free_res)
-{
- MarshallerItem *item;
- uint8_t *res, *p;
- int i;
-
- /* Only supported for root marshaller */
- assert(m->data->marshallers == m);
-
- if (m->n_items == 1) {
- *free_res = FALSE;
- if (m->items[0].len <= skip_bytes) {
- *len = 0;
- return NULL;
- }
- *len = m->items[0].len - skip_bytes;
- return m->items[0].data + skip_bytes;
- }
-
- *free_res = TRUE;
- res = (uint8_t *)spice_malloc(m->data->total_size - skip_bytes);
- *len = m->data->total_size - skip_bytes;
- p = res;
-
- do {
- for (i = 0; i < m->n_items; i++) {
- item = &m->items[i];
-
- if (item->len <= skip_bytes) {
- skip_bytes -= item->len;
- continue;
- }
- memcpy(p, item->data + skip_bytes, item->len - skip_bytes);
- p += item->len - skip_bytes;
- skip_bytes = 0;
- }
- m = m->next;
- } while (m != NULL);
-
- return res;
-}
-
-uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m)
-{
- return m->items[0].data;
-}
-
-size_t spice_marshaller_get_offset(SpiceMarshaller *m)
-{
- SpiceMarshaller *m2;
- size_t offset;
-
- offset = 0;
- m2 = m->data->marshallers;
- while (m2 != m) {
- offset += m2->total_size;
- m2 = m2->next;
- }
- return offset - m->data->base;
-}
-
-size_t spice_marshaller_get_size(SpiceMarshaller *m)
-{
- return m->total_size;
-}
-
-size_t spice_marshaller_get_total_size(SpiceMarshaller *m)
-{
- return m->data->total_size;
-}
-
-void spice_marshaller_flush(SpiceMarshaller *m)
-{
- SpiceMarshaller *m2;
- uint8_t *ptr_pos;
-
- /* Only supported for root marshaller */
- assert(m->data->marshallers == m);
-
- for (m2 = m; m2 != NULL; m2 = m2->next) {
- if (m2->pointer_ref.marshaller != NULL && m2->total_size > 0) {
- ptr_pos = lookup_ref(&m2->pointer_ref);
- if (m2->pointer_ref.is_64bit) {
- write_uint64(ptr_pos,
- spice_marshaller_get_offset(m2));
- } else {
- write_uint32(ptr_pos,
- spice_marshaller_get_offset(m2));
- }
- }
- }
-}
-
-#ifndef WIN32
-int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
- int n_vec, size_t skip_bytes)
-{
- MarshallerItem *item;
- int v, i;
-
- /* Only supported for root marshaller */
- assert(m->data->marshallers == m);
-
- v = 0;
- do {
- for (i = 0; i < m->n_items; i++) {
- item = &m->items[i];
-
- if (item->len <= skip_bytes) {
- skip_bytes -= item->len;
- continue;
- }
- if (v == n_vec) {
- return v; /* Not enough space in vec */
- }
- vec[v].iov_base = item->data + skip_bytes;
- vec[v].iov_len = item->len - skip_bytes;
- skip_bytes = 0;
- v++;
- }
- m = m->next;
- } while (m != NULL);
-
- return v;
-}
-#endif
-
-void *spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(uint64_t));
- write_uint64(ptr, v);
- return (void *)ptr;
-}
-
-void *spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(int64_t));
- write_int64(ptr, v);
- return (void *)ptr;
-}
-
-void *spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(uint32_t));
- write_uint32(ptr, v);
- return (void *)ptr;
-}
-
-void spice_marshaller_set_uint32(SpiceMarshaller *m, void *ref, uint32_t v)
-{
- write_uint32((uint8_t *)ref, v);
-}
-
-void *spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(int32_t));
- write_int32(ptr, v);
- return (void *)ptr;
-}
-
-void *spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(uint16_t));
- write_uint16(ptr, v);
- return (void *)ptr;
-}
-
-void *spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(int16_t));
- write_int16(ptr, v);
- return (void *)ptr;
-}
-
-void *spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(uint8_t));
- write_uint8(ptr, v);
- return (void *)ptr;
-}
-
-void *spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v)
-{
- uint8_t *ptr;
-
- ptr = spice_marshaller_reserve_space(m, sizeof(int8_t));
- write_int8(ptr, v);
- return (void *)ptr;
-}
diff --git a/common/marshaller.h b/common/marshaller.h
deleted file mode 100644
index ae68e85..0000000
--- a/common/marshaller.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2010 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_MARSHALLER
-#define _H_MARSHALLER
-
-#include <spice/types.h>
-#include "mem.h"
-#ifndef WIN32
-#include <sys/uio.h>
-#endif
-
-typedef struct SpiceMarshaller SpiceMarshaller;
-typedef void (*spice_marshaller_item_free_func)(uint8_t *data, void *opaque);
-
-SpiceMarshaller *spice_marshaller_new(void);
-void spice_marshaller_reset(SpiceMarshaller *m);
-void spice_marshaller_destroy(SpiceMarshaller *m);
-uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size);
-void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size);
-uint8_t *spice_marshaller_add(SpiceMarshaller *m, const uint8_t *data, size_t size);
-uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, uint8_t *data, size_t size);
-uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size,
- spice_marshaller_item_free_func free_data, void *opaque);
-void spice_marshaller_add_ref_chunks(SpiceMarshaller *m, SpiceChunks *chunks);
-void spice_marshaller_flush(SpiceMarshaller *m);
-void spice_marshaller_set_base(SpiceMarshaller *m, size_t base);
-uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip,
- size_t *len, int *free_res);
-uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m);
-size_t spice_marshaller_get_offset(SpiceMarshaller *m);
-size_t spice_marshaller_get_size(SpiceMarshaller *m);
-size_t spice_marshaller_get_total_size(SpiceMarshaller *m);
-SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m);
-SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit);
-#ifndef WIN32
-int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
- int n_vec, size_t skip_bytes);
-#endif
-void *spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v);
-void *spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v);
-void *spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v);
-void *spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v);
-void *spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v);
-void *spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v);
-void *spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v);
-void *spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v);
-
-void spice_marshaller_set_uint32(SpiceMarshaller *m, void *ref, uint32_t v);
-
-#endif
diff --git a/common/marshallers.h b/common/marshallers.h
deleted file mode 100644
index c192d5b..0000000
--- a/common/marshallers.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2010 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_MARSHALLERS
-#define _H_MARSHALLERS
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <spice/protocol.h>
-#include <marshaller.h>
-#include <messages.h>
-
-typedef struct {
- void (*msg_SpiceMsgEmpty)(SpiceMarshaller *m, SpiceMsgEmpty *msg);
- void (*msg_SpiceMsgData)(SpiceMarshaller *m, SpiceMsgData *msg);
- void (*msg_SpiceMsgAudioVolume)(SpiceMarshaller *m, SpiceMsgAudioVolume *msg);
- void (*msg_SpiceMsgAudioMute)(SpiceMarshaller *m, SpiceMsgAudioMute *msg);
- void (*msgc_ack_sync)(SpiceMarshaller *m, SpiceMsgcAckSync *msg);
- void (*msgc_pong)(SpiceMarshaller *m, SpiceMsgPing *msg);
- void (*msgc_disconnecting)(SpiceMarshaller *m, SpiceMsgDisconnect *msg);
- void (*msgc_main_client_info)(SpiceMarshaller *m, SpiceMsgcClientInfo *msg);
- void (*msgc_main_mouse_mode_request)(SpiceMarshaller *m, SpiceMsgcMainMouseModeRequest *msg);
- void (*msgc_main_agent_start)(SpiceMarshaller *m, SpiceMsgcMainAgentStart *msg);
- void (*msgc_main_agent_token)(SpiceMarshaller *m, SpiceMsgcMainAgentTokens *msg);
- void (*msgc_display_init)(SpiceMarshaller *m, SpiceMsgcDisplayInit *msg);
- void (*msgc_inputs_key_down)(SpiceMarshaller *m, SpiceMsgcKeyDown *msg);
- void (*msgc_inputs_key_up)(SpiceMarshaller *m, SpiceMsgcKeyUp *msg);
- void (*msgc_inputs_key_modifiers)(SpiceMarshaller *m, SpiceMsgcKeyModifiers *msg);
- void (*msgc_inputs_mouse_motion)(SpiceMarshaller *m, SpiceMsgcMouseMotion *msg);
- void (*msgc_inputs_mouse_position)(SpiceMarshaller *m, SpiceMsgcMousePosition *msg);
- void (*msgc_inputs_mouse_press)(SpiceMarshaller *m, SpiceMsgcMousePress *msg);
- void (*msgc_inputs_mouse_release)(SpiceMarshaller *m, SpiceMsgcMouseRelease *msg);
- void (*msgc_record_data)(SpiceMarshaller *m, SpiceMsgcRecordPacket *msg);
- void (*msgc_record_mode)(SpiceMarshaller *m, SpiceMsgcRecordMode *msg);
- void (*msgc_record_start_mark)(SpiceMarshaller *m, SpiceMsgcRecordStartMark *msg);
- void (*msgc_tunnel_service_add)(SpiceMarshaller *m, SpiceMsgcTunnelAddGenericService *msg, SpiceMarshaller **name_out, SpiceMarshaller **description_out);
- void (*msgc_tunnel_service_remove)(SpiceMarshaller *m, SpiceMsgcTunnelRemoveService *msg);
- void (*msgc_tunnel_socket_open_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenAck *msg);
- void (*msgc_tunnel_socket_open_nack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenNack *msg);
- void (*msgc_tunnel_socket_fin)(SpiceMarshaller *m, SpiceMsgcTunnelSocketFin *msg);
- void (*msgc_tunnel_socket_closed)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosed *msg);
- void (*msgc_tunnel_socket_closed_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosedAck *msg);
- void (*msgc_tunnel_socket_data)(SpiceMarshaller *m, SpiceMsgcTunnelSocketData *msg);
- void (*msgc_tunnel_socket_token)(SpiceMarshaller *m, SpiceMsgcTunnelSocketTokens *msg);
-#ifdef USE_SMARTCARD
- void (*msgc_smartcard_atr)(SpiceMarshaller *m, VSCMsgATR *msg);
- void (*msgc_smartcard_error)(SpiceMarshaller *m, VSCMsgError *msg);
- void (*msgc_smartcard_header)(SpiceMarshaller *m, VSCMsgHeader *msg);
- void (*msgc_smartcard_msg)(SpiceMarshaller *m, SpiceMsgcSmartcard *msg, SpiceMarshaller **reader_name_out);
- void (*msgc_smartcard_reader_add)(SpiceMarshaller *m, VSCMsgReaderAdd *msg);
-#endif
-} SpiceMessageMarshallers;
-
-SpiceMessageMarshallers *spice_message_marshallers_get(void);
-SpiceMessageMarshallers *spice_message_marshallers_get1(void);
-
-#endif
diff --git a/common/mem.c b/common/mem.c
deleted file mode 100644
index 4db8a2c..0000000
--- a/common/mem.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2010 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "mem.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef MALLOC_ERROR
-#define MALLOC_ERROR(format, ...) { \
- printf(format "\n", ## __VA_ARGS__); \
- abort(); \
-}
-#endif
-
-size_t spice_strnlen(const char *str, size_t max_len)
-{
- size_t len = 0;
-
- while (len < max_len && *str != 0) {
- len++;
- str++;
- }
-
- return len;
-}
-
-char *spice_strdup(const char *str)
-{
- char *copy;
-
- if (str == NULL) {
- return NULL;
- }
-
- copy = (char *)spice_malloc(strlen(str) + 1);
- strcpy(copy, str);
- return copy;
-}
-
-char *spice_strndup(const char *str, size_t n_bytes)
-{
- char *copy;
-
- if (str == NULL) {
- return NULL;
- }
-
- copy = (char *)spice_malloc(n_bytes + 1);
- strncpy(copy, str, n_bytes);
- copy[n_bytes] = 0;
- return copy;
-}
-
-void *spice_memdup(const void *mem, size_t n_bytes)
-{
- void *copy;
-
- if (mem == NULL) {
- return NULL;
- }
-
- copy = spice_malloc(n_bytes);
- memcpy(copy, mem, n_bytes);
- return copy;
-}
-
-void *spice_malloc(size_t n_bytes)
-{
- void *mem;
-
- if (SPICE_LIKELY(n_bytes)) {
- mem = malloc(n_bytes);
-
- if (SPICE_LIKELY(mem != NULL)) {
- return mem;
- }
-
- MALLOC_ERROR("spice_malloc: panic: unable to allocate %lu bytes\n",
- (unsigned long)n_bytes);
- }
- return NULL;
-}
-
-void *spice_malloc0(size_t n_bytes)
-{
- void *mem;
-
- if (SPICE_LIKELY(n_bytes)) {
- mem = calloc(1, n_bytes);
-
- if (SPICE_LIKELY(mem != NULL)) {
- return mem;
- }
-
- MALLOC_ERROR("spice_malloc0: panic: unable to allocate %lu bytes\n",
- (unsigned long)n_bytes);
- }
- return NULL;
-}
-
-void *spice_realloc(void *mem, size_t n_bytes)
-{
- if (SPICE_LIKELY(n_bytes)) {
- mem = realloc(mem, n_bytes);
-
- if (SPICE_LIKELY(mem != NULL)) {
- return mem;
- }
-
- MALLOC_ERROR("spice_realloc: panic: unable to allocate %lu bytes\n",
- (unsigned long)n_bytes);
- }
-
- if (mem) {
- free(mem);
- }
-
- return NULL;
-}
-
-#define SIZE_OVERFLOWS(a,b) (SPICE_UNLIKELY ((a) > SIZE_MAX / (b)))
-
-void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes)
-{
- if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
- MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu bytes",
- (unsigned long)n_blocks, (unsigned long)n_block_bytes);
- }
-
- return spice_malloc(n_blocks * n_block_bytes);
-}
-
-void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size)
-{
- size_t size1, size2;
- if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
- MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
- (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
- }
- size1 = n_blocks * n_block_bytes;
- size2 = size1 + extra_size;
- if (size2 < size1) {
- MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
- (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
- }
- return spice_malloc(size2);
-}
-
-
-void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes)
-{
- if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
- MALLOC_ERROR("spice_malloc0_n: overflow allocating %lu*%lu bytes",
- (unsigned long)n_blocks, (unsigned long)n_block_bytes);
- }
-
- return spice_malloc0 (n_blocks * n_block_bytes);
-}
-
-void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes)
-{
- if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
- MALLOC_ERROR("spice_realloc_n: overflow allocating %lu*%lu bytes",
- (unsigned long)n_blocks, (unsigned long)n_block_bytes);
- }
-
- return spice_realloc(mem, n_blocks * n_block_bytes);
-}
-
-SpiceChunks *spice_chunks_new(uint32_t count)
-{
- SpiceChunks *chunks;
-
- chunks = (SpiceChunks *)spice_malloc_n_m(count, sizeof(SpiceChunk), sizeof(SpiceChunks));
- chunks->flags = 0;
- chunks->num_chunks = count;
-
- return chunks;
-}
-
-SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len)
-{
- SpiceChunks *chunks;
-
- chunks = spice_chunks_new(1);
- chunks->data_size = chunks->chunk[0].len = len;
- chunks->chunk[0].data = data;
- return chunks;
-}
-
-void spice_chunks_destroy(SpiceChunks *chunks)
-{
- unsigned int i;
-
- if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
- for (i = 0; i < chunks->num_chunks; i++) {
- free(chunks->chunk[i].data);
- }
- }
-
- free(chunks);
-}
-
-void spice_chunks_linearize(SpiceChunks *chunks)
-{
- uint8_t *data, *p;
- unsigned int i;
-
- if (chunks->num_chunks > 1) {
- data = (uint8_t*)spice_malloc(chunks->data_size);
- for (p = data, i = 0; i < chunks->num_chunks; i++) {
- memcpy(p, chunks->chunk[i].data,
- chunks->chunk[i].len);
- p += chunks->chunk[i].len;
- }
- if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
- for (i = 0; i < chunks->num_chunks; i++) {
- free(chunks->chunk[i].data);
- }
- }
- chunks->num_chunks = 1;
- chunks->flags |= SPICE_CHUNKS_FLAGS_FREE;
- chunks->flags &= ~SPICE_CHUNKS_FLAGS_UNSTABLE;
- chunks->chunk[0].data = data;
- chunks->chunk[0].len = chunks->data_size;
- }
-}
diff --git a/common/mem.h b/common/mem.h
deleted file mode 100644
index 6863953..0000000
--- a/common/mem.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2010 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_MEM
-#define _H_MEM
-
-#include <stdlib.h>
-#include <spice/macros.h>
-
-/* alloca definition from glib/galloca.h */
-#ifdef __GNUC__
-/* GCC does the right thing */
-# undef alloca
-# define alloca(size) __builtin_alloca (size)
-#elif defined (GLIB_HAVE_ALLOCA_H)
-/* a native and working alloca.h is there */
-# include <alloca.h>
-#else /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */
-# if defined(_MSC_VER) || defined(__DMC__)
-# include <malloc.h>
-# define alloca _alloca
-# else /* !_MSC_VER && !__DMC__ */
-# ifdef _AIX
-# pragma alloca
-# else /* !_AIX */
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-# endif /* !alloca */
-# endif /* !_AIX */
-# endif /* !_MSC_VER && !__DMC__ */
-#endif /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */
-
-typedef struct SpiceChunk {
- uint8_t *data;
- uint32_t len;
-} SpiceChunk;
-
-enum {
- SPICE_CHUNKS_FLAGS_UNSTABLE = (1<<0),
- SPICE_CHUNKS_FLAGS_FREE = (1<<1)
-};
-
-typedef struct SpiceChunks {
- uint32_t data_size;
- uint32_t num_chunks;
- uint32_t flags;
- SpiceChunk chunk[0];
-} SpiceChunks;
-
-char *spice_strdup(const char *str) SPICE_GNUC_MALLOC;
-char *spice_strndup(const char *str, size_t n_bytes) SPICE_GNUC_MALLOC;
-void *spice_memdup(const void *mem, size_t n_bytes) SPICE_GNUC_MALLOC;
-void *spice_malloc(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1);
-void *spice_malloc0(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1);
-void *spice_realloc(void *mem, size_t n_bytes) SPICE_GNUC_WARN_UNUSED_RESULT;
-void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2);
-void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size) SPICE_GNUC_MALLOC;
-void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2);
-void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_WARN_UNUSED_RESULT;
-SpiceChunks *spice_chunks_new(uint32_t count) SPICE_GNUC_MALLOC;
-SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len) SPICE_GNUC_MALLOC;
-void spice_chunks_destroy(SpiceChunks *chunks);
-void spice_chunks_linearize(SpiceChunks *chunks);
-
-size_t spice_strnlen(const char *str, size_t max_len);
-
-/* Optimize: avoid the call to the (slower) _n function if we can
- * determine at compile-time that no overflow happens.
- */
-#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
-# define _SPICE_NEW(struct_type, n_structs, func) \
- (struct_type *) (__extension__ ({ \
- size_t __n = (size_t) (n_structs); \
- size_t __s = sizeof (struct_type); \
- void *__p; \
- if (__s == 1) \
- __p = spice_##func (__n); \
- else if (__builtin_constant_p (__n) && \
- __n <= SIZE_MAX / __s) \
- __p = spice_##func (__n * __s); \
- else \
- __p = spice_##func##_n (__n, __s); \
- __p; \
- }))
-# define _SPICE_RENEW(struct_type, mem, n_structs, func) \
- (struct_type *) (__extension__ ({ \
- size_t __n = (size_t) (n_structs); \
- size_t __s = sizeof (struct_type); \
- void *__p = (void *) (mem); \
- if (__s == 1) \
- __p = spice_##func (__p, __n); \
- else if (__builtin_constant_p (__n) && \
- __n <= SIZE_MAX / __s) \
- __p = spice_##func (__p, __n * __s); \
- else \
- __p = spice_##func##_n (__p, __n, __s); \
- __p; \
- }))
-#else
-
-/* Unoptimized version: always call the _n() function. */
-
-#define _SPICE_NEW(struct_type, n_structs, func) \
- ((struct_type *) spice_##func##_n ((n_structs), sizeof (struct_type)))
-#define _SPICE_RENEW(struct_type, mem, n_structs, func) \
- ((struct_type *) spice_##func##_n (mem, (n_structs), sizeof (struct_type)))
-
-#endif
-
-#define spice_new(struct_type, n_structs) _SPICE_NEW(struct_type, n_structs, malloc)
-#define spice_new0(struct_type, n_structs) _SPICE_NEW(struct_type, n_structs, malloc0)
-#define spice_renew(struct_type, mem, n_structs) _SPICE_RENEW(struct_type, mem, n_structs, realloc)
-
-#endif
diff --git a/common/messages.h b/common/messages.h
deleted file mode 100644
index 01689cd..0000000
--- a/common/messages.h
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- Copyright (C) 2009-2010 Red Hat, Inc.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- * Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _H_MESSAGES
-#define _H_MESSAGES
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <spice/protocol.h>
-#ifdef USE_SMARTCARD
-#include <vscard_common.h>
-#endif
-#include "draw.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct SpiceMsgData {
- uint32_t data_size;
- uint8_t data[0];
-} SpiceMsgData;
-
-typedef struct SpiceMsgEmpty {
-} SpiceMsgEmpty;
-
-typedef struct SpiceMsgInputsInit {
- uint32_t keyboard_modifiers;
-} SpiceMsgInputsInit;
-
-typedef struct SpiceMsgInputsKeyModifiers {
- uint32_t modifiers;
-} SpiceMsgInputsKeyModifiers;
-
-typedef struct SpiceMsgMainMultiMediaTime {
- uint32_t time;
-} SpiceMsgMainMultiMediaTime;
-
-typedef struct SpiceMsgMainMigrationBegin {
- uint16_t port;
- uint16_t sport;
- uint32_t host_size;
- uint8_t *host_data;
- uint16_t pub_key_type;
- uint32_t pub_key_size;
- uint8_t *pub_key_data;
- uint32_t cert_subject_size;
- uint8_t *cert_subject_data;
-} SpiceMsgMainMigrationBegin;
-
-typedef struct SpiceMsgMainMigrationSwitchHost {
- uint16_t port;
- uint16_t sport;
- uint32_t host_size;
- uint8_t *host_data;
- uint32_t cert_subject_size;
- uint8_t *cert_subject_data;
-} SpiceMsgMainMigrationSwitchHost;
-
-
-typedef struct SpiceMsgMigrate {
- uint32_t flags;
-} SpiceMsgMigrate;
-
-typedef struct SpiceResourceID {
- uint8_t type;
- uint64_t id;
-} SpiceResourceID;
-
-typedef struct SpiceResourceList {
- uint16_t count;
- SpiceResourceID resources[0];
-} SpiceResourceList;
-
-typedef struct SpiceMsgSetAck {
- uint32_t generation;
- uint32_t window;
-} SpiceMsgSetAck;
-
-typedef struct SpiceMsgcAckSync {
- uint32_t generation;
-} SpiceMsgcAckSync;
-
-typedef struct SpiceWaitForChannel {
- uint8_t channel_type;
- uint8_t channel_id;
- uint64_t message_serial;
-} SpiceWaitForChannel;
-
-typedef struct SpiceMsgWaitForChannels {
- uint8_t wait_count;
- SpiceWaitForChannel wait_list[0];
-} SpiceMsgWaitForChannels;
-
-typedef struct SpiceChannelId {
- uint8_t type;
- uint8_t id;
-} SpiceChannelId;
-
-typedef struct SpiceMsgMainInit {
- uint32_t session_id;
- uint32_t display_channels_hint;
- uint32_t supported_mouse_modes;
- uint32_t current_mouse_mode;
- uint32_t agent_connected;
- uint32_t agent_tokens;
- uint32_t multi_media_time;
- uint32_t ram_hint;
-} SpiceMsgMainInit;
-
-typedef struct SpiceMsgDisconnect {
- uint64_t time_stamp;
- uint32_t reason; // SPICE_ERR_?
-} SpiceMsgDisconnect;
-
-typedef struct SpiceMsgNotify {
- uint64_t time_stamp;
- uint32_t severity;
- uint32_t visibilty;
- uint32_t what;
- uint32_t message_len;
- uint8_t message[0];
-} SpiceMsgNotify;
-
-typedef struct SpiceMsgChannels {
- uint32_t num_of_channels;
- SpiceChannelId channels[0];
-} SpiceMsgChannels;
-
-typedef struct SpiceMsgMainName {
- uint32_t name_len;
- uint8_t name[0];
-} SpiceMsgMainName;
-
-typedef struct SpiceMsgMainUuid {
- uint8_t uuid[16];
-} SpiceMsgMainUuid;
-
-typedef struct SpiceMsgMainMouseMode {
- uint32_t supported_modes;
- uint32_t current_mode;
-} SpiceMsgMainMouseMode;
-
-typedef struct SpiceMsgPing {
- uint32_t id;
- uint64_t timestamp;
- void *data;
- uint32_t data_len;
-} SpiceMsgPing;
-
-typedef struct SpiceMsgMainAgentDisconnect {
- uint32_t error_code; // SPICE_ERR_?
-} SpiceMsgMainAgentDisconnect;
-
-#define SPICE_AGENT_MAX_DATA_SIZE 2048
-
-typedef struct SpiceMsgMainAgentTokens {
- uint32_t num_tokens;
-} SpiceMsgMainAgentTokens, SpiceMsgcMainAgentTokens, SpiceMsgcMainAgentStart;
-
-typedef struct SpiceMsgcClientInfo {
- uint64_t cache_size;
-} SpiceMsgcClientInfo;
-
-typedef struct SpiceMsgcMainMouseModeRequest {
- uint32_t mode;
-} SpiceMsgcMainMouseModeRequest;
-
-typedef struct SpiceCursor {
- uint32_t flags;
- SpiceCursorHeader header;
- uint32_t data_size;
- uint8_t *data;
-} SpiceCursor;
-
-typedef struct SpiceMsgDisplayMode {
- uint32_t x_res;
- uint32_t y_res;
- uint32_t bits;
-} SpiceMsgDisplayMode;
-
-typedef struct SpiceMsgSurfaceCreate {
- uint32_t surface_id;
- uint32_t width;
- uint32_t height;
- uint32_t format;
- uint32_t flags;
-} SpiceMsgSurfaceCreate;
-
-typedef struct SpiceMsgSurfaceDestroy {
- uint32_t surface_id;
-} SpiceMsgSurfaceDestroy;
-
-typedef struct SpiceMsgDisplayBase {
- uint32_t surface_id;
- SpiceRect box;
- SpiceClip clip;
-} SpiceMsgDisplayBase;
-
-typedef struct SpiceMsgDisplayDrawFill {
- SpiceMsgDisplayBase base;
- SpiceFill data;
-} SpiceMsgDisplayDrawFill;
-
-typedef struct SpiceMsgDisplayDrawOpaque {
- SpiceMsgDisplayBase base;
- SpiceOpaque data;
-} SpiceMsgDisplayDrawOpaque;
-
-typedef struct SpiceMsgDisplayDrawCopy {
- SpiceMsgDisplayBase base;
- SpiceCopy data;
-} SpiceMsgDisplayDrawCopy;
-
-typedef struct SpiceMsgDisplayDrawTransparent {
- SpiceMsgDisplayBase base;
- SpiceTransparent data;
-} SpiceMsgDisplayDrawTransparent;
-
-typedef struct SpiceMsgDisplayDrawAlphaBlend {
- SpiceMsgDisplayBase base;
- SpiceAlphaBlend data;
-} SpiceMsgDisplayDrawAlphaBlend;
-
-typedef struct SpiceMsgDisplayCopyBits {
- SpiceMsgDisplayBase base;
- SpicePoint src_pos;
-} SpiceMsgDisplayCopyBits;
-
-typedef SpiceMsgDisplayDrawCopy SpiceMsgDisplayDrawBlend;
-
-typedef struct SpiceMsgDisplayDrawRop3 {
- SpiceMsgDisplayBase base;
- SpiceRop3 data;
-} SpiceMsgDisplayDrawRop3;
-
-typedef struct SpiceMsgDisplayDrawBlackness {
- SpiceMsgDisplayBase base;
- SpiceBlackness data;
-} SpiceMsgDisplayDrawBlackness;
-
-typedef struct SpiceMsgDisplayDrawWhiteness {
- SpiceMsgDisplayBase base;
- SpiceWhiteness data;
-} SpiceMsgDisplayDrawWhiteness;
-
-typedef struct SpiceMsgDisplayDrawInvers {
- SpiceMsgDisplayBase base;
- SpiceInvers data;
-} SpiceMsgDisplayDrawInvers;
-
-typedef struct SpiceMsgDisplayDrawStroke {
- SpiceMsgDisplayBase base;
- SpiceStroke data;
-} SpiceMsgDisplayDrawStroke;
-
-typedef struct SpiceMsgDisplayDrawText {
- SpiceMsgDisplayBase base;
- SpiceText data;
-} SpiceMsgDisplayDrawText;
-
-typedef struct SpiceMsgDisplayInvalOne {
- uint64_t id;
-} SpiceMsgDisplayInvalOne;
-
-typedef struct SpiceMsgDisplayStreamCreate {
- uint32_t surface_id;
- uint32_t id;
- uint32_t flags;
- uint32_t codec_type;
- uint64_t stamp;
- uint32_t stream_width;
- uint32_t stream_height;
- uint32_t src_width;
- uint32_t src_height;
- SpiceRect dest;
- SpiceClip clip;
-} SpiceMsgDisplayStreamCreate;
-
-typedef struct SpiceMsgDisplayStreamData {
- uint32_t id;
- uint32_t multi_media_time;
- uint32_t data_size;
- uint8_t data[0];
-} SpiceMsgDisplayStreamData;
-
-typedef struct SpiceMsgDisplayStreamClip {
- uint32_t id;
- SpiceClip clip;
-} SpiceMsgDisplayStreamClip;
-
-typedef struct SpiceMsgDisplayStreamDestroy {
- uint32_t id;
-} SpiceMsgDisplayStreamDestroy;
-
-typedef struct SpiceMsgCursorInit {
- SpicePoint16 position;
- uint16_t trail_length;
- uint16_t trail_frequency;
- uint8_t visible;
- SpiceCursor cursor;
-} SpiceMsgCursorInit;
-
-typedef struct SpiceMsgCursorSet {
- SpicePoint16 position;
- uint8_t visible;
- SpiceCursor cursor;
-} SpiceMsgCursorSet;
-
-typedef struct SpiceMsgCursorMove {
- SpicePoint16 position;
-} SpiceMsgCursorMove;
-
-typedef struct SpiceMsgCursorTrail {
- uint16_t length;
- uint16_t frequency;
-} SpiceMsgCursorTrail;
-
-typedef struct SpiceMsgcDisplayInit {
- uint8_t pixmap_cache_id;
- int64_t pixmap_cache_size; //in pixels
- uint8_t glz_dictionary_id;
- int32_t glz_dictionary_window_size; // in pixels
-} SpiceMsgcDisplayInit;
-
-typedef struct SpiceMsgcKeyDown {
- uint32_t code;
-} SpiceMsgcKeyDown;
-
-typedef struct SpiceMsgcKeyUp {
- uint32_t code;
-} SpiceMsgcKeyUp;
-
-typedef struct SpiceMsgcKeyModifiers {
- uint32_t modifiers;
-} SpiceMsgcKeyModifiers;
-
-typedef struct SpiceMsgcMouseMotion {
- int32_t dx;
- int32_t dy;
- uint32_t buttons_state;
-} SpiceMsgcMouseMotion;
-
-typedef struct SpiceMsgcMousePosition {
- uint32_t x;
- uint32_t y;
- uint32_t buttons_state;
- uint8_t display_id;
-} SpiceMsgcMousePosition;
-
-typedef struct SpiceMsgcMousePress {
- int32_t button;
- int32_t buttons_state;
-} SpiceMsgcMousePress;
-
-typedef struct SpiceMsgcMouseRelease {
- int32_t button;
- int32_t buttons_state;
-} SpiceMsgcMouseRelease;
-
-typedef struct SpiceMsgAudioVolume {
- uint8_t nchannels;
- uint16_t volume[0];
-} SpiceMsgAudioVolume;
-
-typedef struct SpiceMsgAudioMute {
- uint8_t mute;
-} SpiceMsgAudioMute;
-
-typedef struct SpiceMsgPlaybackMode {
- uint32_t time;
- uint32_t mode; //SPICE_AUDIO_DATA_MODE_?
- uint8_t *data;
- uint32_t data_size;
-} SpiceMsgPlaybackMode, SpiceMsgcRecordMode;
-
-typedef struct SpiceMsgPlaybackStart {
- uint32_t channels;
- uint32_t format; //SPICE_AUDIO_FMT_?
- uint32_t frequency;
- uint32_t time;
-} SpiceMsgPlaybackStart;
-
-typedef struct SpiceMsgPlaybackPacket {
- uint32_t time;
- uint8_t *data;
- uint32_t data_size;
-} SpiceMsgPlaybackPacket, SpiceMsgcRecordPacket;
-
-typedef struct SpiceMsgRecordStart {
- uint32_t channels;
- uint32_t format; //SPICE_AUDIO_FMT_?
- uint32_t frequency;
-} SpiceMsgRecordStart;
-
-typedef struct SpiceMsgcRecordStartMark {
- uint32_t time;
-} SpiceMsgcRecordStartMark;
-
-typedef struct SpiceMsgTunnelInit {
- uint16_t max_num_of_sockets;
- uint32_t max_socket_data_size;
-} SpiceMsgTunnelInit;
-
-typedef uint8_t SpiceTunnelIPv4[4];
-
-typedef struct SpiceMsgTunnelIpInfo {
- uint16_t type;
- union {
- SpiceTunnelIPv4 ipv4;
- } u;
- uint8_t data[0];
-} SpiceMsgTunnelIpInfo;
-
-typedef struct SpiceMsgTunnelServiceIpMap {
- uint32_t service_id;
- SpiceMsgTunnelIpInfo virtual_ip;
-} SpiceMsgTunnelServiceIpMap;
-
-typedef struct SpiceMsgTunnelSocketOpen {
- uint16_t connection_id;
- uint32_t service_id;
- uint32_t tokens;
-} SpiceMsgTunnelSocketOpen;
-
-/* connection id must be the first field in msgs directed to a specific connection */
-
-typedef struct SpiceMsgTunnelSocketFin {
- uint16_t connection_id;
-} SpiceMsgTunnelSocketFin;
-
-typedef struct SpiceMsgTunnelSocketClose {
- uint16_t connection_id;
-} SpiceMsgTunnelSocketClose;
-
-typedef struct SpiceMsgTunnelSocketData {
- uint16_t connection_id;
- uint8_t data[0];
-} SpiceMsgTunnelSocketData;
-
-typedef struct SpiceMsgTunnelSocketTokens {
- uint16_t connection_id;
- uint32_t num_tokens;
-} SpiceMsgTunnelSocketTokens;
-
-typedef struct SpiceMsgTunnelSocketClosedAck {
- uint16_t connection_id;
-} SpiceMsgTunnelSocketClosedAck;
-
-typedef struct SpiceMsgcTunnelAddGenericService {
- uint32_t type;
- uint32_t id;
- uint32_t group;
- uint32_t port;
- uint64_t name;
- uint64_t description;
- union {
- SpiceMsgTunnelIpInfo ip;
- } u;
-} SpiceMsgcTunnelAddGenericService;
-
-typedef struct SpiceMsgcTunnelRemoveService {
- uint32_t id;
-} SpiceMsgcTunnelRemoveService;
-
-/* connection id must be the first field in msgs directed to a specific connection */
-
-typedef struct SpiceMsgcTunnelSocketOpenAck {
- uint16_t connection_id;
- uint32_t tokens;
-} SpiceMsgcTunnelSocketOpenAck;
-
-typedef struct SpiceMsgcTunnelSocketOpenNack {
- uint16_t connection_id;
-} SpiceMsgcTunnelSocketOpenNack;
-
-typedef struct SpiceMsgcTunnelSocketData {
- uint16_t connection_id;
- uint8_t data[0];
-} SpiceMsgcTunnelSocketData;
-
-typedef struct SpiceMsgcTunnelSocketFin {
- uint16_t connection_id;
-} SpiceMsgcTunnelSocketFin;
-
-typedef struct SpiceMsgcTunnelSocketClosed {
- uint16_t connection_id;
-} SpiceMsgcTunnelSocketClosed;
-
-typedef struct SpiceMsgcTunnelSocketClosedAck {
- uint16_t connection_id;
-} SpiceMsgcTunnelSocketClosedAck;
-
-typedef struct SpiceMsgcTunnelSocketTokens {
- uint16_t connection_id;
- uint32_t num_tokens;
-} SpiceMsgcTunnelSocketTokens;
-
-#ifdef USE_SMARTCARD
-typedef struct SpiceMsgSmartcard {
- VSCMsgType type;
- uint32_t length;
- uint32_t reader_id;
- uint8_t data[0];
-} SpiceMsgSmartcard;
-
-typedef struct SpiceMsgcSmartcard {
- VSCMsgHeader header;
- union {
- VSCMsgError error;
- VSCMsgATR atr_data;
- VSCMsgReaderAdd add;
- };
-} SpiceMsgcSmartcard;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _H_SPICE_PROTOCOL */
diff --git a/common/mutex.h b/common/mutex.h
deleted file mode 100644
index a2d35de..0000000
--- a/common/mutex.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_MUTEX
-#define _H_MUTEX
-#ifdef _WIN32
-#include <windows.h>
-typedef CRITICAL_SECTION mutex_t;
-#define MUTEX_INIT(mutex) InitializeCriticalSection(&mutex)
-#define MUTEX_LOCK(mutex) EnterCriticalSection(&mutex)
-#define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex)
-#else
-#include <pthread.h>
-typedef pthread_mutex_t mutex_t;
-#define MUTEX_INIT(mutex) pthread_mutex_init(&mutex, NULL);
-#define MUTEX_LOCK(mutex) pthread_mutex_lock(&mutex)
-#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex)
-#endif
-
-#endif // _H_MUTEX
diff --git a/common/ogl_ctx.c b/common/ogl_ctx.c
deleted file mode 100644
index ae25c2d..0000000
--- a/common/ogl_ctx.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <GL/glx.h>
-
-#include "ogl_ctx.h"
-
-
-#define PANIC(str) { \
- printf("%s: panic: %s", __FUNCTION__, str); \
- abort(); \
-}
-
-enum {
- OGLCTX_TYPE_PBUF,
- OGLCTX_TYPE_PIXMAP,
-};
-
-struct OGLCtx {
- int type;
- Display *x_display;
- GLXContext glx_context;
- GLXDrawable drawable;
-};
-
-typedef struct OGLPixmapCtx {
- OGLCtx base;
- Pixmap pixmap;
-} OGLPixmapCtx;
-
-
-
-const char *oglctx_type_str(OGLCtx *ctx)
-{
- static const char *pbuf_str = "pbuf";
- static const char *pixmap_str = "pixmap";
- static const char *invalid_str = "invalid";
-
- switch (ctx->type) {
- case OGLCTX_TYPE_PBUF:
- return pbuf_str;
- case OGLCTX_TYPE_PIXMAP:
- return pixmap_str;
- default:
- return invalid_str;
- }
-}
-
-void oglctx_make_current(OGLCtx *ctx)
-{
- if (!glXMakeCurrent(ctx->x_display, ctx->drawable, ctx->glx_context)) {
- printf("%s: failed\n", __FUNCTION__);
- }
-}
-
-OGLCtx *pbuf_create(int width, int heigth)
-{
- OGLCtx *ctx;
- Display *x_display;
- int num_configs;
- GLXFBConfig *fb_config;
- GLXPbuffer glx_pbuf;
- GLXContext glx_context;
-
- const int glx_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- GLX_RED_SIZE, 8,
- GLX_GREEN_SIZE, 8,
- GLX_BLUE_SIZE, 8,
- GLX_ALPHA_SIZE, 8,
- GLX_STENCIL_SIZE, 4,
- 0 };
-
- int pbuf_attrib[] = { GLX_PRESERVED_CONTENTS, True,
- GLX_PBUFFER_WIDTH, width,
- GLX_PBUFFER_HEIGHT, heigth,
- GLX_LARGEST_PBUFFER, False,
- 0, 0 };
-
- if (!(ctx = calloc(1, sizeof(*ctx)))) {
- printf("%s: alloc pbuf failed\n", __FUNCTION__);
- return NULL;
- }
-
- if (!(x_display = XOpenDisplay(NULL))) {
- printf("%s: open display failed\n", __FUNCTION__);
- goto error_1;
- }
-
- if (!(fb_config = glXChooseFBConfig(x_display, 0, glx_attributes, &num_configs)) ||
- !num_configs) {
- printf("%s: choose fb config failed\n", __FUNCTION__);
- goto error_2;
- }
-
- if (!(glx_pbuf = glXCreatePbuffer(x_display, fb_config[0], pbuf_attrib))) {
- goto error_3;
- }
-
- if (!(glx_context = glXCreateNewContext(x_display, fb_config[0], GLX_RGBA_TYPE, NULL, True))) {
- printf("%s: create context failed\n", __FUNCTION__);
- goto error_4;
- }
-
- XFree(fb_config);
-
- ctx->type = OGLCTX_TYPE_PBUF;
- ctx->drawable = glx_pbuf;
- ctx->glx_context = glx_context;
- ctx->x_display = x_display;
-
- return ctx;
-
-error_4:
- glXDestroyPbuffer(x_display, glx_pbuf);
-
-error_3:
- XFree(fb_config);
-
-error_2:
- XCloseDisplay(x_display);
-
-error_1:
- free(ctx);
-
- return NULL;
-}
-
-OGLCtx *pixmap_create(int width, int heigth)
-{
- Display *x_display;
- int num_configs;
- GLXFBConfig *fb_config;
- GLXPixmap glx_pixmap;
- GLXContext glx_context;
- Pixmap pixmap;
- int screen;
- Window root_window;
- OGLPixmapCtx *pix;
-
- const int glx_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
- GLX_RED_SIZE, 8,
- GLX_GREEN_SIZE, 8,
- GLX_BLUE_SIZE, 8,
- GLX_ALPHA_SIZE, 8,
- GLX_STENCIL_SIZE, 4,
- 0 };
-
- if (!(pix = calloc(1, sizeof(*pix)))) {
- printf("%s: alloc pix failed\n", __FUNCTION__);
- return NULL;
- }
-
- if (!(x_display = XOpenDisplay(NULL))) {
- printf("%s: open display failed\n", __FUNCTION__);
- goto error_1;
- }
-
- screen = DefaultScreen(x_display);
- root_window = RootWindow(x_display, screen);
-
- if (!(fb_config = glXChooseFBConfig(x_display, 0, glx_attributes, &num_configs)) ||
- !num_configs) {
- printf("%s: choose fb config failed\n", __FUNCTION__);
- goto error_2;
- }
-
- if (!(pixmap = XCreatePixmap(x_display, root_window, width, heigth, 32 /*use fb config*/))) {
- printf("%s: create x pixmap failed\n", __FUNCTION__);
- goto error_3;
- }
-
- if (!(glx_pixmap = glXCreatePixmap(x_display, fb_config[0], pixmap, NULL))) {
- printf("%s: create glx pixmap failed\n", __FUNCTION__);
- goto error_4;
- }
-
-
- if (!(glx_context = glXCreateNewContext(x_display, fb_config[0], GLX_RGBA_TYPE, NULL, True))) {
- printf("%s: create context failed\n", __FUNCTION__);
- goto error_5;
- }
-
- XFree(fb_config);
-
- pix->base.type = OGLCTX_TYPE_PIXMAP;
- pix->base.x_display = x_display;
- pix->base.drawable = glx_pixmap;
- pix->base.glx_context = glx_context;
- pix->pixmap = pixmap;
-
- return &pix->base;
-
-error_5:
- glXDestroyPixmap(x_display, glx_pixmap);
-
-error_4:
- XFreePixmap(x_display, pixmap);
-
-error_3:
- XFree(fb_config);
-
-error_2:
- XCloseDisplay(x_display);
-
-error_1:
- free(pix);
-
- return NULL;
-}
-
-void oglctx_destroy(OGLCtx *ctx)
-{
- if (!ctx) {
- return;
- }
- // test is current ?
-
- glXDestroyContext(ctx->x_display, ctx->glx_context);
- switch (ctx->type) {
- case OGLCTX_TYPE_PBUF:
- glXDestroyPbuffer(ctx->x_display, ctx->drawable);
- break;
- case OGLCTX_TYPE_PIXMAP:
- glXDestroyPixmap(ctx->x_display, ctx->drawable);
- XFreePixmap(ctx->x_display, ((OGLPixmapCtx *)ctx)->pixmap);
- break;
- default:
- PANIC("invalid ogl ctx type");
- }
-
- XCloseDisplay(ctx->x_display);
- free(ctx);
-}
-
diff --git a/common/ogl_ctx.h b/common/ogl_ctx.h
deleted file mode 100644
index 3abe6d7..0000000
--- a/common/ogl_ctx.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_GLCTX
-#define _H_GLCTX
-
-typedef struct OGLCtx OGLCtx;
-
-const char *oglctx_type_str(OGLCtx *ctx);
-void oglctx_make_current(OGLCtx *ctx);
-OGLCtx *pbuf_create(int width, int heigth);
-OGLCtx *pixmap_create(int width, int heigth);
-void oglctx_destroy(OGLCtx *ctx);
-
-#endif
-
diff --git a/common/pixman_utils.c b/common/pixman_utils.c
deleted file mode 100644
index 914c97e..0000000
--- a/common/pixman_utils.c
+++ /dev/null
@@ -1,1614 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "pixman_utils.h"
-#include <spice/macros.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include "mem.h"
-
-#ifndef ASSERT
-#define ASSERT(x) if (!(x)) { \
- printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \
- abort(); \
-}
-#endif
-
-#ifndef PANIC
-#define PANIC(str) { \
- printf("%s: panic: %s", __FUNCTION__, str); \
- abort(); \
-}
-#endif
-
-#define SOLID_RASTER_OP(_name, _size, _type, _equation) \
-static void \
-solid_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type src) \
-{ \
- while (len--) { \
- _type dst = *ptr; \
- if (dst) /* avoid unused warning */{}; \
- *ptr = (_type)(_equation); \
- ptr++; \
- } \
-} \
-
-#define TILED_RASTER_OP(_name, _size, _type, _equation) \
-static void \
-tiled_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) \
-{ \
- while (len--) { \
- _type src = *tile; \
- _type dst = *ptr; \
- if (src) /* avoid unused warning */{}; \
- if (dst) /* avoid unused warning */{}; \
- *ptr = (_type)(_equation); \
- ptr++; \
- tile++; \
- if (tile == tile_end) \
- tile -= tile_width; \
- } \
-} \
-
-#define COPY_RASTER_OP(_name, _size, _type, _equation) \
-static void \
- copy_rop_ ## _name ## _ ## _size (_type *ptr, _type *src_line, int len) \
-{ \
- while (len--) { \
- _type src = *src_line; \
- _type dst = *ptr; \
- if (src) /* avoid unused warning */ {}; \
- if (dst) /* avoid unused warning */{}; \
- *ptr = (_type)(_equation); \
- ptr++; \
- src_line++; \
- } \
-} \
-
-#define RASTER_OP(name, equation) \
- SOLID_RASTER_OP(name, 8, uint8_t, equation) \
- SOLID_RASTER_OP(name, 16, uint16_t, equation) \
- SOLID_RASTER_OP(name, 32, uint32_t, equation) \
- TILED_RASTER_OP(name, 8, uint8_t, equation) \
- TILED_RASTER_OP(name, 16, uint16_t, equation) \
- TILED_RASTER_OP(name, 32, uint32_t, equation) \
- COPY_RASTER_OP(name, 8, uint8_t, equation) \
- COPY_RASTER_OP(name, 16, uint16_t, equation) \
- COPY_RASTER_OP(name, 32, uint32_t, equation)
-
-RASTER_OP(clear, 0x0)
-RASTER_OP(and, src & dst)
-RASTER_OP(and_reverse, src & ~dst)
-RASTER_OP(copy, src)
-RASTER_OP(and_inverted, ~src & dst)
-RASTER_OP(noop, dst)
-RASTER_OP(xor, src ^ dst)
-RASTER_OP(or, src | dst)
-RASTER_OP(nor, ~src & ~dst)
-RASTER_OP(equiv, ~src ^ dst)
-RASTER_OP(invert, ~dst)
-RASTER_OP(or_reverse, src | ~dst)
-RASTER_OP(copy_inverted, ~src)
-RASTER_OP(or_inverted, ~src | dst)
-RASTER_OP(nand, ~src | ~dst)
-RASTER_OP(set, 0xffffffff)
-
-typedef void (*solid_rop_8_func_t)(uint8_t *ptr, int len, uint8_t src);
-typedef void (*solid_rop_16_func_t)(uint16_t *ptr, int len, uint16_t src);
-typedef void (*solid_rop_32_func_t)(uint32_t *ptr, int len, uint32_t src);
-typedef void (*tiled_rop_8_func_t)(uint8_t *ptr, int len,
- uint8_t *tile, uint8_t *tile_end, int tile_width);
-typedef void (*tiled_rop_16_func_t)(uint16_t *ptr, int len,
- uint16_t *tile, uint16_t *tile_end, int tile_width);
-typedef void (*tiled_rop_32_func_t)(uint32_t *ptr, int len,
- uint32_t *tile, uint32_t *tile_end, int tile_width);
-typedef void (*copy_rop_8_func_t)(uint8_t *ptr, uint8_t *src, int len);
-typedef void (*copy_rop_16_func_t)(uint16_t *ptr, uint16_t *src, int len);
-typedef void (*copy_rop_32_func_t)(uint32_t *ptr, uint32_t *src, int len);
-
-#define ROP_TABLE(_type, _size) \
-static void (*solid_rops_ ## _size[16]) (_type *ptr, int len, _type src) = { \
- solid_rop_clear_ ## _size, \
- solid_rop_and_ ## _size, \
- solid_rop_and_reverse_ ## _size, \
- solid_rop_copy_ ## _size, \
- solid_rop_and_inverted_ ## _size, \
- solid_rop_noop_ ## _size, \
- solid_rop_xor_ ## _size, \
- solid_rop_or_ ## _size, \
- solid_rop_nor_ ## _size, \
- solid_rop_equiv_ ## _size, \
- solid_rop_invert_ ## _size, \
- solid_rop_or_reverse_ ## _size, \
- solid_rop_copy_inverted_ ## _size, \
- solid_rop_or_inverted_ ## _size, \
- solid_rop_nand_ ## _size, \
- solid_rop_set_ ## _size \
-}; \
-static void (*tiled_rops_ ## _size[16]) (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) = { \
- tiled_rop_clear_ ## _size, \
- tiled_rop_and_ ## _size, \
- tiled_rop_and_reverse_ ## _size, \
- tiled_rop_copy_ ## _size, \
- tiled_rop_and_inverted_ ## _size, \
- tiled_rop_noop_ ## _size, \
- tiled_rop_xor_ ## _size, \
- tiled_rop_or_ ## _size, \
- tiled_rop_nor_ ## _size, \
- tiled_rop_equiv_ ## _size, \
- tiled_rop_invert_ ## _size, \
- tiled_rop_or_reverse_ ## _size, \
- tiled_rop_copy_inverted_ ## _size, \
- tiled_rop_or_inverted_ ## _size, \
- tiled_rop_nand_ ## _size, \
- tiled_rop_set_ ## _size \
-}; \
-static void (*copy_rops_ ## _size[16]) (_type *ptr, _type *tile, int len) = { \
- copy_rop_clear_ ## _size, \
- copy_rop_and_ ## _size, \
- copy_rop_and_reverse_ ## _size, \
- copy_rop_copy_ ## _size, \
- copy_rop_and_inverted_ ## _size, \
- copy_rop_noop_ ## _size, \
- copy_rop_xor_ ## _size, \
- copy_rop_or_ ## _size, \
- copy_rop_nor_ ## _size, \
- copy_rop_equiv_ ## _size, \
- copy_rop_invert_ ## _size, \
- copy_rop_or_reverse_ ## _size, \
- copy_rop_copy_inverted_ ## _size, \
- copy_rop_or_inverted_ ## _size, \
- copy_rop_nand_ ## _size, \
- copy_rop_set_ ## _size \
-};
-
-ROP_TABLE(uint8_t, 8)
-ROP_TABLE(uint16_t, 16)
-ROP_TABLE(uint32_t, 32)
-
-/* We can't get the real bits per pixel info from pixman_image_t,
- only the DEPTH which is the sum of all a+r+g+b bits, which
- is e.g. 24 for 32bit xRGB. We really want the bpp, so
- we have this ugly conversion thing */
-int spice_pixman_image_get_bpp(pixman_image_t *image)
-{
- int depth;
-
- depth = pixman_image_get_depth(image);
- if (depth == 24) {
- return 32;
- }
- if (depth == 15) {
- return 16;
- }
- return depth;
-}
-
-void spice_pixman_fill_rect(pixman_image_t *dest,
- int x, int y,
- int width, int height,
- uint32_t value)
-{
- uint32_t *bits;
- int stride, depth;
- uint32_t byte_width;
- uint8_t *byte_line;
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- ASSERT(x >= 0);
- ASSERT(y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(x + width <= pixman_image_get_width(dest));
- ASSERT(y + height <= pixman_image_get_height(dest));
-
- if (pixman_fill(bits,
- stride / 4,
- depth,
- x, y,
- width, height,
- value)) {
- return;
- }
-
- if (depth == 8) {
- byte_line = ((uint8_t *)bits) + stride * y + x;
- byte_width = width;
- value = (value & 0xff) * 0x01010101;
- } else if (depth == 16) {
- byte_line = ((uint8_t *)bits) + stride * y + x * 2;
- byte_width = 2 * width;
- value = (value & 0xffff) * 0x00010001;
- } else {
- ASSERT (depth == 32)
- byte_line = ((uint8_t *)bits) + stride * y + x * 4;
- byte_width = 4 * width;
- }
-
- while (height--) {
- int w;
- uint8_t *d = byte_line;
-
- byte_line += stride;
- w = byte_width;
-
- while (w >= 1 && ((uintptr_t)d & 1)) {
- *(uint8_t *)d = (value & 0xff);
- w--;
- d++;
- }
-
- while (w >= 2 && ((uintptr_t)d & 3)) {
- *(uint16_t *)d = value;
- w -= 2;
- d += 2;
- }
-
- while (w >= 4 && ((uintptr_t)d & 7)) {
- *(uint32_t *)d = value;
-
- w -= 4;
- d += 4;
- }
-
- while (w >= 4) {
- *(uint32_t *)d = value;
-
- w -= 4;
- d += 4;
- }
-
- while (w >= 2) {
- *(uint16_t *)d = value;
- w -= 2;
- d += 2;
- }
-
- while (w >= 1) {
- *(uint8_t *)d = (value & 0xff);
- w--;
- d++;
- }
- }
-}
-
-void spice_pixman_fill_rect_rop(pixman_image_t *dest,
- int x, int y,
- int width, int height,
- uint32_t value,
- SpiceROP rop)
-{
- uint32_t *bits;
- int stride, depth;
- uint8_t *byte_line;
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- ASSERT(x >= 0);
- ASSERT(y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(x + width <= pixman_image_get_width(dest));
- ASSERT(y + height <= pixman_image_get_height(dest));
- ASSERT(rop < 16);
-
- if (depth == 8) {
- solid_rop_8_func_t rop_func = solid_rops_8[rop];
-
- byte_line = ((uint8_t *)bits) + stride * y + x;
- while (height--) {
- rop_func((uint8_t *)byte_line, width, (uint8_t)value);
- byte_line += stride;
- }
-
- } else if (depth == 16) {
- solid_rop_16_func_t rop_func = solid_rops_16[rop];
-
- byte_line = ((uint8_t *)bits) + stride * y + x * 2;
- while (height--) {
- rop_func((uint16_t *)byte_line, width, (uint16_t)value);
- byte_line += stride;
- }
- } else {
- solid_rop_32_func_t rop_func = solid_rops_32[rop];
-
- byte_line = ((uint8_t *)bits) + stride * y + x * 4;
- while (height--) {
- rop_func((uint32_t *)byte_line, width, (uint32_t)value);
- byte_line += stride;
- }
- }
-}
-
-void spice_pixman_tile_rect(pixman_image_t *dest,
- int x, int y,
- int width, int height,
- pixman_image_t *tile,
- int offset_x,
- int offset_y)
-{
- uint32_t *bits, *tile_bits;
- int stride, depth;
- int tile_width, tile_height, tile_stride;
- uint8_t *byte_line;
- uint8_t *tile_line;
- int tile_start_x, tile_start_y, tile_end_dx;
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- tile_bits = pixman_image_get_data(tile);
- tile_stride = pixman_image_get_stride(tile);
- tile_width = pixman_image_get_width(tile);
- tile_height = pixman_image_get_height(tile);
-
- ASSERT(x >= 0);
- ASSERT(y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(x + width <= pixman_image_get_width(dest));
- ASSERT(y + height <= pixman_image_get_height(dest));
- ASSERT(depth == spice_pixman_image_get_bpp(tile));
-
- tile_start_x = (x - offset_x) % tile_width;
- if (tile_start_x < 0) {
- tile_start_x += tile_width;
- }
- tile_start_y = (y - offset_y) % tile_height;
- if (tile_start_y < 0) {
- tile_start_y += tile_height;
- }
- tile_end_dx = tile_width - tile_start_x;
-
- if (depth == 8) {
- byte_line = ((uint8_t *)bits) + stride * y + x;
- tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x;
- while (height--) {
- tiled_rop_copy_8((uint8_t *)byte_line, width,
- (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx,
- tile_width);
- byte_line += stride;
- tile_line += tile_stride;
- if (++tile_start_y == tile_height) {
- tile_line -= tile_height * tile_stride;
- tile_start_y = 0;
- }
- }
-
- } else if (depth == 16) {
- byte_line = ((uint8_t *)bits) + stride * y + x * 2;
- tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2;
- while (height--) {
- tiled_rop_copy_16((uint16_t *)byte_line, width,
- (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx,
- tile_width);
- byte_line += stride;
- tile_line += tile_stride;
- if (++tile_start_y == tile_height) {
- tile_line -= tile_height * tile_stride;
- tile_start_y = 0;
- }
- }
- } else {
- ASSERT (depth == 32);
-
- byte_line = ((uint8_t *)bits) + stride * y + x * 4;
- tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4;
- while (height--) {
- tiled_rop_copy_32((uint32_t *)byte_line, width,
- (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx,
- tile_width);
- byte_line += stride;
- tile_line += tile_stride;
- if (++tile_start_y == tile_height) {
- tile_line -= tile_height * tile_stride;
- tile_start_y = 0;
- }
- }
- }
-}
-
-void spice_pixman_tile_rect_rop(pixman_image_t *dest,
- int x, int y,
- int width, int height,
- pixman_image_t *tile,
- int offset_x,
- int offset_y,
- SpiceROP rop)
-{
- uint32_t *bits, *tile_bits;
- int stride, depth;
- int tile_width, tile_height, tile_stride;
- uint8_t *byte_line;
- uint8_t *tile_line;
- int tile_start_x, tile_start_y, tile_end_dx;
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- tile_bits = pixman_image_get_data(tile);
- tile_stride = pixman_image_get_stride(tile);
- tile_width = pixman_image_get_width(tile);
- tile_height = pixman_image_get_height(tile);
-
- ASSERT(x >= 0);
- ASSERT(y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(x + width <= pixman_image_get_width(dest));
- ASSERT(y + height <= pixman_image_get_height(dest));
- ASSERT(rop < 16);
- ASSERT(depth == spice_pixman_image_get_bpp(tile));
-
- tile_start_x = (x - offset_x) % tile_width;
- if (tile_start_x < 0) {
- tile_start_x += tile_width;
- }
- tile_start_y = (y - offset_y) % tile_height;
- if (tile_start_y < 0) {
- tile_start_y += tile_height;
- }
- tile_end_dx = tile_width - tile_start_x;
-
- if (depth == 8) {
- tiled_rop_8_func_t rop_func = tiled_rops_8[rop];
-
- byte_line = ((uint8_t *)bits) + stride * y + x;
- tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x;
- while (height--) {
- rop_func((uint8_t *)byte_line, width,
- (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx,
- tile_width);
- byte_line += stride;
- tile_line += tile_stride;
- if (++tile_start_y == tile_height) {
- tile_line -= tile_height * tile_stride;
- tile_start_y = 0;
- }
- }
-
- } else if (depth == 16) {
- tiled_rop_16_func_t rop_func = tiled_rops_16[rop];
-
- byte_line = ((uint8_t *)bits) + stride * y + x * 2;
- tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2;
- while (height--) {
- rop_func((uint16_t *)byte_line, width,
- (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx,
- tile_width);
- byte_line += stride;
- tile_line += tile_stride;
- if (++tile_start_y == tile_height) {
- tile_line -= tile_height * tile_stride;
- tile_start_y = 0;
- }
- }
- } else {
- tiled_rop_32_func_t rop_func = tiled_rops_32[rop];
-
- ASSERT (depth == 32);
-
- byte_line = ((uint8_t *)bits) + stride * y + x * 4;
- tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4;
- while (height--) {
- rop_func((uint32_t *)byte_line, width,
- (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx,
- tile_width);
- byte_line += stride;
- tile_line += tile_stride;
- if (++tile_start_y == tile_height) {
- tile_line -= tile_height * tile_stride;
- tile_start_y = 0;
- }
- }
- }
-}
-
-
-void spice_pixman_blit(pixman_image_t *dest,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height)
-{
- uint32_t *bits, *src_bits;
- int stride, depth, src_depth;
- int src_width, src_height, src_stride;
- uint8_t *byte_line;
- uint8_t *src_line;
- int byte_width;
-
- if (!src) {
- fprintf(stderr, "missing src!");
- return;
- }
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- src_bits = pixman_image_get_data(src);
- src_stride = pixman_image_get_stride(src);
- src_width = pixman_image_get_width(src);
- src_height = pixman_image_get_height(src);
- src_depth = spice_pixman_image_get_bpp(src);
-
- /* Clip source */
- if (src_x < 0) {
- width += src_x;
- dest_x -= src_x;
- src_x = 0;
- }
- if (src_y < 0) {
- height += src_y;
- dest_y -= src_y;
- src_y = 0;
- }
- if (src_x + width > src_width) {
- width = src_width - src_x;
- }
- if (src_y + height > src_height) {
- height = src_height - src_y;
- }
-
- if (width <= 0 || height <= 0) {
- return;
- }
-
- ASSERT(src_x >= 0);
- ASSERT(src_y >= 0);
- ASSERT(dest_x >= 0);
- ASSERT(dest_y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(dest_x + width <= pixman_image_get_width(dest));
- ASSERT(dest_y + height <= pixman_image_get_height(dest));
- ASSERT(src_x + width <= pixman_image_get_width(src));
- ASSERT(src_y + height <= pixman_image_get_height(src));
- ASSERT(depth == src_depth);
-
- if (pixman_blt(src_bits,
- bits,
- src_stride / 4,
- stride / 4,
- depth, depth,
- src_x, src_y,
- dest_x, dest_y,
- width, height)) {
- return;
- }
-
- if (depth == 8) {
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x;
- byte_width = width;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x;
- } else if (depth == 16) {
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2;
- byte_width = width * 2;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2;
- } else {
- ASSERT (depth == 32);
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4;
- byte_width = width * 4;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4;
- }
-
- while (height--) {
- memcpy(byte_line, src_line, byte_width);
- byte_line += stride;
- src_line += src_stride;
- }
-}
-
-void spice_pixman_blit_rop (pixman_image_t *dest,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- SpiceROP rop)
-{
- uint32_t *bits, *src_bits;
- int stride, depth, src_depth;
- int src_width, src_height, src_stride;
- uint8_t *byte_line;
- uint8_t *src_line;
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- src_bits = pixman_image_get_data(src);
- src_stride = pixman_image_get_stride(src);
- src_width = pixman_image_get_width(src);
- src_height = pixman_image_get_height(src);
- src_depth = spice_pixman_image_get_bpp(src);
-
- /* Clip source */
- if (src_x < 0) {
- width += src_x;
- dest_x -= src_x;
- src_x = 0;
- }
- if (src_y < 0) {
- height += src_y;
- dest_y -= src_y;
- src_y = 0;
- }
- if (src_x + width > src_width) {
- width = src_width - src_x;
- }
- if (src_y + height > src_height) {
- height = src_height - src_y;
- }
-
- if (width <= 0 || height <= 0) {
- return;
- }
-
- ASSERT(src_x >= 0);
- ASSERT(src_y >= 0);
- ASSERT(dest_x >= 0);
- ASSERT(dest_y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(dest_x + width <= pixman_image_get_width(dest));
- ASSERT(dest_y + height <= pixman_image_get_height(dest));
- ASSERT(src_x + width <= pixman_image_get_width(src));
- ASSERT(src_y + height <= pixman_image_get_height(src));
- ASSERT(depth == src_depth);
-
- if (depth == 8) {
- copy_rop_8_func_t rop_func = copy_rops_8[rop];
-
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x;
-
- while (height--) {
- rop_func((uint8_t *)byte_line, (uint8_t *)src_line, width);
- byte_line += stride;
- src_line += src_stride;
- }
- } else if (depth == 16) {
- copy_rop_16_func_t rop_func = copy_rops_16[rop];
-
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2;
-
- while (height--) {
- rop_func((uint16_t *)byte_line, (uint16_t *)src_line, width);
- byte_line += stride;
- src_line += src_stride;
- }
- } else {
- copy_rop_32_func_t rop_func = copy_rops_32[rop];
-
- ASSERT (depth == 32);
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4;
-
- while (height--) {
- rop_func((uint32_t *)byte_line, (uint32_t *)src_line, width);
- byte_line += stride;
- src_line += src_stride;
- }
- }
-
-}
-
-void spice_pixman_blit_colorkey (pixman_image_t *dest,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- uint32_t transparent_color)
-{
- uint32_t *bits, *src_bits;
- int stride, depth;
- int src_width, src_height, src_stride;
- uint8_t *byte_line;
- uint8_t *src_line;
- int x;
-
- bits = pixman_image_get_data(dest);
- stride = pixman_image_get_stride(dest);
- depth = spice_pixman_image_get_bpp(dest);
- /* stride is in bytes, depth in bits */
-
- src_bits = pixman_image_get_data(src);
- src_stride = pixman_image_get_stride(src);
- src_width = pixman_image_get_width(src);
- src_height = pixman_image_get_height(src);
-
- /* Clip source */
- if (src_x < 0) {
- width += src_x;
- dest_x -= src_x;
- src_x = 0;
- }
- if (src_y < 0) {
- height += src_y;
- dest_y -= src_y;
- src_y = 0;
- }
- if (src_x + width > src_width) {
- width = src_width - src_x;
- }
- if (src_y + height > src_height) {
- height = src_height - src_y;
- }
-
- if (width <= 0 || height <= 0) {
- return;
- }
-
- ASSERT(src_x >= 0);
- ASSERT(src_y >= 0);
- ASSERT(dest_x >= 0);
- ASSERT(dest_y >= 0);
- ASSERT(width > 0);
- ASSERT(height > 0);
- ASSERT(dest_x + width <= pixman_image_get_width(dest));
- ASSERT(dest_y + height <= pixman_image_get_height(dest));
- ASSERT(src_x + width <= pixman_image_get_width(src));
- ASSERT(src_y + height <= pixman_image_get_height(src));
- ASSERT(depth == spice_pixman_image_get_bpp(src));
-
- if (depth == 8) {
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x;
-
- while (height--) {
- uint8_t *d = (uint8_t *)byte_line;
- uint8_t *s = (uint8_t *)byte_line;
-
- s = (uint8_t *)src_line;
- for (x = 0; x < width; x++) {
- uint8_t val = *s;
- if (val != (uint8_t)transparent_color) {
- *d = val;
- }
- s++; d++;
- }
-
- byte_line += stride;
- src_line += src_stride;
- }
- } else if (depth == 16) {
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2;
-
- while (height--) {
- uint16_t *d = (uint16_t *)byte_line;
- uint16_t *s = (uint16_t *)byte_line;
-
- s = (uint16_t *)src_line;
- for (x = 0; x < width; x++) {
- uint16_t val = *s;
- if (val != (uint16_t)transparent_color) {
- *d = val;
- }
- s++; d++;
- }
-
- byte_line += stride;
- src_line += src_stride;
- }
- } else {
- ASSERT (depth == 32);
- byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4;
- src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4;
-
- while (height--) {
- uint32_t *d = (uint32_t *)byte_line;
- uint32_t *s = (uint32_t *)byte_line;
-
- transparent_color &= 0xffffff;
- s = (uint32_t *)src_line;
- for (x = 0; x < width; x++) {
- uint32_t val = *s;
- if ((0xffffff & val) != transparent_color) {
- *d = val;
- }
- s++; d++;
- }
-
- byte_line += stride;
- src_line += src_stride;
- }
- }
-}
-
-static void copy_bits_up(uint8_t *data, const int stride, int bpp,
- const int src_x, const int src_y,
- const int width, const int height,
- const int dest_x, const int dest_y)
-{
- uint8_t *src = data + src_y * stride + src_x * bpp;
- uint8_t *dest = data + dest_y * stride + dest_x * bpp;
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride, src += stride) {
- memcpy(dest, src, width * bpp);
- }
-}
-
-static void copy_bits_down(uint8_t *data, const int stride, int bpp,
- const int src_x, const int src_y,
- const int width, const int height,
- const int dest_x, const int dest_y)
-{
- uint8_t *src = data + (src_y + height - 1) * stride + src_x * bpp;
- uint8_t *end = data + (dest_y - 1) * stride + dest_x * bpp;
- uint8_t *dest = end + height * stride;
-
- for (; dest != end; dest -= stride, src -= stride) {
- memcpy(dest, src, width * bpp);
- }
-}
-
-static void copy_bits_same_line(uint8_t *data, const int stride, int bpp,
- const int src_x, const int src_y,
- const int width, const int height,
- const int dest_x, const int dest_y)
-{
- uint8_t *src = data + src_y * stride + src_x * bpp;
- uint8_t *dest = data + dest_y * stride + dest_x * bpp;
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride, src += stride) {
- memmove(dest, src, width * bpp);
- }
-}
-
-void spice_pixman_copy_rect (pixman_image_t *image,
- int src_x, int src_y,
- int width, int height,
- int dest_x, int dest_y)
-{
- uint8_t *data;
- int stride;
- int bpp;
-
- data = (uint8_t *)pixman_image_get_data(image);
- stride = pixman_image_get_stride(image);
- bpp = spice_pixman_image_get_bpp(image) / 8;
-
- if (dest_y > src_y) {
- copy_bits_down(data, stride, bpp,
- src_x, src_y,
- width, height,
- dest_x, dest_y);
- } else if (dest_y < src_y) {
- copy_bits_up(data, stride, bpp,
- src_x, src_y,
- width, height,
- dest_x, dest_y);
- } else {
- copy_bits_same_line(data, stride, bpp,
- src_x, src_y,
- width, height,
- dest_x, dest_y);
- }
-}
-
-pixman_bool_t spice_pixman_region32_init_rects (pixman_region32_t *region,
- const SpiceRect *rects,
- int count)
-{
- /* These types are compatible, so just cast */
- return pixman_region32_init_rects(region, (pixman_box32_t *)rects, count);
-}
-
-pixman_format_code_t spice_surface_format_to_pixman(uint32_t surface_format)
-{
- switch (surface_format) {
- case SPICE_SURFACE_FMT_1_A:
- return PIXMAN_a1;
- case SPICE_SURFACE_FMT_8_A:
- return PIXMAN_a8;
- case SPICE_SURFACE_FMT_16_555:
- return PIXMAN_x1r5g5b5;
- case SPICE_SURFACE_FMT_16_565:
- return PIXMAN_r5g6b5;
- case SPICE_SURFACE_FMT_32_xRGB:
- return PIXMAN_x8r8g8b8;
- case SPICE_SURFACE_FMT_32_ARGB:
- return PIXMAN_a8r8g8b8;
- default:
- printf("Unknown surface format %d\n", surface_format);
- abort();
- break;
- }
- return (pixman_format_code_t)0; /* Not reached */
-}
-
-/* Returns the "spice native" pixman version of a specific bitmap format.
- * This isn't bitwise the same as the bitmap format, for instance we
- * typically convert indexed to real color modes and use the standard
- * surface modes rather than weird things like 24bit
- */
-pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format,
- uint32_t palette_surface_format)
-{
- switch (bitmap_format) {
- case SPICE_BITMAP_FMT_1BIT_LE:
- case SPICE_BITMAP_FMT_1BIT_BE:
- case SPICE_BITMAP_FMT_4BIT_LE:
- case SPICE_BITMAP_FMT_4BIT_BE:
- case SPICE_BITMAP_FMT_8BIT:
- /* Indexed mode palettes are the same as their destination canvas format */
- return spice_surface_format_to_pixman(palette_surface_format);
-
- case SPICE_BITMAP_FMT_16BIT:
- return PIXMAN_x1r5g5b5;
-
- case SPICE_BITMAP_FMT_24BIT:
- case SPICE_BITMAP_FMT_32BIT:
- return PIXMAN_x8r8g8b8;
-
- case SPICE_BITMAP_FMT_RGBA:
- return PIXMAN_a8r8g8b8;
-
- case SPICE_BITMAP_FMT_INVALID:
- default:
- printf("Unknown bitmap format %d\n", bitmap_format);
- abort();
- return PIXMAN_a8r8g8b8;
- }
-}
-
-/* Tries to view a spice bitmap as a pixman_image_t without copying,
- * will often fail due to unhandled formats or strides.
- */
-pixman_image_t *spice_bitmap_try_as_pixman(int src_format,
- int flags,
- int width,
- int height,
- uint8_t *data,
- int stride)
-{
- pixman_format_code_t pixman_format;
-
- /* Pixman stride must be multiple of 4 */
- if (stride % 4 != 0) {
- return NULL;
- }
-
- switch (src_format) {
- case SPICE_BITMAP_FMT_32BIT:
-#ifdef WORDS_BIGENDIAN
- pixman_format = PIXMAN_b8g8r8x8;
-#else
- pixman_format = PIXMAN_x8r8g8b8;
-#endif
- break;
- case SPICE_BITMAP_FMT_RGBA:
-#ifdef WORDS_BIGENDIAN
- pixman_format = PIXMAN_b8g8r8a8;
-#else
- pixman_format = PIXMAN_a8r8g8b8;
-#endif
- break;
- case SPICE_BITMAP_FMT_24BIT:
-#ifdef WORDS_BIGENDIAN
- pixman_format = PIXMAN_b8g8r8;
-#else
- pixman_format = PIXMAN_r8g8b8;
-#endif
- break;
- case SPICE_BITMAP_FMT_16BIT:
-#ifdef WORDS_BIGENDIAN
- return NULL;
-#else
- pixman_format = PIXMAN_x1r5g5b5;
-#endif
- break;
-
- default:
- return NULL;
- }
-
- if (!(flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
- data += stride * (height - 1);
- stride = -stride;
- }
-
- return pixman_image_create_bits (pixman_format,
- width,
- height,
- (uint32_t *)data,
- stride);
-}
-
-#ifdef WORDS_BIGENDIAN
-#define UINT16_FROM_LE(x) SPICE_BYTESWAP16(x)
-#define UINT32_FROM_LE(x) SPICE_BYTESWAP32(x)
-#else
-#define UINT16_FROM_LE(x) (x)
-#define UINT32_FROM_LE(x) (x)
-#endif
-
-static inline uint32_t rgb_16_555_to_32(uint16_t color)
-{
- uint32_t ret;
-
- ret = ((color & 0x001f) << 3) | ((color & 0x001c) >> 2);
- ret |= ((color & 0x03e0) << 6) | ((color & 0x0380) << 1);
- ret |= ((color & 0x7c00) << 9) | ((color & 0x7000) << 4);
-
- return ret;
-}
-
-static inline uint16_t rgb_32_to_16_555(uint32_t color)
-{
- return
- (((color) >> 3) & 0x001f) |
- (((color) >> 6) & 0x03e0) |
- (((color) >> 9) & 0x7c00);
-}
-
-
-static void bitmap_32_to_32(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end)
-{
-#ifdef WORDS_BIGENDIAN
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint32_t* src_line = (uint32_t *)src;
- uint32_t* src_line_end = src_line + width;
- uint32_t* dest_line = (uint32_t *)dest;
-
- for (; src_line < src_line_end; ++dest_line, ++src_line) {
- *dest_line = UINT32_FROM_LE(*src_line);
- }
- }
-#else
- for (; src != end; src += src_stride, dest += dest_stride) {
- memcpy(dest, src, width * 4);
- }
-#endif
-}
-
-static void bitmap_24_to_32(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end)
-{
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint8_t* src_line = src;
- uint8_t* src_line_end = src_line + width * 3;
- uint32_t* dest_line = (uint32_t *)dest;
-
- for (; src_line < src_line_end; ++dest_line) {
- uint32_t r, g, b;
- b = *(src_line++);
- g = *(src_line++);
- r = *(src_line++);
- *dest_line = (r << 16) | (g << 8) | (b);
- }
- }
-}
-
-static void bitmap_16_to_16_555(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end)
-{
-#ifdef WORDS_BIGENDIAN
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint16_t* src_line = (uint16_t *)src;
- uint16_t* src_line_end = src_line + width;
- uint16_t* dest_line = (uint16_t *)dest;
-
- for (; src_line < src_line_end; ++dest_line, ++src_line) {
- *dest_line = UINT16_FROM_LE(*src_line);
- }
- }
-#else
- for (; src != end; src += src_stride, dest += dest_stride) {
- memcpy(dest, src, width * 2);
- }
-#endif
-}
-
-static void bitmap_8_32_to_32(uint8_t *dest, int dest_stride,
- uint8_t *src, int src_stride,
- int width, uint8_t *end,
- SpicePalette *palette)
-{
- uint32_t local_ents[256];
- uint32_t *ents;
- int n_ents;
-#ifdef WORDS_BIGENDIAN
- int i;
-#endif
-
- if (!palette) {
- PANIC("No palette");
- return;
- }
-
- n_ents = MIN(palette->num_ents, 256);
- ents = palette->ents;
-
- if (n_ents < 255
-#ifdef WORDS_BIGENDIAN
- || TRUE
-#endif
- ) {
- memcpy(local_ents, ents, n_ents*4);
- ents = local_ents;
-
-#ifdef WORDS_BIGENDIAN
- for (i = 0; i < n_ents; i++) {
- ents[i] = UINT32_FROM_LE(ents[i]);
- }
-#endif
- }
-
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint32_t *dest_line = (uint32_t*)dest;
- uint8_t *src_line = src;
- uint8_t *src_line_end = src_line + width;
-
- while (src_line < src_line_end) {
- *(dest_line++) = ents[*(src_line++)];
- }
- }
-}
-
-static void bitmap_8_16_to_16_555(uint8_t *dest, int dest_stride,
- uint8_t *src, int src_stride,
- int width, uint8_t *end,
- SpicePalette *palette)
-{
- uint32_t local_ents[256];
- uint32_t *ents;
- int n_ents;
-#ifdef WORDS_BIGENDIAN
- int i;
-#endif
-
- if (!palette) {
- PANIC("No palette");
- return;
- }
-
- n_ents = MIN(palette->num_ents, 256);
- ents = palette->ents;
-
- if (n_ents < 255
-#ifdef WORDS_BIGENDIAN
- || TRUE
-#endif
- ) {
- memcpy(local_ents, ents, n_ents*4);
- ents = local_ents;
-
-#ifdef WORDS_BIGENDIAN
- for (i = 0; i < n_ents; i++) {
- ents[i] = UINT32_FROM_LE(ents[i]);
- }
-#endif
- }
-
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint16_t *dest_line = (uint16_t*)dest;
- uint8_t *src_line = src;
- uint8_t *src_line_end = src_line + width;
-
- while (src_line < src_line_end) {
- *(dest_line++) = ents[*(src_line++)];
- }
- }
-}
-
-static void bitmap_4be_32_to_32(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end,
- SpicePalette *palette)
-{
- uint32_t local_ents[16];
- uint32_t *ents;
- int n_ents;
-#ifdef WORDS_BIGENDIAN
- int i;
-#endif
-
- if (!palette) {
- PANIC("No palette");
- return;
- }
-
- n_ents = MIN(palette->num_ents, 16);
- ents = palette->ents;
-
- if (n_ents < 16
-#ifdef WORDS_BIGENDIAN
- || TRUE
-#endif
- ) {
- memcpy(local_ents, ents, n_ents*4);
- ents = local_ents;
-
-#ifdef WORDS_BIGENDIAN
- for (i = 0; i < n_ents; i++) {
- ents[i] = UINT32_FROM_LE(ents[i]);
- }
-#endif
- }
-
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint32_t *dest_line = (uint32_t *)dest;
- uint8_t *row = src;
- int i;
-
- for (i = 0; i < (width >> 1); i++) {
- *(dest_line++) = ents[(*row >> 4) & 0x0f];
- *(dest_line++) = ents[*(row++) & 0x0f];
- }
- if (width & 1) {
- *(dest_line) = ents[(*row >> 4) & 0x0f];
- }
- }
-}
-
-static void bitmap_4be_16_to_16_555(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end,
- SpicePalette *palette)
-{
- uint32_t local_ents[16];
- uint32_t *ents;
- int n_ents;
-#ifdef WORDS_BIGENDIAN
- int i;
-#endif
-
- if (!palette) {
- PANIC("No palette");
- return;
- }
-
- n_ents = MIN(palette->num_ents, 16);
- ents = palette->ents;
-
- if (n_ents < 16
-#ifdef WORDS_BIGENDIAN
- || TRUE
-#endif
- ) {
- memcpy(local_ents, ents, n_ents*4);
- ents = local_ents;
-
-#ifdef WORDS_BIGENDIAN
- for (i = 0; i < n_ents; i++) {
- ents[i] = UINT32_FROM_LE(ents[i]);
- }
-#endif
- }
-
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint16_t *dest_line = (uint16_t *)dest;
- uint8_t *row = src;
- int i;
-
- for (i = 0; i < (width >> 1); i++) {
- *(dest_line++) = ents[(*row >> 4) & 0x0f];
- *(dest_line++) = ents[*(row++) & 0x0f];
- }
- if (width & 1) {
- *(dest_line) = ents[(*row >> 4) & 0x0f];
- }
- }
-}
-
-static inline int test_bit_be(void* addr, int bit)
-{
- return !!(((uint8_t*)addr)[bit >> 3] & (0x80 >> (bit & 0x07)));
-}
-
-static void bitmap_1be_32_to_32(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end,
- SpicePalette *palette)
-{
- uint32_t fore_color;
- uint32_t back_color;
-
- ASSERT(palette != NULL);
-
- if (!palette) {
- return;
- }
-
- fore_color = UINT32_FROM_LE(palette->ents[1]);
- back_color = UINT32_FROM_LE(palette->ents[0]);
-
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint32_t* dest_line = (uint32_t*)dest;
- int i;
-
- for (i = 0; i < width; i++) {
- if (test_bit_be(src, i)) {
- *(dest_line++) = fore_color;
- } else {
- *(dest_line++) = back_color;
- }
- }
- }
-}
-
-
-static void bitmap_1be_16_to_16_555(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end,
- SpicePalette *palette)
-{
- uint16_t fore_color;
- uint16_t back_color;
-
- ASSERT(palette != NULL);
-
- if (!palette) {
- return;
- }
-
- fore_color = (uint16_t) UINT32_FROM_LE(palette->ents[1]);
- back_color = (uint16_t) UINT32_FROM_LE(palette->ents[0]);
-
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint16_t* dest_line = (uint16_t*)dest;
- int i;
-
- for (i = 0; i < width; i++) {
- if (test_bit_be(src, i)) {
- *(dest_line++) = fore_color;
- } else {
- *(dest_line++) = back_color;
- }
- }
- }
-}
-
-#ifdef NOT_USED_ATM
-
-static void bitmap_16_to_32(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end)
-{
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint16_t* src_line = (uint16_t*)src;
- uint16_t* src_line_end = src_line + width;
- uint32_t* dest_line = (uint32_t*)dest;
-
- for (; src_line < src_line_end; ++dest_line, src_line++) {
- *dest_line = rgb_16_555_to_32(UINT16_FROM_LE(*src_line));
- }
- }
-}
-
-static void bitmap_32_to_16_555(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end)
-{
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint32_t* src_line = (uint32_t *)src;
- uint32_t* src_line_end = src_line + width;
- uint16_t* dest_line = (uint16_t *)dest;
-
- for (; src_line < src_line_end; ++dest_line, ++src_line) {
- *dest_line = rgb_32_to_16_555(UINT16_FROM_LE(*src_line));
- }
- }
-}
-
-
-static void bitmap_24_to_16_555(uint8_t* dest, int dest_stride,
- uint8_t* src, int src_stride,
- int width, uint8_t* end)
-{
- for (; src != end; src += src_stride, dest += dest_stride) {
- uint8_t* src_line = src;
- uint8_t* src_line_end = src_line + width * 3;
- uint16_t* dest_line = (uint16_t *)dest;
-
- for (; src_line < src_line_end; ++dest_line) {
- uint8_t r, g, b;
- b = *(src_line++);
- g = *(src_line++);
- r = *(src_line++);
- *dest_line = rgb_32_to_16_555(r << 24 | g << 16 | b);
- }
- }
-}
-
-#endif
-
-/* This assumes that the dest, if set is the same format as
- spice_bitmap_format_to_pixman would have picked */
-pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image,
- int src_format,
- int flags,
- int width,
- int height,
- uint8_t *src,
- int src_stride,
- uint32_t palette_surface_format,
- SpicePalette *palette)
-{
- uint8_t* dest;
- int dest_stride;
- uint8_t* end;
-
- if (dest_image == NULL) {
- pixman_format_code_t dest_format;
-
- dest_format = spice_bitmap_format_to_pixman(src_format,
- palette_surface_format);
- dest_image = pixman_image_create_bits (dest_format,
- width, height,
- NULL, 0);
- }
-
- dest = (uint8_t *)pixman_image_get_data(dest_image);
- dest_stride = pixman_image_get_stride(dest_image);
- if (!(flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
- ASSERT(height > 0);
- dest += dest_stride * (height - 1);
- dest_stride = -dest_stride;
- }
- end = src + (height * src_stride);
-
- switch (src_format) {
- case SPICE_BITMAP_FMT_32BIT:
- case SPICE_BITMAP_FMT_RGBA:
- bitmap_32_to_32(dest, dest_stride, src, src_stride, width, end);
- break;
- case SPICE_BITMAP_FMT_24BIT:
- bitmap_24_to_32(dest, dest_stride, src, src_stride, width, end);
- break;
- case SPICE_BITMAP_FMT_16BIT:
- bitmap_16_to_16_555(dest, dest_stride, src, src_stride, width, end);
- break;
- case SPICE_BITMAP_FMT_8BIT:
- if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB ||
- palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) {
- bitmap_8_32_to_32(dest, dest_stride, src, src_stride, width, end, palette);
- } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) {
- bitmap_8_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette);
- } else {
- PANIC("Unsupported palette format");
- }
- break;
- case SPICE_BITMAP_FMT_4BIT_BE:
- if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB ||
- palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) {
- bitmap_4be_32_to_32(dest, dest_stride, src, src_stride, width, end, palette);
- } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) {
- bitmap_4be_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette);
- } else {
- PANIC("Unsupported palette format");
- }
- break;
- case SPICE_BITMAP_FMT_1BIT_BE:
- if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB ||
- palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) {
- bitmap_1be_32_to_32(dest, dest_stride, src, src_stride, width, end, palette);
- } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) {
- bitmap_1be_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette);
- } else {
- PANIC("Unsupported palette format");
- }
- break;
- default:
- PANIC("Unsupported bitmap format");
- break;
- }
-
- return dest_image;
-}
-
-static int pixman_format_compatible (pixman_format_code_t dest_format,
- pixman_format_code_t src_format)
-{
- if (dest_format == src_format) {
- return TRUE;
- }
-
- if (src_format == PIXMAN_a8r8g8b8 &&
- dest_format == PIXMAN_x8r8g8b8) {
- /* This is the same, we just ignore the alphas */
- return TRUE;
- }
-
- return FALSE;
-}
-
-pixman_image_t *spice_bitmap_convert_to_pixman(pixman_format_code_t dest_format,
- pixman_image_t *dest_image,
- int src_format,
- int flags,
- int width,
- int height,
- uint8_t *src,
- int src_stride,
- uint32_t palette_surface_format,
- SpicePalette *palette)
-{
- pixman_image_t *src_image;
- pixman_format_code_t native_format;
-
- if (dest_image == NULL) {
- dest_image = pixman_image_create_bits (dest_format,
- width, height,
- NULL, 0);
- }
-
- native_format =
- spice_bitmap_format_to_pixman(src_format, palette_surface_format);
-
- if (pixman_format_compatible (dest_format, native_format)) {
- return spice_bitmap_to_pixman(dest_image,
- src_format,
- flags, width,height,
- src, src_stride,
- palette_surface_format, palette);
- }
-
- src_image = spice_bitmap_try_as_pixman(src_format,
- flags, width,height,
- src, src_stride);
-
- /* Can't convert directly, need a temporary copy
- * Hopefully most bitmap reads should not need conversion (i.e.
- * hit the spice_bitmap_to_pixmap case above) or work with the
- * try_as_pixmap case, but in case some specific combination
- * shows up here commonly we might want to add non-temporary
- * conversion special casing here */
- if (src_image == NULL) {
- src_image = spice_bitmap_to_pixman(NULL,
- src_format,
- flags, width,height,
- src, src_stride,
- palette_surface_format, palette);
- }
-
- pixman_image_composite32 (PIXMAN_OP_SRC,
- src_image, NULL, dest_image,
- 0, 0,
- 0, 0,
- 0, 0,
- width, height);
-
- pixman_image_unref (src_image);
-
- return dest_image;
-}
diff --git a/common/pixman_utils.h b/common/pixman_utils.h
deleted file mode 100644
index e15b682..0000000
--- a/common/pixman_utils.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H__PIXMAN_UTILS
-#define _H__PIXMAN_UTILS
-
-#include <spice/types.h>
-#include <stdlib.h>
-#define PIXMAN_DONT_DEFINE_STDINT
-#include <pixman.h>
-
-#include "draw.h"
-
-/* This lists all possible 2 argument binary raster ops.
- * This enum has the same values as the X11 GXcopy type
- * and same as the GL constants (GL_AND etc) if you
- * or it with 0x1500. However it is not exactly the
- * same as the win32 ROP2 type (they use another order).
- */
-typedef enum {
- SPICE_ROP_CLEAR, /* 0x0 0 */
- SPICE_ROP_AND, /* 0x1 src AND dst */
- SPICE_ROP_AND_REVERSE, /* 0x2 src AND NOT dst */
- SPICE_ROP_COPY, /* 0x3 src */
- SPICE_ROP_AND_INVERTED, /* 0x4 (NOT src) AND dst */
- SPICE_ROP_NOOP, /* 0x5 dst */
- SPICE_ROP_XOR, /* 0x6 src XOR dst */
- SPICE_ROP_OR, /* 0x7 src OR dst */
- SPICE_ROP_NOR, /* 0x8 (NOT src) AND (NOT dst) */
- SPICE_ROP_EQUIV, /* 0x9 (NOT src) XOR dst */
- SPICE_ROP_INVERT, /* 0xa NOT dst */
- SPICE_ROP_OR_REVERSE, /* 0xb src OR (NOT dst) */
- SPICE_ROP_COPY_INVERTED, /* 0xc NOT src */
- SPICE_ROP_OR_INVERTED, /* 0xd (NOT src) OR dst */
- SPICE_ROP_NAND, /* 0xe (NOT src) OR (NOT dst) */
- SPICE_ROP_SET /* 0xf 1 */
-} SpiceROP;
-
-
-int spice_pixman_image_get_bpp(pixman_image_t *image);
-
-pixman_format_code_t spice_surface_format_to_pixman(uint32_t surface_format);
-pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format,
- uint32_t palette_surface_format);
-pixman_image_t *spice_bitmap_try_as_pixman(int src_format, int flags,
- int width, int height,
- uint8_t *data, int stride);
-pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image,
- int src_format, int flags,
- int width, int height,
- uint8_t *src, int src_stride,
- uint32_t palette_surface_format,
- SpicePalette *palette);
-pixman_image_t *spice_bitmap_convert_to_pixman(pixman_format_code_t dest_format,
- pixman_image_t *dest_image,
- int src_format, int flags,
- int width, int height,
- uint8_t *src, int src_stride,
- uint32_t palette_surface_format,
- SpicePalette *palette);
-
-void spice_pixman_region32_init_from_bitmap(pixman_region32_t *region,
- uint32_t *data,
- int width, int height,
- int stride);
-pixman_bool_t spice_pixman_region32_init_rects(pixman_region32_t *region,
- const SpiceRect *rects,
- int count);
-void spice_pixman_fill_rect(pixman_image_t *dest,
- int x, int y,
- int w, int h,
- uint32_t value);
-void spice_pixman_fill_rect_rop(pixman_image_t *dest,
- int x, int y,
- int w, int h,
- uint32_t value,
- SpiceROP rop);
-void spice_pixman_tile_rect(pixman_image_t *dest,
- int x, int y,
- int w, int h,
- pixman_image_t *tile,
- int offset_x,
- int offset_y);
-void spice_pixman_tile_rect_rop(pixman_image_t *dest,
- int x, int y,
- int w, int h,
- pixman_image_t *tile,
- int offset_x,
- int offset_y,
- SpiceROP rop);
-void spice_pixman_blit(pixman_image_t *dest,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int w, int h);
-void spice_pixman_blit_rop(pixman_image_t *dest,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int w, int h,
- SpiceROP rop);
-void spice_pixman_blit_colorkey(pixman_image_t *dest,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- uint32_t transparent_color);
-void spice_pixman_copy_rect(pixman_image_t *image,
- int src_x, int src_y,
- int w, int h,
- int dest_x, int dest_y);
-
-#endif /* _H__PIXMAN_UTILS */
diff --git a/common/quic.c b/common/quic.c
deleted file mode 100644
index 9f2c978..0000000
--- a/common/quic.c
+++ /dev/null
@@ -1,1706 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-// Red Hat image compression based on SFALIC by Roman Starosolski
-// http://sun.iinf.polsl.gliwice.pl/~rstaros/sfalic/index.html
-
-#include "quic.h"
-#include <spice/macros.h>
-
-//#define DEBUG
-
-#define RLE
-#define RLE_STAT
-#define PRED_1
-//#define RLE_PRED_1
-#define RLE_PRED_2
-//#define RLE_PRED_3
-#define QUIC_RGB
-
-#define QUIC_MAGIC (*(uint32_t *)"QUIC")
-#define QUIC_VERSION_MAJOR 0U
-#define QUIC_VERSION_MINOR 1U
-#define QUIC_VERSION ((QUIC_VERSION_MAJOR << 16) | (QUIC_VERSION_MAJOR & 0xffff))
-
-#ifdef DEBUG
-
-#define ASSERT(usr, x) \
- if (!(x)) (usr)->error(usr, "%s: ASSERT %s failed\n", __FUNCTION__, #x);
-
-#else
-
-#define ASSERT(usr, x)
-
-#endif
-
-typedef uint8_t BYTE;
-
-/* maximum number of codes in family */
-#define MAXNUMCODES 8
-
-/* model evolution, warning: only 1,3 and 5 allowed */
-#define DEFevol 3
-#define MINevol 0
-#define MAXevol 5
-
-/* starting wait mask index */
-#define DEFwmistart 0
-#define MINwmistart 0
-
-/* codeword length limit */
-#define DEFmaxclen 26
-
-/* target wait mask index */
-#define DEFwmimax 6
-
-/* number of symbols to encode before increasing wait mask index */
-#define DEFwminext 2048
-#define MINwminext 1
-#define MAXwminext 100000000
-
-typedef struct QuicFamily {
- unsigned int nGRcodewords[MAXNUMCODES]; /* indexed by code number, contains number of
- unmodified GR codewords in the code */
- unsigned int notGRcwlen[MAXNUMCODES]; /* indexed by code number, contains codeword
- length of the not-GR codeword */
- unsigned int notGRprefixmask[MAXNUMCODES]; /* indexed by code number, contains mask to
- determine if the codeword is GR or not-GR */
- unsigned int notGRsuffixlen[MAXNUMCODES]; /* indexed by code number, contains suffix
- length of the not-GR codeword */
-
- /* array for translating distribution U to L for depths up to 8 bpp,
- initialized by decorelateinit() */
- BYTE xlatU2L[256];
-
- /* array for translating distribution L to U for depths up to 8 bpp,
- initialized by corelateinit() */
- unsigned int xlatL2U[256];
-} QuicFamily;
-
-static QuicFamily family_8bpc;
-static QuicFamily family_5bpc;
-
-typedef unsigned COUNTER; /* counter in the array of counters in bucket of the data model */
-
-typedef struct s_bucket {
- COUNTER *pcounters; /* pointer to array of counters */
- unsigned int bestcode; /* best code so far */
-} s_bucket;
-
-typedef struct Encoder Encoder;
-
-typedef struct CommonState {
- Encoder *encoder;
-
- unsigned int waitcnt;
- unsigned int tabrand_seed;
- unsigned int wm_trigger;
- unsigned int wmidx;
- unsigned int wmileft;
-
-#ifdef RLE_STAT
- int melcstate; /* index to the state array */
-
- int melclen; /* contents of the state array location
- indexed by melcstate: the "expected"
- run length is 2^melclen, shorter runs are
- encoded by a 1 followed by the run length
- in binary representation, wit a fixed length
- of melclen bits */
-
- unsigned long melcorder; /* 2^ melclen */
-#endif
-} CommonState;
-
-
-#define MAX_CHANNELS 4
-
-typedef struct FamilyStat {
- s_bucket **buckets_ptrs;
- s_bucket *buckets_buf;
- COUNTER *counters;
-} FamilyStat;
-
-typedef struct Channel {
- Encoder *encoder;
-
- int correlate_row_width;
- BYTE *correlate_row;
-
- s_bucket **_buckets_ptrs;
-
- FamilyStat family_stat_8bpc;
- FamilyStat family_stat_5bpc;
-
- CommonState state;
-} Channel;
-
-struct Encoder {
- QuicUsrContext *usr;
- QuicImageType type;
- unsigned int width;
- unsigned int height;
- unsigned int num_channels;
-
- unsigned int n_buckets_8bpc;
- unsigned int n_buckets_5bpc;
-
- unsigned int io_available_bits;
- uint32_t io_word;
- uint32_t io_next_word;
- uint32_t *io_now;
- uint32_t *io_end;
- uint32_t io_words_count;
-
- int rows_completed;
-
- Channel channels[MAX_CHANNELS];
-
- CommonState rgb_state;
-};
-
-/* target wait mask index */
-static int wmimax = DEFwmimax;
-
-/* number of symbols to encode before increasing wait mask index */
-static int wminext = DEFwminext;
-
-/* model evolution mode */
-static int evol = DEFevol;
-
-/* bppmask[i] contains i ones as lsb-s */
-static const unsigned long int bppmask[33] = {
- 0x00000000, /* [0] */
- 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
- 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
- 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
- 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
- 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
- 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
- 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff /* [32] */
-};
-
-static const unsigned int bitat[32] = {
- 0x00000001, 0x00000002, 0x00000004, 0x00000008,
- 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800,
- 0x00001000, 0x00002000, 0x00004000, 0x00008000,
- 0x00010000, 0x00020000, 0x00040000, 0x00080000,
- 0x00100000, 0x00200000, 0x00400000, 0x00800000,
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000 /* [31]*/
-};
-
-
-#define TABRAND_TABSIZE 256
-#define TABRAND_SEEDMASK 0x0ff
-
-static const unsigned int tabrand_chaos[TABRAND_TABSIZE] = {
- 0x02c57542, 0x35427717, 0x2f5a2153, 0x9244f155, 0x7bd26d07, 0x354c6052, 0x57329b28, 0x2993868e,
- 0x6cd8808c, 0x147b46e0, 0x99db66af, 0xe32b4cac, 0x1b671264, 0x9d433486, 0x62a4c192, 0x06089a4b,
- 0x9e3dce44, 0xdaabee13, 0x222425ea, 0xa46f331d, 0xcd589250, 0x8bb81d7f, 0xc8b736b9, 0x35948d33,
- 0xd7ac7fd0, 0x5fbe2803, 0x2cfbc105, 0x013dbc4e, 0x7a37820f, 0x39f88e9e, 0xedd58794, 0xc5076689,
- 0xfcada5a4, 0x64c2f46d, 0xb3ba3243, 0x8974b4f9, 0x5a05aebd, 0x20afcd00, 0x39e2b008, 0x88a18a45,
- 0x600bde29, 0xf3971ace, 0xf37b0a6b, 0x7041495b, 0x70b707ab, 0x06beffbb, 0x4206051f, 0xe13c4ee3,
- 0xc1a78327, 0x91aa067c, 0x8295f72a, 0x732917a6, 0x1d871b4d, 0x4048f136, 0xf1840e7e, 0x6a6048c1,
- 0x696cb71a, 0x7ff501c3, 0x0fc6310b, 0x57e0f83d, 0x8cc26e74, 0x11a525a2, 0x946934c7, 0x7cd888f0,
- 0x8f9d8604, 0x4f86e73b, 0x04520316, 0xdeeea20c, 0xf1def496, 0x67687288, 0xf540c5b2, 0x22401484,
- 0x3478658a, 0xc2385746, 0x01979c2c, 0x5dad73c8, 0x0321f58b, 0xf0fedbee, 0x92826ddf, 0x284bec73,
- 0x5b1a1975, 0x03df1e11, 0x20963e01, 0xa17cf12b, 0x740d776e, 0xa7a6bf3c, 0x01b5cce4, 0x1118aa76,
- 0xfc6fac0a, 0xce927e9b, 0x00bf2567, 0x806f216c, 0xbca69056, 0x795bd3e9, 0xc9dc4557, 0x8929b6c2,
- 0x789d52ec, 0x3f3fbf40, 0xb9197368, 0xa38c15b5, 0xc3b44fa8, 0xca8333b0, 0xb7e8d590, 0xbe807feb,
- 0xbf5f8360, 0xd99e2f5c, 0x372928e1, 0x7c757c4c, 0x0db5b154, 0xc01ede02, 0x1fc86e78, 0x1f3985be,
- 0xb4805c77, 0x00c880fa, 0x974c1b12, 0x35ab0214, 0xb2dc840d, 0x5b00ae37, 0xd313b026, 0xb260969d,
- 0x7f4c8879, 0x1734c4d3, 0x49068631, 0xb9f6a021, 0x6b863e6f, 0xcee5debf, 0x29f8c9fb, 0x53dd6880,
- 0x72b61223, 0x1f67a9fd, 0x0a0f6993, 0x13e59119, 0x11cca12e, 0xfe6b6766, 0x16b6effc, 0x97918fc4,
- 0xc2b8a563, 0x94f2f741, 0x0bfa8c9a, 0xd1537ae8, 0xc1da349c, 0x873c60ca, 0x95005b85, 0x9b5c080e,
- 0xbc8abbd9, 0xe1eab1d2, 0x6dac9070, 0x4ea9ebf1, 0xe0cf30d4, 0x1ef5bd7b, 0xd161043e, 0x5d2fa2e2,
- 0xff5d3cae, 0x86ed9f87, 0x2aa1daa1, 0xbd731a34, 0x9e8f4b22, 0xb1c2c67a, 0xc21758c9, 0xa182215d,
- 0xccb01948, 0x8d168df7, 0x04238cfe, 0x368c3dbc, 0x0aeadca5, 0xbad21c24, 0x0a71fee5, 0x9fc5d872,
- 0x54c152c6, 0xfc329483, 0x6783384a, 0xeddb3e1c, 0x65f90e30, 0x884ad098, 0xce81675a, 0x4b372f7d,
- 0x68bf9a39, 0x43445f1e, 0x40f8d8cb, 0x90d5acb6, 0x4cd07282, 0x349eeb06, 0x0c9d5332, 0x520b24ef,
- 0x80020447, 0x67976491, 0x2f931ca3, 0xfe9b0535, 0xfcd30220, 0x61a9e6cc, 0xa487d8d7, 0x3f7c5dd1,
- 0x7d0127c5, 0x48f51d15, 0x60dea871, 0xc9a91cb7, 0x58b53bb3, 0x9d5e0b2d, 0x624a78b4, 0x30dbee1b,
- 0x9bdf22e7, 0x1df5c299, 0x2d5643a7, 0xf4dd35ff, 0x03ca8fd6, 0x53b47ed8, 0x6f2c19aa, 0xfeb0c1f4,
- 0x49e54438, 0x2f2577e6, 0xbf876969, 0x72440ea9, 0xfa0bafb8, 0x74f5b3a0, 0x7dd357cd, 0x89ce1358,
- 0x6ef2cdda, 0x1e7767f3, 0xa6be9fdb, 0x4f5f88f8, 0xba994a3a, 0x08ca6b65, 0xe0893818, 0x9e00a16a,
- 0xf42bfc8f, 0x9972eedc, 0x749c8b51, 0x32c05f5e, 0xd706805f, 0x6bfbb7cf, 0xd9210a10, 0x31a1db97,
- 0x923a9559, 0x37a7a1f6, 0x059f8861, 0xca493e62, 0x65157e81, 0x8f6467dd, 0xab85ff9f, 0x9331aff2,
- 0x8616b9f5, 0xedbd5695, 0xee7e29b1, 0x313ac44f, 0xb903112f, 0x432ef649, 0xdc0a36c0, 0x61cf2bba,
- 0x81474925, 0xa8b6c7ad, 0xee5931de, 0xb2f8158d, 0x59fb7409, 0x2e3dfaed, 0x9af25a3f, 0xe1fed4d5,
-};
-
-static unsigned int stabrand(void)
-{
- //ASSERT( !(TABRAND_SEEDMASK & TABRAND_TABSIZE));
- //ASSERT( TABRAND_SEEDMASK + 1 == TABRAND_TABSIZE );
-
- return TABRAND_SEEDMASK;
-}
-
-static unsigned int tabrand(unsigned int *tabrand_seed)
-{
- return tabrand_chaos[++*tabrand_seed & TABRAND_SEEDMASK];
-}
-
-static const unsigned short besttrigtab[3][11] = { /* array of wm_trigger for waitmask and evol,
- used by set_wm_trigger() */
- /* 1 */ { 550, 900, 800, 700, 500, 350, 300, 200, 180, 180, 160},
- /* 3 */ { 110, 550, 900, 800, 550, 400, 350, 250, 140, 160, 140},
- /* 5 */ { 100, 120, 550, 900, 700, 500, 400, 300, 220, 250, 160}
-};
-
-/* set wm_trigger knowing waitmask (param) and evol (glob)*/
-static void set_wm_trigger(CommonState *state)
-{
- unsigned int wm = state->wmidx;
- if (wm > 10) {
- wm = 10;
- }
-
- ASSERT(state->encoder->usr, evol < 6);
-
- state->wm_trigger = besttrigtab[evol / 2][wm];
-
- ASSERT(state->encoder->usr, state->wm_trigger <= 2000);
- ASSERT(state->encoder->usr, state->wm_trigger >= 1);
-}
-
-static int ceil_log_2(int val) /* ceil(log_2(val)) */
-{
- int result;
-
- //ASSERT(val>0);
-
- if (val == 1) {
- return 0;
- }
-
- result = 1;
- val -= 1;
- while (val >>= 1) {
- result++;
- }
-
- return result;
-}
-
-/* number of leading zeroes in the byte, used by cntlzeroes(uint)*/
-static const BYTE lzeroes[256] = {
- 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* count leading zeroes */
-static unsigned int cnt_l_zeroes(const unsigned int bits)
-{
- if (bits & 0xff800000) {
- return lzeroes[bits >> 24];
- } else if (bits & 0xffff8000) {
- return 8 + lzeroes[(bits >> 16) & 0x000000ff];
- } else if (bits & 0xffffff80) {
- return 16 + lzeroes[(bits >> 8) & 0x000000ff];
- } else {
- return 24 + lzeroes[bits & 0x000000ff];
- }
-}
-
-#define QUIC_FAMILY_8BPC
-#include "quic_family_tmpl.c"
-
-#ifdef QUIC_RGB
-#define QUIC_FAMILY_5BPC
-#include "quic_family_tmpl.c"
-#endif
-
-static void decorelate_init(QuicFamily *family, int bpc)
-{
- const unsigned int pixelbitmask = bppmask[bpc];
- const unsigned int pixelbitmaskshr = pixelbitmask >> 1;
- unsigned int s;
-
- //ASSERT(bpc <= 8);
-
- for (s = 0; s <= pixelbitmask; s++) {
- if (s <= pixelbitmaskshr) {
- family->xlatU2L[s] = s << 1;
- } else {
- family->xlatU2L[s] = ((pixelbitmask - s) << 1) + 1;
- }
- }
-}
-
-static void corelate_init(QuicFamily *family, int bpc)
-{
- const unsigned long int pixelbitmask = bppmask[bpc];
- unsigned long int s;
-
- //ASSERT(bpc <= 8);
-
- for (s = 0; s <= pixelbitmask; s++) {
- if (s & 0x01) {
- family->xlatL2U[s] = pixelbitmask - (s >> 1);
- } else {
- family->xlatL2U[s] = (s >> 1);
- }
- }
-}
-
-static void family_init(QuicFamily *family, int bpc, int limit)
-{
- int l;
-
- for (l = 0; l < bpc; l++) { /* fill arrays indexed by code number */
- int altprefixlen, altcodewords;
-
- altprefixlen = limit - bpc;
- if (altprefixlen > (int)(bppmask[bpc - l])) {
- altprefixlen = bppmask[bpc - l];
- }
-
- altcodewords = bppmask[bpc] + 1 - (altprefixlen << l);
-
- family->nGRcodewords[l] = (altprefixlen << l);
- family->notGRcwlen[l] = altprefixlen + ceil_log_2(altcodewords);
- family->notGRprefixmask[l] = bppmask[32 - altprefixlen]; /* needed for decoding only */
- family->notGRsuffixlen[l] = ceil_log_2(altcodewords); /* needed for decoding only */
- }
-
- decorelate_init(family, bpc);
- corelate_init(family, bpc);
-}
-
-static void more_io_words(Encoder *encoder)
-{
- uint32_t *io_ptr;
- int num_io_words = encoder->usr->more_space(encoder->usr, &io_ptr, encoder->rows_completed);
- if (num_io_words <= 0) {
- encoder->usr->error(encoder->usr, "%s: no more words\n", __FUNCTION__);
- }
- ASSERT(encoder->usr, io_ptr);
- encoder->io_words_count += num_io_words;
- encoder->io_now = io_ptr;
- encoder->io_end = encoder->io_now + num_io_words;
-}
-
-static void __write_io_word(Encoder *encoder)
-{
- more_io_words(encoder);
- *(encoder->io_now++) = encoder->io_word;
-}
-
-static void (*__write_io_word_ptr)(Encoder *encoder) = __write_io_word;
-
-static INLINE void write_io_word(Encoder *encoder)
-{
- if (encoder->io_now == encoder->io_end) {
- __write_io_word_ptr(encoder); //disable inline optimizations
- return;
- }
- *(encoder->io_now++) = encoder->io_word;
-}
-
-static INLINE void encode(Encoder *encoder, unsigned int word, unsigned int len)
-{
- int delta;
-
- ASSERT(encoder->usr, len > 0 && len < 32);
- ASSERT(encoder->usr, !(word & ~bppmask[len]));
- if ((delta = ((int)encoder->io_available_bits - len)) >= 0) {
- encoder->io_available_bits = delta;
- encoder->io_word |= word << encoder->io_available_bits;
- return;
- }
- delta = -delta;
- encoder->io_word |= word >> delta;
- write_io_word(encoder);
- encoder->io_available_bits = 32 - delta;
- encoder->io_word = word << encoder->io_available_bits;
-
- ASSERT(encoder->usr, encoder->io_available_bits < 32);
- ASSERT(encoder->usr, (encoder->io_word & bppmask[encoder->io_available_bits]) == 0);
-}
-
-static INLINE void encode_32(Encoder *encoder, unsigned int word)
-{
- encode(encoder, word >> 16, 16);
- encode(encoder, word & 0x0000ffff, 16);
-}
-
-static INLINE void flush(Encoder *encoder)
-{
- if (encoder->io_available_bits > 0 && encoder->io_available_bits != 32) {
- encode(encoder, 0, encoder->io_available_bits);
- }
- encode_32(encoder, 0);
- encode(encoder, 0, 1);
-}
-
-static void __read_io_word(Encoder *encoder)
-{
- more_io_words(encoder);
- encoder->io_next_word = *(encoder->io_now++);
-}
-
-static void (*__read_io_word_ptr)(Encoder *encoder) = __read_io_word;
-
-
-static INLINE void read_io_word(Encoder *encoder)
-{
- if (encoder->io_now == encoder->io_end) {
- __read_io_word_ptr(encoder); //disable inline optimizations
- return;
- }
- ASSERT(encoder->usr, encoder->io_now < encoder->io_end);
- encoder->io_next_word = *(encoder->io_now++);
-}
-
-static INLINE void decode_eatbits(Encoder *encoder, int len)
-{
- int delta;
-
- ASSERT(encoder->usr, len > 0 && len < 32);
- encoder->io_word <<= len;
-
- if ((delta = ((int)encoder->io_available_bits - len)) >= 0) {
- encoder->io_available_bits = delta;
- encoder->io_word |= encoder->io_next_word >> encoder->io_available_bits;
- return;
- }
-
- delta = -delta;
- encoder->io_word |= encoder->io_next_word << delta;
- read_io_word(encoder);
- encoder->io_available_bits = 32 - delta;
- encoder->io_word |= (encoder->io_next_word >> encoder->io_available_bits);
-}
-
-static INLINE void decode_eat32bits(Encoder *encoder)
-{
- decode_eatbits(encoder, 16);
- decode_eatbits(encoder, 16);
-}
-
-#ifdef RLE
-
-#ifdef RLE_STAT
-
-static INLINE void encode_ones(Encoder *encoder, unsigned int n)
-{
- unsigned int count;
-
- for (count = n >> 5; count; count--) {
- encode(encoder, ~0U, 32);
- }
-
- if ((n &= 0x1f)) {
- encode(encoder, (1U << n) - 1, n);
- }
-}
-
-#define MELCSTATES 32 /* number of melcode states */
-
-static int zeroLUT[256]; /* table to find out number of leading zeros */
-
-static int J[MELCSTATES] = {
- 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7,
- 7, 8, 9, 10, 11, 12, 13, 14, 15
-};
-
-/* creates the bit counting look-up table. */
-static void init_zeroLUT(void)
-{
- int i, j, k, l;
-
- j = k = 1;
- l = 8;
- for (i = 0; i < 256; ++i) {
- zeroLUT[i] = l;
- --k;
- if (k == 0) {
- k = j;
- --l;
- j *= 2;
- }
- }
-}
-
-static void encoder_init_rle(CommonState *state)
-{
- state->melcstate = 0;
- state->melclen = J[0];
- state->melcorder = 1 << state->melclen;
-}
-
-#ifdef QUIC_RGB
-
-static void encode_run(Encoder *encoder, unsigned int runlen) //todo: try use end of line
-{
- int hits = 0;
-
- while (runlen >= encoder->rgb_state.melcorder) {
- hits++;
- runlen -= encoder->rgb_state.melcorder;
- if (encoder->rgb_state.melcstate < MELCSTATES) {
- encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate];
- encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen);
- }
- }
-
- /* send the required number of "hit" bits (one per occurrence
- of a run of length melcorder). This number is never too big:
- after 31 such "hit" bits, each "hit" would represent a run of 32K
- pixels.
- */
- encode_ones(encoder, hits);
-
- encode(encoder, runlen, encoder->rgb_state.melclen + 1);
-
- /* adjust melcoder parameters */
- if (encoder->rgb_state.melcstate) {
- encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate];
- encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen);
- }
-}
-
-#endif
-
-static void encode_channel_run(Encoder *encoder, Channel *channel, unsigned int runlen)
-{
- //todo: try use end of line
- int hits = 0;
-
- while (runlen >= channel->state.melcorder) {
- hits++;
- runlen -= channel->state.melcorder;
- if (channel->state.melcstate < MELCSTATES) {
- channel->state.melclen = J[++channel->state.melcstate];
- channel->state.melcorder = (1L << channel->state.melclen);
- }
- }
-
- /* send the required number of "hit" bits (one per occurrence
- of a run of length melcorder). This number is never too big:
- after 31 such "hit" bits, each "hit" would represent a run of 32K
- pixels.
- */
- encode_ones(encoder, hits);
-
- encode(encoder, runlen, channel->state.melclen + 1);
-
- /* adjust melcoder parameters */
- if (channel->state.melcstate) {
- channel->state.melclen = J[--channel->state.melcstate];
- channel->state.melcorder = (1L << channel->state.melclen);
- }
-}
-
-/* decoding routine: reads bits from the input and returns a run length. */
-/* argument is the number of pixels left to end-of-line (bound on run length) */
-
-#ifdef QUIC_RGB
-static int decode_run(Encoder *encoder)
-{
- int runlen = 0;
-
- do {
- register int temp, hits;
- temp = zeroLUT[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the
- input stream, up to 8 */
- for (hits = 1; hits <= temp; hits++) {
- runlen += encoder->rgb_state.melcorder;
-
- if (encoder->rgb_state.melcstate < MELCSTATES) {
- encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate];
- encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen);
- }
- }
- if (temp != 8) {
- decode_eatbits(encoder, temp + 1); /* consume the leading
- 0 of the remainder encoding */
- break;
- }
- decode_eatbits(encoder, 8);
- } while (1);
-
- /* read the length of the remainder */
- if (encoder->rgb_state.melclen) {
- runlen += encoder->io_word >> (32 - encoder->rgb_state.melclen);
- decode_eatbits(encoder, encoder->rgb_state.melclen);
- }
-
- /* adjust melcoder parameters */
- if (encoder->rgb_state.melcstate) {
- encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate];
- encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen);
- }
-
- return runlen;
-}
-
-#endif
-
-static int decode_channel_run(Encoder *encoder, Channel *channel)
-{
- int runlen = 0;
-
- do {
- register int temp, hits;
- temp = zeroLUT[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the
- input stream, up to 8 */
- for (hits = 1; hits <= temp; hits++) {
- runlen += channel->state.melcorder;
-
- if (channel->state.melcstate < MELCSTATES) {
- channel->state.melclen = J[++channel->state.melcstate];
- channel->state.melcorder = (1U << channel->state.melclen);
- }
- }
- if (temp != 8) {
- decode_eatbits(encoder, temp + 1); /* consume the leading
- 0 of the remainder encoding */
- break;
- }
- decode_eatbits(encoder, 8);
- } while (1);
-
- /* read the length of the remainder */
- if (channel->state.melclen) {
- runlen += encoder->io_word >> (32 - channel->state.melclen);
- decode_eatbits(encoder, channel->state.melclen);
- }
-
- /* adjust melcoder parameters */
- if (channel->state.melcstate) {
- channel->state.melclen = J[--channel->state.melcstate];
- channel->state.melcorder = (1U << channel->state.melclen);
- }
-
- return runlen;
-}
-
-#else
-
-static INLINE int find_msb(int x)
-{
- int r;
-
- __asm__("bsrl %1,%0\n\t"
- "jnz 1f\n\t"
- "movl $-1,%0\n"
- "1:" : "=r" (r) : "rm" (x));
- return r + 1;
-}
-
-static INLINE void encode_run(Encoder *encoder, unsigned int len)
-{
- int odd = len & 1U;
- int msb;
-
- len &= ~1U;
-
- while ((msb = find_msb(len))) {
- len &= ~(1 << (msb - 1));
- ASSERT(encoder->usr, msb < 32);
- encode(encoder, (1 << (msb)) - 1, msb);
- encode(encoder, 0, 1);
- }
-
- if (odd) {
- encode(encoder, 2, 2);
- } else {
- encode(encoder, 0, 1);
- }
-}
-
-static INLINE unsigned int decode_run(Encoder *encoder)
-{
- unsigned int len = 0;
- int count;
-
- do {
- count = 0;
- while (encoder->io_word & (1U << 31)) {
- decode_eatbits(encoder, 1);
- count++;
- ASSERT(encoder->usr, count < 32);
- }
- decode_eatbits(encoder, 1);
- len += (1U << count) >> 1;
- } while (count > 1);
-
- return len;
-}
-
-#endif
-#endif
-
-static INLINE void init_decode_io(Encoder *encoder)
-{
- encoder->io_next_word = encoder->io_word = *(encoder->io_now++);
- encoder->io_available_bits = 0;
-}
-
-#ifdef __GNUC__
-#define ATTR_PACKED __attribute__ ((__packed__))
-#else
-#define ATTR_PACKED
-#pragma pack(push)
-#pragma pack(1)
-#endif
-
-typedef struct ATTR_PACKED one_byte_pixel_t {
- BYTE a;
-} one_byte_t;
-
-typedef struct ATTR_PACKED three_bytes_pixel_t {
- BYTE a;
- BYTE b;
- BYTE c;
-} three_bytes_t;
-
-typedef struct ATTR_PACKED four_bytes_pixel_t {
- BYTE a;
- BYTE b;
- BYTE c;
- BYTE d;
-} four_bytes_t;
-
-typedef struct ATTR_PACKED rgb32_pixel_t {
- BYTE b;
- BYTE g;
- BYTE r;
- BYTE pad;
-} rgb32_pixel_t;
-
-typedef struct ATTR_PACKED rgb24_pixel_t {
- BYTE b;
- BYTE g;
- BYTE r;
-} rgb24_pixel_t;
-
-typedef uint16_t rgb16_pixel_t;
-
-#ifndef __GNUC__
-#pragma pack(pop)
-#endif
-
-#undef ATTR_PACKED
-
-#define ONE_BYTE
-#include "quic_tmpl.c"
-
-#define FOUR_BYTE
-#include "quic_tmpl.c"
-
-#ifdef QUIC_RGB
-
-#define QUIC_RGB32
-#include "quic_rgb_tmpl.c"
-
-#define QUIC_RGB24
-#include "quic_rgb_tmpl.c"
-
-#define QUIC_RGB16
-#include "quic_rgb_tmpl.c"
-
-#define QUIC_RGB16_TO_32
-#include "quic_rgb_tmpl.c"
-
-#else
-
-#define THREE_BYTE
-#include "quic_tmpl.c"
-
-#endif
-
-static void fill_model_structures(Encoder *encoder, FamilyStat *family_stat,
- unsigned int rep_first, unsigned int first_size,
- unsigned int rep_next, unsigned int mul_size,
- unsigned int levels, unsigned int ncounters,
- unsigned int nbuckets, unsigned int n_buckets_ptrs)
-{
- unsigned int
- bsize,
- bstart,
- bend = 0,
- repcntr,
- bnumber;
-
- COUNTER * free_counter = family_stat->counters;/* first free location in the array of
- counters */
-
- bnumber = 0;
-
- repcntr = rep_first + 1; /* first bucket */
- bsize = first_size;
-
- do { /* others */
- if (bnumber) {
- bstart = bend + 1;
- } else {
- bstart = 0;
- }
-
- if (!--repcntr) {
- repcntr = rep_next;
- bsize *= mul_size;
- }
-
- bend = bstart + bsize - 1;
- if (bend + bsize >= levels) {
- bend = levels - 1;
- }
-
- family_stat->buckets_buf[bnumber].pcounters = free_counter;
- free_counter += ncounters;
-
- ASSERT(encoder->usr, bstart < n_buckets_ptrs);
- {
- unsigned int i;
- ASSERT(encoder->usr, bend < n_buckets_ptrs);
- for (i = bstart; i <= bend; i++) {
- family_stat->buckets_ptrs[i] = family_stat->buckets_buf + bnumber;
- }
- }
-
- bnumber++;
- } while (bend < levels - 1);
-
- ASSERT(encoder->usr, free_counter - family_stat->counters == nbuckets * ncounters);
-}
-
-static void find_model_params(Encoder *encoder,
- const int bpc,
- unsigned int *ncounters,
- unsigned int *levels,
- unsigned int *n_buckets_ptrs,
- unsigned int *repfirst,
- unsigned int *firstsize,
- unsigned int *repnext,
- unsigned int *mulsize,
- unsigned int *nbuckets)
-{
- unsigned int bsize; /* bucket size */
- unsigned int bstart, bend = 0; /* bucket start and end, range : 0 to levels-1*/
- unsigned int repcntr; /* helper */
-
- ASSERT(encoder->usr, bpc <= 8 && bpc > 0);
-
-
- *ncounters = 8;
-
- *levels = 0x1 << bpc;
-
- *n_buckets_ptrs = 0; /* ==0 means: not set yet */
-
- switch (evol) { /* set repfirst firstsize repnext mulsize */
- case 1: /* buckets contain following numbers of contexts: 1 1 1 2 2 4 4 8 8 ... */
- *repfirst = 3;
- *firstsize = 1;
- *repnext = 2;
- *mulsize = 2;
- break;
- case 3: /* 1 2 4 8 16 32 64 ... */
- *repfirst = 1;
- *firstsize = 1;
- *repnext = 1;
- *mulsize = 2;
- break;
- case 5: /* 1 4 16 64 256 1024 4096 16384 65536 */
- *repfirst = 1;
- *firstsize = 1;
- *repnext = 1;
- *mulsize = 4;
- break;
- case 0: /* obsolete */
- case 2: /* obsolete */
- case 4: /* obsolete */
- encoder->usr->error(encoder->usr, "findmodelparams(): evol value obsolete!!!\n");
- default:
- encoder->usr->error(encoder->usr, "findmodelparams(): evol out of range!!!\n");
- }
-
- *nbuckets = 0;
- repcntr = *repfirst + 1; /* first bucket */
- bsize = *firstsize;
-
- do { /* other buckets */
- if (nbuckets) { /* bucket start */
- bstart = bend + 1;
- } else {
- bstart = 0;
- }
-
- if (!--repcntr) { /* bucket size */
- repcntr = *repnext;
- bsize *= *mulsize;
- }
-
- bend = bstart + bsize - 1; /* bucket end */
- if (bend + bsize >= *levels) { /* if following bucked was bigger than current one */
- bend = *levels - 1; /* concatenate them */
- }
-
- if (!*n_buckets_ptrs) { /* array size not set yet? */
- *n_buckets_ptrs = *levels;
- #if 0
- if (bend == *levels - 1) { /* this bucket is last - all in the first array */
- *n_buckets_ptrs = *levels;
- } else if (bsize >= 256) { /* this bucket is allowed to reside in the 2nd table */
- b_lo_ptrs = bstart;
- assert(bstart); /* previous bucket exists */
- }
- #endif
- }
-
- (*nbuckets)++;
- } while (bend < *levels - 1);
-}
-
-static int init_model_structures(Encoder *encoder, FamilyStat *family_stat,
- unsigned int rep_first, unsigned int first_size,
- unsigned int rep_next, unsigned int mul_size,
- unsigned int levels, unsigned int ncounters,
- unsigned int n_buckets_ptrs, unsigned int n_buckets)
-{
- family_stat->buckets_ptrs = (s_bucket **)encoder->usr->malloc(encoder->usr,
- n_buckets_ptrs *
- sizeof(s_bucket *));
- if (!family_stat->buckets_ptrs) {
- return FALSE;
- }
-
- family_stat->counters = (COUNTER *)encoder->usr->malloc(encoder->usr,
- n_buckets * sizeof(COUNTER) *
- MAXNUMCODES);
- if (!family_stat->counters) {
- goto error_1;
- }
-
- family_stat->buckets_buf = (s_bucket *)encoder->usr->malloc(encoder->usr,
- n_buckets * sizeof(s_bucket));
- if (!family_stat->buckets_buf) {
- goto error_2;
- }
-
- fill_model_structures(encoder, family_stat, rep_first, first_size, rep_next, mul_size, levels,
- ncounters, n_buckets, n_buckets_ptrs);
-
- return TRUE;
-
-error_2:
- encoder->usr->free(encoder->usr, family_stat->counters);
-
-error_1:
- encoder->usr->free(encoder->usr, family_stat->buckets_ptrs);
-
- return FALSE;
-}
-
-static void free_family_stat(QuicUsrContext *usr, FamilyStat *family_stat)
-{
- usr->free(usr, family_stat->buckets_ptrs);
- usr->free(usr, family_stat->counters);
- usr->free(usr, family_stat->buckets_buf);
-}
-
-static int init_channel(Encoder *encoder, Channel *channel)
-{
- unsigned int ncounters;
- unsigned int levels;
- unsigned int rep_first;
- unsigned int first_size;
- unsigned int rep_next;
- unsigned int mul_size;
- unsigned int n_buckets;
- unsigned int n_buckets_ptrs;
-
- channel->encoder = encoder;
- channel->state.encoder = encoder;
- channel->correlate_row_width = 0;
- channel->correlate_row = NULL;
-
- find_model_params(encoder, 8, &ncounters, &levels, &n_buckets_ptrs, &rep_first,
- &first_size, &rep_next, &mul_size, &n_buckets);
- encoder->n_buckets_8bpc = n_buckets;
- if (!init_model_structures(encoder, &channel->family_stat_8bpc, rep_first, first_size,
- rep_next, mul_size, levels, ncounters, n_buckets_ptrs,
- n_buckets)) {
- return FALSE;
- }
-
- find_model_params(encoder, 5, &ncounters, &levels, &n_buckets_ptrs, &rep_first,
- &first_size, &rep_next, &mul_size, &n_buckets);
- encoder->n_buckets_5bpc = n_buckets;
- if (!init_model_structures(encoder, &channel->family_stat_5bpc, rep_first, first_size,
- rep_next, mul_size, levels, ncounters, n_buckets_ptrs,
- n_buckets)) {
- free_family_stat(encoder->usr, &channel->family_stat_8bpc);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void destroy_channel(Channel *channel)
-{
- QuicUsrContext *usr = channel->encoder->usr;
- if (channel->correlate_row) {
- usr->free(usr, channel->correlate_row - 1);
- }
- free_family_stat(usr, &channel->family_stat_8bpc);
- free_family_stat(usr, &channel->family_stat_5bpc);
-}
-
-static int init_encoder(Encoder *encoder, QuicUsrContext *usr)
-{
- int i;
-
- encoder->usr = usr;
- encoder->rgb_state.encoder = encoder;
-
- for (i = 0; i < MAX_CHANNELS; i++) {
- if (!init_channel(encoder, &encoder->channels[i])) {
- for (--i; i >= 0; i--) {
- destroy_channel(&encoder->channels[i]);
- }
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static int encoder_reste(Encoder *encoder, uint32_t *io_ptr, uint32_t *io_ptr_end)
-{
- ASSERT(encoder->usr, ((unsigned long)io_ptr % 4) == ((unsigned long)io_ptr_end % 4));
- ASSERT(encoder->usr, io_ptr <= io_ptr_end);
-
- encoder->rgb_state.waitcnt = 0;
- encoder->rgb_state.tabrand_seed = stabrand();
- encoder->rgb_state.wmidx = DEFwmistart;
- encoder->rgb_state.wmileft = wminext;
- set_wm_trigger(&encoder->rgb_state);
-
-#if defined(RLE) && defined(RLE_STAT)
- encoder_init_rle(&encoder->rgb_state);
-#endif
-
- encoder->io_words_count = io_ptr_end - io_ptr;
- encoder->io_now = io_ptr;
- encoder->io_end = io_ptr_end;
- encoder->rows_completed = 0;
-
- return TRUE;
-}
-
-static int encoder_reste_channels(Encoder *encoder, int channels, int width, int bpc)
-{
- int i;
-
- encoder->num_channels = channels;
-
- for (i = 0; i < channels; i++) {
- s_bucket *bucket;
- s_bucket *end_bucket;
-
- if (encoder->channels[i].correlate_row_width < width) {
- encoder->channels[i].correlate_row_width = 0;
- if (encoder->channels[i].correlate_row) {
- encoder->usr->free(encoder->usr, encoder->channels[i].correlate_row - 1);
- }
- if (!(encoder->channels[i].correlate_row = (BYTE *)encoder->usr->malloc(encoder->usr,
- width + 1))) {
- return FALSE;
- }
- encoder->channels[i].correlate_row++;
- encoder->channels[i].correlate_row_width = width;
- }
-
- if (bpc == 8) {
- MEMCLEAR(encoder->channels[i].family_stat_8bpc.counters,
- encoder->n_buckets_8bpc * sizeof(COUNTER) * MAXNUMCODES);
- bucket = encoder->channels[i].family_stat_8bpc.buckets_buf;
- end_bucket = bucket + encoder->n_buckets_8bpc;
- for (; bucket < end_bucket; bucket++) {
- bucket->bestcode = /*BPC*/ 8 - 1;
- }
- encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_8bpc.buckets_ptrs;
- } else if (bpc == 5) {
- MEMCLEAR(encoder->channels[i].family_stat_5bpc.counters,
- encoder->n_buckets_5bpc * sizeof(COUNTER) * MAXNUMCODES);
- bucket = encoder->channels[i].family_stat_5bpc.buckets_buf;
- end_bucket = bucket + encoder->n_buckets_5bpc;
- for (; bucket < end_bucket; bucket++) {
- bucket->bestcode = /*BPC*/ 5 - 1;
- }
- encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_5bpc.buckets_ptrs;
- } else {
- encoder->usr->warn(encoder->usr, "%s: bad bpc %d\n", __FUNCTION__, bpc);
- return FALSE;
- }
-
- encoder->channels[i].state.waitcnt = 0;
- encoder->channels[i].state.tabrand_seed = stabrand();
- encoder->channels[i].state.wmidx = DEFwmistart;
- encoder->channels[i].state.wmileft = wminext;
- set_wm_trigger(&encoder->channels[i].state);
-
-#if defined(RLE) && defined(RLE_STAT)
- encoder_init_rle(&encoder->channels[i].state);
-#endif
- }
- return TRUE;
-}
-
-static void quic_image_params(Encoder *encoder, QuicImageType type, int *channels, int *bpc)
-{
- ASSERT(encoder->usr, channels && bpc);
- switch (type) {
- case QUIC_IMAGE_TYPE_GRAY:
- *channels = 1;
- *bpc = 8;
- break;
- case QUIC_IMAGE_TYPE_RGB16:
- *channels = 3;
- *bpc = 5;
-#ifndef QUIC_RGB
- encoder->usr->error(encoder->usr, "not implemented\n");
-#endif
- break;
- case QUIC_IMAGE_TYPE_RGB24:
- *channels = 3;
- *bpc = 8;
- break;
- case QUIC_IMAGE_TYPE_RGB32:
- *channels = 3;
- *bpc = 8;
- break;
- case QUIC_IMAGE_TYPE_RGBA:
- *channels = 4;
- *bpc = 8;
- break;
- case QUIC_IMAGE_TYPE_INVALID:
- default:
- *channels = 0;
- *bpc = 0;
- encoder->usr->error(encoder->usr, "bad image type\n");
- }
-}
-
-#define FILL_LINES() { \
- if (line == lines_end) { \
- int n = encoder->usr->more_lines(encoder->usr, &line); \
- if (n <= 0) { \
- encoder->usr->error(encoder->usr, "more lines failed\n"); \
- } \
- lines_end = line + n * stride; \
- } \
-}
-
-#define NEXT_LINE() { \
- line += stride; \
- FILL_LINES(); \
-}
-
-#define QUIC_COMPRESS_RGB(bits) \
- encoder->channels[0].correlate_row[-1] = 0; \
- encoder->channels[1].correlate_row[-1] = 0; \
- encoder->channels[2].correlate_row[-1] = 0; \
- quic_rgb##bits##_compress_row0(encoder, (rgb##bits##_pixel_t *)(line), width); \
- encoder->rows_completed++; \
- for (row = 1; row < height; row++) { \
- prev = line; \
- NEXT_LINE(); \
- encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; \
- encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; \
- encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; \
- quic_rgb##bits##_compress_row(encoder, (rgb##bits##_pixel_t *)prev, \
- (rgb##bits##_pixel_t *)line, width); \
- encoder->rows_completed++; \
- }
-
-int quic_encode(QuicContext *quic, QuicImageType type, int width, int height,
- uint8_t *line, unsigned int num_lines, int stride,
- uint32_t *io_ptr, unsigned int num_io_words)
-{
- Encoder *encoder = (Encoder *)quic;
- uint32_t *io_ptr_end = io_ptr + num_io_words;
- uint8_t *lines_end;
- int row;
- uint8_t *prev;
- int channels;
- int bpc;
-#ifndef QUIC_RGB
- int i;
-#endif
-
- ASSERT(encoder->usr, line);
- lines_end = line + num_lines * stride;
-
- quic_image_params(encoder, type, &channels, &bpc);
-
- if (!encoder_reste(encoder, io_ptr, io_ptr_end) ||
- !encoder_reste_channels(encoder, channels, width, bpc)) {
- return QUIC_ERROR;
- }
-
- encoder->io_word = 0;
- encoder->io_available_bits = 32;
-
- encode_32(encoder, QUIC_MAGIC);
- encode_32(encoder, QUIC_VERSION);
- encode_32(encoder, type);
- encode_32(encoder, width);
- encode_32(encoder, height);
-
- FILL_LINES();
-
- switch (type) {
-#ifdef QUIC_RGB
- case QUIC_IMAGE_TYPE_RGB32:
- ASSERT(encoder->usr, ABS(stride) >= width * 4);
- QUIC_COMPRESS_RGB(32);
- break;
- case QUIC_IMAGE_TYPE_RGB24:
- ASSERT(encoder->usr, ABS(stride) >= width * 3);
- QUIC_COMPRESS_RGB(24);
- break;
- case QUIC_IMAGE_TYPE_RGB16:
- ASSERT(encoder->usr, ABS(stride) >= width * 2);
- QUIC_COMPRESS_RGB(16);
- break;
- case QUIC_IMAGE_TYPE_RGBA:
- ASSERT(encoder->usr, ABS(stride) >= width * 4);
-
- encoder->channels[0].correlate_row[-1] = 0;
- encoder->channels[1].correlate_row[-1] = 0;
- encoder->channels[2].correlate_row[-1] = 0;
- quic_rgb32_compress_row0(encoder, (rgb32_pixel_t *)(line), width);
-
- encoder->channels[3].correlate_row[-1] = 0;
- quic_four_compress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(line + 3), width);
-
- encoder->rows_completed++;
-
- for (row = 1; row < height; row++) {
- prev = line;
- NEXT_LINE();
- encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
- encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];
- encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];
- quic_rgb32_compress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)line, width);
-
- encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0];
- quic_four_compress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3),
- (four_bytes_t *)(line + 3), width);
- encoder->rows_completed++;
- }
- break;
-#else
- case QUIC_IMAGE_TYPE_RGB24:
- ASSERT(encoder->usr, ABS(stride) >= width * 3);
- for (i = 0; i < 3; i++) {
- encoder->channels[i].correlate_row[-1] = 0;
- quic_three_compress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(line + i),
- width);
- }
- encoder->rows_completed++;
- for (row = 1; row < height; row++) {
- prev = line;
- NEXT_LINE();
- for (i = 0; i < 3; i++) {
- encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
- quic_three_compress_row(encoder, &encoder->channels[i], (three_bytes_t *)(prev + i),
- (three_bytes_t *)(line + i), width);
- }
- encoder->rows_completed++;
- }
- break;
- case QUIC_IMAGE_TYPE_RGB32:
- case QUIC_IMAGE_TYPE_RGBA:
- ASSERT(encoder->usr, ABS(stride) >= width * 4);
- for (i = 0; i < channels; i++) {
- encoder->channels[i].correlate_row[-1] = 0;
- quic_four_compress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(line + i),
- width);
- }
- encoder->rows_completed++;
- for (row = 1; row < height; row++) {
- prev = line;
- NEXT_LINE();
- for (i = 0; i < channels; i++) {
- encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
- quic_four_compress_row(encoder, &encoder->channels[i], (four_bytes_t *)(prev + i),
- (four_bytes_t *)(line + i), width);
- }
- encoder->rows_completed++;
- }
- break;
-#endif
- case QUIC_IMAGE_TYPE_GRAY:
- ASSERT(encoder->usr, ABS(stride) >= width);
- encoder->channels[0].correlate_row[-1] = 0;
- quic_one_compress_row0(encoder, &encoder->channels[0], (one_byte_t *)line, width);
- encoder->rows_completed++;
- for (row = 1; row < height; row++) {
- prev = line;
- NEXT_LINE();
- encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
- quic_one_compress_row(encoder, &encoder->channels[0], (one_byte_t *)prev,
- (one_byte_t *)line, width);
- encoder->rows_completed++;
- }
- break;
- case QUIC_IMAGE_TYPE_INVALID:
- default:
- encoder->usr->error(encoder->usr, "bad image type\n");
- }
-
- flush(encoder);
- encoder->io_words_count -= (encoder->io_end - encoder->io_now);
-
- return encoder->io_words_count;
-}
-
-int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words,
- QuicImageType *out_type, int *out_width, int *out_height)
-{
- Encoder *encoder = (Encoder *)quic;
- uint32_t *io_ptr_end = io_ptr + num_io_words;
- QuicImageType type;
- int width;
- int height;
- uint32_t magic;
- uint32_t version;
- int channels;
- int bpc;
-
- if (!encoder_reste(encoder, io_ptr, io_ptr_end)) {
- return QUIC_ERROR;
- }
-
- init_decode_io(encoder);
-
- magic = encoder->io_word;
- decode_eat32bits(encoder);
- if (magic != QUIC_MAGIC) {
- encoder->usr->warn(encoder->usr, "bad magic\n");
- return QUIC_ERROR;
- }
-
- version = encoder->io_word;
- decode_eat32bits(encoder);
- if (version != QUIC_VERSION) {
- encoder->usr->warn(encoder->usr, "bad version\n");
- return QUIC_ERROR;
- }
-
- type = (QuicImageType)encoder->io_word;
- decode_eat32bits(encoder);
-
- width = encoder->io_word;
- decode_eat32bits(encoder);
-
- height = encoder->io_word;
- decode_eat32bits(encoder);
-
- quic_image_params(encoder, type, &channels, &bpc);
-
- if (!encoder_reste_channels(encoder, channels, width, bpc)) {
- return QUIC_ERROR;
- }
-
- *out_width = encoder->width = width;
- *out_height = encoder->height = height;
- *out_type = encoder->type = type;
- return QUIC_OK;
-}
-
-#ifndef QUIC_RGB
-static void clear_row(four_bytes_t *row, int width)
-{
- four_bytes_t *end;
- for (end = row + width; row < end; row++) {
- row->a = 0;
- }
-}
-
-#endif
-
-#ifdef QUIC_RGB
-
-static void uncompress_rgba(Encoder *encoder, uint8_t *buf, int stride)
-{
- unsigned int row;
- uint8_t *prev;
-
- encoder->channels[0].correlate_row[-1] = 0;
- encoder->channels[1].correlate_row[-1] = 0;
- encoder->channels[2].correlate_row[-1] = 0;
- quic_rgb32_uncompress_row0(encoder, (rgb32_pixel_t *)buf, encoder->width);
-
- encoder->channels[3].correlate_row[-1] = 0;
- quic_four_uncompress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(buf + 3),
- encoder->width);
-
- encoder->rows_completed++;
- for (row = 1; row < encoder->height; row++) {
- prev = buf;
- buf += stride;
-
- encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
- encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];
- encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];
- quic_rgb32_uncompress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)buf,
- encoder->width);
-
- encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0];
- quic_four_uncompress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3),
- (four_bytes_t *)(buf + 3), encoder->width);
-
- encoder->rows_completed++;
- }
-}
-
-#endif
-
-static void uncompress_gray(Encoder *encoder, uint8_t *buf, int stride)
-{
- unsigned int row;
- uint8_t *prev;
-
- encoder->channels[0].correlate_row[-1] = 0;
- quic_one_uncompress_row0(encoder, &encoder->channels[0], (one_byte_t *)buf, encoder->width);
- encoder->rows_completed++;
- for (row = 1; row < encoder->height; row++) {
- prev = buf;
- buf += stride;
- encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
- quic_one_uncompress_row(encoder, &encoder->channels[0], (one_byte_t *)prev,
- (one_byte_t *)buf, encoder->width);
- encoder->rows_completed++;
- }
-}
-
-#define QUIC_UNCOMPRESS_RGB(prefix, type) \
- encoder->channels[0].correlate_row[-1] = 0; \
- encoder->channels[1].correlate_row[-1] = 0; \
- encoder->channels[2].correlate_row[-1] = 0; \
- quic_rgb##prefix##_uncompress_row0(encoder, (type *)buf, encoder->width); \
- encoder->rows_completed++; \
- for (row = 1; row < encoder->height; row++) { \
- prev = buf; \
- buf += stride; \
- encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; \
- encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; \
- encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; \
- quic_rgb##prefix##_uncompress_row(encoder, (type *)prev, (type *)buf, \
- encoder->width); \
- encoder->rows_completed++; \
- }
-
-int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride)
-{
- Encoder *encoder = (Encoder *)quic;
- unsigned int row;
- uint8_t *prev;
-#ifndef QUIC_RGB
- int i;
-#endif
-
- ASSERT(encoder->usr, buf);
-
- switch (encoder->type) {
-#ifdef QUIC_RGB
- case QUIC_IMAGE_TYPE_RGB32:
- case QUIC_IMAGE_TYPE_RGB24:
- if (type == QUIC_IMAGE_TYPE_RGB32) {
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4);
- QUIC_UNCOMPRESS_RGB(32, rgb32_pixel_t);
- break;
- } else if (type == QUIC_IMAGE_TYPE_RGB24) {
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 3);
- QUIC_UNCOMPRESS_RGB(24, rgb24_pixel_t);
- break;
- }
- encoder->usr->warn(encoder->usr, "unsupported output format\n");
- return QUIC_ERROR;
- case QUIC_IMAGE_TYPE_RGB16:
- if (type == QUIC_IMAGE_TYPE_RGB16) {
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 2);
- QUIC_UNCOMPRESS_RGB(16, rgb16_pixel_t);
- } else if (type == QUIC_IMAGE_TYPE_RGB32) {
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4);
- QUIC_UNCOMPRESS_RGB(16_to_32, rgb32_pixel_t);
- } else {
- encoder->usr->warn(encoder->usr, "unsupported output format\n");
- return QUIC_ERROR;
- }
-
- break;
- case QUIC_IMAGE_TYPE_RGBA:
-
- if (type != QUIC_IMAGE_TYPE_RGBA) {
- encoder->usr->warn(encoder->usr, "unsupported output format\n");
- return QUIC_ERROR;
- }
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4);
- uncompress_rgba(encoder, buf, stride);
- break;
-#else
- case QUIC_IMAGE_TYPE_RGB24:
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 3);
- for (i = 0; i < 3; i++) {
- encoder->channels[i].correlate_row[-1] = 0;
- quic_three_uncompress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(buf + i),
- encoder->width);
- }
- encoder->rows_completed++;
- for (row = 1; row < encoder->height; row++) {
- prev = buf;
- buf += stride;
- for (i = 0; i < 3; i++) {
- encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
- quic_three_uncompress_row(encoder, &encoder->channels[i],
- (three_bytes_t *)(prev + i),
- (three_bytes_t *)(buf + i),
- encoder->width);
- }
- encoder->rows_completed++;
- }
- break;
- case QUIC_IMAGE_TYPE_RGB32:
- ASSERT(encoder->usr, ABS(stride) >= encoder->width * 4);
- for (i = 0; i < 3; i++) {
- encoder->channels[i].correlate_row[-1] = 0;
- quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i),
- encoder->width);
- }
- clear_row((four_bytes_t *)(buf + 3), encoder->width);
- encoder->rows_completed++;
- for (row = 1; row < encoder->height; row++) {
- prev = buf;
- buf += stride;
- for (i = 0; i < 3; i++) {
- encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
- quic_four_uncompress_row(encoder, &encoder->channels[i],
- (four_bytes_t *)(prev + i),
- (four_bytes_t *)(buf + i),
- encoder->width);
- }
- clear_row((four_bytes_t *)(buf + 3), encoder->width);
- encoder->rows_completed++;
- }
- break;
- case QUIC_IMAGE_TYPE_RGBA:
- ASSERT(encoder->usr, ABS(stride) >= encoder->width * 4);
- for (i = 0; i < 4; i++) {
- encoder->channels[i].correlate_row[-1] = 0;
- quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i),
- encoder->width);
- }
- encoder->rows_completed++;
- for (row = 1; row < encoder->height; row++) {
- prev = buf;
- buf += stride;
- for (i = 0; i < 4; i++) {
- encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0];
- quic_four_uncompress_row(encoder, &encoder->channels[i],
- (four_bytes_t *)(prev + i),
- (four_bytes_t *)(buf + i),
- encoder->width);
- }
- encoder->rows_completed++;
- }
- break;
-#endif
- case QUIC_IMAGE_TYPE_GRAY:
-
- if (type != QUIC_IMAGE_TYPE_GRAY) {
- encoder->usr->warn(encoder->usr, "unsupported output format\n");
- return QUIC_ERROR;
- }
- ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width);
- uncompress_gray(encoder, buf, stride);
- break;
- case QUIC_IMAGE_TYPE_INVALID:
- default:
- encoder->usr->error(encoder->usr, "bad image type\n");
- }
- return QUIC_OK;
-}
-
-static int need_init = TRUE;
-
-QuicContext *quic_create(QuicUsrContext *usr)
-{
- Encoder *encoder;
-
- if (!usr || need_init || !usr->error || !usr->warn || !usr->info || !usr->malloc ||
- !usr->free || !usr->more_space || !usr->more_lines) {
- return NULL;
- }
-
- if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) {
- return NULL;
- }
-
- if (!init_encoder(encoder, usr)) {
- usr->free(usr, encoder);
- return NULL;
- }
- return (QuicContext *)encoder;
-}
-
-void quic_destroy(QuicContext *quic)
-{
- Encoder *encoder = (Encoder *)quic;
- int i;
-
- if (!quic) {
- return;
- }
-
- for (i = 0; i < MAX_CHANNELS; i++) {
- destroy_channel(&encoder->channels[i]);
- }
- encoder->usr->free(encoder->usr, encoder);
-}
-
-void quic_init(void)
-{
- if (!need_init) {
- return;
- }
- need_init = FALSE;
-
- family_init(&family_8bpc, 8, DEFmaxclen);
- family_init(&family_5bpc, 5, DEFmaxclen);
-#if defined(RLE) && defined(RLE_STAT)
- init_zeroLUT();
-#endif
-}
-
diff --git a/common/quic.h b/common/quic.h
deleted file mode 100644
index 35683d2..0000000
--- a/common/quic.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __QUIC_H
-#define __QUIC_H
-
-#include "quic_config.h"
-#include "macros.h"
-
-typedef enum {
- QUIC_IMAGE_TYPE_INVALID,
- QUIC_IMAGE_TYPE_GRAY,
- QUIC_IMAGE_TYPE_RGB16,
- QUIC_IMAGE_TYPE_RGB24,
- QUIC_IMAGE_TYPE_RGB32,
- QUIC_IMAGE_TYPE_RGBA
-} QuicImageType;
-
-#define QUIC_ERROR -1
-#define QUIC_OK 0
-
-typedef void *QuicContext;
-
-typedef struct QuicUsrContext QuicUsrContext;
-struct QuicUsrContext {
- ATTR_PRINTF(2, 3) void (*error)(QuicUsrContext *usr, const char *fmt, ...);
- ATTR_PRINTF(2, 3) void (*warn)(QuicUsrContext *usr, const char *fmt, ...);
- ATTR_PRINTF(2, 3) void (*info)(QuicUsrContext *usr, const char *fmt, ...);
- void *(*malloc)(QuicUsrContext *usr, int size);
- void (*free)(QuicUsrContext *usr, void *ptr);
- int (*more_space)(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed);
- int (*more_lines)(QuicUsrContext *usr, uint8_t **lines); // on return the last line of previous
- // lines bunch must still be valid
-};
-
-int quic_encode(QuicContext *quic, QuicImageType type, int width, int height,
- uint8_t *lines, unsigned int num_lines, int stride,
- uint32_t *io_ptr, unsigned int num_io_words);
-
-int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words,
- QuicImageType *type, int *width, int *height);
-int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride);
-
-
-QuicContext *quic_create(QuicUsrContext *usr);
-void quic_destroy(QuicContext *quic);
-
-void quic_init(void);
-
-#endif
-
diff --git a/common/quic_config.h b/common/quic_config.h
deleted file mode 100644
index 1273dbc..0000000
--- a/common/quic_config.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __QUIC_CONFIG_H
-#define __QUIC_CONFIG_H
-
-#include <spice/types.h>
-
-#ifdef __GNUC__
-
-#include <string.h>
-
-#define INLINE inline
-
-#define MEMCLEAR(ptr, size) memset(ptr, 0, size)
-
-#else
-
-#ifdef QXLDD
-#include <windef.h>
-#include "os_dep.h"
-#define INLINE _inline
-#define MEMCLEAR(ptr, size) RtlZeroMemory(ptr, size)
-#else
-#include <stddef.h>
-#include <string.h>
-
-#define INLINE inline
-#define MEMCLEAR(ptr, size) memset(ptr, 0, size)
-#endif
-
-
-#endif
-
-#endif
-
diff --git a/common/quic_family_tmpl.c b/common/quic_family_tmpl.c
deleted file mode 100644
index e07596b..0000000
--- a/common/quic_family_tmpl.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef QUIC_FAMILY_8BPC
-#undef QUIC_FAMILY_8BPC
-#define FNAME(name) name##_8bpc
-#define VNAME(name) name##_8bpc
-#define BPC 8
-#endif
-
-
-#ifdef QUIC_FAMILY_5BPC
-#undef QUIC_FAMILY_5BPC
-#define FNAME(name) name##_5bpc
-#define VNAME(name) name##_5bpc
-#define BPC 5
-#endif
-
-
-static unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l)
-{
- if (n < VNAME(family).nGRcodewords[l]) {
- return (n >> l) + 1 + l;
- } else {
- return VNAME(family).notGRcwlen[l];
- }
-}
-
-static void FNAME(golomb_coding)(const BYTE n, const unsigned int l, unsigned int * const codeword,
- unsigned int * const codewordlen)
-{
- if (n < VNAME(family).nGRcodewords[l]) {
- (*codeword) = bitat[l] | (n & bppmask[l]);
- (*codewordlen) = (n >> l) + l + 1;
- } else {
- (*codeword) = n - VNAME(family).nGRcodewords[l];
- (*codewordlen) = VNAME(family).notGRcwlen[l];
- }
-}
-
-static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned int bits,
- unsigned int * const codewordlen)
-{
- if (bits > VNAME(family).notGRprefixmask[l]) { /*GR*/
- const unsigned int zeroprefix = cnt_l_zeroes(bits); /* leading zeroes in codeword */
- const unsigned int cwlen = zeroprefix + 1 + l; /* codeword length */
- (*codewordlen) = cwlen;
- return (zeroprefix << l) | ((bits >> (32 - cwlen)) & bppmask[l]);
- } else { /* not-GR */
- const unsigned int cwlen = VNAME(family).notGRcwlen[l];
- (*codewordlen) = cwlen;
- return VNAME(family).nGRcodewords[l] + ((bits) >> (32 - cwlen) &
- bppmask[VNAME(family).notGRsuffixlen[l]]);
- }
-}
-
-/* update the bucket using just encoded curval */
-static void FNAME(update_model)(CommonState *state, s_bucket * const bucket,
- const BYTE curval, unsigned int bpp)
-{
- COUNTER * const pcounters = bucket->pcounters;
- unsigned int i;
- unsigned int bestcode;
- unsigned int bestcodelen;
- //unsigned int bpp = encoder->bpp;
-
- /* update counters, find minimum */
-
- bestcode = bpp - 1;
- bestcodelen = (pcounters[bestcode] += FNAME(golomb_code_len)(curval, bestcode));
-
- for (i = bpp - 2; i < bpp; i--) { /* NOTE: expression i<bpp for signed int i would be: i>=0 */
- const unsigned int ithcodelen = (pcounters[i] += FNAME(golomb_code_len)(curval, i));
-
- if (ithcodelen < bestcodelen) {
- bestcode = i;
- bestcodelen = ithcodelen;
- }
- }
-
- bucket->bestcode = bestcode; /* store the found minimum */
-
- if (bestcodelen > state->wm_trigger) { /* halving counters? */
- for (i = 0; i < bpp; i++) {
- pcounters[i] >>= 1;
- }
- }
-}
-
-static s_bucket *FNAME(find_bucket)(Channel *channel, const unsigned int val)
-{
- ASSERT(channel->encoder->usr, val < (0x1U << BPC));
-
- return channel->_buckets_ptrs[val];
-}
-
-#undef FNAME
-#undef VNAME
-#undef BPC
-
diff --git a/common/quic_rgb_tmpl.c b/common/quic_rgb_tmpl.c
deleted file mode 100644
index 681493a..0000000
--- a/common/quic_rgb_tmpl.c
+++ /dev/null
@@ -1,763 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef QUIC_RGB32
-#undef QUIC_RGB32
-#define PIXEL rgb32_pixel_t
-#define FNAME(name) quic_rgb32_##name
-#define golomb_coding golomb_coding_8bpc
-#define golomb_decoding golomb_decoding_8bpc
-#define update_model update_model_8bpc
-#define find_bucket find_bucket_8bpc
-#define family family_8bpc
-#define BPC 8
-#define BPC_MASK 0xffU
-#define COMPRESS_IMP
-#define SET_r(pix, val) ((pix)->r = val)
-#define GET_r(pix) ((pix)->r)
-#define SET_g(pix, val) ((pix)->g = val)
-#define GET_g(pix) ((pix)->g)
-#define SET_b(pix, val) ((pix)->b = val)
-#define GET_b(pix) ((pix)->b)
-#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0)
-#endif
-
-#ifdef QUIC_RGB24
-#undef QUIC_RGB24
-#define PIXEL rgb24_pixel_t
-#define FNAME(name) quic_rgb24_##name
-#define golomb_coding golomb_coding_8bpc
-#define golomb_decoding golomb_decoding_8bpc
-#define update_model update_model_8bpc
-#define find_bucket find_bucket_8bpc
-#define family family_8bpc
-#define BPC 8
-#define BPC_MASK 0xffU
-#define COMPRESS_IMP
-#define SET_r(pix, val) ((pix)->r = val)
-#define GET_r(pix) ((pix)->r)
-#define SET_g(pix, val) ((pix)->g = val)
-#define GET_g(pix) ((pix)->g)
-#define SET_b(pix, val) ((pix)->b = val)
-#define GET_b(pix) ((pix)->b)
-#define UNCOMPRESS_PIX_START(pix)
-#endif
-
-#ifdef QUIC_RGB16
-#undef QUIC_RGB16
-#define PIXEL rgb16_pixel_t
-#define FNAME(name) quic_rgb16_##name
-#define golomb_coding golomb_coding_5bpc
-#define golomb_decoding golomb_decoding_5bpc
-#define update_model update_model_5bpc
-#define find_bucket find_bucket_5bpc
-#define family family_5bpc
-#define BPC 5
-#define BPC_MASK 0x1fU
-#define COMPRESS_IMP
-#define SET_r(pix, val) (*(pix) = (*(pix) & ~(0x1f << 10)) | ((val) << 10))
-#define GET_r(pix) ((*(pix) >> 10) & 0x1f)
-#define SET_g(pix, val) (*(pix) = (*(pix) & ~(0x1f << 5)) | ((val) << 5))
-#define GET_g(pix) ((*(pix) >> 5) & 0x1f)
-#define SET_b(pix, val) (*(pix) = (*(pix) & ~0x1f) | (val))
-#define GET_b(pix) (*(pix) & 0x1f)
-#define UNCOMPRESS_PIX_START(pix) (*(pix) = 0)
-#endif
-
-#ifdef QUIC_RGB16_TO_32
-#undef QUIC_RGB16_TO_32
-#define PIXEL rgb32_pixel_t
-#define FNAME(name) quic_rgb16_to_32_##name
-#define golomb_coding golomb_coding_5bpc
-#define golomb_decoding golomb_decoding_5bpc
-#define update_model update_model_5bpc
-#define find_bucket find_bucket_5bpc
-#define family family_5bpc
-#define BPC 5
-#define BPC_MASK 0x1fU
-
-#define SET_r(pix, val) ((pix)->r = ((val) << 3) | (((val) & 0x1f) >> 2))
-#define GET_r(pix) ((pix)->r >> 3)
-#define SET_g(pix, val) ((pix)->g = ((val) << 3) | (((val) & 0x1f) >> 2))
-#define GET_g(pix) ((pix)->g >> 3)
-#define SET_b(pix, val) ((pix)->b = ((val) << 3) | (((val) & 0x1f) >> 2))
-#define GET_b(pix) ((pix)->b >> 3)
-#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0)
-#endif
-
-#define SAME_PIXEL(p1, p2) \
- (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \
- GET_b(p1) == GET_b(p2))
-
-
-#define _PIXEL_A(channel, curr) ((unsigned int)GET_##channel((curr) - 1))
-#define _PIXEL_B(channel, prev) ((unsigned int)GET_##channel(prev))
-#define _PIXEL_C(channel, prev) ((unsigned int)GET_##channel((prev) - 1))
-
-/* a */
-
-#define DECORELATE_0(channel, curr, bpc_mask)\
- family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)_PIXEL_A(channel, curr)) & bpc_mask]
-
-#define CORELATE_0(channel, curr, correlate, bpc_mask)\
- ((family.xlatL2U[correlate] + _PIXEL_A(channel, curr)) & bpc_mask)
-
-#ifdef PRED_1
-
-/* (a+b)/2 */
-#define DECORELATE(channel, prev, curr, bpc_mask, r) \
- r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)((_PIXEL_A(channel, curr) + \
- _PIXEL_B(channel, prev)) >> 1)) & bpc_mask]
-
-#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) \
- SET_##channel(r, ((family.xlatL2U[correlate] + \
- (int)((_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev)) >> 1)) & bpc_mask))
-#endif
-
-#ifdef PRED_2
-
-/* .75a+.75b-.5c */
-#define DECORELATE(channel, prev, curr, bpc_mask, r) { \
- int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) - \
- (int)(_PIXEL_C(channel, prev) << 1)) >> 2; \
- if (p < 0) { \
- p = 0; \
- } else if ((unsigned)p > bpc_mask) { \
- p = bpc_mask; \
- } \
- r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - p) & bpc_mask]; \
-}
-
-#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) { \
- const int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) - \
- (int)(_PIXEL_C(channel, prev) << 1) ) >> 2; \
- const unsigned int s = family.xlatL2U[correlate]; \
- if (!(p & ~bpc_mask)) { \
- SET_##channel(r, (s + (unsigned)p) & bpc_mask); \
- } else if (p < 0) { \
- SET_##channel(r, s); \
- } else { \
- SET_##channel(r, (s + bpc_mask) & bpc_mask); \
- } \
-}
-
-#endif
-
-
-#define COMPRESS_ONE_ROW0_0(channel) \
- correlate_row_##channel[0] = family.xlatU2L[GET_##channel(cur_row)]; \
- golomb_coding(correlate_row_##channel[0], find_bucket(channel_##channel, \
- correlate_row_##channel[-1])->bestcode, \
- &codeword, &codewordlen); \
- encode(encoder, codeword, codewordlen);
-
-#define COMPRESS_ONE_ROW0(channel, index) \
- correlate_row_##channel[index] = DECORELATE_0(channel, &cur_row[index], bpc_mask); \
- golomb_coding(correlate_row_##channel[index], find_bucket(channel_##channel, \
- correlate_row_##channel[index -1])->bestcode, \
- &codeword, &codewordlen); \
- encode(encoder, codeword, codewordlen);
-
-#define UPDATE_MODEL(index) \
- update_model(&encoder->rgb_state, find_bucket(channel_r, correlate_row_r[index - 1]), \
- correlate_row_r[index], bpc); \
- update_model(&encoder->rgb_state, find_bucket(channel_g, correlate_row_g[index - 1]), \
- correlate_row_g[index], bpc); \
- update_model(&encoder->rgb_state, find_bucket(channel_b, correlate_row_b[index - 1]), \
- correlate_row_b[index], bpc);
-
-
-#ifdef RLE_PRED_1
-#define RLE_PRED_1_IMP \
-if (SAME_PIXEL(&cur_row[i - 1], &prev_row[i])) { \
- if (run_index != i && SAME_PIXEL(&prev_row[i - 1], &prev_row[i]) && \
- i + 1 < end && SAME_PIXEL(&prev_row[i], &prev_row[i + 1])) { \
- goto do_run; \
- } \
-}
-#else
-#define RLE_PRED_1_IMP
-#endif
-
-#ifdef RLE_PRED_2
-#define RLE_PRED_2_IMP \
-if (SAME_PIXEL(&prev_row[i - 1], &prev_row[i])) { \
- if (run_index != i && i > 2 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2])) { \
- goto do_run; \
- } \
-}
-#else
-#define RLE_PRED_2_IMP
-#endif
-
-#ifdef RLE_PRED_3
-#define RLE_PRED_3_IMP \
-if (i > 1 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2]) && i != run_index) { \
- goto do_run; \
-}
-#else
-#define RLE_PRED_3_IMP
-#endif
-
-#ifdef COMPRESS_IMP
-
-static void FNAME(compress_row0_seg)(Encoder *encoder, int i,
- const PIXEL * const cur_row,
- const int end,
- const unsigned int waitmask,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- Channel * const channel_r = encoder->channels;
- Channel * const channel_g = channel_r + 1;
- Channel * const channel_b = channel_g + 1;
-
- BYTE * const correlate_row_r = channel_r->correlate_row;
- BYTE * const correlate_row_g = channel_g->correlate_row;
- BYTE * const correlate_row_b = channel_b->correlate_row;
- int stopidx;
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (!i) {
- unsigned int codeword, codewordlen;
-
- COMPRESS_ONE_ROW0_0(r);
- COMPRESS_ONE_ROW0_0(g);
- COMPRESS_ONE_ROW0_0(b);
-
- if (encoder->rgb_state.waitcnt) {
- encoder->rgb_state.waitcnt--;
- } else {
- encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- UPDATE_MODEL(0);
- }
- stopidx = ++i + encoder->rgb_state.waitcnt;
- } else {
- stopidx = i + encoder->rgb_state.waitcnt;
- }
-
- while (stopidx < end) {
- for (; i <= stopidx; i++) {
- unsigned int codeword, codewordlen;
- COMPRESS_ONE_ROW0(r, i);
- COMPRESS_ONE_ROW0(g, i);
- COMPRESS_ONE_ROW0(b, i);
- }
-
- UPDATE_MODEL(stopidx);
- stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codeword, codewordlen;
-
- COMPRESS_ONE_ROW0(r, i);
- COMPRESS_ONE_ROW0(g, i);
- COMPRESS_ONE_ROW0(b, i);
- }
- encoder->rgb_state.waitcnt = stopidx - end;
-}
-
-static void FNAME(compress_row0)(Encoder *encoder, const PIXEL *cur_row,
- unsigned int width)
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- int pos = 0;
-
- while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
- if (encoder->rgb_state.wmileft) {
- FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + encoder->rgb_state.wmileft,
- bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
- width -= encoder->rgb_state.wmileft;
- pos += encoder->rgb_state.wmileft;
- }
-
- encoder->rgb_state.wmidx++;
- set_wm_trigger(&encoder->rgb_state);
- encoder->rgb_state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + width,
- bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
- if (wmimax > (int)encoder->rgb_state.wmidx) {
- encoder->rgb_state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
- ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-#define COMPRESS_ONE_0(channel) \
- correlate_row_##channel[0] = family.xlatU2L[(unsigned)((int)GET_##channel(cur_row) - \
- (int)GET_##channel(prev_row) ) & bpc_mask]; \
- golomb_coding(correlate_row_##channel[0], \
- find_bucket(channel_##channel, correlate_row_##channel[-1])->bestcode, \
- &codeword, &codewordlen); \
- encode(encoder, codeword, codewordlen);
-
-#define COMPRESS_ONE(channel, index) \
- DECORELATE(channel, &prev_row[index], &cur_row[index],bpc_mask, \
- correlate_row_##channel[index]); \
- golomb_coding(correlate_row_##channel[index], \
- find_bucket(channel_##channel, correlate_row_##channel[index - 1])->bestcode, \
- &codeword, &codewordlen); \
- encode(encoder, codeword, codewordlen);
-
-static void FNAME(compress_row_seg)(Encoder *encoder, int i,
- const PIXEL * const prev_row,
- const PIXEL * const cur_row,
- const int end,
- const unsigned int waitmask,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- Channel * const channel_r = encoder->channels;
- Channel * const channel_g = channel_r + 1;
- Channel * const channel_b = channel_g + 1;
-
- BYTE * const correlate_row_r = channel_r->correlate_row;
- BYTE * const correlate_row_g = channel_g->correlate_row;
- BYTE * const correlate_row_b = channel_b->correlate_row;
- int stopidx;
-#ifdef RLE
- int run_index = 0;
- int run_size;
-#endif
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (!i) {
- unsigned int codeword, codewordlen;
-
- COMPRESS_ONE_0(r);
- COMPRESS_ONE_0(g);
- COMPRESS_ONE_0(b);
-
- if (encoder->rgb_state.waitcnt) {
- encoder->rgb_state.waitcnt--;
- } else {
- encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- UPDATE_MODEL(0);
- }
- stopidx = ++i + encoder->rgb_state.waitcnt;
- } else {
- stopidx = i + encoder->rgb_state.waitcnt;
- }
- for (;;) {
- while (stopidx < end) {
- for (; i <= stopidx; i++) {
- unsigned int codeword, codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- COMPRESS_ONE(r, i);
- COMPRESS_ONE(g, i);
- COMPRESS_ONE(b, i);
- }
-
- UPDATE_MODEL(stopidx);
- stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codeword, codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- COMPRESS_ONE(r, i);
- COMPRESS_ONE(g, i);
- COMPRESS_ONE(b, i);
- }
- encoder->rgb_state.waitcnt = stopidx - end;
-
- return;
-
-#ifdef RLE
-do_run:
- run_index = i;
- encoder->rgb_state.waitcnt = stopidx - i;
- run_size = 0;
-
- while (SAME_PIXEL(&cur_row[i], &cur_row[i - 1])) {
- run_size++;
- if (++i == end) {
- encode_run(encoder, run_size);
- return;
- }
- }
- encode_run(encoder, run_size);
- stopidx = i + encoder->rgb_state.waitcnt;
-#endif
- }
-}
-
-static void FNAME(compress_row)(Encoder *encoder,
- const PIXEL * const prev_row,
- const PIXEL * const cur_row,
- unsigned int width)
-
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- unsigned int pos = 0;
-
- while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
- if (encoder->rgb_state.wmileft) {
- FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row,
- pos + encoder->rgb_state.wmileft,
- bppmask[encoder->rgb_state.wmidx],
- bpc, bpc_mask);
- width -= encoder->rgb_state.wmileft;
- pos += encoder->rgb_state.wmileft;
- }
-
- encoder->rgb_state.wmidx++;
- set_wm_trigger(&encoder->rgb_state);
- encoder->rgb_state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row, pos + width,
- bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
- if (wmimax > (int)encoder->rgb_state.wmidx) {
- encoder->rgb_state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
- ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-#endif
-
-#define UNCOMPRESS_ONE_ROW0_0(channel) \
- correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \
- correlate_row_##channel[-1])->bestcode, \
- encoder->io_word, &codewordlen); \
- SET_##channel(&cur_row[0], (BYTE)family.xlatL2U[correlate_row_##channel[0]]); \
- decode_eatbits(encoder, codewordlen);
-
-#define UNCOMPRESS_ONE_ROW0(channel) \
- correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \
- correlate_row_##channel[i - 1])->bestcode, \
- encoder->io_word, \
- &codewordlen); \
- SET_##channel(&cur_row[i], CORELATE_0(channel, &cur_row[i], correlate_row_##channel[i], \
- bpc_mask)); \
- decode_eatbits(encoder, codewordlen);
-
-static void FNAME(uncompress_row0_seg)(Encoder *encoder, int i,
- PIXEL * const cur_row,
- const int end,
- const unsigned int waitmask,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- Channel * const channel_r = encoder->channels;
- Channel * const channel_g = channel_r + 1;
- Channel * const channel_b = channel_g + 1;
-
- BYTE * const correlate_row_r = channel_r->correlate_row;
- BYTE * const correlate_row_g = channel_g->correlate_row;
- BYTE * const correlate_row_b = channel_b->correlate_row;
- int stopidx;
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (!i) {
- unsigned int codewordlen;
-
- UNCOMPRESS_PIX_START(&cur_row[i]);
- UNCOMPRESS_ONE_ROW0_0(r);
- UNCOMPRESS_ONE_ROW0_0(g);
- UNCOMPRESS_ONE_ROW0_0(b);
-
- if (encoder->rgb_state.waitcnt) {
- --encoder->rgb_state.waitcnt;
- } else {
- encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- UPDATE_MODEL(0);
- }
- stopidx = ++i + encoder->rgb_state.waitcnt;
- } else {
- stopidx = i + encoder->rgb_state.waitcnt;
- }
-
- while (stopidx < end) {
- for (; i <= stopidx; i++) {
- unsigned int codewordlen;
-
- UNCOMPRESS_PIX_START(&cur_row[i]);
- UNCOMPRESS_ONE_ROW0(r);
- UNCOMPRESS_ONE_ROW0(g);
- UNCOMPRESS_ONE_ROW0(b);
- }
- UPDATE_MODEL(stopidx);
- stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codewordlen;
-
- UNCOMPRESS_PIX_START(&cur_row[i]);
- UNCOMPRESS_ONE_ROW0(r);
- UNCOMPRESS_ONE_ROW0(g);
- UNCOMPRESS_ONE_ROW0(b);
- }
- encoder->rgb_state.waitcnt = stopidx - end;
-}
-
-static void FNAME(uncompress_row0)(Encoder *encoder,
- PIXEL * const cur_row,
- unsigned int width)
-
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- unsigned int pos = 0;
-
- while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
- if (encoder->rgb_state.wmileft) {
- FNAME(uncompress_row0_seg)(encoder, pos, cur_row,
- pos + encoder->rgb_state.wmileft,
- bppmask[encoder->rgb_state.wmidx],
- bpc, bpc_mask);
- pos += encoder->rgb_state.wmileft;
- width -= encoder->rgb_state.wmileft;
- }
-
- encoder->rgb_state.wmidx++;
- set_wm_trigger(&encoder->rgb_state);
- encoder->rgb_state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(uncompress_row0_seg)(encoder, pos, cur_row, pos + width,
- bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask);
- if (wmimax > (int)encoder->rgb_state.wmidx) {
- encoder->rgb_state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
- ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-#define UNCOMPRESS_ONE_0(channel) \
- correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \
- correlate_row_##channel[-1])->bestcode, \
- encoder->io_word, &codewordlen); \
- SET_##channel(&cur_row[0], (family.xlatL2U[correlate_row_##channel[0]] + \
- GET_##channel(prev_row)) & bpc_mask); \
- decode_eatbits(encoder, codewordlen);
-
-#define UNCOMPRESS_ONE(channel) \
- correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \
- correlate_row_##channel[i - 1])->bestcode, \
- encoder->io_word, \
- &codewordlen); \
- CORELATE(channel, &prev_row[i], &cur_row[i], correlate_row_##channel[i], bpc_mask, \
- &cur_row[i]); \
- decode_eatbits(encoder, codewordlen);
-
-static void FNAME(uncompress_row_seg)(Encoder *encoder,
- const PIXEL * const prev_row,
- PIXEL * const cur_row,
- int i,
- const int end,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- Channel * const channel_r = encoder->channels;
- Channel * const channel_g = channel_r + 1;
- Channel * const channel_b = channel_g + 1;
-
- BYTE * const correlate_row_r = channel_r->correlate_row;
- BYTE * const correlate_row_g = channel_g->correlate_row;
- BYTE * const correlate_row_b = channel_b->correlate_row;
- const unsigned int waitmask = bppmask[encoder->rgb_state.wmidx];
- int stopidx;
-#ifdef RLE
- int run_index = 0;
- int run_end;
-#endif
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (!i) {
- unsigned int codewordlen;
-
- UNCOMPRESS_PIX_START(&cur_row[i]);
- UNCOMPRESS_ONE_0(r);
- UNCOMPRESS_ONE_0(g);
- UNCOMPRESS_ONE_0(b);
-
- if (encoder->rgb_state.waitcnt) {
- --encoder->rgb_state.waitcnt;
- } else {
- encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- UPDATE_MODEL(0);
- }
- stopidx = ++i + encoder->rgb_state.waitcnt;
- } else {
- stopidx = i + encoder->rgb_state.waitcnt;
- }
- for (;;) {
- while (stopidx < end) {
- for (; i <= stopidx; i++) {
- unsigned int codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- UNCOMPRESS_PIX_START(&cur_row[i]);
- UNCOMPRESS_ONE(r);
- UNCOMPRESS_ONE(g);
- UNCOMPRESS_ONE(b);
- }
-
- UPDATE_MODEL(stopidx);
-
- stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- UNCOMPRESS_PIX_START(&cur_row[i]);
- UNCOMPRESS_ONE(r);
- UNCOMPRESS_ONE(g);
- UNCOMPRESS_ONE(b);
- }
-
- encoder->rgb_state.waitcnt = stopidx - end;
-
- return;
-
-#ifdef RLE
-do_run:
- encoder->rgb_state.waitcnt = stopidx - i;
- run_index = i;
- run_end = i + decode_run(encoder);
-
- for (; i < run_end; i++) {
- UNCOMPRESS_PIX_START(&cur_row[i]);
- SET_r(&cur_row[i], GET_r(&cur_row[i - 1]));
- SET_g(&cur_row[i], GET_g(&cur_row[i - 1]));
- SET_b(&cur_row[i], GET_b(&cur_row[i - 1]));
- }
-
- if (i == end) {
- return;
- }
-
- stopidx = i + encoder->rgb_state.waitcnt;
-#endif
- }
-}
-
-static void FNAME(uncompress_row)(Encoder *encoder,
- const PIXEL * const prev_row,
- PIXEL * const cur_row,
- unsigned int width)
-
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- unsigned int pos = 0;
-
- while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) {
- if (encoder->rgb_state.wmileft) {
- FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos,
- pos + encoder->rgb_state.wmileft, bpc, bpc_mask);
- pos += encoder->rgb_state.wmileft;
- width -= encoder->rgb_state.wmileft;
- }
-
- encoder->rgb_state.wmidx++;
- set_wm_trigger(&encoder->rgb_state);
- encoder->rgb_state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos,
- pos + width, bpc, bpc_mask);
- if (wmimax > (int)encoder->rgb_state.wmidx) {
- encoder->rgb_state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax);
- ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-#undef PIXEL
-#undef FNAME
-#undef _PIXEL_A
-#undef _PIXEL_B
-#undef _PIXEL_C
-#undef SAME_PIXEL
-#undef RLE_PRED_1_IMP
-#undef RLE_PRED_2_IMP
-#undef RLE_PRED_3_IMP
-#undef UPDATE_MODEL
-#undef DECORELATE_0
-#undef DECORELATE
-#undef COMPRESS_ONE_ROW0_0
-#undef COMPRESS_ONE_ROW0
-#undef COMPRESS_ONE_0
-#undef COMPRESS_ONE
-#undef CORELATE_0
-#undef CORELATE
-#undef UNCOMPRESS_ONE_ROW0_0
-#undef UNCOMPRESS_ONE_ROW0
-#undef UNCOMPRESS_ONE_0
-#undef UNCOMPRESS_ONE
-#undef golomb_coding
-#undef golomb_decoding
-#undef update_model
-#undef find_bucket
-#undef family
-#undef BPC
-#undef BPC_MASK
-#undef COMPRESS_IMP
-#undef SET_r
-#undef GET_r
-#undef SET_g
-#undef GET_g
-#undef SET_b
-#undef GET_b
-#undef UNCOMPRESS_PIX_START
-
diff --git a/common/quic_tmpl.c b/common/quic_tmpl.c
deleted file mode 100644
index 47a6a23..0000000
--- a/common/quic_tmpl.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef ONE_BYTE
-#undef ONE_BYTE
-#define FNAME(name) quic_one_##name
-#define PIXEL one_byte_t
-#endif
-
-#ifdef THREE_BYTE
-#undef THREE_BYTE
-#define FNAME(name) quic_three_##name
-#define PIXEL three_bytes_t
-#endif
-
-#ifdef FOUR_BYTE
-#undef FOUR_BYTE
-#define FNAME(name) quic_four_##name
-#define PIXEL four_bytes_t
-#endif
-
-#define golomb_coding golomb_coding_8bpc
-#define golomb_decoding golomb_decoding_8bpc
-#define update_model update_model_8bpc
-#define find_bucket find_bucket_8bpc
-#define family family_8bpc
-
-#define BPC 8
-#define BPC_MASK 0xffU
-
-#define _PIXEL_A ((unsigned int)curr[-1].a)
-#define _PIXEL_B ((unsigned int)prev[0].a)
-#define _PIXEL_C ((unsigned int)prev[-1].a)
-
-#ifdef RLE_PRED_1
-#define RLE_PRED_1_IMP \
-if (cur_row[i - 1].a == prev_row[i].a) { \
- if (run_index != i && prev_row[i - 1].a == prev_row[i].a && \
- i + 1 < end && prev_row[i].a == prev_row[i + 1].a) { \
- goto do_run; \
- } \
-}
-#else
-#define RLE_PRED_1_IMP
-#endif
-
-#ifdef RLE_PRED_2
-#define RLE_PRED_2_IMP \
-if (prev_row[i - 1].a == prev_row[i].a) { \
- if (run_index != i && i > 2 && cur_row[i - 1].a == cur_row[i - 2].a) { \
- goto do_run; \
- } \
-}
-#else
-#define RLE_PRED_2_IMP
-#endif
-
-#ifdef RLE_PRED_3
-#define RLE_PRED_3_IMP \
-if (i > 1 && cur_row[i - 1].a == cur_row[i - 2].a && i != run_index) { \
- goto do_run; \
-}
-#else
-#define RLE_PRED_3_IMP
-#endif
-
-/* a */
-static INLINE BYTE FNAME(decorelate_0)(const PIXEL * const curr, const unsigned int bpc_mask)
-{
- return family.xlatU2L[(unsigned)((int)curr[0].a - (int)_PIXEL_A) & bpc_mask];
-}
-
-static INLINE void FNAME(corelate_0)(PIXEL *curr, const BYTE corelate,
- const unsigned int bpc_mask)
-{
- curr->a = (family.xlatL2U[corelate] + _PIXEL_A) & bpc_mask;
-}
-
-#ifdef PRED_1
-
-/* (a+b)/2 */
-static INLINE BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr,
- const unsigned int bpc_mask)
-{
- return family.xlatU2L[(unsigned)((int)curr->a - (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask];
-}
-
-
-static INLINE void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate,
- const unsigned int bpc_mask)
-{
- curr->a = (family.xlatL2U[corelate] + (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask;
-}
-
-#endif
-
-#ifdef PRED_2
-
-/* .75a+.75b-.5c */
-static INLINE BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr,
- const unsigned int bpc_mask)
-{
- int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2;
-
- if (p < 0) {
- p = 0;
- } else if ((unsigned)p > bpc_mask) {
- p = bpc_mask;
- }
-
- {
- return family.xlatU2L[(unsigned)((int)curr->a - p) & bpc_mask];
- }
-}
-
-static INLINE void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate,
- const unsigned int bpc_mask)
-{
- const int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2;
- const unsigned int s = family.xlatL2U[corelate];
-
- if (!(p & ~bpc_mask)) {
- curr->a = (s + (unsigned)p) & bpc_mask;
- } else if (p < 0) {
- curr->a = s;
- } else {
- curr->a = (s + bpc_mask) & bpc_mask;
- }
-}
-
-#endif
-
-static void FNAME(compress_row0_seg)(Encoder *encoder, Channel *channel, int i,
- const PIXEL * const cur_row,
- const int end,
- const unsigned int waitmask,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- BYTE * const decorelate_drow = channel->correlate_row;
- int stopidx;
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (i == 0) {
- unsigned int codeword, codewordlen;
-
- decorelate_drow[0] = family.xlatU2L[cur_row->a];
- golomb_coding(decorelate_drow[0], find_bucket(channel, decorelate_drow[-1])->bestcode,
- &codeword, &codewordlen);
- encode(encoder, codeword, codewordlen);
-
- if (channel->state.waitcnt) {
- channel->state.waitcnt--;
- } else {
- channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
- update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]),
- decorelate_drow[i], bpc);
- }
- stopidx = ++i + channel->state.waitcnt;
- } else {
- stopidx = i + channel->state.waitcnt;
- }
-
- while (stopidx < end) {
- for (; i <= stopidx; i++) {
- unsigned int codeword, codewordlen;
- decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask);
- golomb_coding(decorelate_drow[i],
- find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword,
- &codewordlen);
- encode(encoder, codeword, codewordlen);
- }
-
- update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]),
- decorelate_drow[stopidx], bpc);
- stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codeword, codewordlen;
- decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask);
- golomb_coding(decorelate_drow[i], find_bucket(channel, decorelate_drow[i - 1])->bestcode,
- &codeword, &codewordlen);
- encode(encoder, codeword, codewordlen);
- }
- channel->state.waitcnt = stopidx - end;
-}
-
-static void FNAME(compress_row0)(Encoder *encoder, Channel *channel, const PIXEL *cur_row,
- unsigned int width)
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- int pos = 0;
-
- while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
- if (channel->state.wmileft) {
- FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + channel->state.wmileft,
- bppmask[channel->state.wmidx], bpc, bpc_mask);
- width -= channel->state.wmileft;
- pos += channel->state.wmileft;
- }
-
- channel->state.wmidx++;
- set_wm_trigger(&channel->state);
- channel->state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + width,
- bppmask[channel->state.wmidx], bpc, bpc_mask);
- if (wmimax > (int)channel->state.wmidx) {
- channel->state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
- ASSERT(encoder->usr, channel->state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-static void FNAME(compress_row_seg)(Encoder *encoder, Channel *channel, int i,
- const PIXEL * const prev_row,
- const PIXEL * const cur_row,
- const int end,
- const unsigned int waitmask,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- BYTE * const decorelate_drow = channel->correlate_row;
- int stopidx;
-#ifdef RLE
- int run_index = 0;
- int run_size;
-#endif
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (!i) {
- unsigned int codeword, codewordlen;
-
- decorelate_drow[0] = family.xlatU2L[(unsigned)((int)cur_row->a -
- (int)prev_row->a) & bpc_mask];
-
- golomb_coding(decorelate_drow[0],
- find_bucket(channel, decorelate_drow[-1])->bestcode,
- &codeword,
- &codewordlen);
- encode(encoder, codeword, codewordlen);
-
- if (channel->state.waitcnt) {
- channel->state.waitcnt--;
- } else {
- channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
- update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]),
- decorelate_drow[0], bpc);
- }
- stopidx = ++i + channel->state.waitcnt;
- } else {
- stopidx = i + channel->state.waitcnt;
- }
- for (;;) {
- while (stopidx < end) {
- for (; i <= stopidx; i++) {
- unsigned int codeword, codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask);
- golomb_coding(decorelate_drow[i],
- find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword,
- &codewordlen);
- encode(encoder, codeword, codewordlen);
- }
-
- update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]),
- decorelate_drow[stopidx], bpc);
- stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codeword, codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask);
- golomb_coding(decorelate_drow[i], find_bucket(channel,
- decorelate_drow[i - 1])->bestcode,
- &codeword, &codewordlen);
- encode(encoder, codeword, codewordlen);
- }
- channel->state.waitcnt = stopidx - end;
-
- return;
-
-#ifdef RLE
-do_run:
- run_index = i;
- channel->state.waitcnt = stopidx - i;
- run_size = 0;
-
- while (cur_row[i].a == cur_row[i - 1].a) {
- run_size++;
- if (++i == end) {
-#ifdef RLE_STAT
- encode_channel_run(encoder, channel, run_size);
-#else
- encode_run(encoder, run_size);
-#endif
- return;
- }
- }
-#ifdef RLE_STAT
- encode_channel_run(encoder, channel, run_size);
-#else
- encode_run(encoder, run_size);
-#endif
- stopidx = i + channel->state.waitcnt;
-#endif
- }
-}
-
-static void FNAME(compress_row)(Encoder *encoder, Channel *channel,
- const PIXEL * const prev_row,
- const PIXEL * const cur_row,
- unsigned int width)
-
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- unsigned int pos = 0;
-
- while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
- if (channel->state.wmileft) {
- FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row,
- pos + channel->state.wmileft, bppmask[channel->state.wmidx],
- bpc, bpc_mask);
- width -= channel->state.wmileft;
- pos += channel->state.wmileft;
- }
-
- channel->state.wmidx++;
- set_wm_trigger(&channel->state);
- channel->state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row, pos + width,
- bppmask[channel->state.wmidx], bpc, bpc_mask);
- if (wmimax > (int)channel->state.wmidx) {
- channel->state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
- ASSERT(encoder->usr, channel->state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-static void FNAME(uncompress_row0_seg)(Encoder *encoder, Channel *channel, int i,
- BYTE * const correlate_row,
- PIXEL * const cur_row,
- const int end,
- const unsigned int waitmask,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- int stopidx;
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (i == 0) {
- unsigned int codewordlen;
-
- correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel,
- correlate_row[-1])->bestcode,
- encoder->io_word, &codewordlen);
- cur_row[0].a = (BYTE)family.xlatL2U[correlate_row[0]];
- decode_eatbits(encoder, codewordlen);
-
- if (channel->state.waitcnt) {
- --channel->state.waitcnt;
- } else {
- channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
- update_model(&channel->state, find_bucket(channel, correlate_row[-1]),
- correlate_row[0], bpc);
- }
- stopidx = ++i + channel->state.waitcnt;
- } else {
- stopidx = i + channel->state.waitcnt;
- }
-
- while (stopidx < end) {
- struct s_bucket * pbucket = NULL;
-
- for (; i <= stopidx; i++) {
- unsigned int codewordlen;
-
- pbucket = find_bucket(channel, correlate_row[i - 1]);
- correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word,
- &codewordlen);
- FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask);
- decode_eatbits(encoder, codewordlen);
- }
-
- update_model(&channel->state, pbucket, correlate_row[stopidx], bpc);
-
- stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codewordlen;
-
- correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel,
- correlate_row[i - 1])->bestcode,
- encoder->io_word, &codewordlen);
- FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask);
- decode_eatbits(encoder, codewordlen);
- }
- channel->state.waitcnt = stopidx - end;
-}
-
-static void FNAME(uncompress_row0)(Encoder *encoder, Channel *channel,
- PIXEL * const cur_row,
- unsigned int width)
-
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- BYTE * const correlate_row = channel->correlate_row;
- unsigned int pos = 0;
-
- while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
- if (channel->state.wmileft) {
- FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row,
- pos + channel->state.wmileft, bppmask[channel->state.wmidx],
- bpc, bpc_mask);
- pos += channel->state.wmileft;
- width -= channel->state.wmileft;
- }
-
- channel->state.wmidx++;
- set_wm_trigger(&channel->state);
- channel->state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row, pos + width,
- bppmask[channel->state.wmidx], bpc, bpc_mask);
- if (wmimax > (int)channel->state.wmidx) {
- channel->state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
- ASSERT(encoder->usr, channel->state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-static void FNAME(uncompress_row_seg)(Encoder *encoder, Channel *channel,
- BYTE *correlate_row,
- const PIXEL * const prev_row,
- PIXEL * const cur_row,
- int i,
- const int end,
- const unsigned int bpc,
- const unsigned int bpc_mask)
-{
- const unsigned int waitmask = bppmask[channel->state.wmidx];
- int stopidx;
-#ifdef RLE
- int run_index = 0;
- int run_end;
-#endif
-
- ASSERT(encoder->usr, end - i > 0);
-
- if (i == 0) {
- unsigned int codewordlen;
-
- correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel, correlate_row[-1])->bestcode,
- encoder->io_word, &codewordlen);
- cur_row[0].a = (family.xlatL2U[correlate_row[0]] + prev_row[0].a) & bpc_mask;
- decode_eatbits(encoder, codewordlen);
-
- if (channel->state.waitcnt) {
- --channel->state.waitcnt;
- } else {
- channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask);
- update_model(&channel->state, find_bucket(channel, correlate_row[-1]),
- correlate_row[0], bpc);
- }
- stopidx = ++i + channel->state.waitcnt;
- } else {
- stopidx = i + channel->state.waitcnt;
- }
- for (;;) {
- while (stopidx < end) {
- struct s_bucket * pbucket = NULL;
-
- for (; i <= stopidx; i++) {
- unsigned int codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- pbucket = find_bucket(channel, correlate_row[i - 1]);
- correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word,
- &codewordlen);
- FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask);
- decode_eatbits(encoder, codewordlen);
- }
-
- update_model(&channel->state, pbucket, correlate_row[stopidx], bpc);
-
- stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask);
- }
-
- for (; i < end; i++) {
- unsigned int codewordlen;
-#ifdef RLE
- RLE_PRED_1_IMP;
- RLE_PRED_2_IMP;
- RLE_PRED_3_IMP;
-#endif
- correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel,
- correlate_row[i - 1])->bestcode,
- encoder->io_word, &codewordlen);
- FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask);
- decode_eatbits(encoder, codewordlen);
- }
-
- channel->state.waitcnt = stopidx - end;
-
- return;
-
-#ifdef RLE
-do_run:
- channel->state.waitcnt = stopidx - i;
- run_index = i;
-#ifdef RLE_STAT
- run_end = i + decode_channel_run(encoder, channel);
-#else
- run_end = i + decode_run(encoder);
-#endif
-
- for (; i < run_end; i++) {
- cur_row[i].a = cur_row[i - 1].a;
- }
-
- if (i == end) {
- return;
- }
-
- stopidx = i + channel->state.waitcnt;
-#endif
- }
-}
-
-static void FNAME(uncompress_row)(Encoder *encoder, Channel *channel,
- const PIXEL * const prev_row,
- PIXEL * const cur_row,
- unsigned int width)
-
-{
- const unsigned int bpc = BPC;
- const unsigned int bpc_mask = BPC_MASK;
- BYTE * const correlate_row = channel->correlate_row;
- unsigned int pos = 0;
-
- while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) {
- if (channel->state.wmileft) {
- FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos,
- pos + channel->state.wmileft, bpc, bpc_mask);
- pos += channel->state.wmileft;
- width -= channel->state.wmileft;
- }
-
- channel->state.wmidx++;
- set_wm_trigger(&channel->state);
- channel->state.wmileft = wminext;
- }
-
- if (width) {
- FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos,
- pos + width, bpc, bpc_mask);
- if (wmimax > (int)channel->state.wmidx) {
- channel->state.wmileft -= width;
- }
- }
-
- ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax);
- ASSERT(encoder->usr, channel->state.wmidx <= 32);
- ASSERT(encoder->usr, wminext > 0);
-}
-
-#undef PIXEL
-#undef FNAME
-#undef _PIXEL_A
-#undef _PIXEL_B
-#undef _PIXEL_C
-#undef RLE_PRED_1_IMP
-#undef RLE_PRED_2_IMP
-#undef RLE_PRED_3_IMP
-#undef golomb_coding
-#undef golomb_deoding
-#undef update_model
-#undef find_bucket
-#undef family
-#undef BPC
-#undef BPC_MASK
-
diff --git a/common/rect.h b/common/rect.h
deleted file mode 100644
index cdd4335..0000000
--- a/common/rect.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_RECT
-#define _H_RECT
-
-#include "draw.h"
-#include <spice/macros.h>
-
-static inline void rect_sect(SpiceRect* r, const SpiceRect* bounds)
-{
- r->left = MAX(r->left, bounds->left);
- r->right = MIN(r->right, bounds->right);
- r->right = MAX(r->left, r->right);
-
- r->top = MAX(r->top, bounds->top);
- r->bottom = MIN(r->bottom, bounds->bottom);
- r->bottom = MAX(r->top, r->bottom);
-}
-
-static inline void rect_offset(SpiceRect* r, int dx, int dy)
-{
- r->left += dx;
- r->right += dx;
- r->top += dy;
- r->bottom += dy;
-}
-
-static inline int rect_is_empty(const SpiceRect* r)
-{
- return r->top == r->bottom || r->left == r->right;
-}
-
-static inline int rect_intersects(const SpiceRect* r1, const SpiceRect* r2)
-{
- return r1->left < r2->right && r1->right > r2->left &&
- r1->top < r2->bottom && r1->bottom > r2->top;
-}
-
-static inline int rect_is_equal(const SpiceRect *r1, const SpiceRect *r2)
-{
- return r1->top == r2->top && r1->left == r2->left &&
- r1->bottom == r2->bottom && r1->right == r2->right;
-}
-
-static inline void rect_union(SpiceRect *dest, const SpiceRect *r)
-{
- dest->top = MIN(dest->top, r->top);
- dest->left = MIN(dest->left, r->left);
- dest->bottom = MAX(dest->bottom, r->bottom);
- dest->right = MAX(dest->right, r->right);
-}
-
-static inline int rect_is_same_size(const SpiceRect *r1, const SpiceRect *r2)
-{
- return r1->right - r1->left == r2->right - r2->left &&
- r1->bottom - r1->top == r2->bottom - r2->top;
-}
-
-#ifdef __cplusplus
-
-static inline void rect_sect(SpiceRect& r, const SpiceRect& bounds)
-{
- rect_sect(&r, &bounds);
-}
-
-static inline void rect_offset(SpiceRect& r, int dx, int dy)
-{
- rect_offset(&r, dx, dy);
-}
-
-static inline int rect_is_empty(const SpiceRect& r)
-{
- return rect_is_empty(&r);
-}
-
-static inline int rect_intersects(const SpiceRect& r1, const SpiceRect& r2)
-{
- return rect_intersects(&r1, &r2);
-}
-
-static inline int rect_is_equal(const SpiceRect& r1, const SpiceRect& r2)
-{
- return rect_is_equal(&r1, &r2);
-}
-
-static inline void rect_union(SpiceRect& dest, const SpiceRect& r)
-{
- rect_union(&dest, &r);
-}
-
-static inline int rect_is_same_size(const SpiceRect& r1, const SpiceRect& r2)
-{
- return rect_is_same_size(&r1, &r2);
-}
-
-#endif
-
-#endif
-
diff --git a/common/region.c b/common/region.c
deleted file mode 100644
index 3f51f7b..0000000
--- a/common/region.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <spice/macros.h>
-
-#include "region.h"
-#include "rect.h"
-#include "mem.h"
-
-#define ASSERT(x) if (!(x)) { \
- printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \
- abort(); \
-}
-
-/* true iff two Boxes overlap */
-#define EXTENTCHECK(r1, r2) \
- (!( ((r1)->x2 <= (r2)->x1) || \
- ((r1)->x1 >= (r2)->x2) || \
- ((r1)->y2 <= (r2)->y1) || \
- ((r1)->y1 >= (r2)->y2) ) )
-
-/* true iff Box r1 contains Box r2 */
-#define SUBSUMES(r1, r2) \
- ( ((r1)->x1 <= (r2)->x1) && \
- ((r1)->x2 >= (r2)->x2) && \
- ((r1)->y1 <= (r2)->y1) && \
- ((r1)->y2 >= (r2)->y2) )
-
-
-void region_init(QRegion *rgn)
-{
- pixman_region32_init(rgn);
-}
-
-void region_clear(QRegion *rgn)
-{
- pixman_region32_fini(rgn);
- pixman_region32_init(rgn);
-}
-
-void region_destroy(QRegion *rgn)
-{
- pixman_region32_fini(rgn);
-}
-
-void region_clone(QRegion *dest, const QRegion *src)
-{
- pixman_region32_init(dest);
- pixman_region32_copy(dest, (pixman_region32_t *)src);
-}
-
-#define FIND_BAND(r, r_band_end, r_end, ry1) \
- do { \
- ry1 = r->y1; \
- r_band_end = r + 1; \
- while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \
- r_band_end++; \
- } \
- } while (0)
-
-static int test_band(int query,
- int res,
- pixman_box32_t *r1,
- pixman_box32_t *r1_end,
- pixman_box32_t *r2,
- pixman_box32_t *r2_end)
-{
- int x1;
- int x2;
-
- do {
- x1 = MAX(r1->x1, r2->x1);
- x2 = MIN(r1->x2, r2->x2);
-
- /*
- * Is there any overlap between the two rectangles?
- */
- if (x1 < x2) {
- res |= REGION_TEST_SHARED;
-
- if (r1->x1 < r2->x1 || r1->x2 > r2->x2) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- }
-
- if (r2->x1 < r1->x1 || r2->x2 > r1->x2) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
- } else {
- /* No overlap at all, the leftmost is exclusive */
- if (r1->x1 < r2->x1) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- } else {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
- }
-
- if ((res & query) == query) {
- return res;
- }
-
- /*
- * Advance the pointer(s) with the leftmost right side, since the next
- * rectangle on that list may still overlap the other region's
- * current rectangle.
- */
- if (r1->x2 == x2) {
- r1++;
- }
- if (r2->x2 == x2) {
- r2++;
- }
- } while ((r1 != r1_end) && (r2 != r2_end));
-
- /*
- * Deal with whichever band (if any) still has rectangles left.
- */
- if (r1 != r1_end) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- } else if (r2 != r2_end) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
-
- return res;
-}
-
-static int test_generic (pixman_region32_t *reg1,
- pixman_region32_t *reg2,
- int query)
-{
- pixman_box32_t *r1; /* Pointer into first region */
- pixman_box32_t *r2; /* Pointer into 2d region */
- pixman_box32_t *r1_end; /* End of 1st region */
- pixman_box32_t *r2_end; /* End of 2d region */
- int ybot; /* Bottom of intersection */
- int ytop; /* Top of intersection */
- pixman_box32_t * r1_band_end; /* End of current band in r1 */
- pixman_box32_t * r2_band_end; /* End of current band in r2 */
- int top; /* Top of non-overlapping band */
- int bot; /* Bottom of non-overlapping band*/
- int r1y1; /* Temps for r1->y1 and r2->y1 */
- int r2y1;
- int r1_num_rects;
- int r2_num_rects;
- int res;
-
- r1 = pixman_region32_rectangles(reg1, &r1_num_rects);
- r1_end = r1 + r1_num_rects;
-
- r2 = pixman_region32_rectangles(reg2, &r2_num_rects);
- r2_end = r2 + r2_num_rects;
-
- res = 0;
-
- /*
- * Initialize ybot.
- * In the upcoming loop, ybot and ytop serve different functions depending
- * on whether the band being handled is an overlapping or non-overlapping
- * band.
- * In the case of a non-overlapping band (only one of the regions
- * has points in the band), ybot is the bottom of the most recent
- * intersection and thus clips the top of the rectangles in that band.
- * ytop is the top of the next intersection between the two regions and
- * serves to clip the bottom of the rectangles in the current band.
- * For an overlapping band (where the two regions intersect), ytop clips
- * the top of the rectangles of both regions and ybot clips the bottoms.
- */
-
- ybot = MIN(r1->y1, r2->y1);
-
- do {
- /*
- * This algorithm proceeds one source-band (as opposed to a
- * destination band, which is determined by where the two regions
- * intersect) at a time. r1_band_end and r2_band_end serve to mark the
- * rectangle after the last one in the current band for their
- * respective regions.
- */
- FIND_BAND(r1, r1_band_end, r1_end, r1y1);
- FIND_BAND(r2, r2_band_end, r2_end, r2y1);
-
- /*
- * First handle the band that doesn't intersect, if any.
- *
- * Note that attention is restricted to one band in the
- * non-intersecting region at once, so if a region has n
- * bands between the current position and the next place it overlaps
- * the other, this entire loop will be passed through n times.
- */
- if (r1y1 < r2y1) {
- top = MAX (r1y1, ybot);
- bot = MIN (r1->y2, r2y1);
- if (top != bot) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
-
- if ((res & query) == query) {
- return res & query;
- }
- }
-
- ytop = r2y1;
- } else if (r2y1 < r1y1) {
- top = MAX (r2y1, ybot);
- bot = MIN (r2->y2, r1y1);
-
- if (top != bot) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
-
- if ((res & query) == query) {
- return res & query;
- }
- }
- ytop = r1y1;
- } else {
- ytop = r1y1;
- }
-
- /*
- * Now see if we've hit an intersecting band. The two bands only
- * intersect if ybot > ytop
- */
- ybot = MIN (r1->y2, r2->y2);
- if (ybot > ytop) {
- res = test_band(query, res,
- r1, r1_band_end,
- r2, r2_band_end);
- if ((res & query) == query) {
- return res & query;
- }
- }
-
- /*
- * If we've finished with a band (y2 == ybot) we skip forward
- * in the region to the next band.
- */
- if (r1->y2 == ybot) {
- r1 = r1_band_end;
- }
-
- if (r2->y2 == ybot) {
- r2 = r2_band_end;
- }
-
- }
- while (r1 != r1_end && r2 != r2_end);
-
- /*
- * Deal with whichever region (if any) still has rectangles left.
- */
-
- if (r1 != r1_end) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- } else if (r2 != r2_end) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
-
- return res & query;
-}
-
-int region_test(const QRegion *_reg1, const QRegion *_reg2, int query)
-{
- int res;
- pixman_region32_t *reg1 = (pixman_region32_t *)_reg1;
- pixman_region32_t *reg2 = (pixman_region32_t *)_reg2;
-
- query = (query) ? query & REGION_TEST_ALL : REGION_TEST_ALL;
-
- res = 0;
-
- if (!pixman_region32_not_empty(reg1) || !pixman_region32_not_empty(reg2) ||
- !EXTENTCHECK (®1->extents, ®2->extents)) {
- /* One or more regions are empty or they are disjoint */
-
- if (pixman_region32_not_empty(reg1)) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- }
-
- if (pixman_region32_not_empty(reg2)) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
-
- return res & query;
- } else if (!reg1->data && !reg2->data) {
- /* Just two rectangles that intersect */
- res |= REGION_TEST_SHARED;
-
- if (!SUBSUMES(®1->extents, ®2->extents)) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
-
- if (!SUBSUMES(®2->extents, ®1->extents)) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- }
-
- return res & query;
- } else if (!reg2->data && SUBSUMES (®2->extents, ®1->extents)) {
- /* reg2 is just a rect that contains all of reg1 */
-
- res |= REGION_TEST_SHARED; /* some piece must be shared, because reg is not empty */
- res |= REGION_TEST_RIGHT_EXCLUSIVE; /* reg2 contains all of reg1 and then some */
-
- return res & query;
- } else if (!reg1->data && SUBSUMES (®1->extents, ®2->extents)) {
- /* reg1 is just a rect that contains all of reg2 */
-
- res |= REGION_TEST_SHARED; /* some piece must be shared, because reg is not empty */
- res |= REGION_TEST_LEFT_EXCLUSIVE; /* reg1 contains all of reg2 and then some */
-
- return res & query;
- } else if (reg1 == reg2) {
- res |= REGION_TEST_SHARED;
- return res & query;
- } else {
- /* General purpose intersection */
- return test_generic (reg1, reg2, query);
- }
-}
-
-int region_is_valid(const QRegion *rgn)
-{
- return pixman_region32_selfcheck((pixman_region32_t *)rgn);
-}
-
-int region_is_empty(const QRegion *rgn)
-{
- return !pixman_region32_not_empty((pixman_region32_t *)rgn);
-}
-
-SpiceRect *region_dup_rects(const QRegion *rgn, uint32_t *num_rects)
-{
- pixman_box32_t *boxes;
- SpiceRect *rects;
- int n, i;
-
- boxes = pixman_region32_rectangles((pixman_region32_t *)rgn, &n);
- if (num_rects) {
- *num_rects = n;
- }
- rects = spice_new(SpiceRect, n);
- for (i = 0; i < n; i++) {
- rects[i].left = boxes[i].x1;
- rects[i].top = boxes[i].y1;
- rects[i].right = boxes[i].x2;
- rects[i].bottom = boxes[i].y2;
- }
- return rects;
-}
-
-void region_ret_rects(const QRegion *rgn, SpiceRect *rects, uint32_t num_rects)
-{
- pixman_box32_t *boxes;
- unsigned int n, i;
-
- boxes = pixman_region32_rectangles((pixman_region32_t *)rgn, (int *)&n);
- for (i = 0; i < n && i < num_rects; i++) {
- rects[i].left = boxes[i].x1;
- rects[i].top = boxes[i].y1;
- rects[i].right = boxes[i].x2;
- rects[i].bottom = boxes[i].y2;
- }
-
- if (i && i != n) {
- unsigned int x;
-
- for (x = 0; x < (n - num_rects); ++x) {
- rects[i - 1].left = MIN(rects[i - 1].left, boxes[i + x].x1);
- rects[i - 1].top = MIN(rects[i - 1].top, boxes[i + x].y1);
- rects[i - 1].right = MAX(rects[i - 1].right, boxes[i + x].x2);
- rects[i - 1].bottom = MAX(rects[i - 1].bottom, boxes[i + x].y2);
- }
- }
-}
-
-
-int region_is_equal(const QRegion *rgn1, const QRegion *rgn2)
-{
- return pixman_region32_equal((pixman_region32_t *)rgn1, (pixman_region32_t *)rgn2);
-}
-
-int region_intersects(const QRegion *rgn1, const QRegion *rgn2)
-{
- int test_res;
-
- if (!region_bounds_intersects(rgn1, rgn2)) {
- return FALSE;
- }
-
- test_res = region_test(rgn1, rgn2, REGION_TEST_SHARED);
- return !!test_res;
-}
-
-int region_bounds_intersects(const QRegion *rgn1, const QRegion *rgn2)
-{
- pixman_box32_t *extents1, *extents2;
-
- extents1 = pixman_region32_extents((pixman_region32_t *)rgn1);
- extents2 = pixman_region32_extents((pixman_region32_t *)rgn1);
-
- return EXTENTCHECK(extents1, extents2);
-}
-
-int region_contains(const QRegion *rgn, const QRegion *other)
-{
- int test_res;
-
- test_res = region_test(rgn, other, REGION_TEST_RIGHT_EXCLUSIVE);
- return !test_res;
-}
-
-int region_contains_point(const QRegion *rgn, int32_t x, int32_t y)
-{
- return pixman_region32_contains_point((pixman_region32_t *)rgn, x, y, NULL);
-}
-
-void region_or(QRegion *rgn, const QRegion *other_rgn)
-{
- pixman_region32_union(rgn, rgn, (pixman_region32_t *)other_rgn);
-}
-
-void region_and(QRegion *rgn, const QRegion *other_rgn)
-{
- pixman_region32_intersect(rgn, rgn, (pixman_region32_t *)other_rgn);
-}
-
-void region_xor(QRegion *rgn, const QRegion *other_rgn)
-{
- pixman_region32_t intersection;
-
- pixman_region32_copy(&intersection, rgn);
- pixman_region32_intersect(&intersection,
- &intersection,
- (pixman_region32_t *)other_rgn);
- pixman_region32_union(rgn, rgn, (pixman_region32_t *)other_rgn);
- pixman_region32_subtract(rgn, rgn, &intersection);
- pixman_region32_fini(&intersection);
-}
-
-void region_exclude(QRegion *rgn, const QRegion *other_rgn)
-{
- pixman_region32_subtract(rgn, rgn, (pixman_region32_t *)other_rgn);
-}
-
-void region_add(QRegion *rgn, const SpiceRect *r)
-{
- pixman_region32_union_rect(rgn, rgn, r->left, r->top,
- r->right - r->left,
- r->bottom - r->top);
-}
-
-void region_remove(QRegion *rgn, const SpiceRect *r)
-{
- pixman_region32_t rg;
-
- pixman_region32_init_rect(&rg, r->left, r->top,
- r->right - r->left,
- r->bottom - r->top);
- pixman_region32_subtract(rgn, rgn, &rg);
- pixman_region32_fini(&rg);
-}
-
-
-void region_offset(QRegion *rgn, int32_t dx, int32_t dy)
-{
- pixman_region32_translate(rgn, dx, dy);
-}
-
-void region_dump(const QRegion *rgn, const char *prefix)
-{
- pixman_box32_t *rects, *extents;
- int n_rects, i;
-
- printf("%sREGION: %p, ", prefix, rgn);
-
- if (!pixman_region32_not_empty((pixman_region32_t *)rgn)) {
- printf("EMPTY\n");
- return;
- }
-
- extents = pixman_region32_extents((pixman_region32_t *)rgn);
- rects = pixman_region32_rectangles((pixman_region32_t *)rgn, &n_rects);
- printf("num %u bounds (%d, %d, %d, %d)\n",
- n_rects,
- extents->x1,
- extents->y1,
- extents->x2,
- extents->y2);
-
-
- for (i = 0; i < n_rects; i++) {
- printf("%*s %12d %12d %12d %12d\n",
- (int)strlen(prefix), "",
- rects[i].x1,
- rects[i].y1,
- rects[i].x2,
- rects[i].y2);
- }
-}
-
-#ifdef REGION_TEST
-
-static int slow_region_test(const QRegion *rgn, const QRegion *other_rgn, int query)
-{
- pixman_region32_t intersection;
- int res;
-
- pixman_region32_init(&intersection);
- pixman_region32_intersect(&intersection,
- (pixman_region32_t *)rgn,
- (pixman_region32_t *)other_rgn);
-
- res = 0;
-
- if (query & REGION_TEST_SHARED &&
- pixman_region32_not_empty(&intersection)) {
- res |= REGION_TEST_SHARED;
- }
-
- if (query & REGION_TEST_LEFT_EXCLUSIVE &&
- !pixman_region32_equal(&intersection, (pixman_region32_t *)rgn)) {
- res |= REGION_TEST_LEFT_EXCLUSIVE;
- }
-
- if (query & REGION_TEST_RIGHT_EXCLUSIVE &&
- !pixman_region32_equal(&intersection, (pixman_region32_t *)other_rgn)) {
- res |= REGION_TEST_RIGHT_EXCLUSIVE;
- }
-
- pixman_region32_fini(&intersection);
-
- return res;
-}
-
-
-static int rect_is_valid(const SpiceRect *r)
-{
- if (r->top > r->bottom || r->left > r->right) {
- printf("%s: invalid rect\n", __FUNCTION__);
- return FALSE;
- }
- return TRUE;
-}
-
-static void rect_set(SpiceRect *r, int32_t top, int32_t left, int32_t bottom, int32_t right)
-{
- r->top = top;
- r->left = left;
- r->bottom = bottom;
- r->right = right;
- ASSERT(rect_is_valid(r));
-}
-
-static void random_region(QRegion *reg)
-{
- int i;
- int num_rects;
- int x, y, w, h;
- SpiceRect _r;
- SpiceRect *r = &_r;
-
- region_clear(reg);
-
- num_rects = rand() % 20;
- for (i = 0; i < num_rects; i++) {
- x = rand()%100;
- y = rand()%100;
- w = rand()%100;
- h = rand()%100;
- rect_set(r,
- x, y,
- x+w, y+h);
- region_add(reg, r);
- }
-}
-
-static void test(const QRegion *r1, const QRegion *r2, int *expected)
-{
- printf("r1 is_empty %s [%s]\n",
- region_is_empty(r1) ? "TRUE" : "FALSE",
- (region_is_empty(r1) == *(expected++)) ? "OK" : "ERR");
- printf("r2 is_empty %s [%s]\n",
- region_is_empty(r2) ? "TRUE" : "FALSE",
- (region_is_empty(r2) == *(expected++)) ? "OK" : "ERR");
- printf("is_equal %s [%s]\n",
- region_is_equal(r1, r2) ? "TRUE" : "FALSE",
- (region_is_equal(r1, r2) == *(expected++)) ? "OK" : "ERR");
- printf("intersects %s [%s]\n",
- region_intersects(r1, r2) ? "TRUE" : "FALSE",
- (region_intersects(r1, r2) == *(expected++)) ? "OK" : "ERR");
- printf("contains %s [%s]\n",
- region_contains(r1, r2) ? "TRUE" : "FALSE",
- (region_contains(r1, r2) == *(expected++)) ? "OK" : "ERR");
-}
-
-enum {
- EXPECT_R1_EMPTY,
- EXPECT_R2_EMPTY,
- EXPECT_EQUAL,
- EXPECT_SECT,
- EXPECT_CONT,
-};
-
-int main(void)
-{
- QRegion _r1, _r2, _r3;
- QRegion *r1 = &_r1;
- QRegion *r2 = &_r2;
- QRegion *r3 = &_r3;
- SpiceRect _r;
- SpiceRect *r = &_r;
- int expected[5];
- int i, j;
-
- region_init(r1);
- region_init(r2);
-
- printf("dump r1 empty rgn [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = TRUE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = TRUE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clone(r3, r1);
- printf("dump r3 clone rgn [%s]\n", region_is_valid(r3) ? "VALID" : "INVALID");
- region_dump(r3, "");
- expected[EXPECT_R1_EMPTY] = TRUE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = TRUE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r3, expected);
- region_destroy(r3);
- printf("\n");
-
- rect_set(r, 0, 0, 100, 100);
- region_add(r1, r);
- printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r1);
- rect_set(r, 0, 0, 0, 0);
- region_add(r1, r);
- printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = TRUE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = TRUE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- rect_set(r, -100, -100, 0, 0);
- region_add(r1, r);
- printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r1);
- rect_set(r, -100, -100, 100, 100);
- region_add(r1, r);
- printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
-
- region_clear(r1);
- region_clear(r2);
-
- rect_set(r, 100, 100, 200, 200);
- region_add(r1, r);
- printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- rect_set(r, 300, 300, 400, 400);
- region_add(r1, r);
- printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID");
- region_dump(r1, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = TRUE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- rect_set(r, 500, 500, 600, 600);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = FALSE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r2);
-
- rect_set(r, 100, 100, 200, 200);
- region_add(r2, r);
- rect_set(r, 300, 300, 400, 400);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = TRUE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r2);
-
- rect_set(r, 100, 100, 200, 200);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r2);
-
- rect_set(r, -2000, -2000, -1000, -1000);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = FALSE;
- expected[EXPECT_CONT] = FALSE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r2);
-
- rect_set(r, -2000, -2000, 1000, 1000);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = FALSE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r2);
-
- rect_set(r, 150, 150, 175, 175);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r2, expected);
- printf("\n");
-
- region_clear(r2);
-
- rect_set(r, 150, 150, 350, 350);
- region_add(r2, r);
- printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = FALSE;
- test(r1, r2, expected);
- printf("\n");
-
- region_and(r2, r1);
- printf("dump r2 and r1 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID");
- region_dump(r2, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = FALSE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = FALSE;
- test(r2, r1, expected);
- printf("\n");
-
-
- region_clone(r3, r1);
- printf("dump r3 clone rgn [%s]\n", region_is_valid(r3) ? "VALID" : "INVALID");
- region_dump(r3, "");
- expected[EXPECT_R1_EMPTY] = FALSE;
- expected[EXPECT_R2_EMPTY] = FALSE;
- expected[EXPECT_EQUAL] = TRUE;
- expected[EXPECT_SECT] = TRUE;
- expected[EXPECT_CONT] = TRUE;
- test(r1, r3, expected);
- printf("\n");
-
- j = 0;
- for (i = 0; i < 1000000; i++) {
- int res1, res2, test;
- int tests[] = {
- REGION_TEST_LEFT_EXCLUSIVE,
- REGION_TEST_RIGHT_EXCLUSIVE,
- REGION_TEST_SHARED,
- REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE,
- REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_SHARED,
- REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED,
- REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED
- };
-
- random_region(r1);
- random_region(r2);
-
- for (test = 0; test < 7; test++) {
- res1 = region_test(r1, r2, tests[test]);
- res2 = slow_region_test(r1, r2, tests[test]);
- if (res1 != res2) {
- printf ("Error in region_test %d, got %d, expected %d, query=%d\n",
- j, res1, res2, tests[test]);
- printf ("r1:\n");
- region_dump(r1, "");
- printf ("r2:\n");
- region_dump(r2, "");
- }
- j++;
- }
- }
-
- region_destroy(r3);
- region_destroy(r1);
- region_destroy(r2);
-
- return 0;
-}
-
-#endif
-
diff --git a/common/region.h b/common/region.h
deleted file mode 100644
index bad7494..0000000
--- a/common/region.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_REGION
-#define _H_REGION
-
-#include <stdint.h>
-#include "draw.h"
-#include <pixman_utils.h>
-
-typedef pixman_region32_t QRegion;
-
-#define REGION_TEST_LEFT_EXCLUSIVE (1 << 0)
-#define REGION_TEST_RIGHT_EXCLUSIVE (1 << 1)
-#define REGION_TEST_SHARED (1 << 2)
-#define REGION_TEST_ALL \
- (REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED)
-
-void region_init(QRegion *rgn);
-void region_clear(QRegion *rgn);
-void region_destroy(QRegion *rgn);
-void region_clone(QRegion *dest, const QRegion *src);
-SpiceRect *region_dup_rects(const QRegion *rgn, uint32_t *num_rects);
-void region_ret_rects(const QRegion *rgn, SpiceRect *rects, uint32_t num_rects);
-
-int region_test(const QRegion *rgn, const QRegion *other_rgn, int query);
-int region_is_valid(const QRegion *rgn);
-int region_is_empty(const QRegion *rgn);
-int region_is_equal(const QRegion *rgn1, const QRegion *rgn2);
-int region_intersects(const QRegion *rgn1, const QRegion *rgn2);
-int region_bounds_intersects(const QRegion *rgn1, const QRegion *rgn2);
-int region_contains(const QRegion *rgn, const QRegion *other);
-int region_contains_point(const QRegion *rgn, int32_t x, int32_t y);
-
-void region_or(QRegion *rgn, const QRegion *other_rgn);
-void region_and(QRegion *rgn, const QRegion *other_rgn);
-void region_xor(QRegion *rgn, const QRegion *other_rgn);
-void region_exclude(QRegion *rgn, const QRegion *other_rgn);
-
-void region_add(QRegion *rgn, const SpiceRect *r);
-void region_remove(QRegion *rgn, const SpiceRect *r);
-
-void region_offset(QRegion *rgn, int32_t dx, int32_t dy);
-
-void region_dump(const QRegion *rgn, const char *prefix);
-
-#endif
-
diff --git a/common/ring.h b/common/ring.h
deleted file mode 100644
index 0194959..0000000
--- a/common/ring.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_RING2
-#define _H_RING2
-
-#include <stddef.h>
-
-#ifndef ASSERT
-# include <assert.h>
-# define ASSERT(X) assert(X)
-#endif
-
-typedef struct Ring RingItem;
-typedef struct Ring {
- RingItem *prev;
- RingItem *next;
-} Ring;
-
-static inline void ring_init(Ring *ring)
-{
- ring->next = ring->prev = ring;
-}
-
-static inline void ring_item_init(RingItem *item)
-{
- item->next = item->prev = NULL;
-}
-
-static inline int ring_item_is_linked(RingItem *item)
-{
- return !!item->next;
-}
-
-static inline int ring_is_empty(Ring *ring)
-{
- ASSERT(ring->next != NULL && ring->prev != NULL);
- return ring == ring->next;
-}
-
-static inline void ring_add(Ring *ring, RingItem *item)
-{
- ASSERT(ring->next != NULL && ring->prev != NULL);
- ASSERT(item->next == NULL && item->prev == NULL);
-
- item->next = ring->next;
- item->prev = ring;
- ring->next = item->next->prev = item;
-}
-
-static inline void ring_add_after(RingItem *item, RingItem *pos)
-{
- ring_add(pos, item);
-}
-
-static inline void ring_add_before(RingItem *item, RingItem *pos)
-{
- ring_add(pos->prev, item);
-}
-
-static inline void __ring_remove(RingItem *item)
-{
- item->next->prev = item->prev;
- item->prev->next = item->next;
- item->prev = item->next = 0;
-}
-
-static inline void ring_remove(RingItem *item)
-{
- ASSERT(item->next != NULL && item->prev != NULL);
- ASSERT(item->next != item);
-
- __ring_remove(item);
-}
-
-static inline RingItem *ring_get_head(Ring *ring)
-{
- RingItem *ret;
-
- ASSERT(ring->next != NULL && ring->prev != NULL);
-
- if (ring_is_empty(ring)) {
- return NULL;
- }
- ret = ring->next;
- return ret;
-}
-
-static inline RingItem *ring_get_tail(Ring *ring)
-{
- RingItem *ret;
-
- ASSERT(ring->next != NULL && ring->prev != NULL);
-
- if (ring_is_empty(ring)) {
- return NULL;
- }
- ret = ring->prev;
- return ret;
-}
-
-static inline RingItem *ring_next(Ring *ring, RingItem *pos)
-{
- RingItem *ret;
-
- ASSERT(ring->next != NULL && ring->prev != NULL);
- ASSERT(pos);
- ASSERT(pos->next != NULL && pos->prev != NULL);
- ret = pos->next;
- return (ret == ring) ? NULL : ret;
-}
-
-static inline RingItem *ring_prev(Ring *ring, RingItem *pos)
-{
- RingItem *ret;
-
- ASSERT(ring->next != NULL && ring->prev != NULL);
- ASSERT(pos);
- ASSERT(pos->next != NULL && pos->prev != NULL);
- ret = pos->prev;
- return (ret == ring) ? NULL : ret;
-}
-
-static inline unsigned int ring_get_length(Ring *ring)
-{
- RingItem *i;
- unsigned int ret = 0;
-
- for (i = ring_get_head(ring);
- i != NULL;
- i = ring_next(ring, i))
- ret++;
-
- return ret;
-}
-
-#endif
-
diff --git a/common/rop3.c b/common/rop3.c
deleted file mode 100644
index 15de023..0000000
--- a/common/rop3.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdio.h>
-
-#include "rop3.h"
-
-#ifndef ASSERT
-#define ASSERT(x) if (!(x)) { \
- printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \
- abort(); \
-}
-#endif
-
-#ifndef WARN
-#define WARN(x) printf("warning: %s\n", x)
-#endif
-
-typedef void (*rop3_with_pattern_handler_t)(pixman_image_t *d, pixman_image_t *s,
- SpicePoint *src_pos, pixman_image_t *p,
- SpicePoint *pat_pos);
-
-typedef void (*rop3_with_color_handler_t)(pixman_image_t *d, pixman_image_t *s,
- SpicePoint *src_pos, uint32_t rgb);
-
-typedef void (*rop3_test_handler_t)(void);
-
-#define ROP3_NUM_OPS 256
-
-static rop3_with_pattern_handler_t rop3_with_pattern_handlers_32[ROP3_NUM_OPS];
-static rop3_with_pattern_handler_t rop3_with_pattern_handlers_16[ROP3_NUM_OPS];
-static rop3_with_color_handler_t rop3_with_color_handlers_32[ROP3_NUM_OPS];
-static rop3_with_color_handler_t rop3_with_color_handlers_16[ROP3_NUM_OPS];
-static rop3_test_handler_t rop3_test_handlers_32[ROP3_NUM_OPS];
-static rop3_test_handler_t rop3_test_handlers_16[ROP3_NUM_OPS];
-
-
-static void default_rop3_with_pattern_handler(pixman_image_t *d, pixman_image_t *s,
- SpicePoint *src_pos, pixman_image_t *p,
- SpicePoint *pat_pos)
-{
- WARN("not implemented 0x%x");
-}
-
-static void default_rop3_withe_color_handler(pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos,
- uint32_t rgb)
-{
- WARN("not implemented 0x%x");
-}
-
-static void default_rop3_test_handler(void)
-{
-}
-
-#define ROP3_HANDLERS_DEPTH(name, formula, index, depth) \
-static void rop3_handle_p##depth##_##name(pixman_image_t *d, pixman_image_t *s, \
- SpicePoint *src_pos, \
- pixman_image_t *p, SpicePoint *pat_pos) \
-{ \
- int width = pixman_image_get_width(d); \
- int height = pixman_image_get_height(d); \
- uint8_t *dest_line = (uint8_t *)pixman_image_get_data(d); \
- int dest_stride = pixman_image_get_stride(d); \
- uint8_t *end_line = dest_line + height * dest_stride; \
- \
- int pat_width = pixman_image_get_width(p); \
- int pat_height = pixman_image_get_height(p); \
- uint8_t *pat_base = (uint8_t *)pixman_image_get_data(p); \
- int pat_stride = pixman_image_get_stride(p); \
- int pat_v_offset = pat_pos->y; \
- \
- int src_stride = pixman_image_get_stride(s); \
- uint8_t *src_line; \
- src_line = (uint8_t *)pixman_image_get_data(s) + src_pos->y * src_stride + (src_pos->x * depth / 8); \
- \
- for (; dest_line < end_line; dest_line += dest_stride, src_line += src_stride) { \
- uint##depth##_t *dest = (uint##depth##_t *)dest_line; \
- uint##depth##_t *end = dest + width; \
- uint##depth##_t *src = (uint##depth##_t *)src_line; \
- \
- int pat_h_offset = pat_pos->x; \
- \
- for (; dest < end; dest++, src++) { \
- uint##depth##_t *pat; \
- pat = (uint##depth##_t *) \
- (pat_base + pat_v_offset * pat_stride + (pat_h_offset * depth / 8)); \
- *dest = formula; \
- pat_h_offset = (pat_h_offset + 1) % pat_width; \
- } \
- \
- pat_v_offset = (pat_v_offset + 1) % pat_height; \
- } \
-} \
- \
-static void rop3_handle_c##depth##_##name(pixman_image_t *d, pixman_image_t *s, \
- SpicePoint *src_pos, \
- uint32_t rgb) \
-{ \
- int width = pixman_image_get_width(d); \
- int height = pixman_image_get_height(d); \
- uint8_t *dest_line = (uint8_t *)pixman_image_get_data(d); \
- int dest_stride = pixman_image_get_stride(d); \
- uint8_t *end_line = dest_line + height * dest_stride; \
- uint##depth##_t _pat = rgb; \
- uint##depth##_t *pat = &_pat; \
- \
- int src_stride = pixman_image_get_stride(s); \
- uint8_t *src_line; \
- src_line = (uint8_t *) \
- pixman_image_get_data(s) + src_pos->y * src_stride + (src_pos->x * depth / 8); \
- \
- for (; dest_line < end_line; dest_line += dest_stride, src_line += src_stride) { \
- uint##depth##_t *dest = (uint##depth##_t *)dest_line; \
- uint##depth##_t *end = dest + width; \
- uint##depth##_t *src = (uint##depth##_t *)src_line; \
- for (; dest < end; dest++, src++) { \
- *dest = formula; \
- } \
- } \
-} \
- \
-static void rop3_test##depth##_##name(void) \
-{ \
- uint8_t d = 0xaa; \
- uint8_t s = 0xcc; \
- uint8_t p = 0xf0; \
- uint8_t *pat = &p; \
- uint8_t *src = &s; \
- uint8_t *dest = &d; \
- \
- d = formula; \
- if (d != index) { \
- printf("%s: failed, result is 0x%x expect 0x%x\n", __FUNCTION__, d, index); \
- } \
-}
-
-#define ROP3_HANDLERS(name, formula, index) \
- ROP3_HANDLERS_DEPTH(name, formula, index, 32) \
- ROP3_HANDLERS_DEPTH(name, formula, index, 16)
-
-ROP3_HANDLERS(DPSoon, ~(*pat | *src | *dest), 0x01);
-ROP3_HANDLERS(DPSona, ~(*pat | *src) & *dest, 0x02);
-ROP3_HANDLERS(SDPona, ~(*pat | *dest) & *src, 0x04);
-ROP3_HANDLERS(PDSxnon, ~(~(*src ^ *dest) | *pat), 0x06);
-ROP3_HANDLERS(PDSaon, ~((*src & *dest) | *pat), 0x07);
-ROP3_HANDLERS(SDPnaa, ~*pat & *dest & *src, 0x08);
-ROP3_HANDLERS(PDSxon, ~((*src ^ *dest) | *pat), 0x09);
-ROP3_HANDLERS(PSDnaon, ~((~*dest & *src) | *pat), 0x0b);
-ROP3_HANDLERS(PDSnaon, ~((~*src & *dest) | *pat), 0x0d);
-ROP3_HANDLERS(PDSonon, ~(~(*src | *dest) | *pat), 0x0e);
-ROP3_HANDLERS(PDSona, ~(*src | *dest) & *pat, 0x10);
-ROP3_HANDLERS(SDPxnon, ~(~(*pat ^ *dest) | *src), 0x12);
-ROP3_HANDLERS(SDPaon, ~((*pat & *dest) | *src), 0x13);
-ROP3_HANDLERS(DPSxnon, ~(~(*pat ^ *src) | *dest), 0x14);
-ROP3_HANDLERS(DPSaon, ~((*pat & *src) | *dest), 0x15);
-ROP3_HANDLERS(PSDPSanaxx, (~(*pat & *src) & *dest) ^ *src ^ *pat, 0x16);
-ROP3_HANDLERS(SSPxDSxaxn, ~(((*src ^ *dest) & (*src ^ *pat)) ^ *src), 0x17);
-ROP3_HANDLERS(SPxPDxa, (*src ^ *pat) & (*pat ^ *dest), 0x18);
-ROP3_HANDLERS(SDPSanaxn, ~((~(*pat & *src) & *dest) ^ *src), 0x19);
-ROP3_HANDLERS(PDSPaox, ((*pat & *src) | *dest) ^ *pat, 0x1a);
-ROP3_HANDLERS(SDPSxaxn, ~(((*pat ^ *src) & *dest) ^ *src), 0x1b);
-ROP3_HANDLERS(PSDPaox, ((*pat & *dest) | *src) ^ *pat, 0x1c);
-ROP3_HANDLERS(DSPDxaxn, ~(((*pat ^ *dest) & *src) ^ *dest), 0x1d);
-ROP3_HANDLERS(PDSox, (*dest | *src) ^ *pat, 0x1e);
-ROP3_HANDLERS(PDSoan, ~((*src | *dest) & *pat), 0x1f);
-ROP3_HANDLERS(DPSnaa, ~*src & *pat & *dest, 0x20);
-ROP3_HANDLERS(SDPxon, ~((*pat ^ *dest) | *src), 0x21);
-ROP3_HANDLERS(SPDnaon, ~((~*dest & *pat) | *src), 0x23);
-ROP3_HANDLERS(SPxDSxa, (*src ^ *pat) & (*dest ^ *src), 0x24);
-ROP3_HANDLERS(PDSPanaxn, ~((~(*src & *pat) & *dest) ^ *pat), 0x25);
-ROP3_HANDLERS(SDPSaox, ((*src & *pat) | *dest) ^ *src, 0x26);
-ROP3_HANDLERS(SDPSxnox, (~(*src ^ *pat) | *dest) ^ *src, 0x27);
-ROP3_HANDLERS(DPSxa, (*pat ^ *src) & *dest, 0x28);
-ROP3_HANDLERS(PSDPSaoxxn, ~(((*src & *pat) | *dest) ^ *src ^ *pat), 0x29);
-ROP3_HANDLERS(DPSana, ~(*src & *pat) & *dest, 0x2a);
-ROP3_HANDLERS(SSPxPDxaxn, ~(((*pat ^ *dest) & (*src ^ *pat)) ^ *src), 0x2b);
-ROP3_HANDLERS(SPDSoax, ((*src | *dest) & *pat) ^ *src, 0x2c);
-ROP3_HANDLERS(PSDnox, (~*dest | *src) ^ *pat, 0x2d);
-ROP3_HANDLERS(PSDPxox, ((*pat ^ *dest) | *src) ^ *pat, 0x2e);
-ROP3_HANDLERS(PSDnoan, ~((~*dest | *src) & *pat), 0x2f);
-ROP3_HANDLERS(SDPnaon, ~((~*pat & *dest) | *src), 0x31);
-ROP3_HANDLERS(SDPSoox, (*src | *pat | *dest) ^ *src, 0x32);
-ROP3_HANDLERS(SPDSaox, ((*src & *dest) | *pat) ^ *src, 0x34);
-ROP3_HANDLERS(SPDSxnox, (~(*src ^ *dest) | *pat) ^ *src, 0x35);
-ROP3_HANDLERS(SDPox, (*pat | *dest) ^ *src, 0x36);
-ROP3_HANDLERS(SDPoan, ~((*pat | *dest) & *src), 0x37);
-ROP3_HANDLERS(PSDPoax, ((*pat | *dest) & *src) ^ *pat, 0x38);
-ROP3_HANDLERS(SPDnox, (~*dest | *pat) ^ *src, 0x39);
-ROP3_HANDLERS(SPDSxox, ((*src ^ *dest) | *pat) ^ *src, 0x3a);
-ROP3_HANDLERS(SPDnoan, ~((~*dest | *pat) & *src), 0x3b);
-ROP3_HANDLERS(SPDSonox, (~(*src | *dest) | *pat) ^ *src, 0x3d);
-ROP3_HANDLERS(SPDSnaox, ((~*src & *dest) | *pat) ^ *src, 0x3e);
-ROP3_HANDLERS(PSDnaa, ~*dest & *src & *pat, 0x40);
-ROP3_HANDLERS(DPSxon, ~((*src ^ *pat) | *dest), 0x41);
-ROP3_HANDLERS(SDxPDxa, (*src ^ *dest) & (*pat ^ *dest), 0x42);
-ROP3_HANDLERS(SPDSanaxn, ~((~(*src & *dest) & *pat) ^ *src), 0x43);
-ROP3_HANDLERS(DPSnaon, ~((~*src & *pat) | *dest), 0x45);
-ROP3_HANDLERS(DSPDaox, ((*dest & *pat) | *src) ^ *dest, 0x46);
-ROP3_HANDLERS(PSDPxaxn, ~(((*pat ^ *dest) & *src) ^ *pat), 0x47);
-ROP3_HANDLERS(SDPxa, (*pat ^ *dest) & *src, 0x48);
-ROP3_HANDLERS(PDSPDaoxxn, ~(((*dest & *pat) | *src) ^ *dest ^ *pat), 0x49);
-ROP3_HANDLERS(DPSDoax, ((*dest | *src) & *pat) ^ *dest, 0x4a);
-ROP3_HANDLERS(PDSnox, (~*src | *dest) ^ *pat, 0x4b);
-ROP3_HANDLERS(SDPana, ~(*pat & *dest) & *src, 0x4c);
-ROP3_HANDLERS(SSPxDSxoxn, ~(((*src ^ *dest) | (*src ^ *pat)) ^ *src), 0x4d);
-ROP3_HANDLERS(PDSPxox, ((*pat ^ *src) | *dest) ^ *pat, 0x4e);
-ROP3_HANDLERS(PDSnoan, ~((~*src | *dest) & *pat), 0x4f);
-ROP3_HANDLERS(DSPnaon, ~((~*pat & *src) | *dest), 0x51);
-ROP3_HANDLERS(DPSDaox, ((*dest & *src) | *pat) ^ *dest, 0x52);
-ROP3_HANDLERS(SPDSxaxn, ~(((*src ^ *dest) & *pat) ^ *src), 0x53);
-ROP3_HANDLERS(DPSonon, ~(~(*src | *pat) | *dest), 0x54);
-ROP3_HANDLERS(DPSox, (*src | *pat) ^ *dest, 0x56);
-ROP3_HANDLERS(DPSoan, ~((*src | *pat) & *dest), 0x57);
-ROP3_HANDLERS(PDSPoax, ((*pat | *src) & *dest) ^ *pat, 0x58);
-ROP3_HANDLERS(DPSnox, (~*src | *pat) ^ *dest, 0x59);
-ROP3_HANDLERS(DPSDonox, (~(*dest | *src) | *pat) ^ *dest, 0x5b);
-ROP3_HANDLERS(DPSDxox, ((*dest ^ *src) | *pat) ^ *dest, 0x5c);
-ROP3_HANDLERS(DPSnoan, ~((~*src | *pat) & *dest), 0x5d);
-ROP3_HANDLERS(DPSDnaox, ((~*dest & *src) | *pat) ^ *dest, 0x5e);
-ROP3_HANDLERS(PDSxa, (*src ^ *dest) & *pat, 0x60);
-ROP3_HANDLERS(DSPDSaoxxn, ~(((*src & *dest) | *pat) ^ *src ^ *dest), 0x61);
-ROP3_HANDLERS(DSPDoax, ((*dest | *pat) & *src) ^ *dest, 0x62);
-ROP3_HANDLERS(SDPnox, (~*pat | *dest) ^ *src, 0x63);
-ROP3_HANDLERS(SDPSoax, ((*src | *pat) & *dest) ^ *src, 0x64);
-ROP3_HANDLERS(DSPnox, (~*pat | *src) ^ *dest, 0x65);
-ROP3_HANDLERS(SDPSonox, (~(*src | *pat) | *dest) ^ *src, 0x67);
-ROP3_HANDLERS(DSPDSonoxxn, ~((~(*src | *dest) | *pat) ^ *src ^ *dest), 0x68);
-ROP3_HANDLERS(PDSxxn, ~(*src ^ *dest ^ *pat), 0x69);
-ROP3_HANDLERS(DPSax, (*src & *pat) ^ *dest, 0x6a);
-ROP3_HANDLERS(PSDPSoaxxn, ~(((*src | *pat) & *dest) ^ *src ^ *pat), 0x6b);
-ROP3_HANDLERS(SDPax, (*pat & *dest) ^ *src, 0x6c);
-ROP3_HANDLERS(PDSPDoaxxn, ~(((*dest | *pat) & *src) ^ *dest ^ *pat), 0x6d);
-ROP3_HANDLERS(SDPSnoax, ((~*src | *pat) & *dest) ^ *src, 0x6e);
-ROP3_HANDLERS(PDSxnan, ~(~(*src ^ *dest) & *pat), 0x6f);
-ROP3_HANDLERS(PDSana, ~(*src & *dest) & *pat, 0x70);
-ROP3_HANDLERS(SSDxPDxaxn, ~(((*dest ^ *pat) & (*src ^ *dest)) ^ *src), 0x71);
-ROP3_HANDLERS(SDPSxox, ((*src ^ *pat) | *dest) ^ *src, 0x72);
-ROP3_HANDLERS(SDPnoan, ~((~*pat | *dest) & *src), 0x73);
-ROP3_HANDLERS(DSPDxox, ((*dest ^ *pat) | *src) ^ *dest, 0x74);
-ROP3_HANDLERS(DSPnoan, ~((~*pat | *src) & *dest), 0x75);
-ROP3_HANDLERS(SDPSnaox, ((~*src & *pat) | *dest) ^ *src, 0x76);
-ROP3_HANDLERS(PDSax, (*src & *dest) ^ *pat, 0x78);
-ROP3_HANDLERS(DSPDSoaxxn, ~(((*src | *dest) & *pat) ^ *src ^ *dest), 0x79);
-ROP3_HANDLERS(DPSDnoax, ((~*dest | *src) & *pat) ^ *dest, 0x7a);
-ROP3_HANDLERS(SDPxnan, ~(~(*pat ^ *dest) & *src), 0x7b);
-ROP3_HANDLERS(SPDSnoax, ((~*src | *dest) & *pat) ^ *src, 0x7c);
-ROP3_HANDLERS(DPSxnan, ~(~(*src ^ *pat) & *dest), 0x7d);
-ROP3_HANDLERS(SPxDSxo, (*src ^ *dest) | (*pat ^ *src), 0x7e);
-ROP3_HANDLERS(DPSaan, ~(*src & *pat & *dest), 0x7f);
-ROP3_HANDLERS(DPSaa, *src & *pat & *dest, 0x80);
-ROP3_HANDLERS(SPxDSxon, ~((*src ^ *dest) | (*pat ^ *src)), 0x81);
-ROP3_HANDLERS(DPSxna, ~(*src ^ *pat) & *dest, 0x82);
-ROP3_HANDLERS(SPDSnoaxn, ~(((~*src | *dest) & *pat) ^ *src), 0x83);
-ROP3_HANDLERS(SDPxna, ~(*pat ^ *dest) & *src, 0x84);
-ROP3_HANDLERS(PDSPnoaxn, ~(((~*pat | *src) & *dest) ^ *pat), 0x85);
-ROP3_HANDLERS(DSPDSoaxx, ((*src | *dest) & *pat) ^ *src ^ *dest, 0x86);
-ROP3_HANDLERS(PDSaxn, ~((*src & *dest) ^ *pat), 0x87);
-ROP3_HANDLERS(SDPSnaoxn, ~(((~*src & *pat) | *dest) ^ *src), 0x89);
-ROP3_HANDLERS(DSPnoa, (~*pat | *src) & *dest, 0x8a);
-ROP3_HANDLERS(DSPDxoxn, ~(((*dest ^ *pat) | *src) ^ *dest), 0x8b);
-ROP3_HANDLERS(SDPnoa, (~*pat | *dest) & *src, 0x8c);
-ROP3_HANDLERS(SDPSxoxn, ~(((*src ^ *pat) | *dest) ^ *src), 0x8d);
-ROP3_HANDLERS(SSDxPDxax, ((*dest ^ *pat) & (*dest ^ *src)) ^ *src, 0x8e);
-ROP3_HANDLERS(PDSanan, ~(~(*src & *dest) & *pat), 0x8f);
-ROP3_HANDLERS(PDSxna, ~(*src ^ *dest) & *pat, 0x90);
-ROP3_HANDLERS(SDPSnoaxn, ~(((~*src | *pat) & *dest) ^ *src), 0x91);
-ROP3_HANDLERS(DPSDPoaxx, ((*pat | *dest) & *src) ^ *pat ^ *dest, 0x92);
-ROP3_HANDLERS(SPDaxn, ~((*dest & *pat) ^ *src), 0x93);
-ROP3_HANDLERS(PSDPSoaxx, ((*src | *pat) & *dest) ^ *src ^ *pat, 0x94);
-ROP3_HANDLERS(DPSaxn, ~((*src & *pat) ^ *dest), 0x95);
-ROP3_HANDLERS(DPSxx, *src ^ *pat ^ *dest, 0x96);
-ROP3_HANDLERS(PSDPSonoxx, (~(*src | *pat) | *dest) ^ *src ^ *pat, 0x97);
-ROP3_HANDLERS(SDPSonoxn, ~((~(*src | *pat) | *dest) ^ *src), 0x98);
-ROP3_HANDLERS(DPSnax, (~*src & *pat) ^ *dest, 0x9a);
-ROP3_HANDLERS(SDPSoaxn, ~(((*src | *pat) & *dest) ^ *src), 0x9b);
-ROP3_HANDLERS(SPDnax, (~*dest & *pat) ^ *src, 0x9c);
-ROP3_HANDLERS(DSPDoaxn, ~(((*dest | *pat) & *src) ^ *dest), 0x9d);
-ROP3_HANDLERS(DSPDSaoxx, ((*src & *dest) | *pat) ^ *src ^ *dest, 0x9e);
-ROP3_HANDLERS(PDSxan, ~((*src ^ *dest) & *pat), 0x9f);
-ROP3_HANDLERS(PDSPnaoxn, ~(((~*pat & *src) | *dest) ^ *pat), 0xa1);
-ROP3_HANDLERS(DPSnoa, (~*src | *pat) & *dest, 0xa2);
-ROP3_HANDLERS(DPSDxoxn, ~(((*dest ^ *src) | *pat) ^ *dest), 0xa3);
-ROP3_HANDLERS(PDSPonoxn, ~((~(*pat | *src) | *dest) ^ *pat), 0xa4);
-ROP3_HANDLERS(DSPnax, (~*pat & *src) ^ *dest, 0xa6);
-ROP3_HANDLERS(PDSPoaxn, ~(((*pat | *src) & *dest) ^ *pat), 0xa7);
-ROP3_HANDLERS(DPSoa, (*src | *pat) & *dest, 0xa8);
-ROP3_HANDLERS(DPSoxn, ~((*src | *pat) ^ *dest), 0xa9);
-ROP3_HANDLERS(DPSono, ~(*src | *pat) | *dest, 0xab);
-ROP3_HANDLERS(SPDSxax, ((*src ^ *dest) & *pat) ^ *src, 0xac);
-ROP3_HANDLERS(DPSDaoxn, ~(((*dest & *src) | *pat) ^ *dest), 0xad);
-ROP3_HANDLERS(DSPnao, (~*pat & *src) | *dest, 0xae);
-ROP3_HANDLERS(PDSnoa, (~*src | *dest) & *pat, 0xb0);
-ROP3_HANDLERS(PDSPxoxn, ~(((*pat ^ *src) | *dest) ^ *pat), 0xb1);
-ROP3_HANDLERS(SSPxDSxox, ((*src ^ *dest) | (*pat ^ *src)) ^ *src, 0xb2);
-ROP3_HANDLERS(SDPanan, ~(~(*pat & *dest) & *src), 0xb3);
-ROP3_HANDLERS(PSDnax, (~*dest & *src) ^ *pat, 0xb4);
-ROP3_HANDLERS(DPSDoaxn, ~(((*dest | *src) & *pat) ^ *dest), 0xb5);
-ROP3_HANDLERS(DPSDPaoxx, ((*pat & *dest) | *src) ^ *pat ^ *dest, 0xb6);
-ROP3_HANDLERS(SDPxan, ~((*pat ^ *dest) & *src), 0xb7);
-ROP3_HANDLERS(PSDPxax, ((*dest ^ *pat) & *src) ^ *pat, 0xb8);
-ROP3_HANDLERS(DSPDaoxn, ~(((*dest & *pat) | *src) ^ *dest), 0xb9);
-ROP3_HANDLERS(DPSnao, (~*src & *pat) | *dest, 0xba);
-ROP3_HANDLERS(SPDSanax, (~(*src & *dest) & *pat) ^ *src, 0xbc);
-ROP3_HANDLERS(SDxPDxan, ~((*dest ^ *pat) & (*dest ^ *src)), 0xbd);
-ROP3_HANDLERS(DPSxo, (*src ^ *pat) | *dest, 0xbe);
-ROP3_HANDLERS(DPSano, ~(*src & *pat) | *dest, 0xbf);
-ROP3_HANDLERS(SPDSnaoxn, ~(((~*src & *dest) | *pat) ^ *src), 0xc1);
-ROP3_HANDLERS(SPDSonoxn, ~((~(*src | *dest) | *pat) ^ *src), 0xc2);
-ROP3_HANDLERS(SPDnoa, (~*dest | *pat) & *src, 0xc4);
-ROP3_HANDLERS(SPDSxoxn, ~(((*src ^ *dest) | *pat) ^ *src), 0xc5);
-ROP3_HANDLERS(SDPnax, (~*pat & *dest) ^ *src, 0xc6);
-ROP3_HANDLERS(PSDPoaxn, ~(((*pat | *dest) & *src) ^ *pat), 0xc7);
-ROP3_HANDLERS(SDPoa, (*pat | *dest) & *src, 0xc8);
-ROP3_HANDLERS(SPDoxn, ~((*dest | *pat) ^ *src), 0xc9);
-ROP3_HANDLERS(DPSDxax, ((*dest ^ *src) & *pat) ^ *dest, 0xca);
-ROP3_HANDLERS(SPDSaoxn, ~(((*src & *dest) | *pat) ^ *src), 0xcb);
-ROP3_HANDLERS(SDPono, ~(*pat | *dest) | *src, 0xcd);
-ROP3_HANDLERS(SDPnao, (~*pat & *dest) | *src, 0xce);
-ROP3_HANDLERS(PSDnoa, (~*dest | *src) & *pat, 0xd0);
-ROP3_HANDLERS(PSDPxoxn, ~(((*pat ^ *dest) | *src) ^ *pat), 0xd1);
-ROP3_HANDLERS(PDSnax, (~*src & *dest) ^ *pat, 0xd2);
-ROP3_HANDLERS(SPDSoaxn, ~(((*src | *dest) & *pat) ^ *src), 0xd3);
-ROP3_HANDLERS(SSPxPDxax, ((*dest ^ *pat) & (*pat ^ *src)) ^ *src, 0xd4);
-ROP3_HANDLERS(DPSanan, ~(~(*src & *pat) & *dest), 0xd5);
-ROP3_HANDLERS(PSDPSaoxx, ((*src & *pat) | *dest) ^ *src ^ *pat, 0xd6);
-ROP3_HANDLERS(DPSxan, ~((*src ^ *pat) & *dest), 0xd7);
-ROP3_HANDLERS(PDSPxax, ((*pat ^ *src) & *dest) ^ *pat, 0xd8);
-ROP3_HANDLERS(SDPSaoxn, ~(((*src & *pat) | *dest) ^ *src), 0xd9);
-ROP3_HANDLERS(DPSDanax, (~(*dest & *src) & *pat) ^ *dest, 0xda);
-ROP3_HANDLERS(SPxDSxan, ~((*src ^ *dest) & (*pat ^ *src)), 0xdb);
-ROP3_HANDLERS(SPDnao, (~*dest & *pat) | *src, 0xdc);
-ROP3_HANDLERS(SDPxo, (*pat ^ *dest) | *src, 0xde);
-ROP3_HANDLERS(SDPano, ~(*pat & *dest) | *src, 0xdf);
-ROP3_HANDLERS(PDSoa, (*src | *dest) & *pat, 0xe0);
-ROP3_HANDLERS(PDSoxn, ~((*src | *dest) ^ *pat), 0xe1);
-ROP3_HANDLERS(DSPDxax, ((*dest ^ *pat) & *src) ^ *dest, 0xe2);
-ROP3_HANDLERS(PSDPaoxn, ~(((*pat & *dest) | *src) ^ *pat), 0xe3);
-ROP3_HANDLERS(SDPSxax, ((*src ^ *pat) & *dest) ^ *src, 0xe4);
-ROP3_HANDLERS(PDSPaoxn, ~(((*pat & *src) | *dest) ^ *pat), 0xe5);
-ROP3_HANDLERS(SDPSanax, (~(*src & *pat) & *dest) ^ *src, 0xe6);
-ROP3_HANDLERS(SPxPDxan, ~((*dest ^ *pat) & (*pat ^ *src)), 0xe7);
-ROP3_HANDLERS(SSPxDSxax, ((*src ^ *dest) & (*pat ^ *src)) ^ *src, 0xe8);
-ROP3_HANDLERS(DSPDSanaxxn, ~((~(*src & *dest) & *pat) ^ *src ^ *dest), 0xe9);
-ROP3_HANDLERS(DPSao, (*src & *pat) | *dest, 0xea);
-ROP3_HANDLERS(DPSxno, ~(*src ^ *pat) | *dest, 0xeb);
-ROP3_HANDLERS(SDPao, (*pat & *dest) | *src, 0xec);
-ROP3_HANDLERS(SDPxno, ~(*pat ^ *dest) | *src, 0xed);
-ROP3_HANDLERS(SDPnoo, ~*pat | *dest | *src, 0xef);
-ROP3_HANDLERS(PDSono, ~(*src | *dest) | *pat, 0xf1);
-ROP3_HANDLERS(PDSnao, (~*src & *dest) | *pat, 0xf2);
-ROP3_HANDLERS(PSDnao, (~*dest & *src) | *pat, 0xf4);
-ROP3_HANDLERS(PDSxo, (*src ^ *dest) | *pat, 0xf6);
-ROP3_HANDLERS(PDSano, ~(*src & *dest) | *pat, 0xf7);
-ROP3_HANDLERS(PDSao, (*src & *dest) | *pat, 0xf8);
-ROP3_HANDLERS(PDSxno, ~(*src ^ *dest) | *pat, 0xf9);
-ROP3_HANDLERS(DPSnoo, ~*src | *pat | *dest, 0xfb);
-ROP3_HANDLERS(PSDnoo, ~*dest | *src | *pat, 0xfd);
-ROP3_HANDLERS(DPSoo, *src | *pat | *dest, 0xfe);
-
-
-#define ROP3_FILL_HANDLERS(op, index) \
- rop3_with_pattern_handlers_32[index] = rop3_handle_p32_##op; \
- rop3_with_pattern_handlers_16[index] = rop3_handle_p16_##op; \
- rop3_with_color_handlers_32[index] = rop3_handle_c32_##op; \
- rop3_with_color_handlers_16[index] = rop3_handle_c16_##op; \
- rop3_test_handlers_32[index] = rop3_test32_##op; \
- rop3_test_handlers_16[index] = rop3_test16_##op;
-
-void rop3_init(void)
-{
- static int need_init = 1;
- int i;
-
- if (!need_init) {
- return;
- }
- need_init = 0;
-
- for (i = 0; i < ROP3_NUM_OPS; i++) {
- rop3_with_pattern_handlers_32[i] = default_rop3_with_pattern_handler;
- rop3_with_pattern_handlers_16[i] = default_rop3_with_pattern_handler;
- rop3_with_color_handlers_32[i] = default_rop3_withe_color_handler;
- rop3_with_color_handlers_16[i] = default_rop3_withe_color_handler;
- rop3_test_handlers_32[i] = default_rop3_test_handler;
- rop3_test_handlers_16[i] = default_rop3_test_handler;
- }
-
- ROP3_FILL_HANDLERS(DPSoon, 0x01);
- ROP3_FILL_HANDLERS(DPSona, 0x02);
- ROP3_FILL_HANDLERS(SDPona, 0x04);
- ROP3_FILL_HANDLERS(PDSxnon, 0x06);
- ROP3_FILL_HANDLERS(PDSaon, 0x07);
- ROP3_FILL_HANDLERS(SDPnaa, 0x08);
- ROP3_FILL_HANDLERS(PDSxon, 0x09);
- ROP3_FILL_HANDLERS(PSDnaon, 0x0b);
- ROP3_FILL_HANDLERS(PDSnaon, 0x0d);
- ROP3_FILL_HANDLERS(PDSonon, 0x0e);
- ROP3_FILL_HANDLERS(PDSona, 0x10);
- ROP3_FILL_HANDLERS(SDPxnon, 0x12);
- ROP3_FILL_HANDLERS(SDPaon, 0x13);
- ROP3_FILL_HANDLERS(DPSxnon, 0x14);
- ROP3_FILL_HANDLERS(DPSaon, 0x15);
- ROP3_FILL_HANDLERS(PSDPSanaxx, 0x16);
- ROP3_FILL_HANDLERS(SSPxDSxaxn, 0x17);
- ROP3_FILL_HANDLERS(SPxPDxa, 0x18);
- ROP3_FILL_HANDLERS(SDPSanaxn, 0x19);
- ROP3_FILL_HANDLERS(PDSPaox, 0x1a);
- ROP3_FILL_HANDLERS(SDPSxaxn, 0x1b);
- ROP3_FILL_HANDLERS(PSDPaox, 0x1c);
- ROP3_FILL_HANDLERS(DSPDxaxn, 0x1d);
- ROP3_FILL_HANDLERS(PDSox, 0x1e);
- ROP3_FILL_HANDLERS(PDSoan, 0x1f);
- ROP3_FILL_HANDLERS(DPSnaa, 0x20);
- ROP3_FILL_HANDLERS(SDPxon, 0x21);
- ROP3_FILL_HANDLERS(SPDnaon, 0x23);
- ROP3_FILL_HANDLERS(SPxDSxa, 0x24);
- ROP3_FILL_HANDLERS(PDSPanaxn, 0x25);
- ROP3_FILL_HANDLERS(SDPSaox, 0x26);
- ROP3_FILL_HANDLERS(SDPSxnox, 0x27);
- ROP3_FILL_HANDLERS(DPSxa, 0x28);
- ROP3_FILL_HANDLERS(PSDPSaoxxn, 0x29);
- ROP3_FILL_HANDLERS(DPSana, 0x2a);
- ROP3_FILL_HANDLERS(SSPxPDxaxn, 0x2b);
- ROP3_FILL_HANDLERS(SPDSoax, 0x2c);
- ROP3_FILL_HANDLERS(PSDnox, 0x2d);
- ROP3_FILL_HANDLERS(PSDPxox, 0x2e);
- ROP3_FILL_HANDLERS(PSDnoan, 0x2f);
- ROP3_FILL_HANDLERS(SDPnaon, 0x31);
- ROP3_FILL_HANDLERS(SDPSoox, 0x32);
- ROP3_FILL_HANDLERS(SPDSaox, 0x34);
- ROP3_FILL_HANDLERS(SPDSxnox, 0x35);
- ROP3_FILL_HANDLERS(SDPox, 0x36);
- ROP3_FILL_HANDLERS(SDPoan, 0x37);
- ROP3_FILL_HANDLERS(PSDPoax, 0x38);
- ROP3_FILL_HANDLERS(SPDnox, 0x39);
- ROP3_FILL_HANDLERS(SPDSxox, 0x3a);
- ROP3_FILL_HANDLERS(SPDnoan, 0x3b);
- ROP3_FILL_HANDLERS(SPDSonox, 0x3d);
- ROP3_FILL_HANDLERS(SPDSnaox, 0x3e);
- ROP3_FILL_HANDLERS(PSDnaa, 0x40);
- ROP3_FILL_HANDLERS(DPSxon, 0x41);
- ROP3_FILL_HANDLERS(SDxPDxa, 0x42);
- ROP3_FILL_HANDLERS(SPDSanaxn, 0x43);
- ROP3_FILL_HANDLERS(DPSnaon, 0x45);
- ROP3_FILL_HANDLERS(DSPDaox, 0x46);
- ROP3_FILL_HANDLERS(PSDPxaxn, 0x47);
- ROP3_FILL_HANDLERS(SDPxa, 0x48);
- ROP3_FILL_HANDLERS(PDSPDaoxxn, 0x49);
- ROP3_FILL_HANDLERS(DPSDoax, 0x4a);
- ROP3_FILL_HANDLERS(PDSnox, 0x4b);
- ROP3_FILL_HANDLERS(SDPana, 0x4c);
- ROP3_FILL_HANDLERS(SSPxDSxoxn, 0x4d);
- ROP3_FILL_HANDLERS(PDSPxox, 0x4e);
- ROP3_FILL_HANDLERS(PDSnoan, 0x4f);
- ROP3_FILL_HANDLERS(DSPnaon, 0x51);
- ROP3_FILL_HANDLERS(DPSDaox, 0x52);
- ROP3_FILL_HANDLERS(SPDSxaxn, 0x53);
- ROP3_FILL_HANDLERS(DPSonon, 0x54);
- ROP3_FILL_HANDLERS(DPSox, 0x56);
- ROP3_FILL_HANDLERS(DPSoan, 0x57);
- ROP3_FILL_HANDLERS(PDSPoax, 0x58);
- ROP3_FILL_HANDLERS(DPSnox, 0x59);
- ROP3_FILL_HANDLERS(DPSDonox, 0x5b);
- ROP3_FILL_HANDLERS(DPSDxox, 0x5c);
- ROP3_FILL_HANDLERS(DPSnoan, 0x5d);
- ROP3_FILL_HANDLERS(DPSDnaox, 0x5e);
- ROP3_FILL_HANDLERS(PDSxa, 0x60);
- ROP3_FILL_HANDLERS(DSPDSaoxxn, 0x61);
- ROP3_FILL_HANDLERS(DSPDoax, 0x62);
- ROP3_FILL_HANDLERS(SDPnox, 0x63);
- ROP3_FILL_HANDLERS(SDPSoax, 0x64);
- ROP3_FILL_HANDLERS(DSPnox, 0x65);
- ROP3_FILL_HANDLERS(SDPSonox, 0x67);
- ROP3_FILL_HANDLERS(DSPDSonoxxn, 0x68);
- ROP3_FILL_HANDLERS(PDSxxn, 0x69);
- ROP3_FILL_HANDLERS(DPSax, 0x6a);
- ROP3_FILL_HANDLERS(PSDPSoaxxn, 0x6b);
- ROP3_FILL_HANDLERS(SDPax, 0x6c);
- ROP3_FILL_HANDLERS(PDSPDoaxxn, 0x6d);
- ROP3_FILL_HANDLERS(SDPSnoax, 0x6e);
- ROP3_FILL_HANDLERS(PDSxnan, 0x6f);
- ROP3_FILL_HANDLERS(PDSana, 0x70);
- ROP3_FILL_HANDLERS(SSDxPDxaxn, 0x71);
- ROP3_FILL_HANDLERS(SDPSxox, 0x72);
- ROP3_FILL_HANDLERS(SDPnoan, 0x73);
- ROP3_FILL_HANDLERS(DSPDxox, 0x74);
- ROP3_FILL_HANDLERS(DSPnoan, 0x75);
- ROP3_FILL_HANDLERS(SDPSnaox, 0x76);
- ROP3_FILL_HANDLERS(PDSax, 0x78);
- ROP3_FILL_HANDLERS(DSPDSoaxxn, 0x79);
- ROP3_FILL_HANDLERS(DPSDnoax, 0x7a);
- ROP3_FILL_HANDLERS(SDPxnan, 0x7b);
- ROP3_FILL_HANDLERS(SPDSnoax, 0x7c);
- ROP3_FILL_HANDLERS(DPSxnan, 0x7d);
- ROP3_FILL_HANDLERS(SPxDSxo, 0x7e);
- ROP3_FILL_HANDLERS(DPSaan, 0x7f);
- ROP3_FILL_HANDLERS(DPSaa, 0x80);
- ROP3_FILL_HANDLERS(SPxDSxon, 0x81);
- ROP3_FILL_HANDLERS(DPSxna, 0x82);
- ROP3_FILL_HANDLERS(SPDSnoaxn, 0x83);
- ROP3_FILL_HANDLERS(SDPxna, 0x84);
- ROP3_FILL_HANDLERS(PDSPnoaxn, 0x85);
- ROP3_FILL_HANDLERS(DSPDSoaxx, 0x86);
- ROP3_FILL_HANDLERS(PDSaxn, 0x87);
- ROP3_FILL_HANDLERS(SDPSnaoxn, 0x89);
- ROP3_FILL_HANDLERS(DSPnoa, 0x8a);
- ROP3_FILL_HANDLERS(DSPDxoxn, 0x8b);
- ROP3_FILL_HANDLERS(SDPnoa, 0x8c);
- ROP3_FILL_HANDLERS(SDPSxoxn, 0x8d);
- ROP3_FILL_HANDLERS(SSDxPDxax, 0x8e);
- ROP3_FILL_HANDLERS(PDSanan, 0x8f);
- ROP3_FILL_HANDLERS(PDSxna, 0x90);
- ROP3_FILL_HANDLERS(SDPSnoaxn, 0x91);
- ROP3_FILL_HANDLERS(DPSDPoaxx, 0x92);
- ROP3_FILL_HANDLERS(SPDaxn, 0x93);
- ROP3_FILL_HANDLERS(PSDPSoaxx, 0x94);
- ROP3_FILL_HANDLERS(DPSaxn, 0x95);
- ROP3_FILL_HANDLERS(DPSxx, 0x96);
- ROP3_FILL_HANDLERS(PSDPSonoxx, 0x97);
- ROP3_FILL_HANDLERS(SDPSonoxn, 0x98);
- ROP3_FILL_HANDLERS(DPSnax, 0x9a);
- ROP3_FILL_HANDLERS(SDPSoaxn, 0x9b);
- ROP3_FILL_HANDLERS(SPDnax, 0x9c);
- ROP3_FILL_HANDLERS(DSPDoaxn, 0x9d);
- ROP3_FILL_HANDLERS(DSPDSaoxx, 0x9e);
- ROP3_FILL_HANDLERS(PDSxan, 0x9f);
- ROP3_FILL_HANDLERS(PDSPnaoxn, 0xa1);
- ROP3_FILL_HANDLERS(DPSnoa, 0xa2);
- ROP3_FILL_HANDLERS(DPSDxoxn, 0xa3);
- ROP3_FILL_HANDLERS(PDSPonoxn, 0xa4);
- ROP3_FILL_HANDLERS(DSPnax, 0xa6);
- ROP3_FILL_HANDLERS(PDSPoaxn, 0xa7);
- ROP3_FILL_HANDLERS(DPSoa, 0xa8);
- ROP3_FILL_HANDLERS(DPSoxn, 0xa9);
- ROP3_FILL_HANDLERS(DPSono, 0xab);
- ROP3_FILL_HANDLERS(SPDSxax, 0xac);
- ROP3_FILL_HANDLERS(DPSDaoxn, 0xad);
- ROP3_FILL_HANDLERS(DSPnao, 0xae);
- ROP3_FILL_HANDLERS(PDSnoa, 0xb0);
- ROP3_FILL_HANDLERS(PDSPxoxn, 0xb1);
- ROP3_FILL_HANDLERS(SSPxDSxox, 0xb2);
- ROP3_FILL_HANDLERS(SDPanan, 0xb3);
- ROP3_FILL_HANDLERS(PSDnax, 0xb4);
- ROP3_FILL_HANDLERS(DPSDoaxn, 0xb5);
- ROP3_FILL_HANDLERS(DPSDPaoxx, 0xb6);
- ROP3_FILL_HANDLERS(SDPxan, 0xb7);
- ROP3_FILL_HANDLERS(PSDPxax, 0xb8);
- ROP3_FILL_HANDLERS(DSPDaoxn, 0xb9);
- ROP3_FILL_HANDLERS(DPSnao, 0xba);
- ROP3_FILL_HANDLERS(SPDSanax, 0xbc);
- ROP3_FILL_HANDLERS(SDxPDxan, 0xbd);
- ROP3_FILL_HANDLERS(DPSxo, 0xbe);
- ROP3_FILL_HANDLERS(DPSano, 0xbf);
- ROP3_FILL_HANDLERS(SPDSnaoxn, 0xc1);
- ROP3_FILL_HANDLERS(SPDSonoxn, 0xc2);
- ROP3_FILL_HANDLERS(SPDnoa, 0xc4);
- ROP3_FILL_HANDLERS(SPDSxoxn, 0xc5);
- ROP3_FILL_HANDLERS(SDPnax, 0xc6);
- ROP3_FILL_HANDLERS(PSDPoaxn, 0xc7);
- ROP3_FILL_HANDLERS(SDPoa, 0xc8);
- ROP3_FILL_HANDLERS(SPDoxn, 0xc9);
- ROP3_FILL_HANDLERS(DPSDxax, 0xca);
- ROP3_FILL_HANDLERS(SPDSaoxn, 0xcb);
- ROP3_FILL_HANDLERS(SDPono, 0xcd);
- ROP3_FILL_HANDLERS(SDPnao, 0xce);
- ROP3_FILL_HANDLERS(PSDnoa, 0xd0);
- ROP3_FILL_HANDLERS(PSDPxoxn, 0xd1);
- ROP3_FILL_HANDLERS(PDSnax, 0xd2);
- ROP3_FILL_HANDLERS(SPDSoaxn, 0xd3);
- ROP3_FILL_HANDLERS(SSPxPDxax, 0xd4);
- ROP3_FILL_HANDLERS(DPSanan, 0xd5);
- ROP3_FILL_HANDLERS(PSDPSaoxx, 0xd6);
- ROP3_FILL_HANDLERS(DPSxan, 0xd7);
- ROP3_FILL_HANDLERS(PDSPxax, 0xd8);
- ROP3_FILL_HANDLERS(SDPSaoxn, 0xd9);
- ROP3_FILL_HANDLERS(DPSDanax, 0xda);
- ROP3_FILL_HANDLERS(SPxDSxan, 0xdb);
- ROP3_FILL_HANDLERS(SPDnao, 0xdc);
- ROP3_FILL_HANDLERS(SDPxo, 0xde);
- ROP3_FILL_HANDLERS(SDPano, 0xdf);
- ROP3_FILL_HANDLERS(PDSoa, 0xe0);
- ROP3_FILL_HANDLERS(PDSoxn, 0xe1);
- ROP3_FILL_HANDLERS(DSPDxax, 0xe2);
- ROP3_FILL_HANDLERS(PSDPaoxn, 0xe3);
- ROP3_FILL_HANDLERS(SDPSxax, 0xe4);
- ROP3_FILL_HANDLERS(PDSPaoxn, 0xe5);
- ROP3_FILL_HANDLERS(SDPSanax, 0xe6);
- ROP3_FILL_HANDLERS(SPxPDxan, 0xe7);
- ROP3_FILL_HANDLERS(SSPxDSxax, 0xe8);
- ROP3_FILL_HANDLERS(DSPDSanaxxn, 0xe9);
- ROP3_FILL_HANDLERS(DPSao, 0xea);
- ROP3_FILL_HANDLERS(DPSxno, 0xeb);
- ROP3_FILL_HANDLERS(SDPao, 0xec);
- ROP3_FILL_HANDLERS(SDPxno, 0xed);
- ROP3_FILL_HANDLERS(SDPnoo, 0xef);
- ROP3_FILL_HANDLERS(PDSono, 0xf1);
- ROP3_FILL_HANDLERS(PDSnao, 0xf2);
- ROP3_FILL_HANDLERS(PSDnao, 0xf4);
- ROP3_FILL_HANDLERS(PDSxo, 0xf6);
- ROP3_FILL_HANDLERS(PDSano, 0xf7);
- ROP3_FILL_HANDLERS(PDSao, 0xf8);
- ROP3_FILL_HANDLERS(PDSxno, 0xf9);
- ROP3_FILL_HANDLERS(DPSnoo, 0xfb);
- ROP3_FILL_HANDLERS(PSDnoo, 0xfd);
- ROP3_FILL_HANDLERS(DPSoo, 0xfe);
-
- for (i = 0; i < ROP3_NUM_OPS; i++) {
- rop3_test_handlers_32[i]();
- rop3_test_handlers_16[i]();
- }
-}
-
-void do_rop3_with_pattern(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos,
- pixman_image_t *p, SpicePoint *pat_pos)
-{
- int bpp;
-
- bpp = spice_pixman_image_get_bpp(d);
- ASSERT (bpp == spice_pixman_image_get_bpp(s));
- ASSERT (bpp == spice_pixman_image_get_bpp(p));
-
- if (bpp == 32) {
- rop3_with_pattern_handlers_32[rop3](d, s, src_pos, p, pat_pos);
- } else {
- rop3_with_pattern_handlers_16[rop3](d, s, src_pos, p, pat_pos);
- }
-}
-
-void do_rop3_with_color(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos,
- uint32_t rgb)
-{
- int bpp;
-
- bpp = spice_pixman_image_get_bpp(d);
- ASSERT (bpp == spice_pixman_image_get_bpp(s));
-
- if (bpp == 32) {
- rop3_with_color_handlers_32[rop3](d, s, src_pos, rgb);
- } else {
- rop3_with_color_handlers_16[rop3](d, s, src_pos, rgb);
- }
-}
diff --git a/common/rop3.h b/common/rop3.h
deleted file mode 100644
index cbfa940..0000000
--- a/common/rop3.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_ROP3
-#define _H_ROP3
-
-#include <stdint.h>
-
-#include "draw.h"
-#include "pixman_utils.h"
-
-void do_rop3_with_pattern(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos,
- pixman_image_t *p, SpicePoint *pat_pos);
-void do_rop3_with_color(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos,
- uint32_t rgb);
-
-void rop3_init(void);
-#endif
-
diff --git a/common/ssl_verify.c b/common/ssl_verify.c
deleted file mode 100644
index b19a323..0000000
--- a/common/ssl_verify.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2011 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "mem.h"
-#include "ssl_verify.h"
-
-#ifndef WIN32
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-#include <ctype.h>
-#include <string.h>
-
-#ifndef SPICE_DEBUG
-# define SPICE_DEBUG(format, ...)
-#endif
-
-#ifdef WIN32
-static int inet_aton(const char* ip, struct in_addr* in_addr)
-{
- unsigned long addr = inet_addr(ip);
-
- if (addr == INADDR_NONE) {
- return 0;
- }
- in_addr->S_un.S_addr = addr;
- return 1;
-}
-#endif
-
-static int verify_pubkey(X509* cert, const char *key, size_t key_size)
-{
- EVP_PKEY* cert_pubkey = NULL;
- EVP_PKEY* orig_pubkey = NULL;
- BIO* bio = NULL;
- int ret = 0;
-
- if (!key || key_size == 0)
- return 0;
-
- if (!cert) {
- SPICE_DEBUG("warning: no cert!");
- return 0;
- }
-
- cert_pubkey = X509_get_pubkey(cert);
- if (!cert_pubkey) {
- SPICE_DEBUG("warning: reading public key from certificate failed");
- goto finish;
- }
-
- bio = BIO_new_mem_buf((void*)key, key_size);
- if (!bio) {
- SPICE_DEBUG("creating BIO failed");
- goto finish;
- }
-
- orig_pubkey = d2i_PUBKEY_bio(bio, NULL);
- if (!orig_pubkey) {
- SPICE_DEBUG("reading pubkey from bio failed");
- goto finish;
- }
-
- ret = EVP_PKEY_cmp(orig_pubkey, cert_pubkey);
-
- if (ret == 1) {
- SPICE_DEBUG("public keys match");
- } else if (ret == 0) {
- SPICE_DEBUG("public keys mismatch");
- } else {
- SPICE_DEBUG("public keys types mismatch");
- }
-
-finish:
- if (bio)
- BIO_free(bio);
-
- if (orig_pubkey)
- EVP_PKEY_free(orig_pubkey);
-
- if (cert_pubkey)
- EVP_PKEY_free(cert_pubkey);
-
- return ret;
-}
-
-/* from gnutls
- * compare hostname against certificate, taking account of wildcards
- * return 1 on success or 0 on error
- *
- * note: certnamesize is required as X509 certs can contain embedded NULs in
- * the strings such as CN or subjectAltName
- */
-static int _gnutls_hostname_compare(const char *certname,
- size_t certnamesize, const char *hostname)
-{
- /* find the first different character */
- for (; *certname && *hostname && toupper (*certname) == toupper (*hostname);
- certname++, hostname++, certnamesize--)
- ;
-
- /* the strings are the same */
- if (certnamesize == 0 && *hostname == '\0')
- return 1;
-
- if (*certname == '*')
- {
- /* a wildcard certificate */
-
- certname++;
- certnamesize--;
-
- while (1)
- {
- /* Use a recursive call to allow multiple wildcards */
- if (_gnutls_hostname_compare (certname, certnamesize, hostname))
- return 1;
-
- /* wildcards are only allowed to match a single domain
- component or component fragment */
- if (*hostname == '\0' || *hostname == '.')
- break;
- hostname++;
- }
-
- return 0;
- }
-
- return 0;
-}
-
-/**
- * From gnutls and spice red_peer.c
- * TODO: switch to gnutls and get rid of this
- *
- * This function will check if the given certificate's subject matches
- * the given hostname. This is a basic implementation of the matching
- * described in RFC2818 (HTTPS), which takes into account wildcards,
- * and the DNSName/IPAddress subject alternative name PKIX extension.
- *
- * Returns: 1 for a successful match, and 0 on failure.
- **/
-static int verify_hostname(X509* cert, const char *hostname)
-{
- GENERAL_NAMES* subject_alt_names;
- int found_dns_name = 0;
- struct in_addr addr;
- int addr_len = 0;
- int cn_match = 0;
-
- if (!cert) {
- SPICE_DEBUG("warning: no cert!");
- return 0;
- }
-
- // only IpV4 supported
- if (inet_aton(hostname, &addr)) {
- addr_len = sizeof(struct in_addr);
- }
-
- /* try matching against:
- * 1) a DNS name as an alternative name (subjectAltName) extension
- * in the certificate
- * 2) the common name (CN) in the certificate
- *
- * either of these may be of the form: *.domain.tld
- *
- * only try (2) if there is no subjectAltName extension of
- * type dNSName
- */
-
- /* Check through all included subjectAltName extensions, comparing
- * against all those of type dNSName.
- */
- subject_alt_names = (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
-
- if (subject_alt_names) {
- int num_alts = sk_GENERAL_NAME_num(subject_alt_names);
- int i;
- for (i = 0; i < num_alts; i++) {
- const GENERAL_NAME* name = sk_GENERAL_NAME_value(subject_alt_names, i);
- if (name->type == GEN_DNS) {
- found_dns_name = 1;
- if (_gnutls_hostname_compare((char *)ASN1_STRING_data(name->d.dNSName),
- ASN1_STRING_length(name->d.dNSName),
- hostname)) {
- SPICE_DEBUG("alt name match=%s", ASN1_STRING_data(name->d.dNSName));
- GENERAL_NAMES_free(subject_alt_names);
- return 1;
- }
- } else if (name->type == GEN_IPADD) {
- int alt_ip_len = ASN1_STRING_length(name->d.iPAddress);
- found_dns_name = 1;
- if ((addr_len == alt_ip_len)&&
- !memcmp(ASN1_STRING_data(name->d.iPAddress), &addr, addr_len)) {
- SPICE_DEBUG("alt name IP match=%s",
- inet_ntoa(*((struct in_addr*)ASN1_STRING_data(name->d.dNSName))));
- GENERAL_NAMES_free(subject_alt_names);
- return 1;
- }
- }
- }
- GENERAL_NAMES_free(subject_alt_names);
- }
-
- if (found_dns_name) {
- SPICE_DEBUG("warning: SubjectAltName mismatch");
- return 0;
- }
-
- /* extracting commonNames */
- X509_NAME* subject = X509_get_subject_name(cert);
- if (subject) {
- int pos = -1;
- X509_NAME_ENTRY* cn_entry;
- ASN1_STRING* cn_asn1;
-
- while ((pos = X509_NAME_get_index_by_NID(subject, NID_commonName, pos)) != -1) {
- cn_entry = X509_NAME_get_entry(subject, pos);
- if (!cn_entry) {
- continue;
- }
- cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry);
- if (!cn_asn1) {
- continue;
- }
-
- if (_gnutls_hostname_compare((char*)ASN1_STRING_data(cn_asn1),
- ASN1_STRING_length(cn_asn1),
- hostname)) {
- SPICE_DEBUG("common name match=%s", (char*)ASN1_STRING_data(cn_asn1));
- cn_match = 1;
- break;
- }
- }
- }
-
- if (!cn_match) {
- SPICE_DEBUG("warning: common name mismatch");
- }
-
- return cn_match;
-}
-
-static X509_NAME* subject_to_x509_name(const char *subject, int *nentries)
-{
- X509_NAME* in_subject;
- const char *p;
- char *key, *val, *k, *v = NULL;
- int escape;
- enum {
- KEY,
- VALUE
- } state;
-
- key = (char*)alloca(strlen(subject));
- val = (char*)alloca(strlen(subject));
- in_subject = X509_NAME_new();
-
- if (!in_subject || !key || !val) {
- SPICE_DEBUG("failed to allocate");
- return NULL;
- }
-
- *nentries = 0;
-
- k = key;
- state = KEY;
- for (p = subject;; ++p) {
- escape = 0;
- if (*p == '\\') {
- ++p;
- if (*p != '\\' && *p != ',') {
- SPICE_DEBUG("Invalid character after \\");
- goto fail;
- }
- escape = 1;
- }
-
- switch (state) {
- case KEY:
- if (*p == 0) {
- if (k == key) /* empty key */
- goto success;
- goto fail;
- } else if (*p == '=' && !escape) {
- state = VALUE;
- *k = 0;
- v = val;
- } else
- *k++ = *p;
- break;
- case VALUE:
- if (*p == 0 || (*p == ',' && !escape)) {
- if (v == val) /* empty value */
- goto fail;
-
- *v = 0;
-
- if (!X509_NAME_add_entry_by_txt(in_subject, key,
- MBSTRING_UTF8,
- (const unsigned char*)val,
- strlen(val), -1, 0)) {
- SPICE_DEBUG("warning: failed to add entry %s=%s to X509_NAME",
- key, val);
- goto fail;
- }
- *nentries += 1;
-
- if (*p == 0)
- goto success;
-
- state = KEY;
- k = key;
- } else
- *v++ = *p;
- }
- }
-
-success:
- return in_subject;
-
-fail:
- if (in_subject)
- X509_NAME_free(in_subject);
-
- return NULL;
-}
-
-static int verify_subject(X509* cert, SpiceOpenSSLVerify* verify)
-{
- X509_NAME *cert_subject = NULL;
- int ret;
- int in_entries;
-
- if (!cert) {
- SPICE_DEBUG("warning: no cert!");
- return 0;
- }
-
- cert_subject = X509_get_subject_name(cert);
- if (!cert_subject) {
- SPICE_DEBUG("warning: reading certificate subject failed");
- return 0;
- }
-
- if (!verify->in_subject) {
- verify->in_subject = subject_to_x509_name(verify->subject, &in_entries);
- if (!verify->in_subject) {
- SPICE_DEBUG("warning: no in_subject!");
- return 0;
- }
- }
-
- /* Note: this check is redundant with the pre-condition in X509_NAME_cmp */
- if (X509_NAME_entry_count(cert_subject) != in_entries) {
- SPICE_DEBUG("subject mismatch: #entries cert=%d, input=%d",
- X509_NAME_entry_count(cert_subject), in_entries);
- return 0;
- }
-
- ret = X509_NAME_cmp(cert_subject, verify->in_subject);
-
- if (ret == 0) {
- SPICE_DEBUG("subjects match");
- } else {
- SPICE_DEBUG("subjects mismatch");
- }
-
- return !ret;
-}
-
-static int openssl_verify(int preverify_ok, X509_STORE_CTX *ctx)
-{
- int depth;
- SpiceOpenSSLVerify *v;
- SSL *ssl;
- X509* cert;
-
- ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
- v = (SpiceOpenSSLVerify*)SSL_get_app_data(ssl);
-
- depth = X509_STORE_CTX_get_error_depth(ctx);
- if (depth > 0) {
- if (!preverify_ok) {
- SPICE_DEBUG("openssl verify failed at depth=%d", depth);
- v->all_preverify_ok = 0;
- return 0;
- } else
- return 1;
- }
-
- /* depth == 0 */
- cert = X509_STORE_CTX_get_current_cert(ctx);
- if (!cert) {
- SPICE_DEBUG("failed to get server certificate");
- return 0;
- }
-
- if (v->verifyop & SPICE_SSL_VERIFY_OP_PUBKEY &&
- verify_pubkey(cert, v->pubkey, v->pubkey_size))
- return 1;
-
- if (!v->all_preverify_ok || !preverify_ok)
- return 0;
-
- if (v->verifyop & SPICE_SSL_VERIFY_OP_HOSTNAME &&
- verify_hostname(cert, v->hostname))
- return 1;
-
- if (v->verifyop & SPICE_SSL_VERIFY_OP_SUBJECT &&
- verify_subject(cert, v))
- return 1;
-
- return 0;
-}
-
-SpiceOpenSSLVerify* spice_openssl_verify_new(SSL *ssl, SPICE_SSL_VERIFY_OP verifyop,
- const char *hostname,
- const char *pubkey, size_t pubkey_size,
- const char *subject)
-{
- SpiceOpenSSLVerify *v;
-
- if (!verifyop)
- return NULL;
-
- v = spice_new0(SpiceOpenSSLVerify, 1);
-
- v->ssl = ssl;
- v->verifyop = verifyop;
- v->hostname = spice_strdup(hostname);
- v->pubkey = (char*)spice_memdup(pubkey, pubkey_size);
- v->pubkey_size = pubkey_size;
- v->subject = spice_strdup(subject);
-
- v->all_preverify_ok = 1;
-
- SSL_set_app_data(ssl, v);
- SSL_set_verify(ssl,
- SSL_VERIFY_PEER, openssl_verify);
-
- return v;
-}
-
-void spice_openssl_verify_free(SpiceOpenSSLVerify* verify)
-{
- if (!verify)
- return;
-
- free(verify->pubkey);
- free(verify->subject);
- free(verify->hostname);
-
- if (verify->in_subject)
- X509_NAME_free(verify->in_subject);
-
- if (verify->ssl)
- SSL_set_app_data(verify->ssl, NULL);
- free(verify);
-}
diff --git a/common/ssl_verify.h b/common/ssl_verify.h
deleted file mode 100644
index 6922c56..0000000
--- a/common/ssl_verify.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2011 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __SSL_VERIFY_H
-#define __SSL_VERIFY_H
-
-#include "ring.h"
-
-#include <openssl/rsa.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#ifdef X509_NAME
-/* wincrypt.h has already a different define... */
-#undef X509_NAME
-#endif
-#include <openssl/x509v3.h>
-
-typedef enum {
- SPICE_SSL_VERIFY_OP_NONE = 0,
- SPICE_SSL_VERIFY_OP_PUBKEY = (1 << 0),
- SPICE_SSL_VERIFY_OP_HOSTNAME = (1 << 1),
- SPICE_SSL_VERIFY_OP_SUBJECT = (1 << 2),
-} SPICE_SSL_VERIFY_OP;
-
-typedef struct {
- SSL *ssl;
- SPICE_SSL_VERIFY_OP verifyop;
- int all_preverify_ok;
- char *hostname;
- char *pubkey;
- size_t pubkey_size;
- char *subject;
- X509_NAME *in_subject;
-} SpiceOpenSSLVerify;
-
-SpiceOpenSSLVerify* spice_openssl_verify_new(SSL *ssl, SPICE_SSL_VERIFY_OP verifyop,
- const char *hostname,
- const char *pubkey, size_t pubkey_size,
- const char *subject);
-void spice_openssl_verify_free(SpiceOpenSSLVerify* verify);
-
-#endif
diff --git a/common/sw_canvas.c b/common/sw_canvas.c
deleted file mode 100644
index 34ca910..0000000
--- a/common/sw_canvas.c
+++ /dev/null
@@ -1,1321 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <math.h>
-#include "sw_canvas.h"
-#define CANVAS_USE_PIXMAN
-#define CANVAS_SINGLE_INSTANCE
-#include "canvas_base.c"
-#include "rect.h"
-#include "region.h"
-#include "pixman_utils.h"
-
-typedef struct SwCanvas SwCanvas;
-
-struct SwCanvas {
- CanvasBase base;
- uint32_t *private_data;
- int private_data_size;
- pixman_image_t *image;
-};
-
-static pixman_image_t *canvas_get_pixman_brush(SwCanvas *canvas,
- SpiceBrush *brush)
-{
- switch (brush->type) {
- case SPICE_BRUSH_TYPE_SOLID: {
- uint32_t color = brush->u.color;
- pixman_color_t c;
-
- c.blue = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
- color >>= canvas->base.color_shift;
- c.green = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
- color >>= canvas->base.color_shift;
- c.red = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
- c.alpha = 0xffff;
-
- return pixman_image_create_solid_fill(&c);
- }
- case SPICE_BRUSH_TYPE_PATTERN: {
- SwCanvas *surface_canvas;
- pixman_image_t* surface;
- pixman_transform_t t;
-
- surface_canvas = (SwCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat);
- if (surface_canvas) {
- surface = surface_canvas->image;
- surface = pixman_image_ref(surface);
- } else {
- surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE);
- }
- pixman_transform_init_translate(&t,
- pixman_int_to_fixed(-brush->u.pattern.pos.x),
- pixman_int_to_fixed(-brush->u.pattern.pos.y));
- pixman_image_set_transform(surface, &t);
- pixman_image_set_repeat(surface, PIXMAN_REPEAT_NORMAL);
- return surface;
- }
- case SPICE_BRUSH_TYPE_NONE:
- return NULL;
- default:
- spice_warn_if_reached();
- return NULL;
- }
- return NULL;
-}
-
-static pixman_image_t *get_image(SpiceCanvas *canvas)
-{
- SwCanvas *sw_canvas = (SwCanvas *)canvas;
-
- pixman_image_ref(sw_canvas->image);
-
- return sw_canvas->image;
-}
-
-static void copy_region(SpiceCanvas *spice_canvas,
- pixman_region32_t *dest_region,
- int dx, int dy)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *dest_rects;
- int n_rects;
- int i, j, end_line;
-
- dest_rects = pixman_region32_rectangles(dest_region, &n_rects);
-
- if (dy > 0) {
- if (dx >= 0) {
- /* south-east: copy x and y in reverse order */
- for (i = n_rects - 1; i >= 0; i--) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
- dest_rects[i].x2 - dest_rects[i].x1,
- dest_rects[i].y2 - dest_rects[i].y1,
- dest_rects[i].x1, dest_rects[i].y1);
- }
- } else {
- /* south-west: Copy y in reverse order, but x in forward order */
- i = n_rects - 1;
-
- while (i >= 0) {
- /* Copy all rects with same y in forward order */
- for (end_line = i - 1;
- end_line >= 0 && dest_rects[end_line].y1 == dest_rects[i].y1;
- end_line--) {
- }
- for (j = end_line + 1; j <= i; j++) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
- dest_rects[j].x2 - dest_rects[j].x1,
- dest_rects[j].y2 - dest_rects[j].y1,
- dest_rects[j].x1, dest_rects[j].y1);
- }
- i = end_line;
- }
- }
- } else {
- if (dx > 0) {
- /* north-east: copy y in forward order, but x in reverse order */
- i = 0;
-
- while (i < n_rects) {
- /* Copy all rects with same y in reverse order */
- for (end_line = i;
- end_line < n_rects && dest_rects[end_line].y1 == dest_rects[i].y1;
- end_line++) {
- }
- for (j = end_line - 1; j >= i; j--) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
- dest_rects[j].x2 - dest_rects[j].x1,
- dest_rects[j].y2 - dest_rects[j].y1,
- dest_rects[j].x1, dest_rects[j].y1);
- }
- i = end_line;
- }
- } else {
- /* north-west: Copy x and y in forward order */
- for (i = 0; i < n_rects; i++) {
- spice_pixman_copy_rect(canvas->image,
- dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
- dest_rects[i].x2 - dest_rects[i].x1,
- dest_rects[i].y2 - dest_rects[i].y1,
- dest_rects[i].x1, dest_rects[i].y1);
- }
- }
- }
-}
-
-static void fill_solid_spans(SpiceCanvas *spice_canvas,
- SpicePoint *points,
- int *widths,
- int n_spans,
- uint32_t color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_spans; i++) {
- spice_pixman_fill_rect(canvas->image,
- points[i].x, points[i].y,
- widths[i],
- 1,
- color);
- }
-}
-
-static void fill_solid_rects(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- uint32_t color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_fill_rect(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- color);
- }
-}
-
-static void fill_solid_rects_rop(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- uint32_t color,
- SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_fill_rect_rop(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- color, rop);
- }
-}
-
-static void __fill_tiled_rects(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_tile_rect(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- tile, offset_x, offset_y);
- }
-}
-
-static void fill_tiled_rects(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y)
-{
- __fill_tiled_rects(spice_canvas, rects, n_rects, tile, offset_x, offset_y);
-}
-
-static void fill_tiled_rects_from_surface(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __fill_tiled_rects(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x,
- offset_y);
-}
-
-static void __fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- int i;
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_tile_rect_rop(canvas->image,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- tile, offset_x, offset_y,
- rop);
- }
-}
-static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- pixman_image_t *tile,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- __fill_tiled_rects_rop(spice_canvas, rects, n_rects, tile, offset_x, offset_y, rop);
-}
-
-static void fill_tiled_rects_rop_from_surface(SpiceCanvas *spice_canvas,
- pixman_box32_t *rects,
- int n_rects,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __fill_tiled_rects_rop(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x,
- offset_y, rop);
-}
-
-/* Some pixman implementations of OP_OVER on xRGB32 sets
- the high bit to 0xff (which is the right value if the
- destination was ARGB32, and it should be ignored for
- xRGB32. However, this fills our alpha bits with
- data that is not wanted or expected by windows, and its
- causing us to send rgba images rather than rgb images to
- the client. So, we manually clear these bytes. */
-static void clear_dest_alpha(pixman_image_t *dest,
- int x, int y,
- int width, int height)
-{
- uint32_t *data;
- int stride;
- int w, h;
-
- w = pixman_image_get_width(dest);
- h = pixman_image_get_height(dest);
-
- if (x + width <= 0 || x >= w ||
- y + height <= 0 || y >= h ||
- width == 0 || height == 0) {
- return;
- }
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (x + width > w) {
- width = w - x;
- }
-
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (y + height > h) {
- height = h - y;
- }
-
- stride = pixman_image_get_stride(dest);
- data = (uint32_t *) (
- (uint8_t *)pixman_image_get_data(dest) + y * stride + 4 * x);
-
- if ((*data & 0xff000000U) == 0xff000000U) {
- spice_pixman_fill_rect_rop(dest,
- x, y, width, height,
- 0x00ffffff, SPICE_ROP_AND);
- }
-}
-
-static void __blit_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *rects;
- int n_rects, i;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- int src_x, src_y, dest_x, dest_y, width, height;
-
- dest_x = rects[i].x1;
- dest_y = rects[i].y1;
- width = rects[i].x2 - rects[i].x1;
- height = rects[i].y2 - rects[i].y1;
-
- src_x = rects[i].x1 - offset_x;
- src_y = rects[i].y1 - offset_y;
-
- spice_pixman_blit(canvas->image,
- src_image,
- src_x, src_y,
- dest_x, dest_y,
- width, height);
- }
-}
-
-static void blit_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y)
-{
- __blit_image(spice_canvas, region, src_image, offset_x, offset_y);
-}
-
-static void blit_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __blit_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y);
-}
-
-static void __blit_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *rects;
- int n_rects, i;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- int src_x, src_y, dest_x, dest_y, width, height;
-
- dest_x = rects[i].x1;
- dest_y = rects[i].y1;
- width = rects[i].x2 - rects[i].x1;
- height = rects[i].y2 - rects[i].y1;
-
- src_x = rects[i].x1 - offset_x;
- src_y = rects[i].y1 - offset_y;
-
- spice_pixman_blit_rop(canvas->image,
- src_image,
- src_x, src_y,
- dest_x, dest_y,
- width, height, rop);
- }
-}
-
-static void blit_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- __blit_image_rop(spice_canvas, region, src_image, offset_x, offset_y, rop);
-}
-
-static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y,
- SpiceROP rop)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __blit_image_rop(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, rop);
-}
-
-
-
-static void __scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- pixman_image_set_clip_region32(canvas->image, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- spice_return_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
- scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
- PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, canvas->image,
- 0, 0, /* src */
- 0, 0, /* mask */
- dest_x, dest_y, /* dst */
- dest_width, dest_height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- pixman_image_set_clip_region32(canvas->image, NULL);
-}
-
-static void scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode)
-{
- __scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, dest_y,
- dest_width,dest_height,scale_mode);
-}
-
-static void scale_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width,
- src_height, dest_x, dest_y, dest_width,dest_height,scale_mode);
-}
-
-static void __scale_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_image_t *scaled;
- pixman_box32_t *rects;
- int n_rects, i;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- scaled = pixman_image_create_bits(spice_pixman_image_get_format(src),
- dest_width,
- dest_height,
- NULL, 0);
-
- pixman_region32_translate(region, -dest_x, -dest_y);
- pixman_image_set_clip_region32(scaled, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- spice_return_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
- scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
- PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, scaled,
- 0, 0, /* src */
- 0, 0, /* mask */
- 0, 0, /* dst */
- dest_width,
- dest_height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- /* Translate back */
- pixman_region32_translate(region, dest_x, dest_y);
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_blit_rop(canvas->image,
- scaled,
- rects[i].x1 - dest_x,
- rects[i].y1 - dest_y,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- rop);
- }
-
- pixman_image_unref(scaled);
-}
-
-static void scale_image_rop(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop)
-{
- __scale_image_rop(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
- dest_y, dest_width, dest_height, scale_mode, rop);
-}
-
-static void scale_image_rop_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode, SpiceROP rop)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __scale_image_rop(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width,
- src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop);
-}
-
-static pixman_image_t *canvas_get_as_surface(SwCanvas *canvas,
- int with_alpha)
-{
- pixman_image_t *target;
-
- if (with_alpha &&
- canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
- target = pixman_image_create_bits(PIXMAN_a8r8g8b8,
- pixman_image_get_width(canvas->image),
- pixman_image_get_height(canvas->image),
- pixman_image_get_data(canvas->image),
- pixman_image_get_stride(canvas->image));
- } else {
- target = pixman_image_ref(canvas->image);
- }
-
- return target;
-}
-
-static void __blend_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_image_t *mask, *dest;
-
- dest = canvas_get_as_surface(canvas, dest_has_alpha);
-
- pixman_image_set_clip_region32(dest, region);
-
- mask = NULL;
- if (overall_alpha != 0xff) {
- pixman_color_t color = { 0 };
- color.alpha = overall_alpha * 0x101;
- mask = pixman_image_create_solid_fill(&color);
- }
-
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-
- pixman_image_composite32(PIXMAN_OP_OVER,
- src, mask, dest,
- src_x, src_y, /* src */
- 0, 0, /* mask */
- dest_x, dest_y, /* dst */
- width,
- height);
-
- if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
- !dest_has_alpha) {
- clear_dest_alpha(dest, dest_x, dest_y, width, height);
- }
-
- if (mask) {
- pixman_image_unref(mask);
- }
-
- pixman_image_set_clip_region32(dest, NULL);
- pixman_image_unref(dest);
-}
-
-static void blend_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
-{
- __blend_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y,
- dest_x, dest_y, width, height,
- overall_alpha);
-}
-
-static void blend_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- SpiceCanvas *surface_canvas,
- int src_has_alpha,
- int src_x, int src_y,
- int dest_x, int dest_y,
- int width, int height,
- int overall_alpha)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- pixman_image_t *src;
-
- src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha);
- __blend_image(spice_canvas, region, dest_has_alpha,
- src, src_x, src_y,
- dest_x, dest_y,
- width, height, overall_alpha);
- pixman_image_unref(src);
-}
-
-static void __blend_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_image_t *mask, *dest;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- dest = canvas_get_as_surface(canvas, dest_has_alpha);
-
- pixman_image_set_clip_region32(dest, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- mask = NULL;
- if (overall_alpha != 0xff) {
- pixman_color_t color = { 0 };
- color.alpha = overall_alpha * 0x101;
- mask = pixman_image_create_solid_fill(&color);
- }
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- spice_return_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
- scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
- pixman_image_set_filter(src,
- (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
- PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_OVER,
- src, mask, dest,
- 0, 0, /* src */
- 0, 0, /* mask */
- dest_x, dest_y, /* dst */
- dest_width, dest_height);
-
- if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
- !dest_has_alpha) {
- clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height);
- }
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- if (mask) {
- pixman_image_unref(mask);
- }
-
- pixman_image_set_clip_region32(dest, NULL);
- pixman_image_unref(dest);
-}
-
-static void blend_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha)
-{
- __blend_scale_image(spice_canvas, region, dest_has_alpha,
- src, src_x, src_y, src_width, src_height,
- dest_x, dest_y, dest_width, dest_height,
- scale_mode, overall_alpha);
-}
-
-static void blend_scale_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- int dest_has_alpha,
- SpiceCanvas *surface_canvas,
- int src_has_alpha,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- int scale_mode,
- int overall_alpha)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- pixman_image_t *src;
-
- src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha);
- __blend_scale_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, src_width,
- src_height, dest_x, dest_y, dest_width, dest_height, scale_mode,
- overall_alpha);
- pixman_image_unref(src);
-}
-
-static void __colorkey_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- uint32_t transparent_color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_box32_t *rects;
- int n_rects, i;
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- int src_x, src_y, dest_x, dest_y, width, height;
-
- dest_x = rects[i].x1;
- dest_y = rects[i].y1;
- width = rects[i].x2 - rects[i].x1;
- height = rects[i].y2 - rects[i].y1;
-
- src_x = rects[i].x1 - offset_x;
- src_y = rects[i].y1 - offset_y;
-
- spice_pixman_blit_colorkey(canvas->image,
- src_image,
- src_x, src_y,
- dest_x, dest_y,
- width, height,
- transparent_color);
- }
-}
-
-static void colorkey_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src_image,
- int offset_x, int offset_y,
- uint32_t transparent_color)
-{
- __colorkey_image(spice_canvas, region, src_image, offset_x, offset_y, transparent_color);
-}
-
-static void colorkey_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int offset_x, int offset_y,
- uint32_t transparent_color)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __colorkey_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y,
- transparent_color);
-}
-
-static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_transform_t transform;
- pixman_image_t *scaled;
- pixman_box32_t *rects;
- int n_rects, i;
- pixman_fixed_t fsx, fsy;
-
- fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width;
- fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height;
-
- scaled = pixman_image_create_bits(spice_pixman_image_get_format (src),
- dest_width,
- dest_height,
- NULL, 0);
-
- pixman_region32_translate(region, -dest_x, -dest_y);
- pixman_image_set_clip_region32(scaled, region);
-
- pixman_transform_init_scale(&transform, fsx, fsy);
- pixman_transform_translate(&transform, NULL,
- pixman_int_to_fixed (src_x),
- pixman_int_to_fixed (src_y));
-
- pixman_image_set_transform(src, &transform);
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
- pixman_image_set_filter(src,
- PIXMAN_FILTER_NEAREST,
- NULL, 0);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, scaled,
- 0, 0, /* src */
- 0, 0, /* mask */
- 0, 0, /* dst */
- dest_width,
- dest_height);
-
- pixman_transform_init_identity(&transform);
- pixman_image_set_transform(src, &transform);
-
- /* Translate back */
- pixman_region32_translate(region, dest_x, dest_y);
-
- rects = pixman_region32_rectangles(region, &n_rects);
-
- for (i = 0; i < n_rects; i++) {
- spice_pixman_blit_colorkey(canvas->image,
- scaled,
- rects[i].x1 - dest_x,
- rects[i].y1 - dest_y,
- rects[i].x1, rects[i].y1,
- rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- transparent_color);
- }
-
- pixman_image_unref(scaled);
-}
-
-static void colorkey_scale_image(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- pixman_image_t *src,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color)
-{
- __colorkey_scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
- dest_y, dest_width, dest_height, transparent_color);
-}
-
-static void colorkey_scale_image_from_surface(SpiceCanvas *spice_canvas,
- pixman_region32_t *region,
- SpiceCanvas *surface_canvas,
- int src_x, int src_y,
- int src_width, int src_height,
- int dest_x, int dest_y,
- int dest_width, int dest_height,
- uint32_t transparent_color)
-{
- SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
- __colorkey_scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y,
- src_width, src_height, dest_x, dest_y, dest_width, dest_height,
- transparent_color);
-}
-
-static void canvas_put_image(SpiceCanvas *spice_canvas,
-#ifdef WIN32
- HDC dc,
-#endif
- const SpiceRect *dest, const uint8_t *src_data,
- uint32_t src_width, uint32_t src_height, int src_stride,
- const QRegion *clip)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_image_t *src;
- uint32_t dest_width;
- uint32_t dest_height;
- double sx, sy;
- pixman_transform_t transform;
-
- src = pixman_image_create_bits(PIXMAN_x8r8g8b8,
- src_width,
- src_height,
- (uint32_t*)src_data,
- src_stride);
-
-
- if (clip) {
- pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip);
- }
-
- dest_width = dest->right - dest->left;
- dest_height = dest->bottom - dest->top;
-
- if (dest_width != src_width || dest_height != src_height) {
- sx = (double)(src_width) / (dest_width);
- sy = (double)(src_height) / (dest_height);
-
- pixman_transform_init_scale(&transform,
- pixman_double_to_fixed(sx),
- pixman_double_to_fixed(sy));
- pixman_image_set_transform(src, &transform);
- pixman_image_set_filter(src,
- PIXMAN_FILTER_NEAREST,
- NULL, 0);
- }
-
- pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src, NULL, canvas->image,
- 0, 0, /* src */
- 0, 0, /* mask */
- dest->left, dest->top, /* dst */
- dest_width, dest_height);
-
-
- if (clip) {
- pixman_image_set_clip_region32(canvas->image, NULL);
- }
- pixman_image_unref(src);
-}
-
-
-static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox,
- SpiceClip *clip, SpiceText *text)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_region32_t dest_region;
- pixman_image_t *str_mask, *brush;
- SpiceString *str;
- SpicePoint pos = { 0, };
- int depth;
-
- pixman_region32_init_rect(&dest_region,
- bbox->left, bbox->top,
- bbox->right - bbox->left,
- bbox->bottom - bbox->top);
-
- canvas_clip_pixman(&canvas->base, &dest_region, clip);
-
- if (!pixman_region32_not_empty(&dest_region)) {
- touch_brush(&canvas->base, &text->fore_brush);
- touch_brush(&canvas->base, &text->back_brush);
- pixman_region32_fini(&dest_region);
- return;
- }
-
- if (!rect_is_empty(&text->back_area)) {
- pixman_region32_t back_region;
-
- /* Nothing else makes sense for text and we should deprecate it
- * and actually it means OVER really */
- spice_return_if_fail(text->fore_mode == SPICE_ROPD_OP_PUT);
-
- pixman_region32_init_rect(&back_region,
- text->back_area.left,
- text->back_area.top,
- text->back_area.right - text->back_area.left,
- text->back_area.bottom - text->back_area.top);
-
- pixman_region32_intersect(&back_region, &back_region, &dest_region);
-
- if (pixman_region32_not_empty(&back_region)) {
- draw_brush(spice_canvas, &back_region, &text->back_brush, SPICE_ROP_COPY);
- }
-
- pixman_region32_fini(&back_region);
- }
- str = (SpiceString *)SPICE_GET_ADDRESS(text->str);
-
- if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
- depth = 1;
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
- depth = 4;
- } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) {
- spice_warning("untested path A8 glyphs");
- depth = 8;
- } else {
- spice_warning("unsupported path vector glyphs");
- pixman_region32_fini (&dest_region);
- return;
- }
-
- brush = canvas_get_pixman_brush(canvas, &text->fore_brush);
-
- str_mask = canvas_get_str_mask(&canvas->base, str, depth, &pos);
- if (brush) {
- pixman_image_set_clip_region32(canvas->image, &dest_region);
-
- pixman_image_composite32(PIXMAN_OP_OVER,
- brush,
- str_mask,
- canvas->image,
- 0, 0,
- 0, 0,
- pos.x, pos.y,
- pixman_image_get_width(str_mask),
- pixman_image_get_height(str_mask));
- if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
- clear_dest_alpha(canvas->image, pos.x, pos.y,
- pixman_image_get_width(str_mask),
- pixman_image_get_height(str_mask));
- }
- pixman_image_unref(brush);
-
- pixman_image_set_clip_region32(canvas->image, NULL);
- }
- pixman_image_unref(str_mask);
- pixman_region32_fini(&dest_region);
-}
-
-static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest,
- int dest_stride, const SpiceRect *area)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- pixman_image_t* surface;
- uint8_t *src;
- int src_stride;
- uint8_t *dest_end;
- int bpp;
-
- spice_return_if_fail(canvas && area);
-
- surface = canvas->image;
-
- bpp = spice_pixman_image_get_bpp(surface) / 8;
-
- src_stride = pixman_image_get_stride(surface);
- src = (uint8_t *)pixman_image_get_data(surface) +
- area->top * src_stride + area->left * bpp;
- dest_end = dest + (area->bottom - area->top) * dest_stride;
- for (; dest != dest_end; dest += dest_stride, src += src_stride) {
- memcpy(dest, src, (area->right - area->left) * bpp);
- }
-}
-
-static void canvas_clear(SpiceCanvas *spice_canvas)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- spice_pixman_fill_rect(canvas->image,
- 0, 0,
- pixman_image_get_width(canvas->image),
- pixman_image_get_height(canvas->image),
- 0);
-}
-
-static void canvas_destroy(SpiceCanvas *spice_canvas)
-{
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- if (!canvas) {
- return;
- }
- pixman_image_unref(canvas->image);
- canvas_base_destroy(&canvas->base);
- if (canvas->private_data) {
- free(canvas->private_data);
- }
- free(canvas);
-}
-
-static int need_init = 1;
-static SpiceCanvasOps sw_canvas_ops;
-
-static SpiceCanvas *canvas_create_common(pixman_image_t *image,
- uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- SwCanvas *canvas;
-
- if (need_init) {
- return NULL;
- }
- spice_pixman_image_set_format(image,
- spice_surface_format_to_pixman (format));
-
- canvas = spice_new0(SwCanvas, 1);
- canvas_base_init(&canvas->base, &sw_canvas_ops,
- pixman_image_get_width (image),
- pixman_image_get_height (image),
- format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
- canvas->private_data = NULL;
- canvas->private_data_size = 0;
-
- canvas->image = image;
-
- return (SpiceCanvas *)canvas;
-}
-
-SpiceCanvas *canvas_create(int width, int height, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- pixman_image_t *image;
-
- image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
- width, height, NULL, 0);
-
- return canvas_create_common(image, format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
-}
-
-SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
- uint8_t *data, int stride
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- )
-{
- pixman_image_t *image;
-
- image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
- width, height, (uint32_t *)data, stride);
-
- return canvas_create_common(image, format
-#ifdef SW_CANVAS_CACHE
- , bits_cache
- , palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , bits_cache
-#endif
- , surfaces
- , glz_decoder
- , jpeg_decoder
- , zlib_decoder
- );
-}
-
-void sw_canvas_init(void) //unsafe global function
-{
- if (!need_init) {
- return;
- }
- need_init = 0;
-
- canvas_base_init_ops(&sw_canvas_ops);
- sw_canvas_ops.draw_text = canvas_draw_text;
- sw_canvas_ops.put_image = canvas_put_image;
- sw_canvas_ops.clear = canvas_clear;
- sw_canvas_ops.read_bits = canvas_read_bits;
- sw_canvas_ops.destroy = canvas_destroy;
-
- sw_canvas_ops.fill_solid_spans = fill_solid_spans;
- sw_canvas_ops.fill_solid_rects = fill_solid_rects;
- sw_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop;
- sw_canvas_ops.fill_tiled_rects = fill_tiled_rects;
- sw_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface;
- sw_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop;
- sw_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface;
- sw_canvas_ops.blit_image = blit_image;
- sw_canvas_ops.blit_image_from_surface = blit_image_from_surface;
- sw_canvas_ops.blit_image_rop = blit_image_rop;
- sw_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface;
- sw_canvas_ops.scale_image = scale_image;
- sw_canvas_ops.scale_image_from_surface = scale_image_from_surface;
- sw_canvas_ops.scale_image_rop = scale_image_rop;
- sw_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface;
- sw_canvas_ops.blend_image = blend_image;
- sw_canvas_ops.blend_image_from_surface = blend_image_from_surface;
- sw_canvas_ops.blend_scale_image = blend_scale_image;
- sw_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface;
- sw_canvas_ops.colorkey_image = colorkey_image;
- sw_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface;
- sw_canvas_ops.colorkey_scale_image = colorkey_scale_image;
- sw_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface;
- sw_canvas_ops.copy_region = copy_region;
- sw_canvas_ops.get_image = get_image;
- rop3_init();
-}
diff --git a/common/sw_canvas.h b/common/sw_canvas.h
deleted file mode 100644
index 51e594c..0000000
--- a/common/sw_canvas.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H__CANVAS
-#define _H__CANVAS
-
-#include <stdint.h>
-
-#include "draw.h"
-#include "pixman_utils.h"
-#include "canvas_base.h"
-#include "region.h"
-
-SpiceCanvas *canvas_create(int width, int height, uint32_t format
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- );
-
-SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, int stride
-#ifdef SW_CANVAS_CACHE
- , SpiceImageCache *bits_cache
- , SpicePaletteCache *palette_cache
-#elif defined(SW_CANVAS_IMAGE_CACHE)
- , SpiceImageCache *bits_cache
-#endif
- , SpiceImageSurfaces *surfaces
- , SpiceGlzDecoder *glz_decoder
- , SpiceJpegDecoder *jpeg_decoder
- , SpiceZlibDecoder *zlib_decoder
- );
-
-
-void sw_canvas_init(void);
-
-#endif
diff --git a/configure.ac b/configure.ac
index 2d062b1..760736a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,6 +25,8 @@ GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
# Define default SPICE_COMMON_SRCDIR
SPICE_COMMON_SRCDIR='$(top_srcdir)'/common
+# no opengl support yet
+AM_CONDITIONAL(SUPPORT_GL, false)
AC_PROG_CC
AC_PROG_CC_C99
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index f4869b9..9628cc7 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -233,6 +233,8 @@ libspice_client_glib_2_0_la_SOURCES = \
decode-jpeg.c \
decode-zlib.c \
\
+ $(COMMON_DIR)/backtrace.c \
+ $(COMMON_DIR)/backtrace.h \
$(COMMON_DIR)/mem.c \
$(COMMON_DIR)/mem.h \
$(COMMON_DIR)/marshaller.c \
@@ -249,6 +251,8 @@ libspice_client_glib_2_0_la_SOURCES = \
$(COMMON_DIR)/rop3.h \
$(COMMON_DIR)/quic.c \
$(COMMON_DIR)/quic.h \
+ $(COMMON_DIR)/log.c \
+ $(COMMON_DIR)/log.h \
$(COMMON_DIR)/lz.c \
$(COMMON_DIR)/lz.h \
$(COMMON_DIR)/region.c \
@@ -503,10 +507,10 @@ generated_demarshallers1.c: $(top_srcdir)/spice1.proto
$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include messages.h --prefix 1 --ptrsize 8 $< $@ >/dev/null
generated_marshallers.c: $(top_srcdir)/spice.proto
- $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include marshallers.h --client $< $@ >/dev/null
+ $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include client_marshallers.h --client $< $@ >/dev/null
generated_marshallers1.c: $(top_srcdir)/spice1.proto
- $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include marshallers.h --client --prefix 1 --ptrsize 8 $< $@ >/dev/null
+ $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include client_marshallers.h --client --prefix 1 --ptrsize 8 $< $@ >/dev/null
vncdisplaykeymap.c: $(KEYMAPS)
diff --git a/gtk/decode.h b/gtk/decode.h
index 9fee749..9db6383 100644
--- a/gtk/decode.h
+++ b/gtk/decode.h
@@ -19,6 +19,7 @@
# define SPICEGTK_DECODE_H_
#include <glib.h>
+
#include "canvas_base.h"
G_BEGIN_DECLS
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index 482927b..88611d0 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -32,9 +32,8 @@
#include "coroutine.h"
#include "gio-coroutine.h"
-/* common/ */
-#include "marshallers.h"
-#include "demarshallers.h"
+#include "client_marshallers.h"
+#include "client_demarshallers.h"
#include "ssl_verify.h"
--
1.7.7.6
More information about the Spice-devel
mailing list