Index: FL/Fl_Gl_Window_Driver.H
===================================================================
--- FL/Fl_Gl_Window_Driver.H	(revision 12157)
+++ 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 12157)
+++ 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);
+  }
   // Support function for image drawing
   virtual void uncache_pixmap(fl_uintptr_t p);
   // accessor functions to protected image members
@@ -213,8 +217,6 @@
   virtual void pop_matrix();
   virtual void mult_matrix(double a, double b, double c, double d, double x, double y);
   virtual void rotate(double d);
-  virtual void scale(double x, double y);
-  virtual void scale(double x);
   virtual void translate(double x,double y);
   virtual void begin_points();
   virtual void begin_line();
@@ -344,6 +346,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_draw.H
===================================================================
--- FL/fl_draw.H	(revision 12157)
+++ FL/fl_draw.H	(working copy)
@@ -335,12 +335,16 @@
  Concatenates scaling transformation onto the current one.
  \param[in] x,y scale factors in x-direction and y-direction
  */
-inline void fl_scale(double x, double y) { fl_graphics_driver->scale(x, y); }
+inline void fl_scale(double x, double y) {
+  fl_graphics_driver->mult_matrix(x,0,0,y,0,0);
+}
 /**
  Concatenates scaling transformation onto the current one.
  \param[in] x scale factor in both x-direction and y-direction
  */
-inline void fl_scale(double x) { fl_graphics_driver->scale(x, x); }
+inline void fl_scale(double x) {
+  fl_graphics_driver->mult_matrix(x,0,0,x,0,0);
+}
 /**
  Concatenates translation transformation onto the current one.
  \param[in] x,y translation factor in x-direction and y-direction
Index: documentation/src/osissues.dox
===================================================================
--- documentation/src/osissues.dox	(revision 12157)
+++ 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/Fl_Gl_Window.cxx
===================================================================
--- src/Fl_Gl_Window.cxx	(revision 12166)
+++ src/Fl_Gl_Window.cxx	(working copy)
@@ -647,6 +647,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)
 {
@@ -658,6 +659,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 12157)
+++ 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"
@@ -91,7 +92,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,9 @@
    */
 Fl_Offscreen fl_create_offscreen(int w, int h) {
   int rank = find_slot();
-  offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, 0);
+  float d = Fl_Display_Device::display_device()->driver()->scale();
+  int 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 12157)
+++ src/Fl_Screen_Driver.cxx	(working copy)
@@ -268,7 +268,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_Shared_Image.cxx
===================================================================
--- src/Fl_Shared_Image.cxx	(revision 12157)
+++ src/Fl_Shared_Image.cxx	(working copy)
@@ -379,7 +379,7 @@
   }
   // don't call Fl_Graphics_Driver::draw_scaled(Fl_Image*,...) for an enlarged Fl_Bitmap or Fl_Pixmap
   if (shared->image_->as_rgb_image() || (shared->w() <= shared->image_->w() && shared->h() <= shared->image_->h())) {
-    int done = fl_graphics_driver->draw_scaled(shared->image_, X, Y, shared->w(), shared->h());
+    int done = draw_scaled(shared->image_, X, Y, shared->w(), shared->h());
     if (done) return;
   }
   if (shared->scaled_image_ && (shared->scaled_image_->w() != shared->w() || shared->scaled_image_->h() != shared->h())) {
@@ -401,7 +401,7 @@
  This can be useful to draw a shared image on a drawing surface whose resolution is higher
  than the drawing unit for this surface: all pixels of the original image become available to fill
  an area of the drawing surface sized at <tt>width,height</tt>.
- Examples of such drawing surfaces: laser printers, PostScript files, PDF printers, retina displays on Apple hardware.
+ Examples of such drawing surfaces: laser printers, PostScript files, PDF printers, HiDPI displays.
 
  \param width,height   maximum width and height (in drawing units) to use when drawing the shared image
  \param proportional   if not null, keep the width and height of the shared image proportional to those of its original image
@@ -413,7 +413,7 @@
  \code
  Fl_Box *b = ...  // a box
  Fl_Shared_Image *shared = Fl_Shared_Image::get("/path/to/picture.jpeg"); // read a picture file
- shared->scale(b->w(), b->h(), 1); // set the drawing size of the shared image to the size of the box
+ shared->scale(b->w(), b->h()); // set the drawing size of the shared image to the size of the box
  b->image(shared); // use the shared image as the box image
  b->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP); // the image is to be drawn centered in the box
  \endcode
Index: src/Fl_Widget_Surface.cxx
===================================================================
--- src/Fl_Widget_Surface.cxx	(revision 12157)
+++ src/Fl_Widget_Surface.cxx	(working copy)
@@ -22,6 +22,7 @@
 #include <FL/x.H>
 #include <FL/Fl_Shared_Image.H>
 #include <FL/Fl_Window_Driver.H>
