Index: FL/Fl.H
===================================================================
--- FL/Fl.H	(revision 12646)
+++ FL/Fl.H	(working copy)
@@ -134,6 +134,7 @@
 private:
 
   static int use_high_res_GL_;
+  static int draw_GL_text_with_textures_;
 
 public:
 
@@ -1266,6 +1267,27 @@
    */
   static int use_high_res_GL() { return use_high_res_GL_; }
 
+  /**  sets whether OpenGL uses textures to draw all text.
+   By default, FLTK draws OpenGL text using textures, if the necessary
+   hardware support is available. Call \p Fl::draw_GL_text_with_textures(0)
+   once in your program before the first call to gl_font() to have FLTK
+   draw instead OpenGL text using a legacy, platform-dependent procedure.
+   It's recommended not to deactivate textures under the MacOS platform
+   because the MacOS legacy procedure is extremely rudimentary.
+   \param val use 0 to prevent FLTK from drawing GL text with textures
+   \see gl_texture_pile_height(int max)
+   \version 1.4.0
+   */
+  static void draw_GL_text_with_textures(int val) { draw_GL_text_with_textures_ = val; }
+
+  /**  returns whether whether OpenGL uses textures to draw all text.
+   Default is yes.
+   \see draw_GL_text_with_textures(int val)
+   \version 1.4.0
+   */
+  static int draw_GL_text_with_textures() { return draw_GL_text_with_textures_; }
+
+
 #ifdef FLTK_HAVE_CAIRO
   /** \defgroup group_cairo Cairo Support Functions and Classes
       @{ 
Index: FL/Fl_Gl_Window_Driver.H
===================================================================
--- FL/Fl_Gl_Window_Driver.H	(revision 12646)
+++ FL/Fl_Gl_Window_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // Definition of class Fl_Gl_Window_Driver, and of its platform-specific derived classes
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2016-2017 by Bill Spitzak and others.
+// Copyright 2016-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -44,7 +44,7 @@
   void alist(const int *l) { pWindow->alist = l;}
   void* overlay() {return pWindow->overlay;}
   void draw_overlay() {pWindow->draw_overlay();}
-  
+
   Fl_Gl_Window_Driver(Fl_Gl_Window *win) : pWindow(win) {}
   virtual ~Fl_Gl_Window_Driver() {}
   static Fl_Gl_Window_Driver *newGlWindowDriver(Fl_Gl_Window *w);
@@ -79,10 +79,17 @@
   virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual() function
   virtual void gl_start() {} // support for gl_start() function
   virtual void* GetProcAddress(const char *procName); // support for glutGetProcAddress()
-  virtual void draw_string(const char* str, int n); // support for gl_draw()
+  virtual void draw_string_legacy(const char* str, int n); // support for gl_draw()
+  void draw_string_legacy_get_list(const char* str, int n); // support for gl_draw()
+  static void draw_string_legacy_glut(const char* str, int n); // support for gl_draw()
   virtual void get_list(Fl_Font_Descriptor* fd, int r) {} // support for gl_draw() without textures
   virtual void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {} // support for gl_font() without textures
   virtual int overlay_color(Fl_Color i) {return 0;} // support for gl_color() with HAVE_GL_OVERLAY
+  static void draw_string_with_texture(const char* str, int n); // cross-platform
+  // support for gl_draw(). The cross-platform version may be enough.
+  virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
+  virtual int genlistsize() { return 0; } // support for gl_draw()
+  virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum);
 };
 
 #ifdef FL_CFG_GFX_QUARTZ
@@ -111,7 +118,6 @@
   virtual void make_overlay_current();
   virtual void redraw_overlay();
   virtual void gl_start();
-  virtual void draw_string(const char* str, int n);
   static NSOpenGLContext* create_GLcontext_for_window(NSOpenGLPixelFormat *pixelformat, NSOpenGLContext *shared_ctx, Fl_Window *window);
   static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // uses Objective-c
   static void GLcontext_update(NSOpenGLContext*); // uses Objective-c
@@ -118,6 +124,7 @@
   static void GLcontext_release(NSOpenGLContext*); // uses Objective-c
   static void GLcontext_makecurrent(NSOpenGLContext*); // uses Objective-c
   static void GL_cleardrawable(void); // uses Objective-c
+  virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
 };
 #endif // FL_CFG_GFX_QUARTZ
 
@@ -141,8 +148,10 @@
   virtual void make_overlay_current();
   virtual void redraw_overlay();
   virtual void* GetProcAddress(const char *procName);
+  virtual void draw_string_legacy(const char* str, int n);
   virtual void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize);
   virtual void get_list(Fl_Font_Descriptor *fd, int r);
+  virtual int genlistsize();
 #if HAVE_GL_OVERLAY
   virtual int can_do_overlay();
   virtual int overlay_color(Fl_Color i);
@@ -153,7 +162,7 @@
 
 
 #ifdef FL_CFG_GFX_XLIB
-#include <X11/Xutil.h>
+#include <X11/Xutil.h> // for XVisualInfo
 class Fl_X11_Gl_Window_Driver : public Fl_Gl_Window_Driver {
   friend class Fl_Gl_Window_Driver;
   Fl_X11_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
@@ -178,9 +187,14 @@
   virtual void waitGL();
   virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual()
   virtual void gl_start();
+  virtual void draw_string_legacy(const char* str, int n);
   virtual void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize);
   virtual void get_list(Fl_Font_Descriptor *fd, int r);
-public:
+  virtual int genlistsize();
+#if !USE_XFT
+  virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum);
+#endif
+  public:
   static GLContext create_gl_context(XVisualInfo* vis);
 };
 
Index: FL/Fl_Graphics_Driver.H
===================================================================
--- FL/Fl_Graphics_Driver.H	(revision 12646)
+++ FL/Fl_Graphics_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // Definition of classes  Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2017 by Bill Spitzak and others.
+// Copyright 2010-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -90,6 +90,7 @@
   friend void fl_copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
   friend FL_EXPORT int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg);
   friend FL_EXPORT void gl_start();
+  friend FL_EXPORT void gl_finish();
   friend FL_EXPORT Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array);
   friend FL_EXPORT void fl_delete_bitmask(Fl_Bitmask);
 private:
@@ -387,7 +388,7 @@
   /** Some platforms may need to implement this to support fonts */
   virtual Fl_Fontdesc* calc_fl_fonts(void) {return NULL;}
   /** Support for Fl::set_font() */
-  virtual unsigned font_desc_size() {return 0;}
+  virtual unsigned font_desc_size();
   /** Support for Fl::get_font() */
   virtual const char *font_name(int num) {return NULL;}
   /** Support for Fl::set_font() */
@@ -396,6 +397,31 @@
   virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H);
 };
 
+/**
+ This is a structure for an actual system font, with junk to
+ help choose it and info on character sizes.  Each Fl_Fontdesc has a
+ linked list of these.  These are created the first time each system
+ font/size combination is used.
+ */
+class Fl_Font_Descriptor {
+public:
+  /** linked list for this Fl_Fontdesc */
+  Fl_Font_Descriptor *next;
+  Fl_Fontsize size; /**< font size */
+#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc.
+  Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
+  FL_EXPORT ~Fl_Font_Descriptor() {}
+  short ascent, descent, q_width;
+  unsigned int listbase;// base of display list, 0 = none
+#endif // FL_DOXYGEN
+};
+
+struct Fl_Fontdesc {
+  const char *name;
+  char fontname[128];  // "Pretty" font name
+  Fl_Font_Descriptor *first;  // linked list of sizes of this style
+};
+
 #ifndef FL_DOXYGEN
 /* Abstract class Fl_Scalable_Graphics_Driver is platform-independent.
  It supports the scaling of all graphics coordinates by a
Index: FL/gl.h
===================================================================
--- FL/gl.h	(revision 12646)
+++ FL/gl.h	(working copy)
@@ -3,7 +3,7 @@
 //
 // OpenGL header file for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2018 by Bill Spitzak and others.
 //
 // You must include this instead of GL/gl.h to get the Microsoft
 // APIENTRY stuff included (from <windows.h>) prior to the OpenGL
@@ -28,10 +28,11 @@
  *
  *  To use OpenGL from within an FLTK application you MUST use gl_visual()
  *  to select the default visual before doing show() on any windows. Mesa
- *  will crash if yoy try to use a visual not returned by glxChooseVidual.
+ *  will crash if you try to use a visual not returned by glxChooseVisual.
  *
- *  This does not work with Fl_Double_Window's!  It will try to draw
- *  into the front buffer.  Depending on the system this will either
+ *  Historically, this did not always work well with Fl_Double_Window's!
+ *  It can try to draw into the front buffer.
+ *  Depending on the system this might either
  *  crash or do nothing (when pixmaps are being used as back buffer
  *  and GL is being done by hardware), work correctly (when GL is done
  *  with software, such as Mesa), or draw into the front buffer and
@@ -89,16 +90,8 @@
 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__ // PORTME: OpenGL platform texture
-extern FL_EXPORT void gl_texture_pile_height(int max);
-extern FL_EXPORT int gl_texture_pile_height();
-#elif defined(WIN32)
-  // not needed
-#elif defined(FL_PORTING)
-#  pragma message "FL_PORTING: define functions to control OpenGL texture pile height if supported"
-#else // X11
-  // not needed
-#endif
+FL_EXPORT void gl_texture_pile_height(int max);
+FL_EXPORT int  gl_texture_pile_height();
 
 FL_EXPORT void gl_draw_image(const uchar *, int x,int y,int w,int h, int d=3, int ld=0);
 
Index: src/Fl.cxx
===================================================================
--- src/Fl.cxx	(revision 12646)
+++ src/Fl.cxx	(working copy)
@@ -1898,6 +1898,8 @@
 
 int Fl::use_high_res_GL_ = 0;
 
+int Fl::draw_GL_text_with_textures_ = 1;
+
 int Fl::dnd()
 {
   return Fl::screen_driver()->dnd();
Index: src/Fl_Gl_Window.cxx
===================================================================
--- src/Fl_Gl_Window.cxx	(revision 12646)
+++ src/Fl_Gl_Window.cxx	(working copy)
@@ -495,6 +495,10 @@
 #endif // HAVE_DLSYM
 }
 
+Fl_Font_Descriptor** Fl_Gl_Window_Driver::fontnum_to_fontdescriptor(int fnum) {
+  extern FL_EXPORT Fl_Fontdesc *fl_fonts;
+  return &(fl_fonts[fnum].first);
+}
 
 #ifdef FL_CFG_GFX_QUARTZ
 #include <FL/platform.H>
Index: src/Fl_Graphics_Driver.cxx
===================================================================
--- src/Fl_Graphics_Driver.cxx	(revision 12646)
+++ src/Fl_Graphics_Driver.cxx	(working copy)
@@ -217,7 +217,19 @@
   shared->scaled_image_->draw(X, Y, shared->scaled_image_->w(), shared->scaled_image_->h(), 0, 0);
 }
 
+Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) {
+  next = 0;
+#  if HAVE_GL
+  listbase = 0;
+#  endif
+  // OpenGL needs those for its font handling
+  size = Size;
+}
 
+unsigned Fl_Graphics_Driver::font_desc_size() {
+  return (unsigned)sizeof(Fl_Fontdesc);
+}
+
 #ifndef FL_DOXYGEN
 Fl_Scalable_Graphics_Driver::Fl_Scalable_Graphics_Driver() : Fl_Graphics_Driver() {
   scale_ = 1;
Index: src/drivers/GDI/Fl_Font.H
===================================================================
--- src/drivers/GDI/Fl_Font.H	(revision 12646)
+++ src/drivers/GDI/Fl_Font.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Font definitions for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -32,35 +32,19 @@
    linked list of these.  These are created the first time each system
    font/size combination is used.
 */
