write a DEBUG macro and change the render_threads stuff to use it. Shuffle the mutexes in render_threads around again to fix yet another bug... seems to work, but meh
committer: Tero Marttila <terom@fixme.fi>
#include <stdlib.h>
#include <png.h>
#include "common.h"
#include "render_struct.h"
#include "render_png_struct.h"
#include "render_png.h"
static void _render_png_write(png_structp png_ptr, png_bytep data, png_size_t length) {
struct render_png *ctx = png_get_io_ptr(png_ptr);
if (ctx->io_write_fn)
if (ctx->io_write_fn(data, length, ctx->cb_arg)) {
// error, doesn't return
png_error(png_ptr, "_render_png_write: io_write_fn");
}
}
static void _render_png_flush(png_structp png_ptr) {
struct render_png *ctx = png_get_io_ptr(png_ptr);
if (ctx->io_flush_fn)
if (ctx->io_flush_fn(ctx->cb_arg)) {
// error, doesn't return
png_error(png_ptr, "_render_png_flush: io_flush_fn");
}
}
static void _render_png_free (struct render_png *ctx) {
render_png_deinit(ctx);
if (ctx->owned_by_me)
free(ctx);
}
void render_png_deinit (struct render_png *ctx) {
// are we initialized?
if (ctx->png_ptr) {
// libpng error handling
if (setjmp(png_jmpbuf(ctx->png_ptr)))
ERROR("libpng");
png_destroy_write_struct(&ctx->png_ptr, &ctx->info_ptr);
}
return;
error:
WARNING("destroying our libpng structures failed, possible memory leak?");
}
/*
* Note that it's vitally important not to call any libpng functions directly,
* the error-handling setjmp will be invalid.
*/
int render_png_init (struct render_png *ctx, struct render *render) {
// store some info from the struct render
ctx->io_write_fn = render->io_write_fn;
ctx->io_flush_fn = render->io_flush_fn;
ctx->cb_arg = render->cb_arg;
// libpng initialization
if (!(ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
ERROR("png_create_write_struct");
if (!(ctx->info_ptr = png_create_info_struct(ctx->png_ptr)))
ERROR("png_create_info_struct");
// libpng error handling
if (setjmp(png_jmpbuf(ctx->png_ptr)))
ERROR("libpng");
if (render->io_stream) {
// use normal libpng I/O
// XXX: who fcloses this?
png_init_io(ctx->png_ptr, render->io_stream);
} else {
// setup our custom I/O callbacks
png_set_write_fn(ctx->png_ptr, ctx, &_render_png_write, &_render_png_flush);
}
// some PNG metadata
png_set_IHDR(ctx->png_ptr, ctx->info_ptr, render->img_w, render->img_h, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// write out the PNG header
png_write_info(ctx->png_ptr, ctx->info_ptr);
// success
return 0;
error:
render_png_deinit(ctx);
return -1;
}
struct render_png *render_png_alloc (struct render *render) {
struct render_png *ctx = NULL;
// calloc the render_png
if (!(ctx = calloc(1, sizeof(struct render_png))))
ERROR("calloc");
// I need to free it
ctx->owned_by_me = 1;
// init it
if (render_png_init(ctx, render))
goto error;
// success
return ctx;
error:
_render_png_free(ctx);
return NULL;
}
int render_png_row (struct render_png *ctx, unsigned char *rowbuf) {
// libpng error handling
if (setjmp(png_jmpbuf(ctx->png_ptr)))
ERROR("libpng");
// write it in
png_write_row(ctx->png_ptr, rowbuf);
// success
return 0;
error:
// don't free it here, our user needs to do that
return -1;
}
int render_png_done (struct render_png *ctx) {
// libpng error handling
if (setjmp(png_jmpbuf(ctx->png_ptr)))
ERROR("libpng");
// write end
png_write_end(ctx->png_ptr, ctx->info_ptr);
// free everything
_render_png_free(ctx);
// success
return 0;
error:
_render_png_free(ctx);
return -1;
}
int render_png_abort (struct render_png *ctx) {
// libpng error handling
if (setjmp(png_jmpbuf(ctx->png_ptr)))
ERROR("libpng");
// just free it
_render_png_free(ctx);
// success
return 0;
error:
free(ctx);
return -1;
}