summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2015-02-10 14:33:51 +0000
committerManolo Gouy <Manolo>2015-02-10 14:33:51 +0000
commitdb8a39ae4588c191524a1b4898b9c4f5720fff52 (patch)
tree0c4e13849d5ed2aec887bf49e8669a3f5d4a3f72 /src
parent998a6be711e96695f8d920ae0926f7c067d939a2 (diff)
Mac OS: more parsimonious memory usage when drawing Fl_RGB_Image. The image data are no longer duplicated when printing an image with
alloc_array = 1. Duplication remains when printing with alloc_array = 0. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10568 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Image.cxx29
-rw-r--r--src/fl_draw_pixmap.cxx2
2 files changed, 23 insertions, 8 deletions
diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx
index 24d318cdb..b9b324004 100644
--- a/src/Fl_Image.cxx
+++ b/src/Fl_Image.cxx
@@ -197,15 +197,17 @@ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg):
/** The destructor frees all memory and server resources that are used by the image. */
Fl_RGB_Image::~Fl_RGB_Image() {
- uncache();
- if (alloc_array) delete[] (uchar *)array;
+ if (id_) CGImageRelease((CGImageRef)id_);
+ else if (alloc_array) delete[] (uchar *)array;
}
void Fl_RGB_Image::uncache() {
#ifdef __APPLE_QUARTZ__
if (id_) {
+ if (mask_) *(bool*)mask_ = false;
CGImageRelease((CGImageRef)id_);
id_ = 0;
+ mask_ = NULL;
}
#else
if (id_) {
@@ -544,7 +546,8 @@ static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h
#ifdef __APPLE__
static void imgProviderReleaseData (void *info, const void *data, size_t size)
{
- delete[] (unsigned char *)data;
+ if (!info || *(bool*)info) delete[] (unsigned char *)data;
+ delete (bool*)info;
}
void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
@@ -561,7 +564,16 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP,
CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
int ld = img->ld();
if (!ld) ld = img->w() * img->d();
- CGDataProviderRef src = CGDataProviderCreateWithData( NULL, img->array, ld * img->h(), NULL);
+ // If img->alloc_array == 0, the CGImage data provider must not release the image data.
+ // If img->alloc_array != 0, the CGImage data provider will take responsibilty of deleting RGB image data after use:
+ // when the CGImage is deallocated, the release callback of its data provider
+ // (imgProviderReleaseData) is called and can delete the RGB image data.
+ // If the CGImage is printed, it is not deallocated until after the end of the page,
+ // therefore, with img->alloc_array != 0, the RGB image can be safely deleted any time after return from this function.
+ // The previously unused mask_ member allows to make sure the RGB image data is not deleted by Fl_RGB_Image::uncache().
+ if (img->alloc_array) img->mask_ = new bool(true);
+ CGDataProviderRef src = CGDataProviderCreateWithData(img->mask_, img->array, ld * img->h(),
+ img->alloc_array?imgProviderReleaseData:NULL);
img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld,
lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast,
src, 0L, false, kCGRenderingIntentDefault);
@@ -569,16 +581,17 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP,
CGDataProviderRelease(src);
}
if (img->id_ && fl_gc) {
- if (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id && !CGImageGetShouldInterpolate((CGImageRef)img->id_)) {
- // when printing, duplicate the image data so it can be deleted later, after page end,
- // by the release-callback of the image data provider
+ if (!img->alloc_array && Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id && !CGImageGetShouldInterpolate((CGImageRef)img->id_)) {
+ // When printing, the image data is used when the page is completed, that is, after return from this function.
+ // If the image has alloc_array = 0, we must protect against image data being freed before it is used:
+ // we duplicate the image data and have it deleted after use by the release-callback of the CGImage data provider
Fl_RGB_Image* img2 = (Fl_RGB_Image*)img->copy();
img2->alloc_array = 0;
const uchar *img_bytes = img2->array;
int ld = img2->ld();
if (!ld) ld = img2->w() * img2->d();
delete img2;
- CGImageRelease((CGImageRef)img->id_);
+ img->uncache();
CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
CGDataProviderRef src = CGDataProviderCreateWithData( NULL, img_bytes, ld * img->h(), imgProviderReleaseData);
img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld,
diff --git a/src/fl_draw_pixmap.cxx b/src/fl_draw_pixmap.cxx
index afb0935b7..ff5f1985f 100644
--- a/src/fl_draw_pixmap.cxx
+++ b/src/fl_draw_pixmap.cxx
@@ -253,8 +253,10 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
#ifdef __APPLE_QUARTZ__
if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) {
Fl_RGB_Image* rgb = new Fl_RGB_Image(buffer, w, h, 4);
+ rgb->alloc_array = 1;
rgb->draw(x, y);
delete rgb;
+ return 1;
} else {
#endif // __APPLE_QUARTZ__
// build the mask bitmap used by Fl_Pixmap: