From 9b80a38345d2197654c4610f3d3812e27a301c36 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Tue, 21 May 2019 21:17:11 +0200 Subject: [PATCH] Support for fl_scroll() under macOS when GUI is scaled --- src/Fl_cocoa.mm | 4 +-- src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx | 5 +++- .../Fl_Quartz_Graphics_Driver_image.cxx | 25 +------------------ .../Quartz/Fl_Quartz_Graphics_Driver_rect.cxx | 12 ++++----- 4 files changed, 13 insertions(+), 33 deletions(-) diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index f7365630b..3b4af18e4 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -3408,9 +3408,9 @@ void Fl_Cocoa_Window_Driver::make_current() // it gets activated when needed (e.g., draw text) CGContextSetShouldAntialias(gc, false); CGFloat hgt = [[fl_window contentView] frame].size.height; - CGContextTranslateCTM(gc, 0.5, hgt-0.5f); - CGContextScaleCTM(gc, 1.0f, -1.0f); // now 0,0 is top-left point of the window float s = Fl::screen_driver()->scale(0); + CGContextTranslateCTM(gc, 0.5f*s, hgt-0.5f*s); + CGContextScaleCTM(gc, 1.0f, -1.0f); // now 0,0 is top-left point of the window CGContextScaleCTM(gc, s, s); // apply current scaling factor // for subwindows, limit drawing to inside of parent window // half pixel offset is necessary for clipping as done by fl_cgrectmake_cocoa() diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx index 4df52f15d..97308e666 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx +++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx @@ -26,6 +26,7 @@ #include #include #include +#include /** \cond DriverDev @@ -260,7 +261,9 @@ int Fl_Cocoa_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, i { CGImageRef img = CGImage_from_window_rect(src_x, src_y, src_w, src_h); if (img) { - ((Fl_Quartz_Graphics_Driver*)fl_graphics_driver)->draw_CGImage(img,dest_x,dest_y,src_w,src_h,0,0,src_w,src_h); + float s = Fl_Graphics_Driver::default_driver().scale(); + ((Fl_Quartz_Graphics_Driver*)fl_graphics_driver)->draw_CGImage(img, + dest_x, dest_y, lround(s*src_w), lround(s*src_h), 0, 0, src_w, src_h); CFRelease(img); } return 0; diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx index bb4240864..71fc08637 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx @@ -280,32 +280,9 @@ void Fl_Quartz_Graphics_Driver::draw_CGImage(CGImageRef cgimg, int x, int y, int CGContextClipToRect(gc_, CGRectOffset(rect, -0.5, -0.5 )); // move graphics context to origin of vertically reversed image // The 0.5 here cancels the 0.5 offset present in Quartz graphics contexts. - // Thus, image and surface pixels are in phase if there's no scaling. + // Thus, image and surface pixels are in phase. CGContextTranslateCTM(gc_, rect.origin.x - srcx - 0.5, rect.origin.y - srcy + sh - 0.5); CGContextScaleCTM(gc_, 1, -1); - CGAffineTransform at = CGContextGetCTM(gc_); - if (at.a == at.d && at.b == 0 && at.c == 0) { // proportional scaling, no rotation - // We handle x2 and /2 scalings that occur when drawing to - // a double-resolution bitmap, and when drawing a double-resolution bitmap to display. - bool doit = false; - // phase image with display pixels - CGFloat deltax = 0, deltay = 0; - if (at.a == 2) { // make .tx and .ty have even values - deltax = (at.tx/2 - round(at.tx/2)); - deltay = (at.ty/2 - round(at.ty/2)); - doit = true; - } else if (at.a == 0.5) { - doit = true; - if (high_resolution()) { // make .tx and .ty have int or half-int values - deltax = -(at.tx*2 - round(at.tx*2)); - deltay = (at.ty*2 - round(at.ty*2)); - } else { // make .tx and .ty have integral values - deltax = (at.tx - round(at.tx))*2; - deltay = (at.ty - round(at.ty))*2; - } - } - if (doit) CGContextTranslateCTM(gc_, -deltax, -deltay); - } CGContextDrawImage(gc_, CGRectMake(0, 0, sw, sh), cgimg); CGContextRestoreGState(gc_); } diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx index e48cd0361..8266f16e8 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx @@ -75,7 +75,7 @@ void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1) { CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y); CGContextStrokePath(gc_); - if (high_resolution()) { + if (high_resolution() || scale()>=2) { /* On retina displays, all xyline() and yxline() functions produce lines that are half-unit (or one pixel) too short at both ends. This is corrected by filling at both ends rectangles of size one unit by line-width. @@ -92,7 +92,7 @@ void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2) { CGContextAddLineToPoint(gc_, x1, y); CGContextAddLineToPoint(gc_, x1, y2); CGContextStrokePath(gc_); - if (high_resolution()) { + if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x-0.5, y - quartz_line_width_/2, 1 , quartz_line_width_)); CGContextFillRect(gc_, CGRectMake(x1 - quartz_line_width_/2, y2-0.5, quartz_line_width_, 1)); } @@ -106,7 +106,7 @@ void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { CGContextAddLineToPoint(gc_, x1, y2); CGContextAddLineToPoint(gc_, x3, y2); CGContextStrokePath(gc_); - if (high_resolution()) { + if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x-0.5, y - quartz_line_width_/2, 1 , quartz_line_width_)); CGContextFillRect(gc_, CGRectMake(x3-0.5, y2 - quartz_line_width_/2, 1 , quartz_line_width_)); } @@ -118,7 +118,7 @@ void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1) { CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x, y1); CGContextStrokePath(gc_); - if (high_resolution()) { + if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1)); CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y1-0.5, quartz_line_width_, 1)); } @@ -131,7 +131,7 @@ void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2) { CGContextAddLineToPoint(gc_, x, y1); CGContextAddLineToPoint(gc_, x2, y1); CGContextStrokePath(gc_); - if (high_resolution()) { + if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1)); CGContextFillRect(gc_, CGRectMake(x2-0.5, y1 - quartz_line_width_/2, 1 , quartz_line_width_)); } @@ -145,7 +145,7 @@ void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { CGContextAddLineToPoint(gc_, x2, y1); CGContextAddLineToPoint(gc_, x2, y3); CGContextStrokePath(gc_); - if (high_resolution()) { + if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1)); CGContextFillRect(gc_, CGRectMake(x2 - quartz_line_width_/2, y3-0.5, quartz_line_width_, 1)); }