Index: FL/Fl_Bitmap.H
===================================================================
--- FL/Fl_Bitmap.H	(revision 12170)
+++ FL/Fl_Bitmap.H	(working copy)
@@ -45,15 +45,16 @@
 	    int &X, int &Y, int &W, int &H);
   /** for internal use */
   fl_uintptr_t id_;
+  float cache_scale_; // graphics scaling value when id_ was computed
 
 public:
 
   /** The constructors create a new bitmap from the specified bitmap data */
   Fl_Bitmap(const uchar *bits, int W, int H) :
-    Fl_Image(W,H,0), array(bits), alloc_array(0), id_(0) {data((const char **)&array, 1);}
+    Fl_Image(W,H,0), array(bits), alloc_array(0), id_(0), cache_scale_(1) {data((const char **)&array, 1);}
   /** The constructors create a new bitmap from the specified bitmap data */
   Fl_Bitmap(const char *bits, int W, int H) :
-    Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id_(0) {data((const char **)&array, 1);}
+    Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id_(0), cache_scale_(1) {data((const char **)&array, 1);}
   virtual ~Fl_Bitmap();
   virtual Fl_Image *copy(int W, int H);
   Fl_Image *copy() { return copy(w(), h()); }
Index: FL/Fl_Gl_Window_Driver.H
===================================================================
--- FL/Fl_Gl_Window_Driver.H	(revision 12170)
+++ 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 12170)
+++ 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
@@ -145,6 +149,9 @@
   static fl_uintptr_t* id(Fl_Bitmap *bm) {return &(bm->id_);}
   static fl_uintptr_t* mask(Fl_RGB_Image *rgb) {return &(rgb->mask_);}
   static fl_uintptr_t* mask(Fl_Pixmap *pm) {return &(pm->mask_);}
+  static float* cache_scale(Fl_Pixmap *pm) {return &(pm->cache_scale_);}
+  static float* cache_scale(Fl_Bitmap *bm) {return &(bm->cache_scale_);}
+  static float* cache_scale(Fl_RGB_Image *rgb) {return &(rgb->cache_scale_);}
   static Fl_Color* pixmap_bg_color(Fl_Pixmap *pm) {return &(pm->pixmap_bg_color);}
   static void draw_empty(Fl_Image* img, int X, int Y) {img->draw_empty(X, Y);}
   static int prepare(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int &cx, int &cy,
@@ -213,8 +220,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 +349,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;}
@@ -355,6 +361,116 @@
   virtual void font_name(int num, const char *name) {}
 };
 
+#ifndef FL_DOXYGEN
+/* Abstract class Fl_Scalable_Graphics_Driver is platform-independent.
+ It supports the scaling of all graphics coordinates by a
+ float factor helpful to support HiDPI displays.
+ This class does :
+ - compute scaled coordinates
+ - scale the cached offscreen of image objects
+ - scale the pixel arrays used when performing direct image draws
+ - call the member functions of a platform-specific,
+ Fl_Scalable_Graphics_Driver-derived class that do the drawings with adequately 
+ scaled coordinates. The member functions are named with the _unscaled suffix.
+ - scale and unscale the clipping region with member functions of the
+ same derived class called scale_clip() and unscale_clip().
+ 
+ This class is presently used on the X11 platform to support HiDPI.
+ It could also be used on the WIN32 platform.
+ */
+class Fl_Scalable_Graphics_Driver : public Fl_Graphics_Driver {
+public:
+  Fl_Scalable_Graphics_Driver();
+  float scale() { return scale_; }
+  virtual void scale(float f)=0;
+protected:
+  float scale_; // scale between user and graphical coordinates: graphical = user * scale_
+  virtual Fl_Region scale_clip(float f)=0;
+  virtual void unscale_clip(Fl_Region)=0;
+  virtual void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy)=0;
+  virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy)=0;
+  virtual void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy)=0;
+  void draw(Fl_Shared_Image *shared, int X, int Y);
+  virtual void point(int x, int y);
+  virtual void rect(int x, int y, int w, int h);
+  virtual void rect_unscaled(float x, float y, float w, float h) = 0;
+  virtual void rectf(int x, int y, int w, int h);
+  virtual void rectf_unscaled(float x, float y, float w, float h) = 0;
+  virtual void line(int x, int y, int x1, int y1);
+  virtual void line_unscaled(float x, float y, float x1, float y1) = 0;
+  virtual void line(int x, int y, int x1, int y1, int x2, int y2);
+  virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2) = 0;
+  virtual void xyline(int x, int y, int x1);
+  virtual void xyline(int x, int y, int x1, int y2);
+  virtual void xyline(int x, int y, int x1, int y2, int x3);
+  virtual void xyline_unscaled(float x, float y, float x1)=0;
+  virtual void xyline_unscaled(float x, float y, float x1, float y2)=0;
+  virtual void xyline_unscaled(float x, float y, float x1, float y2, float x3)=0;
+  virtual void yxline(int x, int y, int y1);
+  virtual void yxline(int x, int y, int y1, int x2);
+  virtual void yxline(int x, int y, int y1, int x2, int y3);
+  virtual void yxline_unscaled(float x, float y, float y1)=0;
+  virtual void yxline_unscaled(float x, float y, float y1, float x2)=0;
+  virtual void yxline_unscaled(float x, float y, float y1, float x2, float y3)=0;
+  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2)=0;
+  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)=0;
+  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2)=0;
+  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)=0;
+  virtual void circle(double x, double y, double r);
+  virtual void ellipse_unscaled(double xt, double yt, double rx, double ry)=0;
+  virtual void font(Fl_Font face, Fl_Fontsize size);
+  virtual void font_unscaled(Fl_Font face, Fl_Fontsize size)=0;
+  virtual double width(const char *str, int n);
+  virtual double width(unsigned int c);
+  virtual double width_unscaled(const char *str, int n)=0;
+  virtual double width_unscaled(unsigned int c)=0;
+  virtual Fl_Fontsize size();
+  virtual Fl_Fontsize size_unscaled()=0;
+  virtual void text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h);
+  virtual void text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h)=0;
+  virtual int height();
+  virtual int descent();
+  virtual int height_unscaled()=0;
+  virtual int descent_unscaled()=0;
+  virtual void draw(const char *str, int n, int x, int y);
+  virtual void draw_unscaled(const char *str, int n, int x, int y)=0;
+  virtual void draw(int angle, const char *str, int n, int x, int y);
+  virtual void draw_unscaled(int angle, const char *str, int n, int x, int y)=0;
+  virtual void rtl_draw(const char* str, int n, int x, int y);
+  virtual void rtl_draw_unscaled(const char* str, int n, int x, int y)=0;
+  virtual void arc(int x, int y, int w, int h, double a1, double a2);
+  virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2)=0;
+  virtual void pie(int x, int y, int w, int h, double a1, double a2);
+  virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2)=0;
+  virtual void line_style(int style, int width=0, char* dashes=0);
+  virtual void line_style_unscaled(int style, float width, char* dashes)=0;
+  virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+  virtual void copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy)=0;
+  void draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb, int X, int Y, int W, int H, int D, int L, bool mono, float s);
+  virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0)=0;
+  virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3)=0;
+  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);
+  virtual void draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l)=0;
+  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+  virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1)=0;
+  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+
+  void transformed_vertex(double xf, double yf);
+  virtual void transformed_vertex0(float x, float y)=0;
+  void vertex(double x, double y);
+
+};
+#endif // FL_DOXYGEN
+
+
 #endif // FL_GRAPHICS_DRIVER_H
 
 //