-class Fl_Font_Descriptor {
+class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor {
 public:
-  /** linked list for this Fl_Fontdesc */
-  Fl_Font_Descriptor *next;	
-  Fl_Fontsize size; /**< font size */
-#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc. 
   HFONT fid;
   int *width[64];
   TEXTMETRIC metr;
   int angle;
-  FL_EXPORT Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
+  FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size);
 #  if HAVE_GL
-  unsigned int listbase;// base of display list, 0 = none
   char glok[64];
 #  endif // HAVE_GL
-
-  FL_EXPORT ~Fl_Font_Descriptor();
-
-#endif // FL_DOXYGEN
+  FL_EXPORT ~Fl_GDI_Font_Descriptor();
 };
 
-//extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one
-
-struct Fl_Fontdesc {
-  const char *name;
-  char fontname[128];	// "Pretty" font name
-  Fl_Font_Descriptor *first;	// linked list of sizes of this style
-};
-
 extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
 
 #endif
Index: src/drivers/GDI/Fl_GDI_Graphics_Driver.H
===================================================================
--- src/drivers/GDI/Fl_GDI_Graphics_Driver.H	(revision 12646)
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // Definition of classes  Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2017 by Bill Spitzak and others.
+// Copyright 2010-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -146,7 +146,6 @@
   virtual const char* get_font_name(Fl_Font fnum, int* ap);
   virtual const char *font_name(int num);
   virtual void font_name(int num, const char *name);
-  virtual unsigned font_desc_size();
   void global_gc();
 };
 
Index: src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
===================================================================
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx	(revision 12646)
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx	(working copy)
@@ -189,10 +189,6 @@
   return nbSize;
 }
 
-unsigned Fl_GDI_Graphics_Driver::font_desc_size() {
-  return (unsigned)sizeof(Fl_Fontdesc);
-}
-
 const char *Fl_GDI_Graphics_Driver::font_name(int num) {
   return fl_fonts[num].name;
 }
@@ -215,7 +211,7 @@
 static int fl_angle_ = 0;
 
 #ifndef FL_DOXYGEN
-Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize) {
+Fl_GDI_Font_Descriptor::Fl_GDI_Font_Descriptor(const char* name, Fl_Fontsize fsize) : Fl_Font_Descriptor(name,fsize) {
   int weight = FW_NORMAL;
   int italic = 0;
   switch (*name++) {
@@ -252,13 +248,12 @@
   int i;
   memset(width, 0, 64 * sizeof(int*));
 #if HAVE_GL
-  listbase = 0;
   for (i = 0; i < 64; i++) glok[i] = 0;
 #endif
   size = fsize;
 }
 
-Fl_Font_Descriptor::~Fl_Font_Descriptor() {
+Fl_GDI_Font_Descriptor::~Fl_GDI_Font_Descriptor() {
 #if HAVE_GL
 // Delete list created by gl_draw().  This is not done by this code
 // as it will link in GL unnecessarily.  There should be some kind
@@ -296,13 +291,13 @@
 
 Fl_Fontdesc* fl_fonts = built_in_table;
 
-static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) {
+static Fl_GDI_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) {
   Fl_Fontdesc* s = fl_fonts+fnum;
   if (!s->name) s = fl_fonts; // use 0 if fnum undefined
-  Fl_Font_Descriptor* f;
-  for (f = s->first; f; f = f->next)
+  Fl_GDI_Font_Descriptor* f;
+  for (f = (Fl_GDI_Font_Descriptor*)s->first; f; f = (Fl_GDI_Font_Descriptor*)f->next)
     if (f->size == size && f->angle == angle) return f;
-  f = new Fl_Font_Descriptor(s->name, size);
+  f = new Fl_GDI_Font_Descriptor(s->name, size);
   f->next = s->first;
   s->first = f;
   return f;
@@ -328,13 +323,13 @@
 }
 
 int Fl_GDI_Graphics_Driver::height_unscaled() {
-  Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+  Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
   if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
   else return -1;
 }
 
 int Fl_GDI_Graphics_Driver::descent_unscaled() {
-  Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+  Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
   if (fl_fontsize) return fl_fontsize->metr.tmDescent;
   else return -1;
 }
@@ -369,7 +364,7 @@
 }
 
 double Fl_GDI_Graphics_Driver::width_unscaled(unsigned int c) {
-  Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+  Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
   unsigned int r;
   SIZE s;
   // Special Case Handling of Unicode points over U+FFFF.
@@ -468,7 +463,7 @@
 // Function to determine the extent of the "inked" area of the glyphs in a string
 void Fl_GDI_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
 
-  Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+  Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
   if (!fl_fontsize) { // no valid font, nothing to measure
     w = 0; h = 0;
     dx = dy = 0;
@@ -582,7 +577,7 @@
   COLORREF oldColor = SetTextColor(gc_, fl_RGB());
   // avoid crash if no font has been set yet
   if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
-  SelectObject(gc_, font_descriptor()->fid);
+  SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
   int wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
   if(wn >= wstr_len) {
     wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
@@ -597,7 +592,7 @@
   fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), angle);
   int wn = 0; // count of UTF16 cells to render full string
   COLORREF oldColor = SetTextColor(gc_, fl_RGB());
-  SelectObject(gc_, font_descriptor()->fid);
+  SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
   wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
   if(wn >= wstr_len) { // Array too small
     wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
@@ -619,7 +614,7 @@
   }
 
   COLORREF oldColor = SetTextColor(gc_, fl_RGB());
-  SelectObject(gc_, font_descriptor()->fid);
+  SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
 #ifdef RTL_CHAR_BY_CHAR
   int i = 0;
   int lx = 0;
Index: src/drivers/Quartz/Fl_Font.H
===================================================================
--- src/drivers/Quartz/Fl_Font.H	(revision 12646)
+++ src/drivers/Quartz/Fl_Font.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Font definitions for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -34,15 +34,10 @@
    linked list of these.  These are created the first time each system
    font/size combination is used.
 */
-class Fl_Font_Descriptor {
+class Fl_Quartz_Font_Descriptor : public Fl_Font_Descriptor {
 public:
-  /** linked list for this Fl_Fontdesc */
-  Fl_Font_Descriptor *next;	
-  Fl_Fontsize size; /**< font size */
-#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc. 
-  Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
-  FL_EXPORT ~Fl_Font_Descriptor();
-  short ascent, descent, q_width;
+  Fl_Quartz_Font_Descriptor(const char* fontname, Fl_Fontsize size);
+  FL_EXPORT ~Fl_Quartz_Font_Descriptor();
 # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
   CTFontRef fontref;
   // the unicode span is divided in 512 blocks of 128 characters
@@ -52,21 +47,8 @@
   ATSUTextLayout layout;
   ATSUStyle style;
 # endif
-# if HAVE_GL
-  unsigned int listbase;// base of display list, 0 = none
-# endif // HAVE_GL
-
-#endif // FL_DOXYGEN
 };
 
-//extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one
-
-struct Fl_Fontdesc {
-  const char *name;
-  char fontname[128];	// "Pretty" font name
-  Fl_Font_Descriptor *first;	// linked list of sizes of this style
-};
-
 extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
 
 #endif
Index: src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
===================================================================
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H	(revision 12646)
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H	(working copy)
@@ -34,6 +34,7 @@
     MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
 
 struct Fl_Fontdesc;
+class Fl_Quartz_Font_Descriptor;
 
 /**
  \brief The Mac OS X-specific graphics class.
@@ -43,6 +44,7 @@
 class Fl_Quartz_Graphics_Driver : public Fl_Graphics_Driver {
   friend class Fl_Font_Descriptor;
   friend class Fl_Cocoa_Printer_Driver;
+  friend class Fl_Quartz_Font_Descriptor;
 protected:
   CGContextRef gc_;
   int p_size;
@@ -146,10 +148,9 @@
   virtual bool high_resolution() { return high_resolution_; }
   virtual void global_gc();
   void quartz_restore_line_style();
-  inline Fl_Font_Descriptor *valid_font_descriptor();
+  inline Fl_Quartz_Font_Descriptor *valid_font_descriptor();
   virtual const char* get_font_name(Fl_Font fnum, int* ap);
   virtual int get_font_sizes(Fl_Font fnum, int*& sizep);
-  virtual unsigned font_desc_size();
   virtual const char *font_name(int num);
   virtual void font_name(int num, const char *name);
   Fl_Fontdesc* calc_fl_fonts(void);
@@ -165,13 +166,13 @@
   static void init_CoreText_or_ATSU();
   void draw_CoreText(const char *str, int n, float x, float y);
   double width_CoreText(const UniChar* txt, int n);
-  void descriptor_init_CoreText(const char* name, Fl_Fontsize Size, Fl_Font_Descriptor *d);
+  void descriptor_init_CoreText(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
   void text_extents_CoreText(const char*, int n, int& dx, int& dy, int& w, int& h);
   Fl_Font set_fonts_CoreText(const char* xstarname);
 
   void draw_ATSU(const char *str, int n, float x, float y);
   double width_ATSU(const UniChar* txt, int n);
-  void descriptor_init_ATSU(const char* name, Fl_Fontsize Size, Fl_Font_Descriptor *d);
+  void descriptor_init_ATSU(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
   void text_extents_ATSU(const char*, int n, int& dx, int& dy, int& w, int& h);
   Fl_Font set_fonts_ATSU(const char* xstarname);
 
@@ -181,7 +182,7 @@
   static pter_to_draw_member CoreText_or_ATSU_draw;
   static pter_to_width_member CoreText_or_ATSU_width;
 #else
-  void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Font_Descriptor *d);
+  void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
 #endif
 };
 
Index: src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx
===================================================================
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx	(revision 12646)
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx	(working copy)
@@ -179,13 +179,7 @@
   return cnt;
 }
 
-Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) {
-  next = 0;
-#  if HAVE_GL
-  listbase = 0;
-#  endif
-  // OpenGL needs those for its font handling
-  size = Size;
+Fl_Quartz_Font_Descriptor::Fl_Quartz_Font_Descriptor(const char* name, Fl_Fontsize Size) : Fl_Font_Descriptor(name, Size) {
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
   fontref = NULL;
 #endif
@@ -205,7 +199,7 @@
 }
 
 
-Fl_Font_Descriptor::~Fl_Font_Descriptor() {
+Fl_Quartz_Font_Descriptor::~Fl_Quartz_Font_Descriptor() {
 /*
 #if HAVE_GL
  // ++ todo: remove OpenGL font allocations
@@ -257,7 +251,7 @@
   Fl_Font_Descriptor* f;
   for (f = s->first; f; f = f->next)
     if (f->size == size) return f;
-  f = new Fl_Font_Descriptor(s->name, size);
+  f = new Fl_Quartz_Font_Descriptor(s->name, size);
   f->next = s->first;
   s->first = f;
   return f;
@@ -273,19 +267,19 @@
   font_descriptor( find(fnum, size) );
 }
 
-Fl_Font_Descriptor *Fl_Quartz_Graphics_Driver::valid_font_descriptor() {
+Fl_Quartz_Font_Descriptor *Fl_Quartz_Graphics_Driver::valid_font_descriptor() {
   // avoid a crash if no font has been selected by user yet
   if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
-  return font_descriptor();
+  return (Fl_Quartz_Font_Descriptor*)font_descriptor();
 }
 
 int Fl_Quartz_Graphics_Driver::height() {
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   return fl_fontsize->ascent + fl_fontsize->descent;
 }
 
 int Fl_Quartz_Graphics_Driver::descent() {
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   return fl_fontsize->descent + 1;
 }
 
@@ -351,11 +345,6 @@
 #endif
 }
 
-
-unsigned Fl_Quartz_Graphics_Driver::font_desc_size() {
-  return (unsigned)sizeof(Fl_Fontdesc);
-}
-
 const char *Fl_Quartz_Graphics_Driver::font_name(int num) {
   if (!fl_fonts) fl_fonts = calc_fl_fonts();
   return fl_fonts[num].name;
@@ -421,7 +410,7 @@
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
 
 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _CoreText)(const char* name,
-                                                      Fl_Fontsize size, Fl_Font_Descriptor *d)
+                                                      Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d)
 {
   CFStringRef str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
   d->fontref = CTFontCreateWithName(str, size, NULL);
@@ -470,7 +459,7 @@
 }
 
 // returns width of a pair of UniChar's in the surrogate range
-static CGFloat surrogate_width(const UniChar *txt, Fl_Font_Descriptor *fl_fontsize)
+static CGFloat surrogate_width(const UniChar *txt, Fl_Quartz_Font_Descriptor *fl_fontsize)
 {
   CTFontRef font2 = fl_fontsize->fontref;
   bool must_release = false;
@@ -491,7 +480,7 @@
   return a.width;
 }
 
-static CGFloat variation_selector_width(CFStringRef str16, Fl_Font_Descriptor *fl_fontsize)
+static CGFloat variation_selector_width(CFStringRef str16, Fl_Quartz_Font_Descriptor *fl_fontsize)
 {
   CGFloat retval;
   CFDictionarySetValue(attributes, kCTFontAttributeName, fl_fontsize->fontref);
@@ -508,7 +497,7 @@
   double retval = 0;
   UniChar uni;
   int i;
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   for (i = 0; i < n; i++) { // loop over txt
     uni = txt[i];
     if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range
@@ -576,7 +565,7 @@
 // text extent calculation
 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(text_extents, _CoreText)(const char *str8, int n,
                                                                     int &dx, int &dy, int &w, int &h) {
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n);
   CFStringRef str16 = CFStringCreateWithCharactersNoCopy(NULL, txt, n,  kCFAllocatorNull);
   CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref);
@@ -610,7 +599,7 @@
 
 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(draw, _CoreText)(const char *str, int n, float x, float y)
 {
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   // convert to UTF-16 first
   UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n);
   CGContextRef gc = (CGContextRef)this->gc();
@@ -710,7 +699,7 @@
 #if HAS_ATSU
 
 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _ATSU)(const char* name,
-                                                      Fl_Fontsize size, Fl_Font_Descriptor *d)
+                                                      Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d)
 {
   OSStatus err;
   // fill our structure with a few default values
@@ -766,7 +755,7 @@
 
 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(draw, _ATSU)(const char *str, int n, float x, float y)
 {
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   // convert to UTF-16 first
   UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n);
   CGContextRef gc = (CGContextRef)this->gc();
@@ -793,7 +782,7 @@
   ATSUAttributeTag iTag;
   ATSUAttributeValuePtr iValuePtr;
 
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   // Here's my ATSU text measuring attempt... This seems to do the Right Thing
   // now collect our ATSU resources and measure our text string
   layout = fl_fontsize->layout;
@@ -814,7 +803,7 @@
 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(text_extents, _ATSU)(const char *str8, int n,
                                                                 int &dx, int &dy, int &w, int &h)
 {
-  Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
+  Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
   UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n);
   OSStatus err;
   ATSUTextLayout layout;
Index: src/drivers/Xlib/Fl_Font.H
===================================================================
--- src/drivers/Xlib/Fl_Font.H	(revision 12646)
+++ src/drivers/Xlib/Fl_Font.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Font definitions for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -38,12 +38,8 @@
    linked list of these.  These are created the first time each system
    font/size combination is used.
 */
-class Fl_Font_Descriptor {
+class Fl_Xlib_Font_Descriptor : public Fl_Font_Descriptor {
 public:
-  /** linked list for this Fl_Fontdesc */
-  Fl_Font_Descriptor *next;	
-  Fl_Fontsize size; /**< font size */
-#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc. 
 #  if USE_XFT
 #    if USE_PANGO
         int descent_;
@@ -52,24 +48,21 @@
         XftFont* font;
 #    endif
   int angle;
-  FL_EXPORT Fl_Font_Descriptor(const char* xfontname, Fl_Fontsize size, int angle);
+  FL_EXPORT Fl_Xlib_Font_Descriptor(const char* xfontname, Fl_Fontsize size, int angle);
 #  else
   XUtf8FontStruct* font;	// X UTF-8 font information
-  FL_EXPORT Fl_Font_Descriptor(const char* xfontname);
+  FL_EXPORT Fl_Xlib_Font_Descriptor(const char* xfontname);
 #  endif
 #  if HAVE_GL
-  unsigned int listbase;// base of display list, 0 = none
   char glok[64];
 #  endif // HAVE_GL
-
-  FL_EXPORT ~Fl_Font_Descriptor();
-
-#endif // FL_DOXYGEN
+  FL_EXPORT ~Fl_Xlib_Font_Descriptor();
 };
 
 //extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one
 
-struct Fl_Fontdesc {
+#if !USE_XFT
+struct Fl_Xlib_Fontdesc { // replaces Fl_Fontdesc
   const char *name;
   char fontname[128];	// "Pretty" font name
   Fl_Font_Descriptor *first;	// linked list of sizes of this style
@@ -76,6 +69,7 @@
   char **xlist;		// matched X font names
   int n;		// size of xlist, negative = don't free xlist!
 };
+#endif
 
 extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
 
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(revision 12646)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(working copy)
@@ -180,7 +180,9 @@
   virtual void reset_spot();
   virtual const char* get_font_name(Fl_Font fnum, int* ap);
   virtual int get_font_sizes(Fl_Font fnum, int*& sizep);
+#if !USE_XFT
   virtual unsigned font_desc_size();
+#endif
   virtual const char *font_name(int num);
   virtual void font_name(int num, const char *name);
   virtual Fl_Font set_fonts(const char* xstarname);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(revision 12646)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(working copy)
@@ -202,22 +202,34 @@
   XFree(preedit_attr);
 }
 
+#if !USE_XFT
 unsigned Fl_Xlib_Graphics_Driver::font_desc_size() {
-  return (unsigned)sizeof(Fl_Fontdesc);
+  return (unsigned)sizeof(Fl_Xlib_Fontdesc);
 }
+#endif
 
 const char *Fl_Xlib_Graphics_Driver::font_name(int num) {
+#if USE_XFT
   return fl_fonts[num].name;
+#else
+  return ((Fl_Xlib_Fontdesc*)fl_fonts)[num].name;
+#endif
 }
 
 void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) {
-#if USE_PANGO
+#if USE_XFT
+#  if USE_PANGO
     init_built_in_fonts();
+#  endif
+  Fl_Fontdesc *s = fl_fonts + num;
+#else
+    Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts) + num;
 #endif
-  Fl_Fontdesc *s = fl_fonts + num;
   if (s->name) {
     if (!strcmp(s->name, name)) {s->name = name; return;}
+#if !USE_XFT
     if (s->xlist && s->n >= 0) XFreeFontNames(s->xlist);
+#endif
     for (Fl_Font_Descriptor* f = s->first; f;) {
       Fl_Font_Descriptor* n = f->next; delete f; f = n;
     }
@@ -225,7 +237,9 @@
   }
   s->name = name;
   s->fontname[0] = 0;
+#if !USE_XFT
   s->xlist = 0;
+#endif
   s->first = 0;
 }
 
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(revision 12646)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(working copy)
@@ -94,7 +94,7 @@
 
 // turn a stored (with *'s) X font name into a pretty name:
 const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
-  Fl_Fontdesc *f = fl_fonts + fnum;
+  Fl_Xlib_Fontdesc *f = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum;
   if (!f->fontname[0]) {
     int type = 0;
     const char* p = f->name;
@@ -312,9 +312,10 @@
 	break;
       }
     }
-    if (!fl_fonts[j].xlist) {
-      fl_fonts[j].xlist = xlist+first_xlist;
-      fl_fonts[j].n = -(i-first_xlist);
+    Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts)+j;
+    if (!s->xlist) {
+      s->xlist = xlist+first_xlist;
+      s->n = -(i-first_xlist);
       used_xlist = 1;
     }
   }
@@ -323,8 +324,8 @@
 }
 
 int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
