aboutsummaryrefslogtreecommitdiff
path: root/generic/Image.c
diff options
context:
space:
mode:
authorlecoanet2002-05-16 08:33:27 +0000
committerlecoanet2002-05-16 08:33:27 +0000
commitd7c5b765038579619622377bb7a8bed709744825 (patch)
tree5f9a83900c11ac8a08413faf911000b8b2c4bbe8 /generic/Image.c
parent12a44dc133cf2c0426664f1ffaef7ded92f6c2f3 (diff)
downloadtkzinc-d7c5b765038579619622377bb7a8bed709744825.zip
tkzinc-d7c5b765038579619622377bb7a8bed709744825.tar.gz
tkzinc-d7c5b765038579619622377bb7a8bed709744825.tar.bz2
tkzinc-d7c5b765038579619622377bb7a8bed709744825.tar.xz
Re�criture compl�te de la gestion du chargement/lib�ration des images,
des bitmaps et des fontes. On n'utilise plus Tk que pour initialiser l'image, le compte de r�f�rence est gard� en local. Les images et bitmap sont sp�cialis�es par display pour X, par fen�tre pour GL. Les fontes sont sp�cialis�es par fen�tres en GL. Le code de modification dynamique des images propos� par Tk n'est plus pris en compte. Les textures et la m�moire utilis�es par les images/bitmap/fontes sont lib�r�es d�s que possible, r�sultant en une bien meilleure utilisation des ressources (surtout en ce qui concerne les textures). Ces modifs corrigent le bug de dessin des images/fontes observ� sous GL avec deux ou plusieurs Zinc cr��s simultan�ment ou cons�cutivement dans la M�ME application.
Diffstat (limited to 'generic/Image.c')
-rw-r--r--generic/Image.c1562
1 files changed, 1023 insertions, 539 deletions
diff --git a/generic/Image.c b/generic/Image.c
index 52ba2eb..3ef66b4 100644
--- a/generic/Image.c
+++ b/generic/Image.c
@@ -45,240 +45,642 @@ 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;
- Pixmap mask_pmap;
- struct _ImagePixmap *next;
-} ImagePixmap;
-
-static int image_bits_inited = 0;
-static Tcl_HashTable image_bits;
-static Tcl_HashTable bitmap_masks;
+static int images_inited = 0;
+static Tcl_HashTable images;
#ifdef GLX
static Tcl_HashTable font_textures;
#endif
+typedef struct _ImageStruct {
+ union {
+ struct {
+ Pixmap pixmap;
+ Pixmap mask_pmap;
+ Display *dpy;
+ } x;
+ struct {
+ GLuint texobj;
+ struct _WidgetInfo *wi;
+ } gl;
+ } i;
+ struct _ImageBits *bits;
+
+ /* Bookkeeping */
+
+ ZnBool for_gl;
+ int refcount;
+ struct _ImageStruct *next;
+} ImageStruct, *Image;
+
+
+typedef struct _ImageBits {
+ int width;
+ int height;
+ unsigned char *bpixels; /* Needed at least to know the bounds (Pick), or if
+ * the image is a bitmap. Can be NULL if no mask is
+ * defined for the image (i.e the image is
+ * rectangular) and the image is not a bitmap. */
+ int rowstride;
+#ifdef GLX
+ ZnReal t; /* Texture parameters for the image. */
+ ZnReal s;
+#endif
+
+ /* Bookeeping */
+
+ Tcl_HashEntry *hash; /* From this it is easy to get the image/bitmap
+ * name. */
+ XImage *ipixels; /* Keep this to create textures and pixmaps as
+ * needed. NULL if the image is a bitmap. This
+ * can be tested to tell if this is an image or
+ * a bitmap. */
+ XImage *mask; /* Keep this to build special clip mask in X (Icon).
+ * Can be NULL if no mask is defined for the image
+ * (i.e the image is rectangular) or if the image
+ * is a bitmap. */
+#ifdef GLX
+ int t_width; /* Texture size used for this image. */
+ int t_height;
+ unsigned char *t_bits; /* Can be NULL if texture is not used (no GL
+ * rendering active on this image). */
+#endif
+ Image images; /* Linked list of widget/display dependant
+ * specializations of this image. If NULL, the
+ * image has no specialization and can be freed. */
+} ImageBits;
+
+
+/*
+ * Working only for 16 bits displays with 5r6g5b mask,
+ * and 24/32 bits displays. Byte ordering ok on Intel
+ * plateform only.
+ */
+static void
+From5r6g5b(unsigned char *data,
+ int width,
+ int height,
+ int bytes_per_line,
+ int t_width,
+ int t_height,
+ unsigned char *bpixels,
+ int bstride,
+ unsigned char *t_bits)
+{
+ int x, y;
+ int rowstride = t_width * 4;
+ unsigned char *obptr;
+ unsigned char *bptr, *bp2;
+ unsigned char alpha;
+ unsigned short temp;
+
+ bptr = t_bits;
+
+ for (y = 0; y < height; y++) {
+ bp2 = bptr;
+ obptr = data;
+ for (x = 0; x < width; x++) {
+ /*
+ * Configure the alpha value.
+ */
+ alpha = ZnGetBitmapPixel(bpixels, bstride, x, y) ? 255 : 0;
+
+ /*
+ * Dispatch the 3 color components.
+ */
+ temp = ((unsigned short *)obptr)[0];
+ *bp2 = (temp >> 8) & 0xf8; /* r */
+ bp2++;
+ *bp2 = (temp >> 3) & 0xfc; /* v */
+ bp2++;
+ *bp2 = (temp << 3); /* b */
+ bp2++;
+ *bp2 = alpha;
+ bp2++;
+ obptr += 2;
+ }
+ for (x = width; x < t_width; x++) {
+ *bp2 = 0;
+ bp2++;
+ *bp2 = 0;
+ bp2++;
+ *bp2 = 0;
+ bp2++;
+ *bp2 = 0;
+ bp2++;
+ }
+ bptr += rowstride;
+ data += bytes_per_line;
+ }
+ for (y = height; y < t_height; y++) {
+ memset(bptr, 0, rowstride);
+ bptr += rowstride;
+ }
+}
+
+static void
+From8r8g8b(unsigned char *data,
+ int width,
+ int height,
+ int bytes_per_line,
+ int t_width,
+ int t_height,
+ unsigned char *bpixels,
+ int bstride,
+ unsigned char *t_bits)
+{
+ int x, y;
+ int rowstride = t_width * 4;
+ unsigned char *obptr;
+ unsigned char *bptr, *bp2;
+ unsigned char alpha;
+
+ bptr = t_bits;
+
+ for (y = 0; y < height; y++) {
+ bp2 = bptr;
+ obptr = data;
+ for (x = 0; x < width; x++) {
+ /*
+ * Configure the alpha value.
+ */
+ if (bpixels) {
+ alpha = ZnGetBitmapPixel(bpixels, bstride, x, y) ? 255 : 0;
+ }
+ else {
+ alpha = 255;
+ }
+
+ /*
+ * Dispatch the 3 color components.
+ * Be careful the Red and Blue are swapped it works on an Intel
+ * plateform but may need some more tests to be fully generic.
+ */
+ *bp2++ = obptr[2]; /* r */
+ *bp2++ = obptr[1]; /* v */
+ *bp2++ = obptr[0]; /* b */
+ obptr += 4;
+ *bp2++ = alpha;
+ }
+ for (x = width; x < t_width; x++) {
+ *bp2 = 0;
+ bp2++;
+ *bp2 = 0;
+ bp2++;
+ *bp2 = 0;
+ bp2++;
+ *bp2 = 0;
+ bp2++;
+ }
+ bptr += rowstride;
+ data += bytes_per_line;
+ }
+ for (y = height; y < t_height; y++) {
+ memset(bptr, 0, rowstride);
+ bptr += rowstride;
+ }
+}
+
+static int
+To2Power(int a)
+{
+ int result = 1;
+
+ while (result < a) {
+ result *= 2;
+ }
+ return result;
+}
+
+
/*
**********************************************************************************
*
- * ValidateImage --
- * Make sure an image is ok for use in an attribute
- * and do any needed housekeeping.
+ * ZnGetImage --
*
**********************************************************************************
*/
-int
-ValidateImage(WidgetInfo *wi,
- void *item_or_field,
- char *image_name,
- Tk_ImageChangedProc *image_proc,
- Tk_Image *image_ref,
- char *msg)
+static void
+InvalidateImage(ClientData client_data,
+ int x,
+ int y,
+ int width,
+ int height,
+ int image_width,
+ int image_height)
{
- Tk_Image image;
- int w, h, status = ZN_OK;
+ /*
+ * Void stub that keeps the Tk image mecanism happy. Zinc does
+ * _not_ implement image update.
+ */
+}
+
+static void
+GatherImageBits(WidgetInfo *wi,
+ Tk_Image tkimage,
+ ImageBits *bits)
+{
+ Pixmap pmap;
+ int depth = DefaultDepthOfScreen(wi->screen);
+ int x, y;
+ unsigned char *line;
+ GC gc;
+ XImage *im1, *im2;
+ ZnBool full_mask=True;
+
+ /*
+ * Nothing known about this image, collect the image bits.
+ */
+ pmap = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen),
+ bits->width, bits->height, depth);
+ gc = XCreateGC(wi->dpy, pmap, 0, NULL);
+ XSetForeground(wi->dpy, gc, 0);
+ XFillRectangle(wi->dpy, pmap, gc, 0, 0, bits->width, bits->height);
+ Tk_RedrawImage(tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
+ im1 = bits->ipixels = XGetImage(wi->dpy, pmap, 0, 0,
+ bits->width, bits->height, ~0L, ZPixmap);
- if (strcmp(image_name, "") != 0) {
- image = Tk_GetImage(wi->interp, wi->win, image_name,
- image_proc, (ClientData) item_or_field);
- /*
- * The name will not be in sync with the image in
- * these cases.
- */
- if (image == NULL) {
+ XSetForeground(wi->dpy, gc, 1);
+ XFillRectangle(wi->dpy, pmap, gc, 0, 0, bits->width, bits->height);
+ Tk_RedrawImage(tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
+ im2 = XGetImage(wi->dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
+ XFreePixmap(wi->dpy, pmap);
+
+ /*
+ * The image structure can be setup locally (TODO).
+ */
+ XFreeGC(wi->dpy, gc);
+ pmap = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen),
+ bits->width, bits->height, 1);
+ gc = XCreateGC(wi->dpy, pmap, 0, NULL);
+ XSetForeground(wi->dpy, gc, 0);
+ XFillRectangle(wi->dpy, pmap, gc, 0, 0, bits->width, bits->height);
+ XFreeGC(wi->dpy, gc);
+ bits->mask = XGetImage(wi->dpy, pmap, 0, 0, bits->width, bits->height, 1, XYPixmap);
+ XFreePixmap(wi->dpy, pmap);
+
+ bits->rowstride = bits->mask->bytes_per_line;
+ bits->bpixels = ZnMalloc(bits->height * bits->rowstride);
+ memset(bits->bpixels, 0, bits->height * bits->rowstride);
+ line = bits->bpixels;
+ for (y = 0; y < bits->height; y++) {
+ for (x = 0; x < bits->width; x++) {
+ if (XGetPixel(im1, x, y) == XGetPixel(im2, x, y)) {
+ XPutPixel(bits->mask, x, y, 1L);
+ line[x >> 3] |= 0x80 >> (x & 7);
+ }
+ else {
+ full_mask = False;
+ }
+ }
+ line += bits->rowstride;
+ }
+
+ XDestroyImage(im2);
+ if (full_mask) {
+ XDestroyImage(bits->mask);
+ bits->mask = NULL;
+ ZnFree(bits->bpixels);
+ bits->bpixels = NULL;
+ }
+}
+
+static Image
+GetImageInstance(WidgetInfo *wi,
+ ImageBits *bits)
+{
+ int depth = DefaultDepthOfScreen(wi->screen);
+ ZnBool for_gl = wi->render>0;
+ XGCValues values;
+ GC gc;
+ Image image;
+
+ /*
+ * Try to find an image instance that fits this widget/display.
+ */
+ for (image = bits->images; image != NULL; image = image->next) {
+ if (image->for_gl == for_gl) {
+ if (for_gl && (image->i.gl.wi == wi)) {
+ image->refcount++;
+ return image;
+ }
+ else if (!for_gl && (image->i.x.dpy == wi->dpy)) {
+ image->refcount++;
+ return image;
+ }
+ }
+ }
+ /*
+ * Create a new instance for this case.
+ */
+ image = ZnMalloc(sizeof(ImageStruct));
+ image->bits = bits;
+ image->refcount = 1;
+ image->for_gl = for_gl;
+ if (image->for_gl) {
+#ifdef GLX
+ image->i.gl.wi = wi;
+ image->i.gl.texobj = 0;
+ }
+#endif
+ else {
+ image->i.x.dpy = wi->dpy;
+ image->i.x.pixmap = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen),
+ bits->width, bits->height, depth);
+ gc = XCreateGC(wi->dpy, image->i.x.pixmap, 0, NULL);
+ XPutImage(wi->dpy, image->i.x.pixmap, gc, bits->ipixels, 0, 0, 0, 0,
+ bits->width, bits->height);
+ XFreeGC(wi->dpy, gc);
+ if (bits->mask) {
+ image->i.x.mask_pmap = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen),
+ bits->width, bits->height, 1);
+ values.foreground = 1;
+ values.background = 0;
+ gc = XCreateGC(wi->dpy, image->i.x.mask_pmap,
+ GCForeground|GCBackground, &values);
+ XPutImage(wi->dpy, image->i.x.mask_pmap, gc, bits->mask, 0, 0, 0, 0,
+ bits->width, bits->height);
+ XFreeGC(wi->dpy, gc);
+ }
+ else {
+ image->i.x.mask_pmap = None;
+ }
+ }
+ image->next = bits->images;
+ bits->images = image;
+
+ return image;
+}
+
+ZnImage
+ZnGetImage(WidgetInfo *wi,
+ char *image_name)
+{
+ Tcl_HashEntry *entry;
+ int new;
+ ImageBits *bits;
+ Tk_Image tkimage;
+
+ /*printf("ZnGetImage: %s\n", image_name);*/
+ if (!images_inited) {
+ Tcl_InitHashTable(&images, TCL_STRING_KEYS);
+ images_inited = 1;
+ }
+ entry = Tcl_FindHashEntry(&images, image_name);
+ if (entry != NULL) {
+ /*printf("Image %s déjà connue\n", image_name);*/
+ bits = (ImageBits *) Tcl_GetHashValue(entry);
+ }
+ else {
+ /*printf("Nouvelle Image %s\n", image_name);*/
+ if (strcmp(image_name, "") == 0) {
+ return ZnUnspecifiedImage;
+ }
+ bits = ZnMalloc(sizeof(ImageBits));
+ tkimage = Tk_GetImage(wi->interp, wi->win, image_name,
+ InvalidateImage, (ClientData) bits);
+ if (tkimage == NULL) {
im_val_err:
- image = ZnUnspecifiedImage;
- /*Tcl_AppendResult(wi->interp, "unknown or bogus image \"",
- image_name, "\" in ", msg, NULL);
- status = ZN_ERROR; */
+ ZnFree(bits);
ZnWarning("unknown or bogus image \"");
ZnWarning(image_name);
- ZnWarning("\" in ");
- ZnWarning(msg);
- ZnWarning("\n");
- status = ZN_OK;
+ ZnWarning("\"\n");
+ return ZnUnspecifiedImage;
}
else {
- Tk_SizeOfImage(image, &w, &h);
- if ((w == 0) || (h == 0)) {
+ Tk_SizeOfImage(tkimage, &bits->width, &bits->height);
+ if ((bits->width == 0) || (bits->height == 0)) {
+ Tk_FreeImage(tkimage);
goto im_val_err;
}
}
+#ifdef GLX
+ bits->t_bits = NULL;
+#endif
+ bits->images = NULL;
+ bits->mask = NULL;
+ bits->bpixels = NULL;
+ entry = Tcl_CreateHashEntry(&images, image_name, &new);
+ bits->hash = entry;
+ Tcl_SetHashValue(entry, (ClientData) bits);
}
- else {
- image = ZnUnspecifiedImage;
- }
- if (*image_ref != ZnUnspecifiedImage) {
- Tk_FreeImage(*image_ref);
+
+ if (!bits->ipixels) {
+ GatherImageBits(wi, tkimage, bits);
+ Tk_FreeImage(tkimage);
}
- *image_ref = image;
-
- return status;
+ return GetImageInstance(wi, bits);
}
-
/*
**********************************************************************************
*
- * GetImageBits --
+ * ZnGetBitmap --
*
**********************************************************************************
*/
-ImageBits *
-GetImageBits(ZnWindow win,
- char *image_name,
- ZnImage image)
+ZnImage
+ZnGetBitmap(WidgetInfo *wi,
+ char *bitmap_name)
{
Tcl_HashEntry *entry;
- XImage *im1, *im2, *mask;
+ ImageBits *bits;
Pixmap pmap;
- Display *dpy = Tk_Display(win);
- int depth = Tk_Depth(win);
+ XImage *mask;
+ Image image;
+ ZnBool for_gl = wi->render>0;
int x, y, new, width, height;
unsigned char *line;
- XGCValues values;
- GC gc;
- ImageBits *im_bits;
- ZnBool full_mask=True;
- /* printf("GetImageBits: %s\n", image_name);*/
- if (!image_bits_inited) {
- Tcl_InitHashTable(&image_bits, TCL_STRING_KEYS);
- image_bits_inited = 1;
+ /*printf("ZnGetBitmap: %s\n", bitmap_name);*/
+ if (!images_inited) {
+ Tcl_InitHashTable(&images, TCL_STRING_KEYS);
+ images_inited = 1;
}
- entry = Tcl_FindHashEntry(&image_bits, image_name);
+ entry = Tcl_FindHashEntry(&images, bitmap_name);
if (entry != NULL) {
- im_bits = (ImageBits *) Tcl_GetHashValue(entry);
+ bits = (ImageBits *) Tcl_GetHashValue(entry);
}
else {
- Tk_SizeOfImage(image, &width, &height);
- im_bits = (ImageBits *) ZnMalloc(sizeof(ImageBits));
+ pmap = Tk_GetBitmap(wi->interp, wi->win, Tk_GetUid(bitmap_name));
+ if (pmap == ZnUnspecifiedImage) {
+ return ZnUnspecifiedImage;
+ }
+ Tk_SizeOfBitmap(wi->dpy, pmap, &width, &height);
+ bits = ZnMalloc(sizeof(ImageBits));
+ bits->width = width;
+ bits->height = height;
#ifdef GLX
- im_bits->texture = 0;
- im_bits->t_bits = NULL;
+ bits->t_bits = NULL;
#endif
- im_bits->pixmaps = NULL;
- im_bits->b_bits = NULL;
- pmap = XCreatePixmap(dpy, ZnWindowId(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, ZnWindowId(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);
-
- 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;
+ bits->images = NULL;
+ bits->mask = NULL;
+ bits->bpixels = NULL;
+ bits->ipixels = NULL;
+ mask = XGetImage(wi->dpy, pmap, 0, 0, width, height, 1L, XYPixmap);
+ bits->rowstride = mask->bytes_per_line;
+ bits->bpixels = ZnMalloc(height * bits->rowstride);
+ memset(bits->bpixels, 0, height * bits->rowstride);
+ line = bits->bpixels;
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);
+ if (XGetPixel(mask, x, y)) {
line[x >> 3] |= 0x80 >> (x & 7);
}
- else {
- full_mask = False;
- }
}
- line += im_bits->b_bits->rowstride;
+ line += bits->rowstride;
}
+ XDestroyImage(mask);
+ entry = Tcl_CreateHashEntry(&images, bitmap_name, &new);
+ Tcl_SetHashValue(entry, (ClientData) bits);
+ bits->hash = entry;
+ }
- XDestroyImage(im2);
- if (full_mask) {
- XDestroyImage(mask);
- im_bits->mask = ZnUnspecifiedPattern;
+ /*
+ * Try to find an image instance that fits this widget/display.
+ */
+ for (image = bits->images; image != NULL; image = image->next) {
+ if (image->for_gl == for_gl) {
+ if (for_gl && (image->i.gl.wi == wi)) {
+ image->refcount++;
+ return image;
+ }
+ else if (!for_gl && (image->i.x.dpy == wi->dpy)) {
+ image->refcount++;
+ return image;
+ }
+ }
+ }
+
+ /*
+ * Create a new instance for this widget/display conf.
+ */
+ image = ZnMalloc(sizeof(ImageStruct));
+ image->bits = bits;
+ image->refcount = 1;
+ image->for_gl = for_gl;
+ if (image->for_gl) {
+#ifdef GLX
+ image->i.gl.wi = wi;
+ image->i.gl.texobj = 0;
+ }
+#endif
+ else {
+ image->i.x.dpy = wi->dpy;
+ image->i.x.mask_pmap = None;
+ if (bits->images == NULL) {
+ /*
+ * For the first one, the Tk_GetBitmap call has already been done.
+ */
+ image->i.x.pixmap = pmap;
}
else {
- im_bits->mask = mask;
+ /*
+ * Need to get a pixmap that match this dpy.
+ */
+ image->i.x.pixmap = Tk_GetBitmap(wi->interp, wi->win, bitmap_name);
}
-
- entry = Tcl_CreateHashEntry(&image_bits, image_name, &new);
- Tcl_SetHashValue(entry, (ClientData) im_bits);
}
+ image->next = bits->images;
+ bits->images = image;
+
+ return image;
+}
+
- return im_bits;
+/*
+ **********************************************************************************
+ *
+ * ZnGetImageByValue --
+ *
+ **********************************************************************************
+ */
+ZnImage
+ZnGetImageByValue(ZnImage image)
+{
+ ((Image) image)->refcount++;
+ return image;
}
+/*
+ **********************************************************************************
+ *
+ * ZnFreeImage --
+ *
+ **********************************************************************************
+ */
void
-InvalidateImage(char *image_name)
+ZnFreeImage(ZnImage image)
{
- Tcl_HashEntry *entry;
- ImageBits *im_bits;
- ImagePixmap *im_pmap, *next_im_pmap;
-
- if (!image_bits_inited) {
+ Image prev, scan, this = ((Image) image);
+ ImageBits *bits = this->bits;
+
+ /*
+ * Search the instance in the list.
+ */
+ for (prev=NULL, scan=bits->images; (scan!=NULL)&&(scan!=this);
+ prev=scan, scan=scan->next);
+ if (scan != this) {
+ return; /* Not found ? */
+ }
+
+ this->refcount--;
+ if (this->refcount != 0) {
return;
}
+
/*
- * Destroy the image entry and wait the cache fault to
- * reload the new one.
+ * Unlink the deleted image instance.
*/
- /*printf("InvalidateImage %s\n", image_name);*/
- entry = Tcl_FindHashEntry(&image_bits, image_name);
- if (entry != NULL) {
- /*printf("deallocating bits for image %s\n", image_name);*/
- im_bits = (ImageBits *) Tcl_GetHashValue(entry);
- XDestroyImage(im_bits->pixels);
- if (im_bits->mask) {
- XDestroyImage(im_bits->mask);
+ if (prev == NULL) {
+ bits->images = this->next;
+ }
+ else {
+ prev->next = this->next;
+ }
+ if (this->for_gl) {
+ if (this->i.gl.texobj) {
+ glDeleteTextures(1, &this->i.gl.texobj);
}
- im_pmap = im_bits->pixmaps;
- while (im_pmap) {
- next_im_pmap = im_pmap->next;
- XFreePixmap(im_pmap->dpy, im_pmap->pixmap);
- if (im_bits->mask) {
- XFreePixmap(im_pmap->dpy, im_pmap->mask_pmap);
- }
- ZnFree(im_pmap);
- im_pmap = next_im_pmap;
+ }
+ else if (bits->ipixels) {
+ /*
+ * This is an image, we need to free the pixmaps.
+ */
+ if (this->i.x.pixmap != None) {
+ XFreePixmap(this->i.x.dpy, this->i.x.pixmap);
}
- if (im_bits->b_bits) {
- ZnFree(im_bits->b_bits->pixels);
- ZnFree(im_bits->b_bits);
+ if (this->i.x.mask_pmap != None) {
+ XFreePixmap(this->i.x.dpy, this->i.x.mask_pmap);
}
-#ifdef GLX
- if (im_bits->texture) {
- ZnFree(im_bits->t_bits);
- glDeleteTextures(1, &im_bits->texture);
+ }
+ else {
+ /*
+ * This is a bitmap ask Tk to free the resource.
+ */
+ Tk_FreeBitmap(this->i.x.dpy, this->i.x.pixmap);
+ }
+ ZnFree(this);
+
+ /*
+ * No clients for this image, it can be freed.
+ */
+ if (bits->images == NULL) {
+ /*printf("destruction complète de l'image %s\n", ZnNameOfImage(this));*/
+ if (bits->t_bits) {
+ ZnFree(bits->t_bits);
}
-#endif
- ZnFree(im_bits);
- Tcl_DeleteHashEntry(entry);
+ if (bits->mask) {
+ XDestroyImage(bits->mask);
+ }
+ if (bits->ipixels) {
+ XDestroyImage(bits->ipixels);
+ }
+ if (bits->bpixels) {
+ ZnFree(bits->bpixels);
+ }
+ Tcl_DeleteHashEntry(bits->hash);
+ ZnFree(bits);
}
}
@@ -286,141 +688,242 @@ InvalidateImage(char *image_name)
/*
**********************************************************************************
*
- * GetImagePixmap --
+ * ZnNameOfImage --
*
**********************************************************************************
*/
-Pixmap
-GetImagePixmap(ZnWindow win,
- char *image_name,
- ZnImage image,
- Pixmap *mask_pmap)
+char *
+ZnNameOfImage(ZnImage image)
{
- ImageBits *im_bits;
- Display *dpy = Tk_Display(win);
- int depth = Tk_Depth(win);
- ImagePixmap *im_pmap, *next_im_pmap;
- Pixmap pixmap;
- GC gc;
- XGCValues values;
-
- im_bits = GetImageBits(win, image_name, 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)) {
- /* printf("New pixmap\n");*/
- next_im_pmap = (ImagePixmap *) ZnMalloc(sizeof(ImagePixmap));
- next_im_pmap->next = NULL;
- next_im_pmap->dpy = dpy;
- pixmap = XCreatePixmap(dpy, ZnWindowId(win),
- im_bits->width, im_bits->height, depth);
- gc = XCreateGC(dpy, pixmap, 0, NULL);
- XPutImage(dpy, pixmap, gc, im_bits->pixels, 0, 0, 0, 0,
- im_bits->width, im_bits->height);
- XFreeGC(dpy, gc);
- next_im_pmap->pixmap = pixmap;
- if (im_bits->mask) {
- next_im_pmap->mask_pmap = XCreatePixmap(dpy, ZnWindowId(win),
- im_bits->width, im_bits->height, 1);
- values.foreground = 1;
- values.background = 0;
- gc = XCreateGC(dpy, next_im_pmap->mask_pmap,
- GCForeground|GCBackground, &values);
- XPutImage(dpy, next_im_pmap->mask_pmap, gc, im_bits->mask, 0, 0, 0, 0,
- im_bits->width, im_bits->height);
- XFreeGC(dpy, gc);
- if (mask_pmap) {
- *mask_pmap = next_im_pmap->mask_pmap;
- }
- }
- else {
- next_im_pmap->mask_pmap = None;
- }
- if (im_pmap) {
- im_pmap->next = next_im_pmap;
- }
- else {
- im_bits->pixmaps = next_im_pmap;
- }
- }
- else {
- /*printf("Reusing pixmap\n");*/
- pixmap = im_pmap->pixmap;
- if (mask_pmap) {
- *mask_pmap = im_pmap->mask_pmap;
- }
+ return Tcl_GetHashKey(&images, ((Image) image)->bits->hash);
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * ZnSizeOfImage --
+ *
+ **********************************************************************************
+ */
+void
+ZnSizeOfImage(ZnImage image,
+ int *width,
+ int *height)
+{
+ Image im = (Image) image;
+ *width = im->bits->width;
+ *height = im->bits->height;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * ZnImagePattern --
+ *
+ **********************************************************************************
+ */
+char *
+ZnImagePattern(ZnImage image,
+ int *stride)
+{
+ if (stride) {
+ *stride = ((Image) image)->bits->rowstride;
}
+ return ((Image) image)->bits->bpixels;
+}
- return pixmap;
+/*
+ **********************************************************************************
+ *
+ * ZnImageIsBitmap --
+ *
+ **********************************************************************************
+ */
+ZnBool
+ZnImageIsBitmap(ZnImage image)
+{
+ return (((Image) image)->bits->ipixels == NULL);
}
+/*
+ **********************************************************************************
+ *
+ * ZnImageMask --
+ *
+ **********************************************************************************
+ */
+XImage *
+ZnImageMask(ZnImage image)
+{
+ return ((Image) image)->bits->mask;
+}
/*
**********************************************************************************
*
- * GetBitmapMask --
+ * ZnImagePixmap --
*
**********************************************************************************
*/
-BitmapBits *
-GetBitmapMask(Display *dpy,
- Pixmap bitmap)
+Pixmap
+ZnImagePixmap(ZnImage image,
+ Pixmap *mask_pmap)
{
- static int inited = 0;
- BitmapKey key;
- Tcl_HashEntry *entry;
- XImage *mask;
- BitmapBits *b_bits;
- unsigned char *line;
- int x, y, w, h, new;
-
- if (!inited) {
- Tcl_InitHashTable(&bitmap_masks, (sizeof(BitmapKey)) / sizeof(int));
- inited = 1;
+ if (((Image) image)->for_gl) {
+ return None;
}
- key.dpy = dpy;
- key.bitmap = bitmap;
- entry = Tcl_FindHashEntry(&bitmap_masks, (char *) &key);
- if (entry != NULL) {
- b_bits = (BitmapBits *) Tcl_GetHashValue(entry);
+ if (mask_pmap) {
+ *mask_pmap = ((Image) image)->i.x.mask_pmap;
}
- 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);
+ return ((Image) image)->i.x.pixmap;
+}
+
+/*
+ **********************************************************************************
+ *
+ * ZnImageTex --
+ *
+ **********************************************************************************
+ */
+#ifdef GLX
+GLuint
+ZnImageTex(ZnImage image,
+ ZnReal *t,
+ ZnReal *s)
+{
+ Image this = (Image) image;
+ ImageBits *bits = this->bits;
+ ZnBool is_bmap = ZnImageIsBitmap(image);
+ int depth, t_size;
+
+ if (!this->for_gl) {
+ return 0;
+ }
+ if (!bits->t_bits) {
+ /*printf("chargement texture pour image %s\n", ZnNameOfImage(this));*/
+ bits->t_width = To2Power(bits->width);
+ bits->t_height = To2Power(bits->height);
+ bits->s = bits->width / (ZnReal) bits->t_width;
+ bits->t = bits->height / (ZnReal) bits->t_height;
+ if (is_bmap) {
+ int i, j;
+ unsigned char *ostart, *dstart, *d, *o;
+
+ t_size = bits->t_width * bits->t_height;
+ bits->t_bits = ZnMalloc(t_size);
+ memset(bits->t_bits, 0, t_size);
+ ostart = bits->bpixels;
+ dstart = bits->t_bits;
+ for (i = 0; i < bits->height; i++) {
+ d = dstart;
+ o = ostart;
+ for (j = 0; j < bits->width; j++) {
+ *d++ = ZnGetBitmapPixel(bits->bpixels, bits->rowstride, j, i) ? 255 : 0;
}
+ ostart += bits->rowstride;
+ dstart += bits->t_width;
+ }
+ }
+ else {
+ t_size = bits->t_width * 4 * bits->t_height;
+ bits->t_bits = ZnMalloc(t_size);
+ if (this->for_gl) {
+ depth = DefaultDepthOfScreen(this->i.gl.wi->screen);
+ }
+ else {
+ depth = DefaultDepthOfScreen(DefaultScreenOfDisplay(this->i.x.dpy));
+ }
+ if (depth == 16) {
+ From5r6g5b(bits->ipixels->data, bits->width, bits->height,
+ bits->ipixels->bytes_per_line, bits->t_width, bits->t_height,
+ bits->bpixels, bits->rowstride, bits->t_bits);
+ }
+ else if ((depth == 24) || (depth == 32)) {
+ From8r8g8b(bits->ipixels->data, bits->width, bits->height,
+ bits->ipixels->bytes_per_line, bits->t_width, bits->t_height,
+ bits->bpixels, bits->rowstride, bits->t_bits);
}
- line += b_bits->rowstride;
}
- XDestroyImage(mask);
- key.dpy = dpy;
- key.bitmap = bitmap;
- entry = Tcl_CreateHashEntry(&bitmap_masks, (char *) &key, &new);
- Tcl_SetHashValue(entry, (ClientData) b_bits);
}
-
- return b_bits;
+ if (!this->i.gl.texobj) {
+ glGenTextures(1, &this->i.gl.texobj);
+ /*printf("creation texture %d pour image %s\n",
+ this->i.gl.texobj, ZnNameOfImage(this));*/
+ glBindTexture(GL_TEXTURE_2D, this->i.gl.texobj);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ if (ZnImageIsBitmap(image)) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4,
+ this->bits->t_width, this->bits->t_height,
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, this->bits->t_bits);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ this->bits->t_width, this->bits->t_height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, this->bits->t_bits);
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ *t = this->bits->t;
+ *s = this->bits->s;
+ return this->i.gl.texobj;
}
+#endif
+
#ifdef GLX
+/* Copyright (c) Mark J. Kilgard, 1997. */
+
+/* This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain. */
+
#define MAX_GLYPHS_PER_GRAB 512 /* this is big enough for 2^9 glyph
* character sets */
typedef struct {
+ unsigned short c; /* Potentially support 16-bit glyphs. */
+ unsigned char width;
+ unsigned char height;
+ char xoffset;
+ char yoffset;
+ char advance;
+ char dummy; /* Space holder for alignment reasons. */
+ short x;
+ short y;
+} TexGlyphInfo;
+
+typedef struct _TexFontInfo {
+ GLuint texobj;
+ struct _TexFont *txf;
+ WidgetInfo *wi;
+ int refcount;
+ struct _TexFontInfo *next;
+} TexFontInfo;
+
+typedef struct _TexFont {
+ TexFontInfo *tfi;
+ ZnFont tkfont;
+ int tex_width;
+ int tex_height;
+ int max_ascent;
+ int max_descent;
+ int num_glyphs;
+ int min_glyph;
+ int range;
+ unsigned char *teximage;
+ TexGlyphInfo *tgi;
+ ZnTexGVI *tgvi;
+ ZnTexGVI **lut;
+ Tcl_HashEntry *hash;
+} TexFont;
+
+typedef struct {
short width;
short height;
short xoffset;
@@ -504,7 +1007,8 @@ placeGlyph(FontInfoPtr font,
int width, height, spanLength;
int i, j;
- /*printf("x: %d, y: %d, c: %d, texarea: 0x%X\n", x, y, c, texarea);*/
+ /*printf("x: %d, y: %d, c: %d, texarea: 0x%X, stride: %d\n",
+ x, y, c, texarea, stride);*/
if ((c < font->min_char) || (c > font->max_char)) {
return;
}
@@ -514,10 +1018,9 @@ placeGlyph(FontInfoPtr font,
width = glyph->width;
spanLength = (width + 7) / 8;
height = glyph->height;
-
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
- texarea[stride * (y+i) + x + j] = (bitmapData[i*spanLength + j/8] & (1<<(j&7))) ? 255 : 0;
+ texarea[stride * (y+i) + x + j] = (bitmapData[i*spanLength + j/8] & (1<<(j&7))) ? 255 : 0;
}
}
}
@@ -637,10 +1140,10 @@ SuckGlyphsFromServer(ZnWindow win,
spanLength = (charWidth + 7) / 8;
}
bitmapData = ZnMalloc(height * spanLength * sizeof(char));
- memset(bitmapData, 0, height * spanLength * sizeof(char));
if (bitmapData == NULL) {
goto FreeFontAndReturn;
}
+ memset(bitmapData, 0, height * spanLength * sizeof(char));
for (y = 0; y < charHeight; y++) {
for (x = 0; x < charWidth; x++) {
/* XXX The algorithm used to suck across the font ensures that
@@ -694,52 +1197,137 @@ SuckGlyphsFromServer(ZnWindow win,
/*
**********************************************************************************
*
- * GetTexFont --
+ * ZnGetTexFont --
*
**********************************************************************************
*/
-TexFont *
-GetTexFont(ZnWindow win,
- ZnFont font)
+ZnTexFontInfo
+ZnGetTexFont(WidgetInfo *wi,
+ ZnFont font)
{
- unsigned char *glisto = " ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijmklmnopqrstuvwxyz?.;,!*:\"'èéêëïîôâàçûùü/+@#$%^&~{[|`]}()=\\-_<>\t\024\025\026\027";
- unsigned char *glist=NULL, *glist2=NULL;
TexFont *txf;
- TexGlyphInfo *tgi;
- int i, j;
- int min_glyph, max_glyph;
- int gap = 1; /* gap between glyphs */
- int px, py, maxheight;
- int new, width, height;
- GLfloat xstep, ystep, texw, texh;
+ TexFontInfo *tfi;
static int inited = 0;
Tcl_HashEntry *entry;
- int max_tex_size[1];
-
+ char *fontname = Tk_NameOfFont(font);
+ int new;
+
if (!inited) {
- Tcl_InitHashTable(&font_textures, sizeof(ZnFont)/sizeof(int));
+ Tcl_InitHashTable(&font_textures, TCL_STRING_KEYS);
inited = 1;
}
- entry = Tcl_FindHashEntry(&font_textures, (char *) font);
+ entry = Tcl_FindHashEntry(&font_textures, fontname);
if (entry != NULL) {
- return (TexFont *) Tcl_GetHashValue(entry);
+ /*printf("found font: %s\n", fontname);*/
+ txf = (TexFont *) Tcl_GetHashValue(entry);
}
else {
- txf = (TexFont *) ZnMalloc(sizeof(TexFont));
+ /*printf("new font: |%s|\n", fontname);*/
+ txf = ZnMalloc(sizeof(TexFont));
if (txf == NULL) {
- goto error;
+ return NULL;
}
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, max_tex_size);
+ txf->tfi = NULL;
txf->tgi = NULL;
txf->tgvi = NULL;
txf->lut = NULL;
txf->teximage = NULL;
+ txf->tkfont = font;
+
+ entry = Tcl_CreateHashEntry(&font_textures, fontname, &new);
+ Tcl_SetHashValue(entry, (ClientData) txf);
+ txf->hash = entry;
+ }
+
+ /*
+ * Now locate the texture obj in the texture list for this widget.
+ */
+ tfi = txf->tfi;
+ while (tfi != NULL) {
+ if (tfi->wi == wi) {
+ tfi->refcount++;
+ return tfi;
+ }
+ }
+ /*
+ * Not found allocate a new texture object.
+ */
+ tfi = ZnMalloc(sizeof(TexFontInfo));
+ if (tfi == NULL) {
+ ZnFree(txf);
+ return NULL;
+ }
+ tfi->refcount = 1;
+ tfi->texobj = 0;
+ tfi->wi = wi;
+ tfi->txf = txf;
+ tfi->next = txf->tfi;
+ txf->tfi = tfi;
+
+ return tfi;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * ZnNameOfTexFont --
+ *
+ **********************************************************************************
+ */
+char *
+ZnNameOfTexFont(ZnTexFontInfo tfi)
+{
+ return Tcl_GetHashKey(&font_textures, ((TexFontInfo *) tfi)->txf->hash);
+}
+
+/*
+ **********************************************************************************
+ *
+ * ZnTexFontTex --
+ *
+ **********************************************************************************
+ */
+GLuint
+ZnTexFontTex(ZnTexFontInfo tfi)
+{
+ TexFontInfo *this = (TexFontInfo *) tfi;
+ TexFont *txf = this->txf;
+ unsigned char *glisto = " ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijmklmnopqrstuvwxyz?.;,!*:\"'èéêëïîôâàçûùü/+@#$%^&~{[|`]}()=\\-_<>\t\024\025\026\027";
+ unsigned char *glist=NULL, *glist2=NULL;
+ TexGlyphInfo *tgi;
+ int i, j;
+ int min_glyph, max_glyph;
+ int gap = 1; /* gap between glyphs */
+ int px, py, maxheight;
+ int width, height;
+ GLfloat xstep, ystep, texw, texh;
+ GLuint max_tex_size[1];
+
+ if (!txf->teximage) {
+ /*printf("Chargement de la texture pour la fonte %s\n",
+ ZnNameOfTexFont(tfi));*/
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, max_tex_size);
+ fontinfo = SuckGlyphsFromServer(this->wi->win, txf->tkfont);
+ if (fontinfo == NULL) {
+ goto error;
+ }
+ txf->max_ascent = fontinfo->max_ascent;
+ txf->max_descent = fontinfo->max_descent;
+ txf->num_glyphs = strlen(glisto);
+
/*
* Initial size of texture.
- * Assume that max_tex_size is at least 256 texels.
+ * Assume that max_tex_size is at least 128 texels.
*/
texw = 128;
texh = 64;
+ while (texh < txf->max_ascent+txf->max_descent) {
+ texh *= 2;
+ }
+ if (texh > max_tex_size[0]) {
+ goto error;
+ }
xstep = 0/*0.5 / texw*/;
ystep = 0/*0.5 / texh*/;
@@ -749,20 +1337,11 @@ GetTexFont(ZnWindow win,
}
/*memset(txf->teximage, 0x55, texw * texh * sizeof(unsigned char));*/
- fontinfo = SuckGlyphsFromServer(win, font);
- if (fontinfo == NULL) {
- goto error;
- }
-
- txf->max_ascent = fontinfo->max_ascent;
- txf->max_descent = fontinfo->max_descent;
- txf->num_glyphs = strlen(glisto);
-
- txf->tgi = (TexGlyphInfo *) ZnMalloc(txf->num_glyphs * sizeof(TexGlyphInfo));
+ txf->tgi = ZnMalloc(txf->num_glyphs * sizeof(TexGlyphInfo));
if (txf->tgi == NULL) {
goto error;
}
- txf->tgvi = (TexGlyphVertexInfo *) ZnMalloc(txf->num_glyphs * sizeof(TexGlyphVertexInfo));
+ txf->tgvi = ZnMalloc(txf->num_glyphs * sizeof(ZnTexGVI));
if (txf->tgvi == NULL) {
goto error;
}
@@ -776,7 +1355,7 @@ GetTexFont(ZnWindow win,
*/
glist2 = ZnMalloc((txf->num_glyphs+1) * sizeof(unsigned char));
strcpy(glist2, glist);
-
+
restart:
px = gap;
py = gap;
@@ -910,24 +1489,15 @@ GetTexFont(ZnWindow win,
txf->min_glyph = min_glyph;
txf->range = max_glyph - min_glyph + 1;
- txf->lut = (TexGlyphVertexInfo **) ZnMalloc(txf->range * sizeof(TexGlyphVertexInfo *));
- memset(txf->lut, 0, txf->range * sizeof(TexGlyphVertexInfo *));
+ txf->lut = ZnMalloc(txf->range * sizeof(ZnTexGVI *));
if (txf->lut == NULL) {
goto error;
}
+ memset(txf->lut, 0, txf->range * sizeof(ZnTexGVI *));
for (i = 0; i < txf->num_glyphs; i++) {
txf->lut[txf->tgi[i].c - txf->min_glyph] = &txf->tgvi[i];
}
- glGenTextures(1, &txf->texobj);
- glBindTexture(GL_TEXTURE_2D, txf->texobj);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4, txf->tex_width, txf->tex_height, 0,
- GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
-
for (i = 0; i < fontinfo->num_glyphs; i++) {
if (fontinfo->glyph[i].bitmap)
ZnFree(fontinfo->glyph[i].bitmap);
@@ -935,11 +1505,23 @@ GetTexFont(ZnWindow win,
ZnFree(fontinfo);
ZnFree(glist);
ZnFree(glist2);
+ }
- entry = Tcl_CreateHashEntry(&font_textures, (char *) font, &new);
- Tcl_SetHashValue(entry, (ClientData) txf);
- return txf;
+ if (!this->texobj) {
+ glGenTextures(1, &this->texobj);
+ /*printf("creation texture %d pour la fonte %s\n",
+ this->texobj, ZnNameOfTexFont(tfi));*/
+ glBindTexture(GL_TEXTURE_2D, this->texobj);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4, txf->tex_width, txf->tex_height,
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
+
+ return this->texobj;
error:
if (glist) {
@@ -955,247 +1537,149 @@ GetTexFont(ZnWindow win,
}
ZnFree(fontinfo);
}
- if (txf) {
- if (txf->tgi) {
- ZnFree(txf->tgi);
- }
- if (txf->tgvi) {
- ZnFree(txf->tgvi);
- }
- if (txf->lut) {
- ZnFree(txf->lut);
- }
- if (txf->teximage) {
- ZnFree(txf->teximage);
- }
- ZnFree(txf);
+
+ if (txf->tgi) {
+ ZnFree(txf->tgi);
+ txf->tgi = NULL;
}
- return NULL;
+ if (txf->tgvi) {
+ ZnFree(txf->tgvi);
+ txf->tgvi = NULL;
+ }
+ if (txf->lut) {
+ ZnFree(txf->lut);
+ txf->lut = NULL;
+ }
+ if (txf->teximage) {
+ ZnFree(txf->teximage);
+ txf->teximage = NULL;
+ }
+
+ return 0;
}
+
/*
- * Working only for 16 bits displays with 5r6g5b mask,
- * and 24/32 bits displays. Byte ordering ok on Intel
- * plateform only.
+ **********************************************************************************
+ *
+ * ZnFreeTexFont --
+ *
+ **********************************************************************************
*/
void
-From5r6g5b(unsigned char *data,
- int width,
- int height,
- int bytes_per_line,
- int t_width,
- int t_height,
- BitmapBits *b_bits,
- unsigned char *t_bits)
+ZnFreeTexFont(ZnTexFontInfo tfi)
{
- int x, y;
- int rowstride = t_width * 4;
- unsigned char *obptr;
- unsigned char *bptr, *bp2;
- unsigned char alpha;
- unsigned short temp;
-
- bptr = t_bits;
-
- for (y = 0; y < height; y++) {
- bp2 = bptr;
- obptr = data;
- for (x = 0; x < width; x++) {
- /*
- * Configure the alpha value.
- */
- alpha = GetBitmapPixel(b_bits, x, y) ? 255 : 0;
+ TexFontInfo *this = ((TexFontInfo *) tfi);
+ TexFont *txf = this->txf;
+ TexFontInfo *prev, *scan;
- /*
- * Dispatch the 3 color components.
- */
- temp = ((unsigned short *)obptr)[0];
- *bp2 = (temp >> 8) & 0xf8; /* r */
- bp2++;
- *bp2 = (temp >> 3) & 0xfc; /* v */
- bp2++;
- *bp2 = (temp << 3); /* b */
- bp2++;
- *bp2 = alpha;
- bp2++;
- obptr += 2;
- }
- for (x = width; x < t_width; x++) {
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- }
- bptr += rowstride;
- data += bytes_per_line;
- }
- for (y = height; y < t_height; y++) {
- memset(bptr, 0, rowstride);
- bptr += rowstride;
+ for (prev=NULL, scan=this->txf->tfi; (scan!=NULL)&&(scan != this);
+ prev=scan, scan=this->next);
+ if (scan != this) {
+ return;
}
-}
-void
-From8r8g8b(unsigned char *data,
- int width,
- int height,
- int bytes_per_line,
- int t_width,
- int t_height,
- BitmapBits *b_bits,
- unsigned char *t_bits)
-{
- int x, y;
- int rowstride = t_width * 4;
- unsigned char *obptr;
- unsigned char *bptr, *bp2;
- unsigned char alpha;
-
- bptr = t_bits;
-
- for (y = 0; y < height; y++) {
- bp2 = bptr;
- obptr = data;
- for (x = 0; x < width; x++) {
- /*
- * Configure the alpha value.
- */
- alpha = GetBitmapPixel(b_bits, x, y) ? 255 : 0;
+ /*
+ * Decrement tex font object refcount.
+ */
+ this->refcount--;
+ if (this->refcount != 0) {
+ return;
+ }
- /*
- * Dispatch the 3 color components.
- * Be careful the Red and Blue are swapped it works on an Intel
- * plateform but may need some more tests to be fully generic.
- */
- *bp2++ = obptr[2]; /* r */
- *bp2++ = obptr[1]; /* v */
- *bp2++ = obptr[0]; /* b */
- obptr += 4;
- *bp2++ = alpha;
- }
- for (x = width; x < t_width; x++) {
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- }
- bptr += rowstride;
- data += bytes_per_line;
+ /*
+ * Unlink the deleted tex font info.
+ */
+ if (prev == NULL) {
+ txf->tfi = this->next;
}
- for (y = height; y < t_height; y++) {
- memset(bptr, 0, rowstride);
- bptr += rowstride;
+ else {
+ prev->next = this->next;
+ }
+ if (this->texobj) {
+ /*printf("Libération de la texture %d pour la fonte %s\n",
+ this->texobj, ZnNameOfTexFont(tfi));*/
+ glDeleteTextures(1, &this->texobj);
}
-}
-
-static int
-To2Power(int a)
-{
- int result = 1;
- while (result < a) {
- result *= 2;
+ /*
+ * There is no more client for this font
+ * deallocate the structures.
+ */
+ if (txf->tfi == NULL) {
+ /*printf("destruction complète du txf pour %s\n",
+ ZnNameOfTexFont(tfi));*/
+ ZnFree(txf->tgi);
+ ZnFree(txf->tgvi);
+ ZnFree(txf->lut);
+ ZnFree(txf->teximage);
+ ZnFree(txf);
+ Tcl_DeleteHashEntry(txf->hash);
}
- return result;
+
+ ZnFree(this);
}
-
-ImageBits *
-GetImageTexture(ZnWindow win,
- char *image_name,
- ZnImage image)
+
+/*
+ **********************************************************************************
+ *
+ * ZnCharInTexFont --
+ *
+ **********************************************************************************
+ */
+ZnBool
+ZnCharInTexFont(ZnTexFontInfo tfi,
+ int c)
{
- ImageBits *im_bits;
- int t_width, t_height;
- int depth = Tk_Depth(win);
- /* int error;*/
-
- im_bits = GetImageBits(win, image_name, image);
- if (!im_bits->t_bits) {
- t_width = To2Power(im_bits->width);
- t_height = To2Power(im_bits->height);
- im_bits->s = im_bits->width / (ZnReal) t_width;
- im_bits->t = im_bits->height / (ZnReal) t_height;
- im_bits->t_bits = ZnMalloc(t_width * 4 * t_height);
- if (depth == 16) {
- From5r6g5b(im_bits->pixels->data, im_bits->width, im_bits->height,
- im_bits->pixels->bytes_per_line, t_width, t_height,
- im_bits->b_bits, im_bits->t_bits);
- }
- else if (depth == 24) {
- From8r8g8b(im_bits->pixels->data, im_bits->width, im_bits->height,
- im_bits->pixels->bytes_per_line, t_width, t_height,
- im_bits->b_bits, im_bits->t_bits);
- }
+ TexFont *txf = ((TexFontInfo *) tfi)->txf;
- glGenTextures(1, &im_bits->texture);
- /*printf("creation texture %d pour image %s\n", im_bits->texture, image_name);*/
- glBindTexture(GL_TEXTURE_2D, im_bits->texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t_width, t_height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, im_bits->t_bits);
- /*
- error = glGetError();
- if (error != GL_NO_ERROR) {
- printf("GetImageTexture: %s\n", gluErrorString(error));
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ if (txf->lut[c - txf->min_glyph]) {
+ return True;
}
- */
}
-
- return im_bits;
+ return False;
}
-BitmapBits *
-GetBitmapTexture(Display *dpy,
- Pixmap bitmap)
+/*
+ **********************************************************************************
+ *
+ * ZnTexFontGVI --
+ *
+ **********************************************************************************
+ */
+ZnTexGVI *
+ZnTexFontGVI(ZnTexFontInfo tfi,
+ int c)
{
- BitmapBits *b_bits;
- int t_width, t_height;
- int i, j;
- unsigned char *o, *ostart, *d, *dstart;
-
- b_bits = GetBitmapMask(dpy, bitmap);
- if (!b_bits->texture) {
- t_width = To2Power(b_bits->width);
- t_height = To2Power(b_bits->height);
- b_bits->s = b_bits->width / (ZnReal) t_width;
- b_bits->t = b_bits->height / (ZnReal) t_height;
- b_bits->t_bits = ZnMalloc(t_width * t_height);
- memset(b_bits->t_bits, 0, t_width * t_height);
-
- ostart = b_bits->pixels;
- dstart = b_bits->t_bits;
- for (i = 0; i < b_bits->height; i++) {
- d = dstart;
- o = ostart;
- for (j = 0; j < b_bits->width; j++) {
- *d++ = GetBitmapPixel(b_bits, j, i) ? 255 : 0;
+ TexFont *txf = ((TexFontInfo *) tfi)->txf;
+ ZnTexGVI *tgvi;
+
+ /* Automatically substitute uppercase letters with lowercase if not
+ uppercase available (and vice versa). */
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ tgvi = txf->lut[c - txf->min_glyph];
+ if (tgvi) {
+ return tgvi;
+ }
+ if (islower(c)) {
+ c = toupper(c);
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ return txf->lut[c - txf->min_glyph];
+ }
+ }
+ if (isupper(c)) {
+ c = tolower(c);
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ return txf->lut[c - txf->min_glyph];
}
- ostart += b_bits->rowstride;
- dstart += t_width;
}
-
- glGenTextures(1, &b_bits->texture);
- glBindTexture(GL_TEXTURE_2D, b_bits->texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4, t_width, t_height, 0,
- GL_LUMINANCE, GL_UNSIGNED_BYTE, b_bits->t_bits);
}
-
- return b_bits;
+ fprintf(stderr,
+ "Tried to access unavailable texture font character '%c'(\\0%o)\n",
+ c, c);
+ return txf->lut[(int)'!' - txf->min_glyph];
}
+
#endif