Index: FL/Fl_Image.H
===================================================================
--- FL/Fl_Image.H	(revision 12170)
+++ FL/Fl_Image.H	(working copy)
@@ -223,6 +223,7 @@
   // These two variables are used to cache the image and mask for the main display graphics driver
   fl_uintptr_t id_;
   fl_uintptr_t mask_;
+  float cache_scale_; // graphics scaling value when id_ was computed
 
 public:
 
Index: FL/Fl_Pixmap.H
===================================================================
--- FL/Fl_Pixmap.H	(revision 12170)
+++ FL/Fl_Pixmap.H	(working copy)
@@ -56,6 +56,7 @@
   fl_uintptr_t id_;
   fl_uintptr_t mask_;
   Fl_Color pixmap_bg_color;
+  float cache_scale_; // graphics scaling value when id_ was computed
 
 public:
 
Index: FL/fl_draw.H
===================================================================
--- FL/fl_draw.H	(revision 12170)
+++ 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 12170)
+++ 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 12170)
+++ 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_Graphics_Driver::default_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_Graphics_Driver.cxx
===================================================================
--- src/Fl_Graphics_Driver.cxx	(revision 12170)
+++ src/Fl_Graphics_Driver.cxx	(working copy)
@@ -23,6 +23,7 @@
 #include <FL/Fl_Image.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Image_Surface.H>
+#include <FL/math.h>
 
 FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current driver of graphics operations
 
@@ -181,6 +182,330 @@
   fl_delete_offscreen((Fl_Offscreen)p);
 }
 
