Index: CMake/options.cmake
===================================================================
--- CMake/options.cmake	(revision 12029)
+++ CMake/options.cmake	(working copy)
@@ -332,8 +332,46 @@
 #######################################################################
 if(X11_Xft_FOUND)
    option(OPTION_USE_XFT "use lib Xft" ON)
+   option(OPTION_PANGO "use lib Pango" OFF)
 endif(X11_Xft_FOUND)
 
+#######################################################################
+if(X11_Xft_FOUND AND OPTION_PANGO)
+#this covers Debian, Ubuntu, FreeBSD, NetBSD, Darwin
+   if(APPLE AND OPTION_APPLE_X11)
+	list(APPEND CMAKE_INCLUDE_PATH  /sw/include)
+    	list(APPEND CMAKE_LIBRARY_PATH  /sw/lib)
+   endif(APPLE AND OPTION_APPLE_X11)
+   find_file(HAS_PANGO_H pango-1.0/pango/pango.h ${CMAKE_INCLUDE_PATH})
+   find_file(HAS_PANGOXFT_H pango-1.0/pango/pangoxft.h ${CMAKE_INCLUDE_PATH})
+
+  if(HAS_PANGO_H AND HAS_PANGOXFT_H)
+    find_library(HAS_LIB_PANGO pango-1.0 ${CMAKE_LIBRARY_PATH})
+    find_library(HAS_LIB_PANGOXFT pangoxft-1.0 ${CMAKE_LIBRARY_PATH})
+    if(APPLE)
+    	set(HAS_LIB_GOBJECT TRUE)
+    else()
+    	find_library(HAS_LIB_GOBJECT gobject-2.0 ${CMAKE_LIBRARY_PATH})
+    endif(APPLE)
+  endif(HAS_PANGO_H AND HAS_PANGOXFT_H)
+  if(HAS_LIB_PANGO AND HAS_LIB_PANGOXFT AND HAS_LIB_GOBJECT)
+    set(USE_PANGO TRUE)
+    message(STATUS "USE_PANGO=" ${USE_PANGO})
+    #remove last 3 components of HAS_PANGO_H and put in PANGO_H_PREFIX
+    get_filename_component(PANGO_H_PREFIX ${HAS_PANGO_H} PATH)
+    get_filename_component(PANGO_H_PREFIX ${PANGO_H_PREFIX} PATH)
+    get_filename_component(PANGO_H_PREFIX ${PANGO_H_PREFIX} PATH)
+
+    get_filename_component(PANGOLIB_DIR ${HAS_LIB_PANGO} PATH)
+    #glib.h is usually in ${PANGO_H_PREFIX}/glib-2.0/ ...
+    find_path(GLIB_H_PATH glib.h ${PANGO_H_PREFIX}/glib-2.0)
+    if(NOT GLIB_H_PATH) # ... but not under NetBSD
+		find_path(GLIB_H_PATH glib.h ${PANGO_H_PREFIX}/glib/glib-2.0)
+    endif(NOT GLIB_H_PATH)
+    include_directories(${PANGO_H_PREFIX}/pango-1.0 ${GLIB_H_PATH} ${PANGOLIB_DIR}/glib-2.0/include)
+  endif(HAS_LIB_PANGO AND HAS_LIB_PANGOXFT AND HAS_LIB_GOBJECT)
+endif(X11_Xft_FOUND AND OPTION_PANGO)
+
 if(OPTION_USE_XFT)
    set(USE_XFT X11_Xft_FOUND)
    list(APPEND FLTK_LDLIBS -lXft)
Index: FL/Fl_Gl_Window_Driver.H
===================================================================
--- FL/Fl_Gl_Window_Driver.H	(revision 12029)
+++ FL/Fl_Gl_Window_Driver.H	(working copy)
@@ -156,6 +156,7 @@
 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) {}
+  virtual float pixels_per_unit();
   virtual void before_show(int& need_redraw);
   virtual int mode_(int m, const int *a);
   virtual void swap_buffers();
Index: FL/Fl_Graphics_Driver.H
===================================================================
--- FL/Fl_Graphics_Driver.H	(revision 12029)
+++ FL/Fl_Graphics_Driver.H	(working copy)
@@ -135,6 +135,10 @@
   virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) {return 0; }
   /** Support function for image drawing */
   virtual void delete_bitmask(Fl_Bitmask bm) {}
+  static void change_image_size(Fl_Image *img, int W, int H) {
+    img->w(W);
+    img->h(H);
+  }
 
 public:
   Fl_Graphics_Driver();
@@ -324,6 +328,7 @@
   virtual void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
   virtual Fl_Region XRectangleRegion(int x, int y, int w, int h);
   virtual void XDestroyRegion(Fl_Region r);
+  virtual float scale() {return 1;}
   // font support
   virtual const char* get_font_name(Fl_Font fnum, int* ap) {return NULL;}
   virtual int get_font_sizes(Fl_Font fnum, int*& sizep) {return 0;}
Index: FL/Fl_Image.H
===================================================================
--- FL/Fl_Image.H	(revision 12029)
+++ FL/Fl_Image.H	(working copy)
@@ -54,7 +54,8 @@
  a box with an X in it being drawn instead.
 */
 class FL_EXPORT Fl_Image {
-    
+ 
+  friend class Fl_Graphics_Driver;
 public:
   static const int ERR_NO_IMAGE    = -1;
   static const int ERR_FILE_ACCESS = -2;
Index: configh.cmake.in
===================================================================
--- configh.cmake.in	(revision 12029)
+++ configh.cmake.in	(working copy)
@@ -92,6 +92,14 @@
 #cmakedefine01 USE_XFT
 
 /*
+* USE_PANGO:
+*
+* Use the pango library to draw UTF8 text.
+*/
+
+#cmakedefine USE_PANGO 1
+
+/*
  * HAVE_XDBE:
  *
  * Do we have the X double-buffer extension?
Index: configh.in
===================================================================
--- configh.in	(revision 12029)
+++ configh.in	(working copy)
@@ -85,12 +85,20 @@
 /*
  * USE_XFT
  *
- * Use the new Xft library to draw anti-aliased text.
+ * Use the Xft library to draw anti-aliased text.
  */
 
 #define USE_XFT 0
 
 /*
+ * USE_PANGO
+ *
+ * Use the pango library to draw UTF-8 text.
+ */
+
+#define USE_PANGO 0
+
+/*
  * HAVE_XDBE:
  *
  * Do we have the X double-buffer extension?
Index: configure.ac
===================================================================
--- configure.ac	(revision 12029)
+++ configure.ac	(working copy)
@@ -1035,6 +1035,40 @@
 	    fi
 	fi
 
+	dnl Check for the pango library unless disabled...
+        AC_ARG_ENABLE(pango, [  --enable-pango          turn on Pango support [[default=no]]])
+
+	if test x$enable_pango = xyes; then
+	    case $host_os in
+    		darwin*)
+	    	  CXXFLAGS="-I/sw/include/pango-1.0 -I/sw/include/glib-2.0 -I/sw/lib/glib-2.0/include $CXXFLAGS"
+	    	  PANGOLIBDIR="-L/sw/lib"
+	    	  ;;
+    		linux*)
+	    	  CXXFLAGS="-I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include $CXXFLAGS"
+	    	  CXXFLAGS="-I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/glib-2.0/include $CXXFLAGS"
+    	    	  ;;
+    	    	freebsd*)
+	    	  CXXFLAGS="-I/usr/local/include/pango-1.0 -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include $CXXFLAGS"
+	    	  ;;
+     	    	netbsd*)
+	    	  CXXFLAGS="-I/usr/pkg/include/pango-1.0 -I/usr/pkg/include/glib-2.0 -I/usr/pkg/lib/glib-2.0/include $CXXFLAGS"
+	    	  CXXFLAGS="-I/usr/pkg/include/glib/glib-2.0 $CXXFLAGS"
+	    	  PANGOLIBDIR="-L/usr/pkg/lib"
+	    	  LDFLAGS="-Wl,-rpath,/usr/pkg/lib $LDFLAGS"
+	    	  ;;
+   	    esac
+	        CPPFLAGS="$PANGOLIBDIR $CXXFLAGS"
+	        AC_CHECK_HEADER(pango/pango.h,
+		  AC_CHECK_HEADER(pango/pangoxft.h,
+		   AC_CHECK_LIB(pango-1.0, pango_layout_new,
+		    AC_CHECK_LIB(pangoxft-1.0, pango_xft_render_layout,
+			AC_DEFINE(USE_PANGO)
+			BUILD_PANGO="Yes"
+			LIBS="$PANGOLIBDIR -lpango-1.0 -lpangoxft-1.0 -lgobject-2.0 $LIBS"))))
+		CPPFLAGS=$CXXFLAGS
+	fi
+
 	dnl Check for the Xdbe extension unless disabled...
 	AC_ARG_ENABLE(xdbe, [  --enable-xdbe           turn on Xdbe support [[default=yes]]])
 
Index: documentation/src/osissues.dox
===================================================================
--- documentation/src/osissues.dox	(revision 12029)
+++ documentation/src/osissues.dox	(working copy)
@@ -741,7 +741,7 @@
 \par
 Whenever the user drops a file onto an application icon, OS X
 generates an Apple Event of the type "Open". You can have FLTK
-notify you of an Open event by calling the \ref fl_open_callback 
+notify you of an Open event by calling the \ref fl_open_callback()
 function.
 
 void fl_open_display()
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt	(revision 12029)
+++ src/CMakeLists.txt	(working copy)
@@ -471,6 +471,13 @@
     list (APPEND OPTIONAL_LIBS ${X11_Xrender_LIB})
 endif (HAVE_XRENDER)
 
+if (USE_PANGO)
+  list (APPEND OPTIONAL_LIBS ${HAS_LIB_PANGO} ${HAS_LIB_PANGOXFT})
+  if(NOT APPLE)
+  	list (APPEND OPTIONAL_LIBS ${HAS_LIB_GOBJECT} )
+  endif(NOT APPLE)
+endif(USE_PANGO)
+
 if (USE_XFT)
     list (APPEND OPTIONAL_LIBS ${X11_Xft_LIB})
     if (LIB_fontconfig)
Index: src/Fl_Gl_Window.cxx
===================================================================
--- src/Fl_Gl_Window.cxx	(revision 12029)
+++ src/Fl_Gl_Window.cxx	(working copy)
@@ -642,6 +642,7 @@
 #if defined(FL_CFG_GFX_XLIB)
 #include <FL/x.H>
 #include "Fl_Gl_Choice.H"
+#include <FL/Fl_Graphics_Driver.H>
 
 Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
 {
@@ -653,6 +654,11 @@
   if (overlay() && overlay() != pWindow) ((Fl_Gl_Window*)overlay())->show();
 }
 
+float Fl_X11_Gl_Window_Driver::pixels_per_unit()
+{
+  return Fl_Display_Device::display_device()->driver()->scale();
+}
+
 int Fl_X11_Gl_Window_Driver::mode_(int m, const int *a) {
   int oldmode = mode();
   if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer,
Index: src/Fl_Image_Surface.cxx
===================================================================
--- src/Fl_Image_Surface.cxx	(revision 12029)
+++ src/Fl_Image_Surface.cxx	(working copy)
@@ -17,6 +17,7 @@
 //
 
 #include <FL/Fl_Image_Surface.H>
+#include <FL/Fl_Device.H>
 
 #if defined(FL_PORTING)
 # pragma message "FL_PORTING: optionally implement class Fl_XXX_Image_Surface_Driver for your platform"
@@ -92,7 +93,7 @@
   Fl_Shared_Image *s_img = Fl_Shared_Image::get(platform_surface->image());
   int width, height;
   platform_surface->printable_rect(&width, &height);
-  s_img->scale(width, height);
+  s_img->scale(width, height, 1, 1);
   return s_img;
 }
 
@@ -132,7 +133,10 @@
    */
 Fl_Offscreen fl_create_offscreen(int w, int h) {
   int rank = find_slot();
-  offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, 0);
+  int high_res = 0;
+  float d = Fl_Display_Device::display_device()->driver()->scale();
+  high_res = d > 1;
+  offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, high_res);
   return offscreen_api_surface[rank]->offscreen();
 }
 
Index: src/Fl_Screen_Driver.cxx
===================================================================
--- src/Fl_Screen_Driver.cxx	(revision 12029)
+++ src/Fl_Screen_Driver.cxx	(working copy)
@@ -265,7 +265,8 @@
         } else {
           top = full_img->h() - (origin_y - y + img->h());
         }
-        write_image_inside(full_img, img, origin_x - x, top);
+        float s = Fl_Display_Device::display_device()->driver()->scale();
+        write_image_inside(full_img, img, (origin_x - x) * s, top * s);
         delete img;
       }
     }
