FLTK logo

[master] bef46b5 - Improve precision of GUI scaling for Windows platform.

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] bef46b5 - Improve precision of GUI scaling for Windows platform. "ManoloFLTK" Feb 24, 2021  
 
commit bef46b5cb82464713a117b9bdb920735d1b7de37
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Wed Feb 24 14:52:36 2021 +0100
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Wed Feb 24 14:52:47 2021 +0100

    Improve precision of GUI scaling for Windows platform.

 FL/Fl_Graphics_Driver.H                          |   4 +
 src/Fl_Graphics_Driver.cxx                       |  16 +++
 src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx   |   2 +-
 src/drivers/GDI/Fl_GDI_Graphics_Driver.H         |  18 ++-
 src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx       |  21 ++--
 src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx |  22 ++--
 src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx  | 134 +++++++++++++++--------
 src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx   |  10 +-
 8 files changed, 152 insertions(+), 75 deletions(-)

diff --git FL/Fl_Graphics_Driver.H FL/Fl_Graphics_Driver.H
index 2c33212..8a7a93b 100644
--- FL/Fl_Graphics_Driver.H
+++ FL/Fl_Graphics_Driver.H
@@ -237,6 +237,7 @@ protected:
 
   Fl_Graphics_Driver();
   virtual void cache_size(Fl_Image *img, int &width, int &height);
+  void cache_size_finalize(Fl_Image *img, int &width, int &height);
   static unsigned need_pixmap_bg_color;
 public:
   virtual ~Fl_Graphics_Driver() {} ///< Destructor
@@ -444,6 +445,7 @@ protected:
   virtual void circle(double x, double y, double r);
   virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
   virtual void font(Fl_Font face, Fl_Fontsize size);
+  virtual Fl_Font font();
   virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
   virtual double width(const char *str, int n);
   virtual double width(unsigned int c);
@@ -461,8 +463,10 @@ protected:
   virtual void draw_unscaled(const char *str, int n, int x, int y);
   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);
+  virtual void draw(const char *str, int nChars, float x, float y);
   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);
+  virtual void arc(double x, double y, double r, double start, double end);
   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);
   virtual void pie(int x, int y, int w, int h, double a1, double a2);
diff --git src/Fl_Graphics_Driver.cxx src/Fl_Graphics_Driver.cxx
index ec3cc8d..2f687e1 100644
--- src/Fl_Graphics_Driver.cxx
+++ src/Fl_Graphics_Driver.cxx
@@ -211,6 +211,10 @@ void Fl_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height)
   fs = height * s;
   height = (fs - int(fs) < 0.001 ? int(fs) :
            int((height+1) * s));
+  cache_size_finalize(img, width, height);
+}
+
+void Fl_Graphics_Driver::cache_size_finalize(Fl_Image *img, int &width, int &height) {
   if (img) img->cache_size_(width, height);
 }
 
@@ -754,6 +758,10 @@ void Fl_Scalable_Graphics_Driver::font(Fl_Font face, Fl_Fontsize size) {
   font_unscaled(face, Fl_Fontsize(size * scale()));
 }
 
+Fl_Font Fl_Scalable_Graphics_Driver::font() {
+  return Fl_Graphics_Driver::font();
+}
+
 double Fl_Scalable_Graphics_Driver::width(const char *str, int n) {
   return width_unscaled(str, n)/scale();
 }
@@ -790,6 +798,10 @@ void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, int x, int y) {
   unscale_clip(r2);
 }
 
+void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, float x, float y) {
+  Fl_Graphics_Driver::draw(str, n, x, y);
+}
+
 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());
@@ -805,6 +817,10 @@ void Fl_Scalable_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a
   arc_unscaled(x * scale(), y * scale(), w * scale(), h * scale(), a1, a2);
 }
 
+void Fl_Scalable_Graphics_Driver::arc(double x, double y, double r, double start, double end) {
+  Fl_Graphics_Driver::arc(x, y, r, start, end);
+}
+
 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);
 }
