diff options
Diffstat (limited to 'progs')
| -rw-r--r-- | progs/xdemos/Makefile.X11 | 13 | ||||
| -rw-r--r-- | progs/xdemos/xrotfontdemo.c | 220 | ||||
| -rw-r--r-- | progs/xdemos/xuserotfont.c | 399 | ||||
| -rw-r--r-- | progs/xdemos/xuserotfont.h | 12 | 
4 files changed, 643 insertions, 1 deletions
diff --git a/progs/xdemos/Makefile.X11 b/progs/xdemos/Makefile.X11 index de2273c5e4..2254fd3d3b 100644 --- a/progs/xdemos/Makefile.X11 +++ b/progs/xdemos/Makefile.X11 @@ -24,7 +24,8 @@ PROGS = glthreads \  	pbdemo \  	wincopy \  	xdemo \ -	xfont +	xfont \ +	xrotfontdemo @@ -54,6 +55,16 @@ pbutil.o: pbutil.c pbutil.h  	$(CC) -c -I. -I$(INCDIR) $(CFLAGS) pbutil.c +xrotfontdemo: xrotfontdemo.o xuserotfont.o +	$(CC) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@ + +xuserotfont.o: xuserotfont.c xuserotfont.h +	$(CC) -c -I. -I$(INCDIR) $(CFLAGS) xuserotfont.c + +xrotfontdemo.o: xrotfontdemo.c xuserotfont.h +	$(CC) -c -I. -I$(INCDIR) $(CFLAGS) xrotfontdemo.c + +  ##### TARGETS ##### diff --git a/progs/xdemos/xrotfontdemo.c b/progs/xdemos/xrotfontdemo.c new file mode 100644 index 0000000000..58cd0286cc --- /dev/null +++ b/progs/xdemos/xrotfontdemo.c @@ -0,0 +1,220 @@ +/* + * Mesa 3-D graphics library + *  + * Copyright (C) 1999  Brian Paul   All Rights Reserved. + *  + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + *  + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Example of using glXUseRotatedXFontMESA(). + * 24 Jan 2004 + * Brian Paul + */ + + +#include <GL/gl.h> +#include <GL/glx.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "xuserotfont.h" + + +static const char *ProgramName = "xfont"; + +static const char *FontName = "fixed"; + +static GLuint FontBase[4]; + + +static void redraw( Display *dpy, Window w ) +{ +   static const char *text = "  Rotated bitmap text"; +   int i; + +   glClear( GL_COLOR_BUFFER_BIT ); + +   /* triangle */ +   glColor3f( 0.2, 0.2, 1.0 ); +   glBegin(GL_TRIANGLES); +   glVertex2f( -0.8,  0.7 ); +   glVertex2f( -0.8, -0.7 ); +   glVertex2f(  0.8,  0.0 ); +   glEnd(); + +   /* marker */ +   glColor3f( 0, 1, 0 ); +   glBegin(GL_POINTS); +   glVertex2f(0, 0); +   glEnd(); + +   /* text */ +   glColor3f( 1, 1, 1 ); + +   for (i = 0; i < 4; i++) { +      glRasterPos2f(0, 0);  +      glListBase(FontBase[i]); +      glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text); +   } + +   glXSwapBuffers( dpy, w ); +} + + + +static void resize( unsigned int width, unsigned int height ) +{ +   glViewport( 0, 0, width, height ); +   glMatrixMode( GL_PROJECTION ); +   glLoadIdentity(); +   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ); +} + + + +static void setup_font( Display *dpy ) +{ +    XFontStruct *fontInfo; +    Font id; +    unsigned int first, last; +    int i; + +    fontInfo = XLoadQueryFont(dpy, FontName); +    if (!fontInfo) { +        printf("Error: font %s not found\n", FontName); +	exit(0); +    } + +    id = fontInfo->fid; +    first = fontInfo->min_char_or_byte2; +    last = fontInfo->max_char_or_byte2; + +    for (i = 0; i < 4; i++) { +       FontBase[i] = glGenLists((GLuint) last + 1); +       if (!FontBase[i]) { +          printf("Error: unable to allocate display lists\n"); +          exit(0); +       } +       glXUseRotatedXFontMESA(id, first, last - first + 1, FontBase[i] + first, +                              i * 90); +    } +} + + +static Window make_rgb_db_window( Display *dpy, int xpos, int ypos, +				  unsigned int width, unsigned int height ) +{ +   int attrib[] = { GLX_RGBA, +		    GLX_RED_SIZE, 1, +		    GLX_GREEN_SIZE, 1, +		    GLX_BLUE_SIZE, 1, +		    GLX_DOUBLEBUFFER, +		    None }; +   int scrnum; +   XSetWindowAttributes attr; +   unsigned long mask; +   Window root; +   Window win; +   GLXContext ctx; +   XVisualInfo *visinfo; + +   scrnum = DefaultScreen( dpy ); +   root = RootWindow( dpy, scrnum ); + +   visinfo = glXChooseVisual( dpy, scrnum, attrib ); +   if (!visinfo) { +      printf("Error: couldn't get an RGB, Double-buffered visual\n"); +      exit(1); +   } + +   /* window attributes */ +   attr.background_pixel = 0; +   attr.border_pixel = 0; +   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); +   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; +   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + +   win = XCreateWindow( dpy, root, 0, 0, width, height, +		        0, visinfo->depth, InputOutput, +		        visinfo->visual, mask, &attr ); + +   { +      XSizeHints sizehints; +      sizehints.x = xpos; +      sizehints.y = ypos; +      sizehints.width  = width; +      sizehints.height = height; +      sizehints.flags = USSize | USPosition; +      XSetNormalHints(dpy, win, &sizehints); +      XSetStandardProperties(dpy, win, ProgramName, ProgramName, +                              None, (char **)NULL, 0, &sizehints); +   } + + +   ctx = glXCreateContext( dpy, visinfo, NULL, True ); + +   glXMakeCurrent( dpy, win, ctx ); + +   return win; +} + + +static void event_loop( Display *dpy ) +{ +   XEvent event; + +   while (1) { +      XNextEvent( dpy, &event ); + +      switch (event.type) { +	 case Expose: +	    redraw( dpy, event.xany.window ); +	    break; +	 case ConfigureNotify: +	    resize( event.xconfigure.width, event.xconfigure.height ); +	    break; +         case KeyPress: +            exit(0); +         default: +            ;  /* no-op */ +      } +   } +} + + + +int main( int argc, char *argv[] ) +{ +   Display *dpy; +   Window win; + +   dpy = XOpenDisplay(NULL); + +   win = make_rgb_db_window( dpy, 0, 0, 300, 300 ); +   setup_font( dpy ); + +   glShadeModel( GL_FLAT ); +   glClearColor( 0.5, 0.5, 1.0, 1.0 ); + +   XMapWindow( dpy, win ); + +   event_loop( dpy ); +   return 0; +} diff --git a/progs/xdemos/xuserotfont.c b/progs/xdemos/xuserotfont.c new file mode 100644 index 0000000000..c7724818d5 --- /dev/null +++ b/progs/xdemos/xuserotfont.c @@ -0,0 +1,399 @@ +/* + * Mesa 3-D graphics library + * Version:  6.0 + * + * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* \file xuserotfont.c + * + * A function like glXUseXFont() but takes a 0, 90, 180 or 270 degree + * rotation angle for rotated text display. + * + * Based on Mesa's glXUseXFont implementation written by Thorsten Ohl. + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <GL/glx.h> +#include "xuserotfont.h" + + +/** + * Generate OpenGL-compatible bitmap by drawing an X character glyph + * to an off-screen pixmap, then getting the image and testing pixels. + * \param width  bitmap width in pixels + * \param height  bitmap height in pixels + */ +static void +fill_bitmap(Display *dpy, Pixmap pixmap, GC gc, +	    unsigned int bitmapWidth, unsigned int bitmapHeight, +            unsigned int charWidth, unsigned int charHeight, +	    int xPos, int yPos, unsigned int c, GLubyte * bitmap, +            int rotation) +{ +   const int bytesPerRow = (bitmapWidth + 7) / 8; +   XImage *image; +   XChar2b char2b; + +   /* clear pixmap to 0 */ +   XSetForeground(dpy, gc, 0); +   XFillRectangle(dpy, pixmap, gc, 0, 0, charWidth, charHeight); + +   /* The glyph is drawn snug up against the left/top edges of the pixmap */ +   XSetForeground(dpy, gc, 1); +   char2b.byte1 = (c >> 8) & 0xff; +   char2b.byte2 = (c & 0xff); +   XDrawString16(dpy, pixmap, gc, xPos, yPos, &char2b, 1); + +   /* initialize GL bitmap */ +   memset(bitmap, 0, bytesPerRow * bitmapHeight); + +   image = XGetImage(dpy, pixmap, 0, 0, charWidth, charHeight, 1, XYPixmap); +   if (image) { +      /* Set appropriate bits in the GL bitmap. +       * Note: X11 and OpenGL are upside down wrt each other). +       */ +      unsigned int x, y; +      if (rotation == 0) { +         for (y = 0; y < charHeight; y++) { +            for (x = 0; x < charWidth; x++) { +               if (XGetPixel(image, x, y)) { +                  int y2 = bitmapHeight - y - 1; +                  bitmap[bytesPerRow * y2 + x / 8] |= (1 << (7 - (x % 8))); +               } +            } +         } +      } +      else if (rotation == 90) { +         for (y = 0; y < charHeight; y++) { +            for (x = 0; x < charWidth; x++) { +               if (XGetPixel(image, x, y)) { +                  int x2 = y; +                  int y2 = x; +                  bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8))); +               } +            } +         } +      } +      else if (rotation == 180) { +         for (y = 0; y < charHeight; y++) { +            for (x = 0; x < charWidth; x++) { +               if (XGetPixel(image, x, y)) { +                  int x2 = charWidth - x - 1; +                  bitmap[bytesPerRow * y + x2 / 8] |= (1 << (7 - (x2 % 8))); +               } +            } +         } +      } +      else { +         assert(rotation == 270); +         for (y = 0; y < charHeight; y++) { +            for (x = 0; x < charWidth; x++) { +               if (XGetPixel(image, x, y)) { +                  int x2 = charHeight - y - 1; +                  int y2 = charWidth - x - 1; +                  bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8))); +               } +            } +         } +      } +      XDestroyImage(image); +   } +} + + +/* + * Determine if a given glyph is valid and return the + * corresponding XCharStruct. + */ +static const XCharStruct * +isvalid(const XFontStruct * fs, unsigned int which) +{ +   unsigned int rows, pages; +   unsigned int byte1 = 0, byte2 = 0; +   int i, valid = 1; + +   rows = fs->max_byte1 - fs->min_byte1 + 1; +   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + +   if (rows == 1) { +      /* "linear" fonts */ +      if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which)) +	 valid = 0; +   } +   else { +      /* "matrix" fonts */ +      byte2 = which & 0xff; +      byte1 = which >> 8; +      if ((fs->min_char_or_byte2 > byte2) || +	  (fs->max_char_or_byte2 < byte2) || +	  (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1)) +	 valid = 0; +   } + +   if (valid) { +      if (fs->per_char) { +	 if (rows == 1) { +	    /* "linear" fonts */ +	    return fs->per_char + (which - fs->min_char_or_byte2); +	 } +	 else { +	    /* "matrix" fonts */ +	    i = ((byte1 - fs->min_byte1) * pages) + +	       (byte2 - fs->min_char_or_byte2); +	    return fs->per_char + i; +	 } +      } +      else { +	 return &fs->min_bounds; +      } +   } +   return NULL; +} + + +void +glXUseRotatedXFontMESA(Font font, int first, int count, int listbase, +                       int rotation) +{ +   Display *dpy; +   Window win; +   Pixmap pixmap; +   GC gc; +   XFontStruct *fs; +   GLint swapbytes, lsbfirst, rowlength; +   GLint skiprows, skippixels, alignment; +   unsigned int maxCharWidth, maxCharHeight; +   GLubyte *bm; +   int i; + +   if (rotation != 0 && +       rotation != 90 && +       rotation != 180 && +       rotation != 270) +      return; + +   dpy = glXGetCurrentDisplay(); +   if (!dpy) +      return;			/* I guess glXMakeCurrent wasn't called */ +   win = RootWindow(dpy, DefaultScreen(dpy)); + +   fs = XQueryFont(dpy, font); +   if (!fs) { +      /* +      _mesa_error(NULL, GL_INVALID_VALUE, +		  "Couldn't get font structure information"); +      */ +      return; +   } + +   /* Allocate a GL bitmap that can fit any character */ +   maxCharWidth = fs->max_bounds.rbearing - fs->min_bounds.lbearing; +   maxCharHeight = fs->max_bounds.ascent + fs->max_bounds.descent; +   /* use max, in case we're rotating */ +   if (rotation == 90 || rotation == 270) { +      /* swap width/height */ +      bm = (GLubyte *) malloc((maxCharHeight + 7) / 8 * maxCharWidth); +   } +   else { +      /* normal or upside down */ +      bm = (GLubyte *) malloc((maxCharWidth + 7) / 8 * maxCharHeight); +   } +   if (!bm) { +      XFreeFontInfo(NULL, fs, 1); +      /* +      _mesa_error(NULL, GL_OUT_OF_MEMORY, +		  "Couldn't allocate bitmap in glXUseXFont()"); +      */ +      return; +   } + +#if 0 +   /* get the page info */ +   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; +   firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; +   lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; +   rows = fs->max_byte1 - fs->min_byte1 + 1; +   unsigned int first_char, last_char, pages, rows; +#endif + +   /* Save the current packing mode for bitmaps.  */ +   glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); +   glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); +   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); +   glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); +   glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); +   glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + +   /* Enforce a standard packing mode which is compatible with +      fill_bitmap() from above.  This is actually the default mode, +      except for the (non)alignment.  */ +   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); +   glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); +   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); +   glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +   /* Create pixmap and GC */ +   pixmap = XCreatePixmap(dpy, win, maxCharWidth, maxCharHeight, 1); +   { +      XGCValues values; +      unsigned long valuemask; +      values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); +      values.background = WhitePixel(dpy, DefaultScreen(dpy)); +      values.font = fs->fid; +      valuemask = GCForeground | GCBackground | GCFont; +      gc = XCreateGC(dpy, pixmap, valuemask, &values); +   } + +#ifdef DEBUG_XROT +   if (debug_xfonts) +      dump_font_struct(fs); +#endif + +   for (i = 0; i < count; i++) { +      const unsigned int c = first + i; +      const int list = listbase + i; +      unsigned int charWidth, charHeight; +      unsigned int bitmapWidth, bitmapHeight; +      GLfloat xOrig, yOrig, xStep, yStep, dtemp; +      const XCharStruct *ch; +      int xPos, yPos; +      int valid; + +      /* check on index validity and get the bounds */ +      ch = isvalid(fs, c); +      if (!ch) { +	 ch = &fs->max_bounds; +	 valid = 0; +      } +      else { +	 valid = 1; +      } + +#ifdef DEBUG_XROT +      if (debug_xfonts) { +	 char s[7]; +	 sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); +	 dump_char_struct(ch, s); +      } +#endif + +      /* glBitmap()' parameters: +         straight from the glXUseXFont(3) manpage.  */ +      charWidth = ch->rbearing - ch->lbearing; +      charHeight = ch->ascent + ch->descent; +      xOrig = -ch->lbearing; +      yOrig = ch->descent; +      xStep = ch->width; +      yStep = 0; + +      /* X11's starting point.  */ +      xPos = -ch->lbearing; +      yPos = ch->ascent; + +      /* Apply rotation */ +      switch (rotation) { +      case 0: +         /* nothing */ +         bitmapWidth = charWidth; +         bitmapHeight = charHeight; +         break; +      case 90: +         /* xStep, yStep */ +         dtemp = xStep; +         xStep = -yStep; +         yStep = dtemp; +         /* xOrig, yOrig */ +         yOrig = xOrig; +         xOrig = charHeight - (charHeight - yPos); +         /* width, height */ +         bitmapWidth = charHeight; +         bitmapHeight = charWidth; +         break; +      case 180: +         /* xStep, yStep */ +         xStep = -xStep; +         yStep = -yStep; +         /* xOrig, yOrig */ +         xOrig = charWidth - xOrig - 1; +         yOrig = charHeight - yOrig - 1; +         bitmapWidth = charWidth; +         bitmapHeight = charHeight; +         break; +      case 270: +         /* xStep, yStep */ +         dtemp = xStep; +         xStep = yStep; +         yStep = -dtemp; +         /* xOrig, yOrig */ +         dtemp = yOrig; +         yOrig = charWidth - xOrig; +         xOrig = dtemp; +         /* width, height */ +         bitmapWidth = charHeight; +         bitmapHeight = charWidth; +         break; +      default: +         /* should never get here */ +         ; +      } + +      glNewList(list, GL_COMPILE); +      if (valid && bitmapWidth > 0 && bitmapHeight > 0) { + +	 fill_bitmap(dpy, pixmap, gc, bitmapWidth, bitmapHeight, +                     charWidth, charHeight, +                     xPos, yPos, c, bm, rotation); + +	 glBitmap(bitmapWidth, bitmapHeight, xOrig, yOrig, xStep, yStep, bm); + +#ifdef DEBUG_XROT +	 if (debug_xfonts) { +	    printf("width/height = %u/%u\n", bitmapWidth, bitmapHeight); +	    dump_bitmap(bitmapWidth, bitmapHeight, bm); +	 } +#endif +      } +      else { +	 glBitmap(0, 0, 0.0, 0.0, xStep, yStep, NULL); +      } +      glEndList(); +   } + +   free(bm); +   XFreeFontInfo(NULL, fs, 1); +   XFreePixmap(dpy, pixmap); +   XFreeGC(dpy, gc); + +   /* Restore saved packing modes.  */ +   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); +   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); +   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); +   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); +   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); +   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} + + diff --git a/progs/xdemos/xuserotfont.h b/progs/xdemos/xuserotfont.h new file mode 100644 index 0000000000..ea49203b7b --- /dev/null +++ b/progs/xdemos/xuserotfont.h @@ -0,0 +1,12 @@ +#ifndef XUSEROTFONT_H +#define XUSEROTFONT_H + +#include <X11/Xlib.h> + + +extern void +glXUseRotatedXFontMESA(Font font, int first, int count, int listbase, +                       int rotation); + + +#endif  | 
