diff --git a/FL/gl.h b/FL/gl.h
index d1d76a239285d8c097a61e330ec1c75aac81c07c..1f60f63faf4e9c865cea31968abbe3a164c926ef 100644
--- a/FL/gl.h
+++ b/FL/gl.h
@@ -98,6 +98,10 @@ FL_EXPORT void gl_draw(const char*, int n, int x, int y);
 FL_EXPORT void gl_draw(const char*, int n, float x, float y);
 FL_EXPORT void gl_draw(const char*, int x, int y, int w, int h, Fl_Align);
 FL_EXPORT void gl_measure(const char*, int& x, int& y);
+#ifdef __APPLE__
+extern FL_EXPORT void gl_texture_pile_height(int max);
+extern FL_EXPORT int gl_texture_pile_height();
+#endif
 
 FL_EXPORT void gl_draw_image(const uchar *, int x,int y,int w,int h, int d=3, int ld=0);
 
diff --git a/src/gl_draw.cxx b/src/gl_draw.cxx
index f0323d4edc0e92ce935c6d5a0375e064881659c5..8593f40f6e8d2532280ed1e9676ddfecf6eedf66 100644
--- a/src/gl_draw.cxx
+++ b/src/gl_draw.cxx
@@ -29,7 +29,7 @@
 // See also Fl_Gl_Window and gl_start.cxx
 
 #include "flstring.h"
-#if HAVE_GL
+#if HAVE_GL || defined(FL_DOXYGEN)
 
 #include <FL/Fl.H>
 #include <FL/gl.h>
@@ -129,7 +129,6 @@ void  gl_font(int fontid, int size) {
 }
 
 #ifndef __APPLE__
