From f6d11427d9397eb78993099c1faf9c12cbbbb50b Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 13 Nov 2000 10:18:37 +0000 Subject: Ajout de routines pour le rendu local --- generic/Image.c | 1075 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- generic/Image.h | 69 +++- 2 files changed, 1134 insertions(+), 10 deletions(-) (limited to 'generic') 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 +#include #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 + #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 */ -- cgit v1.1