+
+
+Fl_Scalable_Graphics_Driver::Fl_Scalable_Graphics_Driver() : Fl_Graphics_Driver() {
+  scale_ = 1;
+}
+
+void Fl_Scalable_Graphics_Driver::rect(int x, int y, int w, int h)
+{
+  rect_unscaled(x * scale_, y * scale_, w * scale_, h * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::rectf(int x, int y, int w, int h)
+{
+  rectf_unscaled(x * scale_, y * scale_, w * scale_, h * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::point(int x, int y) {
+  rectf_unscaled(x * scale_, y * scale_, scale_, scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1) {
+  line_unscaled( x*scale_, y*scale_, x1*scale_, y1*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+  line_unscaled( x*scale_, y*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1) {
+  xyline_unscaled(x*scale_, y*scale_, x1*scale_);
+}
+void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+  xyline_unscaled(x*scale_, y*scale_, x1*scale_, y2*scale_);
+}
+void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+  xyline_unscaled(x*scale_, y*scale_, x1*scale_, y2*scale_, x3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1) {
+  yxline_unscaled(x*scale_, y*scale_, y1*scale_);
+}
+void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+  yxline_unscaled(x*scale_, y*scale_, y1*scale_, x2*scale_);
+}
+void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+  yxline_unscaled(x*scale_, y*scale_, y1*scale_, x2*scale_, y3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
+  loop_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  loop_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_, x3*scale_, y3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
+  polygon_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  polygon_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_, x3*scale_, y3*scale_);
+}
+
+void Fl_Scalable_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));
+  ellipse_unscaled(xt*scale_, yt*scale_, rx*scale_, ry*scale_);
+}
+
+void Fl_Scalable_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)) {
+    if (*cache_scale(pxm) != scale_) {
+      pxm->uncache();
+    }
+  }
+  if (scale_ == 1) {
+    draw_unscaled(pxm, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Fl_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());
+    *cache_scale(pxm) = s;
+    *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;
+}
+
+
+void Fl_Scalable_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)) {
+    if (*cache_scale(bm) != scale_) {
+      bm->uncache();
+    }
+  }
+  if (scale_ == 1) {
+    draw_unscaled(bm, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Fl_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);
+    *cache_scale(bm) = s;
+    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;
+}
+
+
+void Fl_Scalable_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)) {
+    if (*cache_scale(img) != scale_) {
+      img->uncache();
+    }
+  }
+  if (scale_ == 1) {
+    draw_unscaled(img, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Fl_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;
+    *cache_scale(img) = s;
+    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_Scalable_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;
+  Fl_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;
+}
+
+
+void Fl_Scalable_Graphics_Driver::font(Fl_Font face, Fl_Fontsize size) {
+  font_unscaled(face, size * scale_);
+}
+
+double Fl_Scalable_Graphics_Driver::width(const char *str, int n) {
+  return width_unscaled(str, n)/scale_;
+}
+
+double Fl_Scalable_Graphics_Driver::width(unsigned int c) {
+  return width_unscaled(c)/scale_;
+}
+
+Fl_Fontsize Fl_Scalable_Graphics_Driver::size() {
+  if (!font_descriptor() ) return -1;
+  return size_unscaled()/scale_;
+}
+
+void Fl_Scalable_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
+  text_extents_unscaled(str, n, dx, dy, w, h);
+  dx /= scale_;
+  dy /= scale_;
+  w /= scale_;
+  h /= scale_;
+}
+
+int Fl_Scalable_Graphics_Driver::height() {
+  return int(height_unscaled()/scale_);
+}
+
+int Fl_Scalable_Graphics_Driver::descent() {
+  return descent_unscaled()/scale_;
+}
+
+void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, int x, int y) {
+  if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  Fl_Region r2 = scale_clip(scale_);
+  draw_unscaled(str, n, x*scale_, y*scale_);
+  unscale_clip(r2);
+}
+
+void Fl_Scalable_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+  if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  Fl_Region r2 = scale_clip(scale_);
+  draw_unscaled(angle, str, n, x*scale_, y*scale_);
+  unscale_clip(r2);
+}
+
+void Fl_Scalable_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
+  rtl_draw_unscaled(str, n, x * scale_, y * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+  arc_unscaled(x * scale_, y * scale_, w * scale_, h * scale_, a1, a2);
+}
+
+void Fl_Scalable_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
+  pie_unscaled(x * scale_, y * scale_, w * scale_, h * scale_, a1, a2);
+}
+
+void Fl_Scalable_Graphics_Driver::line_style(int style, int width, char* dashes) {
+  line_style_unscaled(style, width * scale_, dashes);
+}
+
+void Fl_Scalable_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
+  copy_offscreen_unscaled(x * scale_, y * scale_, w * scale_, h * scale_, pixmap, srcx * scale_, srcy * scale_);
+}
+
+/* read the image data from a pointer or with a callback, scale it, and draw it */
+void Fl_Scalable_Graphics_Driver::draw_image_rescale(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;
+  if (scaled_rgb) {
+    Fl_Region r2 = scale_clip(s);
+    draw_image_unscaled(scaled_rgb->array, X * s, Y * s, W * s, H * s, depth);
+    unscale_clip(r2);
+    delete scaled_rgb;
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
+  if (scale_ == 1) {
+    draw_image_unscaled(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, false, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
+  if (scale_ == 1) {
+    draw_image_unscaled(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_rescale(data, cb, X, Y, W, H, D, 0, false, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
+  if (scale_ == 1) {
+    draw_image_mono_unscaled(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, true, scale_);
+  }
+}
+
+void Fl_Scalable_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) {
+    draw_image_mono_unscaled(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_rescale(data, cb, X, Y, W, H, D, 0, true, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::transformed_vertex(double xf, double yf) {
+  transformed_vertex0(xf * scale_, yf * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::vertex(double x,double y) {
+  transformed_vertex0((x*m.a + y*m.c + m.x) * scale_, (x*m.b + y*m.d + m.y) * scale_);
+}
+
 //
 // End of "$Id$".
 //
Index: src/Fl_Image.cxx
===================================================================
--- src/Fl_Image.cxx	(revision 12170)
+++ src/Fl_Image.cxx	(working copy)
@@ -271,7 +271,8 @@
   array(bits),
   alloc_array(0),
   id_(0),
-  mask_(0)
+  mask_(0),
+  cache_scale_(1)
 {
     data((const char **)&array, 1);
     ld(LD);
@@ -293,7 +294,8 @@
   array(0),
   alloc_array(0),
   id_(0),
-  mask_(0)
+  mask_(0),
+  cache_scale_(1)
 {
   if (pxm && pxm->w() > 0 && pxm->h() > 0) {
     array = new uchar[w() * h() * d()];
Index: src/Fl_Image_Surface.cxx
===================================================================
--- src/Fl_Image_Surface.cxx	(revision 12170)
+++ 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_Graphics_Driver::default_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_Pixmap.cxx
===================================================================
--- src/Fl_Pixmap.cxx	(revision 12170)
+++ src/Fl_Pixmap.cxx	(working copy)
@@ -42,6 +42,7 @@
   if (w()<0 && data()) {
     fl_measure_pixmap(data(), W, H);
     w(W); h(H);
+    cache_scale_ = 1;
   }
 }
 
Index: src/Fl_Screen_Driver.cxx
===================================================================
--- src/Fl_Screen_Driver.cxx	(revision 12170)
+++ src/Fl_Screen_Driver.cxx	(working copy)
@@ -154,7 +154,7 @@
 }
 
 uchar *Fl_Screen_Driver::read_image(uchar *p, int X, int Y, int w, int h, int alpha) {
-  uchar *image_data;
+  uchar *image_data = NULL;
   Fl_RGB_Image *img;
   if (fl_find(fl_window) == 0) { // read from off_screen buffer
     img = read_win_rectangle(p, X, Y, w, h, alpha);
@@ -165,14 +165,16 @@
   } else {
     img = traverse_to_gl_subwindows(Fl_Window::current(), p, X, Y, w, h, alpha, NULL);
   }
-  if (img->w() > w) {
-    Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
+  if (img) {
+    if (img->w() > w) {
+      Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
+      delete img;
+      img = img2;
+    }
+    img->alloc_array = 0;
+    image_data = (uchar*)img->array;
     delete img;
-    img = img2;
   }
-  img->alloc_array = 0;
-  image_data = (uchar*)img->array;
-  delete img;
   return image_data;
 }
 
@@ -268,7 +270,8 @@
         } else {
           top = full_img->h() - (origin_y - y + img->h());
         }
-        write_image_inside(full_img, img, origin_x - x, top);
+        float s = Fl_Graphics_Driver::default_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 12170)
+++ 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 12170)
+++ 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 12170)
+++ src/Fl_x.cxx	(working copy)
@@ -601,6 +601,228 @@
   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
+ 
+ It's also possible to use 'Tweak tools' under Ubuntu -> combine the 2 factor values.
+
+*/
+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);
+  
+  // 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;
+
+  bool ubuntu = false;
+  // determine whether we run Ubuntu
+  char line[400] = "";
+  FILE *in = fopen("/proc/version", "r");
+  if (in) {
+    fgets(line, sizeof(line), in);
+    fclose(in);
+    if (strstr(line, "Ubuntu")) ubuntu = true;
+  }
+  
+  // 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;
+  float ubuntu_f = 1, gnome_f = 1;
+
+  if (ubuntu) {
+    schema = "com.ubuntu.user-interface";
+    if (is_schema_valid(schema, known)) {
+      void *gset = g_settings_new_f(schema);
+      void *gvar = g_settings_get_value_f(gset, "scale-factor");
+      void *iter;
+      char str[10], *str2; int v, v2;
+      g_variant_get_f(gvar, "a{si}", &iter);
+      while (g_variant_iter_loop_f(iter, "{si}", &str2, &v2)) { // read the last couple of values
+        strcpy(str, str2);  v = v2;
+      }
+      ubuntu_f = v/8.;
+      printf("com.ubuntu.user-interface  scale-factor name=%s value=%d factor=%g\n", str, v, ubuntu_f);
+      g_variant_iter_free_f(iter);
+      g_variant_unref_f(gvar);
+      g_object_unref_f(gset);
+    }
+  }
+  schema = "org.gnome.settings-daemon.plugins.xsettings";
+  if (is_schema_valid(schema, known)) {
+    void *gset = g_settings_new_f(schema);
+    void *gvar = g_settings_get_value_f(gset, "overrides");
+    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);
+    while (g_variant_iter_loop_f(iter, "{sv}", &str, &gvar)) {
+      if (strstr(str, "WindowScalingFactor") == NULL) continue;
+      //str = (char*)g_variant_get_type_f(gvar); // -> "i"
+      g_variant_get_f(gvar, "i", &v);
+      gnome_f = v;
+      printf("org.gnome.settings-daemon.plugins.xsettings  overrides name=%s value=%d factor=%g\n", str, v, gnome_f);
+      free(str);
+      break;
+    }
+    g_variant_iter_free_f(iter);
+    g_variant_unref_f(gvar);
+    g_object_unref_f(gset);
+  }
+  factor = ubuntu_f * gnome_f;
+  return true;
+}
+#endif // HAVE_DLSYM && HAVE_DLFCN_H && USE_XFT
+
+
+#if USE_XFT
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Image_Surface.H>
+
+static void del_transient_window(void *data) {
+  Fl_Window *win = (Fl_Window*)data;
+  delete (Fl_RGB_Image*)win->child(0)->user_data();
+  Fl::delete_widget(win);
+}
+
+static void transient_scale_display(float f)
+{ // transiently show the new scaling value using a shaped window
+  int w = 150;
+  // draw a white rounded box on black background
+  Fl_Image_Surface *surf = new Fl_Image_Surface(w, w);
+  Fl_Surface_Device::push_current(surf);
+  fl_color(FL_BLACK);
+  fl_rectf(-1, -1, w+2, w+2);
+  Fl_Box *b = new Fl_Box(FL_RFLAT_BOX, 0, 0, w, w/2, "");
+  b->color(FL_WHITE);
+  surf->draw(b);
+  Fl_RGB_Image* img = surf->image(); // img is the window's shape
+  delete surf;
+  Fl_Surface_Device::pop_current();
+  //create a window shaped with the rounded box
+  float s = Fl_Graphics_Driver::default_driver().scale();
+  int X, Y, W, H;
+  Fl::screen_xywh(X, Y, W, H); // get coords of mouse-containing screen
+  Fl_Window *win = new Fl_Window((X + W/2)/s -w/2, (Y + H/2)/s -w/2, w, w, 0);
+  char str[10];
+  sprintf(str, "%d %%", int(f * 100 + 0.5));
+  win->add(b);
+  b->copy_label(str);
+  b->labelfont(FL_TIMES_BOLD);
+  b->labelsize(30);
+  b->labelcolor(FL_BLACK);
+  b->color(FL_YELLOW);
+  win->end();
+  win->shape(img);
+  b->user_data(img);
+  win->user_data((void*)&transient_scale_display); // prevent this window from being rescaled later
+  win->show();
+  Fl::add_timeout(1, del_transient_window, win); // delete after 1 sec
+}
+
+// respond to Ctrl-'+' and Ctrl-'-' (Ctrl-'=' is same as Ctrl-'+') by rescaling all windows
+int scale_handler(int event)
+{
+  if ( event != FL_SHORTCUT || (!Fl::event_ctrl()) ) return 0;
+  int key = Fl::event_key() & ~(FL_SHIFT+FL_CTRL);
+  if (key == '=' || key == '-' || key == '+') {
+    if (Fl::grab()) return 0; // don't rescale when menu windows are on
+    static float scaling_values[] = {0.5, 2.f/3, 0.8, 0.9, 1, 1.1, 1.2, 4.f/3, 1.5, 1.7, 2, 2.4, 3};
+    Fl_Scalable_Graphics_Driver &gd = (Fl_Scalable_Graphics_Driver&)Fl_Graphics_Driver::default_driver();
+    float f = gd.scale(), old_f = f;
+    int i, count = sizeof(scaling_values)/sizeof(float);
+    for (i = 0; i < count; i++) {
+      if (f >= scaling_values[i] && (i+1 >= count || f < scaling_values[i+1])) {
+        break;
+      }
+    }
+    if (key == '-') i--; else i++;
+    if (i < 0) i = 0; if (i >= count) i = count - 1;
+    f = scaling_values[i];
+    if (f == old_f) return 1;
+    gd.scale(f);
+    i = 0, count = 0; // count top-level windows, except transient scale-displaying window
+    Fl_Window *win = Fl::first_window();
+    while (win) {
+      if (!win->window() && win->user_data() != &transient_scale_display) 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->user_data() != &transient_scale_display) {
+        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();
+Fl::check(); // helps reducing partial redraw after window rescale under Compiz. Not completely solved.
+      win->show();
+      win->wait_for_expose();
+Fl::check(); // helps reducing partial redraw after window rescale under Compiz. Not completely solved.
+      win->position(oldx*old_f/f, oldy*old_f/f);
+    }
+    delete[] win_array;
+    transient_scale_display(f);
+    return 1;
+  }
+  return 0;
+}
+#endif // USE_XFT
+
+
 void Fl_X11_Screen_Driver::open_display() {
   if (fl_display) return;
 
@@ -617,6 +839,21 @@
   // 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
+  }
+#endif
+  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 +962,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_Graphics_Driver::default_driver().scale();
+  xx = mx/s;
+  yy = my/s;
 }
 
 ////////////////////////////////////////////////////////////////
@@ -1083,10 +1321,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_Graphics_Driver::default_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 +2234,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_Graphics_Driver::default_driver().scale();
+    window->resize(X/s, Y/s, W/s, H/s);
     break; // allow add_handler to do something too
     }
 
@@ -2066,15 +2306,16 @@
   }
 
   if (resize_from_program && shown()) {
+    float s = Fl_Graphics_Driver::default_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 +2497,7 @@
 {
   Fl_Group::current(0); // get rid of very common user bug: forgot end()
 
+  float s = Fl_Graphics_Driver::default_driver().scale();
   int X = win->x();
   int Y = win->y();
   int W = win->w();
@@ -2362,10 +2604,11 @@
     mask |= CWBackPixel;
   }
 
+  float delta = 0;//s > 1 ? s-0.5 : 0;
   Fl_X* xp =
     set_xid(win, XCreateWindow(fl_display,
                                root,
-                               X, Y, W, H,
+                               s*X, s*Y, s*W - delta, s*H- delta,
                                0, // borderwidth
                                visual->depth,
                                InputOutput,
@@ -2525,12 +2768,20 @@
 
   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_Graphics_Driver::default_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();
+  // for integral scaling values, replace null width_inc by s, and so for height_inc.
+  if (int(s) == s && dw() == 0) {
+    hints->width_inc = s;
+  }
+  if (int(s) == s && dh() == 0) {
+    hints->height_inc = s;
+  }
   hints->win_gravity = StaticGravity;
 
   // see the file /usr/include/X11/Xm/MwmUtil.h:
@@ -2566,8 +2817,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 +3129,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 12170)
+++ 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_Graphics_Driver::default_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 12170)
+++ src/drivers/X11/Fl_X11_Screen_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Definition of X11 Screen interface
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -353,6 +353,13 @@
       }
     }
   }
