Browse Source

Add clearData method to handle reassignment of src, and clean up mime data memory handling.

v1.x
c-spencer 13 years ago
parent
commit
4c5962b90e
  1. 92
      src/Image.cc
  2. 5
      src/Image.h

92
src/Image.cc

@ -127,6 +127,30 @@ Image::GetSource(Local<String>, const AccessorInfo &info) {
return scope.Close(String::New(img->filename ? img->filename : "")); return scope.Close(String::New(img->filename ? img->filename : ""));
} }
/*
* Clean up assets and variables.
*/
void
Image::clearData() {
if (_surface) {
cairo_surface_destroy(_surface);
V8::AdjustAmountOfExternalAllocatedMemory(-_data_len);
_data_len = 0;
_surface = NULL;
}
free(_data);
_data = NULL;
width = height = 0;
free(filename);
filename = NULL;
state = DEFAULT;
}
/* /*
* Set src path. * Set src path.
*/ */
@ -137,6 +161,8 @@ Image::SetSource(Local<String>, Local<Value> val, const AccessorInfo &info) {
Image *img = ObjectWrap::Unwrap<Image>(info.This()); Image *img = ObjectWrap::Unwrap<Image>(info.This());
cairo_status_t status = CAIRO_STATUS_READ_ERROR; cairo_status_t status = CAIRO_STATUS_READ_ERROR;
img->clearData();
// url string // url string
if (val->IsString()) { if (val->IsString()) {
String::AsciiValue src(val); String::AsciiValue src(val);
@ -270,10 +296,6 @@ Image::Image() {
filename = NULL; filename = NULL;
_data = NULL; _data = NULL;
_data_len = 0; _data_len = 0;
#if CAIRO_VERSION_MINOR >= 10
_mime_data = NULL;
_mime_data_len = 0;
#endif
_surface = NULL; _surface = NULL;
width = height = 0; width = height = 0;
state = DEFAULT; state = DEFAULT;
@ -284,21 +306,7 @@ Image::Image() {
*/ */
Image::~Image() { Image::~Image() {
if (_surface) { clearData();
V8::AdjustAmountOfExternalAllocatedMemory(-_data_len);
cairo_surface_destroy(_surface);
}
free(_data);
#if CAIRO_VERSION_MINOR >= 10
if (_mime_data) {
V8::AdjustAmountOfExternalAllocatedMemory(-_mime_data_len);
free(_mime_data);
}
#endif
free(filename);
} }
/* /*
@ -326,7 +334,6 @@ Image::loaded() {
width = cairo_image_surface_get_width(_surface); width = cairo_image_surface_get_width(_surface);
height = cairo_image_surface_get_height(_surface); height = cairo_image_surface_get_height(_surface);
_data_len = height * cairo_image_surface_get_stride(_surface); _data_len = height * cairo_image_surface_get_stride(_surface);
// TODO: adjust accordingly when re-assigned src
V8::AdjustAmountOfExternalAllocatedMemory(_data_len); V8::AdjustAmountOfExternalAllocatedMemory(_data_len);
if (!onload.IsEmpty()) { if (!onload.IsEmpty()) {
@ -757,17 +764,42 @@ Image::decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len) {
return assignDataAsMime(buf, len, CAIRO_MIME_TYPE_JPEG); return assignDataAsMime(buf, len, CAIRO_MIME_TYPE_JPEG);
} }
/*
* Helper function for disposing of a mime data closure.
*/
void
clearMimeData(void *closure) {
V8::AdjustAmountOfExternalAllocatedMemory(-((read_closure_t *)closure)->len);
free(((read_closure_t *) closure)->buf);
free(closure);
}
/*
* Assign a given buffer as mime data against the surface.
* The provided buffer will be copied, and the copy will
* be automatically freed when the surface is destroyed.
*/
cairo_status_t cairo_status_t
Image::assignDataAsMime(uint8_t *data, int len, const char *mime_type) { Image::assignDataAsMime(uint8_t *data, int len, const char *mime_type) {
_mime_data = (uint8_t *) malloc(len); uint8_t *mime_data = (uint8_t *) malloc(len);
if (!_mime_data) return CAIRO_STATUS_NO_MEMORY; if (!mime_data) return CAIRO_STATUS_NO_MEMORY;
V8::AdjustAmountOfExternalAllocatedMemory(len); read_closure_t *mime_closure = (read_closure_t *) malloc(sizeof(read_closure_t));
if (!mime_closure) {
free(mime_data);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy(_mime_data, data, len); memcpy(mime_data, data, len);
_mime_data_len = len;
return cairo_surface_set_mime_data(_surface, mime_type, _mime_data, _mime_data_len, free, _mime_data); mime_closure->buf = mime_data;
mime_closure->len = len;
V8::AdjustAmountOfExternalAllocatedMemory(len);
return cairo_surface_set_mime_data(_surface, mime_type, mime_data, len, clearMimeData, mime_closure);
} }
#endif #endif
@ -803,8 +835,6 @@ cairo_status_t
Image::loadJPEG(FILE *stream) { Image::loadJPEG(FILE *stream) {
cairo_status_t status; cairo_status_t status;
printf("loadJPEG\n");
if (data_mode == DATA_IMAGE) { // Can lazily read in the JPEG. if (data_mode == DATA_IMAGE) { // Can lazily read in the JPEG.
// JPEG setup // JPEG setup
struct jpeg_decompress_struct info; struct jpeg_decompress_struct info;
@ -836,12 +866,6 @@ Image::loadJPEG(FILE *stream) {
fread(buf, len, 1, stream); fread(buf, len, 1, stream);
fclose(stream); fclose(stream);
status = loadJPEGFromBuffer(buf, len);
if (status) {
free(buf);
return status;
}
switch (data_mode) { switch (data_mode) {
case DATA_IMAGE: // Can't be this, but compiler warning. case DATA_IMAGE: // Can't be this, but compiler warning.
case DATA_IMAGE_AND_MIME: case DATA_IMAGE_AND_MIME:

5
src/Image.h

@ -45,6 +45,7 @@ class Image: public node::ObjectWrap {
cairo_status_t loadFromBuffer(uint8_t *buf, unsigned len); cairo_status_t loadFromBuffer(uint8_t *buf, unsigned len);
cairo_status_t loadPNGFromBuffer(uint8_t *buf); cairo_status_t loadPNGFromBuffer(uint8_t *buf);
cairo_status_t loadPNG(); cairo_status_t loadPNG();
void clearData();
#ifdef HAVE_GIF #ifdef HAVE_GIF
cairo_status_t loadGIFFromBuffer(uint8_t *buf, unsigned len); cairo_status_t loadGIFFromBuffer(uint8_t *buf, unsigned len);
cairo_status_t loadGIF(FILE *stream); cairo_status_t loadGIF(FILE *stream);
@ -88,10 +89,6 @@ class Image: public node::ObjectWrap {
cairo_surface_t *_surface; cairo_surface_t *_surface;
uint8_t *_data; uint8_t *_data;
int _data_len; int _data_len;
#if CAIRO_VERSION_MINOR >= 10
uint8_t *_mime_data;
int _mime_data_len;
#endif
~Image(); ~Image();
}; };

Loading…
Cancel
Save