diff --git src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
index 7117c6c..b73c72e 100644
--- src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
+++ src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
@@ -75,7 +75,7 @@ Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() {
       SetClipboardData (CF_ENHMETAFILE, hmf);
       // then put a BITMAP version of the graphics in the clipboard
       float scaling = driver()->scale();
-      int W = int(width * scaling), H = int(height * scaling);
+      int W = Fl_GDI_Graphics_Driver::floor(width, scaling), H = Fl_GDI_Graphics_Driver::floor(height, scaling);
       RECT rect = {0, 0, W, H};
       Fl_Image_Surface *surf = new Fl_Image_Surface(W, H);
       Fl_Surface_Device::push_current(surf);
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver.H src/drivers/GDI/Fl_GDI_Graphics_Driver.H
index e2a29da..d322bc8 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver.H
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver.H
@@ -58,6 +58,11 @@ public:
   char can_do_alpha_blending();
   virtual void gc(void *ctxt) { gc_ = (HDC)ctxt; global_gc(); }
   virtual void *gc() {return gc_;}
+  // This function aims to compute accurately int(x * s) in
+  // presence of rounding errors existing with floating point numbers
+  // and that sometimes differ between 32 and 64 bits.
+  static inline int floor(int x, float s) { return int(x * s + 0.001f); }
+  inline int floor(int x) { return Fl_GDI_Graphics_Driver::floor(x, scale()); }
 
   // --- bitmap stuff
   Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
@@ -96,14 +101,18 @@ public:
 protected:
   void transformed_vertex0(float x, float y);
   void fixloop();
-  virtual void point_unscaled(float x, float y);
+  virtual void point(int x, int y);
   virtual void rect(int x, int y, int w, int h);
   void focus_rect(int x, int y, int w, int h);
-  void rectf_unscaled(float x, float y, float w, float h);
+  virtual void rectf(int x, int y, int w, int 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 yxline_unscaled(float x, float y, float y1);
+  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 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 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);
@@ -144,6 +153,7 @@ protected:
   virtual void font_name(int num, const char *name);
   void global_gc();
   virtual void overlay_rect(int x, int y, int w , int h);
+  virtual void cache_size(Fl_Image *img, int &width, int &height);
 };
 
 
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
index dd9ed5d..09dd6fa 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
@@ -260,15 +260,14 @@ HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Drive
       pt.y = int(pt.y * (f - 1));
     }
     RECT *rects = (RECT*)&(pdata->Buffer);
-    int delta = (f > 1.75 ? 1 : 0) - int(f/2);
     for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
-      int x = int(rects[i].left * f) + pt.x;
-      int y = int(rects[i].top * f) + pt.y;
+      int x = Fl_GDI_Graphics_Driver::floor(rects[i].left, f) + pt.x;
+      int y = Fl_GDI_Graphics_Driver::floor(rects[i].top, f) + pt.y;
       RECT R2;
-      R2.left = x + delta;
-      R2.top  = y + delta;
-      R2.right = int(rects[i].right * f) + pt.x - x + R2.left;
-      R2.bottom = int(rects[i].bottom * f) + pt.y - y + R2.top;
+      R2.left = x;
+      R2.top  = y;
+      R2.right = Fl_GDI_Graphics_Driver::floor(rects[i].right, f) + pt.x - x + R2.left;
+      R2.bottom = Fl_GDI_Graphics_Driver::floor(rects[i].bottom, f) + pt.y - y + R2.top;
       rects[i] = R2;
     }
     r = ExtCreateRegion(NULL, size, pdata);
@@ -287,3 +286,11 @@ Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
 void Fl_GDI_Graphics_Driver::set_current_() {
   restore_clip();
 }
+
+void Fl_GDI_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height)
+{
+  float s = scale();
+  width  = (s == int(s) ? width * int(s) : floor(width+1));
+  height = (s == int(s) ? height * int(s) : floor(height+1));
+  cache_size_finalize(img, width, height);
+}
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
index 0135eb6..29fd653 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
@@ -398,10 +398,10 @@ void Fl_GDI_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
 }
 
 void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) {
-  X = int(X * scale());
-  Y = int(Y * scale());
+  X = this->floor(X);
+  Y = this->floor(Y);
   cache_size(bm, W, H);
-  cx = int(cx * scale()); cy = int(cy * scale());
+  cx = this->floor(cx); cy = this->floor(cy);
 
   HDC tempdc = CreateCompatibleDC(gc_);
   int save = SaveDC(tempdc);
@@ -499,10 +499,10 @@ void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img)
 
 
 void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