Index: src/Fl_Widget_Surface.cxx
===================================================================
--- src/Fl_Widget_Surface.cxx	(revision 12029)
+++ src/Fl_Widget_Surface.cxx	(working copy)
@@ -147,6 +147,7 @@
  @param delta_x Optional horizontal offset from current graphics origin where to print the captured rectangle.
  @param delta_y As above, vertically.
  */
+#include <FL/Fl_Screen_Driver.H>
 void Fl_Widget_Surface::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y)
 {
   Fl_Display_Device::display_device()->set_current();
@@ -153,13 +154,19 @@
   Fl_Window *save_front = Fl::first_window();
   win->show();
   Fl::check();
-  win->driver()->flush(); // makes the window current necessary for fl_read_image
-  uchar *image_data;
-  image_data = fl_read_image(NULL, x, y, w, h);
+  win->driver()->flush(); // makes the window current
+  const uchar *image_data;
+  Fl_RGB_Image *img = Fl_Screen_Driver::traverse_to_gl_subwindows(win, NULL, x, y, w, h, 0, NULL);
+  if (img->w() > w) {
+    Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
+    delete img;
+    img = img2;
+  }
+  image_data = img->array;
   if (save_front != win) save_front->show();
   set_current();
   fl_draw_image(image_data, delta_x, delta_y, w, h, 3);
-  delete[] image_data;
+  delete img;
 }
 
 /**
Index: src/Fl_x.cxx
===================================================================
--- src/Fl_x.cxx	(revision 12029)
+++ src/Fl_x.cxx	(working copy)
@@ -41,6 +41,7 @@
 #  include "drivers/X11/Fl_X11_Window_Driver.H"
 #  include "drivers/X11/Fl_X11_System_Driver.H"
 #  include "drivers/Xlib/Fl_Xlib_Graphics_Driver.H"
+#  include "drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.H"
 #  include <unistd.h>
 #  include <time.h>
 #  include <sys/time.h>
@@ -601,6 +602,82 @@
   fl_xim_deactivate();
 }
 
+#if HAVE_DLSYM && HAVE_DLFCN_H && USE_XFT
+// returns true when schema is among the list of available schemas
+static bool is_schema_valid(const char *schema, const char **known) {
+  int i = 0;
+  while (known[i]) {
+    if (strcmp(known[i++], schema) == 0) return true;
+  }
+  return false;
+}
+
+//returns true under Ubuntu or Debian and when the gnome scaling value has been found
+static bool ubuntu_debian_scale_factor(float& factor) {
+  // define types needed for dynamic lib functions
+  typedef const char** (*g_settings_list_schemas_ftype)(void);
+  typedef void* (*g_settings_new_ftype)(const char *);
+  typedef void* (*g_settings_get_value_ftype)(void *settings, const char *key);
+  typedef void (*g_variant_get_ftype)(void *value, const char *format_string, ...);
+  typedef bool (*g_variant_iter_loop_ftype)(void *iter, const char *format_string, ...);
+  typedef void (*pter_ftype)(void*);
+  
+  enum {debian, ubuntu} os_type;
+  // determine whether we run Ubuntu or Debian
+  char line[400] = "";
+  FILE *in = fopen("/proc/version", "r");
+  if (!in) return false;
+  fgets(line, sizeof(line), in);
+  fclose(in);
+  if (strstr(line, "Ubuntu")) os_type = ubuntu;
+  else if(strstr(line, "Debian")) os_type = debian;
+  else return false;
+  // open dynamic libs
+  void *glib = dlopen("libglib-2.0.so", RTLD_LAZY);
+  void *gio = dlopen("libgio-2.0.so", RTLD_LAZY);
+  void *gobj = dlopen("libgobject-2.0.so", RTLD_LAZY);
+  if (!glib || !gio || !gobj) return false;
+  // define pters to used functions
+  g_settings_list_schemas_ftype g_settings_list_schemas_f = (g_settings_list_schemas_ftype)dlsym(gio, "g_settings_list_schemas"); // 2.26
+  g_settings_new_ftype g_settings_new_f = (g_settings_new_ftype)dlsym(gio, "g_settings_new"); // 2.26
+  g_settings_get_value_ftype g_settings_get_value_f =
+		(g_settings_get_value_ftype)dlsym(gio, "g_settings_get_value"); // 2.26
+  if (!g_settings_list_schemas_f || !g_settings_new_f || !g_settings_get_value_f) return false;
+  g_variant_get_ftype g_variant_get_f = (g_variant_get_ftype)dlsym(glib, "g_variant_get"); //2.24
+  g_variant_iter_loop_ftype g_variant_iter_loop_f =
+  (g_variant_iter_loop_ftype)dlsym(glib, "g_variant_iter_loop"); // 2.24
+  pter_ftype g_variant_iter_free_f =
+  (pter_ftype)dlsym(glib, "g_variant_iter_free"); // 2.24
+  pter_ftype g_object_unref_f = (pter_ftype)dlsym(gobj, "g_object_unref");
+  pter_ftype g_variant_unref_f = (pter_ftype)dlsym(glib, "g_variant_unref"); // 2.24
+  // call dynamic lib functions
+  const char **known = g_settings_list_schemas_f(); // list of available GSettings schemas
+  const char *schema = (os_type == ubuntu ? "com.ubuntu.user-interface" : "org.gnome.desktop.interface");
+  if (!is_schema_valid(schema, known)) return false;
+  void *gset = g_settings_new_f(schema);
+  void *gvar = g_settings_get_value_f(gset, os_type == ubuntu ? "scale-factor" : "scaling-factor");
+  if (os_type == ubuntu) {
+    void *iter;
+    char *str; int v;
+    g_variant_get_f(gvar, "a{si}", &iter);
+    if (g_variant_iter_loop_f(iter, "{si}", &str, &v)) {
+      factor = v/8.;
+      printf("name=%s value=%d factor=%g\n", str, v, factor);
+    }
+    g_variant_iter_free_f(iter);
+  } else if (os_type == debian) {
+    unsigned int v;
+    g_variant_get_f(gvar, "u", &v);
+    factor = v;
+    printf("factor=%g\n", factor);
+  }
+  g_variant_unref_f(gvar);
+  g_object_unref_f(gset);
+  return true;
+}
+#endif
+
+
 void Fl_X11_Screen_Driver::open_display() {
   if (fl_display) return;
 
@@ -617,6 +694,28 @@
   // the unique GC used by all X windows
   GC gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0);
   Fl_Display_Device::display_device()->driver()->gc(gc);
+  
+#if USE_XFT // scaling does not work without Xft
+  // attempt to determine the adequate scaling to support HiDPI displays
+  float factor=1;
+  const char *env = getenv("FL_SCALING_FACTOR");
+  if (env) { // set scaling value through environment variable
+    sscanf(env, "%f", &factor);
+#if HAVE_DLSYM && HAVE_DLFCN_H
+  } else if (ubuntu_debian_scale_factor(factor)) {
+    ; // with Ubuntu or Debian, read the current gnome scaling value
+#endif
+  } else { // otherwise, use display dpi values reported by Xrandr
+    float hdpi, vdpi;
+    Fl::screen_dpi(hdpi, vdpi);
+    factor = hdpi/96;
+    factor = int(10*factor + 0.5)/10.f;
+  }
+  if (factor != 1) {
+    Fl_Scaled_Xlib_Graphics_Driver *dr = (Fl_Scaled_Xlib_Graphics_Driver*)Fl_Display_Device::display_device()->driver();
+    dr->pixel_scale(factor);
+  }
+#endif // USE_XFT
 }
 
 
@@ -725,8 +824,9 @@
   Window root = RootWindow(fl_display, fl_screen);
   Window c; int mx,my,cx,cy; unsigned int mask;
   XQueryPointer(fl_display,root,&root,&c,&mx,&my,&cx,&cy,&mask);
-  xx = mx;
-  yy = my;
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  xx = mx/s;
+  yy = my/s;
 }
 
 ////////////////////////////////////////////////////////////////
@@ -1083,10 +1183,11 @@
 #  if CONSOLIDATE_MOTION
   send_motion = 0;
 #  endif
-  Fl::e_x_root  = fl_xevent->xbutton.x_root;
-  Fl::e_x       = fl_xevent->xbutton.x;
-  Fl::e_y_root  = fl_xevent->xbutton.y_root;
-  Fl::e_y       = fl_xevent->xbutton.y;
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  Fl::e_x_root  = fl_xevent->xbutton.x_root/s;
+  Fl::e_x       = fl_xevent->xbutton.x/s;
+  Fl::e_y_root  = fl_xevent->xbutton.y_root/s;
+  Fl::e_y       = fl_xevent->xbutton.y/s;
   Fl::e_state   = fl_xevent->xbutton.state << 16;
   fl_event_time = fl_xevent->xbutton.time;
 #  ifdef __sgi
@@ -1995,7 +2096,8 @@
 
     // tell Fl_Window about it and set flag to prevent echoing:
     resize_bug_fix = window;
-    window->resize(X, Y, W, H);
+    float s = Fl_Display_Device::display_device()->driver()->scale();
+    window->resize(X/s, Y/s, W/s, H/s);
     break; // allow add_handler to do something too
     }
 
@@ -2066,15 +2168,16 @@
   }
 
   if (resize_from_program && shown()) {
+    float s = Fl_Display_Device::display_device()->driver()->scale();
     if (is_a_resize) {
       if (!pWindow->resizable()) pWindow->size_range(w(), h(), w(), h());
       if (is_a_move) {
-        XMoveResizeWindow(fl_display, fl_xid(pWindow), X, Y, W>0 ? W : 1, H>0 ? H : 1);
+        XMoveResizeWindow(fl_display, fl_xid(pWindow), X*s, Y*s, W>0 ? W*s : 1, H>0 ? H*s : 1);
       } else {
-        XResizeWindow(fl_display, fl_xid(pWindow), W>0 ? W : 1, H>0 ? H : 1);
+        XResizeWindow(fl_display, fl_xid(pWindow), W>0 ? W*s : 1, H>0 ? H*s : 1);
       }
     } else
-      XMoveWindow(fl_display, fl_xid(pWindow), X, Y);
+      XMoveWindow(fl_display, fl_xid(pWindow), X*s, Y*s);
   }
 }
 
@@ -2256,6 +2359,7 @@
 {
   Fl_Group::current(0); // get rid of very common user bug: forgot end()
 
+  float s = Fl_Display_Device::display_device()->driver()->scale();
   int X = win->x();
   int Y = win->y();
   int W = win->w();
@@ -2365,7 +2469,7 @@
   Fl_X* xp =
     set_xid(win, XCreateWindow(fl_display,
                                root,
-                               X, Y, W, H,
+                               s*X, s*Y, s*W, s*H,
                                0, // borderwidth
                                visual->depth,
                                InputOutput,
@@ -2525,12 +2629,13 @@
 
   XSizeHints *hints = XAllocSizeHints();
   // memset(&hints, 0, sizeof(hints)); jreiser suggestion to fix purify?
-  hints->min_width = minw();
-  hints->min_height = minh();
-  hints->max_width = maxw();
-  hints->max_height = maxh();
-  hints->width_inc = dw();
-  hints->height_inc = dh();
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  hints->min_width = s*minw();
+  hints->min_height = s*minh();
+  hints->max_width = s*maxw();
+  hints->max_height = s*maxh();
+  hints->width_inc = s*dw();
+  hints->height_inc = s*dh();
   hints->win_gravity = StaticGravity;
 
   // see the file /usr/include/X11/Xm/MwmUtil.h:
@@ -2566,8 +2671,8 @@
 
   if (force_position()) {
     hints->flags |= USPosition;
-    hints->x = w->x();
-    hints->y = w->y();
+    hints->x = s*w->x();
+    hints->y = s*w->y();
   }
 
   if (!w->border()) {
@@ -2877,7 +2982,8 @@
   printer.print_widget( win, - win->w()/2, - win->h()/2 );
   //printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 );
 #else  
-  printer.print_window(win);
+  //printer.print_window(win);
+printer.print_window_part( win, 0,0, win->w(), win->h(), 0,0 );
 #endif
 
   printer.end_page();
Index: src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx
===================================================================
--- src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx	(revision 12029)
+++ src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx	(working copy)
@@ -106,6 +106,11 @@
   glPixelStorei(GL_PACK_ROW_LENGTH, 0);
   glPixelStorei(GL_PACK_SKIP_ROWS, 0);
   glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+  //
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  if (s != 1) {
+    x *= s; y *= s; w *= s; h *= s;
+  }
   // Read a block of pixels from the frame buffer
   int mByteWidth = w * 3;
   mByteWidth = (mByteWidth + 3) & ~3;    // Align to 4 bytes
Index: src/drivers/X11/Fl_X11_Screen_Driver.cxx
===================================================================
--- src/drivers/X11/Fl_X11_Screen_Driver.cxx	(revision 12029)
+++ src/drivers/X11/Fl_X11_Screen_Driver.cxx	(working copy)
@@ -353,6 +353,13 @@
       }
     }
   }
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  for (int i=0; i<num_screens; i++) {
+    screens[i].x_org /= s;;
+    screens[i].y_org /= s;
+    screens[i].width /= s;
+    screens[i].height /= s;
+  }
 }
 
 
@@ -765,6 +772,8 @@
     image = 0;
 #  endif // __sgi
   
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+
   if (!image) {
     // fetch absolute coordinates
     int dx, dy, sx, sy, sw, sh;
@@ -775,7 +784,8 @@
     else win = fl_find(fl_window);
     if (win) {
       XTranslateCoordinates(fl_display, fl_window,
-                            RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win);
+                            RootWindow(fl_display, fl_screen), X*s, Y*s, &dx, &dy, &child_win);
+      dx /= s; dy /= s;
       // screen dimensions
       Fl::screen_xywh(sx, sy, sw, sh, fl_screen);
     }
@@ -784,7 +794,7 @@
       // however, if the window is obscured etc. the function will still fail. Make sure we
       // catch the error and continue, otherwise an exception will be thrown.
       XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
-      image = XGetImage(fl_display, fl_window, X, Y, w, h, AllPlanes, ZPixmap);
+      image = XGetImage(fl_display, fl_window, X*s, Y*s, w*s, h*s, AllPlanes, ZPixmap);
       XSetErrorHandler(old_handler);
     } else {
       // image is crossing borders, determine visible region
@@ -795,9 +805,9 @@
       
       // allocate the image
       int bpp = fl_visual->depth + ((fl_visual->depth / 8) % 2) * 8;
-      char* buf = (char*)malloc(bpp / 8 * w * h);
+      char* buf = (char*)malloc(bpp / 8 * int(w*s) * int(h*s));
       image = XCreateImage(fl_display, fl_visual->visual,
-                           fl_visual->depth, ZPixmap, 0, buf, w, h, bpp, 0);
+                           fl_visual->depth, ZPixmap, 0, buf, w*s, h*s, bpp, 0);
       if (!image) {
         if (buf) free(buf);
         return 0;
@@ -804,8 +814,8 @@
       }
       
       XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
-      XImage *subimg = XGetSubImage(fl_display, fl_window, X + noffx, Y + noffy,
-                                    nw, nh, AllPlanes, ZPixmap, image, noffx, noffy);
+      XImage *subimg = XGetSubImage(fl_display, fl_window, (X + noffx)*s, (Y + noffy)*s,
+                                    nw*s, nh*s, AllPlanes, ZPixmap, image, noffx*s, noffy*s);
       XSetErrorHandler(old_handler);
       if (!subimg) {
         XDestroyImage(image);
@@ -815,6 +825,9 @@
   }
   
   if (!image) return 0;
+  if (s != 1) {
+    w *= s; h *= s;
+  }
   
 #ifdef DEBUG
   printf("width            = %d\n", image->width);
Index: src/drivers/X11/Fl_X11_Window_Driver.cxx
===================================================================
--- src/drivers/X11/Fl_X11_Window_Driver.cxx	(revision 12029)
+++ src/drivers/X11/Fl_X11_Window_Driver.cxx	(working copy)
@@ -112,11 +112,11 @@
 #if USE_XDBE
   if (can_xdbe()) {
     XdbeDeallocateBackBufferName(fl_display, other_xid);
-    other_xid = 0;
   }
   else
 #endif // USE_XDBE
-    Fl_Window_Driver::destroy_double_buffer();
+    fl_delete_offscreen(other_xid);
+  other_xid = 0;
 }
 
 Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
@@ -160,8 +160,9 @@
   if (status == 0 || root == parent) return;
   XWindowAttributes attributes;
   XGetWindowAttributes(fl_display, parent, &attributes);
-  w = attributes.width;
-  h = attributes.height;
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  w = attributes.width / s;
+  h = attributes.height / s;
 }
 
 
@@ -324,8 +325,9 @@
 #endif
   }
   if (!XShapeCombineMask_f) return;
-  shape_data_->lw_ = w();
-  shape_data_->lh_ = h();
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  shape_data_->lw_ = w()*s;
+  shape_data_->lh_ = h()*s;
   Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
   Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(pWindow),
                                          (const char*)*temp->data(),
@@ -401,25 +403,30 @@
   if (n) XFree(children);
   if (!do_it) wsides = htop = 0;
   int hbottom = wsides;
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  htop /= s; wsides /= s;
   fl_window = parent;
   if (htop) {
     r_top = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, - (w() + 2 * wsides), htop, 0);
     top = Fl_Shared_Image::get(r_top);
+    top->scale(w() + 2 * wsides, htop, 1, 1);
   }
   if (wsides) {
     r_left = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop, -wsides, h(), 0);
     if (r_left) {
       left =  Fl_Shared_Image::get(r_left);
+      left->scale(wsides, h(), 1, 1);
     }
     r_right = Fl::screen_driver()->read_win_rectangle(NULL, w() + wsides, htop, -wsides, h(), 0);
     if (r_right) {
       right = Fl_Shared_Image::get(r_right);
+      right->scale(wsides, h(), 1, 1);
     }
     r_bottom = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop + h(), -(w() + 2*wsides), hbottom, 0);
     if (r_bottom) {
       bottom = Fl_Shared_Image::get(r_bottom);
-    }
-  }
+      bottom->scale(w() + 2*wsides, wsides, 1, 1);
+    }  }
   fl_window = from;
   previous->Fl_Surface_Device::set_current();
 }
@@ -649,8 +656,9 @@
 int Fl_X11_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
                                  void (*draw_area)(void*, int,int,int,int), void* data)
 {
+  float s = Fl_Display_Device::display_device()->driver()->scale();
   XCopyArea(fl_display, fl_window, fl_window, (GC)fl_graphics_driver->gc(),
-            src_x, src_y, src_w, src_h, dest_x, dest_y);
+            src_x*s, src_y*s, src_w*s, src_h*s, dest_x*s, dest_y*s);
   // we have to sync the display and get the GraphicsExpose events! (sigh)
   for (;;) {
     XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
Index: src/drivers/Xlib/Fl_Font.H
===================================================================
--- src/drivers/Xlib/Fl_Font.H	(revision 12029)
+++ src/drivers/Xlib/Fl_Font.H	(working copy)
@@ -45,8 +45,12 @@
   Fl_Fontsize size; /**< font size */
 #ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc. 
 #  if USE_XFT