+  float s = Fl_Graphics_Driver::default_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_Surface_Device::surface()->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 12170)
+++ src/drivers/X11/Fl_X11_Window_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Definition of X11 window driver.
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -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_Graphics_Driver::default_driver().scale();
+  w = attributes.width / s;
+  h = attributes.height / s;
 }
 
 
@@ -196,7 +197,8 @@
 void Fl_X11_Window_Driver::draw_begin()
 {
   if (shape_data_) {
-    if (( shape_data_->lw_ != w() || shape_data_->lh_ != h() ) && shape_data_->shape_) {
+    float s = Fl_Graphics_Driver::default_driver().scale();
+    if (( shape_data_->lw_ != int(s*w()) || shape_data_->lh_ != int(s*h()) ) && shape_data_->shape_) {
       // size of window has changed since last time
       combine_mask();
     }
@@ -324,8 +326,9 @@
 #endif
   }
   if (!XShapeCombineMask_f) return;
-  shape_data_->lw_ = w();
-  shape_data_->lh_ = h();
+  float s = Fl_Graphics_Driver::default_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 +403,30 @@
   if (n) XFree(children);
   if (!do_it) wsides = htop = 0;
   int hbottom = wsides;
+  float s = Fl_Graphics_Driver::default_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 +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_Graphics_Driver::default_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 12170)
+++ 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 12170)
+++ 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 12170)
+++ 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 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Definition of class Fl_Xlib_Graphics_Driver for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2016 by Bill Spitzak and others.
+// Copyright 2010-2017 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
@@ -43,7 +43,7 @@
 #endif // HAVE_X11_XREGION_H
 
 #if USE_PANGO
-#include <pango/pangoxft.h>
+#include <pango/pango.h>
 #endif
 
 
@@ -52,7 +52,20 @@
  *
  This class is implemented only on the Xlib platform.
  */
-class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Graphics_Driver {
+class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Scalable_Graphics_Driver {
+  int line_delta_;
+protected:
+  virtual void draw_unscaled(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+  virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+  virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+  virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+  virtual int height_unscaled();
+  virtual int descent_unscaled();
+  virtual Region scale_clip(float f);
+  virtual void unscale_clip(Region r2);
 #if USE_XFT
   void drawUCS4(const void *str, int n, int x, int y);
 #endif
@@ -61,13 +74,11 @@
   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_;}
@@ -84,6 +95,7 @@
 public:
   Fl_Xlib_Graphics_Driver(void);
   virtual ~Fl_Xlib_Graphics_Driver();
+  virtual void scale(float f);
   virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
   virtual void *gc() { return gc_; }
   virtual void gc(void *value);
@@ -95,26 +107,18 @@
   // --- bitmap stuff
   Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
   void delete_bitmask(Fl_Bitmask bm);
-  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 font(Fl_Font face, Fl_Fontsize size);
-  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_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);
+  virtual void draw_unscaled(const char* str, int n, int x, int y);
+  virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
+  virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
+  virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
   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_);
-  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 copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+  virtual double width_unscaled(const char *str, int n);
+  virtual double width_unscaled(unsigned int c);
+  virtual void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h);
+  virtual Fl_Fontsize size_unscaled();
+  virtual void copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float 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);
 #endif
@@ -122,24 +126,23 @@
   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);
+  virtual void transformed_vertex0(float x, float y);
   void fixloop();
   // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx
-  void point(int x, int y);
-  void rect(int x, int y, int w, int h);
-  void rectf(int x, int y, int w, int h);
-  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 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 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 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);
+  virtual void rect_unscaled(float x, float y, float w, float h);
+  virtual void rectf_unscaled(float x, float y, float w, float h);
+  virtual void line_unscaled(float x, float y, float x1, float y1);
+  virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
+  virtual void xyline_unscaled(float x, float y, float x1);
+  virtual void xyline_unscaled(float x, float y, float x1, float y2);
+  virtual void xyline_unscaled(float x, float y, float x1, float y2, float x3);
+  virtual void yxline_unscaled(float x, float y, float y1);
+  virtual void yxline_unscaled(float x, float y, float y1, float x2);
+  virtual void yxline_unscaled(float x, float y, float y1, float x2, float y3);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
   // --- clipping
   void push_clip(int x, int y, int w, int h);
   int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
@@ -147,10 +150,7 @@
   void push_no_clip();
   void pop_clip();
   void restore_clip();
-  // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
   void begin_complex_polygon();
-  void transformed_vertex(double xf, double yf);
-  void vertex(double x, double y);
   void end_points();
   void end_line();
   void end_loop();
@@ -157,15 +157,11 @@
   void end_polygon();
   void end_complex_polygon();
   void gap();
-  void circle(double x, double y, double r);
-  // --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
-  // using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
+  virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
   // --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
-  void arc(int x, int y, int w, int h, double a1, double a2);
-  void pie(int x, int y, int w, int h, double a1, double a2);
-  // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
-  void line_style(int style, int width=0, char* dashes=0);
-  // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+  virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
+  virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
+  virtual void line_style_unscaled(int style, float width, char* dashes);
   void color(Fl_Color c);
   void set_color(Fl_Color i, unsigned int c);
   void free_color(Fl_Color i, int overlay);
@@ -183,7 +179,6 @@
   virtual Fl_Font set_fonts(const char* xstarname);
 };
 
-
 #endif // FL_CFG_GFX_XLIB_H
 
 //
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(revision 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(working copy)
@@ -57,6 +57,7 @@
   p_size = 0;
   p = NULL;
   line_width_ = 0;
+  line_delta_ = 0;
 #if USE_PANGO
   pfd_ = pango_font_description_new();
   Fl_Graphics_Driver::font(0, 0);
@@ -76,7 +77,27 @@
   fl_gc = gc_;
 }
 
-void Fl_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
+void Fl_Xlib_Graphics_Driver::scale(float f) {
+  if (f != scale_) {
+    size_ = 0;
+    scale_ = f;
+    //fprintf(stderr, "scale=%.2f\n", scale_);
+    line_style(FL_SOLID); // scale also default line width
+    /* Scaling >= 2 transforms 1-pixel wide lines into wider lines.
+     X11 draws 2-pixel wide lines so that half of the line width is above or at left
+     of a 1-pixel wide line that would be drawn with the same coordinates.
+     Thus, if the line starts at coordinates (0,0) half of the line width is invisible.
+     Similarly, if the line ends at w()-1 the last pixel of the window is not drawn.
+     What is wanted when scale_ == 2 is a visible 2-pixel wide line in the first case,
+     and a line at the window's edge in the 2nd case.
+     Setting line_delta_ to 1 and offsetting all line, rectangle, text and clip
+     coordinates by line_delta_ achieves what is wanted until scale_ <= 3.5.
+     */
+    line_delta_ =  (scale_ > 1.5 ? 1 : 0);
+  }
+}
+
+void Fl_Xlib_Graphics_Driver::copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy) {
   XCopyArea(fl_display, pixmap, fl_window, gc_, srcx, srcy, w, h, x, y);
 }
 