+#include <FL/Fl_Screen_Driver.H>
 
 
 /** The constructor.
@@ -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 12157)
+++ 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,166 @@
   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 or FreeBSD and when the gnome scaling value has been found
+ 
+ Ubuntu:
+ Change the gnome scaling factor with:
+    System Settings ==> Displays ==> Scale for menu and title bars
+ Read the current gnome scaling factor with:
+    gsettings get com.ubuntu.user-interface scale-factor
+ Example value: {'VGA-0': 10}
+ Its type is "a{si}". This value should be divided by 8 to get the correct scaling factor.
+ 
+ Debian or FreeBSD :
+ Change the gnome scaling factor with:
+    Tweak tools ==> Windows ==> Window scaling
+ Read the current gnome scaling factor with:
+    gsettings get org.gnome.settings-daemon.plugins.xsettings overrides
+ Example value: {'Gdk/WindowScalingFactor': <2>}
+ Its type is "a{sv}" and v itself is of type i
+
+*/
+static bool gnome_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*);
+  //typedef void* (*g_variant_get_type_ftype)(void *variant);
+  
+  enum {debian, ubuntu, freebsd} os_type;
+  // determine whether we run Ubuntu or Debian or FreeBSD
+  char line[400] = "";
+  FILE *in = fopen("/proc/version", "r");
+  if (in) {
+    fgets(line, sizeof(line), in);
+    fclose(in);
+  } else {
+    FILE *pipe = popen("uname -a", "r");
+    fgets(line, sizeof(line), pipe);
+    pclose(pipe);
+  }
+  if (strstr(line, "Ubuntu")) os_type = ubuntu;
+  else if(strstr(line, "Debian")) os_type = debian;
+  else if (strstr(line, "FreeBSD")) os_type = freebsd;
+  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);
+  //fprintf(stderr,"glib=%p gio=%p gobj=%p\n",glib,gio,gobj);
+  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
+  //g_variant_get_type_ftype g_variant_get_type_f = (g_variant_get_type_ftype)dlsym(glib, "g_variant_get_type"); // 2.24
+  
+  // call dynamic lib functions
+  const char **known = g_settings_list_schemas_f(); // list of available GSettings schemas
+  const char *schema; 
+  if (os_type == ubuntu ) schema = "com.ubuntu.user-interface";
+  else schema = "org.gnome.settings-daemon.plugins.xsettings";
+  if (!is_schema_valid(schema, known)) return false;
+  void *gset = g_settings_new_f(schema);
+  const char *key;
+  if (os_type == ubuntu ) key = "scale-factor";
+  else key = "overrides";
+
+  void *gvar = g_settings_get_value_f(gset, key);
+  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("Ubuntu name=%s value=%d factor=%g\n", str, v, factor);
+    }
+    g_variant_iter_free_f(iter);
+}  else {
+    void *iter;
+    char *str; int v;
+    //str = (char*)g_variant_get_type_f(gvar); // -> "a{sv}"
+    g_variant_get_f(gvar, "a{sv}", &iter);
+    g_variant_unref_f(gvar);
+    if (g_variant_iter_loop_f(iter, "{sv}", &str, &gvar)) {
+	//str = (char*)g_variant_get_type_f(gvar); // -> "i"
+    	g_variant_get_f(gvar, "i", &v);
+	factor = v;
+      	printf("Debian/FreeBSD name=%s value=%d factor=%g\n", str, v, factor);
+    }
+    g_variant_iter_free_f(iter);
+  }
+  g_variant_unref_f(gvar);
+  g_object_unref_f(gset);
+  if (factor == 0) return false;
+  return true;
+}
+#endif
+
+
+int scale_handler(int event) {
+  if ( event != FL_SHORTCUT || (!Fl::event_ctrl()) ) return 0;
+  int key = Fl::event_key() & ~(FL_SHIFT+FL_CTRL);
+  // respond to Ctrl-'+' and Ctrl-'-'
+  if ((Fl::event_shift() && key == '=') || key == '-' || key == '+') {
+    if (Fl::grab()) return 0; // don't rescale when menu windows are on
+    Fl_Xlib_Graphics_Driver &gd = (Fl_Xlib_Graphics_Driver&)Fl_Graphics_Driver::default_driver();
+    float f = gd.scale(), old_f = f;
+    if (key == '-') f -= .5; else f += .5;
+    f = int(f * 10+0.5)/10.; // round to one digit after decimal point
+    gd.scale(f);
+    int i = 0, count = 0; // count top-level windows
+    Fl_Window *win = Fl::first_window();
+    while (win) {
+      if (!win->window()) count++;
+      win = Fl::next_window(win);
+    }
+    Fl_Window **win_array = new Fl_Window*[count];
+    win = Fl::first_window(); // memorize all top-level windows
+    while (win) {
+      if (!win->window()) {
+        win_array[i++] = win;
+      }
+      win = Fl::next_window(win);
+    }
+    for (i = count - 1; i >= 0; i--) { // rescale all top-level windows, finishing with front one
+      win = win_array[i];
+      int oldx = win->x(), oldy = win->y();
+      win->hide();
+      win->show();
+      win->wait_for_expose();
+      win->position(oldx*old_f/f, oldy*old_f/f);
+    }
+    delete[] win_array;
+    return 1;
+  }
+  return 0;
+}
+
+
 void Fl_X11_Screen_Driver::open_display() {
   if (fl_display) return;
 
@@ -617,6 +778,28 @@
   // the unique GC used by all X windows
   GC gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0);
   Fl_Graphics_Driver::default_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;
+#if HAVE_DLSYM && HAVE_DLFCN_H
+  if (gnome_scale_factor(factor)) {
+    ; // try to read the current gnome scaling value
+  } else
+#endif
+  { // 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_Xlib_Graphics_Driver &dr = (Fl_Xlib_Graphics_Driver&)Fl_Graphics_Driver::default_driver();
+    dr.scale(factor);
+  }
+  
+  Fl::add_handler(scale_handler);
+#endif // USE_XFT
 }
 
 
@@ -725,8 +908,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 +1267,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 +2180,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 +2252,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 +2443,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 +2553,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 +2713,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 +2755,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()) {
@@ -2878,6 +3067,7 @@
   //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_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 12157)
+++ 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 12157)
+++ 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 12157)
+++ 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(),
@@ -400,25 +402,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;
   Fl_Surface_Device::pop_current();
 }
@@ -648,8 +655,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_Translated_Xlib_Graphics_Driver.H
===================================================================
--- src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.H	(revision 12157)
+++ src/drivers/Xlib/Fl_Translated_Xlib_Graphics_Driver.H	(working copy)
@@ -21,7 +21,7 @@
 
 #ifndef FL_DOXYGEN
 
