diff options
author | lecoanet | 2004-03-04 08:39:15 +0000 |
---|---|---|
committer | lecoanet | 2004-03-04 08:39:15 +0000 |
commit | 653a94a4a40c2f1c01bdda9345c999f91c310b27 (patch) | |
tree | 48761acfbea96f5224f12a452e9d821d3ec26e7b /generic/Image.c | |
parent | 34e9e2a7e4795e28f8189617f67adb32c0c91c2f (diff) | |
download | tkzinc-653a94a4a40c2f1c01bdda9345c999f91c310b27.zip tkzinc-653a94a4a40c2f1c01bdda9345c999f91c310b27.tar.gz tkzinc-653a94a4a40c2f1c01bdda9345c999f91c310b27.tar.bz2 tkzinc-653a94a4a40c2f1c01bdda9345c999f91c310b27.tar.xz |
* Adaptation for perl/Tk 804.
* Changed the image texture handling code now that only
one context is kept for each display.
* A reference count is kept for images with multiple clients
with same proc/procdata. This will prevent early deallocation
in this case.
* Fixed a bug in the image update procedure when re-creating
an existing image. The transient deleted state was not
properly handled and the type of image can change in the process
as well as the pointer to the photo structure.
* Font texture is cached once per display instead of once per
widget.
Diffstat (limited to 'generic/Image.c')
-rw-r--r-- | generic/Image.c | 111 |
1 files changed, 73 insertions, 38 deletions
diff --git a/generic/Image.c b/generic/Image.c index 7802b31..09ecdd3 100644 --- a/generic/Image.c +++ b/generic/Image.c @@ -38,6 +38,7 @@ #include <stdlib.h> #endif +#include <tkFont.h> static const char rcsid[] = "$Id$"; static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; @@ -52,6 +53,7 @@ static Tcl_HashTable font_textures; typedef struct _ClientStruct { void (*inv_proc)(void *cd); void *client_data; + int refcount; } ClientStruct; typedef struct _ImageStruct { @@ -132,14 +134,17 @@ InvalidateImage(ClientData client_data, int y __unused, int width __unused, int height __unused, - int image_width __unused, - int image_height __unused) + int image_width, + int image_height) { ImageBits *bits = (ImageBits *) client_data; Image this; int num_cs, count, i; ClientStruct *cs; + char *image_name; + /* printf("Invalidation, bits: %d, %d %d %d %d %d %d\n", + client_data, x, y, width, height, image_width, image_height);*/ if (ZnImageIsBitmap(bits->images)) { /* This is a bitmap nothing to update * (This should not happen) */ @@ -157,15 +162,20 @@ InvalidateImage(ClientData client_data, bits->valid_region = NULL; } + bits->width = image_width; + bits->height = image_height; + image_name = ZnNameOfImage(bits->images); + + /* + * The photo pointer must be updated. It changes when creating an new image with + * the same name as an old. The image is first deleted then re-instantiated. + * As a side effect we also rely on it for telling if an image is a photo. + */ + bits->tkphoto = Tk_FindPhoto(bits->wi->interp, image_name); + count = 0; this = bits->images; while (this) { - if (bits->tkphoto) { - Tk_PhotoGetSize(bits->tkphoto, &bits->width, &bits->height); - } - else { - Tk_SizeOfImage(bits->tkimage, &bits->width, &bits->height); - } #ifdef GL if (this->for_gl) { if (this->i.texobj) { @@ -197,7 +207,6 @@ InvalidateImage(ClientData client_data, } /*printf("Invalidate on image %s with %d clients\n", Tcl_GetHashKey(&images, bits->hash), count);*/ - } ZnImage @@ -222,11 +231,11 @@ ZnGetImage(ZnWInfo *wi, image_name = Tk_GetUid(image_name); entry = Tcl_FindHashEntry(&images, image_name); if (entry != NULL) { - /*printf("Image %s déjà connue\n", image_name);*/ + /*printf("Image \"%s\" is in cache\n", image_name);*/ bits = (ImageBits *) Tcl_GetHashValue(entry); } else { - /*printf("Nouvelle Image %s\n", image_name);*/ + /*printf("New image \"%s\"\n", image_name);*/ if (strcmp(image_name, "") == 0) { return ZnUnspecifiedImage; } @@ -314,7 +323,7 @@ ZnGetImage(ZnWInfo *wi, */ for (image = bits->images; image != NULL; image = image->next) { if (image->for_gl == for_gl) { - if ((for_gl && (image->wi == wi)) || + if ((for_gl && (image->wi->dpy == wi->dpy)) || (!for_gl && (image->wi->screen == wi->screen))) { if (!ZnImageIsBitmap(image)) { cs_ptr = ZnListArray(image->clients); @@ -322,6 +331,7 @@ ZnGetImage(ZnWInfo *wi, for (i = 0; i < num_cs; i++, cs_ptr++) { if ((cs_ptr->inv_proc == inv_proc) && (cs_ptr->client_data == client_data)) { + cs_ptr->refcount++; return image; } } @@ -329,7 +339,9 @@ ZnGetImage(ZnWInfo *wi, */ cs.inv_proc = inv_proc; cs.client_data = client_data; + cs.refcount = 1; ZnListAdd(image->clients, &cs, ZnListTail); + return image; } image->refcount++; return image; @@ -340,9 +352,10 @@ ZnGetImage(ZnWInfo *wi, /* * Create a new instance for this case. */ + /*printf("new instance for \"%s\"\n", image_name);*/ image = ZnMalloc(sizeof(ImageStruct)); image->bits = bits; - image->refcount = 1; + image->refcount = 0; image->for_gl = for_gl; image->wi = wi; @@ -350,8 +363,12 @@ ZnGetImage(ZnWInfo *wi, image->clients = ZnListNew(1, sizeof(ClientStruct)); cs.inv_proc = inv_proc; cs.client_data = client_data; + cs.refcount = 1; ZnListAdd(image->clients, &cs, ZnListTail); } + else { + image->refcount++; + } /* Init the real resource and let the client load it * on demand */ @@ -395,15 +412,19 @@ ZnGetImageByValue(ZnImage image, for (i = 0; i < num_cs; i++, cs_ptr++) { if ((cs_ptr->inv_proc == inv_proc) && (cs_ptr->client_data == client_data)) { + cs_ptr->refcount++; return image; } } cs.inv_proc = inv_proc; cs.client_data = client_data; + cs.refcount = 1; ZnListAdd(this->clients, &cs, ZnListTail); } + else { + this->refcount++; + } - this->refcount++; return image; } @@ -435,7 +456,7 @@ ZnFreeImage(ZnImage image, Image prev, scan, this = ((Image) image); ImageBits *bits = this->bits; ClientStruct *cs_ptr; - int i, num_cs; + int i, num_cs, rm_image; /*printf("ZnFreeImage: %s\n", ZnNameOfImage(image));*/ /* @@ -453,16 +474,21 @@ ZnFreeImage(ZnImage image, for (i = 0; i < num_cs; i++, cs_ptr++) { if ((cs_ptr->inv_proc == inv_proc) && (cs_ptr->client_data == client_data)) { - ZnListDelete(this->clients, i); - this->refcount--; + cs_ptr->refcount--; + if (cs_ptr->refcount == 0) { + ZnListDelete(this->clients, i); + } break; } } + rm_image = ZnListSize(this->clients)==0; } else { this->refcount--; + rm_image = this->refcount==0; } - if (this->refcount != 0) { + + if (!rm_image) { return; } @@ -478,9 +504,12 @@ ZnFreeImage(ZnImage image, if (this->for_gl) { #ifdef GL ZnWInfo *wi = this->wi; - if (this->i.texobj && wi->win) { + if (this->i.texobj) { ZnGLMakeCurrent(wi); + /* printf("%d Libération de la texture %d pour l'image %s\n", + wi, this->i.texobj, ZnNameOfImage(image));*/ glDeleteTextures(1, &this->i.texobj); + this->i.texobj = 0; ZnGLRelease(wi); } #endif @@ -954,6 +983,7 @@ ZnImageTex(ZnImage image, t_stride = bits->t_width * 4; t_size = t_stride * bits->t_height; + /*printf("t_width: %d(%d), t_height: %d(%d)\n", bits->t_width, width, bits->t_height, height);*/ bits->t_bits = ZnMalloc(t_size); Tk_PhotoGetImage(bits->tkphoto, &block); green_off = block.offset[1] - block.offset[0]; @@ -1006,8 +1036,8 @@ ZnImageTex(ZnImage image, if (!this->i.texobj) { glGenTextures(1, &this->i.texobj); - /*printf("creation texture %d pour image %s\n", - this->i.texobj, ZnNameOfImage(this));*/ + /*printf("%d creation texture %d pour image %s\n", + bits, this->i.texobj, ZnNameOfImage(this));*/ glBindTexture(GL_TEXTURE_2D, this->i.texobj); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -1027,7 +1057,7 @@ ZnImageTex(ZnImage image, if (glGetError() != GL_NO_ERROR) { ZnWarning("Can't allocate the texture for image "); ZnWarning(ZnNameOfImage(image)); - ZnWarning("\n"); + ZnWarning("\n"); } glBindTexture(GL_TEXTURE_2D, 0); } @@ -1063,8 +1093,8 @@ typedef struct { } TexGlyphInfo; typedef struct _TexFontInfo { - GLuint texobj; struct _TexFont *txf; + GLuint texobj; ZnWInfo *wi; unsigned int refcount; struct _TexFontInfo *next; @@ -1084,7 +1114,7 @@ typedef struct _TexFont { TexGlyphInfo *tgi; ZnTexGVI *tgvi; ZnTexGVI **lut; -#ifndef PTK +#ifndef PTK_800 Tcl_Encoding enc; #endif Tcl_HashEntry *hash; @@ -1193,7 +1223,7 @@ placeGlyph(FontInfoPtr font, } } -#ifdef PTK +#ifdef PTK_800 FontInfoPtr SuckGlyphsFromServer(ZnWInfo *wi, Tk_Font font) @@ -1211,7 +1241,7 @@ SuckGlyphsFromServer(ZnWInfo *wi, unsigned int width, height, length, pixwidth; unsigned int i, j; char str_from[] = " "; -#ifndef PTK +#ifndef PTK_800 char str_utf[8]; #endif unsigned char *bitmapData = NULL; @@ -1246,7 +1276,7 @@ SuckGlyphsFromServer(ZnWInfo *wi, width = 0; for (i = 0; i < myfontinfo->num_glyphs; i++) { *str_from = i + myfontinfo->min_char; -#ifdef PTK +#ifdef PTK_800 Tk_MeasureChars(font, str_from, 1, 0, TK_AT_LEAST_ONE, &length); #else Tcl_ExternalToUtf(wi->interp, enc, str_from, 1, @@ -1289,7 +1319,7 @@ SuckGlyphsFromServer(ZnWInfo *wi, numToGrab = 0; for (i = 0; i < myfontinfo->num_glyphs; i++) { *str_from = i + myfontinfo->min_char; -#ifdef PTK +#ifdef PTK_800 Tk_MeasureChars(font, str_from, 1, 0, TK_AT_LEAST_ONE, &charWidth); #else Tcl_ExternalToUtf(wi->interp, enc, str_from, 1, @@ -1305,7 +1335,7 @@ SuckGlyphsFromServer(ZnWInfo *wi, myfontinfo->glyph[i].advance = charWidth; myfontinfo->glyph[i].bitmap = NULL; if (charWidth != 0) { -#ifdef PTK +#ifdef PTK_800 Tk_DrawChars(wi->dpy, offscreen, xgc, font, str_from, 1, (int) (8*maxSpanLength*numToGrab), myfontinfo->ascent); #else @@ -1376,7 +1406,7 @@ SuckGlyphsFromServer(ZnWInfo *wi, return NULL; } -#ifndef PTK +#ifndef PTK_800 Tcl_Encoding ZnGetFontEncoding(ZnWInfo *wi, Tk_Font tkfont) @@ -1457,12 +1487,17 @@ ZnGetTexFont(ZnWInfo *wi, int width, height; unsigned int texw, texh; GLfloat xstep, ystep; + TkFont *tft = (TkFont *) font; if (!inited) { Tcl_InitHashTable(&font_textures, TCL_ONE_WORD_KEYS); inited = 1; } + /* printf("family: %s, size: %d, weight: %d, slant: %d, underline: %d, overstrike: %d\n", + tft->fa.family, tft->fa.size, tft->fa.weight, tft->fa.slant, tft->fa.underline, + tft->fa.overstrike); + */ entry = Tcl_FindHashEntry(&font_textures, (char *) font); if (entry != NULL) { txf = (TexFont *) Tcl_GetHashValue(entry); @@ -1480,13 +1515,13 @@ ZnGetTexFont(ZnWInfo *wi, /* Get a local reference to the font, it will be deallocated * when no further references on this TexFont exist. */ txf->tkfont = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(font)); -#ifndef PTK +#ifndef PTK_800 txf->enc = ZnGetFontEncoding(wi, txf->tkfont); #endif /*printf("Chargement de la texture pour la fonte %s\n", ZnNameOfTexFont(tfi));*/ -#ifdef PTK +#ifdef PTK_800 fontinfo = SuckGlyphsFromServer(wi, txf->tkfont); #else fontinfo = SuckGlyphsFromServer(wi, txf->tkfont, txf->enc); @@ -1714,7 +1749,7 @@ ZnGetTexFont(ZnWInfo *wi, ZnFree(txf->teximage); txf->teximage = NULL; } -#ifndef PTK +#ifndef PTK_800 Tcl_FreeEncoding(txf->enc); #endif Tk_FreeFont(txf->tkfont); @@ -1747,7 +1782,7 @@ ZnGetTexFont(ZnWInfo *wi, * Now locate the texture obj in the texture list for this widget. */ for (tfi = txf->tfi; tfi != NULL; tfi = tfi->next) { - if (tfi->wi == wi) { + if (tfi->wi->dpy == wi->dpy) { tfi->refcount++; return tfi; } @@ -1760,9 +1795,9 @@ ZnGetTexFont(ZnWInfo *wi, return NULL; } tfi->refcount = 1; - tfi->texobj = 0; tfi->wi = wi; tfi->txf = txf; + tfi->texobj = 0; tfi->next = txf->tfi; txf->tfi = tfi; @@ -1861,7 +1896,7 @@ ZnFreeTexFont(ZnTexFontInfo tfi) else { prev->next = this->next; } - if (this->texobj && wi->win) { + if (this->texobj) { /*printf("%d Libération de la texture %d pour la fonte %s\n", wi, this->texobj, ZnNameOfTexFont(tfi));*/ ZnGLMakeCurrent(wi); @@ -1880,7 +1915,7 @@ ZnFreeTexFont(ZnTexFontInfo tfi) ZnFree(txf->tgvi); ZnFree(txf->lut); ZnFree(txf->teximage); -#ifndef PTK +#ifndef PTK_800 Tcl_FreeEncoding(txf->enc); #endif Tcl_DeleteHashEntry(txf->hash); @@ -1918,7 +1953,7 @@ ZnCharInTexFont(ZnTexFontInfo tfi, * ********************************************************************************** */ -#ifndef PTK +#ifndef PTK_800 Tcl_Encoding ZnTexFontEncoding(ZnTexFontInfo tfi) { |