-  X = int(X * scale());
-  Y = int(Y * scale());
+  X = this->floor(X);
+  Y = this->floor(Y);
   cache_size(img, W, H);
-  cx = int(cx * scale()); cy = int(cy * scale());
+  cx = this->floor(cx); cy = this->floor(cy);
   if (W + cx > img->data_w()) W = img->data_w() - cx;
   if (H + cy > img->data_h()) H = img->data_h() - cy;
   if (!*Fl_Graphics_Driver::id(img)) {
@@ -547,10 +547,10 @@ void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP,
   int save = SaveDC(new_gc);
   SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb));
   if ( (rgb->d() % 2) == 0 ) {
-    alpha_blend_(int(XP*scale()), int(YP*scale()), W, H, new_gc, 0, 0, rgb->data_w(), rgb->data_h());
+    alpha_blend_(this->floor(XP), this->floor(YP), W, H, new_gc, 0, 0, rgb->data_w(), rgb->data_h());
   } else {
     SetStretchBltMode(gc_, HALFTONE);
-    StretchBlt(gc_, int(XP*scale()), int(YP*scale()), W, H, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY);
+    StretchBlt(gc_, this->floor(XP), this->floor(YP), W, H, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY);
   }
   RestoreDC(new_gc, save);
   DeleteDC(new_gc);
@@ -631,10 +631,10 @@ void Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) {
 }
 
 void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) {
-  X = int(X * scale());
-  Y = int(Y * scale());
+  X = this->floor(X);
+  Y = this->floor(Y);
   cache_size(pxm, W, H);
-  cx = int(cx * scale()); cy = int(cy * scale());
+  cx = this->floor(cx); cy = this->floor(cy);
   Fl_Region r2 = scale_clip(scale());
   if (*Fl_Graphics_Driver::mask(pxm)) {
     HDC new_gc = CreateCompatibleDC(gc_);
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
index 8e45c6e..4a8daeb 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
@@ -31,47 +31,51 @@
 
 // --- line and polygon drawing with integer coordinates
 
-void Fl_GDI_Graphics_Driver::point_unscaled(float fx, float fy) {
-  int width = (scale() >= 1 ? int(scale()) : 1);
-  RECT rect;
-  rect.left = int(fx); rect.top = int(fy);
-  rect.right = int(fx) + width; rect.bottom = int(fy) + width;
-  FillRect(gc_, &rect, fl_brush());
+void Fl_GDI_Graphics_Driver::point(int x, int y) {
+  rectf(x, y, 1, 1);
 }
 
 void Fl_GDI_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
   // make pen have a one-pixel width
   line_style_unscaled( (color()==FL_WHITE?FL_SOLID:FL_DOT), 1, NULL);
-  loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1);
+  int right = this->floor(x+w-1), bottom = this->floor(y+h-1);
+  x = this->floor(x); y = this->floor(y);
+  MoveToEx(gc_, x, y, 0L);
+  LineTo(gc_, right, y);
+  LineTo(gc_, right, bottom);
+  LineTo(gc_, x, bottom);
+  LineTo(gc_, x, y);
 }
 
 void Fl_GDI_Graphics_Driver::rect(int x, int y, int w, int h)
 {
   if (w > 0 && h > 0) {
-    float s = scale();
-    xyline_unscaled(x*s, y*s, (x+w-1)*s);
-    yxline_unscaled(x*s, y*s, (y+h-1)*s);
-    yxline_unscaled((x+w-1)*s, y*s, (y+h-1)*s);
-    xyline_unscaled(x*s, (y+h-1)*s, (x+w-1)*s);
+    xyline(x, y, (x+w-1));
+    yxline(x, y, (y+h-1));
+    yxline((x+w-1), y, (y+h-1));
+    xyline(x, (y+h-1), (x+w-1));
   }
 }
 
 void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) {
   // Windows 95/98/ME do not implement the dotted line style, so draw
   // every other pixel around the focus area...
-  w--; h--;
+  w = floor(x+w-1) - floor(x) + 1;
+  h = floor(y+h-1) - floor(y) + 1;
+  x = floor(x); y = floor(y);
   int i=1, xx, yy;
-  for (xx = 0; xx < w; xx++, i++) if (i & 1) point(x + xx, y);
-  for (yy = 0; yy < h; yy++, i++) if (i & 1) point(x + w, y + yy);
-  for (xx = w; xx > 0; xx--, i++) if (i & 1) point(x + xx, y + h);
-  for (yy = h; yy > 0; yy--, i++) if (i & 1) point(x, y + yy);
+  COLORREF c = fl_RGB();
+  for (xx = 0; xx < w; xx++, i++) if (i & 1) SetPixel(gc_, x+xx, y, c);
+  for (yy = 0; yy < h; yy++, i++) if (i & 1) SetPixel(gc_, x+w, y+yy, c);
+  for (xx = w; xx > 0; xx--, i++) if (i & 1) SetPixel(gc_, x+xx, y+h, c);
+  for (yy = h; yy > 0; yy--, i++) if (i & 1) SetPixel(gc_, x, y+yy, c);
 }
 