-#include <src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H>
+#include "Fl_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 {
@@ -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 12157)
+++ 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_Xlib_Graphics_Driver() {
   offset_x = 0; offset_y = 0;
   depth = 0;
 }
@@ -120,6 +120,13 @@
   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_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);
Index: src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx	(working copy)
@@ -31,6 +31,7 @@
   virtual void end_current_();
 protected:
   Fl_Offscreen xid;
+  int pixmap_w, pixmap_h;
   Window oldwindow;
   Fl_Xlib_Copy_Surface_Driver(int w, int h);
   ~Fl_Xlib_Copy_Surface_Driver();
@@ -51,8 +52,12 @@
 
 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_Graphics_Driver::default_driver().scale();
+  ((Fl_Translated_Xlib_Graphics_Driver*)driver())->scale(s);
   oldwindow = fl_window;
   xid = fl_create_offscreen(w,h);
+  pixmap_w = w * s;
+  pixmap_h = h * s;
   driver()->push_no_clip();
   fl_window = xid;
   driver()->color(FL_WHITE);
@@ -65,10 +70,10 @@
   driver()->pop_clip();
   bool need_push = (Fl_Surface_Device::surface() != this);
   if (need_push) Fl_Surface_Device::push_current(this);
-  unsigned char *data = fl_read_image(NULL,0,0,width,height,0);
+  Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
   if (need_push) Fl_Surface_Device::pop_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 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(working copy)
@@ -53,6 +53,18 @@
  This class is implemented only on the Xlib platform.
  */
 class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Graphics_Driver {
+  float scale_; // scale between user and graphical coordinates: graphical = user * scale_
+  void draw_unscaled(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw_unscaled(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw_unscaled(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+  void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+  void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+  void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+  int unscaled_height();
+  int unscaled_descent();
+  Region scale_clip(float f);
+  void unscale_clip(Region r2);
 #if USE_XFT
   void drawUCS4(const void *str, int n, int x, int y);
 #endif
@@ -88,6 +100,8 @@
   virtual void *gc() { return gc_; }
   virtual void gc(void *value);
   char can_do_alpha_blending();
+  float scale() { return scale_; }
+  void scale(float f);
 #if USE_XFT
   static void destroy_xft_draw(Window id);
 #endif
@@ -102,10 +116,13 @@
   void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
   void draw(Fl_Bitmap *pxm, 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 *shared, 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 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);
   fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
   fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
   void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
@@ -114,6 +131,8 @@
   void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
   int height();
   int descent();
+  Fl_Fontsize size();
+  Fl_Fontsize unscaled_size() {return (Fl_Fontsize)(size_); }
   void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
 #if ! defined(FL_DOXYGEN)
   void copy_offscreen_with_alpha(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
@@ -122,7 +141,7 @@
   Fl_Region XRectangleRegion(int x, int y, int w, int h);
   void XDestroyRegion(Fl_Region r);
 protected:
-  virtual void transformed_vertex0(short x, short y);
+  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);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(working copy)
@@ -57,6 +57,7 @@
   p_size = 0;
   p = NULL;
   line_width_ = 0;
+  scale_ = 1;
 #if USE_PANGO
   pfd_ = pango_font_description_new();
   Fl_Graphics_Driver::font(0, 0);
@@ -77,7 +78,7 @@
 }
 
 void Fl_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
-  XCopyArea(fl_display, pixmap, fl_window, gc_, srcx, srcy, w, h, x, y);
+  XCopyArea(fl_display, pixmap, fl_window, gc_, srcx*scale_, srcy*scale_, w*scale_, h*scale_, x*scale_, y*scale_);
 }
 
 #ifndef FL_DOXYGEN
@@ -118,6 +119,7 @@
 }
 
 void Fl_Xlib_Graphics_Driver::transformed_vertex0(short x, short y) {
+  x *= scale_; y *= scale_;
   if (!n || x != p[n-1].x || y != p[n-1].y) {
     if (n >= p_size) {
       p_size = p ? 2*p_size : 16;
@@ -231,6 +233,42 @@
   s->first = 0;
 }
 
+void Fl_Xlib_Graphics_Driver::scale(float f) {
+  if (f != scale_) {
+    size_ = 0;
+    scale_ = f;
+fprintf(stderr,"scale=%.1f\n",scale_);
+    line_style(FL_SOLID); // scale also default line width
+  }
+}
+
+Region Fl_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_Xlib_Graphics_Driver::unscale_clip(Region r2) {
+  if (r2) {
+    Region r = rstack[rstackptr];
+    if (r) XDestroyRegion(r);
+    rstack[rstackptr] = r2;
+  }
+}
+
 //
 // End of "$Id$".
 //
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx	(working copy)
@@ -28,11 +28,13 @@
 
 void Fl_Xlib_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
   if (w <= 0 || h <= 0) return;
+  x *= scale_; y *= scale_; w *= scale_; h *= scale_;
   XDrawArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
 }
 
 void Fl_Xlib_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
   if (w <= 0 || h <= 0) return;
+  x *= scale_; y *= scale_; w *= scale_; h *= scale_;
   XDrawArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
   XFillArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
 }
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(working copy)
@@ -621,6 +621,11 @@
   else return -1;
 }
 
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size() {
+  if (font_descriptor()) return size_;
+  return -1;
+}
+
 double Fl_Xlib_Graphics_Driver::width(const char* c, int n) {
   if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
   else return -1;
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(working copy)
@@ -58,6 +58,22 @@
 #endif
 
 
+int Fl_Xlib_Graphics_Driver::height() {
+  if (!font_descriptor() ) return -1;
+  return int(ceil(unscaled_height()/scale_));
+}
+
+int Fl_Xlib_Graphics_Driver::descent() {
+  if (!font_descriptor() ) return -1;
+  return unscaled_descent()/scale_;
+}
+
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size() {
+  if (!font_descriptor() ) return -1;
+  return unscaled_size()/scale_;
+}
+
+
 #if ! USE_PANGO
 
 // The predefined fonts that FLTK has:
@@ -456,7 +472,7 @@
 
 
 void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
-  fl_xft_font(this,fnum,size,0);
+  fl_xft_font(this, fnum, size * scale_, 0);
 }
 
 static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core, int angle) {
@@ -691,12 +707,12 @@
 #endif
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::unscaled_height() {
   if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
   else return -1;
 }
 
-int Fl_Xlib_Graphics_Driver::descent() {
+int Fl_Xlib_Graphics_Driver::unscaled_descent() {
   if (font_descriptor()) return font_descriptor()->font->descent;
   else return -1;
 }
@@ -705,7 +721,7 @@
   if (!font_descriptor()) return -1.0;
   XGlyphInfo i;
   utf8extents(font_descriptor(), str, n, &i);
-  return i.xOff;
+  return i.xOff/scale_;
 }
 
 static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) {
@@ -716,7 +732,8 @@
 }
 
 double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
