Continue support for GUI rescaling under MacOS: fix Fl_Overlay_Window.

This patch also improves by simplification the code of class Fl_Quartz_Image_Surface_Driver:
because, under the driver model, there's a separate graphics content for the display and for 
each offscreen buffer, it's possible to reverse the drawing orientation (draw from top to bottom) 
once at offscreen creation. It's thus no longer necessary to reverse orientation in 
Fl_Quartz_Graphics_Driver::restore_clip() specifically for offscreen buffers.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12603 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2017-12-23 06:34:42 +00:00
parent c44382e973
commit e1893334fd
5 changed files with 43 additions and 41 deletions

View File

@ -3349,6 +3349,10 @@ void Fl_Cocoa_Window_Driver::make_current()
fl_window = i->xid;
((Fl_Quartz_Graphics_Driver&)Fl_Graphics_Driver::default_driver()).high_resolution( mapped_to_retina() );
if (pWindow->as_overlay_window() && other_xid && changed_resolution()) {
destroy_double_buffer();
changed_resolution(false);
}
NSGraphicsContext *nsgc;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if (fl_mac_os_version >= 100400)

View File

@ -104,6 +104,7 @@ public:
virtual void draw_end();
virtual void make_current();
virtual void label(const char *name, const char *mininame);
virtual void destroy_double_buffer();
virtual void show();
virtual void resize(int X,int Y,int W,int H);
virtual void hide();

View File

@ -3,7 +3,7 @@
//
// Definition of Apple Cocoa 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
@ -22,10 +22,11 @@
#include "../Quartz/Fl_Quartz_Graphics_Driver.H"
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Overlay_Window.H>
#include <FL/Fl_Image_Surface.H>
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <FL/x.H>
#include <ApplicationServices/ApplicationServices.h>
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
{
@ -65,33 +66,44 @@ void Fl_Cocoa_Window_Driver::flush_overlay()
if (!oWindow->shown()) return;
pWindow->make_current(); // make sure fl_gc is non-zero
Fl_X *myi = Fl_X::i(pWindow);
if (!myi) return; // window not yet created
if (!other_xid) {
other_xid = fl_create_offscreen(oWindow->w(), oWindow->h());
oWindow->clear_damage(FL_DAMAGE_ALL);
Fl_Quartz_Graphics_Driver *g_driver = (Fl_Quartz_Graphics_Driver*)&Fl_Graphics_Driver::default_driver();
float s = g_driver->scale() * (mapped_to_retina() ? 2 : 1);
if (!other_xid) { // create offscreen accounting for GUI scaling and retina
other_xid = (Fl_Offscreen)new Fl_Image_Surface(s * oWindow->w(), s * oWindow->h());
oWindow->clear_damage(FL_DAMAGE_ALL);
// scale the offscreen buffer's graphics context
Fl_Surface_Device::push_current((Fl_Image_Surface*)other_xid);
CGContextRestoreGState(fl_gc);
CGContextScaleCTM(fl_gc, s, s);
CGContextSaveGState(fl_gc);
Fl_Surface_Device::pop_current();
}
if (oWindow->damage() & ~FL_DAMAGE_EXPOSE) {
Fl_X *myi = Fl_X::i(pWindow);
fl_clip_region(myi->region); myi->region = 0;
Fl_Surface_Device::push_current((Fl_Image_Surface*)other_xid);
draw();
Fl_Surface_Device::pop_current();
}
if (oWindow->damage() & ~FL_DAMAGE_EXPOSE) {
fl_clip_region(myi->region); myi->region = 0;
if ( other_xid ) {
fl_begin_offscreen( other_xid );
fl_clip_region( 0 );
draw();
fl_end_offscreen();
} else {
draw();
}
}
if (erase_overlay) fl_clip_region(0);
// on Irix (at least) it is faster to reduce the area copied to
// the current clip region:
int X,Y,W,H; fl_clip_box(0,0,oWindow->w(),oWindow->h(),X,Y,W,H);
if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid, X, Y);
if (other_xid) {
CGContextSaveGState(fl_gc);
CGContextScaleCTM(fl_gc, 1/s, 1/s);
// copy offscreen to window using adequate scaling
fl_copy_offscreen(0, 0, s * oWindow->w(),s * oWindow->h(), ((Fl_Image_Surface*)other_xid)->offscreen(), 0, 0);
CGContextRestoreGState(fl_gc);
}
if (overlay() == oWindow) oWindow->draw_overlay();
}
void Fl_Cocoa_Window_Driver::destroy_double_buffer()
{
if (pWindow->as_overlay_window()) delete (Fl_Image_Surface*)other_xid;
other_xid = 0;
}
void Fl_Cocoa_Window_Driver::draw_begin()
{
if (!Fl_Surface_Device::surface()->driver()->has_feature(Fl_Graphics_Driver::NATIVE)) return;

View File

@ -296,19 +296,6 @@ void Fl_Quartz_Graphics_Driver::restore_clip() {
CGContextRestoreGState(gc_);
CGContextSaveGState(gc_);
}
// FLTK has only one global graphics state.
// This copies the FLTK state into the current Quartz context
if ( ! fl_window ) { // a bitmap context
CGFloat hgt = CGBitmapContextGetHeight(gc_);
CGAffineTransform at = CGContextGetCTM(gc_);
CGFloat offset = 0.5;
if (at.a != 1 && at.a == at.d && at.b == 0 && at.c == 0) { // proportional scaling, no rotation
hgt /= at.a;
offset /= at.a;
}
CGContextTranslateCTM(gc_, offset, hgt-offset);
CGContextScaleCTM(gc_, 1.0f, -1.0f); // now 0,0 is top-left point of the context
}
color(color());
quartz_restore_line_style();
if (r) { //apply program clip

View File

@ -57,9 +57,9 @@ Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int
CGContextScaleCTM(offscreen, 2, 2);
}
CGContextSetShouldAntialias(offscreen, false);
CGContextSaveGState(offscreen);
CGContextTranslateCTM(offscreen, 0, height);
CGContextTranslateCTM(offscreen, 0, height);
CGContextScaleCTM(offscreen, 1.0f, -1.0f);
CGContextSaveGState(offscreen);
CGContextSetRGBFillColor(offscreen, 1, 1, 1, 0);
CGContextFillRect(offscreen, CGRectMake(0,0,w,h));
}
@ -84,10 +84,8 @@ void Fl_Quartz_Image_Surface_Driver::set_current() {
void Fl_Quartz_Image_Surface_Driver::translate(int x, int y) {
CGContextRestoreGState(offscreen);
CGContextSaveGState(offscreen);
CGContextTranslateCTM(offscreen, x, -y);
CGContextTranslateCTM(offscreen, x, y);
CGContextSaveGState(offscreen);
CGContextTranslateCTM(offscreen, 0, height);
CGContextScaleCTM(offscreen, 1.0f, -1.0f);
}
void Fl_Quartz_Image_Surface_Driver::untranslate() {