Added full support of retina displays on the mac platform.

On such displays, one drawing unit equals two pixels.
The fl_xyline() and fl_yxline() functions are modified to perform
extra operations when drawing to a window on a retina display.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10463 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2014-11-19 16:23:36 +00:00
parent 659480f28b
commit f52b457cc2
5 changed files with 53 additions and 7 deletions

View File

@ -546,6 +546,10 @@ public:
*/
class FL_EXPORT Fl_Display_Device : public Fl_Surface_Device {
static Fl_Display_Device *_display; // the platform display device
#ifdef __APPLE__
friend class Fl_X;
static bool high_res_window_; // true when drawing to a window of a retina display
#endif
public:
static const char *class_id;
const char *class_name() {return class_id;};
@ -553,6 +557,9 @@ public:
Fl_Display_Device(Fl_Graphics_Driver *graphics_driver);
/** Returns the platform display device. */
static inline Fl_Display_Device *display_device() {return _display;};
#ifdef __APPLE__
static bool high_resolution() {return high_res_window_;}
#endif
};
/**

View File

@ -162,6 +162,7 @@ public:
static int insertion_point_location(int *px, int *py, int *pheight); // computes window coordinates & height of insertion point
static const int CoreText_threshold; // Mac OS version from which the Core Text API is used to display text
static Fl_Fontdesc* calc_fl_fonts(void); // computes the fl_fonts global variable
static void set_high_resolution(bool);
};
extern Window fl_window;

View File

@ -26,6 +26,7 @@ const char *Fl_Display_Device::class_id = "Fl_Display_Device";
const char *Fl_Graphics_Driver::class_id = "Fl_Graphics_Driver";
#if defined(__APPLE__) || defined(FL_DOXYGEN)
const char *Fl_Quartz_Graphics_Driver::class_id = "Fl_Quartz_Graphics_Driver";
bool Fl_Display_Device::high_res_window_ = false;
#endif
#if defined(WIN32) || defined(FL_DOXYGEN)
const char *Fl_GDI_Graphics_Driver::class_id = "Fl_GDI_Graphics_Driver";

View File

@ -792,9 +792,8 @@ double fl_mac_flush_and_wait(double time_to_wait) {
time_to_wait = 0.0;
double retval = fl_wait(time_to_wait);
if (fl_gc) {
CGContextFlush(fl_gc);
fl_gc = 0;
}
Fl_X::q_release_context();
}
[pool release];
return retval;
}
@ -2989,6 +2988,9 @@ void Fl_Window::make_current()
if (make_current_counts) make_current_counts++;
Fl_X::q_release_context();
fl_window = i->xid;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
Fl_X::set_high_resolution(fl_mac_os_version >= 100700 && [fl_window backingScaleFactor] > 1.0);
#endif
current_ = this;
NSGraphicsContext *nsgc = through_drawRect ? [NSGraphicsContext currentContext] :
@ -3048,6 +3050,9 @@ void Fl_X::q_release_context(Fl_X *x) {
if (x && x->gc!=fl_gc) return;
if (!fl_gc) return;
CGContextRestoreGState(fl_gc); // KEEP IT: matches the CGContextSaveGState of make_current
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
Fl_X::set_high_resolution(false);
#endif
CGContextFlush(fl_gc);
fl_gc = 0;
#if defined(FLTK_USE_CAIRO)
@ -3073,6 +3078,11 @@ void Fl_X::q_end_image() {
CGContextRestoreGState(fl_gc);
}
void Fl_X::set_high_resolution(bool new_val)
{
Fl_Display_Device::high_res_window_ = new_val;
}
void Fl_Copy_Surface::complete_copy_pdf_and_tiff()
{
CGContextRestoreGState(gc);
@ -3583,6 +3593,7 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
printer.origin(w/2, h/2);
#endif
printer.print_window(win, -ww/2, -wh/2);
//printer.print_window_part(win,0,0,win->w(),win->h(), -ww/2, -wh/2);
printer.end_page();
printer.end_job();
fl_unlock_function();
@ -3933,9 +3944,7 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
} else {
NSView *winview = nil;
if ( through_drawRect && Fl_Window::current() == win ) {
CGFloat epsilon = 0;
if (fl_mac_os_version >= 100600) epsilon = 0.5; // STR #2887
rect = NSMakeRect(x - epsilon, y - epsilon, w, h);
rect = NSMakeRect(x - 0.5, y - 0.5, w, h);
}
else {
rect = NSMakeRect(x, win->h()-(y+h), w, h);

View File

@ -40,7 +40,7 @@ extern int fl_line_width_;
#ifdef __APPLE_QUARTZ__
extern float fl_quartz_line_width_;
#define USINGQUARTZPRINTER (Fl_Surface_Device::surface() != Fl_Display_Device::display_device())
#define USINGQUARTZPRINTER (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id)
#endif
#ifdef USE_X11
@ -205,6 +205,14 @@ void Fl_Graphics_Driver::xyline(int x, int y, int x1) {
CGContextMoveToPoint(fl_gc, x, y);
CGContextAddLineToPoint(fl_gc, x1, y);
CGContextStrokePath(fl_gc);
if (Fl_Display_Device::high_resolution()) {
/* 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.
*/
CGContextFillRect(fl_gc, CGRectMake(x-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
CGContextFillRect(fl_gc, CGRectMake(x1-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
}
if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
#else
# error unsupported platform
@ -229,6 +237,10 @@ void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
CGContextAddLineToPoint(fl_gc, x1, y);
CGContextAddLineToPoint(fl_gc, x1, y2);
CGContextStrokePath(fl_gc);
if (Fl_Display_Device::high_resolution()) {
CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
CGContextFillRect(fl_gc, CGRectMake(x1 - fl_quartz_line_width_/2, y2-0.5, fl_quartz_line_width_, 1));
}
if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
#else
#error unsupported platform
@ -256,6 +268,10 @@ void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
CGContextAddLineToPoint(fl_gc, x1, y2);
CGContextAddLineToPoint(fl_gc, x3, y2);
CGContextStrokePath(fl_gc);
if (Fl_Display_Device::high_resolution()) {
CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
CGContextFillRect(fl_gc, CGRectMake(x3-0.5, y2 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
}
if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
#else
# error unsupported platform
@ -274,6 +290,10 @@ void Fl_Graphics_Driver::yxline(int x, int y, int y1) {
CGContextMoveToPoint(fl_gc, x, y);
CGContextAddLineToPoint(fl_gc, x, y1);
CGContextStrokePath(fl_gc);
if (Fl_Display_Device::high_resolution()) {
CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1));
CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y1-0.5, fl_quartz_line_width_, 1));
}
if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
#else
# error unsupported platform
@ -298,6 +318,10 @@ void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
CGContextAddLineToPoint(fl_gc, x, y1);
CGContextAddLineToPoint(fl_gc, x2, y1);
CGContextStrokePath(fl_gc);
if (Fl_Display_Device::high_resolution()) {
CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1));
CGContextFillRect(fl_gc, CGRectMake(x2-0.5, y1 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
}
if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
#else
# error unsupported platform
@ -325,6 +349,10 @@ void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
CGContextAddLineToPoint(fl_gc, x2, y1);
CGContextAddLineToPoint(fl_gc, x2, y3);
CGContextStrokePath(fl_gc);
if (Fl_Display_Device::high_resolution()) {
CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1));
CGContextFillRect(fl_gc, CGRectMake(x2 - fl_quartz_line_width_/2, y3-0.5, fl_quartz_line_width_, 1));
}
if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
#else
# error unsupported platform