aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlecoanet2001-10-12 07:44:41 +0000
committerlecoanet2001-10-12 07:44:41 +0000
commitfe131efdd2deb5f0672b8e18549fd076a3acff8c (patch)
tree493414df6164a48c86ebae0c279d179f5bc72dcb
parent7291fbef4efff7323d083614038a32d5d1c2d9f1 (diff)
downloadtkzinc-fe131efdd2deb5f0672b8e18549fd076a3acff8c.zip
tkzinc-fe131efdd2deb5f0672b8e18549fd076a3acff8c.tar.gz
tkzinc-fe131efdd2deb5f0672b8e18549fd076a3acff8c.tar.bz2
tkzinc-fe131efdd2deb5f0672b8e18549fd076a3acff8c.tar.xz
Suppression du code LIBART.
Ajout de routines pour g�rer le texte en m�moire de texture. Ajout de routines pour g�rer les images/bitmap en m�moire de texture.
-rw-r--r--generic/Image.c1570
1 files changed, 598 insertions, 972 deletions
diff --git a/generic/Image.c b/generic/Image.c
index 1474291..d3f9563 100644
--- a/generic/Image.c
+++ b/generic/Image.c
@@ -32,6 +32,13 @@
#include "Image.h"
#include "WidgetInfo.h"
#include "Geo.h"
+#ifdef GLX
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glu.h>
+#include "Draw.h"
+#endif
static const char rcsid[] = "$Id$";
@@ -53,9 +60,12 @@ typedef struct _ImagePixmap {
struct _ImagePixmap *next;
} ImagePixmap;
+static int image_bits_inited = 0;
static Tcl_HashTable image_bits;
static Tcl_HashTable bitmap_masks;
-static Tcl_HashTable font_bitmaps;
+#ifdef GLX
+static Tcl_HashTable font_textures;
+#endif
/*
@@ -70,7 +80,6 @@ GetImageBits(ZnWindow win,
char *image_name,
ZnImage image)
{
- static int inited = 0;
Tcl_HashEntry *entry;
XImage *im1, *im2, *mask;
Pixmap pmap;
@@ -83,9 +92,9 @@ GetImageBits(ZnWindow win,
ImageBits *im_bits;
ZnBool full_mask=True;
- if (!inited) {
+ if (!image_bits_inited) {
Tcl_InitHashTable(&image_bits, TCL_STRING_KEYS);
- inited = 1;
+ image_bits_inited = 1;
}
entry = Tcl_FindHashEntry(&image_bits, image_name);
if (entry != NULL) {
@@ -94,12 +103,9 @@ GetImageBits(ZnWindow win,
else {
Tk_SizeOfImage(image, &width, &height);
im_bits = (ImageBits *) ZnMalloc(sizeof(ImageBits));
-#ifdef LIBART
- im_bits->pixbuf = NULL;
-#endif
#ifdef GLX
im_bits->texture = 0;
- im_bits->i_bits = NULL;
+ im_bits->t_bits = NULL;
#endif
im_bits->pixmaps = NULL;
im_bits->b_bits = NULL;
@@ -160,7 +166,7 @@ GetImageBits(ZnWindow win,
else {
im_bits->mask = mask;
}
-
+
entry = Tcl_CreateHashEntry(&image_bits, image_name, &new);
Tcl_SetHashValue(entry, (ClientData) im_bits);
}
@@ -175,6 +181,9 @@ InvalidateImage(char *image_name)
ImageBits *im_bits;
ImagePixmap *im_pmap, *next_im_pmap;
+ if (!image_bits_inited) {
+ return;
+ }
/*
* Destroy the image entry and wait the cache fault to
* reload the new one.
@@ -202,14 +211,9 @@ InvalidateImage(char *image_name)
ZnFree(im_bits->b_bits->pixels);
ZnFree(im_bits->b_bits);
}
-#ifdef LIBART
- if (im_bits->pixbuf) {
- art_pixbuf_free(im_bits->pixbuf);
- }
-#endif
#ifdef GLX
if (im_bits->texture) {
- ZnFree(im_bits->i_bits);
+ ZnFree(im_bits->t_bits);
glDeleteTextures(1, &im_bits->texture);
}
#endif
@@ -352,1022 +356,531 @@ GetBitmapMask(Display *dpy,
}
-/*
- **********************************************************************************
- *
- * GetFontBitmap --
- *
- **********************************************************************************
- */
-FontBitmap *
-GetFontBitmap(ZnWindow win,
- ZnFont font)
-{
- static int inited = 0;
- Tcl_HashEntry *entry;
- FontBitmap *f_bits;
- XImage *im;
- Pixmap pix;
- GC gc;
- XGCValues values;
- Tk_FontMetrics fm;
- Display *dpy = Tk_Display(win);
- int i, x, y, black_pixel, pixel;
- int new, size, width, height;
- char str[1];
- char *line;
-
- if (!inited) {
- Tcl_InitHashTable(&font_bitmaps, sizeof(ZnFont)/sizeof(int));
- inited = 1;
- }
- entry = Tcl_FindHashEntry(&font_bitmaps, (char *) font);
- if (entry != NULL) {
- f_bits = (FontBitmap *) Tcl_GetHashValue(entry);
- }
- else {
- f_bits = (FontBitmap *) ZnMalloc(sizeof(FontBitmap));
- Tk_GetFontMetrics(font, &fm);
-
- height = fm.ascent + fm.descent;
- x = 0;
-
- for (i = 0; i < 256; i++) {
- str[0] = i;
- f_bits->chars[i].width = Tk_TextWidth(font, str, 1);
- f_bits->chars[i].bitmap_offset = x;
- /* Next char will be aligned on a 32 bit boundary; */
- x += (f_bits->chars[i].width + 31) & -32;
- }
-
- width = x;
- f_bits->width = width;
- f_bits->height = height;
- f_bits->ascent = fm.ascent;
- f_bits->descent = fm.descent;
-
- pix = XCreatePixmap(dpy, ZnWindowId(win), width, height, 1);
- values.foreground = WhitePixel(dpy, DefaultScreen(dpy));
- values.font = Tk_FontId(font);
- gc = XCreateGC(dpy, pix, GCForeground|GCFont, &values);
- XFillRectangle(dpy, pix, gc, 0, 0, width, height);
- black_pixel = BlackPixel(dpy, DefaultScreen(dpy));
- values.foreground = black_pixel;
- XChangeGC(dpy, gc, GCForeground, &values);
-
- for (i = 0; i < 256; i++) {
- str[0] = i;
- XDrawString(dpy, pix, gc, f_bits->chars[i].bitmap_offset,
- f_bits->ascent, str, 1);
- }
-
- im = XGetImage(dpy, pix, 0, 0, width, height, 1L, XYPixmap);
- size = (width >> 3) * height;
- f_bits->bitmap = ZnMalloc(size);
- memset(f_bits->bitmap, 0, size);
-
- line = f_bits->bitmap;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- pixel = XGetPixel(im, x, y);
- if (pixel == black_pixel) {
- line[x >> 3] |= 128 >> (x & 7);
- }
- }
- line += width >> 3;
- }
-
- XDestroyImage(im);
- XFreePixmap(dpy, pix);
- XFreeGC(dpy, gc);
-
- entry = Tcl_CreateHashEntry(&font_bitmaps, (char *) font, &new);
- Tcl_SetHashValue(entry, (ClientData) f_bits);
- }
-
- return f_bits;
-}
-
-
-#ifdef LIBART
-static void
-rgb_text_opaque(art_u8 *dst,
- int x0, int y0, int x1, int y1, int dst_rowstride,
- char *text , int num_chars, int start_x, int start_y,
- FontBitmap *fb, art_u32 rgb)
-{
- art_u8 *src, *src_p, *dst_p, *dst_linestart;
- art_u8 r, g, b;
- art_u8 bm;
- SuckChar *ch;
- int run_x0, run_y0;
- int j, x, y, tmp;
- int next_start, src_width, src_height, src_rowstride;
- int src_x0, src_y0, src_x1, src_y1;
-
- src_height = fb->height;
- src_rowstride = fb->width >> 3;
- src_y0 = 0;
- run_y0 = start_y - y0;
- if (run_y0 < 0) {
- src_y0 = -run_y0;
- run_y0 = 0;
- }
- src_y1 = src_height;
- tmp = start_y + src_height - y1;
- if (tmp > 0) {
- src_y1 -= tmp;
- }
+#ifdef GLX
+#define MAX_GLYPHS_PER_GRAB 512 /* this is big enough for 2^9 glyph
+ * character sets */
- r = rgb >> 16;
- g = (rgb >> 8) & 0xff;
- b = rgb & 0xff;
+typedef struct {
+ short width;
+ short height;
+ short xoffset;
+ short yoffset;
+ short advance;
+ unsigned char *bitmap;
+} PerGlyphInfo, *PerGlyphInfoPtr;
- for (j = 0; j < num_chars; j++) {
- if (start_x > x1) {
- break;
- }
- ch = &fb->chars[(unsigned char)(*text)];
- src_width = ch->width;
- next_start = start_x + src_width;
- if (next_start < x0) {
- goto nexto;
- }
- src = fb->bitmap + (ch->bitmap_offset >> 3);
- src_x0 = 0;
- run_x0 = start_x - x0;
- if (run_x0 < 0) {
- src_x0 = -run_x0;
- run_x0 = 0;
- }
- src_x1 = src_width;
- tmp = next_start - x1;
- if (tmp > 0) {
- src_x1 -= tmp;
- }
+typedef struct {
+ int min_char;
+ int max_char;
+ int max_ascent;
+ int max_descent;
+ int num_glyphs;
+ PerGlyphInfo glyph[1];
+} FontInfo, *FontInfoPtr;
- dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
- src_p = src + src_y0 * src_rowstride;
-
- for (y = src_y0; y < src_y1; y++) {
- dst_p = dst_linestart;
- for (x = src_x0; x < src_x1; x++) {
- bm = *(src_p + (x >> 3));
- if (bm & (128 >> (x & 7))) {
- *dst_p = r;
- dst_p++;
- *dst_p = g;
- dst_p++;
- *dst_p = b;
- dst_p++;
- }
- else {
- dst_p += 3;
- }
- }
- dst_linestart += dst_rowstride;
- src_p += src_rowstride;
- }
- nexto:
- start_x = next_start;
- text++;
- }
-}
+static FontInfoPtr fontinfo;
void
-rgb_text(art_u8 *dst,
- int x0, int y0, int x1, int y1, int dst_rowstride,
- char *text, int num_chars, int start_x, int start_y,
- FontBitmap *fb, art_u32 rgba)
+getMetric(FontInfoPtr font,
+ int c,
+ TexGlyphInfo *tgi)
{
- art_u8 *src, *src_p, *dst_p, *dst_linestart;
- art_u8 r, g, b;
- art_u8 bm, comp;
- SuckChar *ch;
- int alpha;
- int run_x0, run_y0;
- int j, x, y, tmp;
- int next_start, src_width, src_height, src_rowstride;
- int src_x0, src_y0, src_x1, src_y1;
-
- src_height = fb->height;
- if ((start_y > y1) ||
- (start_y+src_height < y0) ||
- (start_x > x1)) {
+ 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;
}
-
- alpha = rgba & 0xff;
- if (alpha == 0xff) {
- rgb_text_opaque(dst, x0, y0, x1, y1, dst_rowstride,
- text, num_chars, start_x, start_y,
- fb, rgba >> 8);
- return;
- }
-
- src_rowstride = fb->width >> 3;
- src_y0 = 0;
- run_y0 = start_y - y0;
- if (run_y0 < 0) {
- src_y0 = -run_y0;
- run_y0 = 0;
- }
- src_y1 = src_height;
- tmp = start_y + src_height - y1;
- if (tmp > 0) {
- src_y1 -= tmp;
+ 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\' %d\n", c, glyph->advance);*/
+ tgi->advance = glyph->advance;
+}
- alpha = (alpha << 8) + alpha + (alpha >> 7);
- r = rgba >> 24;
- g = (rgba >> 16) & 0xff;
- b = (rgba >> 8) & 0xff;
-
- for (j = 0; j < num_chars; j++) {
- if (start_x > x1) {
- break;
- }
- ch = &fb->chars[(unsigned char)(*text)];
- src_width = ch->width;
- next_start = start_x + src_width;
- if (next_start < x0) {
- goto next;
- }
- src = fb->bitmap + (ch->bitmap_offset >> 3);
- src_x0 = 0;
- run_x0 = start_x - x0;
- if (run_x0 < 0) {
- src_x0 = -run_x0;
- run_x0 = 0;
- }
- src_x1 = src_width;
- tmp = next_start - x1;
- if (tmp > 0) {
- src_x1 -= tmp;
- }
-
- dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
- src_p = src + src_y0 * src_rowstride;
-
- for (y = src_y0; y < src_y1; y++) {
- dst_p = dst_linestart;
- for (x = src_x0; x < src_x1; x++) {
- bm = *(src_p + (x >> 3));
- if (bm & (128 >> (x & 7))) {
- comp = *dst_p;
- *dst_p = comp + (((r - comp) * alpha + 0x8000) >> 16);
- dst_p++;
- comp = *dst_p;
- *dst_p = comp + (((g - comp) * alpha + 0x8000) >> 16);
- dst_p++;
- comp = *dst_p;
- *dst_p = comp + (((b - comp) * alpha + 0x8000) >> 16);
- dst_p++;
- }
- else {
- dst_p += 3;
- }
- }
- dst_linestart += dst_rowstride;
- src_p += src_rowstride;
- }
- next:
- start_x = next_start;
- text++;
- }
+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;
}
-/* rgb_image */
void
-rgb_image(art_u8 *dst,
- int x0, int y0, int x1, int y1, int dst_rowstride,
- ArtPixBuf *pixbuf, int start_x, int start_y, int alpha)
+placeGlyph(FontInfoPtr font,
+ int c,
+ unsigned char *texarea,
+ int stride,
+ int x,
+ int y)
{
- art_u8 *src, *src_p, *dst_p;
- art_u8 *dst_linestart, *src_linestart;
- art_u8 r, g, b;
- int a;
- int run_x0, run_y0;
- int x, y, tmp;
- int src_x0, src_y0, src_x1, src_y1;
- int src_width, src_height, src_rowstride;
-
- if (pixbuf->format != ART_PIX_RGB) {
- ZnWarning("art_rgb_pixbuf_affine: need RGB format image\n");
- return;
- }
- if (pixbuf->bits_per_sample != 8) {
- ZnWarning("art_rgb_pixbuf_affine: need 8-bit sample data\n");
- return;
- }
- if ((pixbuf->n_channels != 4) || !pixbuf->has_alpha) {
- ZnWarning("art_rgb_pixbuf_affine: need RGBA sample data\n");
- return;
- }
-
- src_width = pixbuf->width;
- src_height = pixbuf->height;
+ PerGlyphInfoPtr glyph;
+ unsigned char *bitmapData;
+ int width, height, spanLength;
+ int i, j;
- if ((start_y > y1) ||
- (start_y+src_height < y0) ||
- (start_x > x1) ||
- (start_x+src_width < x0)) {
+ /*printf("x: %d, y: %d, c: %d, texarea: 0x%X\n", x, y, c, texarea);*/
+ 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;
- src_rowstride = pixbuf->rowstride;
- src = pixbuf->pixels;
-
- src_x0 = src_y0 = 0;
- run_y0 = start_y - y0;
- if (run_y0 < 0) {
- src_y0 = -run_y0;
- run_y0 = 0;
- }
- src_y1 = src_height;
- tmp = start_y + src_height - y1;
- if (tmp > 0) {
- src_y1 -= tmp;
- }
- run_x0 = start_x - x0;
- if (run_x0 < 0) {
- src_x0 = -run_x0;
- run_x0 = 0;
- }
- src_x1 = src_width;
- tmp = start_x + src_width - x1;
- if (tmp > 0) {
- src_x1 -= tmp;
- }
-
- dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
- src_linestart = src + src_y0 * src_rowstride + src_x0 * 4;
-
- for (y = src_y0; y < src_y1; y++) {
- dst_p = dst_linestart;
- src_p = src_linestart;
- for (x = src_x0; x < src_x1; x++) {
- a = src_p[3] * alpha / 255;
- if (a) {
- if (a == 255) {
- dst_p[0] = src_p[0];
- dst_p[1] = src_p[1];
- dst_p[2] = src_p[2];
- }
- else {
- r = dst_p[0];
- g = dst_p[1];
- b = dst_p[2];
- tmp = (src_p[0] - r) * a;
- r = r + ((tmp + (tmp >> 8) + 0x80) >> 8);
- tmp = (src_p[1] - g) * a;
- g = g + ((tmp + (tmp >> 8) + 0x80) >> 8);
- tmp = (src_p[2] - b) * a;
- b = b + ((tmp + (tmp >> 8) + 0x80) >> 8);
- dst_p[0] = r;
- dst_p[1] = g;
- dst_p[2] = b;
- }
+ 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;
}
- dst_p += 3;
- src_p += 4;
}
- dst_linestart += dst_rowstride;
- src_linestart += src_rowstride;
}
}
-/* rgb_bitmap */
-static void
-rgb_bitmap_opaque(art_u8 *dst,
- int x0, int y0, int x1, int y1, int dst_rowstride,
- art_u8 *src, int start_x, int start_y,
- int src_width, int src_height, int src_rowstride,
- art_u32 rgb)
+FontInfoPtr
+SuckGlyphsFromServer(ZnWindow win,
+ ZnFont font)
{
- art_u8 *src_p, *dst_p, *dst_linestart;
- art_u8 r, g, b;
- art_u8 bm;
- int run_x0, run_y0;
- int x, y, tmp;
- int src_x0, src_y0, src_x1, src_y1;
-
- src_x0 = src_y0 = 0;
- run_y0 = start_y - y0;
- if (run_y0 < 0) {
- src_y0 = -run_y0;
- run_y0 = 0;
- }
- src_y1 = src_height;
- tmp = start_y + src_height - y1;
- if (tmp > 0) {
- src_y1 -= tmp;
- }
- run_x0 = start_x - x0;
- if (run_x0 < 0) {
- src_x0 = -run_x0;
- run_x0 = 0;
- }
- src_x1 = src_width;
- tmp = start_x + src_width - x1;
- if (tmp > 0) {
- src_x1 -= tmp;
- }
-
- r = rgb >> 16;
- g = (rgb >> 8) & 0xff;
- b = rgb & 0xff;
-
- dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
- src_p = src + src_y0 * src_rowstride;
-
- for (y = src_y0; y < src_y1; y++) {
- dst_p = dst_linestart;
- for (x = src_x0; x < src_x1; x++) {
- bm = *(src_p + (x >> 3));
- if (bm & (128 >> (x & 7))) {
- *dst_p = r;
- dst_p++;
- *dst_p = g;
- dst_p++;
- *dst_p = b;
- dst_p++;
- }
- else {
- dst_p += 3;
- }
- }
- dst_linestart += dst_rowstride;
- src_p += src_rowstride;
- }
-}
-
-void
-rgb_bitmap(art_u8 *dst,
- int x0, int y0, int x1, int y1, int dst_rowstride,
- art_u8 *src, int start_x, int start_y,
- int src_width, int src_height, int src_rowstride,
- art_u32 rgba)
-{
- art_u8 *src_p, *dst_p, *dst_linestart;
- art_u8 r, g, b;
- art_u8 bm, comp;
- int alpha;
- int run_x0, run_y0;
- int x, y, tmp;
- int src_x0, src_y0, src_x1, src_y1;
-
- if ((start_y > y1) ||
- (start_y+src_height < y0) ||
- (start_x > x1) ||
- (start_x+src_width < x0)) {
- return;
- }
+ Display *dpy = Tk_Display(win);
+ XFontStruct *fontinfo = NULL;
+ Pixmap offscreen = 0;
+ XImage *image = NULL;
+ GC xgc = 0;
+ XGCValues values;
+ int width, height, pixwidth;
+ int i, j;
+ XCharStruct *charinfo;
+ XChar2b character;
+ unsigned char *bitmapData = NULL;
+ int x, y;
+ int numchars, spanLength;
+ int charWidth, charHeight, maxSpanLength;
+ int grabList[MAX_GLYPHS_PER_GRAB];
+ int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
+ int numToGrab, thisglyph;
+ FontInfoPtr myfontinfo = NULL;
- alpha = rgba & 0xff;
- if (alpha == 0xff) {
- rgb_bitmap_opaque(dst, x0, y0, x1, y1, dst_rowstride,
- src, start_x, start_y,
- src_width, src_height, src_rowstride,
- rgba >> 8);
- return;
+ fontinfo = XQueryFont(dpy, Tk_FontId(font));
+ if (!fontinfo) {
+ return NULL;
}
- src_x0 = src_y0 = 0;
- run_y0 = start_y - y0;
- if (run_y0 < 0) {
- src_y0 = -run_y0;
- run_y0 = 0;
- }
- src_y1 = src_height;
- tmp = start_y + src_height - y1;
- if (tmp > 0) {
- src_y1 -= tmp;
- }
- run_x0 = start_x - x0;
- if (run_x0 < 0) {
- src_x0 = -run_x0;
- run_x0 = 0;
+ numchars = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
+ if (numchars < 1) {
+ return NULL;
}
- src_x1 = src_width;
- tmp = start_x + src_width - x1;
- if (tmp > 0) {
- src_x1 -= tmp;
- }
-
- alpha = (alpha << 8) + alpha + (alpha >> 7);
- r = rgba >> 24;
- g = (rgba >> 16) & 0xff;
- b = (rgba >> 8) & 0xff;
- dst_linestart = dst + run_y0 * dst_rowstride + run_x0 * 3;
- src_p = src + src_y0 * src_rowstride;
-
- for (y = src_y0; y < src_y1; y++) {
- dst_p = dst_linestart;
- for (x = src_x0; x < src_x1; x++) {
- bm = *(src_p + (x >> 3));
- if (bm & (128 >> (x & 7))) {
- comp = *dst_p;
- *dst_p = comp + (((r - comp) * alpha + 0x8000) >> 16);
- dst_p++;
- comp = *dst_p;
- *dst_p = comp + (((g - comp) * alpha + 0x8000) >> 16);
- dst_p++;
- comp = *dst_p;
- *dst_p = comp + (((b - comp) * alpha + 0x8000) >> 16);
- dst_p++;
- }
- else {
- dst_p += 3;
+ myfontinfo = (FontInfoPtr) ZnMalloc(sizeof(FontInfo) + (numchars - 1) * sizeof(PerGlyphInfo));
+ if (!myfontinfo) {
+ return NULL;
+ }
+
+ myfontinfo->num_glyphs = numchars;
+ myfontinfo->min_char = fontinfo->min_char_or_byte2;
+ myfontinfo->max_char = fontinfo->max_char_or_byte2;
+ myfontinfo->max_ascent = fontinfo->max_bounds.ascent;
+ myfontinfo->max_descent = fontinfo->max_bounds.descent;
+
+ width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing;
+ height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent;
+
+ maxSpanLength = (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
+ need to limit the glyphs per grab. */
+ if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
+ glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
+ }
+ pixwidth = glyphsPerGrab * 8 * maxSpanLength;
+ offscreen = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
+ pixwidth, height, 1);
+
+ values.font = Tk_FontId(font);
+ values.background = 0;
+ values.foreground = 0;
+ xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values);
+
+ XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
+ XSetForeground(dpy, xgc, 1);
+
+ numToGrab = 0;
+ if (fontinfo->per_char == NULL) {
+ charinfo = &(fontinfo->min_bounds);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ spanLength = (charWidth + 7) / 8;
+ }
+ for (i = 0; i < myfontinfo->num_glyphs; i++) {
+ if (fontinfo->per_char != NULL) {
+ charinfo = &(fontinfo->per_char[i]);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ if (charWidth == 0 || charHeight == 0) {
+ /* Still must move raster pos even if empty character */
+ myfontinfo->glyph[i].width = 0;
+ myfontinfo->glyph[i].height = 0;
+ myfontinfo->glyph[i].xoffset = 0;
+ myfontinfo->glyph[i].yoffset = 0;
+ myfontinfo->glyph[i].advance = charinfo->width;
+ myfontinfo->glyph[i].bitmap = NULL;
+ goto PossiblyDoGrab;
}
}
- dst_linestart += dst_rowstride;
- src_p += src_rowstride;
- }
-}
+ grabList[numToGrab] = i;
-typedef struct _TileSVPData {
- ArtPixBuf *tile;
- int tile_x;
- int tile_y;
- art_u32 b_rgb;
- int alphatab[256];
- art_u8 *buf;
- int rowstride;
- int x0, x1;
-} TileSVPData;
-
-static void
-tile_fill_run(art_u8 *buf,
- int num,
- art_u8 *tile_line,
- int tile_dx,
- int tile_width)
-{
- int i, start_len;
- art_u8 *ptr;
+ /* XXX is this right for large fonts? */
+ character.byte2 = (i + fontinfo->min_char_or_byte2) & 255;
+ character.byte1 = (i + fontinfo->min_char_or_byte2) >> 8;
- tile_dx %= tile_width;
- if (tile_dx < 0) {
- tile_dx += tile_width;
- }
- start_len = tile_width - tile_dx;
- if (start_len > num) {
- start_len = num;
- }
- ptr = tile_line + 4*tile_dx;
- for (i = 0; i < start_len; i++) {
- *buf++ = *ptr++;
- *buf++ = *ptr++;
- *buf++ = *ptr++;
- ptr++;
- }
- num -= start_len;
- while (num > 0) {
- ptr = tile_line;
- for (i = MIN(tile_width, num); i > 0; i--) {
- *buf++ = *ptr++;
- *buf++ = *ptr++;
- *buf++ = *ptr++;
- ptr++;
+ XDrawString16(dpy, offscreen, xgc,
+ -charinfo->lbearing + 8 * maxSpanLength * numToGrab,
+ charinfo->ascent, &character, 1);
+
+ numToGrab++;
+
+ PossiblyDoGrab:
+ if ((numToGrab >= glyphsPerGrab) || (i == myfontinfo->num_glyphs - 1)) {
+ image = XGetImage(dpy, offscreen, 0, 0, pixwidth, height, 1, XYPixmap);
+ for (j = 0; j < numToGrab; j++) {
+ thisglyph = grabList[j];
+ if (fontinfo->per_char != NULL) {
+ charinfo = &(fontinfo->per_char[thisglyph]);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ spanLength = (charWidth + 7) / 8;
+ }
+ bitmapData = ZnMalloc(height * spanLength * sizeof(char));
+ memset(bitmapData, 0, height * spanLength * sizeof(char));
+ if (bitmapData == NULL) {
+ goto FreeFontAndReturn;
+ }
+ for (y = 0; y < charHeight; y++) {
+ for (x = 0; x < charWidth; x++) {
+ /* 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
+ bitmap. We actually use the XGetPixel function to extract
+ each pixel from the image which is not that efficient. We
+ could either do tighter packing in the pixmap or more
+ efficient extraction from the image. Oh well. */
+ if (XGetPixel(image, j * maxSpanLength * 8 + x, y)) {
+ bitmapData[y * spanLength + x / 8] |= (1 << (x & 7));
+ }
+ }
+ }
+ myfontinfo->glyph[thisglyph].width = charWidth;
+ myfontinfo->glyph[thisglyph].height = charHeight;
+ myfontinfo->glyph[thisglyph].xoffset = charinfo->lbearing;
+ myfontinfo->glyph[thisglyph].yoffset = charinfo->descent;
+ myfontinfo->glyph[thisglyph].advance = charinfo->width;
+ myfontinfo->glyph[thisglyph].bitmap = bitmapData;
+ }
+ XDestroyImage(image);
+ numToGrab = 0;
+ /* do we need to clear the offscreen pixmap to get more? */
+ if (i < myfontinfo->num_glyphs - 1) {
+ XSetForeground(dpy, xgc, 0);
+ XFillRectangle(dpy, offscreen, xgc, 0, 0,
+ 8 * maxSpanLength * glyphsPerGrab, height);
+ XSetForeground(dpy, xgc, 1);
+ }
}
- num -= tile_width;
}
+ XFreeFontInfo(NULL, fontinfo, 1);
+ XFreeGC(dpy, xgc);
+ XFreePixmap(dpy, offscreen);
+ return myfontinfo;
+
+ FreeFontAndReturn:
+ XFreeFontInfo(NULL, fontinfo, 1);
+ XDestroyImage(image);
+ XFreeGC(dpy, xgc);
+ XFreePixmap(dpy, offscreen);
+ for (i = 0; i < myfontinfo->num_glyphs; i++) {
+ if (myfontinfo->glyph[i].bitmap)
+ ZnFree(myfontinfo->glyph[i].bitmap);
+ }
+ ZnFree(myfontinfo);
+ return NULL;
}
-static void
-tile_svp_aa_cb(void *callback_data,
- int y,
- int start,
- ArtSVPRenderAAStep *steps,
- int n_steps)
+/*
+ **********************************************************************************
+ *
+ * GetTexFont --
+ *
+ **********************************************************************************
+ */
+TexFont *
+GetTexFont(ZnWindow win,
+ ZnFont font)
{
- TileSVPData *data = (TileSVPData *)callback_data;
- art_u8 *linebuf, *tile_line;
- int run_x0, run_x1;
- art_u32 running_sum = start;
- art_u8 b_r, b_g, b_b;
- int x0, x1, k, dy;
+ unsigned char *glisto = " ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijmklmnopqrstuvwxyz?.;,!*:\"'èéêëïîôâàçûùü/+@#$%^&()\\-_<>\t\020\021\022\023";
+ unsigned char *glist = 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;
+ static int inited = 0;
+ Tcl_HashEntry *entry;
- linebuf = data->buf;
- x0 = data->x0;
- x1 = data->x1;
- b_r = data->b_rgb >> 16;
- b_g = (data->b_rgb >> 8) & 0xff;
- b_b = data->b_rgb & 0xff;
-
- dy = y - data->tile_y;
- dy %= data->tile->height;
- if (dy < 0) {
- dy += data->tile->height;
+ if (!inited) {
+ Tcl_InitHashTable(&font_textures, sizeof(ZnFont)/sizeof(int));
+ inited = 1;
}
- tile_line = data->tile->pixels + dy * data->tile->rowstride;
-
- if (n_steps > 0) {
- run_x1 = steps[0].x;
- if (run_x1 > x0) {
- if (((running_sum >> 16) & 0xff) > 128) {
- tile_fill_run(linebuf, run_x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width);
- }
- else {
- art_rgb_fill_run(linebuf, b_r, b_g, b_b, run_x1 - x0);
- }
- }
-
- for (k = 0; k < n_steps - 1; k++) {
- running_sum += steps[k].delta;
- run_x0 = run_x1;
- run_x1 = steps[k + 1].x;
- if (run_x1 > run_x0) {
- if (((running_sum >> 16) & 0xff) > 128) {
- tile_fill_run(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
- tile_line, run_x0 - data->tile_x, data->tile->width);
- }
- else {
- art_rgb_fill_run(linebuf + (run_x0 - x0) * 3, b_r, b_g, b_b,
- run_x1 - run_x0);
- }
- }
- }
- running_sum += steps[k].delta;
- if (x1 > run_x1) {
- if (((running_sum >> 16) & 0xff) > 128) {
- tile_fill_run(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
- tile_line, run_x1 - data->tile_x, data->tile->width);
- }
- else {
- art_rgb_fill_run(linebuf + (run_x1 - x0) * 3, b_r, b_g, b_b,
- x1 - run_x1);
- }
- }
+ entry = Tcl_FindHashEntry(&font_textures, (char *) font);
+ if (entry != NULL) {
+ return (TexFont *) Tcl_GetHashValue(entry);
}
else {
- if (((running_sum >> 16) & 0xff) > 128) {
- tile_fill_run(linebuf, x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width);
+ txf = (TexFont *) ZnMalloc(sizeof(TexFont));
+ if (txf == NULL) {
+ goto error;
}
- else {
- art_rgb_fill_run(linebuf, b_r, b_g, b_b, x1 - x0);
+ txf->tgi = NULL;
+ txf->tgvi = NULL;
+ txf->lut = NULL;
+ txf->teximage = NULL;
+ texw = txf->tex_width = 256; /* Size of texture */
+ texh = txf->tex_height = 256;
+ xstep = 0/*0.5 / texw*/;
+ ystep = 0/*0.5 / texh*/;
+
+ txf->teximage = ZnMalloc(texw * texh * sizeof(unsigned char));
+ if (txf->teximage == NULL) {
+ goto error;
+ }
+ memset(txf->teximage, 0x55, texw * texh * sizeof(unsigned char));
+
+ fontinfo = SuckGlyphsFromServer(win, font);
+ if (fontinfo == NULL) {
+ goto error;
}
- }
-
- data->buf += data->rowstride;
-}
-
-void
-tile_svp_aa(const ArtSVP *svp,
- int x0,
- int y0,
- int x1,
- int y1,
- int tile_x,
- int tile_y,
- ArtPixBuf *tile,
- art_u32 bg_color,
- art_u8 *buf,
- int rowstride)
-{
- TileSVPData data;
-
- data.tile = tile;
- data.tile_x = tile_x;
- data.tile_y = tile_y;
- data.b_rgb = bg_color;
- data.buf = buf;
- data.rowstride = rowstride;
- data.x0 = x0;
- data.x1 = x1;
-
- art_svp_render_aa(svp, x0, y0, x1, y1, tile_svp_aa_cb, &data);
-}
-static void
-tile_fill_run_alpha(art_u8 *buf,
- int num,
- art_u8 *tile_line,
- int tile_dx,
- int tile_width,
- int alpha)
-{
- int v, vt, i, start_len;
- art_u8 *ptr;
+ txf->max_ascent = fontinfo->max_ascent;
+ txf->max_descent = fontinfo->max_descent;
+ txf->num_glyphs = strlen(glisto);
+ glist = ZnMalloc((txf->num_glyphs+1) * sizeof(unsigned char));
+ strcpy(glist, glisto);
- tile_dx %= tile_width;
- if (tile_dx < 0) {
- tile_dx += tile_width;
- }
- start_len = tile_width - tile_dx;
- if (start_len > num) {
- start_len = num;
- }
- ptr = tile_line + 4*tile_dx;
- for (i = 0; i < start_len; i++) {
- v = *buf;
- vt = *ptr++;
- *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
- v = *buf;
- vt = *ptr++;
- *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
- v = *buf;
- vt = *ptr++;
- *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
- ptr++;
- }
- num -= start_len;
- while (num > 0) {
- ptr = tile_line;
- for (i = MIN(tile_width, num); i > 0; i--) {
- v = *buf;
- vt = *ptr++;
- *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
- v = *buf;
- vt = *ptr++;
- *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
- v = *buf;
- vt = *ptr++;
- *buf++ = v + (((vt - v) * alpha + 0x80) >> 8);
- ptr++;
+ txf->tgi = (TexGlyphInfo *) ZnMalloc(txf->num_glyphs * sizeof(TexGlyphInfo));
+ if (txf->tgi == NULL) {
+ goto error;
}
- num -= tile_width;
- }
-}
-
-static void
-tile_svp_alpha_opaque_cb(void *callback_data,
- int y,
- int start,
- ArtSVPRenderAAStep *steps,
- int n_steps)
-{
- TileSVPData *data = (TileSVPData *)callback_data;
- art_u8 *linebuf, *tile_line;
- int run_x0, run_x1;
- art_u32 running_sum = start;
- int x0, x1, k, dy;
- int *alphatab;
- int alpha;
-
- linebuf = data->buf;
- x0 = data->x0;
- x1 = data->x1;
- alphatab = data->alphatab;
-
- dy = y - data->tile_y;
- dy %= data->tile->height;
- if (dy < 0) {
- dy += data->tile->height;
- }
- tile_line = data->tile->pixels + dy * data->tile->rowstride;
-
- if (n_steps > 0) {
- run_x1 = steps[0].x;
- if (run_x1 > x0) {
- alpha = running_sum >> 16;
- if (alpha) {
- if (alpha >= 255) {
- tile_fill_run(linebuf, run_x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width);
- }
- else {
- tile_fill_run_alpha(linebuf, run_x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width,
- alphatab[alpha]);
- }
- }
+ txf->tgvi = (TexGlyphVertexInfo *) ZnMalloc(txf->num_glyphs * sizeof(TexGlyphVertexInfo));
+ if (txf->tgvi == NULL) {
+ goto error;
}
- for (k = 0; k < n_steps - 1; k++) {
- running_sum += steps[k].delta;
- run_x0 = run_x1;
- run_x1 = steps[k + 1].x;
- if (run_x1 > run_x0) {
- alpha = running_sum >> 16;
- if (alpha) {
- if (alpha >= 255) {
- tile_fill_run(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
- tile_line, run_x0 - data->tile_x, data->tile->width);
+ qsort(glist, txf->num_glyphs, sizeof(unsigned char), glyphCompare);
+
+ 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 (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 {
- tile_fill_run_alpha(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
- tile_line, run_x0 - data->tile_x, data->tile->width,
- alphatab[alpha]);
+ tgi = &txf->tgi[i];
+ getMetric(fontinfo, glist[i], tgi);
+ width = tgi->width;
+ height = tgi->height;
+
+ py += maxheight + gap;
+ px = gap;
+ maxheight = height;
+ if (py + height + gap >= texh) {
+ ZnWarning("Font texture overflow");
+ goto error; /* Overflowed texture space */
+ }
+ c = i;
}
- }
- }
- }
- running_sum += steps[k].delta;
- if (x1 > run_x1) {
- alpha = running_sum >> 16;
- if (alpha) {
- if (alpha >= 255) {
- tile_fill_run(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
- tile_line, run_x1 - data->tile_x, data->tile->width);
+
+ /* 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 {
- tile_fill_run_alpha(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
- tile_line, run_x1 - data->tile_x, data->tile->width,
- alphatab[alpha]);
+ /* 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 / texw + xstep;
+ txf->tgvi[c].t0[1] = tgi->y / 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) / texw + xstep;
+ txf->tgvi[c].t1[1] = tgi->y / 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) / texw + xstep;
+ txf->tgvi[c].t2[1] = (tgi->y + tgi->height) / 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 / texw + xstep;
+ txf->tgvi[c].t3[1] = (tgi->y + tgi->height) / texh + ystep;
+ txf->tgvi[c].v3[0] = tgi->xoffset;
+ txf->tgvi[c].v3[1] = tgi->yoffset;
+ txf->tgvi[c].advance = tgi->advance;
}
}
- }
- else {
- alpha = running_sum >> 16;
- if (alpha) {
- if (alpha >= 255) {
- tile_fill_run(linebuf, x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width);
- }
- else {
- tile_fill_run_alpha(linebuf, x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width,
- alphatab[alpha]);
+
+ 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;
}
- }
- }
-
- data->buf += data->rowstride;
-}
-
-static void
-tile_svp_alpha_cb(void *callback_data,
- int y,
- int start,
- ArtSVPRenderAAStep *steps,
- int n_steps)
-{
- TileSVPData *data = (TileSVPData *)callback_data;
- art_u8 *linebuf, *tile_line;
- int run_x0, run_x1;
- art_u32 running_sum = start;
- int x0, x1, k, dy;
- int *alphatab;
- int alpha;
-
- linebuf = data->buf;
- x0 = data->x0;
- x1 = data->x1;
- alphatab = data->alphatab;
-
- dy = y - data->tile_y;
- dy %= data->tile->height;
- if (dy < 0) {
- dy += data->tile->height;
- }
- tile_line = data->tile->pixels + dy * data->tile->rowstride;
-
- if (n_steps > 0) {
- run_x1 = steps[0].x;
- if (run_x1 > x0) {
- alpha = (running_sum >> 16) & 0xff;
- if (alpha) {
- tile_fill_run_alpha(linebuf, run_x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width,
- alphatab[alpha]);
+ if (txf->tgi[i].c > max_glyph) {
+ max_glyph = txf->tgi[i].c;
}
}
+ /* 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;
- for (k = 0; k < n_steps - 1; k++) {
- running_sum += steps[k].delta;
- run_x0 = run_x1;
- run_x1 = steps[k + 1].x;
- if (run_x1 > run_x0) {
- alpha = (running_sum >> 16) & 0xff;
- if (alpha) {
- tile_fill_run_alpha(linebuf + (run_x0 - x0) * 3, run_x1 - run_x0,
- tile_line, run_x0 - data->tile_x, data->tile->width,
- alphatab[alpha]);
- }
- }
+ txf->lut = (TexGlyphVertexInfo **) ZnMalloc(txf->range * sizeof(TexGlyphVertexInfo *));
+ memset(txf->lut, 0, txf->range * sizeof(TexGlyphVertexInfo *));
+ if (txf->lut == NULL) {
+ goto error;
}
- running_sum += steps[k].delta;
- if (x1 > run_x1) {
- alpha = (running_sum >> 16) & 0xff;
- if (alpha) {
- tile_fill_run_alpha(linebuf + (run_x1 - x0) * 3, x1 - run_x1,
- tile_line, run_x1 - data->tile_x, data->tile->width,
- alphatab[alpha]);
- }
+ for (i = 0; i < txf->num_glyphs; i++) {
+ txf->lut[txf->tgi[i].c - txf->min_glyph] = &txf->tgvi[i];
}
- }
- else {
- alpha = (running_sum >> 16) & 0xff;
- if (alpha) {
- tile_fill_run_alpha(linebuf, x1 - x0,
- tile_line, x0 - data->tile_x, data->tile->width,
- alphatab[alpha]);
+
+ 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, 256, 256, 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);
}
+ ZnFree(fontinfo);
+ ZnFree(glist);
+
+ entry = Tcl_CreateHashEntry(&font_textures, (char *) font, &new);
+ Tcl_SetHashValue(entry, (ClientData) txf);
+ return txf;
}
- data->buf += data->rowstride;
-}
-
-void
-tile_svp_alpha(const ArtSVP *svp,
- int x0,
- int y0,
- int x1,
- int y1,
- int tile_x,
- int tile_y,
- ArtPixBuf *tile,
- art_u8 alpha,
- art_u8 *buf,
- int rowstride)
-{
- TileSVPData data;
- int i, a, da;
-
- data.tile = tile;
- data.tile_x = tile_x;
- data.tile_y = tile_y;
- data.buf = buf;
- data.rowstride = rowstride;
- data.x0 = x0;
- data.x1 = x1;
-
- a = 0x8000;
- da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
- for (i = 0; i < 256; i++) {
- data.alphatab[i] = a >> 16;
- a += da;
- }
-
- if (alpha == 255) {
- art_svp_render_aa(svp, x0, y0, x1, y1, tile_svp_alpha_opaque_cb, &data);
- }
- else {
- art_svp_render_aa(svp, x0, y0, x1, y1, tile_svp_alpha_cb, &data);
+ error:
+ if (glist) {
+ ZnFree(glist);
+ }
+ if (fontinfo) {
+ for (i = 0; i < fontinfo->num_glyphs; i++) {
+ if (fontinfo->glyph[i].bitmap)
+ ZnFree(fontinfo->glyph[i].bitmap);
+ }
+ ZnFree(fontinfo);
}
-}
-
-/*
- * Working only for 16 bits displays with 5r6g5b mask.
- */
-ArtPixBuf *
-GetImagePixbuf(ZnWindow win,
- char *image_name,
- ZnImage image)
-{
- ImageBits *im_bits;
- BitmapBits *b_bits;
- int width, height;
- int x, y;
- int rowstride;
- art_u8 *obuf, *obptr;
- int bpl;
- art_u8 *pixels, *bptr, *bp2;
- art_u8 alpha;
- art_u16 temp;
-
- im_bits = GetImageBits(win, image_name, image);
- if (!im_bits->pixbuf) {
- b_bits = im_bits->b_bits;
- width = im_bits->width;
- height = im_bits->height;
- rowstride = width*4;
- bptr = pixels = art_alloc(rowstride * height);
- obuf = im_bits->pixels->data;
- bpl = im_bits->pixels->bytes_per_line;
-
- for (y = 0; y < height; y++) {
- bp2 = bptr;
- obptr = obuf;
- for (x = 0; x < width; x++) {
- /*
- * Configure the alpha value.
- */
- alpha = GetBitmapPixel(b_bits, x, y) ? 255 : 0;
- /*
- * Dispatch the 3 color components.
- */
- temp = ((art_u16 *)obptr)[0];
- *bp2 = (temp >> 8) & 0xf8; /* r */
- bp2++;
- *bp2 = (temp >> 3) & 0xfc; /* v */
- bp2++;
- *bp2 = (temp << 3); /* b */
- bp2++;
- *bp2 = alpha;
- bp2++;
- obptr += 2;
- }
- bptr += rowstride;
- obuf += bpl;
+ if (txf) {
+ if (txf->tgi) {
+ ZnFree(txf->tgi);
}
-
- im_bits->pixbuf = art_pixbuf_new_rgba(pixels, width, height, rowstride);
+ if (txf->tgvi) {
+ ZnFree(txf->tgvi);
+ }
+ if (txf->lut) {
+ ZnFree(txf->lut);
+ }
+ if (txf->teximage) {
+ ZnFree(txf->teximage);
+ }
+ ZnFree(txf);
}
- return im_bits->pixbuf;
+ return NULL;
}
-#endif
-#ifdef GLX
/*
- * Working only for 16 bits displays with 5r6g5b mask.
- * Need more work at least to support 24 and 32 bit displays.
+ * Working only for 16 bits displays with 5r6g5b mask,
+ * and 24/32 bits displays. Byte ordering ok on Intel
+ * plateform only.
*/
void
From5r6g5b(unsigned char *data,
@@ -1377,7 +890,7 @@ From5r6g5b(unsigned char *data,
int t_width,
int t_height,
BitmapBits *b_bits,
- unsigned char *i_bits)
+ unsigned char *t_bits)
{
int x, y;
int rowstride = t_width * 4;
@@ -1386,7 +899,7 @@ From5r6g5b(unsigned char *data,
unsigned char alpha;
unsigned short temp;
- bptr = i_bits;
+ bptr = t_bits;
for (y = 0; y < height; y++) {
bp2 = bptr;
@@ -1396,7 +909,7 @@ From5r6g5b(unsigned char *data,
* Configure the alpha value.
*/
alpha = GetBitmapPixel(b_bits, x, y) ? 255 : 0;
- alpha = 255;
+
/*
* Dispatch the 3 color components.
*/
@@ -1430,6 +943,63 @@ From5r6g5b(unsigned char *data,
}
}
+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;
+
+ /*
+ * 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)
{
@@ -1448,19 +1018,27 @@ GetImageTexture(ZnWindow win,
{
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->i_bits) {
+ 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->i_bits = ZnMalloc(t_width * 4 * t_height);
- 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->i_bits);
+ 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);
+ }
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
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);
@@ -1468,12 +1046,60 @@ GetImageTexture(ZnWindow win,
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->i_bits);
+ 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));
+ }
+ */
}
return im_bits;
}
+
+BitmapBits *
+GetBitmapTexture(Display *dpy,
+ Pixmap bitmap)
+{
+ 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;
+ }
+ 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;
+}
+
#endif