-  Fl_Fontdesc *s = fl_fonts+fnum;
-  if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+  Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum;
+  if (!s->name) s = ((Fl_Xlib_Fontdesc*)fl_fonts); // empty slot in table, use entry 0
   if (!s->xlist) {
     fl_open_display();
     s->xlist = XListFonts(fl_display, s->name, 100, &(s->n));
@@ -358,7 +359,7 @@
 
 #ifndef FL_DOXYGEN
 
-Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) {
+Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name) : Fl_Font_Descriptor(name, 0) {
   font = XCreateUtf8FontStruct(fl_display, name);
   if (!font) {
     Fl::warning("bad font: %s", name);
@@ -372,7 +373,7 @@
 
 Fl_XFont_On_Demand fl_xfont;
 
-Fl_Font_Descriptor::~Fl_Font_Descriptor() {
+Fl_Xlib_Font_Descriptor::~Fl_Xlib_Font_Descriptor() {
 #  if HAVE_GL
 // Delete list created by gl_draw().  This is not done by this code
 // as it will link in GL unnecessarily.  There should be some kind
@@ -389,7 +390,7 @@
 
 // WARNING: if you add to this table, you must redefine FL_FREE_FONT
 // in Enumerations.H & recompile!!
-static Fl_Fontdesc built_in_table[] = {
+static Fl_Xlib_Fontdesc built_in_table[] = {
 {"-*-helvetica-medium-r-normal--*"},
 {"-*-helvetica-bold-r-normal--*"},
 {"-*-helvetica-medium-o-normal--*"},
@@ -408,7 +409,7 @@
 {"-*-*zapf dingbats-*"}
 };
 
-Fl_Fontdesc* fl_fonts = built_in_table;
+Fl_Fontdesc* fl_fonts = (Fl_Fontdesc*)built_in_table;
 
 #define MAXSIZE 32767
 
@@ -554,8 +555,8 @@
 
 
 char *fl_get_font_xfld(int fnum, int size) {
-  Fl_Fontdesc* s = fl_fonts+fnum;
-  if (!s->name) s = fl_fonts; // use font 0 if still undefined
+  Fl_Xlib_Fontdesc* s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum;
+  if (!s->name) s = (Fl_Xlib_Fontdesc*)fl_fonts; // use font 0 if still undefined
   fl_open_display();
   return put_font_size(s->name, size);
 }
@@ -563,8 +564,8 @@
 // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size:
 static Fl_Font_Descriptor* find(int fnum, int size) {
   char *name;
-  Fl_Fontdesc* s = fl_fonts+fnum;
-  if (!s->name) s = fl_fonts; // use font 0 if still undefined
+  Fl_Xlib_Fontdesc* s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum;
+  if (!s->name) s = (Fl_Xlib_Fontdesc*)fl_fonts; // use font 0 if still undefined
   Fl_Font_Descriptor* f;
   for (f = s->first; f; f = f->next)
     if (f->size == size) return f;
@@ -571,7 +572,7 @@
   fl_open_display();
 
   name = put_font_size(s->name, size);
-  f = new Fl_Font_Descriptor(name);
+  f = new Fl_Xlib_Font_Descriptor(name);
   f->size = size;
   f->next = s->first;
   s->first = f;
@@ -597,7 +598,7 @@
   }
   if (fnum == Fl_Graphics_Driver::font() && size == Fl_Graphics_Driver::size()) return;
   Fl_Graphics_Driver::font(fnum, size);
-  Fl_Font_Descriptor* f = find(fnum, size);
+  Fl_Xlib_Font_Descriptor* f = (Fl_Xlib_Font_Descriptor*)find(fnum, size);
   if (f != this->font_descriptor()) {
     this->font_descriptor(f);
     fl_xfont = f->font->fonts[0];
@@ -606,12 +607,12 @@
 }
 
 int Fl_Xlib_Graphics_Driver::height_unscaled() {
-  if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
+  if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->ascent + ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent;
   else return -1;
 }
 
 int Fl_Xlib_Graphics_Driver::descent_unscaled() {
-  if (font_descriptor()) return font_descriptor()->font->descent;
+  if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent;
   else return -1;
 }
 
@@ -621,12 +622,12 @@
 }
 
 double Fl_Xlib_Graphics_Driver::width_unscaled(const char* c, int n) {
-  if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
+  if (font_descriptor()) return (double) XUtf8TextWidth(((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, c, n);
   else return -1;
 }
 
 double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
-  if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
+  if (font_descriptor()) return (double) XUtf8UcsWidth(((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, c);
   else return -1;
 }
 
@@ -634,11 +635,11 @@
   if (font_gc != gc_) {
     if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
-    XSetFont(fl_display, gc_, font_descriptor()->font->fid);
+    XSetFont(fl_display, gc_, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->fid);
   }
   int xx, yy, ww, hh;
   xx = yy = ww = hh = 0;
-  if (gc_) XUtf8_measure_extents(fl_display, fl_window, font_descriptor()->font, gc_, &xx, &yy, &ww, &hh, c, n);
+  if (gc_) XUtf8_measure_extents(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, &xx, &yy, &ww, &hh, c, n);
 
   W = ww; H = hh; dx = xx; dy = yy;
 // This is the safe but mostly wrong thing we used to do...
@@ -652,9 +653,9 @@
   if (font_gc != gc_) {
     if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
-    XSetFont(fl_display, gc_, font_descriptor()->font->fid);
+    XSetFont(fl_display, gc_, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->fid);
   }
-  if (gc_) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
+  if (gc_) XUtf8DrawString(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, x+offset_x_, y+offset_y_, c, n);
 }
 
 void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
@@ -673,7 +674,7 @@
     if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
   }
-  if (gc_) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
+  if (gc_) XUtf8DrawRtlString(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, x+offset_x_, y+offset_y_, c, n);
 }
 
 float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
@@ -680,7 +681,7 @@
   float ps_size = (float) s;
   // Non-Xft fonts can be smaller than required.
   // Set the PostScript font size to the display font height
-  char *name = desc->font->font_name_list[0];
+  char *name = ((Fl_Xlib_Font_Descriptor*)desc)->font->font_name_list[0];
   char *p = strstr(name, "--");
   if (p) {
     sscanf(p + 2, "%f", &ps_size);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(revision 12646)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(working copy)
@@ -695,13 +695,9 @@
   }
 } // end of fontopen
 
-Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) {
+Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) : Fl_Font_Descriptor(name, fsize) {
 //  encoding = fl_encoding_;
-  size = fsize;
   angle = fangle;
-#if HAVE_GL
-  listbase = 0;
-#endif // HAVE_GL
   font = fontopen(name, fsize, false, angle);
 }
 
@@ -998,7 +994,7 @@
   return 2;
 }
 
-Fl_Font_Descriptor::~Fl_Font_Descriptor() {
+Fl_Xlib_Font_Descriptor::~Fl_Xlib_Font_Descriptor() {
   if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
   //  XftFontClose(fl_display, font);
 }
@@ -1020,17 +1016,17 @@
     return;
   }
   Fl_Font_Descriptor* f = driver->font_descriptor();
-  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size_unscaled() && f && f->angle == angle)
+  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size_unscaled() && f && ((Fl_Xlib_Font_Descriptor*)f)->angle == angle)
     return;
   driver->Fl_Graphics_Driver::font(fnum, size);
   Fl_Fontdesc *font = fl_fonts + fnum;
   // search the fontsizes we have generated already
   for (f = font->first; f; f = f->next) {
-    if (f->size == size && f->angle == angle)// && !strcasecmp(f->encoding, fl_encoding_))
+    if (f->size == size && ((Fl_Xlib_Font_Descriptor*)f)->angle == angle)// && !strcasecmp(f->encoding, fl_encoding_))
       break;
   }
   if (!f) {
-    f = new Fl_Font_Descriptor(font->name, size, angle);
+    f = new Fl_Xlib_Font_Descriptor(font->name, size, angle);
     f->next = font->first;
     font->first = f;
   }
@@ -1215,7 +1211,7 @@
   pfd_ = pango_font_description_from_string(Fl::get_font_name(fnum));
   pango_font_description_set_absolute_size(pfd_, size*PANGO_SCALE); // 1.8
   if (!pctxt_) context();
-  Fl_Font_Descriptor *fd = font_descriptor();
+  Fl_Xlib_Font_Descriptor *fd = (Fl_Xlib_Font_Descriptor*)font_descriptor();
   if (!fd->height_) {
     PangoFont *pfont = pango_font_map_load_font(pfmap_, pctxt_, pfd_);
     PangoRectangle logical_rect;
@@ -1339,7 +1335,7 @@
 }
 
 int Fl_Xlib_Graphics_Driver::height_unscaled() {
-  if (font_descriptor())  return font_descriptor()->height_;
+  if (font_descriptor())  return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->height_;
   else return -1;
 }
 
@@ -1350,7 +1346,7 @@
 }
 
 int Fl_Xlib_Graphics_Driver::descent_unscaled() {
-  if (font_descriptor()) return font_descriptor()->descent_;
+  if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->descent_;
   else return -1;
 }
 
@@ -1433,13 +1429,9 @@
   return 1;
 }
 
-Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) {
+Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) : Fl_Font_Descriptor(name, fsize) {
   fl_open_display();
-  size = fsize;
   angle = fangle;
-#if HAVE_GL
-  listbase = 0;
-#endif // HAVE_GL
   height_ = 0;
   descent_ = 0;
 }
Index: src/gl_draw.cxx
===================================================================
--- src/gl_draw.cxx	(revision 12646)
+++ src/gl_draw.cxx	(working copy)
@@ -1,7 +1,7 @@
 //
 // "$Id$"
 //
-// OpenGL drawing support routines for the Fast Light Tool Kit (FLTK).
+// OpenGL text drawing support routines for the Fast Light Tool Kit (FLTK).
 //
 // Copyright 1998-2018 by Bill Spitzak and others.
 //
@@ -19,12 +19,23 @@
 // Functions from <FL/gl.h>
 // See also Fl_Gl_Window and gl_start.cxx
 
+/* Note about implementing GL text support for a new platform
+
+ 1) if the GL_EXT_texture_rectangle (a.k.a. GL_ARB_texture_rectangle) GL extension
+ is available, no platform-specific code is needed, besides support for fl_draw() for the platform.
+
+ 2) if the GL_EXT_texture_rectangle GL extension is not available,
+ a rudimentary support through GLUT is obtained without any platform-specific code.
+
+ 3) A more elaborate support can be obtained implementing
+ get_list(), gl_bitmap_font() and draw_string_legacy() for the platform's Fl_XXX_Gl_Window_Driver.
+ */
+
 #include "config_lib.h"
 #if defined(FL_PORTING)
 #  pragma message "FL_PORTING: implement OpenGL text rendering here"
-#endif
+#endif // defined(FL_PORTING)
 
-#include "flstring.h"
 #if HAVE_GL || defined(FL_DOXYGEN)
 
 #include <FL/Fl.H>
@@ -32,25 +43,13 @@
 #include <FL/gl_draw.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Gl_Window_Driver.H>
+#include <FL/Fl_Image_Surface.H>
+#include <FL/glu.h>  // for gluUnProject()
+#  include <FL/glut.H> // for glutStrokeString() and glutStrokeLength()
 
-#if defined(FL_CFG_GFX_QUARTZ)
-#include "drivers/Quartz/Fl_Font.H"
-#  define GENLISTSIZE 0
-
-#elif defined(FL_CFG_GFX_GDI)
-#include "drivers/GDI/Fl_Font.H"
-#define GENLISTSIZE 0x10000
-
-#elif defined(FL_CFG_GFX_XLIB)
-#include "drivers/Xlib/Fl_Font.H"
-#if USE_XFT
-#  define GENLISTSIZE 256
-#else
-#  define GENLISTSIZE 0x10000
-#endif // USE_XFT
-
+#ifndef GL_TEXTURE_RECTANGLE_ARB
+#  define GL_TEXTURE_RECTANGLE_ARB 0x84F5
 #endif
-#include <FL/fl_utf8.h>
 
 
 /** Returns the current font's height */
@@ -65,23 +64,37 @@
 double gl_width(uchar c) {return fl_width(c);}
 
 static Fl_Font_Descriptor *gl_fontsize;