-  return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1);
+  if (!font_descriptor()) return -1.0;
+  return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1) / scale_;
 }
 
 void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
@@ -732,13 +749,22 @@
   h = gi.height;
   dx = -gi.x;
   dy = -gi.y;
+  dx /= scale_;
+  dy /=scale_;
+  w /= scale_;
+  h /= scale_;
 } // fl_text_extents
 
 
 void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
-  if ( !this->font_descriptor() ) {
+  if (!size_ || !font_descriptor() ) {
     this->font(FL_HELVETICA, FL_NORMAL_SIZE);
   }
+  float s = 1;
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
+  x *= s;
+  y *= s;
 #if USE_OVERLAY
   XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
   if (fl_overlay) {
@@ -756,31 +782,41 @@
     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);
+  if (!(region && XEmptyRegion(region))) {
+    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);
+    XftDrawString16(draw_, &color, font_descriptor()->font, x, y, (XftChar16 *)buffer, n);
 #else
-  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
+    XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
 #endif
+  }
+  scale_ = s;
+  unscale_clip(r2);
 }
 
+
 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);
+  if (!size_ || !font_descriptor() ) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->unscaled_size(), angle);
+  float s = 1;
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
+  this->draw(str, n, (int)x*s, (int)y*s);
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->unscaled_size(), 0);
+  scale_ = s;
+  unscale_clip(r2);
 }
 
 void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
@@ -851,7 +887,7 @@
   }
   // 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);
+  drawUCS4(ucs_txt, n, (x*scale_-offs), y * scale_);
 
   delete[] ucs_txt;
 }
@@ -902,7 +938,7 @@
 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();
+  int max = unscaled_height();
   float ps_size = s * 1.15;
   if (ps_size > max) ps_size = max;
   return ps_size;
@@ -972,7 +1008,7 @@
     return;
   }
   Fl_Font_Descriptor* f = driver->font_descriptor();
-  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && f && f->angle == angle)
+  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->unscaled_size() && f && f->angle == angle)
     return;
   driver->Fl_Graphics_Driver::font(fnum, size);
   Fl_Fontdesc *font = fl_fonts + fnum;
@@ -1021,7 +1057,7 @@
 //       well for the fltk "built-in" font names.
 static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) {
   XFontStruct* xgl_font = 0;
-  int size = driver->size();
+  int size = ((Fl_Xlib_Graphics_Driver*)driver)->unscaled_size();
   int fnum = driver->font();
   const char *wt_med = "medium";
   const char *wt_bold = "bold";
@@ -1112,10 +1148,10 @@
   static int glsize = 0;
   static int glfont = -1;
   // Do we need to load a new font?
-  if ((!xgl_font) || (glsize != driver->size()) || (glfont != driver->font())) {
+  if ((!xgl_font) || (glsize != ((Fl_Xlib_Graphics_Driver*)driver)->unscaled_size()) || (glfont != driver->font())) {
     // create a dummy XLFD for some font of the appropriate size...
     if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea
-    glsize = driver->size(); // record current font size
+    glsize = ((Fl_Xlib_Graphics_Driver*)driver)->unscaled_size(); // record current font size
     glfont = driver->font(); // and face
     xgl_font = load_xfont_for_xft2(driver);
   }
@@ -1126,7 +1162,7 @@
   }
   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.
+  xftfont = fontopen(fl_fonts[driver->font()].name, ((Fl_Xlib_Graphics_Driver*)driver)->unscaled_size(), true, 0); // else request XFT to load a suitable "core" font instead.
   return xftfont->u.core.font;
 #  endif // XFT_MAJOR > 1
 }
@@ -1163,7 +1199,12 @@
 
 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;
+  if (size < 0) {
+    Fl_Graphics_Driver::font(0, 0);
+    return;
+  }
+  size *= scale_;
+  if (this->Fl_Graphics_Driver::font() == fnum && this->unscaled_size() == size) return;
   fl_xft_font(this, fnum, size, 0);
   init_built_in_fonts();
   if (pfd_) pango_font_description_free(pfd_);
@@ -1181,20 +1222,32 @@
 }
 
 void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
-  do_draw(0, str, n, x, y);
+  if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  float s = 1;
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
+  do_draw(0, str, n, x*s, y*s);
+  scale_ = s;
+  unscale_clip(r2);
 }
 
 void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+  if (!size_ || !font_descriptor() ) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  float s = 1;
+  Region r2 = scale_clip(scale_);
+  s = scale_; scale_ = 1;
   PangoMatrix mat = PANGO_MATRIX_INIT; // 1.6