-  XftFont* font;
-  //const char* encoding;
+#    if USE_PANGO
+        int descent_;
+        int height_;
+#    else
+        XftFont* font;
+#    endif
   int angle;
   FL_EXPORT Fl_Font_Descriptor(const char* xfontname, Fl_Fontsize size, int angle);
 #  else
Index: src/drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.H
===================================================================
--- src/drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.H	(nonexistent)
+++ src/drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.H	(working copy)
@@ -0,0 +1,90 @@
+//
+// "$Id:$"
+//
+// Draw code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 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
+// file is missing or damaged, see the license at:
+//
+//     http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+//     http://www.fltk.org/str.php
+//
+
+#ifndef Fl_Scaled_Xlib_Graphics_Driver_h
+#define Fl_Scaled_Xlib_Graphics_Driver_h
+
+#ifndef FL_DOXYGEN
+
+#include "Fl_Xlib_Graphics_Driver.H"
+#include <FL/Fl_Image.H>
+
+/* graphics driver that scales all graphics coordinates before calling Xlib */
+class Fl_Scaled_Xlib_Graphics_Driver : public Fl_Xlib_Graphics_Driver {
+private:
+  float scale_; // scale between user and graphical coordinates: graphical = user * scale_
+  void draw_image_innards(void *buf, Fl_Draw_Image_Cb cb,
+                          int X, int Y, int W, int H, int D, int L, bool mono, float s);
+  Region scale_clip(float f);
+  void unscale_clip(Region);
+public:
+  Fl_Scaled_Xlib_Graphics_Driver(float factor);
+  virtual ~Fl_Scaled_Xlib_Graphics_Driver();
+  float scale() { return scale_; }
+  void pixel_scale(float f) {scale_ = f;}
+  void font(Fl_Font face, Fl_Fontsize size);
+  Fl_Fontsize size();
+  double width(const char *str, int n);
+  double width(unsigned int c);
+  void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
+  int height();
+  int descent();
+  void rect(int x, int y, int w, int h);
+  void rectf(int x, int y, int w, int h);
+  void xyline(int x, int y, int x1);
+  void xyline(int x, int y, int x1, int y2);
+  void xyline(int x, int y, int x1, int y2, int x3);
+  void yxline(int x, int y, int y1);
+  void yxline(int x, int y, int y1, int x2);
+  void yxline(int x, int y, int y1, int x2, int y3);
+  void line(int x, int y, int x1, int y1);
+  void line(int x, int y, int x1, int y1, int x2, int y2);
+  void draw(const char* str, int n, int x, int y);
+  void draw(int angle, const char *str, int n, int x, int y);
+  void rtl_draw(const char* str, int n, int x, int y);
+  void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw(Fl_Shared_Image *img, int x, int y);
+  void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+  void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) ;
+  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+  void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+  void pie(int x, int y, int w, int h, double a1, double a2);
+  void arc(int x, int y, int w, int h, double a1, double a2);
+  void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
+  void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  void loop(int x0, int y0, int x1, int y1, int x2, int y2);
+  void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  void point(int x, int y);
+  void restore_clip();
+  void line_style(int style, int width=0, char* dashes=0);
+  void transformed_vertex0(short x, short y);
+  void circle(double x, double y, double r);
+  void end_loop();
+  void gap();
+};
+
+#endif // FL_DOXYGEN
+
+#endif /* Fl_Scaled_Xlib_Graphics_Driver_h */
+
+//
+// End of "$Id:$".
+//
Index: src/drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.cxx	(nonexistent)
+++ src/drivers/Xlib/Fl_Scaled_Xlib_Graphics_Driver.cxx	(working copy)
@@ -0,0 +1,406 @@
+//
+// "$Id:$"
+//
+// Drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 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
+// file is missing or damaged, see the license at:
+//
+//     http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+//     http://www.fltk.org/str.php
+//
+
+#include <config.h>
+#include "Fl_Scaled_Xlib_Graphics_Driver.H"
+#include "Fl_Font.H"
+#include <FL/Fl.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/fl_draw.H>
+#include <math.h>
+
+#ifndef FL_DOXYGEN
+
+Fl_Scaled_Xlib_Graphics_Driver::Fl_Scaled_Xlib_Graphics_Driver(float factor) : Fl_Xlib_Graphics_Driver() {
+  scale_ = factor;
+}
+
+Fl_Scaled_Xlib_Graphics_Driver::~Fl_Scaled_Xlib_Graphics_Driver() {}
+
+void Fl_Scaled_Xlib_Graphics_Driver::font(Fl_Font face, Fl_Fontsize size) {
+  Fl_Xlib_Graphics_Driver::font(face, (Fl_Fontsize)(size*scale_ + 0.5));
+}
+
+Fl_Fontsize Fl_Scaled_Xlib_Graphics_Driver::size() {return (Fl_Fontsize)(size_/scale_); }
+
+void Fl_Scaled_Xlib_Graphics_Driver::rect(int x, int y, int w, int h) {
+  Fl_Xlib_Graphics_Driver::rect((int)(x*scale_), (int)(y*scale_), (int)(w*scale_), (int)(h*scale_));
+}
+
+double Fl_Scaled_Xlib_Graphics_Driver::width(const char *str, int n) {
+  return Fl_Xlib_Graphics_Driver::width(str, n)/scale_;
+}
+
+double Fl_Scaled_Xlib_Graphics_Driver::width(unsigned int c) {
+  return Fl_Xlib_Graphics_Driver::width(c)/scale_;
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::text_extents(const char*c, int n, int& dx, int& dy, int& w, int& h) {
+  float s = scale_; scale_ = 1;
+  Fl_Xlib_Graphics_Driver::text_extents(c, n, dx, dy, w, h);
+  scale_ = s;
+  dx /= scale_;
+  dy /= scale_;
+  w /= scale_;
+  h /= scale_;
+}
+
+int Fl_Scaled_Xlib_Graphics_Driver::height() {return Fl_Xlib_Graphics_Driver::height()/scale_;}
+
+int Fl_Scaled_Xlib_Graphics_Driver::descent() {return Fl_Xlib_Graphics_Driver::descent()/scale_;}
+
+void Fl_Scaled_Xlib_Graphics_Driver::rectf(int x, int y, int w, int h) {
+  Fl_Xlib_Graphics_Driver::rectf((int)(x*scale_), (int)(y*scale_), (int)(w*scale_), (int)(h*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::xyline(int x, int y, int x1) {
+  Fl_Xlib_Graphics_Driver::xyline((int)(x*scale_), (int)(y*scale_), (int)(x1*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+  Fl_Xlib_Graphics_Driver::xyline((int)(x*scale_), (int)(y*scale_), (int)(x1*scale_), (int)(y2*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+  Fl_Xlib_Graphics_Driver::xyline((int)(x*scale_), (int)(y*scale_), (int)(x1*scale_), (int)(y2*scale_), (int)(x3*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::yxline(int x, int y, int y1) {
+  Fl_Xlib_Graphics_Driver::yxline((int)(x*scale_), (int)(y*scale_), (int)(y1*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+  Fl_Xlib_Graphics_Driver::yxline((int)(x*scale_), (int)(y*scale_), (int)(y1*scale_), (int)(x2*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+  Fl_Xlib_Graphics_Driver::yxline((int)(x*scale_), (int)(y*scale_), (int)(y1*scale_), (int)(x2*scale_), (int)(y3*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1) {
+  Fl_Xlib_Graphics_Driver::line((int)(x*scale_), (int)(y*scale_), (int)(x1*scale_), (int)(y1*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+  Fl_Xlib_Graphics_Driver::line((int)(x*scale_), (int)(y*scale_), (int)(x1*scale_), (int)(y1*scale_), (int)(x2*scale_), (int)(y2*scale_));
+}
+
+Region Fl_Scaled_Xlib_Graphics_Driver::scale_clip(float f) {
+  Region r = rstack[rstackptr];
+  if (r == 0 || f == 1) return 0;
+  Region r2 = XCreateRegion();
+  XUnionRegion(r, r, r2); // make r2 a copy of r
+  
+  for (int i = 0; i < r->numRects; i++) {
+    r->rects[i].x1 = short(r->rects[i].x1*f+0.5);
+    r->rects[i].x2 = short(r->rects[i].x2*f+0.5);
+    r->rects[i].y1 = short(r->rects[i].y1*f+0.5);
+    r->rects[i].y2 = short(r->rects[i].y2*f+0.5);
+  }
+  r->extents.x1 = short(r->extents.x1*f+0.5);
+  r->extents.x2 = short(r->extents.x2*f+0.5);
+  r->extents.y1 = short(r->extents.y1*f+0.5);
+  r->extents.y2 = short(r->extents.y2*f+0.5);
+  return r2;
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::unscale_clip(Region r2) {
+  if (r2) {
+    XDestroyRegion(rstack[rstackptr]);
+    rstack[rstackptr] = r2;
+  }
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw(const char* str, int n, int x, int y) {
+  float s = 1;
+#if USE_XFT
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
+#endif
+  Fl_Xlib_Graphics_Driver::draw(str, n, int(x*s), int(y*s));
+#if USE_XFT
+  scale_ = s;
+  unscale_clip(r2);
+#endif
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+  float s = 1;
+#if USE_XFT
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
+#endif
+  Fl_Xlib_Graphics_Driver::draw(angle, str, n, int(x*s), int(y*s));
+#if USE_XFT
+  scale_ = s;
+  unscale_clip(r2);
+#endif
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
+  float s = 1;
+#if USE_XFT
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
+#endif
+  Fl_Xlib_Graphics_Driver::rtl_draw(str, n, int(x*s), int(y*s));
+#if USE_XFT
+  scale_ = s;
+  unscale_clip(r2);
+#endif
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw(pxm, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);
+  if (!pixmap_id(pxm)) { // build a scaled id_ & pixmap_ for pxm
+    Fl_Pixmap *pxm2 = (Fl_Pixmap*)pxm->copy(pxm->w()*s, pxm->h()*s);
+    pixmap_id(pxm, cache(pxm2, pxm2->w(), pxm2->h(), pxm2->data()));
+    pixmap_mask(pxm, pixmap_mask(pxm2));
+    pixmap_mask(pxm2, 0);
+    delete pxm2;
+  }
+  // draw pxm using its scaled id_ & pixmap_
+  int img_w = pxm->w();
+  int img_h = pxm->h();
+  change_image_size(pxm, img_w*s, img_h*s); // temporarily scale the size of pxm
+  Fl_Xlib_Graphics_Driver::draw(pxm, XP*s, YP*s, WP*s, HP*s, cx*s, cy*s);
+  change_image_size(pxm, img_w, img_h);
+  unscale_clip(r2);
+  scale_ = s;
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw(bm, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);
+  if (!bitmap_id(bm)) { // build a scaled id_ for bm
+    Fl_Bitmap *bm2 = (Fl_Bitmap*)bm->copy(bm->w()*s, bm->h()*s);
+    bitmap_id(bm, cache(bm2, bm2->w(), bm2->h(), bm2->array));
+    delete bm2;
+  }
+  // draw bm using its scaled id_
+  int img_w = bm->w();
+  int img_h = bm->h();
+  change_image_size(bm, img_w*s, img_h*s); // temporarily scale the size of bm
+  Fl_Xlib_Graphics_Driver::draw(bm, XP*s, YP*s, WP*s, HP*s, cx*s, cy*s);
+  change_image_size(bm, img_w, img_h);
+  unscale_clip(r2);
+  scale_ = s;
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw(img, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);
+  if (!rgb_id(img)) { // build and draw a scaled id_ for img
+    Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(img->w()*s, img->h()*s);
+    Fl_Xlib_Graphics_Driver::draw(img2, XP*s, YP*s, WP*s, HP*s, cx*s, cy*s);
+    rgb_id(img, rgb_id(img2));
+    rgb_id(img2, 0);
+    delete img2;
+  }
+  else { // draw img using its scaled id_
+    int img_w = img->w();
+    int img_h = img->h();
+    change_image_size(img, img_w*s, img_h*s); // temporarily scale the size of img
+    Fl_Xlib_Graphics_Driver::draw(img, XP*s, YP*s, WP*s, HP*s, cx*s, cy*s);
+    change_image_size(img, img_w, img_h);
+  }
+  unscale_clip(r2);
+  scale_ = s;
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw(Fl_Shared_Image *shared, int X, int Y) {
+  if (scale_ == 1) {
+    Fl_Graphics_Driver::draw(shared, X, Y);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);
+  int oldw=shared->w();
+  int oldh=shared->h();
+  change_image_size(shared, oldw*s, oldh*s);
+  Fl_Graphics_Driver::draw(shared, X*s, Y*s);
+  change_image_size(shared, oldw, oldh);
+  unscale_clip(r2);
+  scale_ = s;
+}
+
+/* read the image data from a pointer or with a callback, scale it, and draw it */
+void Fl_Scaled_Xlib_Graphics_Driver::draw_image_innards(void *buf, Fl_Draw_Image_Cb cb,
+                    int X, int Y, int W, int H, int D, int L, bool mono, float s) {
+  int aD = abs(D);
+  if (L == 0) L = W*aD;
+  int depth = mono ? (aD%2==0?2:1) : aD;
+  uchar *tmp_buf = new uchar[W*H*depth];
+  if (cb) {
+    for (int i = 0; i < H; i++) {
+      cb(buf, 0, i, W, tmp_buf + i * W * depth);
+    }
+  } else {
+    uchar *q, *p = tmp_buf;
+    for (int i = 0; i < H; i++) {
+      q = (uchar*)buf + i * L;
+      for (int j = 0; j < W; j++) {
+        memcpy(p, q, depth);
+        p += depth; q += D;
+      }
+    }
+  }
+  Fl_RGB_Image *rgb = new Fl_RGB_Image(tmp_buf, W, H, depth);
+  rgb->alloc_array = 1;
+  Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(W * s, H * s);
+  delete rgb;
+  Region r2 = scale_clip(s);
+  Fl_Xlib_Graphics_Driver::draw_image(scaled_rgb->array, X * s, Y * s, W * s, H * s, depth);
+  unscale_clip(r2);
+  delete scaled_rgb;
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw_image(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_innards((void*)buf, NULL, X, Y, W, H, D, L, false, scale_);
+  }
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw_image(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_innards(data, cb, X, Y, W, H, D, 0, false, scale_);
+  }
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw_image_mono(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_innards((void*)buf, NULL, X, Y, W, H, D, L, true, scale_);
+  }
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
+  if (scale_ == 1) {
+    Fl_Xlib_Graphics_Driver::draw_image_mono(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_innards(data, cb, X, Y, W, H, D, 0, true, scale_);
+  }
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
+  Fl_Xlib_Graphics_Driver::copy_offscreen(x*scale_,y*scale_,w*scale_,h*scale_,pixmap,srcx*scale_,srcy*scale_);
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {
+  Fl_Xlib_Graphics_Driver::pie((int)(x*scale_), (int)(y*scale_), (int)(w*scale_), (int)(h*scale_),a1,a2);
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
+  Fl_Xlib_Graphics_Driver::arc((int)(x*scale_), (int)(y*scale_), (int)(w*scale_), (int)(h*scale_),a1,a2);
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
+  Fl_Xlib_Graphics_Driver::polygon((int)(x0*scale_), (int)(y0*scale_), (int)(x1*scale_), (int)(y1*scale_),(int)(x2*scale_), (int)(y2*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  Fl_Xlib_Graphics_Driver::polygon((int)(x0*scale_), (int)(y0*scale_), (int)(x1*scale_), (int)(y1*scale_),(int)(x2*scale_), (int)(y2*scale_), (int)(x3*scale_), (int)(y3*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
+  Fl_Xlib_Graphics_Driver::loop((int)(x0*scale_), (int)(y0*scale_), (int)(x1*scale_), (int)(y1*scale_),(int)(x2*scale_), (int)(y2*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  Fl_Xlib_Graphics_Driver::loop((int)(x0*scale_), (int)(y0*scale_), (int)(x1*scale_), (int)(y1*scale_),(int)(x2*scale_), (int)(y2*scale_), (int)(x3*scale_), (int)(y3*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::point(int x, int y) {
+  Fl_Xlib_Graphics_Driver::point((int)(x*scale_), (int)(y*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::restore_clip() {
+  fl_clip_state_number++;
+  if (gc_) {
+    Region r = rstack[rstackptr];
+    if (r) {
+      Region r2 = scale_clip(scale_);
+      XSetRegion(fl_display, gc_, r);
+      unscale_clip(r2);
+    }
+    else XSetClipMask(fl_display, gc_, 0);
+  }
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) {
+  Fl_Xlib_Graphics_Driver::line_style(style, (int)(width*scale_+0.5), dashes);
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::transformed_vertex0(short x, short y) {
+   Fl_Xlib_Graphics_Driver::transformed_vertex0( short(x*scale_),  short(y*scale_));
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::circle(double x, double y,double r) {
+  double xt = transform_x(x,y)*scale_;
+  double yt = transform_y(x,y)*scale_;
+  double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); rx *= scale_;
+  double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); ry *= scale_;
+  int llx = (int)rint(xt-rx);
+  int w = (int)rint(xt+rx)-llx;
+  int lly = (int)rint(yt-ry);
+  int h = (int)rint(yt+ry)-lly;
+  
+  (what == POLYGON ? XFillArc : XDrawArc)
+  (fl_display, fl_window, gc_, llx, lly, w, h, 0, 360*64);
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::end_loop() {
+  fixloop();
+  if (n>2) Fl_Xlib_Graphics_Driver::transformed_vertex0((short)p[0].x, (short)p[0].y);
+  end_line();
+}
+
+void Fl_Scaled_Xlib_Graphics_Driver::gap() {
+  while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--;
+  if (n > gap_+2) {
+    Fl_Xlib_Graphics_Driver::transformed_vertex0((short)p[gap_].x, (short)p[gap_].y);
+    gap_ = n;
+  } else {
+    n = gap_;
+  }
+}
+
+#endif // FL_DOXYGEN
+
+//
+// End of "$Id: Fl_Scaled_Xlib_Graphics_Driver.cxx 11700 2016-04-26 07:25:53Z manolo $".
+//
+
Index: src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.H
===================================================================
--- src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.H	(revision 12029)
+++ src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.H	(working copy)
@@ -21,10 +21,10 @@
 
 #ifndef FL_DOXYGEN
 
-#include <src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H>
+#include "Fl_Scaled_Xlib_Graphics_Driver.H"
 
 /* graphics driver that translates all graphics coordinates before calling Xlib */
-class Fl_Translated_Xlib_Graphics_Driver : public Fl_Xlib_Graphics_Driver {
+class Fl_Translated_Xlib_Graphics_Driver : public Fl_Scaled_Xlib_Graphics_Driver {
   int offset_x, offset_y; // translation between user and graphical coordinates: graphical = user + offset
   unsigned depth; // depth of translation stack
   int stack_x[20], stack_y[20]; // translation stack allowing cumulative translations
@@ -49,6 +49,7 @@
   void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
   void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy);
   void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw(Fl_Shared_Image *img, int XP, int YP);
   void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
   void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
   void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) ;
Index: src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.cxx	(revision 12029)
+++ src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.cxx	(working copy)
@@ -22,7 +22,7 @@
 
 #ifndef FL_DOXYGEN
 
-Fl_Translated_Xlib_Graphics_Driver::Fl_Translated_Xlib_Graphics_Driver() {
+Fl_Translated_Xlib_Graphics_Driver::Fl_Translated_Xlib_Graphics_Driver() : Fl_Scaled_Xlib_Graphics_Driver(1) {
   offset_x = 0; offset_y = 0;
   depth = 0;
 }
@@ -48,47 +48,47 @@
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::rect(int x, int y, int w, int h) {
-  Fl_Xlib_Graphics_Driver::rect(x+offset_x, y+offset_y, w, h);
+  Fl_Scaled_Xlib_Graphics_Driver::rect(x+offset_x, y+offset_y, w, h);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::rectf(int x, int y, int w, int h) {
-  Fl_Xlib_Graphics_Driver::rectf(x+offset_x, y+offset_y, w, h);
+  Fl_Scaled_Xlib_Graphics_Driver::rectf(x+offset_x, y+offset_y, w, h);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::xyline(int x, int y, int x1) {
-  Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x);
+  Fl_Scaled_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
-  Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
-  Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y, x3+offset_x);
+  Fl_Scaled_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y, x3+offset_x);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::yxline(int x, int y, int y1) {
-  Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
-  Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x);
+  Fl_Scaled_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
-  Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x, y3+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x, y3+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1) {
-  Fl_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
-  Fl_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y, x2+offset_x, y2+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y, x2+offset_x, y2+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::draw(const char* str, int n, int x, int y) {
-  Fl_Xlib_Graphics_Driver::draw(str, n, x+offset_x, y+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::draw(str, n, x+offset_x, y+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
@@ -96,13 +96,13 @@
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
-  Fl_Xlib_Graphics_Driver::rtl_draw(str, n, x+offset_x, y+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::rtl_draw(str, n, x+offset_x, y+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
   XP += offset_x; YP += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw(pxm, XP, YP, WP,HP,cx,cy);
+  Fl_Scaled_Xlib_Graphics_Driver::draw(pxm, XP, YP, WP,HP,cx,cy);
   untranslate_all();
 }
 
@@ -109,7 +109,7 @@
 void Fl_Translated_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
   XP += offset_x; YP += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw(bm, XP, YP, WP,HP,cx,cy);
+  Fl_Scaled_Xlib_Graphics_Driver::draw(bm, XP, YP, WP,HP,cx,cy);
   untranslate_all();
 }
 
@@ -116,14 +116,21 @@
 void Fl_Translated_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
   XP += offset_x; YP += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw(img, XP, YP, WP,HP,cx,cy);
+  Fl_Scaled_Xlib_Graphics_Driver::draw(img, XP, YP, WP,HP,cx,cy);
   untranslate_all();
 }
 
+void Fl_Translated_Xlib_Graphics_Driver::draw(Fl_Shared_Image *img, int XP, int YP) {
+  XP += offset_x; YP += offset_y;
+  translate_all(-offset_x, -offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::draw(img, XP, YP);
+  untranslate_all();
+}
+
 void Fl_Translated_Xlib_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
   X += offset_x; Y += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw_image(buf, X, Y, W,H,D,L);
+  Fl_Scaled_Xlib_Graphics_Driver::draw_image(buf, X, Y, W,H,D,L);
   untranslate_all();
 }
 
@@ -130,7 +137,7 @@
 void Fl_Translated_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
   X += offset_x; Y += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw_image(cb, data, X, Y, W,H,D);
+  Fl_Scaled_Xlib_Graphics_Driver::draw_image(cb, data, X, Y, W,H,D);
   untranslate_all();
 }
 
@@ -137,7 +144,7 @@
 void Fl_Translated_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
   X += offset_x; Y += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw_image_mono(buf, X, Y, W,H,D,L);
+  Fl_Scaled_Xlib_Graphics_Driver::draw_image_mono(buf, X, Y, W,H,D,L);
   untranslate_all();
 }
 
@@ -144,24 +151,24 @@
 void Fl_Translated_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
   X += offset_x; Y += offset_y;
   translate_all(-offset_x, -offset_y);
-  Fl_Xlib_Graphics_Driver::draw_image_mono(cb, data, X, Y, W,H,D);
+  Fl_Scaled_Xlib_Graphics_Driver::draw_image_mono(cb, data, X, Y, W,H,D);
   untranslate_all();
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
-  Fl_Xlib_Graphics_Driver::copy_offscreen(x+offset_x, y+offset_y, w, h,pixmap,srcx,srcy);
+  Fl_Scaled_Xlib_Graphics_Driver::copy_offscreen(x+offset_x, y+offset_y, w, h,pixmap,srcx,srcy);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) {
-  Fl_Xlib_Graphics_Driver::push_clip(x+offset_x, y+offset_y, w, h);
+  Fl_Scaled_Xlib_Graphics_Driver::push_clip(x+offset_x, y+offset_y, w, h);
 }
 
 int Fl_Translated_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
-  return Fl_Xlib_Graphics_Driver::not_clipped(x + offset_x, y + offset_y, w, h);
+  return Fl_Scaled_Xlib_Graphics_Driver::not_clipped(x + offset_x, y + offset_y, w, h);
 }
 
 int Fl_Translated_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) {
-  int retval = Fl_Xlib_Graphics_Driver::clip_box(x + offset_x, y + offset_y, w,h,X,Y,W,H);
+  int retval = Fl_Scaled_Xlib_Graphics_Driver::clip_box(x + offset_x, y + offset_y, w,h,X,Y,W,H);
   X -= offset_x;
   Y -= offset_y;
   return retval;
@@ -168,31 +175,31 @@
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {
-  Fl_Xlib_Graphics_Driver::pie(x+offset_x,y+offset_y,w,h,a1,a2);
+  Fl_Scaled_Xlib_Graphics_Driver::pie(x+offset_x,y+offset_y,w,h,a1,a2);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
-  Fl_Xlib_Graphics_Driver::arc(x+offset_x,y+offset_y,w,h,a1,a2);
+  Fl_Scaled_Xlib_Graphics_Driver::arc(x+offset_x,y+offset_y,w,h,a1,a2);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
-  Fl_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
-  Fl_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
-  Fl_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
-  Fl_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y);
 }
 
 void Fl_Translated_Xlib_Graphics_Driver::point(int x, int y) {
-  Fl_Xlib_Graphics_Driver::point(x+offset_x, y+offset_y);
+  Fl_Scaled_Xlib_Graphics_Driver::point(x+offset_x, y+offset_y);
 }
 
 #endif // FL_DOXYGEN
Index: src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx	(revision 12029)
+++ src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx	(working copy)
@@ -30,6 +30,7 @@
   friend class Fl_Copy_Surface_Driver;
 protected:
   Fl_Offscreen xid;
+  int pixmap_w, pixmap_h;
   Window oldwindow;
   Fl_Surface_Device *_ss;
   Fl_Xlib_Copy_Surface_Driver(int w, int h);
@@ -51,9 +52,13 @@
 
 Fl_Xlib_Copy_Surface_Driver::Fl_Xlib_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
   driver(new Fl_Translated_Xlib_Graphics_Driver());
+  float s = Fl_Display_Device::display_device()->driver()->scale();
+  ((Fl_Translated_Xlib_Graphics_Driver*)driver())->pixel_scale(s);
   Fl::first_window()->make_current();
   oldwindow = fl_xid(Fl::first_window());
   xid = fl_create_offscreen(w,h);
+  pixmap_w = w * s;
+  pixmap_h = h * s;
   _ss = NULL;
   Fl_Surface_Device *present_surface = Fl_Surface_Device::surface();
   Fl_Surface_Device::set_current();
@@ -67,11 +72,12 @@
 
 Fl_Xlib_Copy_Surface_Driver::~Fl_Xlib_Copy_Surface_Driver() {
   fl_pop_clip();
-  unsigned char *data = fl_read_image(NULL,0,0,width,height,0);
+fl_window = xid;
+  Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
   fl_window = oldwindow;
   _ss->set_current();
-  Fl_X11_Screen_Driver::copy_image(data, width, height, 1);
-  delete[] data;
+  Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1);
+  delete rgb;
   fl_delete_offscreen(xid);
   delete driver();
 }
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(revision 12029)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(working copy)
@@ -1,8 +1,7 @@
 //
 // "$Id$"
 //
-// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
-// for the Fast Light Tool Kit (FLTK).
+// Definition of class Fl_Xlib_Graphics_Driver for the Fast Light Tool Kit (FLTK).
 //
 // Copyright 2010-2016 by Bill Spitzak and others.
 //
@@ -43,6 +42,11 @@
 };
 #endif // HAVE_X11_XREGION_H
 
+#if USE_PANGO
+#include <pango/pangoxft.h>
+#endif
+
+
 /**
  \brief The Xlib-specific graphics class.
  *
@@ -49,7 +53,21 @@
  This class is implemented only on the Xlib platform.
  */
 class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Graphics_Driver {
+#if USE_XFT
+  void drawUCS4(const void *str, int n, int x, int y);
+#endif
+#if USE_PANGO
+  friend class Fl_X11_Screen_Driver;
+  static PangoContext *pctxt_;
+  static PangoFontMap *pfmap_;
+  static PangoLayout *playout_;
 protected:
+  PangoFontDescription *pfd_;
+  void do_draw(int from_right, const char *str, int n, int x, int y);
+  static PangoContext *context();
+  static void init_built_in_fonts();
+#endif
+protected:
   static GC gc_;
   uchar **mask_bitmap_;
   uchar **mask_bitmap() {return mask_bitmap_;}
@@ -57,9 +75,13 @@
   int p_size;
   typedef struct {short x, y;} XPOINT;
   XPOINT *p;
+#if USE_XFT
+  static Window draw_window;
+  static struct _XftDraw* draw_;
+#endif
 public:
   Fl_Xlib_Graphics_Driver(void);
-  virtual ~Fl_Xlib_Graphics_Driver() { if (p) free(p); }
+  virtual ~Fl_Xlib_Graphics_Driver();
   virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
   virtual void *gc() { return gc_; }
   virtual void gc(void *value);
@@ -98,7 +120,7 @@
   Fl_Region XRectangleRegion(int x, int y, int w, int h);
   void XDestroyRegion(Fl_Region r);
 protected:
-  void transformed_vertex0(short x, short y);
+  virtual void transformed_vertex0(short x, short y);
   void fixloop();
   // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx
   void point(int x, int y);
@@ -157,6 +179,19 @@
   virtual const char *font_name(int num);
   virtual void font_name(int num, const char *name);
   virtual Fl_Font set_fonts(const char* xstarname);
+  // accessors to private image members
+  static void rgb_id(Fl_RGB_Image *rgb, fl_uintptr_t v) {rgb->id_ = v;}
+  static fl_uintptr_t rgb_id(Fl_RGB_Image *rgb) { return rgb->id_;}
+  static void bitmap_id(Fl_Bitmap *bm, fl_uintptr_t v) {bm->id_ = v;}
+  static fl_uintptr_t bitmap_id(Fl_Bitmap *bm) { return bm->id_;}
+  static fl_uintptr_t pixmap_id(Fl_Pixmap *pm) { return pm->id_; }
+  static fl_uintptr_t pixmap_mask(Fl_Pixmap *pm) { return pm->mask_; }
+  static void pixmap_id(Fl_Pixmap *pm, fl_uintptr_t value) {
+    pm->id_ = value;
+  }
+  static void pixmap_mask(Fl_Pixmap *pm, fl_uintptr_t mask) {
+    pm->mask_ = mask;
+  }
 };
 
 
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(revision 12029)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(working copy)
@@ -19,6 +19,7 @@
 
 #include "../../config_lib.h"
 #include "Fl_Xlib_Graphics_Driver.H"
+#include "Fl_Scaled_Xlib_Graphics_Driver.cxx"
 #include "Fl_Font.H"
 #include <FL/fl_draw.H>
 #include <FL/x.H>
@@ -41,7 +42,7 @@
  */
 Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
 {
-  return new Fl_Xlib_Graphics_Driver();
+  return new Fl_Scaled_Xlib_Graphics_Driver(1);
 }
 
 GC Fl_Xlib_Graphics_Driver::gc_ = NULL;
@@ -56,8 +57,20 @@
   mask_bitmap_ = NULL;
   p_size = 0;
   p = NULL;
+#if USE_PANGO
+  pfd_ = pango_font_description_new();
+  Fl_Graphics_Driver::font(0, 0);
+#endif
 }
 
+Fl_Xlib_Graphics_Driver::~Fl_Xlib_Graphics_Driver() {
+  if (p) free(p);
+#if USE_PANGO
+  pango_font_description_free(pfd_);
+#endif
+}
+
+
 void Fl_Xlib_Graphics_Driver::gc(void *value) {
   gc_ = (GC)value;
   fl_gc = gc_;
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(revision 12029)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(working copy)
@@ -16,7 +16,8 @@
 //     http://www.fltk.org/str.php
 //
 
-// Select fonts from the FLTK font table.
+#ifndef FL_DOXYGEN
+
 #include "../../flstring.h"
 #include "Fl_Xlib_Graphics_Driver.H"
 #include <FL/Fl.H>
@@ -26,46 +27,107 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <math.h>
 
 #include <X11/Xft/Xft.h>
+#include <X11/Xft/XftCompat.h>
 
-// This function fills in the fltk font table with all the fonts that
-// are found on the X server.  It tries to place the fonts into families
-// and to sort them so the first 4 in a family are normal, bold, italic,
-// and bold italic.
+#define USE_OVERLAY 0
 
-// Bug: older versions calculated the value for *ap as a side effect of
-// making the name, and then forgot about it. To avoid having to change
-// the header files I decided to store this value in the last character
-// of the font name array.
-#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+#if USE_OVERLAY
+// Currently Xft does not work with colormapped visuals, so this probably
+// does not work unless you have a true-color overlay.
+extern bool fl_overlay;
+extern Colormap fl_overlay_colormap;
+extern XVisualInfo* fl_overlay_visual;
+#endif
 
-#define USE_OVERLAY 0
+Fl_XFont_On_Demand fl_xfont = 0;
 
-// turn a stored font name in "fltk format" into a pretty name:
-const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
-  Fl_Fontdesc *f = fl_fonts + fnum;
-  if (!f->fontname[0]) {
-    const char* p = f->name;
-    int type;
-    switch (p[0]) {
-    case 'B': type = FL_BOLD; break;
-    case 'I': type = FL_ITALIC; break;
-    case 'P': type = FL_BOLD | FL_ITALIC; break;
-    default:  type = 0; break;
-    }
+static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle);
 
-  // NOTE: This can cause duplications in fonts that already have Bold or Italic in
-  // their "name". Maybe we need to find a cleverer way?
-    strlcpy(f->fontname, p+1, ENDOFBUFFER);
-    if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
-    if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
-    f->fontname[ENDOFBUFFER] = (char)type;
-  }
-  if (ap) *ap = f->fontname[ENDOFBUFFER];
-  return f->fontname;
-}
+// For some reason Xft produces errors if you destroy a window whose id
+// still exists in an XftDraw structure. It would be nice if this is not
+// true, a lot of junk is needed to try to stop this:
 
+XftDraw* Fl_Xlib_Graphics_Driver::draw_ = 0;
+Window Fl_Xlib_Graphics_Driver::draw_window = (Window)0;
+#if USE_OVERLAY
+static XftDraw* draw_overlay;
+static Window draw_overlay_window;
+#endif
+
+
+#if ! USE_PANGO
+
+// The predefined fonts that FLTK has:
+static Fl_Fontdesc built_in_table[] = {
+#if 1
+  {" sans"},
+  {"Bsans"},
+  {"Isans"},
+  {"Psans"},
+  {" mono"},
+  {"Bmono"},
+  {"Imono"},
+  {"Pmono"},
+  {" serif"},
+  {"Bserif"},
+  {"Iserif"},
+  {"Pserif"},
+  {" symbol"},
+  {" screen"},
+  {"Bscreen"},
+  {" zapf dingbats"},
+#else
+  {" helvetica"},
+  {"Bhelvetica"},
+  {"Ihelvetica"},
+  {"Phelvetica"},
+  {" courier"},
+  {"Bcourier"},
+  {"Icourier"},
+  {"Pcourier"},
+  {" times"},
+  {"Btimes"},
+  {"Itimes"},
+  {"Ptimes"},
+  {" symbol"},
+  {" lucidatypewriter"},
+  {"Blucidatypewriter"},
+  {" zapf dingbats"},
+#endif
+};
+
+#else
+
+// The predefined fonts that FLTK has with Pango:
+static Fl_Fontdesc built_in_table[] = {
+  {" Sans"},
+  {" Sans Bold"},
+  {" Sans Italic"},
+  {" Sans Bold Italic"},
+  {" Monospace"},
+  {" Monospace Bold"},
+  {" Monospace Italic"},
+  {" Monospace Bold Italic"},
+  {" Serif"},
+  {" Serif Bold"},
+  {" Serif Italic"},
+  {" Serif Bold Italic"},
+  {" Sans"},
+  {" Monospace"},
+  {" Monospace Bold"},
+  {" Sans"},
+};
+
+#endif // USE_PANGO
+
+Fl_Fontdesc* fl_fonts = built_in_table;
+
+
+#if ! USE_PANGO
+
 ///////////////////////////////////////////////////////////
 #define LOCAL_RAW_NAME_MAX 256
 
@@ -349,49 +411,9 @@
   }
   return (Fl_Font)fl_free_font;
 } // ::set_fonts
-////////////////////////////////////////////////////////////////
 
-
-extern "C" {
-static int int_sort(const void *aa, const void *bb) {
-  return (*(int*)aa)-(*(int*)bb);
-}
-}
-
 ////////////////////////////////////////////////////////////////
 
-// Return all the point sizes supported by this font:
-// Suprisingly enough Xft works exactly like fltk does and returns
-// the same list. Except there is no way to tell if the font is scalable.
-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_open_display();
-  XftFontSet* fs = XftListFonts(fl_display, fl_screen,
-                                XFT_FAMILY, XftTypeString, s->name+1,
-				(void *)0,
-                                XFT_PIXEL_SIZE,
-				(void *)0);
-  static int* array = 0;
-  static int array_size = 0;
-  if (fs->nfont >= array_size) {
-    delete[] array;
-    array = new int[array_size = fs->nfont+1];
-  }
-  array[0] = 0; int j = 1; // claim all fonts are scalable
-  for (int i = 0; i < fs->nfont; i++) {
-    double v;
-    if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) {
-      array[j++] = int(v);
-    }
-  }
-  qsort(array+1, j-1, sizeof(int), int_sort);
-  XftFontSetDestroy(fs);
-  sizep = array;
-  return j;
-}
-
 //
 // Draw fonts using Keith Packard's Xft library to provide anti-
 // aliased text. Yow!
@@ -428,92 +450,16 @@
 // itself. You should edit the ~/.xftconfig file to "fix" things, there
 // are several web pages of information on how to do this.
 //
-#ifndef FL_DOXYGEN
 
-#include <X11/Xft/Xft.h>
-
-#include <math.h>
-
-// The predefined fonts that FLTK has:
-static Fl_Fontdesc built_in_table[] = {
-#if 1
-{" sans"},
-{"Bsans"},
-{"Isans"},
-{"Psans"},
-{" mono"},
-{"Bmono"},
-{"Imono"},
-{"Pmono"},
-{" serif"},
-{"Bserif"},
-{"Iserif"},
-{"Pserif"},
-{" symbol"},
-{" screen"},
-{"Bscreen"},
-{" zapf dingbats"},
-#else
-{" helvetica"},
-{"Bhelvetica"},
-{"Ihelvetica"},
-{"Phelvetica"},
-{" courier"},
-{"Bcourier"},
-{"Icourier"},
-{"Pcourier"},
-{" times"},
-{"Btimes"},
-{"Itimes"},
-{"Ptimes"},
-{" symbol"},
-{" lucidatypewriter"},
-{"Blucidatypewriter"},
-{" zapf dingbats"},
-#endif
-};
-
-Fl_Fontdesc* fl_fonts = built_in_table;
-
-Fl_XFont_On_Demand fl_xfont;
-void *fl_xftfont = 0;
 //static const char* fl_encoding_ = "iso8859-1";
 static const char* fl_encoding_ = "iso10646-1";
 
-static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
-  if (fnum==-1) { // special case to stop font caching
-    driver->Fl_Graphics_Driver::font(0, 0);
-    return;
-  }
-  Fl_Font_Descriptor* f = driver->font_descriptor();
-  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && f && 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_))
-      break;
-  }
-  if (!f) {
-    f = new Fl_Font_Descriptor(font->name, size, angle);
-    f->next = font->first;
-    font->first = f;
-  }
-  driver->font_descriptor(f);
-#if XFT_MAJOR < 2
-  fl_xfont    = f->font->u.core.font;
-#else
-  fl_xfont    = NULL; // invalidate
-#endif // XFT_MAJOR < 2
-  fl_xftfont = (void*)f->font;
-}
 
 void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
   fl_xft_font(this,fnum,size,0);
 }
 
-static XftFont* fontopen(const char* name, Fl_Fontsize size, bool core, int angle) {
+static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core, int angle) {
   // Check: does it look like we have been passed an old-school XLFD fontname?
   bool is_xlfd = false;
   int hyphen_count = 0;
@@ -710,10 +656,6 @@
   font = fontopen(name, fsize, false, angle);
 }
 
-Fl_Font_Descriptor::~Fl_Font_Descriptor() {
-  if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
-//  XftFontClose(fl_display, font);
-}
 
 /* decodes the input UTF-8 string into a series of wchar_t characters.
  n is set upon return to the number of characters.
@@ -766,10 +708,6 @@
   return i.xOff;
 }
 
-/*double fl_width(uchar c) {
-  return fl_graphics_driver->width((const char *)(&c), 1);
-}*/
-
 static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) {
   if (!desc) return -1.0;
   XGlyphInfo i;
@@ -797,14 +735,277 @@
 } // fl_text_extents
 
 
+void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
+  if ( !this->font_descriptor() ) {
+    this->font(FL_HELVETICA, FL_NORMAL_SIZE);
+  }
+#if USE_OVERLAY
+  XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
+  if (fl_overlay) {
+    if (!draw_)
+      draw_ = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
+			   fl_overlay_visual->visual, fl_overlay_colormap);
+    else //if (draw_overlay_window != fl_window)
+      XftDrawChange(draw_, draw_overlay_window = fl_window);
+  } else
+#endif
+  if (!draw_)
+    draw_ = XftDrawCreate(fl_display, draw_window = fl_window,
+			 fl_visual->visual, fl_colormap);
+  else //if (draw_window != fl_window)
+    XftDrawChange(draw_, draw_window = fl_window);
+
+  Region region = fl_clip_region();
+  if (region && XEmptyRegion(region)) return;
+  XftDrawSetClip(draw_, region);
+
+  // Use fltk's color allocator, copy the results to match what
+  // XftCollorAllocValue returns:
+  XftColor color;
+  color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
+  uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
+  color.color.red   = ((int)r)*0x101;
+  color.color.green = ((int)g)*0x101;
+  color.color.blue  = ((int)b)*0x101;
+  color.color.alpha = 0xffff;
+
+  const wchar_t *buffer = utf8reformat(str, n);
+#ifdef __CYGWIN__
+  XftDrawString16(draw_, &color, font_descriptor()->font, x, y, (XftChar16 *)buffer, n);
+#else
+  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
+#endif
+}
+
+void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
+  this->draw(str, n, (int)x, (int)y);
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), 0);
+}
+
+void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
+#if USE_OVERLAY
+  XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
+  if (fl_overlay) {
+    if (!draw_)
+      draw_ = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
+			   fl_overlay_visual->visual, fl_overlay_colormap);
+    else //if (draw_overlay_window != fl_window)
+      XftDrawChange(draw_, draw_overlay_window = fl_window);
+  } else
+#endif
+  if (!draw_)
+    draw_ = XftDrawCreate(fl_display, draw_window = fl_window,
+			 fl_visual->visual, fl_colormap);
+  else //if (draw_window != fl_window)
+    XftDrawChange(draw_, draw_window = fl_window);
+
+  Region region = fl_clip_region();
+  if (region && XEmptyRegion(region)) return;
+  XftDrawSetClip(draw_, region);
+
+  // Use fltk's color allocator, copy the results to match what
+  // XftCollorAllocValue returns:
+  XftColor color;
+  color.pixel = fl_xpixel(this->color());
+  uchar r,g,b; Fl::get_color(this->color(), r,g,b);
+  color.color.red   = ((int)r)*0x101;
+  color.color.green = ((int)g)*0x101;
+  color.color.blue  = ((int)b)*0x101;
+  color.color.alpha = 0xffff;
+
+  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (FcChar32 *)str, n);
+}
+
+
+void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+
+#if defined(__GNUC__)
+// FIXME: warning Need to improve this XFT right to left draw function
+#endif /*__GNUC__*/
+
+// This actually draws LtoR, but aligned to R edge with the glyph order reversed...
+// but you can't just byte-rev a UTF-8 string, that isn't valid.
+// You can reverse a UCS4 string though...
+  int num_chars, wid, utf_len = strlen(c);
+  FcChar8 *u8 = (FcChar8 *)c;
+  FcBool valid = FcUtf8Len(u8, utf_len, &num_chars, &wid);
+  if (!valid)
+  {
+    // badly formed Utf-8 input string
+    return;
+  }
+  if (num_chars < n) n = num_chars; // limit drawing to usable characters in input array
+  FcChar32 *ucs_txt = new FcChar32[n+1];
+  FcChar32* pu;
+  int out, sz;
+  ucs_txt[n] = 0;
+  out = n-1;
+  while ((out >= 0) && (utf_len > 0))
+  {
+    pu = &ucs_txt[out];
+    sz = FcUtf8ToUcs4(u8, pu, utf_len);
+    utf_len = utf_len - sz;
+    u8 = u8 + sz;
+    out = out - 1;
+  }
+  // Now we have a UCS4 version of the input text, reversed, in ucs_txt
+  int offs = (int)fl_xft_width(font_descriptor(), ucs_txt, n);
+  drawUCS4(ucs_txt, n, (x-offs), y);
+
+  delete[] ucs_txt;
+}
+
+
+extern "C" {
+  static int int_sort(const void *aa, const void *bb) {
+    return (*(int*)aa)-(*(int*)bb);
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// Return all the point sizes supported by this font:
+// Suprisingly enough Xft works exactly like fltk does and returns
+// the same list. Except there is no way to tell if the font is scalable.
+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_open_display();
+  XftFontSet* fs = XftListFonts(fl_display, fl_screen,
+                                XFT_FAMILY, XftTypeString, s->name+1,
+                                (void *)0,
+                                XFT_PIXEL_SIZE,
+                                (void *)0);
+  static int* array = 0;
+  static int array_size = 0;
+  if (fs->nfont >= array_size) {
+    delete[] array;
+    array = new int[array_size = fs->nfont+1];
+  }
+  array[0] = 0; int j = 1; // claim all fonts are scalable
+  for (int i = 0; i < fs->nfont; i++) {
+    double v;
+    if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) {
+      array[j++] = int(v);
+    }
+  }
+  qsort(array+1, j-1, sizeof(int), int_sort);
+  XftFontSetDestroy(fs);
+  sizep = array;
+  return j;
+}
+
+#endif // !USE_PANGO
+
+float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
+  // Xft font height is sometimes larger than the required size (see STR 2566).
+  // Increase the PostScript font size by 15% without exceeding the display font height
+  int max = height();
+  float ps_size = s * 1.15;
+  if (ps_size > max) ps_size = max;
+  return ps_size;
+}
+
+
+// This function fills in the fltk font table with all the fonts that
+// are found on the X server.  It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+// Bug: older versions calculated the value for *ap as a side effect of
+// making the name, and then forgot about it. To avoid having to change
+// the header files I decided to store this value in the last character
+// of the font name array.
+#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+
+
+// turn a stored font name in "fltk format" into a pretty name:
+const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
+  Fl_Fontdesc *f = fl_fonts + fnum;
+  if (!f->fontname[0]) {
+    const char* p = f->name;
+    int type;
+    switch (p[0]) {
+      case 'B': type = FL_BOLD; break;
+      case 'I': type = FL_ITALIC; break;
+      case 'P': type = FL_BOLD | FL_ITALIC; break;
+      default:  type = 0; break;
+    }
+    
+    // NOTE: This can cause duplications in fonts that already have Bold or Italic in
+    // their "name". Maybe we need to find a cleverer way?
+    strlcpy(f->fontname, p+1, ENDOFBUFFER);
+    if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
+    if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
+    f->fontname[ENDOFBUFFER] = (char)type;
+  }
+  if (ap) *ap = f->fontname[ENDOFBUFFER];
+  return f->fontname;
+}
+
+
+float Fl_Xlib_Graphics_Driver::scale_bitmap_for_PostScript() {
+  return 2;
+}
+
+Fl_Font_Descriptor::~Fl_Font_Descriptor() {
+  if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
+  //  XftFontClose(fl_display, font);
+}
+
+
+void Fl_Xlib_Graphics_Driver::destroy_xft_draw(Window id) {
+  if (id == draw_window)
+    XftDrawChange(draw_, draw_window = fl_message_window);
+#if USE_OVERLAY
+  if (id == draw_overlay_window)
+    XftDrawChange(draw_overlay, draw_overlay_window = fl_message_window);
+#endif
+}
+
+void *fl_xftfont = 0; // always 0 under Pango
+static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
+  if (fnum==-1) { // special case to stop font caching
+    driver->Fl_Graphics_Driver::font(0, 0);
+    return;
+  }
+  Fl_Font_Descriptor* f = driver->font_descriptor();
+  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && f && 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_))
+      break;
+  }
+  if (!f) {
+    f = new Fl_Font_Descriptor(font->name, size, angle);
+    f->next = font->first;
+    font->first = f;
+  }
+  driver->font_descriptor(f);
+#if XFT_MAJOR < 2 && ! USE_PANGO
+  fl_xfont    = f->font->u.core.font;
+#else
+  fl_xfont    = NULL; // invalidate
+#endif // XFT_MAJOR < 2
+#if USE_PANGO
+  fl_xftfont = NULL;
+#else
+  fl_xftfont = (void*)f->font;
+#endif
+}
+
 /* This code is used (mainly by opengl) to get a bitmapped font. The
  * original XFT-1 code used XFT's "core" fonts methods to load an XFT
  * font that was actually a X-bitmap font, that could then be readily
  * used with GL.  But XFT-2 does not provide that ability, and there
  * is no easy method to use an XFT font directly with GL. So...
-*/
-
-#  if XFT_MAJOR > 1
+ */
+#  if XFT_MAJOR > 1 || USE_PANGO
 // This function attempts, on XFT2 systems, to find a suitable "core" Xfont
 // for GL or other bitmap font needs (we dont have an XglUseXftFont(...) function.)
 // There's probably a better way to do this. I can't believe it is this hard...
@@ -828,14 +1029,30 @@
   char slant = 'r';   // regular non-italic by default
   char xlfd[128];     // we will put our synthetic XLFD in here
   char *pc = strdup(fl_fonts[fnum].name); // what font were we asked for?
+#if USE_PANGO
+  char *p = pc;
+  while (*p) { *p = tolower(*p); p++; }
+  p = pc + strlen(pc) - 12;
+  if (memcmp(p, " bold italic\0", 13) == 0) {
+    *pc = 'P'; *p = 0;
+  }
+  p = pc + strlen(pc) - 5;
+  if (memcmp(p, " bold\0", 6) == 0) {
+    *pc = 'B'; *p = 0;
+  }
+  p = pc + strlen(pc) - 7;
+  if (memcmp(p, " italic\0", 8) == 0) {
+    *pc = 'I'; *p = 0;
+  }
+#endif // USE_PANGO
   const char *name = pc;    // keep a handle to the original name for freeing later
   // Parse the "fltk-name" of the font
   switch (*name++) {
-  case 'I': slant = 'i'; break;       // italic
-  case 'P': slant = 'i';              // bold-italic (falls-through)
-  case 'B': weight = wt_bold; break;  // bold
-  case ' ': break;                    // regular
-  default: name--;                    // no prefix, restore name
+    case 'I': slant = 'i'; break;       // italic
+    case 'P': slant = 'i';              // bold-italic (falls-through)
+    case 'B': weight = wt_bold; break;  // bold
+    case ' ': break;                    // regular
+    default: name--;                    // no prefix, restore name
   }
 
   // first, we do a query with no prefered size, to see if the font exists at all
@@ -852,7 +1069,8 @@
   if (!xgl_font) {
     if (!strcmp(name, "sans")) {
       name = "helvetica";
-    } else if (!strcmp(name, "mono")) {
+      if (slant == 'i') slant = 'o';
+    } else if (!strcmp(name, "mono") || !strcmp(name, "monospace")) {
       name = "courier";
     } else if (!strcmp(name, "serif")) {
       name = "times";
@@ -887,7 +1105,7 @@
 #  endif
 
 static XFontStruct* fl_xxfont(Fl_Graphics_Driver *driver) {
-#  if XFT_MAJOR > 1
+#  if XFT_MAJOR > 1 || USE_PANGO
   // kludge! XFT 2 and later does not provide core fonts for us to use with GL
   // try to load a bitmap X font instead
   static XFontStruct* xgl_font = 0;
@@ -905,7 +1123,7 @@
 #  else // XFT-1 provides a means to load a "core" font directly
   if (driver->font_descriptor()->font->core) {
     return driver->font_descriptor()->font->u.core.font; // is the current font a "core" font? If so, use it.
-    }
+  }
   static XftFont* xftfont;
   if (xftfont) XftFontClose (fl_display, xftfont);
   xftfont = fontopen(fl_fonts[driver->font()].name, driver->size(), true, 0); // else request XFT to load a suitable "core" font instead.
@@ -918,168 +1136,223 @@
   return ptr;
 }
 
-#if USE_OVERLAY
-// Currently Xft does not work with colormapped visuals, so this probably
-// does not work unless you have a true-color overlay.
-extern bool fl_overlay;
-extern Colormap fl_overlay_colormap;
-extern XVisualInfo* fl_overlay_visual;
+#if USE_PANGO
+
+#include <pango/pangoxft.h>
+#include <pango/pango.h>
+#if ! PANGO_VERSION_CHECK(1,8,0)
+#error "Requires Pango 1.8 or higher"
 #endif
 
-// For some reason Xft produces errors if you destroy a window whose id
-// still exists in an XftDraw structure. It would be nice if this is not
-// true, a lot of junk is needed to try to stop this:
+PangoFontMap *Fl_Xlib_Graphics_Driver::pfmap_ = 0;
+PangoContext *Fl_Xlib_Graphics_Driver::pctxt_ = 0;
+PangoLayout *Fl_Xlib_Graphics_Driver::playout_ = 0;
 
-static XftDraw* draw_;
-static Window draw_window;
-#if USE_OVERLAY
-static XftDraw* draw_overlay;
-static Window draw_overlay_window;
+PangoContext *Fl_Xlib_Graphics_Driver::context() {
+  if (fl_display && !pctxt_) {
+    pfmap_ = pango_xft_get_font_map(fl_display, fl_screen); // 1.2
+#if PANGO_VERSION_CHECK(1,22,0)
+    pctxt_ = pango_font_map_create_context(pfmap_); // 1.22
+#else
+    pctxt_ = pango_xft_get_context(fl_display, fl_screen); // deprecated since 1.22
 #endif
+    playout_ = pango_layout_new(pctxt_);
+  }
+  return pctxt_;
+}
 
-void Fl_Xlib_Graphics_Driver::destroy_xft_draw(Window id) {
-  if (id == draw_window)
-    XftDrawChange(draw_, draw_window = fl_message_window);
-#if USE_OVERLAY
-  if (id == draw_overlay_window)
-    XftDrawChange(draw_overlay, draw_overlay_window = fl_message_window);
-#endif
+void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+  if (!size) return;
+  if (this->Fl_Graphics_Driver::font() == fnum && this->size() == size) return;
+  fl_xft_font(this, fnum, size, 0);
+  init_built_in_fonts();
+  if (pfd_) pango_font_description_free(pfd_);
+  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();
+  if (!fd->height_) {
+    PangoFont *pfont = pango_font_map_load_font(pfmap_, pctxt_, pfd_);
+    PangoRectangle ink_rect, logical_rect;
+    pango_font_get_glyph_extents(pfont, /*PangoGlyph glyph*/'p', &ink_rect, &logical_rect);
+    fd->descent_ = PANGO_DESCENT(logical_rect)/PANGO_SCALE;
+    fd->height_ = logical_rect.height/PANGO_SCALE;
+  }
 }
 
 void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
-  if ( !this->font_descriptor() ) {
-    this->font(FL_HELVETICA, FL_NORMAL_SIZE);
-  }
-#if USE_OVERLAY
-  XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
-  if (fl_overlay) {
-    if (!draw_)
-      draw_ = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
-			   fl_overlay_visual->visual, fl_overlay_colormap);
-    else //if (draw_overlay_window != fl_window)
-      XftDrawChange(draw_, draw_overlay_window = fl_window);
-  } else
-#endif
-  if (!draw_)
-    draw_ = XftDrawCreate(fl_display, draw_window = fl_window,
-			 fl_visual->visual, fl_colormap);
-  else //if (draw_window != fl_window)
-    XftDrawChange(draw_, draw_window = fl_window);
+  do_draw(0, str, n, x, y);
+}
 
-  Region region = fl_clip_region();
+void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+  PangoMatrix mat = PANGO_MATRIX_INIT; // 1.6
+  pango_matrix_translate(&mat, x, y); // 1.6
+  pango_matrix_rotate(&mat, angle); // 1.6
+  pango_context_set_matrix(pctxt_, &mat); // 1.6
+  do_draw(0, str, n, 0, 0);
+  pango_context_set_matrix(pctxt_, NULL); // 1.6
+}
+
+void Fl_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
+  do_draw(1, str, n, x, y);
+}
+
+void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, int x, int y) {
+  if (!fl_display || n == 0) return;
+  Region region = clip_region();
   if (region && XEmptyRegion(region)) return;
-  XftDrawSetClip(draw_, region);
-
-  // Use fltk's color allocator, copy the results to match what
-  // XftCollorAllocValue returns:
+  if (!playout_) context();
+  
+  char *str2 = NULL;
+  const char *tmpv = (const char *)memchr(str, '\n', n);
+  if (tmpv == str + n - 1) { // ignore final '\n'
+    if (--n == 0) return;
+    tmpv = NULL;
+  }
+  pango_layout_set_font_description(playout_, pfd_);
+  if (tmpv) { // replace newlines by spaces in a copy of str
+    str2 = (char*)malloc(n);
+    memcpy(str2, str, n);
+    do {
+      str2[tmpv - str] = ' ';
+      if (tmpv >= str + n - 1) break;
+      tmpv = (const char *)memchr(tmpv + 1, '\n', n - (tmpv - str + 1));
+    }
+    while (tmpv);
+    str = str2;
+  }
+  const char *old = 0;
+  if (!str2) old = pango_layout_get_text(playout_);
+  if (!old || strlen(old) != n || memcmp(str, old, n)) // do not re-set text if equal to text already in layout
+        pango_layout_set_text(playout_, str, n);
+  if (str2) free(str2);
+  
   XftColor color;
-  color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
-  uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
+  Fl_Color c = this->color();
+  color.pixel = fl_xpixel(c);
+  uchar r,g,b; Fl::get_color(c, r,g,b);
   color.color.red   = ((int)r)*0x101;
   color.color.green = ((int)g)*0x101;
   color.color.blue  = ((int)b)*0x101;
   color.color.alpha = 0xffff;
+  if (from_right) {
+    int width, height;
+    pango_layout_get_pixel_size(playout_, &width, &height);
+    x -= width;
+  }
+  if (!draw_)
+    draw_ = XftDrawCreate(fl_display, draw_window = fl_window, fl_visual->visual, fl_colormap);
+  else
+    XftDrawChange(draw_, draw_window = fl_window);
+  XftDrawSetClip(draw_, region);
+  pango_xft_render_layout(draw_, &color, playout_, x*PANGO_SCALE, (y-height()+descent())*PANGO_SCALE ); // 1.8
+}
 
-  const wchar_t *buffer = utf8reformat(str, n);
-#ifdef __CYGWIN__
-  XftDrawString16(draw_, &color, font_descriptor()->font, x, y, (XftChar16 *)buffer, n);
-#else
-  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
-#endif
+double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+  if (!n) return 0;
+  if (!fl_display || fl_size() == 0) return -1;
+  if (!playout_) context();
+  int width, height;
+  pango_layout_set_font_description(playout_, pfd_);
+  pango_layout_set_text(playout_, str, n);
+  pango_layout_get_pixel_size(playout_, &width, &height);
+  return (double)width;
 }
 
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
-  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
-  this->draw(str, n, (int)x, (int)y);
-  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), 0);
+void Fl_Xlib_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
+  if (!playout_) context();
+  pango_layout_set_font_description(playout_, pfd_);
+  pango_layout_set_text(playout_, str, n);
+  PangoRectangle ink_rect, logical_rect;
+  pango_layout_get_pixel_extents(playout_, &ink_rect, &logical_rect);
+  dx = ink_rect.x;
+  dy = ink_rect.y - height() + descent();
+  w = ink_rect.width;
+  h = ink_rect.height;
 }
 