+static int has_texture_rectangle = 0; // true means GL_EXT_texture_rectangle is available
 
+extern float gl_start_scale; // in gl_start.cxx
 
 /**
-  Sets the current OpenGL font to the same font as calling fl_font()
+  Sets the current OpenGL font to the same font as calling fl_font().
+ \see Fl::draw_GL_text_with_textures(int val)
   */
 void  gl_font(int fontid, int size) {
+  static bool once = true;
+  if (once) {
+    once = false;
+    if (Fl::draw_GL_text_with_textures()) {
+      // For the font texture pile to work, we need a texture rectangle extension, so check for
+      // one here. First we check for GL_EXT_texture_rectangle and if that fails we try
+      // for GL_ARB_texture_rectangle instead. If that also fails, we fall back to the
+      // legacy methods used by fltk-1.3 and earlier.
+      has_texture_rectangle = (strstr((const char*)glGetString(GL_EXTENSIONS), "GL_EXT_texture_rectangle") != NULL);
+      if (!has_texture_rectangle) has_texture_rectangle =
+        (strstr((const char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_rectangle") != NULL);
+      Fl::draw_GL_text_with_textures(has_texture_rectangle);
+    }
+  }
   fl_font(fontid, size);
   Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
-  Fl_Gl_Window_Driver::global()->gl_bitmap_font(fl_fontsize);
+  if (!has_texture_rectangle) Fl_Gl_Window_Driver::global()->gl_bitmap_font(fl_fontsize);
   gl_fontsize = fl_fontsize;
 }
 
-#if defined(FL_CFG_GFX_QUARTZ) || defined(FL_CFG_GFX_GDI) || defined(FL_CFG_GFX_XLIB)
-
 void gl_remove_displaylist_fonts()
 {
-# if HAVE_GL
   // clear variables used mostly in fl_font
   fl_graphics_driver->font(0, 0);
 
@@ -88,20 +101,18 @@
   for (int j = 0 ; j < FL_FREE_FONT ; ++j)
   {
     Fl_Font_Descriptor* past = 0;
-    Fl_Fontdesc* s    = fl_fonts + j ;
-    Fl_Font_Descriptor* f    = s->first;
+    Fl_Font_Descriptor** s_first = Fl_Gl_Window_Driver::global()->fontnum_to_fontdescriptor(j);
+    Fl_Font_Descriptor* f = *s_first;
     while (f != 0) {
       if(f->listbase) {
-        if(f == s->first) {
-          s->first = f->next;
+        if(f == *s_first) {
+          *s_first = f->next;
         }
         else {
           past->next = f->next;
         }
-
         // It would be nice if this next line was in a destructor somewhere
-        glDeleteLists(f->listbase, GENLISTSIZE);
-
+        glDeleteLists(f->listbase, Fl_Gl_Window_Driver::global()->genlistsize());
         Fl_Font_Descriptor* tmp = f;
         f = f->next;
         delete tmp;
@@ -112,44 +123,22 @@
       }
     }
   }
-#endif // HAVE_GL
 }
-#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)
+  Draws an array of n characters of the string in the current font at the current position.
+ \see  gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int n) {
-  Fl_Gl_Window_Driver::global()->draw_string(str, n);
+  if (has_texture_rectangle)  Fl_Gl_Window_Driver::draw_string_with_texture(str, n);
+  else Fl_Gl_Window_Driver::global()->draw_string_legacy(str, n);
 }
 
-void Fl_Gl_Window_Driver::draw_string(const char* str, int n) {
-  static unsigned short *buf = NULL;
-  static int l = 0;
-  int wn = fl_utf8toUtf16(str, n, (unsigned short*)buf, l);
-  if(wn >= l) {
-    buf = (unsigned short*) realloc(buf, sizeof(unsigned short) * (wn + 1));
-    l = wn + 1;
-    wn = fl_utf8toUtf16(str, n, (unsigned short*)buf, l);
-  }
-  n = wn;
-  
-  int i;
-  for (i = 0; i < n; i++) {
-    unsigned int r;
-    r = (str[i] & 0xFC00) >> 10;
-    //if (!gl_fontsize->glok[r]) get_list(r);
-    this->get_list(gl_fontsize, r);
-  }
-  glCallLists(n, GL_UNSIGNED_SHORT, buf);
-}
 
 /**
-  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)
+  Draws n characters of the string in the current font at the given position
+ \see  gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int n, int x, int y) {
   glRasterPos2i(x, y);
@@ -157,8 +146,8 @@
 }
 
 /**
-  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)
+  Draws n characters of the string in the current font at the given position
+ \see  gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int n, float x, float y) {
   glRasterPos2f(x, y);
@@ -167,7 +156,7 @@
 
 /**
   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)
+ \see  gl_texture_pile_height(int)
   */
 void gl_draw(const char* str) {
   gl_draw(str, strlen(str));
@@ -174,8 +163,8 @@
 }
 
 /**
-  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)
+  Draws a nul-terminated string in the current font at the given position
+ \see  gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, int x, int y) {
   gl_draw(str, strlen(str), x, y);
@@ -182,8 +171,8 @@
 }
 
 /**
-  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)
+  Draws a nul-terminated string in the current font at the given position
+ \see  gl_texture_pile_height(int)
   */
 void gl_draw(const char* str, float x, float y) {
   gl_draw(str, strlen(str), x, y);
@@ -229,7 +218,14 @@
   glEnd();
 }
 
+void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) {
+  if (!ld) ld = w*d;
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d);
+  glRasterPos2i(x,y);
+  glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
+}
 
+
 /**
   Sets the curent OpenGL color to an FLTK color.
 
@@ -244,155 +240,29 @@
 }
 
 
-#if defined(FL_CFG_GFX_XLIB)
-#include <FL/platform.H>
-#include <GL/glx.h>
+#if ! defined(FL_DOXYGEN) // do not want too much of the gl_texture_fifo internals in the documentation
 
+/* Implement the gl_texture_fifo mechanism:
+ Strings to be drawn are memorized in a fifo pile (which max size can
+ be increased calling gl_texture_pile_height(int)).
+ Each pile element contains the string, the font, the GUI scale, and a
+ image of the string in the form of a GL texture.
+ Strings are drawn in 2 steps:
+    1) compute the texture for that string if it was not computed before;
+    2) draw the texture using the current GL color.
+*/
 
-void Fl_X11_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {
-  if (!fl_fontsize->listbase) {
-#if !USE_XFT
-    fl_fontsize->listbase = glGenLists(GENLISTSIZE);
-#else // Fltk-1.1.8 style GL font selection
-    // FIXME:  warning Ideally, for XFT, we really need a glXUseXftFont implementation here...
-    // FIXME:  warning GL font selection is basically wrong here
-    /* OksiD had a fairly sophisticated scheme for storing multiple X fonts in a XUtf8FontStruct,
-     * then sorting through them at draw time (for normal X rendering) to find which one can
-     * render the current glyph... But for now, just use the first font in the list for GL...
-     */
-     XFontStruct *font = fl_xfont.value();
-     int base = font->min_char_or_byte2;
-     int count = font->max_char_or_byte2-base+1;
-     fl_fontsize->listbase = glGenLists(GENLISTSIZE);
-     glXUseXFont(font->fid, base, count, fl_fontsize->listbase+base);
-#endif // !USE_XFT
-     }
-     glListBase(fl_fontsize->listbase);
-}
+static float gl_scale = 1; // scaling factor between FLTK and GL drawing units: GL = FLTK * gl_scale
 
-
-void Fl_X11_Gl_Window_Driver::get_list(Fl_Font_Descriptor *gl_fd, int r) {
-  if (gl_fd->glok[r]) return;
-  gl_fd->glok[r] = 1;
-# if USE_XFT
-  // FIXME
-# else
-  unsigned int ii = r * 0x400;
-  for (int i = 0; i < 0x400; i++) {
-    XFontStruct *font = NULL;
-    unsigned short id;
-    fl_XGetUtf8FontAndGlyph(gl_fd->font, ii, &font, &id);
-    if (font) glXUseXFont(font->fid, id, 1, gl_fd->listbase+ii);
-    ii++;
-  }
-# endif
-}
-
-#if HAVE_GL_OVERLAY
-extern uchar fl_overlay;
-int Fl_X11_Gl_Window_Driver::overlay_color(Fl_Color i) {
-  if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return 1;}
-  return 0;
-}
-#endif // HAVE_GL_OVERLAY
-#endif // FL_CFG_GFX_XLIB
-
-
-#if defined(FL_CFG_GFX_GDI)
-
-void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {
-  if (!fl_fontsize->listbase) {
-    fl_fontsize->listbase = glGenLists(GENLISTSIZE);
-     /* old, unused WIN32 code
-     int base = fl_fontsize->metr.tmFirstChar;
-     int count = fl_fontsize->metr.tmLastChar-base+1;
-     HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), fl_fontsize->fid);
-     fl_fontsize->listbase = glGenLists(256);
-     wglUseFontBitmaps((HDC)fl_graphics_driver->gc(), base, count, fl_fontsize->listbase+base);
-     SelectObject((HDC)fl_graphics_driver->gc(), oldFid);
-     */
-  }
-  glListBase(fl_fontsize->listbase);
-}
-
-
-void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *gl_fd, int r) {
-  if (gl_fd->glok[r]) return;
-  gl_fd->glok[r] = 1;
-  unsigned int ii = r * 0x400;
-  HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid);
-  wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, ii + 0x03ff, gl_fd->listbase+ii);
-  SelectObject((HDC)fl_graphics_driver->gc(), oldFid);
-}
-
-#if HAVE_GL_OVERLAY
-extern uchar fl_overlay;
-extern int fl_overlay_depth;
-int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) {
-  if (fl_overlay && fl_overlay_depth) {
-    if (fl_overlay_depth < 8) {
-      // only black & white produce the expected colors.  This could
-      // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx
-      int size = 1<<fl_overlay_depth;
-      if (!i) glIndexi(size-2);
-      else if (i >= size-2) glIndexi(size-1);
-      else glIndexi(i);
-    } else {
-      glIndexi(i ? i : FL_GRAY_RAMP);
-    }
-    return 1;
-  }
-  return 0;
-}
-#endif // HAVE_GL_OVERLAY
-#endif // FL_CFG_GFX_GDI
-
-
-void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) {
-  if (!ld) ld = w*d;
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d);
-  glRasterPos2i(x,y);
-  glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
-}
-
-
-#if defined(FL_CFG_GFX_QUARTZ) || defined(FL_DOXYGEN)
-
-#if ! defined(FL_DOXYGEN)
-
-#include <FL/platform.H>
-#if !defined(kCGBitmapByteOrder32Host) // doc says available 10.4 but some 10.4 don't have it
-#  define kCGBitmapByteOrder32Host 0
-#endif
-
-#if  MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
-#  include <OpenGL/glext.h>
-#  define GL_TEXTURE_RECTANGLE_ARB GL_TEXTURE_RECTANGLE_EXT
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED
-
-/* Text drawing to an OpenGL scene under Mac OS X is implemented using textures, as recommended by Apple.
- This allows to use any font at any size, and any Unicode character.
- Some old Apple hardware doesn't implement the required GL_EXT_texture_rectangle extension.
- For these, glutStrokeString() is used to draw text. In that case, it's possible to vary text size,
- but not text font, and only ASCII characters can be drawn.
- */
-
-static float gl_scale = 1; // set to 2 for high resolution Fl_Gl_Window
-static int has_texture_rectangle = 0; // true means GL_EXT_texture_rectangle is available
-
-#include <FL/glu.h>  // for gluUnProject() and gluCheckExtension()
-#include <FL/glut.H> // for glutStrokeString() and glutStrokeLength()
-
 // manages a fifo pile of pre-computed string textures
 class gl_texture_fifo {
-  friend class Fl_Cocoa_Gl_Window_Driver;
+  friend class Fl_Gl_Window_Driver;
 private:
   typedef struct { // information for a pre-computed texture
     GLuint texName; // its name
     char *utf8; //its text
     Fl_Font_Descriptor *fdesc; // its font
-    float ratio; // used without rectangle texture
-    int scale; // 1 or 2 for low/high resolution
+    float scale; // scaling factor of the GUI
   } data;
   data *fifo; // array of pile elements
   int size_; // pile height
@@ -421,10 +291,34 @@
   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);
 }
 