-  pango_matrix_translate(&mat, x, y); // 1.6
+  pango_matrix_translate(&mat, x * s, y * s); // 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
+  scale_ = s;
+  unscale_clip(r2);
 }
 
 void Fl_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
-  do_draw(1, str, n, x, y);
+  do_draw(1, str, n, x * scale_, y * scale_);
 }
 
 void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, int x, int y) {
@@ -1245,18 +1298,18 @@
   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
+  pango_xft_render_layout(draw_, &color, playout_, x*PANGO_SCALE, (y-unscaled_height()+unscaled_descent())*PANGO_SCALE ); // 1.8
 }
 
 double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
   if (!n) return 0;
-  if (!fl_display || fl_size() == 0) return -1;
+  if (!fl_display || 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;
+  return (double)width/scale_;
 }
 
 void Fl_Xlib_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
@@ -1266,12 +1319,16 @@
   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();
+  dy = ink_rect.y - unscaled_height() + unscaled_descent();
   w = ink_rect.width;
   h = ink_rect.height;
+  dx /= scale_;
+  dy /=scale_;
+  w /= scale_;
+  h /= scale_;
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::unscaled_height() {
   return font_descriptor()->height_;
 }
 
@@ -1281,8 +1338,9 @@
   return width(buf4, n);
 }
 
-int Fl_Xlib_Graphics_Driver::descent() {
-  return font_descriptor()->descent_;
+int Fl_Xlib_Graphics_Driver::unscaled_descent() {
+  if (font_descriptor()) return font_descriptor()->descent_;
+  else return -1;
 }
 
 typedef int (*sort_f_type)(const void *aa, const void *bb);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx	(working copy)
@@ -571,7 +571,7 @@
   }
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+void Fl_Xlib_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
 
   const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA);
   if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
@@ -580,7 +580,7 @@
   innards(buf,x,y,w,h,d,l,mono,0,0,alpha,gc_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
+void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data,
 		   int x, int y, int w, int h,int d) {
 
   const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA);
@@ -590,15 +590,78 @@
   innards(0,x,y,w,h,d,0,mono,cb,data,alpha,gc_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
   innards(buf,x,y,w,h,d,l,1,0,0,0,gc_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data,
 		   int x, int y, int w, int h,int d) {
   innards(0,x,y,w,h,d,0,1,cb,data,0,gc_);
 }
 
+/* read the image data from a pointer or with a callback, scale it, and draw it */
+void Fl_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_unscaled(scaled_rgb->array, X * s, Y * s, W * s, H * s, depth);
+  unscale_clip(r2);
+  delete scaled_rgb;
+}
+
+void Fl_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_unscaled(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_innards((void*)buf, NULL, X, Y, W, H, D, L, false, scale_);
+  }
+}
+
+void Fl_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_unscaled(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_innards(data, cb, X, Y, W, H, D, 0, false, scale_);
+  }
+}
+
+void Fl_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_unscaled(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_innards((void*)buf, NULL, X, Y, W, H, D, L, true, scale_);
+  }
+}
+
+void Fl_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_unscaled(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_innards(data, cb, X, Y, W, H, D, 0, true, scale_);
+  }
+}
+
 void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
   if (fl_visual->depth > 16) {
     fl_color(r,g,b);
@@ -619,7 +682,7 @@
   XFreePixmap(fl_display, bm);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
   int X, Y, W, H;
   if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
     return;
@@ -634,7 +697,38 @@
   XSetFillStyle(fl_display, gc_, FillSolid);
 }
 
+#include <FL/Fl_Screen_Driver.H>
+void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
+  // to allow rescale at runtime
+  if (*id(bm)) {
+    int px_width, px_height;
+    Fl::screen_driver()->offscreen_size(*id(bm), px_width, px_height);
+    if (int(bm->h()*scale_) != px_height) {
+      bm->uncache();
+    }
+  }
+  if (scale_ == 1) {
+    draw_unscaled(bm, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);  
+  if (!*id(bm)) { // build a scaled id_ for bm
+    Fl_Bitmap *bm2 = (Fl_Bitmap*)bm->copy(bm->w()*s, bm->h()*s);
+    *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
+  draw_unscaled(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;
+}
 
+
 // Composite an image with alpha on systems that don't have accelerated
 // alpha compositing...
 static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
@@ -693,7 +787,7 @@
 }
 
 
-void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
   int X, Y, W, H;
   // Don't draw an empty image...
   if (!img->d() || !img->array) {
@@ -732,6 +826,40 @@
   }
 }
 