-static void fl_drawUCS4(Fl_Graphics_Driver *driver, const FcChar32 *str, int n, int x, int y) {
-#if USE_OVERLAY
-  XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
-  if (fl_overlay) {
-    if (!draw_)
-      draw_ = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
-			   fl_overlay_visual->visual, fl_overlay_colormap);
-    else //if (draw_overlay_window != fl_window)
-      XftDrawChange(draw_, draw_overlay_window = fl_window);
-  } else
-#endif
-  if (!draw_)
-    draw_ = XftDrawCreate(fl_display, draw_window = fl_window,
-			 fl_visual->visual, fl_colormap);
-  else //if (draw_window != fl_window)
-    XftDrawChange(draw_, draw_window = fl_window);
+int Fl_Xlib_Graphics_Driver::height() {
+  return font_descriptor()->height_;
+}
 
-  Region region = fl_clip_region();
-  if (region && XEmptyRegion(region)) return;
-  XftDrawSetClip(draw_, region);
+double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+  char buf4[4];
+  int n = fl_utf8encode(c, buf4);
+  return width(buf4, n);
+}
 
-  // Use fltk's color allocator, copy the results to match what
-  // XftCollorAllocValue returns:
-  XftColor color;
-  color.pixel = fl_xpixel(driver->color());
-  uchar r,g,b; Fl::get_color(driver->color(), r,g,b);
-  color.color.red   = ((int)r)*0x101;
-  color.color.green = ((int)g)*0x101;
-  color.color.blue  = ((int)b)*0x101;
-  color.color.alpha = 0xffff;
+int Fl_Xlib_Graphics_Driver::descent() {
+  return font_descriptor()->descent_;
+}
 
