summaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
Diffstat (limited to 'image')
-rw-r--r--image/bitmap.h38
-rw-r--r--image/jpeg.c219
-rw-r--r--image/jpeg.h24
-rw-r--r--image/mng.c480
-rw-r--r--image/mng.h35
5 files changed, 796 insertions, 0 deletions
diff --git a/image/bitmap.h b/image/bitmap.h
new file mode 100644
index 000000000..052a3a4f4
--- /dev/null
+++ b/image/bitmap.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ */
+
+/** \file
+ * Generic bitmap handling (interface).
+ *
+ * This interface wraps the native platform-specific image format, so that
+ * portable image convertors can be written.
+ *
+ * The bitmap format is either RGBA.
+ */
+
+#ifndef _NETSURF_IMAGE_BITMAP_H_
+#define _NETSURF_IMAGE_BITMAP_H_
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+struct content;
+
+/** An opaque image. */
+struct bitmap;
+
+struct bitmap *bitmap_create(int width, int height);
+char *bitmap_get_buffer(struct bitmap *bitmap);
+size_t bitmap_get_rowstride(struct bitmap *bitmap);
+void bitmap_destroy(struct bitmap *bitmap);
+bool bitmap_redraw(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour);
+bool bitmap_save(struct bitmap *bitmap, const char *path);
+
+#endif
diff --git a/image/jpeg.c b/image/jpeg.c
new file mode 100644
index 000000000..85711bd2e
--- /dev/null
+++ b/image/jpeg.c
@@ -0,0 +1,219 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ */
+
+/** \file
+ * Content for image/jpeg (implementation).
+ *
+ * This implementation uses the IJG JPEG library.
+ */
+
+#include <assert.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define JPEG_INTERNAL_OPTIONS
+#include "libjpeg/jpeglib.h"
+#include "netsurf/utils/config.h"
+#include "netsurf/content/content.h"
+#include "netsurf/image/bitmap.h"
+#include "netsurf/image/jpeg.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/messages.h"
+#include "netsurf/utils/utils.h"
+
+
+/* We prefer the library to be configured with these options to save
+ * copying data during decoding. */
+#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
+#warning JPEG library not optimally configured. Decoding will be slower.
+#endif
+
+
+static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];
+
+
+struct nsjpeg_error_mgr {
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+
+static void nsjpeg_error_exit(j_common_ptr cinfo);
+static void nsjpeg_init_source(j_decompress_ptr cinfo);
+static boolean nsjpeg_fill_input_buffer(j_decompress_ptr cinfo);
+static void nsjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes);
+static void nsjpeg_term_source(j_decompress_ptr cinfo);
+
+
+/**
+ * Convert a CONTENT_JPEG for display.
+ */
+
+bool nsjpeg_convert(struct content *c, int w, int h)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct nsjpeg_error_mgr jerr;
+ struct jpeg_source_mgr source_mgr = { 0, 0,
+ nsjpeg_init_source, nsjpeg_fill_input_buffer,
+ nsjpeg_skip_input_data, jpeg_resync_to_restart,
+ nsjpeg_term_source };
+ unsigned int height;
+ unsigned int width;
+ struct bitmap *bitmap = NULL;
+ char *pixels;
+ size_t rowstride;
+ union content_msg_data msg_data;
+
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = nsjpeg_error_exit;
+ if (setjmp(jerr.setjmp_buffer)) {
+ jpeg_destroy_decompress(&cinfo);
+ if (bitmap)
+ bitmap_destroy(bitmap);
+
+ msg_data.error = nsjpeg_error_buffer;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+ jpeg_create_decompress(&cinfo);
+ source_mgr.next_input_byte = c->source_data;
+ source_mgr.bytes_in_buffer = c->source_size;
+ cinfo.src = &source_mgr;
+ jpeg_read_header(&cinfo, TRUE);
+ cinfo.out_color_space = JCS_RGB;
+ cinfo.dct_method = JDCT_ISLOW;
+ jpeg_start_decompress(&cinfo);
+
+ width = cinfo.output_width;
+ height = cinfo.output_height;
+
+ bitmap = bitmap_create(width, height);
+ if (!bitmap) {
+ jpeg_destroy_decompress(&cinfo);
+
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return false;
+ }
+
+ pixels = bitmap_get_buffer(bitmap);
+ rowstride = bitmap_get_rowstride(bitmap);
+ do {
+ JSAMPROW scanlines[1];
+ scanlines[0] = (JSAMPROW) (pixels +
+ rowstride * cinfo.output_scanline);
+ jpeg_read_scanlines(&cinfo, scanlines, 1);
+
+#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
+ /* expand to RGBA */
+ for (int i = width - 1; 0 <= i; i--) {
+ int r = scanlines[0][i * RGB_PIXELSIZE + RGB_RED];
+ int g = scanlines[0][i * RGB_PIXELSIZE + RGB_GREEN];
+ int b = scanlines[0][i * RGB_PIXELSIZE + RGB_BLUE];
+ scanlines[0][i * 4 + 0] = r;
+ scanlines[0][i * 4 + 1] = g;
+ scanlines[0][i * 4 + 2] = b;
+ scanlines[0][i * 4 + 3] = 0xff;
+ }
+
+#endif
+ } while (cinfo.output_scanline != cinfo.output_height);
+
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ c->width = width;
+ c->height = height;
+ c->bitmap = bitmap;
+ c->title = malloc(100);
+ if (c->title)
+ snprintf(c->title, 100, messages_get("JPEGTitle"),
+ width, height, c->source_size);
+ c->size += height * rowstride + 100;
+ c->status = CONTENT_STATUS_DONE;
+ return true;
+}
+
+
+/**
+ * Fatal error handler for JPEG library.
+ *
+ * This prevents jpeglib calling exit() on a fatal error.
+ */
+
+void nsjpeg_error_exit(j_common_ptr cinfo)
+{
+ struct nsjpeg_error_mgr *err = (struct nsjpeg_error_mgr *) cinfo->err;
+ err->pub.format_message(cinfo, nsjpeg_error_buffer);
+ longjmp(err->setjmp_buffer, 1);
+}
+
+
+/**
+ * JPEG data source manager: initialize source.
+ */
+
+void nsjpeg_init_source(j_decompress_ptr cinfo)
+{
+}
+
+
+static char nsjpeg_eoi[] = { 0xff, JPEG_EOI };
+
+/**
+ * JPEG data source manager: fill the input buffer.
+ *
+ * This can only occur if the JPEG data was truncated or corrupted. Insert a
+ * fake EOI marker to allow the decompressor to output as much as possible.
+ */
+
+boolean nsjpeg_fill_input_buffer(j_decompress_ptr cinfo)
+{
+ cinfo->src->next_input_byte = nsjpeg_eoi;
+ cinfo->src->bytes_in_buffer = 2;
+ return TRUE;
+}
+
+
+/**
+ * JPEG data source manager: skip num_bytes worth of data.
+ */
+
+void nsjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ if ((long) cinfo->src->bytes_in_buffer < num_bytes) {
+ cinfo->src->next_input_byte = 0;
+ cinfo->src->bytes_in_buffer = 0;
+ } else {
+ cinfo->src->next_input_byte += num_bytes;
+ cinfo->src->bytes_in_buffer -= num_bytes;
+ }
+}
+
+
+/**
+ * JPEG data source manager: terminate source.
+ */
+
+void nsjpeg_term_source(j_decompress_ptr cinfo)
+{
+}
+
+
+/**
+ * Destroy a CONTENT_JPEG and free all resources it owns.
+ */
+
+void nsjpeg_destroy(struct content *c)
+{
+ if (c->bitmap)
+ bitmap_destroy(c->bitmap);
+ free(c->title);
+}
diff --git a/image/jpeg.h b/image/jpeg.h
new file mode 100644
index 000000000..c20678537
--- /dev/null
+++ b/image/jpeg.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ */
+
+/** \file
+ * Content for image/jpeg (interface).
+ */
+
+#ifndef _NETSURF_IMAGE_JPEG_H_
+#define _NETSURF_IMAGE_JPEG_H_
+
+struct bitmap;
+struct content;
+
+struct content_jpeg_data {
+};
+
+bool nsjpeg_convert(struct content *c, int width, int height);
+void nsjpeg_destroy(struct content *c);
+
+#endif
diff --git a/image/mng.c b/image/mng.c
new file mode 100644
index 000000000..fecebe6f3
--- /dev/null
+++ b/image/mng.c
@@ -0,0 +1,480 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ */
+
+/** \file
+ * Content for image/mng, image/png, and image/jng (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include "libmng.h"
+#include "netsurf/utils/config.h"
+#include "netsurf/content/content.h"
+#include "netsurf/desktop/browser.h"
+#include "netsurf/image/bitmap.h"
+#include "netsurf/image/mng.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/messages.h"
+#include "netsurf/utils/utils.h"
+
+#ifdef WITH_MNG
+
+/* We do not currently support any form of colour/gamma correction, nor do
+ we support dynamic MNGs.
+*/
+
+
+static mng_bool nsmng_openstream(mng_handle mng);
+static mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread);
+static mng_bool nsmng_closestream(mng_handle mng);
+static mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height);
+static mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line);
+static mng_uint32 nsmng_gettickcount(mng_handle mng);
+static mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h);
+static mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs);
+static void nsmng_animate(void *p);
+static bool nsmng_broadcast_error(struct content *c);
+static mng_bool nsmng_trace(mng_handle mng, mng_int32 iFunNr, mng_int32 iFuncseq, mng_pchar zFuncname);
+static mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
+ mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq,
+ mng_int32 extra1, mng_int32 extra2, mng_pchar text);
+#ifndef MNG_INTERNAL_MEMMNGMT
+static mng_ptr nsmng_alloc(mng_size_t n);
+static void nsmng_free(mng_ptr p, mng_size_t n);
+#endif
+
+
+bool nsmng_create(struct content *c, const char *params[]) {
+
+ /* Initialise the library
+ */
+#ifdef MNG_INTERNAL_MEMMNGMT
+ c->data.mng.handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL);
+#else
+ c->data.mng.handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL);
+#endif
+ if (c->data.mng.handle == MNG_NULL) {
+ LOG(("Unable to initialise MNG library."));
+ return nsmng_broadcast_error(c);
+ }
+
+ /* We need to decode in suspension mode
+ */
+ if (mng_set_suspensionmode(c->data.mng.handle, MNG_TRUE) != MNG_NOERROR) {
+ LOG(("Unable to set suspension mode."));
+ return nsmng_broadcast_error(c);
+ }
+
+ /* We need to register our callbacks
+ */
+ if (mng_setcb_openstream(c->data.mng.handle, nsmng_openstream) != MNG_NOERROR) {
+ LOG(("Unable to set openstream callback."));
+ return nsmng_broadcast_error(c);
+ }
+ if (mng_setcb_readdata(c->data.mng.handle, nsmng_readdata) != MNG_NOERROR) {
+ LOG(("Unable to set readdata callback."));
+ return nsmng_broadcast_error(c);
+ }
+ if (mng_setcb_closestream(c->data.mng.handle, nsmng_closestream) != MNG_NOERROR) {
+ LOG(("Unable to set closestream callback."));
+ return nsmng_broadcast_error(c);
+ }
+ if (mng_setcb_processheader(c->data.mng.handle, nsmng_processheader) != MNG_NOERROR) {
+ LOG(("Unable to set processheader callback."));
+ return nsmng_broadcast_error(c);
+ }
+
+ /* Register our callbacks for displaying
+ */
+ if (mng_setcb_getcanvasline(c->data.mng.handle, nsmng_getcanvasline) != MNG_NOERROR) {
+ LOG(("Unable to set getcanvasline callback."));
+ return nsmng_broadcast_error(c);
+ }
+ if (mng_setcb_refresh(c->data.mng.handle, nsmng_refresh) != MNG_NOERROR) {
+ LOG(("Unable to set refresh callback."));
+ return nsmng_broadcast_error(c);
+ }
+ if (mng_setcb_gettickcount(c->data.mng.handle, nsmng_gettickcount) != MNG_NOERROR) {
+ LOG(("Unable to set gettickcount callback."));
+ return nsmng_broadcast_error(c);
+ }
+ if (mng_setcb_settimer(c->data.mng.handle, nsmng_settimer) != MNG_NOERROR) {
+ LOG(("Unable to set settimer callback."));
+ return nsmng_broadcast_error(c);
+ }
+
+ /* register error handling function */
+ if (mng_setcb_errorproc(c->data.mng.handle, nsmng_errorproc) != MNG_NOERROR) {
+ LOG(("Unable to set errorproc"));
+ return nsmng_broadcast_error(c);
+ }
+
+ /* Initialise the reading
+ */
+ c->data.mng.read_start = true;
+ c->data.mng.read_resume = false;
+ c->data.mng.read_size = 0;
+ c->data.mng.waiting = false;
+ return true;
+}
+
+
+/* START OF CALLBACKS REQUIRED FOR READING
+*/
+
+
+mng_bool nsmng_openstream(mng_handle mng) {
+ return MNG_TRUE;
+}
+
+mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) {
+ struct content *c;
+
+ /* Get our content back
+ */
+ c = (struct content *)mng_get_userdata(mng);
+
+ /* Copy any data we have (maximum of 'size')
+ */
+ *bytesread = ((c->source_size - c->data.mng.read_size) < size) ?
+ (c->source_size - c->data.mng.read_size) : size;
+
+ LOG(("Read %d, processing %p", *bytesread, mng));
+
+ if ((*bytesread) > 0) {
+ memcpy(buffer, c->source_data + c->data.mng.read_size, *bytesread);
+ c->data.mng.read_size += *bytesread;
+ }
+
+ /* Return success
+ */
+ return MNG_TRUE;
+}
+
+mng_bool nsmng_closestream(mng_handle mng) {
+ return MNG_TRUE;
+}
+
+mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height) {
+ struct content *c;
+ union content_msg_data msg_data;
+
+ /* This function is called when the header has been read and we know
+ the dimensions of the canvas.
+ */
+ c = (struct content *)mng_get_userdata(mng);
+ c->bitmap = bitmap_create(width, height);
+ if (!c->bitmap) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ LOG(("Insufficient memory to create canvas."));
+ return MNG_FALSE;
+ }
+
+ /* Initialise the content size
+ */
+ c->width = width;
+ c->height = height;
+
+ /* Set the canvas style
+ */
+ if (mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8) != MNG_NOERROR) {
+ LOG(("Error setting canvas style."));
+ }
+
+ /* Return success
+ */
+ return MNG_TRUE;
+}
+
+
+/* END OF CALLBACKS REQUIRED FOR READING
+*/
+
+
+bool nsmng_process_data(struct content *c, char *data, unsigned int size) {
+ mng_retcode status;
+
+ /* We only need to do any processing if we're starting/resuming reading.
+ */
+ if ((!c->data.mng.read_resume) && (!c->data.mng.read_start)) return true;
+
+ /* Try to start processing, or process some more data
+ */
+ if (c->data.mng.read_start) {
+ status = mng_read(c->data.mng.handle);
+ c->data.mng.read_start = false;
+ } else {
+ status = mng_read_resume(c->data.mng.handle);
+ }
+ c->data.mng.read_resume = (status == MNG_NEEDMOREDATA);
+ if ((status != MNG_NOERROR) && (status != MNG_NEEDMOREDATA)) {
+ LOG(("Failed to start/continue reading (%i).", status));
+ return nsmng_broadcast_error(c);
+ }
+
+ /* Continue onwards
+ */
+ return true;
+}
+
+
+bool nsmng_convert(struct content *c, int width, int height) {
+ mng_retcode status;
+
+ LOG(("Converting"));
+
+ /* Set the title
+ */
+ c->title = malloc(100);
+ if (c->title) {
+ if (c->type == CONTENT_MNG) {
+ snprintf(c->title, 100, messages_get("MNGTitle"),
+ c->width, c->height, c->source_size);
+ } else if (c->type == CONTENT_PNG) {
+ snprintf(c->title, 100, messages_get("PNGTitle"),
+ c->width, c->height, c->source_size);
+ } else {
+ snprintf(c->title, 100, messages_get("JNGTitle"),
+ c->width, c->height, c->source_size);
+ }
+ }
+ c->size += c->width * c->height * 4 + 100;
+ c->status = CONTENT_STATUS_DONE;
+
+
+ /* Start displaying
+ */
+ status = mng_display(c->data.mng.handle);
+ if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) {
+ LOG(("Unable to start display (%i)", status));
+ return nsmng_broadcast_error(c);
+ }
+ return true;
+}
+
+
+/* START OF CALLBACKS REQUIRED FOR DISPLAYING
+*/
+
+
+mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line) {
+ struct content *c;
+
+ /* Get our content back
+ */
+ c = (struct content *)mng_get_userdata(mng);
+
+ /* Calculate the address
+ */
+ return bitmap_get_buffer(c->bitmap) +
+ bitmap_get_rowstride(c->bitmap) * line;
+}
+
+
+/**
+ * Get the wall-clock time in milliseconds since some fixed time.
+ */
+
+mng_uint32 nsmng_gettickcount(mng_handle mng) {
+ static bool start = true;
+ static time_t t0;
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+ if (start) {
+ t0 = tv.tv_sec;
+ start = false;
+ }
+
+ return (tv.tv_sec - t0) * 1000 + tv.tv_usec / 1000;
+}
+
+
+mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) {
+ union content_msg_data data;
+ struct content *c;
+
+ /* Get our content back
+ */
+ c = (struct content *)mng_get_userdata(mng);
+
+ /* Set the minimum redraw area
+ */
+ data.redraw.x = x;
+ data.redraw.y = y;
+ data.redraw.width = w;
+ data.redraw.height = h;
+
+ /* Set the redraw area to the whole canvas to ensure that if we can redraw something
+ to trigger animation later then we do
+ */
+/* data.redraw.x = 0;
+ data.redraw.y = 0;
+ data.redraw.width = c->width;
+ data.redraw.height = c->height;
+*/
+ /* Always redraw everything
+ */
+ data.redraw.full_redraw = true;
+
+ /* Set the object characteristics
+ */
+ data.redraw.object = c;
+ data.redraw.object_x = 0;
+ data.redraw.object_y = 0;
+ data.redraw.object_width = c->width;
+ data.redraw.object_height = c->height;
+
+ content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ return MNG_TRUE;
+}
+
+mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs) {
+ struct content *c;
+
+ /* Get our content back
+ */
+ c = (struct content *)mng_get_userdata(mng);
+
+ /* Perform the scheduling
+ */
+ schedule(msecs / 10, nsmng_animate, c);
+ return MNG_TRUE;
+}
+
+
+/* END OF CALLBACKS REQUIRED FOR DISPLAYING
+*/
+
+
+void nsmng_destroy(struct content *c) {
+ /* Cleanup the MNG structure and release the canvas memory
+ */
+ schedule_remove(nsmng_animate, c);
+ mng_cleanup(&c->data.mng.handle);
+ if (c->bitmap)
+ bitmap_destroy(c->bitmap);
+ free(c->title);
+}
+
+
+bool nsmng_redraw(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour)
+{
+ bool ret;
+
+ ret = bitmap_redraw(c, x, y, width, height,
+ clip_x0, clip_y0, clip_x1, clip_y1,
+ scale, background_colour);
+
+ /* Check if we need to restart the animation
+ */
+ if (c->data.mng.waiting) nsmng_animate(c);
+
+ return ret;
+}
+
+/**
+ * Animates to the next frame
+ */
+void nsmng_animate(void *p) {
+ struct content *c = p;
+
+ /* If we used the last animation we advance, if not we try again later
+ */
+ if (c->user_list->next == NULL) {
+ c->data.mng.waiting = true;
+ } else {
+ c->data.mng.waiting = false;
+ mng_display_resume(c->data.mng.handle);
+ }
+}
+
+
+
+/**
+ * Broadcasts an error message and returns false
+ *
+ * \param c the content to broadcast for
+ * \return false
+ */
+bool nsmng_broadcast_error(struct content *c) {
+ union content_msg_data msg_data;
+ if (c->type == CONTENT_MNG) {
+ msg_data.error = messages_get("MNGError");
+ } else if (c->type == CONTENT_PNG) {
+ msg_data.error = messages_get("PNGError");
+ } else {
+ msg_data.error = messages_get("JNGError");
+ }
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+
+}
+
+mng_bool nsmng_trace(mng_handle mng, mng_int32 iFunNr, mng_int32 iFuncseq, mng_pchar zFuncname)
+{
+ LOG(("In %s(%d,%d), processing: %p", zFuncname, iFunNr, iFuncseq, mng));
+ return MNG_TRUE;
+}
+
+mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
+ mng_int8 severity,
+ mng_chunkid chunktype, mng_uint32 chunkseq,
+ mng_int32 extra1, mng_int32 extra2, mng_pchar text)
+{
+ struct content *c;
+ char chunk[5];
+
+ c = (struct content *)mng_get_userdata(mng);
+
+ chunk[0] = (char)((chunktype >> 24) & 0xFF);
+ chunk[1] = (char)((chunktype >> 16) & 0xFF);
+ chunk[2] = (char)((chunktype >> 8) & 0xFF);
+ chunk[3] = (char)((chunktype ) & 0xFF);
+ chunk[4] = '\0';
+
+ LOG(("error playing '%s' chunk %s (%d):", c->url, chunk, chunkseq));
+ LOG(("code %d severity %d extra1 %d extra2 %d text:'%s'", code,
+ severity, extra1, extra2, text));
+
+ return (0);
+}
+
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+
+/**
+ * Memory allocation callback for libmng.
+ */
+
+mng_ptr nsmng_alloc(mng_size_t n)
+{
+ return calloc(1, n);
+}
+
+
+/**
+ * Memory free callback for libmng.
+ */
+
+void nsmng_free(mng_ptr p, mng_size_t n)
+{
+ free(p);
+}
+
+#endif
+
+#endif
diff --git a/image/mng.h b/image/mng.h
new file mode 100644
index 000000000..6a67b840e
--- /dev/null
+++ b/image/mng.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ */
+
+/** \file
+ * Content for image/mng, image/png, and image/jng (interface).
+ */
+
+#ifndef _NETSURF_IMAGE_MNG_H_
+#define _NETSURF_IMAGE_MNG_H_
+
+#include "libmng.h"
+
+struct content;
+
+struct content_mng_data {
+ bool read_start;
+ bool read_resume;
+ int read_size;
+ bool waiting;
+ mng_handle handle;
+};
+
+bool nsmng_create(struct content *c, const char *params[]);
+bool nsmng_process_data(struct content *c, char *data, unsigned int size);
+bool nsmng_convert(struct content *c, int width, int height);
+void nsmng_destroy(struct content *c);
+bool nsmng_redraw(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour);
+#endif