@@ -117,7 +138,8 @@
   XUnionRectWithRegion(&R, r, r);
 }
 
-void Fl_Xlib_Graphics_Driver::transformed_vertex0(short x, short y) {
+void Fl_Xlib_Graphics_Driver::transformed_vertex0(float fx, float fy) {
+  short x = short(fx), y = short(fy);
   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 +253,35 @@
   s->first = 0;
 }
 
+
+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
+  
+  float delta = (f >= 2 ? f/3 : 0);
+  for (int i = 0; i < r->numRects; i++) {
+    r->rects[i].x1 = short(r->rects[i].x1*f-delta + line_delta_);
+    r->rects[i].x2 = short(r->rects[i].x2*f-delta + line_delta_);
+    r->rects[i].y1 = short(r->rects[i].y1*f-delta + line_delta_);
+    r->rects[i].y2 = short(r->rects[i].y2*f-delta + line_delta_);
+  }
+  r->extents.x1 = short(r->extents.x1*f-delta + line_delta_);
+  r->extents.x2 = short(r->extents.x2*f-delta + line_delta_);
+  r->extents.y1 = short(r->extents.y1*f-delta + line_delta_);
+  r->extents.y2 = short(r->extents.y2*f-delta + line_delta_);
+  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 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx	(working copy)
@@ -26,12 +26,12 @@
   \brief Utility functions for drawing circles using integers
 */
 
-void Fl_Xlib_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+void Fl_Xlib_Graphics_Driver::arc_unscaled(float x,float y,float w,float h,double a1,double a2) {
   if (w <= 0 || h <= 0) return;
-  XDrawArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
+  XDrawArc(fl_display, fl_window, gc_, int(x), int(y), int(w-1), int(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) {
+void Fl_Xlib_Graphics_Driver::pie_unscaled(float x,float y,float w,float h,double a1,double a2) {
   if (w <= 0 || h <= 0) return;
   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 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(working copy)
@@ -596,7 +596,7 @@
   return ptr;
 }
 
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
   if (fnum==-1) {
     Fl_Graphics_Driver::font(0, 0);
     return;
@@ -611,27 +611,32 @@
   }
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
   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::descent_unscaled() {
   if (font_descriptor()) return font_descriptor()->font->descent;
   else return -1;
 }
 
-double Fl_Xlib_Graphics_Driver::width(const char* c, int n) {
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
+  if (font_descriptor()) return size_;
+  return -1;
+}
+
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* c, int n) {
   if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
   else return -1;
 }
 
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
   if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
   else return -1;
 }
 
-void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &W, int &H) {
   if (font_gc != gc_) {
     if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
@@ -649,7 +654,7 @@
 //  dy = fl_descent() - H;
 }
 
-void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char* c, int n, int x, int y) {
   if (font_gc != gc_) {
     if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
@@ -658,7 +663,7 @@
   if (gc_) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, gc_, x, y, c, n);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
   static char warning = 0; // issue warning only once
   if (!warning && angle != 0) {
     warning = 1;
@@ -669,7 +674,7 @@
   this->draw(str, n, (int)x, (int)y);
 }
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
   if (font_gc != gc_) {
     if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(revision 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(working copy)
@@ -125,7 +125,31 @@
 
 Fl_Fontdesc* fl_fonts = built_in_table;
 
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
+  return (Fl_Fontsize)(size_);
+}
 
+static void correct_extents (float scale_, int &dx, int &dy, int &w, int &h) {
+  if (int(scale_) == scale_) { // correct for extents non divisible by integral scale_
+    int delta = dx - int(dx/scale_)*scale_;
+    if (delta) {
+      dx -= delta; w += delta;
+    }
+    delta = -dy - int((-dy)/scale_)*scale_;
+    if (delta) {
+      dy -= delta; h += delta;
+    }
+    delta = h - int(h/scale_)*scale_;
+    if (delta) {
+      h += delta;
+    }
+    delta = w - int(w/scale_)*scale_;
+    if (delta) {
+      w += delta;
+    }
+  }
+}
+
 #if ! USE_PANGO
 
 ///////////////////////////////////////////////////////////
@@ -455,8 +479,8 @@
 static const char* fl_encoding_ = "iso10646-1";
 
 
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
-  fl_xft_font(this,fnum,size,0);
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
+  fl_xft_font(this, fnum, size, 0);
 }
 
 static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core, int angle) {
@@ -691,17 +715,17 @@
 #endif
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
   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::descent_unscaled() {
   if (font_descriptor()) return font_descriptor()->font->descent;
   else return -1;
 }
 
-double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
   if (!font_descriptor()) return -1.0;
   XGlyphInfo i;
   utf8extents(font_descriptor(), str, n, &i);
@@ -715,11 +739,13 @@
   return i.xOff;
 }
 
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
+  if (!font_descriptor()) return -1.0;
   return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1);
 }
 
-void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
+
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
   if (!font_descriptor()) {
     w = h = 0;
     dx = dy = 0;
@@ -730,15 +756,13 @@
 
   w = gi.width;
   h = gi.height;
-  dx = -gi.x;
-  dy = -gi.y;
-} // fl_text_extents
+  dx = -gi.x + line_delta_;
+  dy = -gi.y + line_delta_;
+  correct_extents(scale_, dx, dy, w, h);
+}
 
 
-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);
-  }
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {
 #if USE_OVERLAY
   XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
   if (fl_overlay) {
@@ -756,31 +780,33 @@
     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+line_delta_, y+line_delta_, (XftChar16 *)buffer, n);
 #else
-  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
+    XftDrawString32(draw_, &color, font_descriptor()->font, x+line_delta_, y+line_delta_, (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::draw_unscaled(int angle, const char *str, int n, int x, int y) {
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), angle);
+  this->draw_unscaled(str, n, x, y);
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), 0);
 }
 
 void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
@@ -814,11 +840,11 @@
   color.color.blue  = ((int)b)*0x101;
   color.color.alpha = 0xffff;
 
-  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (FcChar32 *)str, n);
+  XftDrawString32(draw_, &color, font_descriptor()->font, x+line_delta_, y+line_delta_, (FcChar32 *)str, n);
 }
 
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
 
 #if defined(__GNUC__)
 // FIXME: warning Need to improve this XFT right to left draw function
@@ -902,7 +928,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 = height_unscaled();
   float ps_size = s * 1.15;
   if (ps_size > max) ps_size = max;
   return ps_size;
@@ -972,7 +998,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->size_unscaled() && f && f->angle == angle)
     return;
   driver->Fl_Graphics_Driver::font(fnum, size);
   Fl_Fontdesc *font = fl_fonts + fnum;