-  XftDrawString32(draw_, &color, driver->font_descriptor()->font, x, y, (FcChar32 *)str, n);
+typedef int (*sort_f_type)(const void *aa, const void *bb);
+
+static int font_sort(Fl_Fontdesc *fa, Fl_Fontdesc *fb) {
+  return strcmp(fa->name, fb->name);
 }
 
+Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* pattern_name)
+{
+  fl_open_display();
+  int n_families, count = 0;
+  PangoFontFamily **families;
+  Fl_Xlib_Graphics_Driver::context();
+  Fl_Xlib_Graphics_Driver::init_built_in_fonts();
+  pango_font_map_list_families(Fl_Xlib_Graphics_Driver::pfmap_, &families, &n_families);
+  for (int fam = 0; fam < n_families; fam++) {
+    PangoFontFace **faces;
+    int n_faces;
+    const char *fam_name = pango_font_family_get_name (families[fam]);
+    int l = strlen(fam_name);
+    pango_font_family_list_faces(families[fam], &faces, &n_faces);
+    for (int j = 0; j < n_faces; j++) {
+      const char *p =  pango_font_face_get_face_name(faces[j]);
+      if (strcmp(p, "Regular") == 0) p = NULL;
+      int lq = l+2;
+      if (p) lq += strlen(p) + 1;
+      char *q = new char[lq];
+      sprintf(q, " %s", fam_name);
+      if (p) sprintf(q + strlen(q), " %s", p);
+      // at this point, q contains " family-name[ face-name-except-Regular]"
+      Fl::set_font((Fl_Font)(count++ + FL_FREE_FONT), q);
+    }
+    /*g_*/free(faces); // glib source code shows that g_free is equivalent to free
+  }
+  /*g_*/free(families);
+  // Sort the list into alphabetic order
+  qsort(fl_fonts + FL_FREE_FONT, count, sizeof(Fl_Fontdesc), (sort_f_type)font_sort);
+  return FL_FREE_FONT + count;
+}
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
 
