blob: 4ca2c8f868f4afe43ee84d2fd055c9105bbffc2d [file] [log] [blame]
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001/*
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
Kristian Høgsberg286ce272007-11-06 14:34:15 -050036#ifdef GLX_DIRECT_RENDERING
Adam Jacksoncb3610e2004-10-25 21:09:16 +000037
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
48int debug_xfonts = 0;
49
50static void
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020051dump_char_struct(XCharStruct * ch, char *prefix)
Adam Jacksoncb3610e2004-10-25 21:09:16 +000052{
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020053 printf("%slbearing = %d, rbearing = %d, width = %d\n",
Adam Jacksoncb3610e2004-10-25 21:09:16 +000054 prefix, ch->lbearing, ch->rbearing, ch->width);
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020055 printf("%sascent = %d, descent = %d, attributes = %u\n",
Adam Jacksoncb3610e2004-10-25 21:09:16 +000056 prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
57}
58
59static void
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020060dump_font_struct(XFontStruct * font)
Adam Jacksoncb3610e2004-10-25 21:09:16 +000061{
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020062 printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
63 printf("char_or_byte2 = (%u,%u)\n",
Adam Jacksoncb3610e2004-10-25 21:09:16 +000064 font->min_char_or_byte2, font->max_char_or_byte2);
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020065 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 : ' '),
Adam Jacksoncb3610e2004-10-25 21:09:16 +000069 font->default_char);
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020070 dump_char_struct(&font->min_bounds, "min> ");
71 dump_char_struct(&font->max_bounds, "max> ");
Adam Jacksoncb3610e2004-10-25 21:09:16 +000072#if 0
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020073 for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +000074 char prefix[8];
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020075 sprintf(prefix, "%d> ", c);
76 dump_char_struct(&font->per_char[c], prefix);
77 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +000078#endif
79}
80
81static void
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020082dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +000083{
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020084 unsigned int x, y;
Adam Jacksoncb3610e2004-10-25 21:09:16 +000085
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020086 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))))
Adam Jacksoncb3610e2004-10-25 21:09:16 +000095 ? '*' : '.');
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020096 printf(" ");
Adam Jacksoncb3610e2004-10-25 21:09:16 +000097 for (x = 0; x < width; x++)
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +020098 printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
99 putchar('\n');
100 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000101}
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 */
131static void
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200132fill_bitmap(Display * dpy, Window win, GC gc,
133 unsigned int width, unsigned int height,
134 int x0, int y0, unsigned int c, GLubyte * bitmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000135{
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200136 XImage *image;
137 unsigned int x, y;
138 Pixmap pixmap;
139 XChar2b char2b;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000140
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200141 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);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000145
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200146 char2b.byte1 = (c >> 8) & 0xff;
147 char2b.byte2 = (c & 0xff);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000148
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200149 XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000150
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200151 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 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000161
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200162 XFreePixmap(dpy, pixmap);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000163}
164
165/*
166 * determine if a given glyph is valid and return the
167 * corresponding XCharStruct.
168 */
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200169static XCharStruct *
170isvalid(XFontStruct * fs, int which)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000171{
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200172 unsigned int rows, pages;
173 int byte1 = 0, byte2 = 0;
174 int i, valid = 1;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000175
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200176 rows = fs->max_byte1 - fs->min_byte1 + 1;
177 pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000178
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200179 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 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000193
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200194 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 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000206 }
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200207 else {
208 return (&fs->min_bounds);
209 }
210 }
211 return (NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000212}
213
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200214_X_HIDDEN void
Kristian Høgsbergc356f582010-07-28 11:16:00 -0400215DRI_glXUseXFont(struct glx_context *CC, Font font, int first, int count, int listbase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000216{
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200217 Display *dpy;
218 Window win;
219 Pixmap pixmap;
220 GC gc;
221 XGCValues values;
222 unsigned long valuemask;
223 XFontStruct *fs;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000224
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200225 GLint swapbytes, lsbfirst, rowlength;
226 GLint skiprows, skippixels, alignment;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000227
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200228 unsigned int max_width, max_height, max_bm_width, max_bm_height;
229 GLubyte *bm;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000230
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200231 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000232
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200233 dpy = CC->currentDpy;
234 win = CC->currentDrawable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000235
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200236 fs = XQueryFont(dpy, font);
237 if (!fs) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000238 __glXSetError(CC, GL_INVALID_VALUE);
239 return;
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200240 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000241
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200242 /* 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;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000247
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200248 bm = (GLubyte *) Xmalloc((max_bm_width * max_bm_height) * sizeof(GLubyte));
249 if (!bm) {
250 XFreeFontInfo(NULL, fs, 1);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000251 __glXSetError(CC, GL_OUT_OF_MEMORY);
252 return;
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200253 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000254
255#if 0
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200256 /* 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;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000262#endif
263
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200264 /* 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);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000271
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200272 /* 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);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000281
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200282 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);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000289
290#ifdef DEBUG
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200291 if (debug_xfonts)
292 dump_font_struct(fs);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000293#endif
294
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200295 for (i = 0; i < count; i++) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000296 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) {
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200307 ch = &fs->max_bounds;
308 valid = 0;
309 }
310 else {
311 valid = 1;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000312 }
313
314#ifdef DEBUG
315 if (debug_xfonts) {
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200316 char s[7];
317 sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
318 dump_char_struct(ch, s);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000319 }
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;
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200326 x0 = -ch->lbearing;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000327 y0 = ch->descent - 1;
328 dx = ch->width;
329 dy = 0;
330
331 /* X11's starting point. */
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200332 x = -ch->lbearing;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000333 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
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200341 glNewList(list, GL_COMPILE);
342 if (valid && (bm_width > 0) && (bm_height > 0)) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000343
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200344 memset(bm, '\0', bm_width * bm_height);
345 fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000346
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200347 glBitmap(width, height, x0, y0, dx, dy, bm);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000348#ifdef DEBUG
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200349 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 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000354#endif
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200355 }
356 else {
357 glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
358 }
359 glEndList();
360 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000361
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200362 Xfree(bm);
363 XFreeFontInfo(NULL, fs, 1);
364 XFreeGC(dpy, gc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000365
RALOVICH, Kristóf1d0a9e42008-10-13 15:04:31 +0200366 /* 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);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000373}
374
Kristian Høgsberg286ce272007-11-06 14:34:15 -0500375#endif