summaryrefslogtreecommitdiff
path: root/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2021-02-24 14:52:36 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2021-02-24 14:52:47 +0100
commitbef46b5cb82464713a117b9bdb920735d1b7de37 (patch)
treee645da2fdd342a8a8a41c90b54b2e96e29d849a0 /src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
parent9f84fd05e8090c3b7554c965d15ac5c41a0d4852 (diff)
Improve precision of GUI scaling for Windows platform.
Diffstat (limited to 'src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx')
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx134
1 files changed, 87 insertions, 47 deletions
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
index 8e45c6eb9..4a8daebb1 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
+++ b/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) {