Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / glx / xfont.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  3.1
4  *
5  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25
26 /* xfonts.c -- glXUseXFont() for Mesa written by
27  * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
28  */
29
30 /*
31   This was take from Mesa and modified to work in the real GLX structure.
32   It provides a fully client side implementation of glXUseXFont and is
33   called by that routine when direct rendering is enabled.
34 */
35
36 #ifdef GLX_DIRECT_RENDERING
37
38 #include "glxclient.h"
39
40 /* Some debugging info.  */
41
42 #ifdef DEBUG
43 #undef _R
44 #undef _G
45 #undef _B
46 #include <ctype.h>
47
48 int debug_xfonts = 0;
49
50 static void
51 dump_char_struct(XCharStruct * ch, char *prefix)
52 {
53    printf("%slbearing = %d, rbearing = %d, width = %d\n",
54           prefix, ch->lbearing, ch->rbearing, ch->width);
55    printf("%sascent = %d, descent = %d, attributes = %u\n",
56           prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
57 }
58
59 static void
60 dump_font_struct(XFontStruct * font)
61 {
62    printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
63    printf("char_or_byte2 = (%u,%u)\n",
64           font->min_char_or_byte2, font->max_char_or_byte2);
65    printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
66    printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
67    printf("default_char = %c (\\%03o)\n",
68           (char) (isprint(font->default_char) ? font->default_char : ' '),
69           font->default_char);
70    dump_char_struct(&font->min_bounds, "min> ");
71    dump_char_struct(&font->max_bounds, "max> ");
72 #if 0
73    for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
74       char prefix[8];
75       sprintf(prefix, "%d> ", c);
76       dump_char_struct(&font->per_char[c], prefix);
77    }
78 #endif
79 }
80
81 static void
82 dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
83 {
84    unsigned int x, y;
85
86    printf("    ");
87    for (x = 0; x < 8 * width; x++)
88       printf("%o", 7 - (x % 8));
89    putchar('\n');
90    for (y = 0; y < height; y++) {
91       printf("%3o:", y);
92       for (x = 0; x < 8 * width; x++)
93          putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %
94                                                                          8))))
95                  ? '*' : '.');
96       printf("   ");
97       for (x = 0; x < width; x++)
98          printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
99       putchar('\n');
100    }
101 }
102 #endif /* DEBUG */
103
104
105 /* Implementation.  */
106
107 /* Fill a BITMAP with a character C from thew current font
108    in the graphics context GC.  WIDTH is the width in bytes
109    and HEIGHT is the height in bits.
110
111    Note that the generated bitmaps must be used with
112
113         glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
114         glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
115         glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
116         glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
117         glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
118         glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
119
120    Possible optimizations:
121
122      * use only one reusable pixmap with the maximum dimensions.
123      * draw the entire font into a single pixmap (careful with
124        proportional fonts!).
125 */
126
127
128 /*
129  * Generate OpenGL-compatible bitmap.
130  */
131 static void
132 fill_bitmap(Display * dpy, Window win, GC gc,
133             unsigned int width, unsigned int height,
134             int x0, int y0, unsigned int c, GLubyte * bitmap)
135 {
136    XImage *image;
137    unsigned int x, y;
138    Pixmap pixmap;
139    XChar2b char2b;
140
141    pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
142    XSetForeground(dpy, gc, 0);
143    XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
144    XSetForeground(dpy, gc, 1);
145
146    char2b.byte1 = (c >> 8) & 0xff;
147    char2b.byte2 = (c & 0xff);
148
149    XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
150
151    image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
152    if (image) {
153       /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
154       for (y = 0; y < height; y++)
155          for (x = 0; x < 8 * width; x++)
156             if (XGetPixel(image, x, y))
157                bitmap[width * (height - y - 1) + x / 8] |=
158                   (1 << (7 - (x % 8)));
159       XDestroyImage(image);
160    }
161
162    XFreePixmap(dpy, pixmap);
163 }
164
165 /*
166  * determine if a given glyph is valid and return the
167  * corresponding XCharStruct.
168  */
169 static XCharStruct *
170 isvalid(XFontStruct * fs, int which)
171 {
172    unsigned int rows, pages;
173    int byte1 = 0, byte2 = 0;
174    int i, valid = 1;
175
176    rows = fs->max_byte1 - fs->min_byte1 + 1;
177    pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
178
179    if (rows == 1) {
180       /* "linear" fonts */
181       if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
182          valid = 0;
183    }
184    else {
185       /* "matrix" fonts */
186       byte2 = which & 0xff;
187       byte1 = which >> 8;
188       if ((fs->min_char_or_byte2 > byte2) ||
189           (fs->max_char_or_byte2 < byte2) ||
190           (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
191          valid = 0;
192    }
193
194    if (valid) {
195       if (fs->per_char) {
196          if (rows == 1) {
197             /* "linear" fonts */
198             return (fs->per_char + (which - fs->min_char_or_byte2));
199          }
200          else {
201             /* "matrix" fonts */
202             i = ((byte1 - fs->min_byte1) * pages) +
203                (byte2 - fs->min_char_or_byte2);
204             return (fs->per_char + i);
205          }
206       }
207       else {
208          return (&fs->min_bounds);
209       }
210    }
211    return (NULL);
212 }
213
214 _X_HIDDEN void
215 DRI_glXUseXFont(struct glx_context *CC, Font font, int first, int count, int listbase)
216 {
217    Display *dpy;
218    Window win;
219    Pixmap pixmap;
220    GC gc;
221    XGCValues values;
222    unsigned long valuemask;
223    XFontStruct *fs;
224
225    GLint swapbytes, lsbfirst, rowlength;
226    GLint skiprows, skippixels, alignment;
227
228    unsigned int max_width, max_height, max_bm_width, max_bm_height;
229    GLubyte *bm;
230
231    int i;
232
233    dpy = CC->currentDpy;
234    win = CC->currentDrawable;
235
236    fs = XQueryFont(dpy, font);
237    if (!fs) {
238       __glXSetError(CC, GL_INVALID_VALUE);
239       return;
240    }
241
242    /* Allocate a bitmap that can fit all characters.  */
243    max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
244    max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
245    max_bm_width = (max_width + 7) / 8;
246    max_bm_height = max_height;
247
248    bm = (GLubyte *) Xmalloc((max_bm_width * max_bm_height) * sizeof(GLubyte));
249    if (!bm) {
250       XFreeFontInfo(NULL, fs, 1);
251       __glXSetError(CC, GL_OUT_OF_MEMORY);
252       return;
253    }
254
255 #if 0
256    /* get the page info */
257    pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
258    firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
259    lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
260    rows = fs->max_byte1 - fs->min_byte1 + 1;
261    unsigned int first_char, last_char, pages, rows;
262 #endif
263
264    /* Save the current packing mode for bitmaps.  */
265    glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
266    glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
267    glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
268    glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
269    glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
270    glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
271
272    /* Enforce a standard packing mode which is compatible with
273       fill_bitmap() from above.  This is actually the default mode,
274       except for the (non)alignment.  */
275    glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
276    glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
277    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
278    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
279    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
280    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
281
282    pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
283    values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
284    values.background = WhitePixel(dpy, DefaultScreen(dpy));
285    values.font = fs->fid;
286    valuemask = GCForeground | GCBackground | GCFont;
287    gc = XCreateGC(dpy, pixmap, valuemask, &values);
288    XFreePixmap(dpy, pixmap);
289
290 #ifdef DEBUG
291    if (debug_xfonts)
292       dump_font_struct(fs);
293 #endif
294
295    for (i = 0; i < count; i++) {
296       unsigned int width, height, bm_width, bm_height;
297       GLfloat x0, y0, dx, dy;
298       XCharStruct *ch;
299       int x, y;
300       unsigned int c = first + i;
301       int list = listbase + i;
302       int valid;
303
304       /* check on index validity and get the bounds */
305       ch = isvalid(fs, c);
306       if (!ch) {
307          ch = &fs->max_bounds;
308          valid = 0;
309       }
310       else {
311          valid = 1;
312       }
313
314 #ifdef DEBUG
315       if (debug_xfonts) {
316          char s[7];
317          sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
318          dump_char_struct(ch, s);
319       }
320 #endif
321
322       /* glBitmap()' parameters:
323          straight from the glXUseXFont(3) manpage.  */
324       width = ch->rbearing - ch->lbearing;
325       height = ch->ascent + ch->descent;
326       x0 = -ch->lbearing;
327       y0 = ch->descent - 1;
328       dx = ch->width;
329       dy = 0;
330
331       /* X11's starting point.  */
332       x = -ch->lbearing;
333       y = ch->ascent;
334
335       /* Round the width to a multiple of eight.  We will use this also
336          for the pixmap for capturing the X11 font.  This is slightly
337          inefficient, but it makes the OpenGL part real easy.  */
338       bm_width = (width + 7) / 8;
339       bm_height = height;
340
341       glNewList(list, GL_COMPILE);
342       if (valid && (bm_width > 0) && (bm_height > 0)) {
343
344          memset(bm, '\0', bm_width * bm_height);
345          fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
346
347          glBitmap(width, height, x0, y0, dx, dy, bm);
348 #ifdef DEBUG
349          if (debug_xfonts) {
350             printf("width/height = %u/%u\n", width, height);
351             printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
352             dump_bitmap(bm_width, bm_height, bm);
353          }
354 #endif
355       }
356       else {
357          glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
358       }
359       glEndList();
360    }
361
362    Xfree(bm);
363    XFreeFontInfo(NULL, fs, 1);
364    XFreeGC(dpy, gc);
365
366    /* Restore saved packing modes.  */
367    glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
368    glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
369    glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
370    glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
371    glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
372    glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
373 }
374
375 #endif