+// 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) && (fifo[rank].scale == gl_scale) ) {
+        return rank;
+    }
+  }
+  return -1; // means no texture exists yet for that string
+}
+
+static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance
+
+void gl_texture_reset()
+{
+  if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height());
+}
+
+
+// Cross-platform implementation of the texture mechanism for text rendering
+// using textures with the alpha channel only.
+
 // displays a pre-computed texture on the GL scene
 void gl_texture_fifo::display_texture(int rank)
 {
@@ -440,46 +334,39 @@
   float winw = gl_scale * Fl_Window::current()->w();
   float winh = gl_scale * Fl_Window::current()->h();
   // GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable
-  glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); 
+  glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
   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
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDisable(GL_LIGHTING);
   GLfloat pos[4];
   glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+  if (gl_start_scale != 1) { // using gl_start() / gl_finish()
+    pos[0] /= gl_start_scale;
+    pos[1] /= gl_start_scale;
+  }
+
   float R = 2;
-  if (!has_texture_rectangle) {
-    R *= fifo[rank].ratio;
-  }
   glScalef (R/winw, R/winh, 1.0f);
   glTranslatef (-winw/R, -winh/R, 0.0f);
-  GLint width;
-  if (has_texture_rectangle) {
-    glEnable (GL_TEXTURE_RECTANGLE_ARB);
-    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName);
-    GLint height;
-    glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width);
-    glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_HEIGHT, &height);
-    CGRect bounds = CGRectMake (pos[0], pos[1] - gl_scale*fl_descent(), width, height);
-    //write the texture on screen
-    glBegin (GL_QUADS);
-    glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
-    glVertex2f (bounds.origin.x, bounds.origin.y);
-    
-    glTexCoord2f (0.0f, height); // draw upper left in world coordinates
-    glVertex2f (bounds.origin.x, bounds.origin.y + bounds.size.height);
-    
-    glTexCoord2f (width, height); // draw upper right in world coordinates
-    glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height);
-    
-    glTexCoord2f (width, 0.0f); // draw lower right in world coordinates
-    glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y);
-    glEnd ();
-  } else {
-    glTranslatef(pos[0]*2/R, pos[1]*2/R, 0.0);
-    glutStrokeString(GLUT_STROKE_ROMAN, (uchar*)fifo[rank].utf8);
-    width = fl_width(fifo[rank].utf8);
-  }
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName);
+  GLint width, height;
+  glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width);
+  glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_HEIGHT, &height);
+  //write the texture on screen
+  glBegin (GL_QUADS);
+  float ox = pos[0];
+  float oy = pos[1] + height - gl_scale * fl_descent();
+  glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
+  glVertex2f (ox, oy);
+  glTexCoord2f (0.0f, height); // draw upper left in world coordinates
+  glVertex2f (ox, oy - height);
+  glTexCoord2f (width, height); // draw upper right in world coordinates
+  glVertex2f (ox + width, oy - height);
+  glTexCoord2f (width, 0.0f); // draw lower right in world coordinates
+  glVertex2f (ox + width, oy);
+  glEnd ();
   glPopAttrib();
   
   // reset original matrices
@@ -498,14 +385,18 @@
   GLint viewport[4];
   glGetIntegerv (GL_VIEWPORT, viewport);
   gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ);
+
+  if (gl_start_scale != 1) { // using gl_start() / gl_finish()
+    objX *= gl_start_scale;
+    objY *= gl_start_scale;
+  }
   glRasterPos2d(objX, objY);
-}
+} // display_texture
 
+
 // pre-computes a string texture
 int gl_texture_fifo::compute_texture(const char* str, int n)
 {
-  Fl_Graphics_Driver *prev_driver = fl_graphics_driver;
-  fl_graphics_driver = Fl_Display_Device::display_device()->driver();
   current = (current + 1) % size_;
   if (current > last) last = current;
   if ( fifo[current].utf8 ) free(fifo[current].utf8);
@@ -515,114 +406,389 @@
   fl_graphics_driver->font_descriptor(gl_fontsize);
   int w, h;
   w = fl_width(fifo[current].utf8, n) * gl_scale;
+  // Hack - make w be aligned
+  w = (w + 3) & 0xFFFFFFC;
   h = fl_height() * gl_scale;
+
   fifo[current].scale = gl_scale;
   fifo[current].fdesc = gl_fontsize;
-  if (has_texture_rectangle) {
-    //write str to a bitmap just big enough
-    CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
-    void *base = NULL;
-    if (fl_mac_os_version < 100600) base = calloc(4*w, h);
-    void* save_gc = fl_graphics_driver->gc();
-    CGContextRef gc = CGBitmapContextCreate(base, w, h, 8, w*4, lut,
-                                  (CGBitmapInfo)(kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
-    fl_graphics_driver->gc(gc);
-    CGColorSpaceRelease(lut);
-    GLfloat colors[4];
-    glGetFloatv(GL_CURRENT_COLOR, colors);
-    fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255));
-    CGContextTranslateCTM(gc, 0, h - gl_scale*fl_descent());
-    CGContextScaleCTM(gc, gl_scale, gl_scale);
-    fl_draw(str, n, 0, 0);
-    //put this bitmap in a texture
-    glPushAttrib(GL_TEXTURE_BIT);
-    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName);
-    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
-    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, w, h, 0,  GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, CGBitmapContextGetData(gc));
-    glPopAttrib();
-    CGContextRelease(gc);
-    fl_graphics_driver->gc(save_gc);
-    if (base) free(base);
-  } else {
-    fifo[current].ratio = float(w)/glutStrokeLength(GLUT_STROKE_ROMAN, (uchar*)fifo[current].utf8);
-  }
-  fl_graphics_driver = prev_driver;
+  char *txt_buf = Fl_Gl_Window_Driver::global()->alpha_mask_for_string(str, n, w, h);
+
+  // put the bitmap in an alpha-component-only texture
+  glPushAttrib(GL_TEXTURE_BIT);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName);
+  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  //glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
+  // GL_ALPHA8 is defined in GL/gl.h of X11 and of MinGW32 and of MinGW64 and of OpenGL.framework for MacOS
+  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA8, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, txt_buf);
+  /* For the record: texture construction if an alpha-only-texture is not possible
+   glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, rgba_buf);
+   and also, replace GL_SRC_ALPHA by GL_ONE in glBlendFunc() call of display_texture()
+   */
+  delete[] txt_buf; // free the buffer now we have copied it into the Gl texture
+  glPopAttrib();
   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)
+#endif  // ! defined(FL_DOXYGEN)
+
+/**
+ Returns the current maximum height of the pile of pre-computed string textures
+
+ The default value is 100
+ */
+int gl_texture_pile_height(void)
 {
-  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 && fifo[rank].scale == gl_scale) return rank;
-  }
-  return -1;
+  if (! gl_fifo) gl_fifo = new gl_texture_fifo();
+  return gl_fifo->size();
 }
 
-static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance
+/**
+ Changes the maximum height of the pile of pre-computed string textures
 
-// draws a utf8 string using pre-computed texture if available
-void Fl_Cocoa_Gl_Window_Driver::draw_string(const char* str, int n)
+ 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 Maximum 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);
+}
+
+
+void Fl_Gl_Window_Driver::draw_string_legacy(const char* str, int n)
+{
+  draw_string_legacy_glut(str,  n);
+}
+
+
+/** draws a utf8 string using an OpenGL texture */
+void Fl_Gl_Window_Driver::draw_string_with_texture(const char* str, int n)
+{
   Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window();
   gl_scale = (gwin ? gwin->pixels_per_unit() : 1);
-  
-  //fprintf(stderr,"gl_scale=%d\n",gl_scale);
-  if (! gl_fifo) gl_fifo = new gl_texture_fifo();
+  if (!gl_fifo) gl_fifo = new gl_texture_fifo();
   if (!gl_fifo->textures_generated) {
-    has_texture_rectangle = gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", glGetString(GL_EXTENSIONS));
     if (has_texture_rectangle) 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);
+  int index = gl_fifo->already_known(str, n);
+  if (index == -1) {
+    index = gl_fifo->compute_texture(str, n);
   }
-  gl_fifo->display_texture(rank);
+  gl_fifo->display_texture(index);
 }
 
-void gl_texture_reset()
+
+char *Fl_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h)
 {
-  if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height());
+  // write str to a bitmap that is just big enough
+  // create an Fl_Image_Surface object
+  Fl_Image_Surface *image_surface = new Fl_Image_Surface(w, h);
+  Fl_Font fnt = fl_font(); // get the current font
+  // direct all further graphics requests to the image
+  Fl_Surface_Device::push_current(image_surface);
+  // fill the background with black, which we will interpret as transparent
+  fl_color(0,0,0);
+  fl_rectf(0, 0, w, h);
+  // set up the text colour as white, which we will interpret as opaque
+  fl_color(255,255,255);
+  // Fix the font scaling
+  fl_font (fnt, gl_fontsize->size); // resize "fltk" font to current GL view scaling
+  int desc = fl_descent();
+  // Render the text to the buffer
+  fl_draw(str, n, 0, h - desc);
+  // get the resulting image
+  Fl_RGB_Image* image = image_surface->image();
+  // direct graphics requests back to previous state
+  Fl_Surface_Device::pop_current();
+  delete image_surface;
+  // This gives us an RGB rendering of the text. We build an alpha channel from that.
+  char *txt_buf = new char [w * h];
+  for (int idx = 0; idx < w * h; ++idx)
+  { // Fake up the alpha component using the green component's value
+    txt_buf[idx] = image->array[idx * 3 + 1];
+  }
+  delete image;
+  return txt_buf;
 }
 
-#endif  //! defined(FL_DOXYGEN)
 