+void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
+  // to allow rescale at runtime
+  if (*id(img)) {
+    int px_width, px_height;
+    Fl::screen_driver()->offscreen_size(*id(img), px_width, px_height);
+    if (int(img->w()*scale_) != px_width) {
+      img->uncache();
+    }
+  }
+  if (scale_ == 1) {
+    draw_unscaled(img, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);
+  if (!*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);
+    draw_unscaled(img2, XP*s, YP*s, WP*s, HP*s, cx*s, cy*s);
+    *id(img) = *id(img2);
+    *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
+    draw_unscaled(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_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
 {
   if (id_) {
@@ -744,7 +872,7 @@
   return (fl_uintptr_t)create_bitmask(w, h, array);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
   int X, Y, W, H;
   if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return;
   if (*Fl_Graphics_Driver::mask(pxm)) {
@@ -783,6 +911,39 @@
 }
 
 
+void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
+  // to allow rescale at runtime
+  if (*id(pxm)) {
+    int px_width, px_height;
+    Fl::screen_driver()->offscreen_size(*id(pxm), px_width, px_height);
+    if (int(pxm->w()*scale_) != px_width) {
+      pxm->uncache();
+    }
+  }
+  if (scale_ == 1) {
+    draw_unscaled(pxm, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Region r2 = scale_clip(s);
+  if (!*id(pxm)) { // build a scaled id_ & pixmap_ for pxm
+    Fl_Pixmap *pxm2 = (Fl_Pixmap*)pxm->copy(pxm->w()*s, pxm->h()*s);
+    *id(pxm) = cache(pxm2, pxm2->w(), pxm2->h(), pxm2->data());
+    *mask(pxm) = *mask(pxm2);
+    *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
+  draw_unscaled(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;
+}
+
+
 fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) {
   Fl_Offscreen id;
   id = fl_create_offscreen(w, h);
@@ -800,6 +961,23 @@
 }
 
 
+void Fl_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;
+}
+
+
 //
 // End of "$Id$".
 //
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx	(working copy)
@@ -35,9 +35,9 @@
 #include "Fl_Xlib_Graphics_Driver.H"
 
 void Fl_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) {
-
+  width *= scale_;
   // save line width for X11 clipping
-  if (width == 0) line_width_ = 1;
+  if (width == 0) line_width_ = scale_ < 2 ? 0 : scale_;
   else line_width_ = width>0 ? width : -width;
 
   int ndashes = dashes ? strlen(dashes) : 0;
@@ -66,7 +66,8 @@
   }
   static int Cap[4] = {CapButt, CapButt, CapRound, CapProjecting};
   static int Join[4] = {JoinMiter, JoinMiter, JoinRound, JoinBevel};
-  XSetLineAttributes(fl_display, gc_, width,
+  XSetLineAttributes(fl_display, gc_,
+                     line_width_,
 		     ndashes ? LineOnOffDash : LineSolid,
 		     Cap[(style>>8)&3], Join[(style>>12)&3]);
   if (ndashes) XSetDashes(fl_display, gc_, 0, dashes, ndashes);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx	(working copy)
@@ -164,96 +164,128 @@
 // --- line and polygon drawing with integer coordinates
 
 void Fl_Xlib_Graphics_Driver::point(int x, int y) {
-  XDrawPoint(fl_display, fl_window, gc_, clip_x(x), clip_x(y));
+  //XDrawPoint(fl_display, fl_window, gc_, clip_x(x * scale_), clip_x(y * scale_));
+  rectf(x, y, 1, 1);
 }
 
 void Fl_Xlib_Graphics_Driver::rect(int x, int y, int w, int h) {
   if (w<=0 || h<=0) return;
+  x = x*scale_+0.5; y = y*scale_+0.5;
+  w = w*scale_+0.5; h = h*scale_+0.5;
   if (!clip_to_short(x, y, w, h, line_width_))
-    XDrawRectangle(fl_display, fl_window, gc_, x, y, w-1, h-1);
+    XDrawRectangle(fl_display, fl_window, gc_, x, y, w-scale_, h-scale_);
 }
 
 void Fl_Xlib_Graphics_Driver::rectf(int x, int y, int w, int h) {
   if (w<=0 || h<=0) return;
+  int delta = scale_ >= 2 ? scale_/2 : 0;
+  x = x*scale_-delta; y = y*scale_-delta;
+  w = w*scale_; h = h*scale_;
   if (!clip_to_short(x, y, w, h, line_width_))
     XFillRectangle(fl_display, fl_window, gc_, x, y, w, h);
 }
 
 void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1) {
-  XDrawLine(fl_display, fl_window, gc_, x, y, x1, y1);
+  XDrawLine(fl_display, fl_window, gc_, x*scale_, y*scale_, x1*scale_, y1*scale_);
 }
 
 void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
   XPoint p[3];
-  p[0].x = x;  p[0].y = y;
-  p[1].x = x1; p[1].y = y1;
-  p[2].x = x2; p[2].y = y2;
+  p[0].x = x*scale_;  p[0].y = y*scale_;
+  p[1].x = x1*scale_; p[1].y = y1*scale_;
+  p[2].x = x2*scale_; p[2].y = y2*scale_;
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1) {
+  if (scale_ >= 2) {
+    point(x,y);
+    point(x1,y);
+  }
+  x = (x)*scale_; y = y*scale_; x1 = (x1)*scale_;
   XDrawLine(fl_display, fl_window, gc_, clip_x(x), clip_x(y), clip_x(x1), clip_x(y));
 }
 
 void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+  if (scale_ >= 2) {
+    point(x,y);
+    point(x1,y2);
+  }
   XPoint p[3];
-  p[0].x = clip_x(x);  p[0].y = p[1].y = clip_x(y);
-  p[1].x = p[2].x = clip_x(x1); p[2].y = clip_x(y2);
+  p[0].x = clip_x(x*scale_);  p[0].y = p[1].y = clip_x(y*scale_);
+  p[1].x = p[2].x = clip_x(x1*scale_); p[2].y = clip_x(y2*scale_);
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+  if (scale_ >= 2) {
+    point(x,y);
+    point(x3,y2);
+  }
   XPoint p[4];
-  p[0].x = clip_x(x);  p[0].y = p[1].y = clip_x(y);
-  p[1].x = p[2].x = clip_x(x1); p[2].y = p[3].y = clip_x(y2);
-  p[3].x = clip_x(x3);
+  p[0].x = clip_x(x*scale_);  p[0].y = p[1].y = clip_x(y*scale_);
+  p[1].x = p[2].x = clip_x(x1*scale_); p[2].y = p[3].y = clip_x(y2*scale_);
+  p[3].x = clip_x(x3*scale_);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1) {
+  if (scale_ >= 2) {
+    point(x,y);
+    point(x,y1);
+  }
+  y = (y)*scale_; x = x*scale_; y1 = (y1)*scale_;
   XDrawLine(fl_display, fl_window, gc_, clip_x(x), clip_x(y), clip_x(x), clip_x(y1));
 }
 
 void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+  if (scale_ >= 2) {
+    point(x,y);
+    point(x2,y1);
+  }
   XPoint p[3];
-  p[0].x = p[1].x = clip_x(x);  p[0].y = clip_x(y);
-  p[1].y = p[2].y = clip_x(y1); p[2].x = clip_x(x2);
+  p[0].x = p[1].x = clip_x(x*scale_);  p[0].y = clip_x(y*scale_);
+  p[1].y = p[2].y = clip_x(y1*scale_); p[2].x = clip_x(x2*scale_);
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+  if (scale_ >= 2) {
+    point(x,y);
+    point(x2,y3);
+  }
   XPoint p[4];
-  p[0].x = p[1].x = clip_x(x);  p[0].y = clip_x(y);
-  p[1].y = p[2].y = clip_x(y1); p[2].x = p[3].x = clip_x(x2);
-  p[3].y = clip_x(y3);
+  p[0].x = p[1].x = clip_x(x*scale_);  p[0].y = clip_x(y*scale_);
+  p[1].y = p[2].y = clip_x(y1*scale_); p[2].x = p[3].x = clip_x(x2*scale_);
+  p[3].y = clip_x(y3*scale_);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) {
   XPoint p[4];
-  p[0].x = x;  p[0].y = y;
-  p[1].x = x1; p[1].y = y1;
-  p[2].x = x2; p[2].y = y2;
-  p[3].x = x;  p[3].y = y;
+  p[0].x = x * scale_;  p[0].y = y * scale_;
+  p[1].x = x1 * scale_; p[1].y = y1 * scale_;
+  p[2].x = x2 * scale_; p[2].y = y2 * scale_;
+  p[3].x = x * scale_;  p[3].y = y * scale_;
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
   XPoint p[5];
-  p[0].x = x;  p[0].y = y;
-  p[1].x = x1; p[1].y = y1;
-  p[2].x = x2; p[2].y = y2;
-  p[3].x = x3; p[3].y = y3;
-  p[4].x = x;  p[4].y = y;
+  p[0].x = x * scale_;  p[0].y = y * scale_;
+  p[1].x = x1 * scale_; p[1].y = y1 * scale_;
+  p[2].x = x2 * scale_; p[2].y = y2 * scale_;
+  p[3].x = x3 * scale_; p[3].y = y3 * scale_;
+  p[4].x = x * scale_;  p[4].y = y * scale_;
   XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
 }
 
 void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
   XPoint p[4];
-  p[0].x = x;  p[0].y = y;
-  p[1].x = x1; p[1].y = y1;
-  p[2].x = x2; p[2].y = y2;
-  p[3].x = x;  p[3].y = y;
+  p[0].x = x * scale_;  p[0].y = y * scale_;
+  p[1].x = x1 * scale_; p[1].y = y1 * scale_;
+  p[2].x = x2 * scale_; p[2].y = y2 * scale_;
+  p[3].x = x * scale_;  p[3].y = y * scale_;
   XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
@@ -260,11 +292,11 @@
 
 void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
   XPoint p[5];
-  p[0].x = x;  p[0].y = y;
-  p[1].x = x1; p[1].y = y1;
-  p[2].x = x2; p[2].y = y2;
-  p[3].x = x3; p[3].y = y3;
-  p[4].x = x;  p[4].y = y;
+  p[0].x = x * scale_;  p[0].y = y * scale_;
+  p[1].x = x1 * scale_; p[1].y = y1 * scale_;
+  p[2].x = x2 * scale_; p[2].y = y2 * scale_;
+  p[3].x = x3 * scale_; p[3].y = y3 * scale_;
+  p[4].x = x * scale_;  p[4].y = y * scale_;
   XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0);
   XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
 }
