From 3371a27391e828c6417e6d805572cf261b138785 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Fri, 3 Sep 2004 22:44:48 +0000 Subject: [project @ 2004-09-03 22:44:47 by bursa] Add generic bitmap functions. Move jpeg and mng code from riscos/ to image/ and update to use bitmap. Note: background tiling and drawfile export for jpeg and mng/png are broken. svn path=/import/netsurf/; revision=1265 --- image/bitmap.h | 38 +++++ image/jpeg.c | 219 ++++++++++++++++++++++++++ image/jpeg.h | 24 +++ image/mng.c | 480 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ image/mng.h | 35 +++++ 5 files changed, 796 insertions(+) create mode 100644 image/bitmap.h create mode 100644 image/jpeg.c create mode 100644 image/jpeg.h create mode 100644 image/mng.c create mode 100644 image/mng.h (limited to 'image') 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 + */ + +/** \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 +#include + +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 + * Copyright 2004 John M Bell + */ + +/** \file + * Content for image/jpeg (implementation). + * + * This implementation uses the IJG JPEG library. + */ + +#include +#include +#include +#include +#include +#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 + */ + +/** \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 + */ + +/** \file + * Content for image/mng, image/png, and image/jng (implementation). + */ + +#include +#include +#include +#include +#include +#include +#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 + */ + +/** \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 -- cgit v1.2.3