-/** \addtogroup group_macosx
- @{ */
+// platform-independent, no-texture GL text drawing procedure
+// when Fl_XXX_Gl_Window_Driver::get_list() and gl_bitmap_font() are implemented
+void Fl_Gl_Window_Driver::draw_string_legacy_get_list(const char* str, int n) {
+  static unsigned short *buf = NULL;
+  static unsigned l = 0;
+  unsigned wn = fl_utf8toUtf16(str, n, buf, l);
+  if (wn >= l) {
+    buf = (unsigned short*) realloc(buf, sizeof(unsigned short) * (wn + 1));
+    l = wn + 1;
+    wn = fl_utf8toUtf16(str, n, buf, l);
+  }
+  int size = 0;
+  if (gl_start_scale != 1) { // using gl_start() / gl_finish()
+    size = fl_graphics_driver->font_descriptor()->size;
+    gl_font(fl_font(), size * gl_start_scale);
+  }
+  for (unsigned i = 0; i < wn; i++) {
+    unsigned int r;
+    r = (buf[i] & 0xFC00) >> 10;
+    get_list(gl_fontsize, r);
+  }
+  glCallLists(wn, GL_UNSIGNED_SHORT, buf);
+  if (gl_start_scale != 1) { // using gl_start() / gl_finish()
+    gl_font(fl_font(), size);
+  }
+}
 
-/**
- \brief Returns the current height of the pile of pre-computed string textures
- *
- The default value is 100
+/* Platform-independent, no-texture, GL text drawing procedure when there's no OS support whatsoever:
+ glutStrokeString() is used to draw text. It's possible to vary text size, but not text font,
+ and only ASCII characters can be drawn.
  */
-int gl_texture_pile_height(void)
+void Fl_Gl_Window_Driver::draw_string_legacy_glut(const char* str, int n)
 {
-  if (! gl_fifo) gl_fifo = new gl_texture_fifo();
-  return gl_fifo->size();
+  uchar *str_nul = new uchar[n + 1];
+  int m = 0;
+  for (int i = 0; i < n; i++) {
+    if ((uchar)str[i] < 128) str_nul[m++] = str[i];
+  }
+  str_nul[m] = 0;
+  n = m;
+  Fl_Surface_Device::push_current(Fl_Display_Device::display_device());
+  fl_graphics_driver->font_descriptor(gl_fontsize);
+  Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window();
+  gl_scale = (gwin ? gwin->pixels_per_unit() : 1);
+  float ratio = fl_width((char*)str_nul, n) * gl_scale/glutStrokeLength(GLUT_STROKE_ROMAN, str_nul);
+  Fl_Surface_Device::pop_current();
+
+  //setup matrices
+  GLint matrixMode;
+  glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
+  glMatrixMode (GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity ();
+  glMatrixMode (GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity ();
+  float winw = gl_scale * Fl_Window::current()->w();
+  float winh = gl_scale * Fl_Window::current()->h();
+
+  GLfloat pos[4];
+  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+  if (gl_start_scale != 1) { // using gl_start() / gl_finish()
+    pos[0] /= gl_start_scale;
+    pos[1] /= gl_start_scale;
+  }
+  float R = 2 * ratio;
+  glScalef (R/winw, R/winh, 1.0f);
+  glTranslatef (-winw/R, -winh/R, 0.0f);
+  glTranslatef(pos[0]*2/R, pos[1]*2/R, 0.0);
+  glutStrokeString(GLUT_STROKE_ROMAN, str_nul);
+  float width = fl_width((char*)str_nul);
+  delete[] str_nul;
+  glPopAttrib();
+  // reset original matrices
+  glPopMatrix(); // GL_MODELVIEW
+  glMatrixMode (GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode (matrixMode);
+  //set the raster position to end of string
+  pos[0] += width;
+  GLdouble modelmat[16];
+  glGetDoublev (GL_MODELVIEW_MATRIX, modelmat);
+  GLdouble projmat[16];
+  glGetDoublev (GL_PROJECTION_MATRIX, projmat);
+  GLdouble objX, objY, objZ;
+  GLint viewport[4];
+  glGetIntegerv (GL_VIEWPORT, viewport);
+  gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ);
+  if (gl_start_scale != 1) { // using gl_start() / gl_finish()
+    objX *= gl_start_scale;
+    objY *= gl_start_scale;
+  }
+  glRasterPos2d(objX, objY);
 }
 
-/**
- \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
+
+#if  defined(FL_CFG_GFX_XLIB)
+#  include "drivers/Xlib/Fl_Font.H"
+#  include <FL/x.H>
+#  include <GL/glx.h>
+
+void Fl_X11_Gl_Window_Driver::draw_string_legacy(const char* str, int n) {
+  draw_string_legacy_get_list(str, n);
+}
+
+int Fl_X11_Gl_Window_Driver::genlistsize() {
+#if USE_XFT
+  return 256;
+#else
+  return 0x10000;
+#endif
+}
+
+void Fl_X11_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {
+  /* This method should ONLY be triggered if our GL font texture pile mechanism
+   * is not working on this platform. This code might not reliably render glyphs
+   * from higher codepoints. */
+  if (!fl_fontsize->listbase) {
+#if USE_XFT
+    /* Ideally, for XFT, we need a glXUseXftFont implementation here... But we
+     * do not have such a thing. Instead, we try to find a legacy Xlib font that
+     * matches the current XFT font and use that.
+     * Ideally, we never come here - we hope the texture pile implementation
+     * will work correctly so that XFT can render the face directly without the
+     * need for this workaround. */
+    XFontStruct *font = fl_xfont.value();
+    int base = font->min_char_or_byte2;
+    int count = font->max_char_or_byte2 - base + 1;
+    fl_fontsize->listbase = glGenLists(genlistsize());
+    glXUseXFont(font->fid, base, count, fl_fontsize->listbase+base);
+#else
+    /* Not using XFT to render text - the legacy Xlib fonts can usually be rendered
+     * directly by using glXUseXFont mechanisms. */
+    fl_fontsize->listbase = glGenLists(genlistsize());
+#endif // !USE_XFT
+  }
+  glListBase(fl_fontsize->listbase);
+}
+
+
+void Fl_X11_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) {
+  Fl_Xlib_Font_Descriptor *gl_fd = (Fl_Xlib_Font_Descriptor*)fd;
+  if (gl_fd->glok[r]) return;
+  gl_fd->glok[r] = 1;
+# if USE_XFT
+  /* We hope not to come here: We hope that any system using XFT will also
+   * have sufficient GL capability to support our font texture pile mechansim,
+   * allowing XFT to render the face directly. */
+  // Face already set by gl_bitmap_font in this case.
+# else
+  unsigned int ii = r * 0x400;
+  for (int i = 0; i < 0x400; i++) {
+    XFontStruct *font = NULL;
+    unsigned short id;
+    fl_XGetUtf8FontAndGlyph(gl_fd->font, ii, &font, &id);
+    if (font) glXUseXFont(font->fid, id, 1, gl_fd->listbase+ii);
+    ii++;
+  }
+# endif
+}
+
+#if !USE_XFT
+Fl_Font_Descriptor** Fl_X11_Gl_Window_Driver::fontnum_to_fontdescriptor(int fnum) {
+  Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum;
+  return &(s->first);
+}
+#endif
+
+#if HAVE_GL_OVERLAY
+extern uchar fl_overlay;
+int Fl_X11_Gl_Window_Driver::overlay_color(Fl_Color i) {
+  if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return 1;}
+  return 0;
+}
+#endif // HAVE_GL_OVERLAY
+
+#endif // FL_CFG_GFX_XLIB
+
+
+#if defined(FL_CFG_GFX_GDI)
+#  include "drivers/GDI/Fl_Font.H"
+
+void Fl_WinAPI_Gl_Window_Driver::draw_string_legacy(const char* str, int n) {
+  draw_string_legacy_get_list(str, n);
+}
+
+int Fl_WinAPI_Gl_Window_Driver::genlistsize() {
+  return 0x10000;
+}
+
+void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {
+  if (!fl_fontsize->listbase) {
+    fl_fontsize->listbase = glGenLists(genlistsize());
+  }
+  glListBase(fl_fontsize->listbase);
+}
+
+void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) {
+  Fl_GDI_Font_Descriptor* gl_fd = (Fl_GDI_Font_Descriptor*)fd;
+  if (gl_fd->glok[r]) return;
+  gl_fd->glok[r] = 1;
+  unsigned int ii = r * 0x400;
+  HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid);
+  wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, 0x400, gl_fd->listbase+ii);
+  SelectObject((HDC)fl_graphics_driver->gc(), oldFid);
+}
+
+#if HAVE_GL_OVERLAY
+extern uchar fl_overlay;
+extern int fl_overlay_depth;
+int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) {
+  if (fl_overlay && fl_overlay_depth) {
+    if (fl_overlay_depth < 8) {
+      // only black & white produce the expected colors.  This could
+      // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx
+      int size = 1<<fl_overlay_depth;
+      if (!i) glIndexi(size-2);
+      else if (i >= size-2) glIndexi(size-1);
+      else glIndexi(i);
+    } else {
+      glIndexi(i ? i : FL_GRAY_RAMP);
+    }
+    return 1;
+  }
+  return 0;
+}
+#endif // HAVE_GL_OVERLAY
+#endif // FL_CFG_GFX_GDI
+
+
+#if defined(FL_CFG_GFX_QUARTZ)
+#  include "drivers/Quartz/Fl_Font.H"
+
+#  if !defined(kCGBitmapByteOrder32Host) // doc says available 10.4 but some 10.4 don't have it
+#   define kCGBitmapByteOrder32Host 0
+#  endif // !defined(kCGBitmapByteOrder32Host)
+
+/* Some old Apple hardware doesn't implement the GL_EXT_texture_rectangle extension.
+ For it, draw_string_legacy_glut() is used to draw text.
  */