-#if defined(__GNUC__)
-// FIXME: warning Need to improve this XFT right to left draw function
-#endif /*__GNUC__*/
-
-// This actually draws LtoR, but aligned to R edge with the glyph order reversed...
-// but you can't just byte-rev a UTF-8 string, that isn't valid.
-// You can reverse a UCS4 string though...
-  int num_chars, wid, utf_len = strlen(c);
-  FcChar8 *u8 = (FcChar8 *)c;
-  FcBool valid = FcUtf8Len(u8, utf_len, &num_chars, &wid);
-  if (!valid)
-  {
-    // badly formed Utf-8 input string
-    return;
+void Fl_Xlib_Graphics_Driver::init_built_in_fonts() {
+  static int i = 0;
+  while (i < FL_FREE_FONT) {
+    Fl::set_font((Fl_Font)i, built_in_table[i].name);
+    i++;
   }
-  if (num_chars < n) n = num_chars; // limit drawing to usable characters in input array
-  FcChar32 *ucs_txt = new FcChar32[n+1];
-  FcChar32* pu;
-  int out, sz;
-  ucs_txt[n] = 0;
-  out = n-1;
-  while ((out >= 0) && (utf_len > 0))
-  {
-    pu = &ucs_txt[out];
-    sz = FcUtf8ToUcs4(u8, pu, utf_len);
-    utf_len = utf_len - sz;
-    u8 = u8 + sz;
-    out = out - 1;
-  }
-  // Now we have a UCS4 version of the input text, reversed, in ucs_txt
-  int offs = (int)fl_xft_width(font_descriptor(), ucs_txt, n);
-  fl_drawUCS4(this, ucs_txt, n, (x-offs), y);
-
-  delete[] ucs_txt;
 }
 
-float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
-  // Xft font height is sometimes larger than the required size (see STR 2566).
-  // Increase the PostScript font size by 15% without exceeding the display font height
-  int max = desc->font->height;
-  float ps_size = s * 1.15;
-  if (ps_size > max) ps_size = max;
-  return ps_size;
+
+int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
+  static int array[1] = {0};
+  sizep = array;
+  return 1;
 }
 