@@ -342,8 +374,12 @@
 void Fl_Xlib_Graphics_Driver::restore_clip() {
   fl_clip_state_number++;
   if (gc_) {
-    Fl_Region r = rstack[rstackptr];
-    if (r) XSetRegion(fl_display, gc_, r);
+    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);
   }
 }
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx	(working copy)
@@ -52,7 +52,11 @@
 
 void Fl_Xlib_Graphics_Driver::end_loop() {
   fixloop();
-  if (n>2) transformed_vertex((short)p[0].x, (short)p[0].y);
+  if (n>2) {
+    float s = scale_; scale_ = 1;
+    transformed_vertex0((short)(p[0].x), (short)(p[0].y));
+    scale_ = s;
+  }
   end_line();
 }
 
@@ -73,7 +77,9 @@
 void Fl_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) {
-    transformed_vertex((short)p[gap_].x, (short)p[gap_].y);
+    float s = scale_; scale_ = 1;
+    transformed_vertex0((short)(p[gap_].x), (short)(p[gap_].y));
+    scale_ = s;
     gap_ = n;
   } else {
     n = gap_;
@@ -94,10 +100,10 @@
 // See fl_arc.c for portable version.
 
 void Fl_Xlib_Graphics_Driver::circle(double x, double y,double r) {
-  double xt = transform_x(x,y);
-  double yt = transform_y(x,y);
-  double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
-  double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+  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);
Index: src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(revision 12157)
+++ src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(working copy)
@@ -24,10 +24,13 @@
 #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;
   virtual void end_current_();
+protected:
+  int pixmap_w, pixmap_h;
 public:
   Window pre_window;
   int was_high;
@@ -45,11 +48,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) {
+  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())->scale(d);
 }
 
 Fl_Xlib_Image_Surface_Driver::~Fl_Xlib_Image_Surface_Driver() {
@@ -74,9 +86,7 @@
 
 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 = new Fl_RGB_Image(data, width, height);
-  image->alloc_array = 1;
+  Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
   return image;
 }
 