-void gl_texture_pile_height(int max)
+
+char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h)
 {
-  if (gl_fifo) delete gl_fifo;
-  gl_fifo = new gl_texture_fifo(max);
+  // write str to a bitmap just big enough
+  CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+  void *base = NULL;
+  if (fl_mac_os_version < 100600) base = calloc(4*w, h);
+  void* save_gc = fl_graphics_driver->gc();
+  CGContextRef gc = CGBitmapContextCreate(base, w, h, 8, w*4, lut,
+                                          (CGBitmapInfo)(kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+  CGColorSpaceRelease(lut);
+  fl_graphics_driver->gc(gc);
+  fl_color(FL_WHITE);
+  CGContextScaleCTM(gc, gl_scale, -gl_scale);
+  CGContextTranslateCTM(gc, 0,  -fl_descent());
+  fl_draw(str, n, 0, 0);
+  // get the alpha channel only of the bitmap
+  char *txt_buf = new char[w*h], *r = txt_buf, *q;
+  q = (char*)CGBitmapContextGetData(gc);
+  for (int i = 0; i < h; i++) {
+    for (int j = 0; j < w; j++) {
+      *r++ = *(q+3);
+      q += 4;
+    }
+  }
+  CGContextRelease(gc);
+  fl_graphics_driver->gc(save_gc);
+  if (base) free(base);
+  return txt_buf;
 }
 
-/** @} */
-
 #endif // FL_CFG_GFX_QUARTZ
 
-#endif // HAVE_GL
+#endif // HAVE_GL || defined(FL_DOXYGEN)
 
 //
 // End of "$Id$".
Index: src/gl_start.cxx
===================================================================
--- src/gl_start.cxx	(revision 12646)
+++ src/gl_start.cxx	(working copy)
@@ -42,11 +42,13 @@
 static GLContext context;
 static int clip_state_number=-1;
 static int pw, ph;
+float gl_start_scale = 1;
 
 static Fl_Gl_Choice* gl_choice;
 
 /** Creates an OpenGL context */
 void gl_start() {
+  gl_start_scale = Fl_Display_Device::display_device()->driver()->scale();
   if (!context) {
     if (!gl_choice) Fl::gl_visual(0);
     context = Fl_Gl_Window_Driver::global()->create_gl_context(Fl_Window::current(), gl_choice);
@@ -53,12 +55,12 @@
   }
   Fl_Gl_Window_Driver::global()->set_gl_context(Fl_Window::current(), context);
   Fl_Gl_Window_Driver::global()->gl_start();
-  if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
-    pw = Fl_Window::current()->w();
-    ph = Fl_Window::current()->h();
+  if (pw != int(Fl_Window::current()->w() * gl_start_scale) || ph != int(Fl_Window::current()->h() * gl_start_scale)) {
+    pw = int(Fl_Window::current()->w() * gl_start_scale);
+    ph = int(Fl_Window::current()->h() * gl_start_scale);
     glLoadIdentity();
     glViewport(0, 0, pw, ph);
-    glOrtho(0, pw, 0, ph, -1, 1);
+    glOrtho(0, Fl_Window::current()->w(), 0, Fl_Window::current()->h(), -1, 1);
     glDrawBuffer(GL_FRONT);
   }
   if (clip_state_number != fl_graphics_driver->fl_clip_state_number) {
@@ -67,12 +69,13 @@
     if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(),
 		    x, y, w, h)) {
       fl_clip_region(Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h));
-      glScissor(x, Fl_Window::current()->h()-(y+h), w, h);
+      glScissor(x*gl_start_scale, (Fl_Window::current()->h()-(y+h))*gl_start_scale, w*gl_start_scale, h*gl_start_scale);
       glEnable(GL_SCISSOR_TEST);
     } else {
       glDisable(GL_SCISSOR_TEST);
     }
   }
+  Fl_Display_Device::display_device()->driver()->scale(1);
 }
 
 /** Releases an OpenGL context */
@@ -79,6 +82,8 @@
 void gl_finish() {
   glFlush();
   Fl_Gl_Window_Driver::global()->waitGL();
+  Fl_Display_Device::display_device()->driver()->scale(gl_start_scale);
+  gl_start_scale = 1;
 }
 
 void Fl_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) {
Index: test/cube.cxx
===================================================================
--- test/cube.cxx	(revision 12646)
+++ test/cube.cxx	(working copy)
@@ -5,7 +5,7 @@
 //
 // Modified to have 2 cubes to test multiple OpenGL contexts
 //
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -110,9 +110,14 @@
   drawcube(wire);
   glPopMatrix();
   gl_color(FL_GRAY);
+//  gl_color(FL_RED);
+//  gl_color(FL_GREEN);
+//  gl_color(FL_BLUE);
+//  gl_color(FL_BLACK);
+//  gl_color(FL_WHITE);
   glDisable(GL_DEPTH_TEST);
   gl_font(FL_HELVETICA_BOLD, 16 );
-  gl_draw(wire ? "Cube: wire" : "Cube: flat", -4.5f, -4.5f );
+  gl_draw(wire ? "Cube: wire" : "Cube: çè§φνйцу€新東株式会社様", -4.5f, -4.5f );
   glEnable(GL_DEPTH_TEST);
 
   // if an OpenGL graphics driver is installed, give it a chance
@@ -179,6 +184,7 @@
 
 int main(int argc, char **argv) {
   Fl::use_high_res_GL(1);
+  //Fl::draw_GL_text_with_textures(0);
   makeform(argv[0]);
   // added to demo printing
   form->begin();
Index: test/fractals.cxx
===================================================================
--- test/fractals.cxx	(revision 12646)
+++ test/fractals.cxx	(working copy)
@@ -7,7 +7,7 @@
 // demonstrate how to add FLTK controls to a GLUT program.   The GLUT
 // code is unchanged except for the end (search for FLTK to find changes).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2018 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -34,10 +34,10 @@
  *
  * Usage: fractals
  *
- * Homework 6, Part 2: fractal mountains and fractal trees 
+ * Homework 6, Part 2: fractal mountains and fractal trees
  * (Pretty Late)
  *
- * Draws fractal mountains and trees -- and an island of mountains in water 
+ * Draws fractal mountains and trees -- and an island of mountains in water
  * (I tried having trees on the island but it didn't work too well.)
  *
  * Two viewer modes: polar and flying (both restrained to y>0 for up vector).
@@ -75,7 +75,7 @@
 #  define srand48(x) (srand((x)))
 #endif
 
-typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, 
+typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF,
                MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES,
                AXES } DisplayLists;
 
@@ -83,9 +83,9 @@
 
 int Rebuild = 1,        /* Rebuild display list in next display? */
     fractal = TREE,     /* What fractal are we building */
-    Level   = 4;        /* levels of recursion for fractals */     
+    Level   = 4;        /* levels of recursion for fractals */
 
-int DrawAxes = 0;       
+int DrawAxes = 0;
 
 /***************************************************************/
 /************************* VECTOR JUNK *************************/
@@ -156,7 +156,7 @@
 
 #define NUMRANDS 191
 float RandTable[NUMRANDS];  /* hash table of random numbers so we can
-			       raise the same midpoints by the same amount */ 
+			       raise the same midpoints by the same amount */
 
          /* The following are for permitting an edge of a moutain to be   */
          /* pegged so it won't be displaced up or down.  This makes it    */
@@ -164,7 +164,7 @@
 
 GLfloat Verts[3][3],    /* Vertices of outside edges of mountain */
         Slopes[3];      /* Slopes between these outside edges */
-int     Pegged[3];      /* Is this edge pegged or not */           
+int     Pegged[3];      /* Is this edge pegged or not */
 
  /*
   * Comes up with a new table of random numbers [0,1)
@@ -187,7 +187,7 @@
   mid[0] = (v1[0] + v2[0]) / 2;
   mid[1] = (v1[1] + v2[1]) / 2;
   mid[2] = (v1[2] + v2[2]) / 2;
-  if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) 
+  if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid)
                         - Slopes[edge]) > 0.00001)) {
     srand48((int)((v1[0]+v2[0])*23344));
     hash = unsigned(drand48() * 7334334);
@@ -198,9 +198,9 @@
 }
 
   /*
-   * Recursive moutain drawing routine -- from lecture with addition of 
+   * Recursive moutain drawing routine -- from lecture with addition of
    * allowing an edge to be pegged.  This function requires the above
-   * globals to be set, as well as the Level global for fractal level 
+   * globals to be set, as well as the Level global for fractal level
    */
 static float cutoff = -1;
 
@@ -239,7 +239,7 @@
   GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4  };
   GLfloat bias[8]     = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1  };
   int i;
-  float avglen = (xzlength(v1, v2) + 
+  float avglen = (xzlength(v1, v2) +
                   xzlength(v2, v3) +
 		  xzlength(v3, v1) / 3);
 
@@ -254,15 +254,15 @@
   Slopes[1] = xzslope(Verts[1], Verts[2]);
   Slopes[2] = xzslope(Verts[2], Verts[0]);
 
-  lengths[0] = avglen;          
-  for (i = 1; i < Level; i++) {   
+  lengths[0] = avglen;
+  for (i = 1; i < Level; i++) {
     lengths[i] = lengths[i-1]/2;     /* compute edge length for each level */
   }
 
-  for (i = 0; i < Level; i++) {     /* DispFactor and DispBias arrays */      
+  for (i = 0; i < Level; i++) {     /* DispFactor and DispBias arrays */
     DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7]));
     DispBias[i]   = ((i <= 7) ? bias[i] : bias[7]);
-  } 
+  }
 
   glBegin(GL_TRIANGLES);
     FMR(v1, v2, v3, 0);    /* issues no GL but vertex calls */
@@ -301,7 +301,7 @@
                      at a different level */
 
  /*
-  * recursive tree drawing thing, fleshed out from class notes pseudocode 
+  * recursive tree drawing thing, fleshed out from class notes pseudocode
   */
 void FractalTree(int level, long level_seed)
 {
@@ -318,7 +318,7 @@
     glScalef(0.7, 0.7, 0.7);
 
       srand48(level_seed+1);
-      glPushMatrix();    
+      glPushMatrix();
         glRotatef(110 + drand48()*40, 0, 1, 0);
         glRotatef(30 + drand48()*20, 0, 0, 1);
         FractalTree(level + 1, level_seed+4);
@@ -412,7 +412,7 @@
     FractalTree(0, TreeSeed);
     glPopAttrib();
     glPopMatrix();
-  glEndList();  
+  glEndList();
 }
 
  /*
@@ -477,7 +477,7 @@
 
   glPopMatrix();
   glPopAttrib();
-  glEndList();  
+  glEndList();
 }
 
 
@@ -565,7 +565,7 @@
   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
-    
+
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
 
   glEnable(GL_LIGHTING);
@@ -590,7 +590,7 @@
   CreateTreeLists();
 
   glFlush();
-} 
+}
 
 /***************************************************************/
 /************************ GLUT STUFF ***************************/
@@ -640,7 +640,7 @@
   gluOrtho2D(0.0, winwidth, 0.0, winheight);
 
   sprintf(buf, "FPS=%d", fps);
-  glColor3f(1.0f, 1.0f, 1.0f);
+  glColor3f(1.0f, 1.0f, 0.0f);
   gl_font(FL_HELVETICA, 12);
   gl_draw(buf, 10, 10);
 
@@ -792,7 +792,7 @@
   g->end();
 
   b = new Fl_Button(400,50,100,30,"New Fractal"); b->callback(handlemenu,(void*)MENU_RAND);
-  
+
   b = new Fl_Button( 10,10,100,30,"Mountain"); b->callback(choosefract,(void*)MOUNTAIN);
   b = new Fl_Button(110,10,100,30,"Tree"); b->callback(choosefract,(void*)TREE);
   b = new Fl_Button(210,10,100,30,"Island"); b->callback(choosefract,(void*)ISLAND);
@@ -817,7 +817,7 @@
 
   NewFractals();
   agvMakeAxesList(AXES);
-  myGLInit(); 
+  myGLInit();
   MenuInit();
 
   glutMainLoop(); // you could use Fl::run() instead
