diff options
-rw-r--r-- | generic/Image.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/generic/Image.c b/generic/Image.c new file mode 100644 index 0000000..1b9093b --- /dev/null +++ b/generic/Image.c @@ -0,0 +1,262 @@ +/* + * Image.c -- Image support routines. + * + * Authors : Patrick LECOANET + * Creation date : Wed Dec 8 11:04:44 1999 + */ + +/* + * Copyright (c) 1999 CENA, Patrick Lecoanet -- + * + * This code is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This code 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this code; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include <malloc.h> + +#include "Types.h" +#include "Image.h" + + +static const char rcsid[] = "$Id$"; +static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; + + +/* + * Key used to index the bitmap_masks hash table. + */ +typedef struct { + Display *dpy; + Pixmap bitmap; +} BitmapKey; + +typedef struct _ImagePixmap { + Display *dpy; + Pixmap pixmap; + struct _ImagePixmap *next; +} ImagePixmap; + + +static Tcl_HashTable image_bits; +static Tcl_HashTable bitmap_masks; + + +/* + ********************************************************************************** + * + * GetImageBits -- + * + ********************************************************************************** + */ +ImageBits * +GetImageBits(RadarWindow win, + RadarImage image) +{ + static int inited = 0; + Tcl_HashEntry *entry; + XImage *im1, *im2, *mask; + Pixmap pmap; + Display *dpy = Tk_Display(win); + int depth = Tk_Depth(win); + int x, y, new, width, height; + XGCValues values; + GC gc; + ImageBits *im_bits; + RadarBool full_mask=True; + + if (!inited) { + Tcl_InitHashTable(&image_bits, TCL_ONE_WORD_KEYS); + inited = 1; + } + entry = Tcl_FindHashEntry(&image_bits, (char *) image); + if (entry != NULL) { + im_bits = (ImageBits *) Tcl_GetHashValue(entry); + } + else { + Tk_SizeOfImage(image, &width, &height); + im_bits = (ImageBits *) RadarMalloc(sizeof(ImageBits)); + im_bits->pixmaps = NULL; + pmap = XCreatePixmap(dpy, RadarWindowId(win), width, height, depth); + + values.foreground = 0; + gc = XCreateGC(dpy, pmap, GCForeground, &values); + XFillRectangle(dpy, pmap, gc, 0, 0, width, height); + Tk_RedrawImage(image, 0, 0, width, height, pmap, 0, 0); + im_bits->pixels = im1 = XGetImage(dpy, pmap, 0, 0, width, height, ~0L, ZPixmap); + im_bits->width = width; + im_bits->height = height; + + values.foreground = 1; + XChangeGC(dpy, gc, GCForeground, &values); + XFillRectangle(dpy, pmap, gc, 0, 0, width, height); + XFreeGC(dpy, gc); + Tk_RedrawImage(image, 0, 0, width, height, pmap, 0, 0); + im2 = XGetImage(dpy, pmap, 0, 0, width, height, ~0L, ZPixmap); + XFreePixmap(dpy, pmap); + + /* + * The image structure can be setup locally (TODO). + */ + pmap = XCreatePixmap(dpy, RadarWindowId(win), width, height, 1); + values.foreground = 0; + gc = XCreateGC(dpy, pmap, GCForeground, &values); + XFillRectangle(dpy, pmap, gc, 0, 0, width, height); + XFreeGC(dpy, gc); + 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++) { + if (XGetPixel(im1, x, y) == XGetPixel(im2, x, y)) { + XPutPixel(mask, x, y, 1L); + } + else { + full_mask = False; + } + } + } + + XDestroyImage(im2); + if (full_mask) { + XDestroyImage(mask); + im_bits->mask = RadarUnspecifiedPattern; + } + else { + im_bits->mask = mask; + } + + entry = Tcl_CreateHashEntry(&image_bits, (char *) image, &new); + Tcl_SetHashValue(entry, (ClientData) im_bits); + } + + return im_bits; +} + +void +InvalidateImage(RadarImage image) +{ + Tcl_HashEntry *entry; + ImageBits *im_bits; + ImagePixmap *im_pmap, *next_im_pmap; + + /* + * Destroy the image entry and wait the cache fault to + * reload the new one. + */ + entry = Tcl_FindHashEntry(&image_bits, (char *) image); + if (entry != NULL) { + im_bits = (ImageBits *) Tcl_GetHashValue(entry); + XDestroyImage(im_bits->pixels); + if (im_bits->mask) { + XDestroyImage(im_bits->mask); + } + im_pmap = im_bits->pixmaps; + while (im_pmap) { + next_im_pmap = im_pmap->next; + XFreePixmap(im_pmap->dpy, im_pmap->pixmap); + RadarFree(im_pmap); + im_pmap = next_im_pmap; + } + RadarFree(im_bits); + Tcl_DeleteHashEntry(entry); + } +} + + +/* + ********************************************************************************** + * + * GetImagePixmap -- + * + ********************************************************************************** + */ +Pixmap +GetImagePixmap(RadarWindow win, + RadarImage image) +{ + ImageBits *im_bits; + Display *dpy = Tk_Display(win); + int depth = Tk_Depth(win); + ImagePixmap *im_pmap, *next_im_pmap; + Pixmap pixmap; + + im_bits = GetImageBits(win, image); + im_pmap = next_im_pmap = im_bits->pixmaps; + while (next_im_pmap && (im_pmap->dpy != dpy)) { + im_pmap = next_im_pmap; + next_im_pmap = next_im_pmap->next; + } + if (!im_pmap || (im_pmap->dpy != dpy)) { + next_im_pmap = (ImagePixmap *) RadarMalloc(sizeof(ImagePixmap)); + next_im_pmap->next = NULL; + next_im_pmap->dpy = dpy; + pixmap = XCreatePixmap(dpy, RadarWindowId(win), + im_bits->width, im_bits->height, depth); + Tk_RedrawImage(image, 0, 0, im_bits->width, im_bits->height, pixmap, 0, 0); + next_im_pmap->pixmap = pixmap; + if (im_pmap) { + im_pmap->next = next_im_pmap; + } + else { + im_bits->pixmaps = next_im_pmap; + } + } + else { + pixmap = im_pmap->pixmap; + } + + return pixmap; +} + + +/* + ********************************************************************************** + * + * GetBitmapMask -- + * + ********************************************************************************** + */ +XImage * +GetBitmapMask(Display *dpy, + Pixmap bitmap) +{ + static int inited = 0; + BitmapKey key; + Tcl_HashEntry *entry; + XImage *mask; + int w, h, new; + + if (!inited) { + Tcl_InitHashTable(&bitmap_masks, (sizeof(Display *)+sizeof(Pixmap)) / 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); + } + else { + Tk_SizeOfBitmap(dpy, bitmap, &w, &h); + mask = XGetImage(dpy, bitmap, 0, 0, w, h, 1L, XYPixmap); + key.dpy = dpy; + key.bitmap = bitmap; + entry = Tcl_CreateHashEntry(&bitmap_masks, (char *) &key, &new); + Tcl_SetHashValue(entry, (ClientData) mask); + } + + return mask; +} |