/* * 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 #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; }