Browse Source

Added closure_destroy(), and implemented some ToBuffer() fixes by Olaf

v1.x
Tj Holowaychuk 14 years ago
parent
commit
fde7404e08
  1. 40
      src/Canvas.cc
  2. 14
      src/closure.h

40
src/Canvas.cc

@ -106,17 +106,29 @@ Canvas::SetHeight(Local<String> prop, Local<Value> val, const AccessorInfo &info
static cairo_status_t static cairo_status_t
toBuffer(void *c, const uint8_t *data, unsigned len) { toBuffer(void *c, const uint8_t *data, unsigned len) {
closure_t *closure = (closure_t *) c; closure_t *closure = (closure_t *) c;
if (closure->len) {
closure->data = (uint8_t *) realloc(closure->data, closure->len + len); // Olaf (2011-02-21): Store more data, but don't call realloc() on every chunk.
if (!closure->data) return CAIRO_STATUS_NO_MEMORY; // Also, keep track of how much memory is used
memcpy(closure->data + closure->len, data, len); if (closure->len + len > closure->max_len) {
closure->len += len; uint8_t * new_data;
} else { unsigned new_max_len = closure->max_len;
closure->data = (uint8_t *) malloc(len);
if (!closure->data) return CAIRO_STATUS_NO_MEMORY; // Round up the buffer size to be a multiple of 1024 bytes.
memcpy(closure->data, data, len); new_max_len = (closure->max_len + len + 1023) & ~1023;
closure->len += len;
new_data = (uint8_t *) realloc(closure->data, new_max_len);
if (new_data == NULL) return CAIRO_STATUS_NO_MEMORY;
// Keep track of how much more memory we just allocated.
V8::AdjustAmountOfExternalAllocatedMemory(new_max_len - closure->max_len);
closure->data = new_data;
closure->max_len = new_max_len;
} }
memcpy(closure->data + closure->len, data, len);
closure->len += len;
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
@ -158,7 +170,7 @@ Canvas::EIO_AfterToBuffer(eio_req *req) {
closure->canvas->Unref(); closure->canvas->Unref();
closure->pfn.Dispose(); closure->pfn.Dispose();
free(closure->data); closure_destroy(closure);
free(closure); free(closure);
return 0; return 0;
} }
@ -186,18 +198,22 @@ Canvas::ToBuffer(const Arguments &args) {
return Undefined(); return Undefined();
} else { } else {
closure_t closure; closure_t closure;
closure.len = 0; // Olaf (2011-02-21): zero everything
memset(&closure, 0, sizeof(closure));
TryCatch try_catch; TryCatch try_catch;
cairo_status_t status = cairo_surface_write_to_png_stream(canvas->surface(), toBuffer, &closure); cairo_status_t status = cairo_surface_write_to_png_stream(canvas->surface(), toBuffer, &closure);
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
closure_destroy(&closure);
return try_catch.ReThrow(); return try_catch.ReThrow();
} else if (status) { } else if (status) {
closure_destroy(&closure);
return ThrowException(Canvas::Error(status)); return ThrowException(Canvas::Error(status));
} else { } else {
Buffer *buf = Buffer::New(closure.len); Buffer *buf = Buffer::New(closure.len);
memcpy(Buffer::Data(buf->handle_), closure.data, closure.len); memcpy(Buffer::Data(buf->handle_), closure.data, closure.len);
closure_destroy(&closure);
return buf->handle_; return buf->handle_;
} }
} }

14
src/closure.h

@ -16,9 +16,23 @@ typedef struct {
Persistent<Function> pfn; Persistent<Function> pfn;
Handle<Function> fn; Handle<Function> fn;
unsigned len; unsigned len;
unsigned max_len;
uint8_t *data; uint8_t *data;
Canvas *canvas; Canvas *canvas;
cairo_status_t status; cairo_status_t status;
} closure_t; } closure_t;
/*
* Free the given closure's data,
* and hint V8 at the memory dealloc.
*/
void
closure_destroy(closure_t *closure) {
if (closure->len) {
free(closure->data);
V8::AdjustAmountOfExternalAllocatedMemory(-closure->max_len);
}
}
#endif /* __NODE_CLOSURE_H__ */ #endif /* __NODE_CLOSURE_H__ */

Loading…
Cancel
Save