@@ -1021,7 +1047,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)->size_unscaled();
   int fnum = driver->font();
   const char *wt_med = "medium";
   const char *wt_bold = "bold";
@@ -1112,10 +1138,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)->size_unscaled()) || (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)->size_unscaled(); // record current font size
     glfont = driver->font(); // and face
     xgl_font = load_xfont_for_xft2(driver);
   }
@@ -1126,7 +1152,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)->size_unscaled(), true, 0); // else request XFT to load a suitable "core" font instead.
   return xftfont->u.core.font;
 #  endif // XFT_MAJOR > 1
 }
@@ -1161,9 +1187,13 @@
   return pctxt_;
 }
 
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_Xlib_Graphics_Driver::font_unscaled(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;
+  }
+  if (this->Fl_Graphics_Driver::font() == fnum && this->size_unscaled() == size) return;
   fl_xft_font(this, fnum, size, 0);
   init_built_in_fonts();
   if (pfd_) pango_font_description_free(pfd_);
@@ -1180,11 +1210,11 @@
   }
 }
 
-void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {
   do_draw(0, str, n, x, y);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(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
@@ -1193,7 +1223,7 @@
   pango_context_set_matrix(pctxt_, NULL); // 1.6
 }
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) {
   do_draw(1, str, n, x, y);
 }
 
@@ -1245,12 +1275,13 @@
   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 + line_delta_)*PANGO_SCALE,
+                          (y+line_delta_-height_unscaled()+descent_unscaled())*PANGO_SCALE ); // 1.8
+  }
 
-double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(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_);
@@ -1259,30 +1290,32 @@
   return (double)width;
 }
 
-void Fl_Xlib_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(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();
+  dx = ink_rect.x + line_delta_;
+  dy = ink_rect.y + line_delta_ - height_unscaled() + descent_unscaled();
   w = ink_rect.width;
   h = ink_rect.height;
+  correct_extents(scale_, dx, dy, w, h);
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
   return font_descriptor()->height_;
 }
 
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
   char buf4[4];
   int n = fl_utf8encode(c, buf4);
-  return width(buf4, n);
+  return width_unscaled(buf4, n);
 }
 
-int Fl_Xlib_Graphics_Driver::descent() {
-  return font_descriptor()->descent_;
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
+  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 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Image drawing routines for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -51,6 +51,7 @@
 #  include <FL/fl_draw.H>
 #  include <FL/x.H>
 #  include <FL/Fl_Image_Surface.H>
+#include <FL/Fl_Screen_Driver.H>
 #  include "../../Fl_XColor.H"
 #  include "../../flstring.h"
 
@@ -571,7 +572,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 +581,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,11 +591,11 @@
   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_);
 }
@@ -619,7 +620,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;
@@ -693,7 +694,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) {
@@ -718,6 +719,7 @@
       fl_draw_image(img->array, 0, 0, img->w(), img->h(), depth, img->ld());
       Fl_Surface_Device::pop_current();
       *Fl_Graphics_Driver::id(img) = surface->get_offscreen_before_delete();
+      *cache_scale(img) =  Fl_Scalable_Graphics_Driver::scale();
       delete surface;
     }
   }
@@ -740,11 +742,12 @@
   }
 }
 
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) {
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) {
+  *cache_scale(bm) =  Fl_Scalable_Graphics_Driver::scale();
   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)) {
@@ -796,6 +799,7 @@
     delete[] bitmap;
   }
   fl_end_offscreen();
+  *cache_scale(img) =  Fl_Scalable_Graphics_Driver::scale();
   return (fl_uintptr_t)id;
 }
 
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx	(revision 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx	(working copy)
@@ -34,10 +34,9 @@
 
 #include "Fl_Xlib_Graphics_Driver.H"
 
-void Fl_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) {
-
+void Fl_Xlib_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) {
   // 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;
@@ -63,10 +62,12 @@
     case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break;
     }
     ndashes = p-buf;
+if (*dashes == 0) ndashes = 0;//against error with very small scaling
   }
   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 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx	(working copy)
@@ -163,108 +163,149 @@
 
 // --- 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));
-}
 
-void Fl_Xlib_Graphics_Driver::rect(int x, int y, int w, int h) {
-  if (w<=0 || h<=0) return;
+void Fl_Xlib_Graphics_Driver::rect_unscaled(float fx, float fy, float fw, float fh) {
+  if (fw<=0 || fh<=0) return;
+  int x = fx; int y = fy;
+  int w = int(fw+0.5 - scale_); int h = int(fh+0.5 - scale_);
   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+line_delta_, y+line_delta_, w, h);
 }
 
-void Fl_Xlib_Graphics_Driver::rectf(int x, int y, int w, int h) {
-  if (w<=0 || h<=0) return;
+void Fl_Xlib_Graphics_Driver::rectf_unscaled(float fx, float fy, float fw, float fh) {
+  if (fw<=0 || fh<=0) return;
+  int deltaf = scale_ >= 2 ? scale_/2 : 0;
+  int x = fx-deltaf; int y = fy-deltaf;
+  int w = fw; int h = fh;
   if (!clip_to_short(x, y, w, h, line_width_))
-    XFillRectangle(fl_display, fl_window, gc_, x, y, w, h);
+    XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, 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);
+void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) {
+  if (x == x1) yxline_unscaled(x, y, y1);
+  else if (y == y1) xyline_unscaled(x, y, x1);
+  else XDrawLine(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, x1+line_delta_, y1+line_delta_);
 }
 
-void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float 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+line_delta_;  p[0].y = y+line_delta_;
+  p[1].x = x1+line_delta_; p[1].y = y1+line_delta_;
+  p[2].x = x2+line_delta_; p[2].y = y2+line_delta_;
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1) {
-  XDrawLine(fl_display, fl_window, gc_, clip_x(x), clip_x(y), clip_x(x1), clip_x(y));
+
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {
+  if (scale_ >= 2) {
+    rectf_unscaled(x,y+line_delta_-line_width_/2, line_width_, line_width_);
+    rectf_unscaled(x1,y+line_delta_-line_width_/2, line_width_, line_width_);
+  }
+  int ix = clip_x(x+line_delta_);
+  int iy = clip_x(y+line_delta_);
+  int ix1 = clip_x(x1+line_delta_);
+  XDrawLine(fl_display, fl_window, gc_, ix, iy, ix1, iy);
+  // TO TEST: attempt to improve box drawing with fractional scaling factor
+  int tw = line_width_ ? line_width_ : 1; // true line width
+  if (y+line_delta_ + scale_ >= iy + tw+1 -0.001) XDrawLine(fl_display, fl_window, gc_, ix, iy+1, ix1, iy+1);
 }
 
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2) {
+  if (scale_ >= 2) {
+    rectf_unscaled(x,y+line_delta_-line_width_/2, line_width_, line_width_);
+    rectf_unscaled(x1+line_delta_-line_width_/2,y2, line_width_, line_width_);
+  }
   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+line_delta_);  p[0].y = p[1].y = clip_x(y+line_delta_);
