Support for fl_scroll() under macOS when GUI is scaled
This commit is contained in:
parent
07f4fd4380
commit
9b80a38345
@ -3408,9 +3408,9 @@ void Fl_Cocoa_Window_Driver::make_current()
|
|||||||
// it gets activated when needed (e.g., draw text)
|
// it gets activated when needed (e.g., draw text)
|
||||||
CGContextSetShouldAntialias(gc, false);
|
CGContextSetShouldAntialias(gc, false);
|
||||||
CGFloat hgt = [[fl_window contentView] frame].size.height;
|
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);
|
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
|
CGContextScaleCTM(gc, s, s); // apply current scaling factor
|
||||||
// for subwindows, limit drawing to inside of parent window
|
// for subwindows, limit drawing to inside of parent window
|
||||||
// half pixel offset is necessary for clipping as done by fl_cgrectmake_cocoa()
|
// half pixel offset is necessary for clipping as done by fl_cgrectmake_cocoa()
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <FL/fl_draw.H>
|
#include <FL/fl_draw.H>
|
||||||
#include <FL/Fl.H>
|
#include <FL/Fl.H>
|
||||||
#include <FL/platform.H>
|
#include <FL/platform.H>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\cond DriverDev
|
\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);
|
CGImageRef img = CGImage_from_window_rect(src_x, src_y, src_w, src_h);
|
||||||
if (img) {
|
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);
|
CFRelease(img);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -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 ));
|
CGContextClipToRect(gc_, CGRectOffset(rect, -0.5, -0.5 ));
|
||||||
// move graphics context to origin of vertically reversed image
|
// move graphics context to origin of vertically reversed image
|
||||||
// The 0.5 here cancels the 0.5 offset present in Quartz graphics contexts.
|
// 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);
|
CGContextTranslateCTM(gc_, rect.origin.x - srcx - 0.5, rect.origin.y - srcy + sh - 0.5);
|
||||||
CGContextScaleCTM(gc_, 1, -1);
|
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);
|
CGContextDrawImage(gc_, CGRectMake(0, 0, sw, sh), cgimg);
|
||||||
CGContextRestoreGState(gc_);
|
CGContextRestoreGState(gc_);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1) {
|
|||||||
CGContextMoveToPoint(gc_, x, y);
|
CGContextMoveToPoint(gc_, x, y);
|
||||||
CGContextAddLineToPoint(gc_, x1, y);
|
CGContextAddLineToPoint(gc_, x1, y);
|
||||||
CGContextStrokePath(gc_);
|
CGContextStrokePath(gc_);
|
||||||
if (high_resolution()) {
|
if (high_resolution() || scale()>=2) {
|
||||||
/* On retina displays, all xyline() and yxline() functions produce lines that are half-unit
|
/* 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
|
(or one pixel) too short at both ends. This is corrected by filling at both ends rectangles
|
||||||
of size one unit by line-width.
|
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, y);
|
||||||
CGContextAddLineToPoint(gc_, x1, y2);
|
CGContextAddLineToPoint(gc_, x1, y2);
|
||||||
CGContextStrokePath(gc_);
|
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(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));
|
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_, x1, y2);
|
||||||
CGContextAddLineToPoint(gc_, x3, y2);
|
CGContextAddLineToPoint(gc_, x3, y2);
|
||||||
CGContextStrokePath(gc_);
|
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(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_));
|
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);
|
CGContextMoveToPoint(gc_, x, y);
|
||||||
CGContextAddLineToPoint(gc_, x, y1);
|
CGContextAddLineToPoint(gc_, x, y1);
|
||||||
CGContextStrokePath(gc_);
|
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, y-0.5, quartz_line_width_, 1));
|
||||||
CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y1-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_, x, y1);
|
||||||
CGContextAddLineToPoint(gc_, x2, y1);
|
CGContextAddLineToPoint(gc_, x2, y1);
|
||||||
CGContextStrokePath(gc_);
|
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, y-0.5, quartz_line_width_, 1));
|
||||||
CGContextFillRect(gc_, CGRectMake(x2-0.5, y1 - quartz_line_width_/2, 1 , quartz_line_width_));
|
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, y1);
|
||||||
CGContextAddLineToPoint(gc_, x2, y3);
|
CGContextAddLineToPoint(gc_, x2, y3);
|
||||||
CGContextStrokePath(gc_);
|
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, y-0.5, quartz_line_width_, 1));
|
||||||
CGContextFillRect(gc_, CGRectMake(x2 - quartz_line_width_/2, y3-0.5, quartz_line_width_, 1));
|
CGContextFillRect(gc_, CGRectMake(x2 - quartz_line_width_/2, y3-0.5, quartz_line_width_, 1));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user