aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2004-03-04 08:39:15 +0000
committerlecoanet2004-03-04 08:39:15 +0000
commit653a94a4a40c2f1c01bdda9345c999f91c310b27 (patch)
tree48761acfbea96f5224f12a452e9d821d3ec26e7b /generic
parent34e9e2a7e4795e28f8189617f67adb32c0c91c2f (diff)
downloadtkzinc-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')
-rw-r--r--generic/Image.c111
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)
{