aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2004-04-30 14:59:46 +0000
committerlecoanet2004-04-30 14:59:46 +0000
commitc2e5e479e8c9e5e58bd1e36b2ac62e5cc8844bca (patch)
tree832580886ae7406b4baa5a53b7991d98e7967c49 /generic
parenta42310190047400463d564c39576392fadfe01f3 (diff)
downloadtkzinc-c2e5e479e8c9e5e58bd1e36b2ac62e5cc8844bca.zip
tkzinc-c2e5e479e8c9e5e58bd1e36b2ac62e5cc8844bca.tar.gz
tkzinc-c2e5e479e8c9e5e58bd1e36b2ac62e5cc8844bca.tar.bz2
tkzinc-c2e5e479e8c9e5e58bd1e36b2ac62e5cc8844bca.tar.xz
Rewritting of the font texture code.
Adaptation of the code needing GL context activation.
Diffstat (limited to 'generic')
-rw-r--r--generic/Image.c867
1 files changed, 241 insertions, 626 deletions
diff --git a/generic/Image.c b/generic/Image.c
index fd0bb60..9db3b1b 100644
--- a/generic/Image.c
+++ b/generic/Image.c
@@ -182,9 +182,11 @@ InvalidateImage(ClientData client_data,
#ifdef GL
if (this->for_gl) {
if (this->i.texobj) {
- ZnGLMakeCurrent(this->dpy, 0);
+ ZnGLContextEntry *ce;
+ /*OutputDebugString("InvalidateImage\n");*/
+ ce = ZnGLMakeCurrent(this->dpy, 0);
glDeleteTextures(1, &this->i.texobj);
- /*ZnGLRelease(this->wi);*/
+ ZnGLReleaseContext(ce);
this->i.texobj = 0;
}
}
@@ -512,12 +514,14 @@ ZnFreeImage(ZnImage image,
if (this->for_gl) {
#ifdef GL
if (this->i.texobj) {
- ZnGLMakeCurrent(this->dpy, 0);
- /* printf("%d Libération de la texture %d pour l'image %s\n",
+ ZnGLContextEntry *ce;
+ /*OutputDebugString("FreeImage\n");*/
+ ce = ZnGLMakeCurrent(this->dpy, 0);
+ /* printf("%d Liberation 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);*/
+ ZnGLReleaseContext(ce);
}
#endif
}
@@ -543,7 +547,7 @@ ZnFreeImage(ZnImage image,
* No clients for this image, it can be freed.
*/
if (bits->images == NULL) {
- /*printf("destruction complète de l'image %s\n", ZnNameOfImage(this));*/
+ /*printf("destruction complète de l'image %s\n", ZnNameOfImage(this));*/
#ifdef GL
if (bits->t_bits) {
ZnFree(bits->t_bits);
@@ -1082,233 +1086,169 @@ ZnImageTex(ZnImage image,
#ifdef GL
-/* This code is adapted from a work 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_CHAR 255
-#define MIN_CHAR 32
#define MAX_GLYPHS_PER_GRAB 256
-typedef struct {
- unsigned char c;
- char dummy; /* Space holder for alignment reasons. */
- short width;
- short height;
- short xoffset;
- short yoffset;
- short advance;
- short x;
- short y;
-} TexGlyphInfo;
-
typedef struct _TexFontInfo {
struct _TexFont *txf;
GLuint texobj;
- ZnWInfo *wi;
+ Display *dpy;
unsigned int refcount;
struct _TexFontInfo *next;
} TexFontInfo;
+typedef struct {
+ short width;
+} PerGlyphInfo, *PerGlyphInfoPtr;
+
typedef struct _TexFont {
TexFontInfo *tfi;
Tk_Font tkfont;
- int tex_width;
- int tex_height;
+ unsigned int tex_width;
+ unsigned int tex_height;
int ascent;
int descent;
- unsigned int num_glyphs;
- unsigned int min_glyph;
- unsigned int range;
+ unsigned int max_char_width;
unsigned char *teximage;
- TexGlyphInfo *tgi;
+ unsigned int num_glyphs;
+ PerGlyphInfo *glyph;
ZnTexGVI *tgvi;
- ZnTexGVI **lut;
-#ifndef PTK_800
- Tcl_Encoding enc;
-#endif
Tcl_HashEntry *hash;
} TexFont;
-typedef struct {
- short width;
- short height;
- short xoffset;
- short yoffset;
- short advance;
- unsigned char *bitmap;
-} PerGlyphInfo, *PerGlyphInfoPtr;
-typedef struct {
- int min_char;
- int max_char;
- int ascent;
- int descent;
- unsigned int num_glyphs;
- PerGlyphInfo glyph[1];
-} FontInfo, *FontInfoPtr;
-
-static FontInfoPtr fontinfo;
-
-void
-getMetric(FontInfoPtr font,
- int c,
- TexGlyphInfo *tgi)
-{
- PerGlyphInfoPtr glyph;
- unsigned char *bitmapData;
-
- tgi->c = c;
- if ((c < font->min_char) || (c > font->max_char)) {
- tgi->width = 0;
- tgi->height = 0;
- tgi->xoffset = 0;
- tgi->yoffset = 0;
- tgi->dummy = 0;
- tgi->advance = 0;
- return;
- }
- glyph = &font->glyph[c - font->min_char];
- bitmapData = glyph->bitmap;
- if (bitmapData) {
- tgi->width = glyph->width;
- tgi->height = glyph->height;
- tgi->xoffset = glyph->xoffset;
- tgi->yoffset = glyph->yoffset;
- }
- else {
- tgi->width = 0;
- tgi->height = 0;
- tgi->xoffset = 0;
- tgi->yoffset = 0;
- }
- tgi->dummy = 0;
- /*printf("\'%c\' %X %d\n", c, c, glyph->advance);*/
- tgi->advance = glyph->advance;
-}
+#ifndef PTK_800
+#include "CharsetUTF8.h"
+#else
+#include "CharsetISO8859-15.h"
+#endif
-int
-glyphCompare(const void *a,
- const void *b)
-{
- unsigned char *c1 = (unsigned char *) a;
- unsigned char *c2 = (unsigned char *) b;
- TexGlyphInfo tgi1;
- TexGlyphInfo tgi2;
-
- getMetric(fontinfo, *c1, &tgi1);
- getMetric(fontinfo, *c2, &tgi2);
- return tgi2.height - tgi1.height;
-}
-void
-placeGlyph(FontInfoPtr font,
- int c,
- unsigned char *texarea,
- unsigned int stride,
- int x,
- int y)
-{
- PerGlyphInfoPtr glyph;
- unsigned char *bitmapData;
- int width, height, spanLength;
- int i, j;
-
- /*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;
- }
- glyph = &font->glyph[c - font->min_char];
- bitmapData = glyph->bitmap;
- if (bitmapData) {
- 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;
- }
- }
- }
-}
-
-#ifdef PTK_800
-FontInfoPtr
-SuckGlyphsFromServer(ZnWInfo *wi,
- Tk_Font font)
-#else
-FontInfoPtr
+static int
SuckGlyphsFromServer(ZnWInfo *wi,
Tk_Font font,
- Tcl_Encoding enc)
-#endif
+ TexFont *txf)
{
Pixmap offscreen = 0;
XImage *image = NULL;
GC xgc = 0;
- XGCValues values;
- unsigned int width, height, length, pixwidth;
- unsigned int i, j;
- char str_from[] = " ";
-#ifndef PTK_800
- char str_utf[8];
-#endif
- unsigned char *bitmapData = NULL;
+ unsigned int height, length, pixwidth;
+ unsigned int i, j, use_max_width;
+ unsigned int wgap=2, hgap=2, tex_width, tex_height;
+ unsigned char *to;
unsigned int x, y;
- int num_chars, written, spanLength=0;
- unsigned int charWidth=0, maxSpanLength;
+ unsigned int width=0, maxSpanLength;
int grabList[MAX_GLYPHS_PER_GRAB];
unsigned int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
- unsigned int numToGrab, thisglyph;
- FontInfoPtr myfontinfo = NULL;
+ unsigned int numToGrab, glyph;
+ ZnTexGVI *tgvip;
Tk_FontMetrics fm;
+ CONST char *cur, *next;
+#ifndef PTK_800
+ Tcl_UniChar uni_ch;
+#endif
+ ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
Tk_GetFontMetrics(font, &fm);
- num_chars = (MAX_CHAR-MIN_CHAR)+1;
- myfontinfo = ZnMalloc(sizeof(FontInfo) + num_chars * sizeof(PerGlyphInfo));
- if (!myfontinfo) {
- ZnWarning("Out of memory, ");
- return NULL;
+#ifndef PTK_800
+ txf->num_glyphs = Tcl_NumUtfChars(ZnDefaultCharset, strlen(ZnDefaultCharset));
+#else
+ txf->num_glyphs = strlen(ZnDefaultCharset);
+#endif
+ txf->glyph = ZnMalloc(txf->num_glyphs * sizeof(PerGlyphInfo));
+ if (!txf->glyph) {
+ goto FreeAndReturn;
}
-
- myfontinfo->min_char = MIN_CHAR;
- myfontinfo->max_char = MAX_CHAR;
- myfontinfo->num_glyphs = num_chars;
- myfontinfo->ascent = fm.ascent;
- myfontinfo->descent = fm.descent;
+ txf->tgvi = ZnMalloc(txf->num_glyphs * sizeof(ZnTexGVI));
+ if (!txf->tgvi) {
+ goto FreeAndReturn;
+ }
+
+ txf->ascent = fm.ascent;
+ txf->descent = fm.descent;
+ txf->max_char_width = 0;
+ tex_width = tex_height = 0;
+ use_max_width = 0;
+ height = txf->ascent + txf->descent;
+ tgvip = txf->tgvi;
/*
* Compute the max character size in the font. This may be
* a bit heavy hammer style but it avoid guessing on characters
* not available in the font.
*/
- width = 0;
- for (i = 0; i < myfontinfo->num_glyphs; i++) {
- *str_from = i + myfontinfo->min_char;
-#ifdef PTK_800
- Tk_MeasureChars(font, str_from, 1, 0, TK_AT_LEAST_ONE, &length);
+ cur = ZnDefaultCharset;
+ i = 0;
+ while (*cur) {
+#ifndef PTK_800
+ next = Tcl_UtfNext(cur);
#else
- Tcl_ExternalToUtf(wi->interp, enc, str_from, 1,
- TCL_ENCODING_START|TCL_ENCODING_END,
- NULL, str_utf, 8, NULL, &written, NULL);
- Tk_MeasureChars(font, str_utf, written, 0, TK_AT_LEAST_ONE, &length);
+ next = cur + 1;
#endif
- width = MAX(width, length);
+ Tk_MeasureChars(font, cur, next - cur, 0, TK_AT_LEAST_ONE, &length);
+ txf->glyph[i].width = length;
+ txf->max_char_width = MAX(txf->max_char_width, length);
+
+ if (tex_width + length + wgap > ce->max_tex_size) {
+ tex_width = 0;
+ use_max_width = 1;
+ tex_height += height + hgap;
+ if ((tex_height > ce->max_tex_size) || (length > ce->max_tex_size)) {
+ goto FreeAndReturn;
+ }
+ }
+
+ tgvip->v0x = 0;
+ tgvip->v0y = txf->descent - height;
+ tgvip->v1x = length;
+ tgvip->v1y = txf->descent;
+ tgvip->t0x = tex_width;
+ tgvip->t0y = tex_height;
+ tgvip->t1x = tgvip->t0x + length;
+ tgvip->t1y = tgvip->t0y + height;
+ tgvip->advance = length;
+#ifndef PTK_800
+ Tcl_UtfToUniChar(cur, &uni_ch);
+ tgvip->code = uni_ch;
+#else
+ tgvip->code = *cur;
+#endif
+ tex_width += length + wgap;
+
+ cur = next;
+ i++;
+ tgvip++;
}
- if (width == 0) {
- /*
- * Something weird with the font, abort!
- */
- ZnWarning("NULL character width, ");
- goto FreeFontInfoAndReturn;
+ if (use_max_width) {
+ tex_width = ce->max_tex_size;
+ }
+ tex_height += height;
+
+ /*
+ * Round the texture size to the next power of two.
+ */
+ tex_height = To2Power(tex_height);
+ tex_width = To2Power(tex_width);
+ if ((tex_height > ce->max_tex_size) || (tex_width > ce->max_tex_size)) {
+ printf("Font doesn't fit into a texture\n");
+ goto FreeAndReturn;
+ }
+ txf->tex_width = tex_width;
+ txf->tex_height = tex_height;
+ printf("(%s) Texture size is %d x %d for %d chars (max size: %d)\n",
+ Tk_NameOfFont(font), txf->tex_width, txf->tex_height, txf->num_glyphs, ce->max_tex_size);
+
+ /*
+ * Now render the font bits into the texture.
+ */
+ txf->teximage = ZnMalloc(tex_height * tex_width);
+ if (!txf->teximage) {
+ goto FreeAndReturn;
}
- height = myfontinfo->ascent + myfontinfo->descent;
+ memset(txf->teximage, 0, tex_height * tex_width);
- maxSpanLength = (width + 7) / 8;
+ maxSpanLength = (txf->max_char_width + 7) / 8;
/* Be careful determining the width of the pixmap; the X protocol allows
pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
max out at 2^15-1 (signed short size). If the width is too large, we
@@ -1320,60 +1260,44 @@ SuckGlyphsFromServer(ZnWInfo *wi,
offscreen = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
(int) pixwidth, (int) height, 1);
- values.background = WhitePixelOfScreen(wi->screen);
- values.foreground = WhitePixelOfScreen(wi->screen);
- values.font = Tk_FontId(font);
- xgc = XCreateGC(wi->dpy, offscreen, GCBackground|GCForeground|GCFont, &values);
+ xgc = XCreateGC(wi->dpy, offscreen, 0, NULL);
+ XSetForeground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
+ XSetBackground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
XFillRectangle(wi->dpy, offscreen, xgc, 0, 0, pixwidth, height);
- values.foreground = BlackPixelOfScreen(wi->screen);
- XChangeGC(wi->dpy, xgc, GCForeground, &values);
+ XSetForeground(wi->dpy, xgc, BlackPixelOfScreen(wi->screen));
+ XSetFont(wi->dpy, xgc, Tk_FontId(font));
numToGrab = 0;
- for (i = 0; i < myfontinfo->num_glyphs; i++) {
- *str_from = i + myfontinfo->min_char;
-#ifdef PTK_800
- Tk_MeasureChars(font, str_from, 1, 0, TK_AT_LEAST_ONE, &charWidth);
-#else
- Tcl_ExternalToUtf(wi->interp, enc, str_from, 1,
- TCL_ENCODING_START|TCL_ENCODING_END,
- NULL, str_utf, 8, NULL, &written, NULL);
- Tk_MeasureChars(font, str_utf, written, 0, TK_AT_LEAST_ONE, &charWidth);
-#endif
+ cur = ZnDefaultCharset;
+ i = 0;
- myfontinfo->glyph[i].width = charWidth;
- myfontinfo->glyph[i].height = height;
- myfontinfo->glyph[i].xoffset = 0;
- myfontinfo->glyph[i].yoffset = myfontinfo->descent;
- myfontinfo->glyph[i].advance = charWidth;
- myfontinfo->glyph[i].bitmap = NULL;
- if (charWidth != 0) {
-#ifdef PTK_800
- Tk_DrawChars(wi->dpy, offscreen, xgc, font, str_from, 1,
- (int) (8*maxSpanLength*numToGrab), myfontinfo->ascent);
+ while (*cur) {
+#ifndef PTK_800
+ next = Tcl_UtfNext(cur);
#else
- Tk_DrawChars(wi->dpy, offscreen, xgc, font, str_utf, written,
- (int) (8*maxSpanLength*numToGrab), myfontinfo->ascent);
+ next = cur + 1;
#endif
+ if (txf->glyph[i].width != 0) {
+ Tk_DrawChars(wi->dpy, offscreen, xgc, font, cur, next - cur,
+ (int) (8*maxSpanLength*numToGrab), txf->ascent);
grabList[numToGrab] = i;
numToGrab++;
}
- if ((numToGrab >= glyphsPerGrab) || (i == myfontinfo->num_glyphs - 1)) {
+ if ((numToGrab >= glyphsPerGrab) || (i == txf->num_glyphs - 1)) {
image = XGetImage(wi->dpy, offscreen, 0, 0, pixwidth, height, 1, XYPixmap);
for (j = 0; j < numToGrab; j++) {
- thisglyph = grabList[j];
- charWidth = myfontinfo->glyph[thisglyph].width;
- spanLength = (charWidth + 7) / 8;
- bitmapData = ZnMalloc(height * spanLength * sizeof(char));
- if (bitmapData == NULL) {
- ZnWarning("Out of memory, ");
- goto FreeFontAndReturn;
- }
- memset(bitmapData, 0, height * spanLength * sizeof(char));
- myfontinfo->glyph[thisglyph].bitmap = bitmapData;
+ glyph = grabList[j];
+ width = txf->glyph[glyph].width;
+ tgvip = &txf->tgvi[glyph];
+ to = txf->teximage + (int) (tgvip->t0y * tex_width) + (int) tgvip->t0x;
+ tgvip->t0x = tgvip->t0x / (GLfloat) tex_width;
+ tgvip->t0y = tgvip->t0y / (GLfloat) tex_height;
+ tgvip->t1x = tgvip->t1x / (GLfloat) tex_width;
+ tgvip->t1y = tgvip->t1y / (GLfloat) tex_height;
for (y = 0; y < height; y++) {
- for (x = 0; x < charWidth; x++) {
+ for (x = 0; x < width; x++, to++) {
/* XXX The algorithm used to suck across the font ensures that
each glyph begins on a byte boundary. In theory this would
make it convienent to copy the glyph into a byte oriented
@@ -1382,97 +1306,48 @@ SuckGlyphsFromServer(ZnWInfo *wi,
could either do tighter packing in the pixmap or more
efficient extraction from the image. Oh well. */
if (XGetPixel(image, (int) (j*maxSpanLength*8) + x, y) == BlackPixelOfScreen(wi->screen)) {
- bitmapData[y * spanLength + x / 8] |= (1 << (x & 7));
- }
+ *to = 255;
+ }
}
+ to += tex_width - width;
}
}
XDestroyImage(image);
+ image = NULL;
numToGrab = 0;
/* do we need to clear the offscreen pixmap to get more? */
- if (i < myfontinfo->num_glyphs - 1) {
- values.foreground = WhitePixelOfScreen(wi->screen);
- XChangeGC(wi->dpy, xgc, GCForeground, &values);
+ if (i < txf->num_glyphs - 1) {
+ XSetForeground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
XFillRectangle(wi->dpy, offscreen, xgc, 0, 0,
8 * maxSpanLength * glyphsPerGrab, height);
- values.foreground = BlackPixelOfScreen(wi->screen);
- XChangeGC(wi->dpy, xgc, GCForeground, &values);
+ XSetForeground(wi->dpy, xgc, BlackPixelOfScreen(wi->screen));
}
}
+
+ cur = next;
+ i++;
}
XFreeGC(wi->dpy, xgc);
Tk_FreePixmap(wi->dpy, offscreen);
- return myfontinfo;
+ return 1;
- FreeFontAndReturn:
- XDestroyImage(image);
- XFreeGC(wi->dpy, xgc);
- Tk_FreePixmap(wi->dpy, offscreen);
- for (i = 0; i < myfontinfo->num_glyphs; i++) {
- if (myfontinfo->glyph[i].bitmap)
- ZnFree(myfontinfo->glyph[i].bitmap);
+ FreeAndReturn:
+ if (txf->glyph) {
+ ZnFree(txf->glyph);
+ txf->glyph = NULL;
}
- FreeFontInfoAndReturn:
- ZnFree(myfontinfo);
- return NULL;
-}
-
-#ifndef PTK_800
-Tcl_Encoding
-ZnGetFontEncoding(ZnWInfo *wi,
- Tk_Font tkfont)
-{
-#ifdef WIN
- return Tcl_GetEncoding(wi->interp, "unicode");
-#else
- Tcl_Encoding enc;
- XFontStruct *fs;
- int count;
- unsigned long prop;
- char CONST *xlfd;
- char *charset_lc=NULL;
- char *charset, *charset_def = "iso8859-1";
-
- fs = XQueryFont(wi->dpy, Tk_FontId(tkfont));
-
- charset = charset_def;
- xlfd = Tk_NameOfFont(tkfont);
- if (XGetFontProperty(fs, XInternAtom(wi->dpy, "FONT", 0), &prop) != False) {
- xlfd = charset = XGetAtomName(wi->dpy, prop);
- for (count = 0; count < 13; count++) {
- charset = strchr(charset, '-');
- if (!charset) {
- charset = charset_def;
- goto getenc;
- }
- charset++;
- }
- /* Get a lower case string */
- count = strlen(charset);
- charset_lc = ZnMalloc(count+1);
- charset_lc[count] = '\000';
- for (count--; count >= 0; count--) {
- charset_lc[count] = tolower(charset[count]);
- }
- charset = charset_lc;
- }
-
- getenc:
- enc = Tcl_GetEncoding(wi->interp, charset);
- if (charset_lc) {
- ZnFree(charset_lc);
+ if (txf->tgvi) {
+ ZnFree(txf->tgvi);
+ txf->tgvi = NULL;
}
- if (!enc) {
- ZnWarning("Unable to find encoding for font ");
- ZnWarning(xlfd);
- ZnWarning("\n");
+ if (txf->teximage) {
+ ZnFree(txf->teximage);
+ txf->teximage = NULL;
}
- return enc;
-#endif
+ return 0;
}
-#endif
/*
**********************************************************************************
@@ -1490,16 +1365,6 @@ ZnGetTexFont(ZnWInfo *wi,
static int inited = 0;
Tcl_HashEntry *entry;
int new;
- unsigned char *glist=NULL, *glist2=NULL;
- TexGlyphInfo *tgi;
- unsigned int i, j;
- int min_glyph, max_glyph;
- int gap = 1; /* gap between glyphs */
- int px, py, maxheight;
- int width, height;
- unsigned int texw, texh;
- GLfloat xstep, ystep;
- ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
if (!inited) {
Tcl_InitHashTable(&font_textures, TCL_ONE_WORD_KEYS);
@@ -1521,270 +1386,20 @@ ZnGetTexFont(ZnWInfo *wi,
return NULL;
}
txf->tfi = NULL;
- txf->tgi = NULL;
txf->tgvi = NULL;
- txf->lut = NULL;
+ txf->glyph = NULL;
+ txf->teximage = NULL;
+
/* 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_800
- txf->enc = ZnGetFontEncoding(wi, txf->tkfont);
-#endif
/*printf("Chargement de la texture pour la fonte %s\n",
ZnNameOfTexFont(tfi));*/
-#ifdef PTK_800
- fontinfo = SuckGlyphsFromServer(wi, txf->tkfont);
-#else
- fontinfo = SuckGlyphsFromServer(wi, txf->tkfont, txf->enc);
-#endif
- if (fontinfo == NULL) {
- goto error;
- }
- txf->ascent = fontinfo->ascent;
- txf->descent = fontinfo->descent;
- /*
- * Try to use all glyphs in a font except the first 32
- * control chars.
- */
- txf->num_glyphs = MAX_CHAR-MIN_CHAR+1;
-
- /*
- * Initial size of texture.
- */
- texw = ce->max_tex_size;
- texh = 64;
- while (texh < (unsigned int) (txf->ascent+txf->descent)) {
- texh *= 2;
- }
- /*printf("Taille réelle de texture utilisée: %d\n", ce->max_tex_size);*/
- /*
- * This is temporarily disabled until we find out
- * how to reliably get max_tex_size up front without
- * waiting for the window mapping.
- */
- if (texh > ce->max_tex_size) {
- goto error;
- }
- xstep = 0/*0.5 / texw*/;
- ystep = 0/*0.5 / texh*/;
-
- txf->teximage = ZnMalloc(texw * texh * sizeof(unsigned char));
- if (txf->teximage == NULL) {
+ if (!SuckGlyphsFromServer(wi, txf->tkfont, txf)) {
goto error;
}
- txf->tgi = ZnMalloc(txf->num_glyphs * sizeof(TexGlyphInfo));
- if (txf->tgi == NULL) {
- goto error;
- }
- txf->tgvi = ZnMalloc(txf->num_glyphs * sizeof(ZnTexGVI));
- if (txf->tgvi == NULL) {
- goto error;
- }
-
- glist = ZnMalloc((txf->num_glyphs+1) * sizeof(unsigned char));
- for (i = 0; i < txf->num_glyphs; i++) {
- glist[i] = i+MIN_CHAR;
- }
- glist[txf->num_glyphs] = 0;
- qsort(glist, txf->num_glyphs, sizeof(unsigned char), glyphCompare);
- /*
- * Keep a cache a the sorted list in case we need to
- * restart the allocation process.
- */
- glist2 = ZnMalloc((txf->num_glyphs+1) * sizeof(unsigned char));
- strcpy(glist2, glist);
-
- restart:
- px = gap;
- py = gap;
- maxheight = 0;
- for (i = 0; i < txf->num_glyphs; i++) {
- if (glist[i] != 0) { /* If not already processed... */
- int foundWidthFit = 0;
- int c;
-
- /* Try to find a character from the glist that will fit on the
- remaining space on the current row. */
- tgi = &txf->tgi[i];
- getMetric(fontinfo, glist[i], tgi);
- width = tgi->width;
- height = tgi->height;
-
- if ((height > 0) && (width > 0)) {
- for (j = i; j < txf->num_glyphs;) {
- if ((height > 0) && (width > 0)) {
- if ((unsigned int) (px + width + gap) < texw) {
- foundWidthFit = 1;
- if (j != i) {
- i--; /* Step back so i loop increment leaves us at same character. */
- }
- break;
- }
- }
- do {
- j++;
- } while (glist[j] == 0);
- if (j < txf->num_glyphs) {
- tgi = &txf->tgi[j];
- getMetric(fontinfo, glist[j], tgi);
- width = tgi->width;
- height = tgi->height;
- }
- }
-
- /* If a fit was found, use that character; otherwise
- * advance a line in the texture. */
- if (foundWidthFit) {
- if (height > maxheight) {
- maxheight = height;
- }
- c = j;
- }
- else {
- tgi = &txf->tgi[i];
- getMetric(fontinfo, glist[i], tgi);
- width = tgi->width;
- height = tgi->height;
-
- py += maxheight + gap;
- px = gap;
- maxheight = height;
- if ((unsigned int) (py + height + gap) >= texh) {
- if (texh*2 < ce->max_tex_size) {
- texh *= 2;
- ZnFree(txf->teximage);
- txf->teximage = ZnMalloc(texw * texh * sizeof(unsigned char));
- strcpy(glist, glist2);
- goto restart;
- }
- else if (texw*2 < ce->max_tex_size) {
- texw *= 2;
- ZnFree(txf->teximage);
- txf->teximage = ZnMalloc(texw * texh * sizeof(unsigned char));
- strcpy(glist, glist2);
- goto restart;
- }
- else {
- /* Overflowed texture space */
- goto error;
- }
- }
- c = i;
- }
-
- /* Place the glyph in the texture image. */
- placeGlyph(fontinfo, glist[c], txf->teximage, texw, px, py);
-
- /* Assign glyph's texture coordinate. */
- tgi->x = px;
- tgi->y = py;
-
- /* Advance by glyph width, remaining in the current line. */
- px += width + gap;
- }
- else {
- /* No texture image; assign invalid bogus texture coordinates. */
- tgi->x = -1;
- tgi->y = -1;
- c = i;
- }
- glist[c] = 0; /* Mark processed; don't process again. */
- txf->tgvi[c].t0[0] = tgi->x / ((GLfloat) texw) + xstep;
- txf->tgvi[c].t0[1] = tgi->y / ((GLfloat) texh) + ystep;
- txf->tgvi[c].v0[0] = tgi->xoffset;
- txf->tgvi[c].v0[1] = tgi->yoffset - tgi->height;
- txf->tgvi[c].t1[0] = (tgi->x + tgi->width) / ((GLfloat) texw) + xstep;
- txf->tgvi[c].t1[1] = tgi->y / ((GLfloat) texh) + ystep;
- txf->tgvi[c].v1[0] = (tgi->xoffset + tgi->width);
- txf->tgvi[c].v1[1] = tgi->yoffset - tgi->height;
- txf->tgvi[c].t2[0] = (tgi->x + tgi->width) / ((GLfloat) texw) + xstep;
- txf->tgvi[c].t2[1] = (tgi->y + tgi->height) / ((GLfloat) texh) + ystep;
- txf->tgvi[c].v2[0] = (tgi->xoffset + tgi->width);
- txf->tgvi[c].v2[1] = tgi->yoffset;
- txf->tgvi[c].t3[0] = tgi->x / ((GLfloat) texw) + xstep;
- txf->tgvi[c].t3[1] = (tgi->y + tgi->height) / ((GLfloat) texh) + ystep;
- txf->tgvi[c].v3[0] = tgi->xoffset;
- txf->tgvi[c].v3[1] = tgi->yoffset;
- txf->tgvi[c].advance = tgi->advance;
- }
- }
-
- min_glyph = txf->tgi[0].c;
- max_glyph = txf->tgi[0].c;
- for (i = 1; i < txf->num_glyphs; i++) {
- if (txf->tgi[i].c < min_glyph) {
- min_glyph = txf->tgi[i].c;
- }
- if (txf->tgi[i].c > max_glyph) {
- max_glyph = txf->tgi[i].c;
- }
- }
- txf->tex_width = texw;
- txf->tex_height = texh;
- /*printf("texture width: %g, texture height: %g\n", texw, texh);
- printf("min glyph: (%d) \"%c\", max glyph: (%d) \"%c\"\n",
- min_glyph, min_glyph, max_glyph, max_glyph);*/
- txf->min_glyph = min_glyph;
- txf->range = max_glyph - min_glyph + 1;
-
- txf->lut = ZnMalloc(txf->range * sizeof(ZnTexGVI *));
- if (txf->lut == NULL) {
- error:
- if (glist) {
- ZnFree(glist);
- }
- if (glist2) {
- ZnFree(glist2);
- }
- if (fontinfo) {
- for (i = 0; i < fontinfo->num_glyphs; i++) {
- if (fontinfo->glyph[i].bitmap)
- ZnFree(fontinfo->glyph[i].bitmap);
- }
- ZnFree(fontinfo);
- }
- if (txf->tgi) {
- ZnFree(txf->tgi);
- txf->tgi = 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;
- }
-#ifndef PTK_800
- Tcl_FreeEncoding(txf->enc);
-#endif
- Tk_FreeFont(txf->tkfont);
- ZnFree(txf);
- ZnWarning("Cannot load font texture for font ");
- ZnWarning(Tk_NameOfFont(font));
- ZnWarning("\n");
- return 0;
- }
-
- 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];
- }
-
- for (i = 0; i < fontinfo->num_glyphs; i++) {
- if (fontinfo->glyph[i].bitmap)
- ZnFree(fontinfo->glyph[i].bitmap);
- }
- ZnFree(fontinfo);
- ZnFree(glist);
- ZnFree(glist2);
-
entry = Tcl_CreateHashEntry(&font_textures, (char *) font, &new);
Tcl_SetHashValue(entry, (ClientData) txf);
txf->hash = entry;
@@ -1794,7 +1409,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->dpy == wi->dpy) {
+ if (tfi->dpy == wi->dpy) {
tfi->refcount++;
return tfi;
}
@@ -1807,13 +1422,21 @@ ZnGetTexFont(ZnWInfo *wi,
return NULL;
}
tfi->refcount = 1;
- tfi->wi = wi;
+ tfi->dpy = wi->dpy;
tfi->txf = txf;
tfi->texobj = 0;
tfi->next = txf->tfi;
txf->tfi = tfi;
return tfi;
+
+ error:
+ Tk_FreeFont(txf->tkfont);
+ ZnFree(txf);
+ ZnWarning("Cannot load font texture for font ");
+ ZnWarning(Tk_NameOfFont(font));
+ ZnWarning("\n");
+ return 0;
}
@@ -1846,7 +1469,7 @@ ZnTexFontTex(ZnTexFontInfo tfi)
if (!this->texobj) {
glGenTextures(1, &this->texobj);
/*printf("%d creation texture %d pour la fonte %s\n",
- this->wi, this->texobj, ZnNameOfTexFont(tfi));*/
+ this->dpy, 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);
@@ -1854,8 +1477,8 @@ ZnTexFontTex(ZnTexFontInfo tfi)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGetError();
/*printf("Demande texture de %d x %d\n", txf->tex_width, txf->tex_height);*/
- glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4, txf->tex_width,
- txf->tex_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, txf->tex_width,
+ txf->tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
txf->teximage);
if (glGetError() != GL_NO_ERROR) {
ZnWarning("Can't allocate the texture for font ");
@@ -1881,7 +1504,6 @@ void
ZnFreeTexFont(ZnTexFontInfo tfi)
{
TexFontInfo *this = ((TexFontInfo *) tfi);
- ZnWInfo *wi = this->wi;
TexFont *txf = this->txf;
TexFontInfo *prev, *scan;
@@ -1909,11 +1531,13 @@ ZnFreeTexFont(ZnTexFontInfo tfi)
prev->next = this->next;
}
if (this->texobj) {
- /*printf("%d Libération de la texture %d pour la fonte %s\n",
- wi, this->texobj, ZnNameOfTexFont(tfi));*/
- ZnGLMakeCurrent(wi->dpy, 0);
+ ZnGLContextEntry *ce;
+ /*printf("%d Liberation de la texture %d pour la fonte %s\n",
+ this->dpy, this->texobj, ZnNameOfTexFont(tfi));*/
+ /*OutputDebugString("FreeFont\n");*/
+ ce = ZnGLMakeCurrent(this->dpy, 0);
glDeleteTextures(1, &this->texobj);
- /*ZnGLRelease(wi);*/
+ ZnGLReleaseContext(ce);
}
/*
@@ -1921,15 +1545,11 @@ ZnFreeTexFont(ZnTexFontInfo tfi)
* deallocate the structures.
*/
if (txf->tfi == NULL) {
- /*printf("%d destruction complète du txf pour %s\n", this, ZnNameOfTexFont(tfi));*/
+ /*printf("%d destruction complète du txf pour %s\n", this, ZnNameOfTexFont(tfi));*/
Tk_FreeFont(txf->tkfont);
- ZnFree(txf->tgi);
+ ZnFree(txf->glyph);
ZnFree(txf->tgvi);
- ZnFree(txf->lut);
ZnFree(txf->teximage);
-#ifndef PTK_800
- Tcl_FreeEncoding(txf->enc);
-#endif
Tcl_DeleteHashEntry(txf->hash);
ZnFree(txf);
}
@@ -1937,41 +1557,53 @@ ZnFreeTexFont(ZnTexFontInfo tfi)
ZnFree(this);
}
+
/*
**********************************************************************************
*
- * ZnCharInTexFont --
+ * ZnGetFontIndex --
*
**********************************************************************************
*/
-ZnBool
-ZnCharInTexFont(ZnTexFontInfo tfi,
- unsigned int c)
+int
+ZnGetFontIndex(ZnTexFontInfo tfi,
+ int c)
{
- TexFont *txf = ((TexFontInfo *) tfi)->txf;
+ TexFont *txf;
+ ZnTexGVI *tgvi;
+ int code, min, max, mid;
- if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
- if (txf->lut[c - txf->min_glyph]) {
- return True;
- }
+ if (c < 127) {
+ /*
+ * It is possible to index the points below 127. Unicode
+ * is the same as ascii down there.
+ */
+ return c - 32;
}
- return False;
-}
-/*
- **********************************************************************************
- *
- * ZnTexFontEncoding --
- *
- **********************************************************************************
- */
-#ifndef PTK_800
-Tcl_Encoding
-ZnTexFontEncoding(ZnTexFontInfo tfi)
-{
- return ((TexFontInfo *) tfi)->txf->enc;
+ /*
+ * Else, search by dichotomy in the remaining chars.
+ */
+ txf = ((TexFontInfo *) tfi)->txf;
+ tgvi = txf->tgvi;
+ min = 127;
+ max = txf->num_glyphs;
+ while (min < max) {
+ mid = (min + max) >> 1;
+ code = tgvi[mid].code;
+ if (c == code) {
+ return mid;
+ }
+ if (c < code) {
+ max = mid;
+ }
+ else {
+ min = mid + 1;
+ }
+ }
+ /*fprintf(stderr, "Tried to access unavailable texture font character %d (Unicode)\n", c);*/
+ return -1;
}
-#endif
/*
**********************************************************************************
@@ -1981,36 +1613,19 @@ ZnTexFontEncoding(ZnTexFontInfo tfi)
**********************************************************************************
*/
ZnTexGVI *
-ZnTexFontGVI(ZnTexFontInfo tfi,
- unsigned int c)
+ZnTexFontGVI(ZnTexFontInfo tfi,
+ int c)
{
TexFont *txf = ((TexFontInfo *) tfi)->txf;
- ZnTexGVI *tgvi;
+ ZnTexGVI *tgvi = NULL;
+ int index;
- /* 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];
- }
- }
+ index = ZnGetFontIndex(tfi, c);
+ if (index >= 0) {
+ tgvi = &txf->tgvi[index];
}
- fprintf(stderr,
- "Tried to access unavailable texture font character '%c'(\\0%o)\n",
- c, c);
- return txf->lut[(int)'!' - txf->min_glyph];
+
+ return tgvi;
}
#endif