summaryrefslogtreecommitdiff
path: root/image/png.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2011-05-07 23:35:57 +0000
committerVincent Sanders <vince@netsurf-browser.org>2011-05-07 23:35:57 +0000
commitf2e8be9fe75817a29eb7aeda08659944c0c69932 (patch)
tree6d0388888720ba06fd1bbfd276f122052aa76a67 /image/png.c
parent489c35c5f776c691a136efa9bb65dba2ef5183d1 (diff)
downloadnetsurf-f2e8be9fe75817a29eb7aeda08659944c0c69932.tar.gz
netsurf-f2e8be9fe75817a29eb7aeda08659944c0c69932.tar.bz2
Cleanup png code
only use the bitmap pointer in the png content the one in teh base content seems extraneous for png. svn path=/trunk/netsurf/; revision=12304
Diffstat (limited to 'image/png.c')
-rw-r--r--image/png.c556
1 files changed, 266 insertions, 290 deletions
diff --git a/image/png.c b/image/png.c
index 5469e6923..8a88a09c8 100644
--- a/image/png.c
+++ b/image/png.c
@@ -45,8 +45,8 @@
#ifndef png_jmpbuf
#warning you have an antique libpng
-#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
-#endif
+#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
#if PNG_LIBPNG_VER < 10209
#define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png)
@@ -58,278 +58,95 @@ typedef struct nspng_content {
png_structp png;
png_infop info;
int interlace;
- struct bitmap *bitmap; /**< Created NetSurf bitmap */
- size_t rowstride, bpp; /**< Bitmap rowstride and bpp */
- size_t rowbytes; /**< Number of bytes per row */
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+ size_t rowstride, bpp; /**< Bitmap rowstride and bpp */
+ size_t rowbytes; /**< Number of bytes per row */
} nspng_content;
-static nserror nspng_create(const content_handler *handler,
- lwc_string *imime_type, const http_parameter *params,
- llcache_handle *llcache, const char *fallback_charset,
- bool quirks, struct content **c);
-static nserror nspng_create_png_data(nspng_content *c);
-static bool nspng_process_data(struct content *c, const char *data,
- unsigned int size);
-static bool nspng_convert(struct content *c);
-static void nspng_destroy(struct content *c);
-static bool nspng_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-static bool nspng_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-static nserror nspng_clone(const struct content *old, struct content **newc);
-static content_type nspng_content_type(lwc_string *mime_type);
-
-static void info_callback(png_structp png, png_infop info);
-static void row_callback(png_structp png, png_bytep new_row,
- png_uint_32 row_num, int pass);
-static void end_callback(png_structp png, png_infop info);
-
-static const content_handler nspng_content_handler = {
- nspng_create,
- nspng_process_data,
- nspng_convert,
- NULL,
- nspng_destroy,
- NULL,
- NULL,
- NULL,
- nspng_redraw,
- nspng_redraw_tiled,
- NULL,
- NULL,
- nspng_clone,
- NULL,
- nspng_content_type,
- false
-};
-
static const char *nspng_types[] = {
"image/png"
};
static lwc_string *nspng_mime_types[NOF_ELEMENTS(nspng_types)];
-nserror nspng_init(void)
-{
- uint32_t i;
- lwc_error lerror;
- nserror error;
-
- for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
- lerror = lwc_intern_string(nspng_types[i],
- strlen(nspng_types[i]),
- &nspng_mime_types[i]);
- if (lerror != lwc_error_ok) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
- error = content_factory_register_handler(nspng_mime_types[i],
- &nspng_content_handler);
- if (error != NSERROR_OK)
- goto error;
- }
-
- return NSERROR_OK;
-
-error:
- nspng_fini();
-
- return error;
-}
-
-void nspng_fini(void)
-{
- uint32_t i;
-
- for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
- if (nspng_mime_types[i] != NULL)
- lwc_string_unref(nspng_mime_types[i]);
- }
-}
-
-nserror nspng_create(const content_handler *handler,
- lwc_string *imime_type, const http_parameter *params,
- llcache_handle *llcache, const char *fallback_charset,
- bool quirks, struct content **c)
-{
- nspng_content *png;
- nserror error;
-
- png = talloc_zero(0, nspng_content);
- if (png == NULL)
- return NSERROR_NOMEM;
-
- error = content__init(&png->base, handler, imime_type, params,
- llcache, fallback_charset, quirks);
- if (error != NSERROR_OK) {
- talloc_free(png);
- return error;
- }
-
- error = nspng_create_png_data(png);
- if (error != NSERROR_OK) {
- talloc_free(png);
- return error;
- }
-
- *c = (struct content *) png;
-
- return NSERROR_OK;
-}
-
-nserror nspng_create_png_data(nspng_content *c)
-{
- union content_msg_data msg_data;
-
- c->bitmap = NULL;
-
- c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- if (c->png == NULL) {
- msg_data.error = messages_get("NoMemory");
- content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
- warn_user("NoMemory", 0);
- return NSERROR_NOMEM;
- }
-
- c->info = png_create_info_struct(c->png);
- if (c->info == NULL) {
- png_destroy_read_struct(&c->png, &c->info, 0);
-
- msg_data.error = messages_get("NoMemory");
- content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
- warn_user("NoMemory", 0);
- return NSERROR_NOMEM;
- }
-
- if (setjmp(png_jmpbuf(c->png))) {
- png_destroy_read_struct(&c->png, &c->info, 0);
- LOG(("Failed to set callbacks"));
- c->png = NULL;
- c->info = NULL;
-
- msg_data.error = messages_get("PNGError");
- content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
- return NSERROR_NOMEM;
- }
-
- png_set_progressive_read_fn(c->png, c,
- info_callback, row_callback, end_callback);
-
- return NSERROR_OK;
-}
-
-
-bool nspng_process_data(struct content *c, const char *data, unsigned int size)
-{
- nspng_content *png = (nspng_content *) c;
- union content_msg_data msg_data;
-
- if (setjmp(png_jmpbuf(png->png))) {
- png_destroy_read_struct(&png->png, &png->info, 0);
- LOG(("Failed to process data"));
- png->png = NULL;
- png->info = NULL;
- if (png->bitmap != NULL) {
- bitmap_destroy(png->bitmap);
- png->bitmap = NULL;
- }
-
- msg_data.error = messages_get("PNGError");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
- }
-
- png_process_data(png->png, png->info, (uint8_t *) data, size);
-
- return true;
-}
-
+static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0};
+static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0};
+static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1};
+static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
/**
* info_callback -- PNG header has been completely received, prepare to process
* image data
*/
-
-void info_callback(png_structp png, png_infop info)
+static void info_callback(png_structp png_s, png_infop info)
{
int bit_depth, color_type, interlace, intent;
double gamma;
png_uint_32 width, height;
- nspng_content *c = png_get_progressive_ptr(png);
+ nspng_content *png_c = png_get_progressive_ptr(png_s);
/* Read the PNG details */
- png_get_IHDR(png, info, &width, &height, &bit_depth,
- &color_type, &interlace, 0, 0);
+ png_get_IHDR(png_s, info, &width, &height, &bit_depth,
+ &color_type, &interlace, 0, 0);
/* Claim the required memory for the converted PNG */
- c->bitmap = bitmap_create(width, height, BITMAP_NEW);
- if (c->bitmap == NULL) {
+ png_c->bitmap = bitmap_create(width, height, BITMAP_NEW);
+ if (png_c->bitmap == NULL) {
/* Failed -- bail out */
- longjmp(png_jmpbuf(png), 1);
+ longjmp(png_jmpbuf(png_s), 1);
}
- c->rowstride = bitmap_get_rowstride(c->bitmap);
- c->bpp = bitmap_get_bpp(c->bitmap);
+ png_c->rowstride = bitmap_get_rowstride(png_c->bitmap);
+ png_c->bpp = bitmap_get_bpp(png_c->bitmap);
- /* Set up our transformations */
+ /* Set up our transformations */
if (color_type == PNG_COLOR_TYPE_PALETTE)
- png_set_palette_to_rgb(png);
- if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
- png_set_expand_gray_1_2_4_to_8(png);
- if (png_get_valid(png, info, PNG_INFO_tRNS))
- png_set_tRNS_to_alpha(png);
+ png_set_palette_to_rgb(png_s);
+ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8))
+ png_set_expand_gray_1_2_4_to_8(png_s);
+ if (png_get_valid(png_s, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png_s);
if (bit_depth == 16)
- png_set_strip_16(png);
+ png_set_strip_16(png_s);
if (color_type == PNG_COLOR_TYPE_GRAY ||
- color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- png_set_gray_to_rgb(png);
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_s);
if (!(color_type & PNG_COLOR_MASK_ALPHA))
- png_set_filler(png, 0xff, PNG_FILLER_AFTER);
+ png_set_filler(png_s, 0xff, PNG_FILLER_AFTER);
/* gamma correction - we use 2.2 as our screen gamma
* this appears to be correct (at least in respect to !Browse)
* see http://www.w3.org/Graphics/PNG/all_seven.html for a test case
*/
- if (png_get_sRGB(png, info, &intent))
- png_set_gamma(png, 2.2, 0.45455);
- else {
- if (png_get_gAMA(png, info, &gamma))
- png_set_gamma(png, 2.2, gamma);
- else
- png_set_gamma(png, 2.2, 0.45455);
+ if (png_get_sRGB(png_s, info, &intent)) {
+ png_set_gamma(png_s, 2.2, 0.45455);
+ } else {
+ if (png_get_gAMA(png_s, info, &gamma)) {
+ png_set_gamma(png_s, 2.2, gamma);
+ } else {
+ png_set_gamma(png_s, 2.2, 0.45455);
+ }
}
+ png_read_update_info(png_s, info);
- png_read_update_info(png, info);
-
- c->rowbytes = png_get_rowbytes(png, info);
- c->interlace = (interlace == PNG_INTERLACE_ADAM7);
- c->base.width = width;
- c->base.height = height;
+ png_c->rowbytes = png_get_rowbytes(png_s, info);
+ png_c->interlace = (interlace == PNG_INTERLACE_ADAM7);
+ png_c->base.width = width;
+ png_c->base.height = height;
LOG(("size %li * %li, bpp %i, rowbytes %zu", (unsigned long)width,
- (unsigned long)height, bit_depth, c->rowbytes));
+ (unsigned long)height, bit_depth, png_c->rowbytes));
}
-
-static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0};
-static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0};
-static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1};
-static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
-
-void row_callback(png_structp png, png_bytep new_row,
- png_uint_32 row_num, int pass)
+static void row_callback(png_structp png_s, png_bytep new_row,
+ png_uint_32 row_num, int pass)
{
- nspng_content *c = png_get_progressive_ptr(png);
- unsigned long i, j, rowbytes = c->rowbytes;
- unsigned int start, step;
+ nspng_content *png_c = png_get_progressive_ptr(png_s);
+ unsigned long rowbytes = png_c->rowbytes;
unsigned char *buffer, *row;
/* Give up if there's no bitmap */
- if (c->bitmap == NULL)
+ if (png_c->bitmap == NULL)
return;
/* Abort if we've not got any data */
@@ -337,31 +154,35 @@ void row_callback(png_structp png, png_bytep new_row,
return;
/* Get bitmap buffer */
- buffer = bitmap_get_buffer(c->bitmap);
+ buffer = bitmap_get_buffer(png_c->bitmap);
if (buffer == NULL) {
/* No buffer, bail out */
- longjmp(png_jmpbuf(png), 1);
+ longjmp(png_jmpbuf(png_s), 1);
}
/* Calculate address of row start */
- row = buffer + (c->rowstride * row_num);
+ row = buffer + (png_c->rowstride * row_num);
/* Handle interlaced sprites using the Adam7 algorithm */
- if (c->interlace) {
+ if (png_c->interlace) {
+ unsigned long dst_off;
+ unsigned long src_off = 0;
+ unsigned int start, step;
+
start = interlace_start[pass];
step = interlace_step[pass];
row_num = interlace_row_start[pass] +
- interlace_row_step[pass] * row_num;
+ interlace_row_step[pass] * row_num;
/* Copy the data to our current row taking interlacing
* into consideration */
- row = buffer + (c->rowstride * row_num);
+ row = buffer + (png_c->rowstride * row_num);
- for (j = 0, i = start; i < rowbytes; i += step) {
- row[i++] = new_row[j++];
- row[i++] = new_row[j++];
- row[i++] = new_row[j++];
- row[i++] = new_row[j++];
+ for (dst_off = start; dst_off < rowbytes; dst_off += step) {
+ row[dst_off++] = new_row[src_off++];
+ row[dst_off++] = new_row[src_off++];
+ row[dst_off++] = new_row[src_off++];
+ row[dst_off++] = new_row[src_off++];
}
} else {
/* Do a fast memcpy of the row data */
@@ -370,23 +191,117 @@ void row_callback(png_structp png, png_bytep new_row,
}
-void end_callback(png_structp png, png_infop info)
+static void end_callback(png_structp png_s, png_infop info)
{
}
+static nserror nspng_create_png_data(nspng_content *png_c)
+{
+ union content_msg_data msg_data;
+
+ png_c->bitmap = NULL;
+
+ png_c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ if (png_c->png == NULL) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return NSERROR_NOMEM;
+ }
+
+ png_c->info = png_create_info_struct(png_c->png);
+ if (png_c->info == NULL) {
+ png_destroy_read_struct(&png_c->png, &png_c->info, 0);
+
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return NSERROR_NOMEM;
+ }
+
+ if (setjmp(png_jmpbuf(png_c->png))) {
+ png_destroy_read_struct(&png_c->png, &png_c->info, 0);
+ LOG(("Failed to set callbacks"));
+ png_c->png = NULL;
+ png_c->info = NULL;
+
+ msg_data.error = messages_get("PNGError");
+ content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
+ }
+
+ png_set_progressive_read_fn(png_c->png, png_c,
+ info_callback, row_callback, end_callback);
+
+ return NSERROR_OK;
+}
+
+static nserror nspng_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nspng_content *png_c;
+ nserror error;
+
+ png_c = talloc_zero(0, nspng_content);
+ if (png_c == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&png_c->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(png_c);
+ return error;
+ }
+
+ error = nspng_create_png_data(png_c);
+ if (error != NSERROR_OK) {
+ talloc_free(png_c);
+ return error;
+ }
+
+ *c = (struct content *)png_c;
+
+ return NSERROR_OK;
+}
-bool nspng_convert(struct content *c)
+static bool nspng_process_data(struct content *c, const char *data,
+ unsigned int size)
{
- nspng_content *png = (nspng_content *) c;
- const char *data;
- unsigned long size;
+ nspng_content *png_c = (nspng_content *)c;
+ union content_msg_data msg_data;
+
+ if (setjmp(png_jmpbuf(png_c->png))) {
+ png_destroy_read_struct(&png_c->png, &png_c->info, 0);
+ LOG(("Failed to process data"));
+ png_c->png = NULL;
+ png_c->info = NULL;
+ if (png_c->bitmap != NULL) {
+ bitmap_destroy(png_c->bitmap);
+ png_c->bitmap = NULL;
+ }
+
+ msg_data.error = messages_get("PNGError");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ png_process_data(png_c->png, png_c->info, (uint8_t *)data, size);
+
+ return true;
+}
+
+static bool nspng_convert(struct content *c)
+{
+ nspng_content *png_c = (nspng_content *) c;
char title[100];
- assert(png->png != NULL);
- assert(png->info != NULL);
+ assert(png_c->png != NULL);
+ assert(png_c->info != NULL);
- if (png->bitmap == NULL) {
+ if (png_c->bitmap == NULL) {
union content_msg_data msg_data;
msg_data.error = messages_get("PNGError");
@@ -395,19 +310,19 @@ bool nspng_convert(struct content *c)
return false;
}
- data = content__get_source_data(c, &size);
+ /* clean up png structures */
+ png_destroy_read_struct(&png_c->png, &png_c->info, 0);
- png_destroy_read_struct(&png->png, &png->info, 0);
+ c->size += (c->width * c->height * 4);
+ /* set title text */
snprintf(title, sizeof(title), messages_get("PNGTitle"),
- c->width, c->height, size);
+ c->width, c->height, c->size);
content__set_title(c, title);
- c->size += (c->width * c->height * 4);
+ bitmap_set_opaque(png_c->bitmap, bitmap_test_opaque(png_c->bitmap));
+ bitmap_modified(png_c->bitmap);
- c->bitmap = png->bitmap;
- bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
- bitmap_modified(c->bitmap);
content_set_ready(c);
content_set_done(c);
content_set_status(c, "");
@@ -416,92 +331,153 @@ bool nspng_convert(struct content *c)
}
-void nspng_destroy(struct content *c)
+static void nspng_destroy(struct content *c)
{
- nspng_content *png = (nspng_content *) c;
+ nspng_content *png_c = (nspng_content *) c;
- if (png->bitmap != NULL) {
- bitmap_destroy(png->bitmap);
+ if (png_c->bitmap != NULL) {
+ bitmap_destroy(png_c->bitmap);
}
}
-bool nspng_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour)
+static bool nspng_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour)
{
- assert(c->bitmap != NULL);
+ nspng_content *png_c = (nspng_content *) c;
- return plot.bitmap(x, y, width, height, c->bitmap,
- background_colour, BITMAPF_NONE);
+ assert(png_c->bitmap != NULL);
+
+ return plot.bitmap(x, y, width, height, png_c->bitmap,
+ background_colour, BITMAPF_NONE);
}
-bool nspng_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y)
+static bool nspng_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y)
{
+ nspng_content *png_c = (nspng_content *) c;
bitmap_flags_t flags = 0;
- assert(c->bitmap != NULL);
+ assert(png_c->bitmap != NULL);
if (repeat_x)
flags |= BITMAPF_REPEAT_X;
if (repeat_y)
flags |= BITMAPF_REPEAT_Y;
- return plot.bitmap(x, y, width, height, c->bitmap,
- background_colour, flags);
+ return plot.bitmap(x, y, width, height,
+ png_c->bitmap, background_colour, flags);
}
-nserror nspng_clone(const struct content *old, struct content **newc)
+static nserror nspng_clone(const struct content *old_c, struct content **new_c)
{
- nspng_content *png;
+ nspng_content *clone_png_c;
nserror error;
const char *data;
unsigned long size;
- png = talloc_zero(0, nspng_content);
- if (png == NULL)
+ clone_png_c = talloc_zero(0, nspng_content);
+ if (clone_png_c == NULL)
return NSERROR_NOMEM;
- error = content__clone(old, &png->base);
+ error = content__clone(old_c, &clone_png_c->base);
if (error != NSERROR_OK) {
- content_destroy(&png->base);
+ content_destroy(&clone_png_c->base);
return error;
}
/* Simply replay create/process/convert */
- error = nspng_create_png_data(png);
+ error = nspng_create_png_data(clone_png_c);
if (error != NSERROR_OK) {
- content_destroy(&png->base);
+ content_destroy(&clone_png_c->base);
return error;
}
- data = content__get_source_data(&png->base, &size);
+ data = content__get_source_data(&clone_png_c->base, &size);
if (size > 0) {
- if (nspng_process_data(&png->base, data, size) == false) {
- content_destroy(&png->base);
+ if (nspng_process_data(&clone_png_c->base, data, size) == false) {
+ content_destroy(&clone_png_c->base);
return NSERROR_NOMEM;
}
}
- if (old->status == CONTENT_STATUS_READY ||
- old->status == CONTENT_STATUS_DONE) {
- if (nspng_convert(&png->base) == false) {
- content_destroy(&png->base);
+ if ((old_c->status == CONTENT_STATUS_READY) ||
+ (old_c->status == CONTENT_STATUS_DONE)) {
+ if (nspng_convert(&clone_png_c->base) == false) {
+ content_destroy(&clone_png_c->base);
return NSERROR_CLONE_FAILED;
}
}
- *newc = (struct content *) png;
+ *new_c = (struct content *)clone_png_c;
return NSERROR_OK;
}
-content_type nspng_content_type(lwc_string *mime_type)
+static content_type nspng_content_type(lwc_string *mime_type)
{
return CONTENT_IMAGE;
}
+static const content_handler nspng_content_handler = {
+ nspng_create,
+ nspng_process_data,
+ nspng_convert,
+ NULL,
+ nspng_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nspng_redraw,
+ nspng_redraw_tiled,
+ NULL,
+ NULL,
+ nspng_clone,
+ NULL,
+ nspng_content_type,
+ false
+};
+
+nserror nspng_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
+ lerror = lwc_intern_string(nspng_types[i],
+ strlen(nspng_types[i]),
+ &nspng_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nspng_mime_types[i],
+ &nspng_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nspng_fini();
+
+ return error;
+}
+
+void nspng_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
+ if (nspng_mime_types[i] != NULL)
+ lwc_string_unref(nspng_mime_types[i]);
+ }
+}
+
#endif