+  p[1].x = p[2].x = clip_x(x1+line_delta_); p[2].y = clip_x(y2+line_delta_);
   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) {
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2, float x3) {
+  if (scale_ >= 2) {
+    rectf_unscaled(x,y+line_delta_-line_width_/2, line_width_, line_width_);
+    rectf_unscaled(x3,y2+line_delta_-line_width_/2, line_width_, line_width_);
+  }
   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+line_delta_);  p[0].y = p[1].y = clip_x(y+line_delta_);
+  p[1].x = p[2].x = clip_x(x1+line_delta_); p[2].y = p[3].y = clip_x(y2+line_delta_);
+  p[3].x = clip_x(x3+line_delta_);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1) {
-  XDrawLine(fl_display, fl_window, gc_, clip_x(x), clip_x(y), clip_x(x), clip_x(y1));
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {
+  if (scale_ >= 2) {
+    rectf_unscaled(x+line_delta_-line_width_/2,y, line_width_, line_width_);
+    rectf_unscaled(x+line_delta_-line_width_/2,y1, line_width_, line_width_);
+  }
+  int ix = clip_x(x+line_delta_);
+  int iy = clip_x(y+line_delta_);
+  int iy1 = clip_x(y1+line_delta_);
+  XDrawLine(fl_display, fl_window, gc_, ix, iy, ix, iy1);
+  // TO TEST: attempt to improve box drawing with fractional scaling factor
+  int tw = line_width_ ? line_width_ : 1; // true line width
+  if (x+line_delta_+scale_ >= ix + tw+1 -0.001) XDrawLine(fl_display, fl_window, gc_, ix+1, iy, ix+1, iy1);
 }
 
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2) {
+  if (scale_ >= 2) {
+    rectf_unscaled(x+line_delta_-line_width_/2,y, line_width_, line_width_);
+    rectf_unscaled(x2,y1+line_delta_-line_width_/2, line_width_, line_width_);
+  }
   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+line_delta_);  p[0].y = clip_x(y+line_delta_);
+  p[1].y = p[2].y = clip_x(y1+line_delta_); p[2].x = clip_x(x2+line_delta_);
   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) {
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2, float y3) {
+  if (scale_ >= 2) {
+    rectf_unscaled(x+line_delta_-line_width_/2,y, line_width_, line_width_);
+    rectf_unscaled(x2+line_delta_-line_width_/2,y3, line_width_, line_width_);
+  }
   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+line_delta_);  p[0].y = clip_x(y+line_delta_);
+  p[1].y = p[2].y = clip_x(y1+line_delta_); p[2].x = p[3].x = clip_x(x2+line_delta_);
+  p[3].y = clip_x(y3+line_delta_);
   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) {
+void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float 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 +line_delta_;  p[0].y = y +line_delta_;
+  p[1].x = x1 +line_delta_; p[1].y = y1 +line_delta_;
+  p[2].x = x2 +line_delta_; p[2].y = y2 +line_delta_;
+  p[3].x = x +line_delta_;  p[3].y = y +line_delta_;
   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) {
+void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float 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+line_delta_;  p[0].y = y+line_delta_;
+  p[1].x = x1 +line_delta_; p[1].y = y1+line_delta_;
+  p[2].x = x2+line_delta_; p[2].y = y2+line_delta_;
+  p[3].x = x3+line_delta_; p[3].y = y3+line_delta_;
+  p[4].x = x+line_delta_;  p[4].y = y+line_delta_;
   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) {
+void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float 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+line_delta_;  p[0].y = y+line_delta_;
+  p[1].x = x1+line_delta_; p[1].y = y1+line_delta_;
+  p[2].x = x2+line_delta_; p[2].y = y2+line_delta_;
+  p[3].x = x+line_delta_;  p[3].y = y+line_delta_;
   XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float 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+line_delta_;  p[0].y = y+line_delta_;
+  p[1].x = x1+line_delta_; p[1].y = y1+line_delta_;
+  p[2].x = x2+line_delta_; p[2].y = y2+line_delta_;
+  p[3].x = x3+line_delta_; p[3].y = y3+line_delta_;
+  p[4].x = x+line_delta_;  p[4].y = y+line_delta_;
   XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0);
   XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
 }
@@ -342,8 +383,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 12170)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx	(working copy)
@@ -30,14 +30,6 @@
 #include <FL/math.h>
 
 
-void Fl_Xlib_Graphics_Driver::transformed_vertex(double xf, double yf) {
-  transformed_vertex0(short(rint(xf)), short(rint(yf)));
-}
-
-void Fl_Xlib_Graphics_Driver::vertex(double x,double y) {
-  transformed_vertex0(short(x*m.a + y*m.c + m.x), short(x*m.b + y*m.d + m.y));
-}
-
 void Fl_Xlib_Graphics_Driver::end_points() {
   if (n>1) XDrawPoints(fl_display, fl_window, gc_, (XPoint*)p, n, 0);
 }
@@ -52,7 +44,9 @@
 
 void Fl_Xlib_Graphics_Driver::end_loop() {
   fixloop();
-  if (n>2) transformed_vertex((short)p[0].x, (short)p[0].y);
+  if (n>2) {
+    transformed_vertex0(p[0].x, p[0].y);
+  }
   end_line();
 }
 
@@ -73,7 +67,7 @@
 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);
+    transformed_vertex0(p[gap_].x, p[gap_].y);
     gap_ = n;
   } else {
     n = gap_;
@@ -92,19 +86,14 @@
 // shortcut the closed circles so they use XDrawArc:
 // warning: these do not draw rotated ellipses correctly!
 // 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));
+void Fl_Xlib_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {
   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);
+  (fl_display, fl_window, gc_, llx, lly, w, h, 0, 360*64);
 }
 
 //
Index: src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(revision 12170)
+++ 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 && high_res) {
+      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 && high_res) ((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 12170)
+++ src/fl_boxtype.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Box drawing code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -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 12170)
+++ 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 12170)
+++ 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 12170)
+++ 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!
 };
 
 /*****************************************************************************/
@@ -77,7 +78,8 @@
   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),
-  offsc_w(0), offsc_h(0) // offscreen size - initially none
+  offsc_w(0), offsc_h(0), // offscreen size - initially none
+  iters(num_iterations + 1)
 { } // Constructor
 
 /*****************************************************************************/
@@ -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())
   {