-float Fl_Xlib_Graphics_Driver::scale_bitmap_for_PostScript() {
-  return 2;
+Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) {
+  fl_open_display();
+  size = fsize;
+  angle = fangle;
+#if HAVE_GL
+  listbase = 0;
+#endif // HAVE_GL
+  height_ = 0;
+  descent_ = 0;
 }
 
+#endif // USE_PANGO
+
 #endif // FL_DOXYGEN
 
 //
Index: src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(revision 12029)
+++ src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(working copy)
@@ -24,9 +24,12 @@
 #include "Fl_Xlib_Graphics_Driver.H"
 #include <FL/Fl_Image_Surface.H>
 #include "Fl_Translated_Xlib_Graphics_Driver.H"
+#include <FL/Fl_Screen_Driver.H>
 
 class Fl_Xlib_Image_Surface_Driver : public Fl_Image_Surface_Driver {
   friend class Fl_Image_Surface;
+protected:
+  int pixmap_w, pixmap_h;
 public:
   Fl_Surface_Device *previous;
   Window pre_window;
@@ -47,11 +50,20 @@
 
 Fl_Xlib_Image_Surface_Driver::Fl_Xlib_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
   previous = 0;
+  float d = 1;
   if (!off) {
     fl_open_display();
+    d = fl_graphics_driver->scale();
+    if (d != 1) {
+      w = int(w*d);
+      h = int(h*d);
+    }
+    pixmap_w = w;
+    pixmap_h = h;
     offscreen = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth);
   }
   driver(new Fl_Translated_Xlib_Graphics_Driver());
+  if (d != 1) ((Fl_Translated_Xlib_Graphics_Driver*)driver())->pixel_scale(d);
 }
 
 Fl_Xlib_Image_Surface_Driver::~Fl_Xlib_Image_Surface_Driver() {
@@ -77,10 +89,8 @@
 
 Fl_RGB_Image* Fl_Xlib_Image_Surface_Driver::image()
 {
-  unsigned char *data = fl_read_image(NULL, 0, 0, width, height, 0);
+  Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
   end_current();
-  Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height);
-  image->alloc_array = 1;
   return image;
 }
 
