home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / xfonts.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  9KB  |  334 lines

  1. /* xfonts.c -- glXUseXFont() for Mesa
  2.    Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; see the file COPYING.  If not, write to
  16.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  */
  19.  
  20.  
  21.  
  22. static char *RCS_Id =
  23. "@(#) $Id: xfonts.c,v 1.6 1995/11/02 14:56:06 brianp Exp $";
  24.  
  25. /*
  26. $Id: xfonts.c,v 1.6 1995/11/02 14:56:06 brianp Exp $
  27.  
  28. $Log: xfonts.c,v $
  29.  * Revision 1.6  1995/11/02  14:56:06  brianp
  30.  * added (GLubyte *) cast per Steven Spitz
  31.  *
  32.  * Revision 1.5  1995/07/24  20:35:20  brianp
  33.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  34.  *
  35.  * Revision 1.4  1995/07/21  16:25:46  brianp
  36.  * replaced XFreeFont() with XFreeFontInfo() per Kevin Adams
  37.  *
  38.  * Revision 1.3  1995/04/17  13:58:52  brianp
  39.  * changed CC->window to CC->frontbuffer
  40.  *
  41.  * Revision 1.2  1995/03/13  15:23:24  brianp
  42.  * Changed XSetForeground to hardcoded values
  43.  *
  44.  * Revision 1.1  1995/03/13  15:20:34  brianp
  45.  * Initial revision
  46.  *
  47.  */
  48.  
  49.  
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <X11/Xlib.h>
  55. #include <X11/Xutil.h>
  56. #include <GL/gl.h>
  57. #include <GL/xmesa.h>
  58. #include "macros.h"
  59.  
  60.  
  61. /* Some debugging info.  */
  62.  
  63. #ifdef DEBUG
  64. #include <ctype.h>
  65.  
  66. int debug_xfonts = 0;
  67.  
  68. static void
  69. dump_char_struct (XCharStruct *ch, char *prefix)
  70. {
  71.   printf ("%slbearing = %d, rbearing = %d, width = %d\n",
  72.       prefix, ch->lbearing, ch->rbearing, ch->width);
  73.   printf ("%sascent = %d, descent = %d, attributes = %u\n",
  74.       prefix, ch->ascent, ch->descent, ch->attributes);
  75. }
  76.  
  77. static void
  78. dump_font_struct (XFontStruct *font)
  79. {
  80.   int c;
  81.   
  82.   printf ("ascent = %d, descent = %d\n", font->ascent, font->descent);
  83.   printf ("char_or_byte2 = (%d,%d)\n",
  84.       font->min_char_or_byte2, font->max_char_or_byte2);
  85.   printf ("byte1 = (%d,%d)\n", font->min_byte1, font->max_byte1);
  86.   printf ("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
  87.   printf ("default_char = %c (\\%03o)\n",
  88.       isprint (font->default_char) ? font->default_char : ' ',
  89.       font->default_char);
  90.   dump_char_struct (&font->min_bounds, "min> ");
  91.   dump_char_struct (&font->max_bounds, "max> ");
  92. #if 0
  93.   for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++)
  94.     {
  95.       char prefix[8];
  96.       sprintf (prefix, "%d> ", c);
  97.       dump_char_struct (&font->per_char[c], prefix);
  98.     }
  99. #endif
  100. }
  101.  
  102. static void
  103. dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap)
  104. {
  105.   int x, y;
  106.  
  107.   printf ("    ");
  108.   for (x = 0; x < 8*width; x++)
  109.     printf ("%o", 7 - (x % 8));
  110.   putchar ('\n');
  111.   for (y = 0; y < height; y++)
  112.     {
  113.       printf ("%3o:", y);
  114.       for (x = 0; x < 8*width; x++)
  115.         putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x % 8))))
  116.          ? '*' : '.');
  117.       printf ("   ");
  118.       for (x = 0; x < width; x++)
  119.     printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]);
  120.       putchar ('\n');
  121.     }
  122. }
  123. #endif /* DEBUG */
  124.  
  125.  
  126. /* Implementation.  */
  127.  
  128. /* Fill a BITMAP with a character C from thew current font
  129.    in the graphics context GC.  WIDTH is the width in bytes
  130.    and HEIGHT is the height in bits.
  131.  
  132.    Note that the generated bitmaps must be used with
  133.  
  134.     glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
  135.     glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
  136.     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
  137.     glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
  138.     glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
  139.     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  140.  
  141.    Possible optimizations:
  142.  
  143.      * use only one reusable pixmap with the maximum dimensions.
  144.      * draw the entire font into a single pixmap (careful with
  145.        proportional fonts!).
  146. */
  147.  
  148. static void
  149. fill_bitmap (Display *dpy, Window win, GC gc,
  150.          unsigned int width, unsigned int height,
  151.          int x0, int y0, char c, GLubyte *bitmap)
  152. {
  153.   XImage *image;
  154.   int x, y;
  155.   Pixmap pixmap;
  156.  
  157.   pixmap = XCreatePixmap (dpy, win, 8*width, height, 1);
  158.   XSetForeground(dpy, gc, 0);
  159.   XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height);
  160.   XSetForeground(dpy, gc, 1);
  161.   XDrawString (dpy, pixmap, gc, x0, y0, &c, 1);
  162.  
  163.   image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap);
  164.  
  165.   /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
  166.   for (y = 0; y < height; y++)
  167.     for (x = 0; x < 8*width; x++)
  168.       if (XGetPixel (image, x, y))
  169.     bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8)));
  170.   
  171.   XFreePixmap (dpy, pixmap);
  172.   XDestroyImage (image);
  173. }
  174.  
  175. #include "xmesaP.h"
  176. #include "context.h"
  177.  
  178. void
  179. glXUseXFont (Font font, int first, int count, int listbase)
  180. {
  181.   XMesaContext CC;
  182.   Display *dpy;
  183.   Window win;
  184.   Pixmap pixmap;
  185.   GC gc;
  186.   XGCValues values;
  187.   unsigned long valuemask;
  188.  
  189.   XFontStruct *fs;
  190.  
  191.   GLint swapbytes, lsbfirst, rowlength;
  192.   GLint skiprows, skippixels, alignment;
  193.  
  194.   unsigned int max_width, max_height, max_bm_width, max_bm_height;
  195.   GLubyte *bm;
  196.  
  197.   int i;
  198.  
  199.   CC = XMesaGetCurrentContext ();  
  200.   dpy = CC->display;
  201.   win = CC->frontbuffer;
  202.  
  203.   fs = XQueryFont (dpy, font);  
  204.   if (!fs)
  205.     {
  206.       gl_error (GL_INVALID_VALUE,
  207.         "Couldn't get font structure information");
  208.       return;
  209.     }
  210.  
  211.   /* Allocate a bitmap that can fit all characters.  */
  212.   max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
  213.   max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
  214.   max_bm_width = (max_width + 7) / 8;
  215.   max_bm_height = max_height;
  216.  
  217.   bm = (GLubyte *) malloc ((max_bm_width * max_bm_height) * sizeof (GLubyte));
  218.   if (!bm)
  219.     {
  220.       gl_error (GL_OUT_OF_MEMORY,
  221.         "Couldn't allocate bitmap in glXUseXFont()");
  222.       return;
  223.     }
  224.  
  225.   /* Save the current packing mode for bitmaps.  */
  226.   glGetIntegerv    (GL_UNPACK_SWAP_BYTES, &swapbytes);
  227.   glGetIntegerv    (GL_UNPACK_LSB_FIRST, &lsbfirst);
  228.   glGetIntegerv    (GL_UNPACK_ROW_LENGTH, &rowlength);
  229.   glGetIntegerv    (GL_UNPACK_SKIP_ROWS, &skiprows);
  230.   glGetIntegerv    (GL_UNPACK_SKIP_PIXELS, &skippixels);
  231.   glGetIntegerv    (GL_UNPACK_ALIGNMENT, &alignment);
  232.  
  233.   /* Enforce a standard packing mode which is compatible with
  234.      fill_bitmap() from above.  This is actually the default mode,
  235.      except for the (non)alignment.  */
  236.   glPixelStorei    (GL_UNPACK_SWAP_BYTES, GL_FALSE);
  237.   glPixelStorei    (GL_UNPACK_LSB_FIRST, GL_FALSE);
  238.   glPixelStorei    (GL_UNPACK_ROW_LENGTH, 0);
  239.   glPixelStorei    (GL_UNPACK_SKIP_ROWS, 0);
  240.   glPixelStorei    (GL_UNPACK_SKIP_PIXELS, 0);
  241.   glPixelStorei    (GL_UNPACK_ALIGNMENT, 1);
  242.  
  243.   pixmap = XCreatePixmap (dpy, win, 10, 10, 1);
  244.   values.foreground = BlackPixel (dpy, DefaultScreen (dpy));
  245.   values.background = WhitePixel (dpy, DefaultScreen (dpy));
  246.   values.font = fs->fid;
  247.   valuemask = GCForeground | GCBackground | GCFont;
  248.   gc = XCreateGC (dpy, pixmap, valuemask, &values);
  249.   XFreePixmap (dpy, pixmap);
  250.  
  251. #ifdef DEBUG
  252.   if (debug_xfonts)
  253.     dump_font_struct (fs);
  254. #endif
  255.   
  256.   for (i = 0; i < count; i++)
  257.     {
  258.       unsigned int width, height, bm_width, bm_height;
  259.       GLfloat x0, y0, dx, dy;
  260.       XCharStruct *ch;
  261.       int x, y;
  262.       int c = first + i;
  263.       int list = listbase + i;
  264.  
  265.       if (fs->per_char
  266.       && (c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2))
  267.     ch = &fs->per_char[c-fs->min_char_or_byte2];
  268.       else
  269.     ch = &fs->max_bounds;
  270.  
  271. #ifdef DEBUG
  272.       if (debug_xfonts)
  273.     {
  274.       char s[7];
  275.       sprintf (s, isprint (c) ? "%c> " : "\\%03o> ", c);
  276.       dump_char_struct (ch, s);
  277.     }
  278. #endif
  279.       
  280.       /* glBitmap()' parameters:
  281.      straight from the glXUseXFont(3) manpage.  */
  282.       width = ch->rbearing - ch->lbearing;
  283.       height = ch->ascent + ch->descent;
  284.       x0 = - ch->lbearing;
  285.       y0 = ch->descent - 1;
  286.       dx = ch->width;
  287.       dy = 0;
  288.  
  289.       /* X11's starting point.  */
  290.       x = - ch->lbearing;
  291.       y = ch->ascent;
  292.       
  293.       /* Round the width to a multiple of eight.  We will use this also
  294.      for the pixmap for capturing the X11 font.  This is slightly
  295.      inefficient, but it makes the OpenGL part real easy.  */
  296.       bm_width = (width + 7) / 8;
  297.       bm_height = height;
  298.  
  299.       glNewList (list, GL_COMPILE);
  300.         if ((c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2)
  301.         && (bm_width > 0) && (bm_height > 0))
  302.       {
  303.         MEMSET (bm, '\0', bm_width * bm_height);
  304.         fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm);
  305.         glBitmap (width, height, x0, y0, dx, dy, bm);
  306. #ifdef DEBUG
  307.         if (debug_xfonts)
  308.           {
  309.         printf ("width/height = %d/%d\n", width, height);
  310.         printf ("bm_width/bm_height = %d/%d\n", bm_width, bm_height);
  311.         dump_bitmap (bm_width, bm_height, bm);
  312.           }
  313. #endif
  314.       }
  315.     else
  316.       glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL);
  317.       glEndList ();
  318.     }
  319.  
  320.   free (bm);
  321.   XFreeFontInfo( NULL, fs, 0 );
  322.   XFreeGC (dpy, gc);
  323.  
  324.   /* Restore saved packing modes.  */    
  325.   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
  326.   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
  327.   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
  328.   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
  329.   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
  330.   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
  331. }
  332.  
  333. /* The End. */
  334.