-void Fl_GDI_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) {
+void Fl_GDI_Graphics_Driver::rectf(int x, int y, int w, int h) {
   if (w<=0 || h<=0) return;
   RECT rect;
-  rect.left = int(x); rect.top = int(y);
-  rect.right = int(x + w); rect.bottom = int(y + h);
+  rect.left = this->floor(x); rect.top = this->floor(y);
+  rect.right = this->floor(x + w); rect.bottom = this->floor(y + h);
   FillRect(gc_, &rect, fl_brush());
 }
 
@@ -88,38 +92,74 @@ void Fl_GDI_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1,
   SetPixel(gc_, int(x2), int(y2), fl_RGB());
 }
 
-void Fl_GDI_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {
-  int line_delta_ =  (scale() > 1.75 ? 1 : 0);
-  int tw = line_width_ ? line_width_ : 1; // true line width
-  if (x > x1) { float exch = x; x = x1; x1 = exch; }
-  int ix = int(x) + line_delta_; if (scale() >= 2.f) ix -= int(scale()/2);
-  int iy = int(y) + line_delta_;
-  if (scale() > 1.9 && line_width_/scale() >= 2) iy--;
-  int ix1 = int( int(x1/scale()+1.5f) * scale() ) - 1; // extend line to pixel before line beginning at x1/scale_ + 1
-  ix1 += line_delta_; if (scale() >= 2) ix1 -= 1;; if (scale() >= 4) ix1 -= 1;
-  MoveToEx(gc_, ix, iy, 0L); LineTo(gc_, ix1+1, iy);
-  // try and make sure no unfilled area lies between xyline(x,y,x1) and xyline(x,y+1,x1)
-  if (int(scale()) != scale() && y+line_delta_ + scale() >= iy + tw+1 - 0.001 ) {
-    MoveToEx(gc_, ix, iy+1, 0L); LineTo(gc_, ix1+1, iy+1);
+static HPEN change_pen_width(int width, HDC gc) { // set the width of the pen, return previous pen
+  LOGBRUSH penbrush = {BS_SOLID, fl_RGB(), 0};
+  HPEN newpen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, width, &penbrush, 0, 0);
+  return (HPEN)SelectObject(gc, newpen);
+}
+
+void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1) {
+  if (y < 0) return;
+  float s = scale();
+  int xx = (x < x1 ? x : x1);
+  int xx1 = (x < x1 ? x1 : x);
+  if (s != int(s) && line_width_ <= int(s)) {
+    int lwidth = this->floor((y+1)) - this->floor(y);
+    bool need_pen = (lwidth != int(s));
+    HPEN oldpen = (need_pen ? change_pen_width(lwidth, gc_) : NULL);
+    MoveToEx(gc_, this->floor(xx), this->floor(y) + int(lwidth/2.f) , 0L);
+    LineTo(gc_, this->floor((xx1+1)), this->floor(y) + int(lwidth/2.f));
+    if (need_pen) {
+      DeleteObject(SelectObject(gc_, oldpen));
+    }
+  } else {
+    y = int((y + 0.5f) * s);
+    MoveToEx(gc_, this->floor(xx), y, 0L);
+    LineTo(gc_, this->floor(xx1) + int(s) , y);
   }
 }
 
