summaryrefslogtreecommitdiff
path: root/src/drivers/Quartz
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/Quartz')
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H5
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx76
2 files changed, 80 insertions, 1 deletions
diff --git a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
index b6f58ec8f..69e00dfd0 100644
--- a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
+++ b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
@@ -21,6 +21,11 @@
#include <FL/platform.H>
class Fl_Quartz_Image_Surface_Driver : public Fl_Image_Surface_Driver {
+private:
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ CGImageRef mask_;
+ void mask(const Fl_RGB_Image *) FL_OVERRIDE;
+#endif
void end_current() FL_OVERRIDE;
public:
FLWindow *pre_window;
diff --git a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
index 451078484..fb522745a 100644
--- a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
+++ b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
@@ -1,7 +1,7 @@
//
// Draw-to-image code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2018 by Bill Spitzak and others.
+// Copyright 1998-2023 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
@@ -23,6 +23,9 @@
Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ mask_ = NULL;
+#endif
int W = w, H = h;
float s = 1;
if (high_res) {
@@ -49,6 +52,12 @@ Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int
}
Fl_Quartz_Image_Surface_Driver::~Fl_Quartz_Image_Surface_Driver() {
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (mask_) {
+ CGImageRelease(mask_);
+ }
+#endif
+ if (offscreen) CGContextRestoreGState((CGContextRef)offscreen);
if (offscreen && !external_offscreen) {
void *data = CGBitmapContextGetData((CGContextRef)offscreen);
free(data);
@@ -56,6 +65,7 @@ Fl_Quartz_Image_Surface_Driver::~Fl_Quartz_Image_Surface_Driver() {
}
delete driver();
}
+
void Fl_Quartz_Image_Surface_Driver::set_current() {
Fl_Surface_Device::set_current();
@@ -63,6 +73,15 @@ void Fl_Quartz_Image_Surface_Driver::set_current() {
driver()->gc((CGContextRef)offscreen);
fl_window = 0;
((Fl_Quartz_Graphics_Driver*)driver())->high_resolution( CGBitmapContextGetWidth((CGContextRef)offscreen) > (size_t)width );
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (mask_) {
+ int W, H;
+ printable_rect(&W, &H);
+ CGContextSaveGState((CGContextRef)offscreen);
+ CGContextClipToMask((CGContextRef)offscreen, CGRectMake(0,0,W,H), mask_); // 10.4
+ CGContextSaveGState((CGContextRef)offscreen);
+ }
+# endif
}
void Fl_Quartz_Image_Surface_Driver::translate(int x, int y) {
@@ -79,6 +98,13 @@ void Fl_Quartz_Image_Surface_Driver::untranslate() {
Fl_RGB_Image* Fl_Quartz_Image_Surface_Driver::image()
{
CGContextFlush((CGContextRef)offscreen);
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (mask_) {
+ CGContextRestoreGState((CGContextRef)offscreen);
+ CGImageRelease(mask_);
+ mask_ = NULL;
+ }
+#endif
int W = (int)CGBitmapContextGetWidth((CGContextRef)offscreen);
int H = (int)CGBitmapContextGetHeight((CGContextRef)offscreen);
int bpr = (int)CGBitmapContextGetBytesPerRow((CGContextRef)offscreen);
@@ -101,6 +127,54 @@ Fl_RGB_Image* Fl_Quartz_Image_Surface_Driver::image()
void Fl_Quartz_Image_Surface_Driver::end_current()
{
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (mask_) {
+ CGContextRestoreGState((CGContextRef)offscreen);
+ CGContextRestoreGState((CGContextRef)offscreen);
+ }
+# endif
fl_window = pre_window;
Fl_Surface_Device::end_current();
}
+
+
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+
+static void MyProviderReleaseData (void *info, const void *data, size_t size) {
+ delete[] (uchar*)data;
+}
+
+
+void Fl_Quartz_Image_Surface_Driver::mask(const Fl_RGB_Image *img) {
+ if (!&CGContextClipToMask) return;
+ int W = (int)CGBitmapContextGetWidth((CGContextRef)offscreen);
+ int H = (int)CGBitmapContextGetHeight((CGContextRef)offscreen);
+ bool using_copy = false;
+ if (W != img->data_w() || H != img->data_h()) {
+ Fl_RGB_Image *copy = (Fl_RGB_Image*)img->copy(W, H);
+ img = copy;
+ using_copy = true;
+ }
+
+ int i, d = img->d(), w = img->data_w(), h = img->data_h();
+ // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits
+ int bytes_per_row = (img->ld() ? img->ld() : w * d);
+ uchar *from = new uchar[w * h];
+ for ( i = 0; i < h; i++) {
+ const uchar *p = img->array + bytes_per_row * i;
+ const uchar *last = p + bytes_per_row;
+ uchar *q = from + (h - 1 - i) * w;
+ while (p < last) {
+ unsigned u = *p++;
+ u += *p++;
+ u += *p++;
+ *q++ = ~(u/3);
+ }
+ }
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData);
+ mask_ = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
+ CFRelease(provider);
+ if (using_copy) delete img;
+}
+
+#endif