aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2000-11-13 10:18:37 +0000
committerlecoanet2000-11-13 10:18:37 +0000
commitf6d11427d9397eb78993099c1faf9c12cbbbb50b (patch)
tree347a02466f13690b58185f60169088d8ab870e7b /generic
parentc914a00fb8b2257cc827d1d0b41ce5ee496b9289 (diff)
downloadtkzinc-f6d11427d9397eb78993099c1faf9c12cbbbb50b.zip
tkzinc-f6d11427d9397eb78993099c1faf9c12cbbbb50b.tar.gz
tkzinc-f6d11427d9397eb78993099c1faf9c12cbbbb50b.tar.bz2
tkzinc-f6d11427d9397eb78993099c1faf9c12cbbbb50b.tar.xz
Ajout de routines pour le rendu local
Diffstat (limited to 'generic')
-rw-r--r--generic/Image.c1075
-rw-r--r--generic/Image.h69
2 files changed, 1134 insertions, 10 deletions
diff --git a/generic/Image.c b/generic/Image.c
index 1f4025b..a163e27 100644
--- a/generic/Image.c
+++ b/generic/Image.c
@@ -26,9 +26,12 @@
#include <malloc.h>
+#include <memory.h>
#include "Types.h"
#include "Image.h"
+#include "WidgetInfo.h"
+#include "Geo.h"
static const char rcsid[] = "$Id$";
@@ -50,9 +53,9 @@ typedef struct _ImagePixmap {
struct _ImagePixmap *next;
} ImagePixmap;
-
static Tcl_HashTable image_bits;
static Tcl_HashTable bitmap_masks;
+static Tcl_HashTable font_bitmaps;
/*
@@ -74,6 +77,7 @@ GetImageBits(ZnWindow win,
Display *dpy = Tk_Display(win);
int depth = Tk_Depth(win);
int x, y, new, width, height;
+ unsigned char *line;
XGCValues values;
GC gc;
ImageBits *im_bits;
@@ -90,7 +94,11 @@ GetImageBits(ZnWindow win,
else {
Tk_SizeOfImage(image, &width, &height);
im_bits = (ImageBits *) ZnMalloc(sizeof(ImageBits));
+#ifdef SHM
+ im_bits->pixbuf = NULL;
+#endif
im_bits->pixmaps = NULL;
+ im_bits->b_bits = NULL;
pmap = XCreatePixmap(dpy, ZnWindowId(win), width, height, depth);
values.foreground = 0;
@@ -120,15 +128,24 @@ GetImageBits(ZnWindow win,
mask = XGetImage(dpy, pmap, 0, 0, width, height, 1, XYPixmap);
XFreePixmap(dpy, pmap);
- for (x = 0; x < width; x++) {
- for (y = 0; y < height; y++) {
+ im_bits->b_bits = (BitmapBits *) ZnMalloc(sizeof(BitmapBits));
+ im_bits->b_bits->pixels = ZnMalloc(height * mask->bytes_per_line);
+ memset(im_bits->b_bits->pixels, 0, height * mask->bytes_per_line);
+ im_bits->b_bits->rowstride = mask->bytes_per_line;
+ im_bits->b_bits->width = width;
+ im_bits->b_bits->height = height;
+ line = im_bits->b_bits->pixels;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
if (XGetPixel(im1, x, y) == XGetPixel(im2, x, y)) {
XPutPixel(mask, x, y, 1L);
+ line[x >> 3] |= 0x80 >> (x & 7);
}
else {
full_mask = False;
}
}
+ line += im_bits->b_bits->rowstride;
}
XDestroyImage(im2);
@@ -177,6 +194,15 @@ InvalidateImage(char *image_name)
ZnFree(im_pmap);
im_pmap = next_im_pmap;
}
+ if (im_bits->b_bits) {
+ ZnFree(im_bits->b_bits->pixels);
+ ZnFree(im_bits->b_bits);
+ }
+#ifdef SHM
+ if (im_bits->pixbuf) {
+ art_pixbuf_free(im_bits->pixbuf);
+ }
+#endif
ZnFree(im_bits);
Tcl_DeleteHashEntry(entry);
}
@@ -265,7 +291,7 @@ GetImagePixmap(ZnWindow win,
*
**********************************************************************************
*/
-XImage *
+BitmapBits *
GetBitmapMask(Display *dpy,
Pixmap bitmap)
{
@@ -273,26 +299,1057 @@ GetBitmapMask(Display *dpy,
BitmapKey key;
Tcl_HashEntry *entry;
XImage *mask;
- int w, h, new;
+ BitmapBits *b_bits;
+ unsigned char *line;
+ int x, y, w, h, new;
if (!inited) {
- Tcl_InitHashTable(&bitmap_masks, (sizeof(Display *)+sizeof(Pixmap)) / sizeof(int));
+ Tcl_InitHashTable(&bitmap_masks, (sizeof(BitmapKey)) / sizeof(int));
inited = 1;
}
key.dpy = dpy;
key.bitmap = bitmap;
entry = Tcl_FindHashEntry(&bitmap_masks, (char *) &key);
if (entry != NULL) {
- mask = (XImage *) Tcl_GetHashValue(entry);
+ b_bits = (BitmapBits *) Tcl_GetHashValue(entry);
}
else {
Tk_SizeOfBitmap(dpy, bitmap, &w, &h);
mask = XGetImage(dpy, bitmap, 0, 0, w, h, 1L, XYPixmap);
+ b_bits = (BitmapBits *) ZnMalloc(sizeof(BitmapBits));
+ b_bits->pixels = ZnMalloc(h * mask->bytes_per_line);
+ memset(b_bits->pixels, 0, h * mask->bytes_per_line);
+ b_bits->rowstride = mask->bytes_per_line;
+ b_bits->width = w;
+ b_bits->height = h;
+ line = b_bits->pixels;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (XGetPixel(mask, x, y)) {
+ line[x >> 3] |= 0x80 >> (x & 7);
+ }
+ }
+ line += b_bits->rowstride;
+ }
+ XDestroyImage(mask);
key.dpy = dpy;
key.bitmap = bitmap;
entry = Tcl_CreateHashEntry(&bitmap_masks, (char *) &key, &new);
- Tcl_SetHashValue(entry, (ClientData) mask);
+ Tcl_SetHashValue(entry, (ClientData) b_bits);
+ }
+
+ return b_bits;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * GetFontBitmap --
+ *
+ **********************************************************************************
+ */
+FontBitmap *
+GetFontBitmap(ZnWindow win,
+ ZnFont font)
+{
+ static int inited = 0;
+ Tcl_HashEntry *entry;
+ FontBitmap *f_bits;
+ XImage *im;
+ Pixmap pix;
+ GC gc;
+ XGCValues values;
+ Tk_FontMetrics fm;
+ Display *dpy = Tk_Display(win);
+ int i, x, y, black_pixel, pixel;
+ int new, size, width, height;
+ char str[1];
+ char *line;
+
+ if (!inited) {
+ Tcl_InitHashTable(&font_bitmaps, (sizeof(ZnFont)) / sizeof(int));
+ inited = 1;
+ }
+ entry = Tcl_FindHashEntry(&font_bitmaps, (char *) &font);
+ if (entry != NULL) {
+ f_bits = (FontBitmap *) Tcl_GetHashValue(entry);
+ }
+ else {
+ f_bits = (FontBitmap *) ZnMalloc(sizeof(FontBitmap));
+ Tk_GetFontMetrics(font, &fm);
+
+ height = fm.ascent + fm.descent;
+ x = 0;
+
+ for (i = 0; i < 256; i++) {
+ str[0] = i;
+ f_bits->chars[i].width = Tk_TextWidth(font, str, 1);
+ f_bits->chars[i].bitmap_offset = x;
+ /* Next char will be aligned on a 32 bit boundary; */
+ x += (f_bits->chars[i].width + 31) & -32;
+ }
+
+ width = x;
+ f_bits->width = width;
+ f_bits->height = height;
+ f_bits->ascent = fm.ascent;
+ f_bits->descent = fm.descent;
+
+ pix = XCreatePixmap(dpy, ZnWindowId(win), width, height, 1);
+ values.foreground = WhitePixel(dpy, DefaultScreen(dpy));
+ values.font = Tk_FontId(font);
+ gc = XCreateGC(dpy, pix, GCForeground|GCFont, &values);
+ XFillRectangle(dpy, pix, gc, 0, 0, width, height);
+ black_pixel = BlackPixel(dpy, DefaultScreen(dpy));
+ values.foreground = black_pixel;
+ XChangeGC(dpy, gc, GCForeground, &values);
+
+ for (i = 0; i < 256; i++) {
+ str[0] = i;
+ XDrawString(dpy, pix, gc, f_bits->chars[i].bitmap_offset,
+ f_bits->ascent, str, 1);
+ }
+
+ im = XGetImage(dpy, pix, 0, 0, width, height, 1L, XYPixmap);
+ size = (width >> 3) * height;
+ f_bits->bitmap = ZnMalloc(size);
+ memset(f_bits->bitmap, 0, size);
+
+ line = f_bits->bitmap;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ pixel = XGetPixel(im, x, y);
+ if (pixel == black_pixel) {
+ line[x >> 3] |= 128 >> (x & 7);
+ }
+ }
+ line += width >> 3;
+ }
+
+ XDestroyImage(im);
+ XFreePixmap(dpy, pix);
+ XFreeGC(dpy, gc);
+
+ entry = Tcl_CreateHashEntry(&font_bitmaps, (char *) &font, &new);
+ Tcl_SetHashValue(entry, (ClientData) f_bits);
+ }
+
+ return f_bits;
+}
+
+
+static void
+rgb_text_opaque(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ char *text , int num_chars, int start_x, int start_y,
+ FontBitmap *fb, art_u32 rgb)
+{
+ art_u8 *src, *src_p, *dst_p, *dst_linestart;
+ art_u8 r, g, b;
+ art_u8 bm;
+ SuckChar *ch;
+ int run_x0, run_y0;
+ int j, x, y, tmp;
+ int next_start, src_width, src_height, src_rowstride;
+ int src_x0, src_y0, src_x1, src_y1;
+
+ src_height = fb->height;
+ src_rowstride = fb->width >> 3;
+ src_y0 = 0;
+ run_y0 = start_y - y0;
+ if (run_y0 < 0) {
+ src_y0 = -run_y0;
+ run_y0 = 0;
+ }
+ src_y1 = src_height;
+ tmp = start_y + src_height - y1;
+ if (tmp > 0) {
+ src_y1 -= tmp;
+ }
+
+ r = rgb >> 16;
+ g = (rgb >> 8) & 0xff;
+ b = rgb & 0xff;
+
+ for (j = 0; j < num_chars; j++) {
+ if (start_x > x1) {
+ break;
+ }
+ ch = &fb->chars[(unsigned char)(*text)];
+ src_width = ch->width;
+ next_start = start_x + src_width;
+ if (next_start < x0) {
+ goto nexto;
+ }
+ src = fb->bitmap + (ch->bitmap_offset >> 3);
+ src_x0 = 0;
+ run_x0 = start_x - x0;
+ if (run_x0 < 0) {
+ src_x0 = -run_x0;
+ run_x0 = 0;
+ }
+ src_x1 = src_width;
+ tmp = next_start - x1;
+ if (tmp > 0) {
+ src_x1 -= tmp;
+ }
+
+ dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
+ src_p = src + src_y0 * src_rowstride;
+
+ for (y = src_y0; y < src_y1; y++) {
+ dst_p = dst_linestart;
+ for (x = src_x0; x < src_x1; x++) {
+ bm = *(src_p + (x >> 3));
+ if (bm & (128 >> (x & 7))) {
+ *dst_p = r;
+ dst_p++;
+ *dst_p = g;
+ dst_p++;
+ *dst_p = b;
+ dst_p++;
+ }
+ else {
+ dst_p += 3;
+ }
+ }
+ dst_linestart += dst_rowstride;
+ src_p += src_rowstride;
+ }
+ nexto:
+ start_x = next_start;
+ text++;
+ }
+}
+
+void
+rgb_text(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ char *text, int num_chars, int start_x, int start_y,
+ FontBitmap *fb, art_u32 rgba)
+{
+ art_u8 *src, *src_p, *dst_p, *dst_linestart;
+ art_u8 r, g, b;
+ art_u8 bm, comp;
+ SuckChar *ch;
+ int alpha;
+ int run_x0, run_y0;
+ int j, x, y, tmp;
+ int next_start, src_width, src_height, src_rowstride;
+ int src_x0, src_y0, src_x1, src_y1;
+
+ src_height = fb->height;
+ if ((start_y > y1) ||
+ (start_y+src_height < y0) ||
+ (start_x > x1)) {
+ return;
+ }
+
+ alpha = rgba & 0xff;
+ if (alpha == 0xff) {
+ rgb_text_opaque(dst, x0, y0, x1, y1, dst_rowstride,
+ text, num_chars, start_x, start_y,
+ fb, rgba >> 8);
+ return;
+ }
+
+ src_rowstride = fb->width >> 3;
+ src_y0 = 0;
+ run_y0 = start_y - y0;
+ if (run_y0 < 0) {
+ src_y0 = -run_y0;
+ run_y0 = 0;
+ }
+ src_y1 = src_height;
+ tmp = start_y + src_height - y1;
+ if (tmp > 0) {
+ src_y1 -= tmp;
+ }
+
+ alpha = (alpha << 8) + alpha + (alpha >> 7);
+ r = rgba >> 24;
+ g = (rgba >> 16) & 0xff;
+ b = (rgba >> 8) & 0xff;
+
+ for (j = 0; j < num_chars; j++) {
+ if (start_x > x1) {
+ break;
+ }
+ ch = &fb->chars[(unsigned char)(*text)];
+ src_width = ch->width;
+ next_start = start_x + src_width;
+ if (next_start < x0) {
+ goto next;
+ }
+ src = fb->bitmap + (ch->bitmap_offset >> 3);
+ src_x0 = 0;
+ run_x0 = start_x - x0;
+ if (run_x0 < 0) {
+ src_x0 = -run_x0;
+ run_x0 = 0;
+ }
+ src_x1 = src_width;
+ tmp = next_start - x1;
+ if (tmp > 0) {
+ src_x1 -= tmp;
+ }
+
+ dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
+ src_p = src + src_y0 * src_rowstride;
+
+ for (y = src_y0; y < src_y1; y++) {
+ dst_p = dst_linestart;
+ for (x = src_x0; x < src_x1; x++) {
+ bm = *(src_p + (x >> 3));
+ if (bm & (128 >> (x & 7))) {
+ comp = *dst_p;
+ *dst_p = comp + (((r - comp) * alpha + 0x8000) >> 16);
+ dst_p++;
+ comp = *dst_p;
+ *dst_p = comp + (((g - comp) * alpha + 0x8000) >> 16);
+ dst_p++;
+ comp = *dst_p;
+ *dst_p = comp + (((b - comp) * alpha + 0x8000) >> 16);
+ dst_p++;
+ }
+ else {
+ dst_p += 3;
+ }
+ }
+ dst_linestart += dst_rowstride;
+ src_p += src_rowstride;
+ }
+ next:
+ start_x = next_start;
+ text++;
+ }
+}
+
+/* rgb_image */
+void
+rgb_image(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ ArtPixBuf *pixbuf, int start_x, int start_y, int alpha)
+{
+ art_u8 *src, *src_p, *dst_p;
+ art_u8 *dst_linestart, *src_linestart;
+ art_u8 r, g, b;
+ int a;
+ int run_x0, run_y0;
+ int x, y, tmp;
+ int src_x0, src_y0, src_x1, src_y1;
+ int src_width, src_height, src_rowstride;
+
+ if (pixbuf->format != ART_PIX_RGB) {
+ ZnWarning("art_rgb_pixbuf_affine: need RGB format image\n");
+ return;
+ }
+ if (pixbuf->bits_per_sample != 8) {
+ ZnWarning("art_rgb_pixbuf_affine: need 8-bit sample data\n");
+ return;
+ }
+ if ((pixbuf->n_channels != 4) || !pixbuf->has_alpha) {
+ ZnWarning("art_rgb_pixbuf_affine: need RGBA sample data\n");
+ return;
+ }
+
+ src_width = pixbuf->width;
+ src_height = pixbuf->height;
+
+ if ((start_y > y1) ||
+ (start_y+src_height < y0) ||
+ (start_x > x1) ||
+ (start_x+src_width < x0)) {
+ return;
}
- return mask;
+ src_rowstride = pixbuf->rowstride;
+ src = pixbuf->pixels;
+
+ src_x0 = src_y0 = 0;
+ run_y0 = start_y - y0;
+ if (run_y0 < 0) {
+ src_y0 = -run_y0;
+ run_y0 = 0;
+ }
+ src_y1 = src_height;
+ tmp = start_y + src_height - y1;
+ if (tmp > 0) {
+ src_y1 -= tmp;
+ }
+ run_x0 = start_x - x0;
+ if (run_x0 < 0) {
+ src_x0 = -run_x0;
+ run_x0 = 0;
+ }
+ src_x1 = src_width;
+ tmp = start_x + src_width - x1;
+ if (tmp > 0) {
+ src_x1 -= tmp;
+ }
+
+ dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
+ src_linestart = src + src_y0 * src_rowstride + src_x0 * 4;
+
+ for (y = src_y0; y < src_y1; y++) {
+ dst_p = dst_linestart;
+ src_p = src_linestart;
+ for (x = src_x0; x < src_x1; x++) {
+ a = src_p[3] * alpha / 255;
+ if (a) {
+ if (a == 255) {
+ dst_p[0] = src_p[0];
+ dst_p[1] = src_p[1];
+ dst_p[2] = src_p[2];
+ }
+ else {
+ r = dst_p[0];
+ g = dst_p[1];
+ b = dst_p[2];
+ tmp = (src_p[0] - r) * a;
+ r = r + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ tmp = (src_p[1] - g) * a;
+ g = g + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ tmp = (src_p[2] - b) * a;
+ b = b + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ dst_p[0] = r;
+ dst_p[1] = g;
+ dst_p[2] = b;
+ }
+ }
+ dst_p += 3;
+ src_p += 4;
+ }
+ dst_linestart += dst_rowstride;
+ src_linestart += src_rowstride;
+ }
+}
+
+/* rgb_bitmap */
+static void
+rgb_bitmap_opaque(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ art_u8 *src, int start_x, int start_y,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgb)
+{
+ art_u8 *src_p, *dst_p, *dst_linestart;
+ art_u8 r, g, b;
+ art_u8 bm;
+ int run_x0, run_y0;
+ int x, y, tmp;
+ int src_x0, src_y0, src_x1, src_y1;
+
+ src_x0 = src_y0 = 0;
+ run_y0 = start_y - y0;
+ if (run_y0 < 0) {
+ src_y0 = -run_y0;
+ run_y0 = 0;
+ }
+ src_y1 = src_height;
+ tmp = start_y + src_height - y1;
+ if (tmp > 0) {
+ src_y1 -= tmp;
+ }
+ run_x0 = start_x - x0;
+ if (run_x0 < 0) {
+ src_x0 = -run_x0;
+ run_x0 = 0;
+ }
+ src_x1 = src_width;
+ tmp = start_x + src_width - x1;
+ if (tmp > 0) {
+ src_x1 -= tmp;
+ }
+
+ r = rgb >> 16;
+ g = (rgb >> 8) & 0xff;
+ b = rgb & 0xff;
+
+ dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
+ src_p = src + src_y0 * src_rowstride;
+
+ for (y = src_y0; y < src_y1; y++) {
+ dst_p = dst_linestart;
+ for (x = src_x0; x < src_x1; x++) {
+ bm = *(src_p + (x >> 3));
+ if (bm & (128 >> (x & 7))) {
+ *dst_p = r;
+ dst_p++;
+ *dst_p = g;
+ dst_p++;
+ *dst_p = b;
+ dst_p++;
+ }
+ else {
+ dst_p += 3;
+ }
+ }
+ dst_linestart += dst_rowstride;
+ src_p += src_rowstride;
+ }
+}
+
+void
+rgb_bitmap(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ art_u8 *src, int start_x, int start_y,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgba)
+{
+ art_u8 *src_p, *dst_p, *dst_linestart;
+ art_u8 r, g, b;
+ art_u8 bm, comp;
+ int alpha;
+ int run_x0, run_y0;
+ int x, y, tmp;
+ int src_x0, src_y0, src_x1, src_y1;
+
+ if ((start_y > y1) ||
+ (start_y+src_height < y0) ||
+ (start_x > x1) ||
+ (start_x+src_width < x0)) {
+ return;
+ }
+
+ alpha = rgba & 0xff;
+ if (alpha == 0xff) {
+ rgb_bitmap_opaque(dst, x0, y0, x1, y1, dst_rowstride,
+ src, start_x, start_y,
+ src_width, src_height, src_rowstride,
+ rgba >> 8);
+ return;
+ }
+
+ src_x0 = src_y0 = 0;
+ run_y0 = start_y - y0;
+ if (run_y0 < 0) {
+ src_y0 = -run_y0;
+ run_y0 = 0;
+ }
+ src_y1 = src_height;
+ tmp = start_y + src_height - y1;
+ if (tmp > 0) {
+ src_y1 -= tmp;
+ }
+ run_x0 = start_x - x0;
+ if (run_x0 < 0) {
+ src_x0 = -run_x0;
+ run_x0 = 0;
+ }
+ src_x1 = src_width;
+ tmp = start_x + src_width - x1;
+ if (tmp > 0) {
+ src_x1 -= tmp;
+ }
+
+ alpha = (alpha << 8) + alpha + (alpha >> 7);
+ r = rgba >> 24;
+ g = (rgba >> 16) & 0xff;
+ b = (rgba >> 8) & 0xff;
+
+ dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
+ src_p = src + src_y0 * src_rowstride;
+
+ for (y = src_y0; y < src_y1; y++) {
+ dst_p = dst_linestart;
+ for (x = src_x0; x < src_x1; x++) {
+ bm = *(src_p + (x >> 3));
+ if (bm & (128 >> (x & 7))) {
+ comp = *dst_p;
+ *dst_p = comp + (((r - comp) * alpha + 0x8000) >> 16);
+ dst_p++;
+ comp = *dst_p;
+ *dst_p = comp + (((g - comp) * alpha + 0x8000) >> 16);
+ dst_p++;
+ comp = *dst_p;
+ *dst_p = comp + (((b - comp) * alpha + 0x8000) >> 16);
+ dst_p++;
+ }
+ else {
+ dst_p += 3;
+ }
+ }
+ dst_linestart += dst_rowstride;
+ src_p += src_rowstride;
+ }
+}
+
+typedef struct _TileSVPData {
+ ArtPixBuf *tile;
+ int tile_x;
+ int tile_y;
+ art_u32 b_rgb;
+ int alphatab[256];
+ art_u8 *buf;
+ int rowstride;
+ int x0, x1;
+} TileSVPData;
+
+static void
+tile_fill_run(art_u8 *buf,
+ int num,
+ art_u8 *tile_line,
+ int tile_dx,
+ int tile_width)
+{
+ int i, start_len;
+ art_u8 *ptr;
+
+ tile_dx %= tile_width;
+ if (tile_dx < 0) {
+ tile_dx += tile_width;
+ }
+ start_len = tile_width - tile_dx;
+ if (start_len > num) {
+ start_len = num;
+ }
+ ptr = tile_line + 4*tile_dx;
+ for (i = 0; i < start_len; i++) {
+ *buf++ = *ptr++;
+ *buf++ = *ptr++;
+ *buf++ = *ptr++;
+ ptr++;
+ }
+ num -= start_len;
+ while (num > 0) {
+ ptr = tile_line;
+ for (i = MIN(tile_width, num); i > 0; i--) {
+ *buf++ = *ptr++;
+ *buf++ = *ptr++;
+ *buf++ = *ptr++;
+ ptr++;
+ }
+ num -= tile_width;
+ }
+}
+
+static void
+tile_svp_aa_cb(void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps,
+ int n_steps)
+{
+ TileSVPData *data = (TileSVPData *)callback_data;
+ art_u8 *linebuf, *tile_line;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ art_u8 b_r, b_g, b_b;
+ int x0, x1, k, dy;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+ b_r = data->b_rgb >> 16;
+ b_g = (data->b_rgb >> 8) & 0xff;
+ b_b = data->b_rgb & 0xff;
+
+ dy = y - data->tile_y;
+ dy %= data->tile->height;
+ if (dy < 0) {
+ dy += data->tile->height;
+ }
+ tile_line = data->tile->pixels + dy * data->tile->rowstride;
+
+ if (n_steps > 0) {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0) {
+ if (((running_sum >> 16) & 0xff) > 128) {
+ tile_fill_run(linebuf, run_x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width);
+ }
+ else {
+ art_rgb_fill_run(linebuf, b_r, b_g, b_b, run_x1 - x0);
+ }
+ }
+
+ for (k = 0; k < n_steps - 1; k++) {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0) {
+ if (((running_sum >> 16) & 0xff) > 128) {
+ tile_fill_run(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
+ tile_line, run_x0 - data->tile_x, data->tile->width);
+ }
+ else {
+ art_rgb_fill_run(linebuf + (run_x0 - x0) * 3, b_r, b_g, b_b,
+ run_x1 - run_x0);
+ }
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1) {
+ if (((running_sum >> 16) & 0xff) > 128) {
+ tile_fill_run(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
+ tile_line, run_x1 - data->tile_x, data->tile->width);
+ }
+ else {
+ art_rgb_fill_run(linebuf + (run_x1 - x0) * 3, b_r, b_g, b_b,
+ x1 - run_x1);
+ }
+ }
+ }
+ else {
+ if (((running_sum >> 16) & 0xff) > 128) {
+ tile_fill_run(linebuf, x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width);
+ }
+ else {
+ art_rgb_fill_run(linebuf, b_r, b_g, b_b, x1 - x0);
+ }
+ }
+
+ data->buf += data->rowstride;
+}
+
+void
+tile_svp_aa(const ArtSVP *svp,
+ int x0,
+ int y0,
+ int x1,
+ int y1,
+ int tile_x,
+ int tile_y,
+ ArtPixBuf *tile,
+ art_u32 bg_color,
+ art_u8 *buf,
+ int rowstride)
+{
+ TileSVPData data;
+
+ data.tile = tile;
+ data.tile_x = tile_x;
+ data.tile_y = tile_y;
+ data.b_rgb = bg_color;
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+
+ art_svp_render_aa(svp, x0, y0, x1, y1, tile_svp_aa_cb, &data);
+}
+
+static void
+tile_fill_run_alpha(art_u8 *buf,
+ int num,
+ art_u8 *tile_line,
+ int tile_dx,
+ int tile_width,
+ int alpha)
+{
+ int v, vt, i, start_len;
+ art_u8 *ptr;
+
+ tile_dx %= tile_width;
+ if (tile_dx < 0) {
+ tile_dx += tile_width;
+ }
+ start_len = tile_width - tile_dx;
+ if (start_len > num) {
+ start_len = num;
+ }
+ ptr = tile_line + 4*tile_dx;
+ for (i = 0; i < start_len; i++) {
+ v = *buf;
+ vt = *ptr++;
+ *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ vt = *ptr++;
+ *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ vt = *ptr++;
+ *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
+ ptr++;
+ }
+ num -= start_len;
+ while (num > 0) {
+ ptr = tile_line;
+ for (i = MIN(tile_width, num); i > 0; i--) {
+ v = *buf;
+ vt = *ptr++;
+ *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ vt = *ptr++;
+ *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ vt = *ptr++;
+ *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
+ ptr++;
+ }
+ num -= tile_width;
+ }
+}
+
+static void
+tile_svp_alpha_opaque_cb(void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps,
+ int n_steps)
+{
+ TileSVPData *data = (TileSVPData *)callback_data;
+ art_u8 *linebuf, *tile_line;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1, k, dy;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+ alphatab = data->alphatab;
+
+ dy = y - data->tile_y;
+ dy %= data->tile->height;
+ if (dy < 0) {
+ dy += data->tile->height;
+ }
+ tile_line = data->tile->pixels + dy * data->tile->rowstride;
+
+ if (n_steps > 0) {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0) {
+ alpha = running_sum >> 16;
+ if (alpha) {
+ if (alpha >= 255) {
+ tile_fill_run(linebuf, run_x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width);
+ }
+ else {
+ tile_fill_run_alpha(linebuf, run_x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+ }
+
+ for (k = 0; k < n_steps - 1; k++) {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0) {
+ alpha = running_sum >> 16;
+ if (alpha) {
+ if (alpha >= 255) {
+ tile_fill_run(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
+ tile_line, run_x0 - data->tile_x, data->tile->width);
+ }
+ else {
+ tile_fill_run_alpha(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
+ tile_line, run_x0 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1) {
+ alpha = running_sum >> 16;
+ if (alpha) {
+ if (alpha >= 255) {
+ tile_fill_run(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
+ tile_line, run_x1 - data->tile_x, data->tile->width);
+ }
+ else {
+ tile_fill_run_alpha(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
+ tile_line, run_x1 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+ }
+ }
+ else {
+ alpha = running_sum >> 16;
+ if (alpha) {
+ if (alpha >= 255) {
+ tile_fill_run(linebuf, x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width);
+ }
+ else {
+ tile_fill_run_alpha(linebuf, x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+ }
+
+ data->buf += data->rowstride;
+}
+
+static void
+tile_svp_alpha_cb(void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps,
+ int n_steps)
+{
+ TileSVPData *data = (TileSVPData *)callback_data;
+ art_u8 *linebuf, *tile_line;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1, k, dy;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+ alphatab = data->alphatab;
+
+ dy = y - data->tile_y;
+ dy %= data->tile->height;
+ if (dy < 0) {
+ dy += data->tile->height;
+ }
+ tile_line = data->tile->pixels + dy * data->tile->rowstride;
+
+ if (n_steps > 0) {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0) {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha) {
+ tile_fill_run_alpha(linebuf, run_x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+
+ for (k = 0; k < n_steps - 1; k++) {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0) {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha) {
+ tile_fill_run_alpha(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
+ tile_line, run_x0 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1) {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha) {
+ tile_fill_run_alpha(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
+ tile_line, run_x1 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+ }
+ else {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha) {
+ tile_fill_run_alpha(linebuf, x1 - x0,
+ tile_line, x0 - data->tile_x, data->tile->width,
+ alphatab[alpha]);
+ }
+ }
+
+ data->buf += data->rowstride;
+}
+
+void
+tile_svp_alpha(const ArtSVP *svp,
+ int x0,
+ int y0,
+ int x1,
+ int y1,
+ int tile_x,
+ int tile_y,
+ ArtPixBuf *tile,
+ art_u8 alpha,
+ art_u8 *buf,
+ int rowstride)
+{
+ TileSVPData data;
+ int i, a, da;
+
+ data.tile = tile;
+ data.tile_x = tile_x;
+ data.tile_y = tile_y;
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+
+ a = 0x8000;
+ da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
+ for (i = 0; i < 256; i++) {
+ data.alphatab[i] = a >> 16;
+ a += da;
+ }
+
+ if (alpha == 255) {
+ art_svp_render_aa(svp, x0, y0, x1, y1, tile_svp_alpha_opaque_cb, &data);
+ }
+ else {
+ art_svp_render_aa(svp, x0, y0, x1, y1, tile_svp_alpha_cb, &data);
+ }
+}
+
+#ifdef SHM
+/*
+ * Working only for 16 bits displays with 5r6g5b mask.
+ */
+ArtPixBuf *
+GetImagePixbuf(ZnWindow win,
+ char *image_name,
+ ZnImage image)
+{
+ ImageBits *im_bits;
+ BitmapBits *b_bits;
+ int width, height;
+ int x, y;
+ int rowstride;
+ art_u8 *obuf, *obptr;
+ int bpl;
+ art_u8 *pixels, *bptr, *bp2;
+ art_u8 alpha;
+ art_u16 temp;
+
+ im_bits = GetImageBits(win, image_name, image);
+ if (!im_bits->pixbuf) {
+ b_bits = im_bits->b_bits;
+ width = im_bits->width;
+ height = im_bits->height;
+ rowstride = width*4;
+ bptr = pixels = art_alloc(rowstride * height);
+ obuf = im_bits->pixels->data;
+ bpl = im_bits->pixels->bytes_per_line;
+
+ for (y = 0; y < height; y++) {
+ bp2 = bptr;
+ obptr = obuf;
+ for (x = 0; x < width; x++) {
+ /*
+ * Configure the alpha value.
+ */
+ alpha = GetBitmapPixel(b_bits, x, y) ? 255 : 0;
+ /*
+ * Dispatch the 3 color components.
+ */
+ temp = ((art_u16 *)obptr)[0];
+ *bp2 = (temp >> 8) & 0xf8; /* r */
+ bp2++;
+ *bp2 = (temp >> 3) & 0xfc; /* v */
+ bp2++;
+ *bp2 = (temp << 3); /* b */
+ bp2++;
+ *bp2 = alpha;
+ bp2++;
+ obptr += 2;
+ }
+ bptr += rowstride;
+ obuf += bpl;
+ }
+
+ im_bits->pixbuf = art_pixbuf_new_rgba(pixels, width, height, rowstride);
+ }
+ return im_bits->pixbuf;
}
+#endif
diff --git a/generic/Image.h b/generic/Image.h
index cd89278..b98619b 100644
--- a/generic/Image.h
+++ b/generic/Image.h
@@ -31,17 +31,45 @@
#define _Image_h
+#include <libart_lgpl/libart.h>
+
#include "Types.h"
typedef struct {
+ unsigned char *pixels;
+ int width;
+ int height;
+ int rowstride;
+} BitmapBits;
+
+
+typedef struct {
XImage *pixels;
XImage *mask;
+ BitmapBits *b_bits;
int width;
int height;
struct _ImagePixmap *pixmaps;
+#ifdef SHM
+ ArtPixBuf *pixbuf;
+#endif
} ImageBits;
+typedef struct _SuckChar {
+ int width;
+ int bitmap_offset;
+} SuckChar;
+
+typedef struct _SuckFont {
+ unsigned char *bitmap;
+ int width;
+ int height;
+ int ascent;
+ int descent;
+ SuckChar chars[256];
+} FontBitmap;
+
ImageBits *
GetImageBits(ZnWindow /* win */,
@@ -54,9 +82,48 @@ GetImagePixmap(ZnWindow /* win */,
Pixmap *mask_pmap);
void
InvalidateImage(char */* image_name */);
-XImage *
+BitmapBits *
GetBitmapMask(Display */* dpy */,
Pixmap /* bitmap */);
+#define GetBitmapPixel(bbits, x, y) (((bbits)->pixels[(y)*(bbits)->rowstride+((x)>>3)]<<((x)&7))&0x80)
+
+FontBitmap *
+GetFontBitmap(ZnWindow win,
+ ZnFont font);
+
+void
+rgb_text(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ char *text, int num_chars, int start_x, int start_y,
+ FontBitmap *fb, art_u32 rgba);
+void
+rgb_bitmap(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ art_u8 *src, int start_x, int start_y,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgba);
+void
+rgb_image(art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ ArtPixBuf *pixbuf, int start_x, int start_y, int alpha);
+void
+tile_svp_aa(const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ int tile_x, int tile_y, ArtPixBuf *tile,
+ art_u32 bg_color, art_u8 *buf, int rowstride);
+void
+tile_svp_alpha(const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ int tile_x, int tile_y, ArtPixBuf *tile,
+ art_u8 alpha, art_u8 *buf, int rowstride);
+
+#ifdef SHM
+ArtPixBuf *
+GetImagePixbuf(ZnWindow /* win */,
+ char */* image_name */,
+ ZnImage /* image */);
+#endif
+
#endif /* _Image_h */