-// The OSX build does not use this at present... It probbaly should, though...
 static void get_list(int r) {
   gl_fontsize->glok[r] = 1;
 #if defined(USE_X11)
@@ -151,7 +150,7 @@ static void get_list(int r) {
   wglUseFontBitmapsW(fl_gc, ii, ii + 0x03ff, gl_fontsize->listbase+ii);
   SelectObject(fl_gc, oldFid);
 #elif defined(__APPLE_QUARTZ__)
-// FIXME:
+// handled by textures
 #else
 #  error unsupported platform
 #endif
@@ -197,14 +196,15 @@ void gl_remove_displaylist_fonts()
 #endif
 }
 
-/**
-  Draws an array of n characters of the string in the current font
-  at the current position.
-  */
 #ifdef __APPLE__
 static void gl_draw_cocoa(const char* str, int n);
 #endif
 
+/**
+  Draws an array of n characters of the string in the current font
+  at the current position.
+ \see On the Mac OS X platform, see gl_texture_pile_height(int)
+  */
 void gl_draw(const char* str, int n) {
 #ifdef __APPLE__  
   gl_draw_cocoa(str, n);  
@@ -237,6 +237,7 @@ void gl_draw(const char* str, int n) {
 
 /**
   Draws n characters of the string in the current font at the given position 
+ \see On the Mac OS X platform, see gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int n, int x, int y) {
   glRasterPos2i(x, y);
@@ -245,6 +246,7 @@ void gl_draw(const char* str, int n, int x, int y) {
 
 /**
   Draws n characters of the string in the current font at the given position 
+ \see On the Mac OS X platform, see gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int n, float x, float y) {
   glRasterPos2f(x, y);
@@ -253,6 +255,7 @@ void gl_draw(const char* str, int n, float x, float y) {
 
 /**
   Draws a nul-terminated string in the current font at the current position
+ \see On the Mac OS X platform, see gl_texture_pile_height(int)
   */
 void gl_draw(const char* str) {
   gl_draw(str, strlen(str));
@@ -260,6 +263,7 @@ void gl_draw(const char* str) {
 
 /**
   Draws a nul-terminated string in the current font at the given position 
+ \see On the Mac OS X platform, see gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int x, int y) {
   gl_draw(str, strlen(str), x, y);
@@ -267,6 +271,7 @@ void gl_draw(const char* str, int x, int y) {
 
 /**
   Draws a nul-terminated string in the current font at the given position 
+ \see On the Mac OS X platform, see gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, float x, float y) {
   gl_draw(str, strlen(str), x, y);
@@ -289,6 +294,7 @@ void gl_draw(
   fl_draw(str, x, -y-h, w, h, align, gl_draw_invert);
 }
 
+/** Measure how wide and tall the string will be when drawn by the gl_draw() function */
 void gl_measure(const char* str, int& x, int& y) {fl_measure(str,x,y);}
 
 /**
@@ -351,13 +357,56 @@ void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) {
   glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
 }
 
-#ifdef __APPLE__
+#if defined( __APPLE__) || defined(FL_DOXYGEN)
 
 #include <FL/glu.h>
 
-static void gl_draw_cocoa(const char* str, int n) 
+// manages a fifo pile of pre-computed string textures
+class gl_texture_fifo {
+  friend void gl_draw_cocoa(const char *, int);
+private:
+  typedef struct { // information for a pre-computed texture
+    GLuint texName; // its name
+    char *utf8; //its text
+    Fl_Font_Descriptor *fdesc; // its font
+    int width; // its width
+    int height; // its height
+  } data;
+  data *fifo; // array of pile elements
+  int size_; // pile height
+  int current; // the oldest texture to have entered the pile
+  int last; // pile top
+  int textures_generated; // true iff glGenTextures has been called
+  void display_texture(int rank);
+  int compute_texture(const char* str, int n);
+  int already_known(const char *str, int n);
+public:
+  gl_texture_fifo(int max = 100); // 100 = default height of texture pile
+  inline int size(void) {return size_; };
+  ~gl_texture_fifo(void);
+};
+
+gl_texture_fifo::gl_texture_fifo(int max)
+{
+  size_ = max;
+  last = current = -1;
+  textures_generated = 0;
+  fifo = (data*)calloc(size_, sizeof(data));
+}
+
+gl_texture_fifo::~gl_texture_fifo()
+{
+  for (int i = 0; i < size_; i++) {
+    if (fifo[i].utf8) free(fifo[i].utf8);
+    if (textures_generated) glDeleteTextures(1, &fifo[i].texName);
+    }
+  free(fifo);
+}
+
+// displays a pre-computed texture on the GL scene
+void gl_texture_fifo::display_texture(int rank)
 {
-//setup matrices
+  //setup matrices
   GLint matrixMode;
   glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
   glMatrixMode (GL_PROJECTION);
@@ -370,64 +419,41 @@ static void gl_draw_cocoa(const char* str, int n)
   float winh = Fl_Window::current()->h();
   glScalef (2.0f / winw, 2.0f /  winh, 1.0f);
   glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f);
-//write str to a bitmap just big enough  
-  int w = 0, h = 0;
-  fl_measure(str, w, h, 0);
-  CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
-  void *base = calloc(4*w, h);
-  if(base == NULL) return;
-  fl_gc = CGBitmapContextCreate(base, w, h, 8, w*4, lut, kCGImageAlphaPremultipliedLast);
-  CGColorSpaceRelease(lut);
-  fl_fontsize = gl_fontsize;
-  fl_draw(str, 0, h - fl_descent());
-//put this bitmap in a texture  
-  static GLuint texName = 0;
-  glPushAttrib(GL_TEXTURE_BIT);
-  if (0 == texName) glGenTextures (1, &texName);
-  glBindTexture (GL_TEXTURE_RECTANGLE_EXT, texName);
-  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, w, h, 0,  GL_RGBA, GL_UNSIGNED_BYTE, base);
-  glPopAttrib();
-  CGContextRelease(fl_gc);
-  fl_gc = NULL;
-  free(base);
+  //write the texture on screen
   GLfloat pos[4];
   glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-  if (texName) {//write the texture on screen
-	CGRect bounds = CGRectMake (pos[0], pos[1] - fl_descent(), w, h);
-	glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); // GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable
-	
-	glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test.
-	glEnable (GL_BLEND); // for text fading
-	glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // ditto
-	glEnable (GL_TEXTURE_RECTANGLE_EXT);	
-	
-	glBindTexture (GL_TEXTURE_RECTANGLE_EXT, texName);
-	glBegin (GL_QUADS);
-	glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
-	glVertex2f (bounds.origin.x, bounds.origin.y);
-	
-	glTexCoord2f (0.0f, h); // draw upper left in world coordinates
-	glVertex2f (bounds.origin.x, bounds.origin.y + bounds.size.height);
-	
-	glTexCoord2f (w, h); // draw upper right in world coordinates
-	glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height);
-	
-	glTexCoord2f (w, 0.0f); // draw lower right in world coordinates
-	glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y);
-	glEnd ();
-	
-	glPopAttrib();
-	glDeleteTextures(1, &texName);
-  }
+  CGRect bounds = CGRectMake (pos[0], pos[1] - fl_descent(), fifo[rank].width, fifo[rank].height);
+  glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); // GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable
+  
+  glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test.
+  glEnable (GL_BLEND); // for text fading
+  glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // ditto
+  glEnable (GL_TEXTURE_RECTANGLE_EXT);	
+  
+  glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[rank].texName);
+  glBegin (GL_QUADS);
+  glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
+  glVertex2f (bounds.origin.x, bounds.origin.y);
+  
+  glTexCoord2f (0.0f, fifo[rank].height); // draw upper left in world coordinates
+  glVertex2f (bounds.origin.x, bounds.origin.y + bounds.size.height);
+  
+  glTexCoord2f (fifo[rank].width, fifo[rank].height); // draw upper right in world coordinates
+  glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height);
+  
+  glTexCoord2f (fifo[rank].width, 0.0f); // draw lower right in world coordinates
+  glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y);
+  glEnd ();
+  
+  glPopAttrib();
   // reset original matrices
   glPopMatrix(); // GL_MODELVIEW
   glMatrixMode (GL_PROJECTION);
   glPopMatrix();
   glMatrixMode (matrixMode);
-//set the raster position to end of string
-  pos[0] += w;
+  
+  //set the raster position to end of string
+  pos[0] += fifo[rank].width;
   GLdouble modelmat[16];
   glGetDoublev (GL_MODELVIEW_MATRIX, modelmat);
   GLdouble projmat[16];
@@ -438,9 +464,100 @@ static void gl_draw_cocoa(const char* str, int n)
   gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ);
   glRasterPos2d(objX, objY);
 }
-#endif
 
-#endif
+// pre-computes a string texture
+int gl_texture_fifo::compute_texture(const char* str, int n)
+{
+  current = (current + 1) % size_;
+  if (current > last) last = current;
+  //write str to a bitmap just big enough  
+  fifo[current].width = 0, fifo[current].height = 0;
+  fl_measure(str, fifo[current].width, fifo[current].height, 0);
+  CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+  void *base = calloc(4*fifo[current].width, fifo[current].height);
+  if (base == NULL) return -1;
+  fl_gc = CGBitmapContextCreate(base, fifo[current].width, fifo[current].height, 8, fifo[current].width*4, lut, kCGImageAlphaPremultipliedLast);
+  CGColorSpaceRelease(lut);
+  fl_fontsize = gl_fontsize;
+  fl_draw(str, 0, fifo[current].height - fl_descent());
+  //put this bitmap in a texture  
+  glPushAttrib(GL_TEXTURE_BIT);
+  glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[current].texName);
+  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, fifo[current].width, fifo[current].height, 0,  GL_RGBA, GL_UNSIGNED_BYTE, base);
+  glPopAttrib();
+  CGContextRelease(fl_gc);
+  fl_gc = NULL;
+  free(base);
+  if ( fifo[current].utf8 ) free(fifo[current].utf8);
+  fifo[current].utf8 = (char *)malloc(n + 1);
+  memcpy(fifo[current].utf8, str, n);
+  fifo[current].utf8[n] = 0;
+  fifo[current].fdesc = gl_fontsize;
+  return current;
+}
+
+// returns rank of pre-computed texture for a string if it exists
+int gl_texture_fifo::already_known(const char *str, int n)
+{
+  int rank;
+  for ( rank = 0; rank <= last; rank++) {
+    if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 &&
+      fifo[rank].fdesc == gl_fontsize) return rank;
+  }
+  return -1;
+}
+
+static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance
+
+// draws a utf8 string using pre-computed texture if available
+static void gl_draw_cocoa(const char* str, int n) 
+{
+  if (! gl_fifo) gl_fifo = new gl_texture_fifo();
+  if (!gl_fifo->textures_generated) {
+    for (int i = 0; i < gl_fifo->size_; i++) glGenTextures (1, &(gl_fifo->fifo[i].texName));
+    gl_fifo->textures_generated = 1;
+  }
+  int rank = gl_fifo->already_known(str, n);
+  if (rank == -1) {
+    rank = gl_fifo->compute_texture(str, n);
+  }
+  gl_fifo->display_texture(rank);
+}
+
+/** \addtogroup group_macosx
+ @{ */
+
+/**
+ \brief Returns the current height of the pile of pre-computed string textures
+ *
+ The default value is 100
+ */
+int gl_texture_pile_height(void)
+{
+  if (! gl_fifo) gl_fifo = new gl_texture_fifo();
+  return gl_fifo->size();
+}
+
+/**
+ \brief Changes the height of the pile of pre-computed string textures
+ *
+ Strings that are often re-displayed can be processed much faster if
+ this pile is set high enough to hold all of them.
+ \param max Height of the texture pile
+ */
+void gl_texture_pile_height(int max)
+{
+  if (gl_fifo) delete gl_fifo;
+  gl_fifo = new gl_texture_fifo(max);
+}
+
+/** @} */
+
+#endif // __APPLE__
+
+#endif // HAVE_GL
 
 //
 // End of "$Id$".