Index: src/fl_boxtype.cxx
===================================================================
--- src/fl_boxtype.cxx	(revision 12157)
+++ src/fl_boxtype.cxx	(working copy)
@@ -210,9 +210,14 @@
 
 /** Draws a box of type FL_UP_BOX */
 void fl_up_box(int x, int y, int w, int h, Fl_Color c) {
+  /*fl_up_frame(x,y,w,h,c);
+  Fl::set_box_color(c);
+  fl_rectf(x+D1, y+D1, w-D2, h-D2);*/
+  Fl::set_box_color(c);
+  Fl_Color b = fl_color();
+  fl_rectf(x, y, w, h);
   fl_up_frame(x,y,w,h,c);
-  Fl::set_box_color(c);
-  fl_rectf(x+D1, y+D1, w-D2, h-D2);
+  fl_color(b);
 }
 
 /** Draws a frame of type FL_DOWN_FRAME */
@@ -230,9 +235,11 @@
 
 /** Draws a box of type FL_DOWN_BOX */
 void fl_down_box(int x, int y, int w, int h, Fl_Color c) {
+  Fl::set_box_color(c);
+  Fl_Color b = fl_color();
+  fl_rectf(x, y, w, h);
   fl_down_frame(x,y,w,h,c);
-  Fl::set_box_color(c);
-  fl_rectf(x+D1, y+D1, w-D2, h-D2);
+  fl_color(b);
 }
 
 /** Draws a frame of type FL_ENGRAVED_FRAME */
@@ -242,9 +249,14 @@
 
 /** Draws a box of type FL_ENGRAVED_BOX */
 void fl_engraved_box(int x, int y, int w, int h, Fl_Color c) {
+  /*fl_engraved_frame(x,y,w,h,c);
+  Fl::set_box_color(c);
+  fl_rectf(x+2, y+2, w-4, h-4);*/
+  Fl::set_box_color(c);
+  Fl_Color b = fl_color();
+  fl_rectf(x, y, w, h);
   fl_engraved_frame(x,y,w,h,c);
-  Fl::set_box_color(c);
-  fl_rectf(x+2, y+2, w-4, h-4);
+  fl_color(b);
 }
 
 /** Draws a frame of type FL_EMBOSSED_FRAME */
@@ -254,9 +266,14 @@
 
 /** Draws a box of type FL_EMBOSSED_BOX */
 void fl_embossed_box(int x, int y, int w, int h, Fl_Color c) {
+  /*fl_embossed_frame(x,y,w,h,c);
+  Fl::set_box_color(c);
+  fl_rectf(x+2, y+2, w-4, h-4);*/
+  Fl::set_box_color(c);
+  Fl_Color b = fl_color();
+  fl_rectf(x, y, w, h);
   fl_embossed_frame(x,y,w,h,c);
-  Fl::set_box_color(c);
-  fl_rectf(x+2, y+2, w-4, h-4);
+  fl_color(b);
 }
 
 /**
Index: src/fl_draw.cxx
===================================================================
--- src/fl_draw.cxx	(revision 12157)
+++ src/fl_draw.cxx	(working copy)
@@ -64,7 +64,7 @@
       // test for word-wrap:
       if (word_start < p && wrap) {
 	double newwidth = w + fl_width(word_end, (int) (o-word_end) );
-	if (word_end > buf && newwidth > maxw) { // break before this word
+	if (word_end > buf && int(newwidth) > maxw) { // break before this word
 	  o = word_end;
 	  p = word_start;
 	  break;
Index: src/fl_vertex.cxx
===================================================================
--- src/fl_vertex.cxx	(revision 12157)
+++ src/fl_vertex.cxx	(working copy)
@@ -78,16 +78,6 @@
   }
 }
 
-/** see fl_scale(double, double) */
-void Fl_Graphics_Driver::scale(double x, double y) {
-  mult_matrix(x,0,0,y,0,0);
-}
-
-/** see fl_scale(double) */
-void Fl_Graphics_Driver::scale(double x) {
-  mult_matrix(x,0,0,x,0,0);
-}
-
 /** see fl_translate() */
 void Fl_Graphics_Driver::translate(double x,double y) {
   mult_matrix(1,0,0,1,x,y);
Index: test/offscreen.cxx
===================================================================
--- test/offscreen.cxx	(revision 12157)
+++ test/offscreen.cxx	(working copy)
@@ -68,6 +68,7 @@
   int page_x, page_y; // top left of view area
   // Width and height of the offscreen surface
   int offsc_w, offsc_h;
+  int iters; // Must be set on first pass!
 };
 
 /*****************************************************************************/
@@ -74,6 +75,7 @@
 oscr_box::oscr_box(int x, int y, int w, int h) :
   Fl_Box(x, y, w, h), // base box
   oscr(0), // offscreen is not set at start
+  iters(num_iterations + 1),
   x1(0), y1(0), drag_state(0), // not dragging view
   page_x((offscreen_size - win_size) / 2), // roughly centred in view
   page_y((offscreen_size - win_size) / 2),
@@ -110,6 +112,12 @@
 int oscr_box::handle(int ev)
 {
   int ret = Fl_Box::handle(ev);
+  
+  if (ev == FL_HIDE && oscr) {
+      fl_delete_offscreen(oscr);
+      oscr = 0;
+      iters = num_iterations + 1;
+  }
   // handle dragging of visible page area - if a valid context exists
   if (has_oscr())
   {
@@ -184,7 +192,6 @@
   static int icol = first_useful_color;
   static int ox = (offscreen_size / 2);
   static int oy = (offscreen_size / 2);
-  static int iters = num_iterations + 1; // Must be set on first pass!
 
   if (!has_oscr())
   {
