Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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