-void Fl_GDI_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {
-  if (y1 < y) { float exch = y; y = y1; y1 = exch;}
-  int line_delta_ =  (scale() > 1.75 ? 1 : 0);
-  int tw = line_width_ ? line_width_ : 1; // true line width
-
-  int ix = int(x) + line_delta_;
-  if (scale() > 1.9 && line_width_/scale() >= 2) ix--;
-  int iy = int(y) + line_delta_; if (scale() >= 2) iy -= int(scale()/2);
-  int iy1 = int( int(y1/scale()+1.5) * scale() ) - 1;
-  iy1 += line_delta_; if (scale() >= 2) iy1 -= 1;; if (scale() >= 4) iy1 -= 1; // extend line to pixel before line beginning at y1/scale_ + 1
-  MoveToEx(gc_, ix, iy, 0L); LineTo(gc_, ix, iy1+1);
-  // try and make sure no unfilled area lies between yxline(x,y,y1) and yxline(x+1,y,y1)
-  if (int(scale()) != scale() && x+line_delta_+scale() >= ix + tw+1 -0.001) {
-    MoveToEx(gc_, ix+1, iy, 0L); LineTo(gc_, ix+1, iy1+1);
+void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+  xyline(x, y, x1);
+  yxline(x1, y, y2);
+}
+
+void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+  xyline(x, y, x1);
+  yxline(x1, y, y2);
+  xyline(x1, y2, x3);
+}
+
+void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1) {
+  if (x < 0) return;
+  double s = scale();
+  int yy = (y < y1 ? y : y1);
+  int yy1 = (y < y1 ? y1 : y);
+  if (s != int(s) && line_width_ <= int(s)) {
+    int lwidth = (this->floor((x+1)) - this->floor(x));
+    bool need_pen = (lwidth != int(s));
+    HPEN oldpen = (need_pen ? change_pen_width(lwidth, gc_) : NULL);
+    MoveToEx(gc_, this->floor(x) + int(lwidth/2.f), this->floor(yy), 0L);
+    LineTo(gc_, this->floor(x) + int(lwidth/2.f), this->floor((yy1+1)) );
+    if (need_pen) {
+      DeleteObject(SelectObject(gc_, oldpen));
+    }
+  } else {
+    x = int((x + 0.5f) * s);
+    MoveToEx(gc_, x, this->floor(yy), 0L);
+    LineTo(gc_, x, this->floor(yy1) + int(s));
   }
+}
+
+void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+  yxline(x, y, y1);
+  xyline(x, y1, x2);
+}
 
+void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+  yxline(x, y, y1);
+  xyline(x, y1, x2);
+  yxline(x2, y1, y3);
 }
 
 void Fl_GDI_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
diff --git src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
index 7c57d08..eb437b9 100644
--- src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
@@ -20,7 +20,7 @@
 #include "../GDI/Fl_Font.H"
 #include <FL/Fl.H>
 #include <FL/platform.H>
-#include <FL/Fl_Graphics_Driver.H>
+#include "../GDI/Fl_GDI_Graphics_Driver.H"
 #include <FL/Fl_RGB_Image.H>
 #include <FL/fl_ask.H>
 #include <stdio.h>
@@ -499,14 +499,14 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(
 {
   float s = Fl_Surface_Device::surface()->driver()->scale();
   int ws, hs;
-  if (int(s) == s) { ws = int(w * s); hs = int(h * s);}
+  if (int(s) == s) { ws = w * int(s); hs = h * int(s);}
   else {
-    ws = int((w+1) * s); // approximates what Fl_Graphics_Driver::cache_size() does
-    hs = int((h+1) * s);
+    ws = Fl_GDI_Graphics_Driver::floor(w+1, s); // approximates what Fl_Graphics_Driver::cache_size() does
+    hs = Fl_GDI_Graphics_Driver::floor(h+1, s);
     if (ws < 1) ws = 1;
     if (hs < 1) hs = 1;
   }
-  return read_win_rectangle_unscaled(int(X*s), int(Y*s), ws, hs, win);
+  return read_win_rectangle_unscaled(Fl_GDI_Graphics_Driver::floor(X, s), Fl_GDI_Graphics_Driver::floor(Y, s), ws, hs, win);
 }
 
 Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win)
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.