Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4363 → Rev 4364

/contrib/network/netsurf/netsurf/image/bitmap.h
0,0 → 1,87
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Generic bitmap handling (interface).
*
* This interface wraps the native platform-specific image format, so that
* portable image convertors can be written.
*
* Bitmaps are required to be 32bpp with components in the order RR GG BB AA.
*
* For example, an opaque 1x1 pixel image would yield the following bitmap
* data:
*
* Red : 0xff 0x00 0x00 0x00
* Green: 0x00 0xff 0x00 0x00
* Blue : 0x00 0x00 0xff 0x00
*
* Any attempt to read pixels by casting bitmap data to uint32_t or similar
* will need to cater for the order of bytes in a word being different on
* big and little endian systems. To avoid confusion, it is recommended
* that pixel data is loaded as follows:
*
* uint32_t read_pixel(const uint8_t *bmp)
* {
* // red green blue alpha
* return bmp[0] | (bmp[1] << 8) | (bmp[2] << 16) | (bmp[3] << 24);
* }
*
* and *not* as follows:
*
* uint32_t read_pixel(const uint8_t *bmp)
* {
* return *((uint32_t *) bmp);
* }
*/
 
#ifndef _NETSURF_IMAGE_BITMAP_H_
#define _NETSURF_IMAGE_BITMAP_H_
 
#include <stdbool.h>
#include <stdlib.h>
 
#define BITMAP_NEW 0
#define BITMAP_OPAQUE (1 << 0) /** image is opaque */
#define BITMAP_MODIFIED (1 << 1) /** buffer has been modified */
#define BITMAP_PERSISTENT (1 << 2) /** retain between sessions */
#define BITMAP_CLEAR_MEMORY (1 << 3) /** memory should be wiped */
#define BITMAP_READY (1 << 4) /** fully initialised */
 
#define BITMAP_SAVE_FULL_ALPHA (1 << 0) /** save with full alpha channel (if not opaque) */
 
struct content;
 
/** An opaque image. */
struct bitmap;
 
void *bitmap_create(int width, int height, unsigned int state);
void bitmap_set_opaque(void *bitmap, bool opaque);
bool bitmap_test_opaque(void *bitmap);
bool bitmap_get_opaque(void *bitmap);
unsigned char *bitmap_get_buffer(void *bitmap);
size_t bitmap_get_rowstride(void *bitmap);
size_t bitmap_get_bpp(void *bitmap);
void bitmap_destroy(void *bitmap);
bool bitmap_save(void *bitmap, const char *path, unsigned flags);
void bitmap_modified(void *bitmap);
 
int bitmap_get_width(void *bitmap);
int bitmap_get_height(void *bitmap);
 
#endif
/contrib/network/netsurf/netsurf/image/bmp.c
0,0 → 1,289
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/bmp (implementation)
*/
 
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnsbmp.h>
 
#include "utils/config.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
#include "image/bitmap.h"
#include "image/bmp.h"
 
typedef struct nsbmp_content {
struct content base;
 
bmp_image *bmp; /** BMP image data */
 
struct bitmap *bitmap; /**< Created NetSurf bitmap */
} nsbmp_content;
 
static nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
{
union content_msg_data msg_data;
 
bmp->bmp = calloc(sizeof(struct bmp_image), 1);
if (bmp->bmp == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&bmp->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
 
bmp_create(bmp->bmp, &bmp_bitmap_callbacks);
 
return NSERROR_OK;
}
 
 
static nserror nsbmp_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
{
nsbmp_content *bmp;
nserror error;
 
bmp = calloc(1, sizeof(nsbmp_content));
if (bmp == NULL)
return NSERROR_NOMEM;
 
error = content__init(&bmp->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(bmp);
return error;
}
 
error = nsbmp_create_bmp_data(bmp);
if (error != NSERROR_OK) {
free(bmp);
return error;
}
 
*c = (struct content *) bmp;
 
return NSERROR_OK;
}
 
/**
* Callback for libnsbmp; forwards the call to bitmap_create()
*
* \param width width of image in pixels
* \param height width of image in pixels
* \param state a flag word indicating the initial state
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
static void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state)
{
unsigned int bitmap_state = BITMAP_NEW;
 
/* set bitmap state based on bmp state */
bitmap_state |= (bmp_state & BMP_OPAQUE) ? BITMAP_OPAQUE : 0;
bitmap_state |= (bmp_state & BMP_CLEAR_MEMORY) ?
BITMAP_CLEAR_MEMORY : 0;
 
/* return the created bitmap */
return bitmap_create(width, height, bitmap_state);
}
 
/* The Bitmap callbacks function table;
* necessary for interaction with nsbmplib.
*/
bmp_bitmap_callback_vt bmp_bitmap_callbacks = {
.bitmap_create = nsbmp_bitmap_create,
.bitmap_destroy = bitmap_destroy,
.bitmap_get_buffer = bitmap_get_buffer,
.bitmap_get_bpp = bitmap_get_bpp
};
 
static bool nsbmp_convert(struct content *c)
{
nsbmp_content *bmp = (nsbmp_content *) c;
bmp_result res;
union content_msg_data msg_data;
uint32_t swidth;
const char *data;
unsigned long size;
char *title;
 
/* set the bmp data */
data = content__get_source_data(c, &size);
 
/* analyse the BMP */
res = bmp_analyse(bmp->bmp, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
break;
case BMP_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
case BMP_INSUFFICIENT_DATA:
case BMP_DATA_ERROR:
msg_data.error = messages_get("BadBMP");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
/* Store our content width and description */
c->width = bmp->bmp->width;
c->height = bmp->bmp->height;
swidth = bmp->bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bmp->bitmap) *
bmp->bmp->width;
c->size += (swidth * bmp->bmp->height) + 16 + 44;
 
/* set title text */
title = messages_get_buff("BMPTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
/* exit as a success */
bmp->bitmap = bmp->bmp->bitmap;
bitmap_modified(bmp->bitmap);
 
content_set_ready(c);
content_set_done(c);
 
/* Done: update status bar */
content_set_status(c, "");
return true;
}
 
static bool nsbmp_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
nsbmp_content *bmp = (nsbmp_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
 
if (bmp->bmp->decoded == false)
if (bmp_decode(bmp->bmp) != BMP_OK)
return false;
 
bmp->bitmap = bmp->bmp->bitmap;
 
if (data->repeat_x)
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
 
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
bmp->bitmap, data->background_colour, flags);
}
 
 
static void nsbmp_destroy(struct content *c)
{
nsbmp_content *bmp = (nsbmp_content *) c;
 
bmp_finalise(bmp->bmp);
free(bmp->bmp);
}
 
 
static nserror nsbmp_clone(const struct content *old, struct content **newc)
{
nsbmp_content *new_bmp;
nserror error;
 
new_bmp = calloc(1, sizeof(nsbmp_content));
if (new_bmp == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &new_bmp->base);
if (error != NSERROR_OK) {
content_destroy(&new_bmp->base);
return error;
}
 
/* We "clone" the old content by replaying creation and conversion */
error = nsbmp_create_bmp_data(new_bmp);
if (error != NSERROR_OK) {
content_destroy(&new_bmp->base);
return error;
}
 
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (nsbmp_convert(&new_bmp->base) == false) {
content_destroy(&new_bmp->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) new_bmp;
 
return NSERROR_OK;
}
 
static void *nsbmp_get_internal(const struct content *c, void *context)
{
nsbmp_content *bmp = (nsbmp_content *)c;
 
return bmp->bitmap;
}
 
static content_type nsbmp_content_type(void)
{
return CONTENT_IMAGE;
}
 
 
static const content_handler nsbmp_content_handler = {
.create = nsbmp_create,
.data_complete = nsbmp_convert,
.destroy = nsbmp_destroy,
.redraw = nsbmp_redraw,
.clone = nsbmp_clone,
.get_internal = nsbmp_get_internal,
.type = nsbmp_content_type,
.no_share = false,
};
 
static const char *nsbmp_types[] = {
"application/bmp",
"application/preview",
"application/x-bmp",
"application/x-win-bitmap",
"image/bmp",
"image/ms-bmp",
"image/x-bitmap",
"image/x-bmp",
"image/x-ms-bmp",
"image/x-win-bitmap",
"image/x-windows-bmp",
"image/x-xbitmap"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsbmp, nsbmp_types, nsbmp_content_handler);
/contrib/network/netsurf/netsurf/image/bmp.h
0,0 → 1,35
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/bmp (interface).
*/
 
#ifndef _NETSURF_IMAGE_BMP_H_
#define _NETSURF_IMAGE_BMP_H_
 
#include <libnsbmp.h>
 
#include "image/bitmap.h"
 
extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
 
nserror nsbmp_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/gif.c
0,0 → 1,427
/*
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/gif (implementation)
*
* All GIFs are dynamically decompressed using the routines that gifread.c
* provides. Whilst this allows support for progressive decoding, it is
* not implemented here as NetSurf currently does not provide such support.
*
* [rjw] - Sun 4th April 2004
*/
 
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnsgif.h>
 
#include "utils/config.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/image.h"
#include "image/bitmap.h"
#include "image/gif.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
#include "utils/utils.h"
 
typedef struct nsgif_content {
struct content base;
 
struct gif_animation *gif; /**< GIF animation data */
int current_frame; /**< current frame to display [0...(max-1)] */
} nsgif_content;
 
 
/**
* Callback for libnsgif; forwards the call to bitmap_create()
*
* \param width width of image in pixels
* \param height width of image in pixels
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
static void *nsgif_bitmap_create(int width, int height)
{
return bitmap_create(width, height, BITMAP_NEW);
}
 
/* The Bitmap callbacks function table;
* necessary for interaction with nsgiflib.
*/
static gif_bitmap_callback_vt gif_bitmap_callbacks = {
.bitmap_create = nsgif_bitmap_create,
.bitmap_destroy = bitmap_destroy,
.bitmap_get_buffer = bitmap_get_buffer,
.bitmap_set_opaque = bitmap_set_opaque,
.bitmap_test_opaque = bitmap_test_opaque,
.bitmap_modified = bitmap_modified
};
 
static nserror nsgif_create_gif_data(nsgif_content *c)
{
union content_msg_data msg_data;
 
/* Initialise our data structure */
c->gif = calloc(sizeof(gif_animation), 1);
if (c->gif == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
gif_create(c->gif, &gif_bitmap_callbacks);
return NSERROR_OK;
}
 
 
 
static nserror nsgif_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
{
nsgif_content *result;
nserror error;
 
result = calloc(1, sizeof(nsgif_content));
if (result == NULL)
return NSERROR_NOMEM;
 
error = content__init(&result->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(result);
return error;
}
 
error = nsgif_create_gif_data(result);
if (error != NSERROR_OK) {
free(result);
return error;
}
 
*c = (struct content *) result;
 
return NSERROR_OK;
}
 
/**
* Performs any necessary animation.
*
* \param p The content to animate
*/
static void nsgif_animate(void *p)
{
nsgif_content *gif = p;
union content_msg_data data;
int delay;
int f;
 
/* Advance by a frame, updating the loop count accordingly */
gif->current_frame++;
if (gif->current_frame == (int)gif->gif->frame_count_partial) {
gif->current_frame = 0;
 
/* A loop count of 0 has a special meaning of infinite */
if (gif->gif->loop_count != 0) {
gif->gif->loop_count--;
if (gif->gif->loop_count == 0) {
gif->current_frame =
gif->gif->frame_count_partial - 1;
gif->gif->loop_count = -1;
}
}
}
 
/* Continue animating if we should */
if (gif->gif->loop_count >= 0) {
delay = gif->gif->frames[gif->current_frame].frame_delay;
if (delay < nsoption_int(minimum_gif_delay))
delay = nsoption_int(minimum_gif_delay);
schedule(delay, nsgif_animate, gif);
}
 
if ((!nsoption_bool(animate_images)) ||
(!gif->gif->frames[gif->current_frame].display)) {
return;
}
 
/* area within gif to redraw */
f = gif->current_frame;
data.redraw.x = gif->gif->frames[f].redraw_x;
data.redraw.y = gif->gif->frames[f].redraw_y;
data.redraw.width = gif->gif->frames[f].redraw_width;
data.redraw.height = gif->gif->frames[f].redraw_height;
 
/* redraw background (true) or plot on top (false) */
if (gif->current_frame > 0) {
data.redraw.full_redraw =
gif->gif->frames[f - 1].redraw_required;
/* previous frame needed clearing: expand the redraw area to
* cover it */
if (data.redraw.full_redraw) {
if (data.redraw.x >
(int)(gif->gif->frames[f - 1].redraw_x)) {
data.redraw.width += data.redraw.x -
gif->gif->frames[f - 1].redraw_x;
data.redraw.x =
gif->gif->frames[f - 1].redraw_x;
}
if (data.redraw.y >
(int)(gif->gif->frames[f - 1].redraw_y)) {
data.redraw.height += (data.redraw.y -
gif->gif->frames[f - 1].redraw_y);
data.redraw.y =
gif->gif->frames[f - 1].redraw_y;
}
if ((int)(gif->gif->frames[f - 1].redraw_x +
gif->gif->frames[f - 1].redraw_width) >
(data.redraw.x + data.redraw.width))
data.redraw.width =
gif->gif->frames[f - 1].redraw_x -
data.redraw.x +
gif->gif->frames[f - 1].redraw_width;
if ((int)(gif->gif->frames[f - 1].redraw_y +
gif->gif->frames[f - 1].redraw_height) >
(data.redraw.y + data.redraw.height))
data.redraw.height =
gif->gif->frames[f - 1].redraw_y -
data.redraw.y +
gif->gif->frames[f - 1].redraw_height;
}
} else {
/* do advanced check */
if ((data.redraw.x == 0) && (data.redraw.y == 0) &&
(data.redraw.width == (int)(gif->gif->width)) &&
(data.redraw.height == (int)(gif->gif->height))) {
data.redraw.full_redraw = !gif->gif->frames[f].opaque;
} else {
data.redraw.full_redraw = true;
data.redraw.x = 0;
data.redraw.y = 0;
data.redraw.width = gif->gif->width;
data.redraw.height = gif->gif->height;
}
}
 
/* other data */
data.redraw.object = (struct content *) gif;
data.redraw.object_x = 0;
data.redraw.object_y = 0;
data.redraw.object_width = gif->base.width;
data.redraw.object_height = gif->base.height;
 
content_broadcast(&gif->base, CONTENT_MSG_REDRAW, data);
}
 
static bool nsgif_convert(struct content *c)
{
nsgif_content *gif = (nsgif_content *) c;
int res;
union content_msg_data msg_data;
const char *data;
unsigned long size;
char *title;
 
/* Get the animation */
data = content__get_source_data(c, &size);
 
/* Initialise the GIF */
do {
res = gif_initialise(gif->gif, size, (unsigned char *) data);
if (res != GIF_OK && res != GIF_WORKING &&
res != GIF_INSUFFICIENT_FRAME_DATA) {
switch (res) {
case GIF_FRAME_DATA_ERROR:
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
msg_data.error = messages_get("BadGIF");
break;
case GIF_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
break;
}
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
} while (res != GIF_OK && res != GIF_INSUFFICIENT_FRAME_DATA);
 
/* Abort on bad GIFs */
if ((gif->gif->frame_count_partial == 0) || (gif->gif->width == 0) ||
(gif->gif->height == 0)) {
msg_data.error = messages_get("BadGIF");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
/* Store our content width, height and calculate size */
c->width = gif->gif->width;
c->height = gif->gif->height;
c->size += (gif->gif->width * gif->gif->height * 4) + 16 + 44;
 
/* set title text */
title = messages_get_buff("GIFTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
/* Schedule the animation if we have one */
gif->current_frame = 0;
if (gif->gif->frame_count_partial > 1)
schedule(gif->gif->frames[0].frame_delay, nsgif_animate, c);
 
/* Exit as a success */
content_set_ready(c);
content_set_done(c);
 
/* Done: update status bar */
content_set_status(c, "");
return true;
}
 
 
/**
* Updates the GIF bitmap to display the current frame
*
* \param c the content to update
*/
static gif_result nsgif_get_frame(nsgif_content *gif)
{
int previous_frame, current_frame, frame;
gif_result res = GIF_OK;
 
current_frame = gif->current_frame;
if (!nsoption_bool(animate_images)) {
current_frame = 0;
}
 
if (current_frame < gif->gif->decoded_frame)
previous_frame = 0;
else
previous_frame = gif->gif->decoded_frame + 1;
 
for (frame = previous_frame; frame <= current_frame; frame++) {
res = gif_decode_frame(gif->gif, frame);
}
 
return res;
}
 
static bool nsgif_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
nsgif_content *gif = (nsgif_content *) c;
 
if (gif->current_frame != gif->gif->decoded_frame) {
if (nsgif_get_frame(gif) != GIF_OK) {
return false;
}
}
 
return image_bitmap_plot(gif->gif->frame_image, data, clip, ctx);
}
 
 
static void nsgif_destroy(struct content *c)
{
nsgif_content *gif = (nsgif_content *) c;
 
/* Free all the associated memory buffers */
schedule_remove(nsgif_animate, c);
gif_finalise(gif->gif);
free(gif->gif);
}
 
 
static nserror nsgif_clone(const struct content *old, struct content **newc)
{
nsgif_content *gif;
nserror error;
 
gif = calloc(1, sizeof(nsgif_content));
if (gif == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &gif->base);
if (error != NSERROR_OK) {
content_destroy(&gif->base);
return error;
}
 
/* Simply replay creation and conversion of content */
error = nsgif_create_gif_data(gif);
if (error != NSERROR_OK) {
content_destroy(&gif->base);
return error;
}
 
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (nsgif_convert(&gif->base) == false) {
content_destroy(&gif->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) gif;
 
return NSERROR_OK;
}
 
static void *nsgif_get_internal(const struct content *c, void *context)
{
nsgif_content *gif = (nsgif_content *) c;
 
if (gif->current_frame != gif->gif->decoded_frame) {
if (nsgif_get_frame(gif) != GIF_OK)
return NULL;
}
 
return gif->gif->frame_image;
}
 
static content_type nsgif_content_type(void)
{
return CONTENT_IMAGE;
}
 
static const content_handler nsgif_content_handler = {
.create = nsgif_create,
.data_complete = nsgif_convert,
.destroy = nsgif_destroy,
.redraw = nsgif_redraw,
.clone = nsgif_clone,
.get_internal = nsgif_get_internal,
.type = nsgif_content_type,
.no_share = false,
};
 
static const char *nsgif_types[] = {
"image/gif"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsgif, nsgif_types, nsgif_content_handler);
/contrib/network/netsurf/netsurf/image/gif.h
0,0 → 1,29
/*
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/gif (interface).
*/
 
#ifndef _NETSURF_IMAGE_GIF_H_
#define _NETSURF_IMAGE_GIF_H_
 
nserror nsgif_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/ico.c
0,0 → 1,277
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/ico (implementation)
*/
 
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/bmp.h"
#include "image/ico.h"
#include "image/image.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
typedef struct nsico_content {
struct content base;
 
struct ico_collection *ico; /** ICO collection data */
 
} nsico_content;
 
 
static nserror nsico_create_ico_data(nsico_content *c)
{
union content_msg_data msg_data;
 
c->ico = calloc(sizeof(ico_collection), 1);
if (c->ico == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
ico_collection_create(c->ico, &bmp_bitmap_callbacks);
return NSERROR_OK;
}
 
 
static nserror nsico_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
{
nsico_content *result;
nserror error;
 
result = calloc(1, sizeof(nsico_content));
if (result == NULL)
return NSERROR_NOMEM;
 
error = content__init(&result->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(result);
return error;
}
 
error = nsico_create_ico_data(result);
if (error != NSERROR_OK) {
free(result);
return error;
}
 
*c = (struct content *) result;
 
return NSERROR_OK;
}
 
 
 
static bool nsico_convert(struct content *c)
{
nsico_content *ico = (nsico_content *) c;
struct bmp_image *bmp;
bmp_result res;
union content_msg_data msg_data;
const char *data;
unsigned long size;
char *title;
 
/* set the ico data */
data = content__get_source_data(c, &size);
 
/* analyse the ico */
res = ico_analyse(ico->ico, size, (unsigned char *) data);
 
switch (res) {
case BMP_OK:
break;
case BMP_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
case BMP_INSUFFICIENT_DATA:
case BMP_DATA_ERROR:
msg_data.error = messages_get("BadICO");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
/* Store our content width, height and calculate size */
c->width = ico->ico->width;
c->height = ico->ico->height;
c->size += (ico->ico->width * ico->ico->height * 4) + 16 + 44;
 
/* set title text */
title = messages_get_buff("ICOTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
/* select largest icon to ensure one can be selected */
bmp = ico_find(ico->ico, 255, 255);
if (bmp == NULL) {
/* return error */
LOG(("Failed to select icon"));
return false;
}
 
content_set_ready(c);
content_set_done(c);
 
/* Done: update status bar */
content_set_status(c, "");
return true;
}
 
 
static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
nsico_content *ico = (nsico_content *)c;
struct bmp_image *bmp;
 
/* select most appropriate sized icon for size */
bmp = ico_find(ico->ico, data->width, data->height);
if (bmp == NULL) {
/* return error */
LOG(("Failed to select icon"));
return false;
}
 
/* ensure its decided */
if (bmp->decoded == false) {
if (bmp_decode(bmp) != BMP_OK) {
return false;
} else {
LOG(("Decoding bitmap"));
bitmap_modified(bmp->bitmap);
}
 
}
 
return image_bitmap_plot(bmp->bitmap, data, clip, ctx);
}
 
 
static void nsico_destroy(struct content *c)
{
nsico_content *ico = (nsico_content *) c;
 
ico_finalise(ico->ico);
free(ico->ico);
}
 
static nserror nsico_clone(const struct content *old, struct content **newc)
{
nsico_content *ico;
nserror error;
 
ico = calloc(1, sizeof(nsico_content));
if (ico == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &ico->base);
if (error != NSERROR_OK) {
content_destroy(&ico->base);
return error;
}
 
/* Simply replay creation and conversion */
error = nsico_create_ico_data(ico);
if (error != NSERROR_OK) {
content_destroy(&ico->base);
return error;
}
 
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (nsico_convert(&ico->base) == false) {
content_destroy(&ico->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) ico;
 
return NSERROR_OK;
}
 
static void *nsico_get_internal(const struct content *c, void *context)
{
nsico_content *ico = (nsico_content *) c;
/* TODO: Pick best size for purpose.
* Currently assumes it's for a URL bar. */
struct bmp_image *bmp;
 
bmp = ico_find(ico->ico, 16, 16);
if (bmp == NULL) {
/* return error */
LOG(("Failed to select icon"));
return NULL;
}
 
if (bmp->decoded == false) {
if (bmp_decode(bmp) != BMP_OK) {
return NULL;
} else {
bitmap_modified(bmp->bitmap);
}
}
 
return bmp->bitmap;
}
 
static content_type nsico_content_type(void)
{
return CONTENT_IMAGE;
}
 
static const content_handler nsico_content_handler = {
.create = nsico_create,
.data_complete = nsico_convert,
.destroy = nsico_destroy,
.redraw = nsico_redraw,
.clone = nsico_clone,
.get_internal = nsico_get_internal,
.type = nsico_content_type,
.no_share = false,
};
 
static const char *nsico_types[] = {
"application/ico",
"application/x-ico",
"image/ico",
"image/vnd.microsoft.icon",
"image/x-icon"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsico, nsico_types, nsico_content_handler);
/contrib/network/netsurf/netsurf/image/ico.h
0,0 → 1,28
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/ico (interface).
*/
 
#ifndef _NETSURF_IMAGE_ICO_H_
#define _NETSURF_IMAGE_ICO_H_
 
nserror nsico_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/image.c
0,0 → 1,181
/*
* Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
 
#include "utils/errors.h"
#include "utils/config.h"
#include "utils/log.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
 
#include "image/bmp.h"
#include "image/gif.h"
#include "image/ico.h"
#include "image/jpeg.h"
#include "image/mng.h"
#include "image/nssprite.h"
#include "image/png.h"
#include "image/rsvg.h"
#include "image/svg.h"
#include "image/webp.h"
 
#include "image/image.h"
 
/**
* Initialise image content handlers
*
* \return NSERROR_OK on success, appropriate error otherwise.
*/
nserror image_init(void)
{
nserror error;
 
#ifdef WITH_BMP
error = nsbmp_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_GIF
error = nsgif_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_BMP
error = nsico_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_JPEG
error = nsjpeg_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_MNG
error = nsmng_init();
if (error != NSERROR_OK)
return error;
 
error = nsjpng_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_PNG
/* Prefer libpng over libmng for pngs by registering later */
error = nspng_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_NSSPRITE
error = nssprite_init();
if (error != NSERROR_OK)
return error;
#endif
 
/* Prefer rsvg over libsvgtiny for svgs */
#ifdef WITH_NS_SVG
error = svg_init();
if (error != NSERROR_OK)
return error;
#endif
#ifdef WITH_RSVG
error = nsrsvg_init();
if (error != NSERROR_OK)
return error;
#endif
 
#ifdef WITH_WEBP
error = webp_init();
if (error != NSERROR_OK)
return error;
#endif /* WITH_WEBP */
 
return NSERROR_OK;
}
 
 
bool image_bitmap_plot(struct bitmap *bitmap,
struct content_redraw_data *data,
const struct rect *clip,
const struct redraw_context *ctx)
{
bitmap_flags_t flags = BITMAPF_NONE;
 
int width;
int height;
unsigned char *pixel;
plot_style_t fill_style;
struct rect area;
 
width = bitmap_get_width(bitmap);
if (width == 1) {
height = bitmap_get_height(bitmap);
if (height == 1) {
/* optimise 1x1 bitmap plot */
pixel = bitmap_get_buffer(bitmap);
fill_style.fill_colour = pixel_to_colour(pixel);
 
if (bitmap_get_opaque(bitmap) ||
((fill_style.fill_colour & 0xff000000) == 0xff000000)) {
 
area = *clip;
 
if (data->repeat_x != true) {
area.x0 = data->x;
area.x1 = data->x + data->width;
}
 
if (data->repeat_y != true) {
area.y0 = data->y;
area.y1 = data->y + data->height;
}
 
fill_style.stroke_type = PLOT_OP_TYPE_NONE;
fill_style.fill_type = PLOT_OP_TYPE_SOLID;
 
return ctx->plot->rectangle(area.x0, area.y0,
area.x1, area.y1,
&fill_style);
 
} else if ((fill_style.fill_colour & 0xff000000) == 0) {
/* transparent pixel used as spacer, skip it */
return true;
}
}
}
/* do the plot */
if (data->repeat_x)
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
 
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
bitmap, data->background_colour, flags);
 
}
/contrib/network/netsurf/netsurf/image/image.h
0,0 → 1,43
/*
* Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Initialisation/finalisation of image handlers.
*/
 
#ifndef NETSURF_IMAGE_IMAGE_H_
#define NETSURF_IMAGE_IMAGE_H_
 
#include "utils/errors.h"
 
/** Initialise the content handlers for image types.
*/
nserror image_init(void);
 
/** Common image content handler bitmap plot call.
*
* This plots the specified bitmap controlled by the redraw context
* and specific content redraw data. It is a helper specifically
* provided for image content handlers redraw callback.
*/
bool image_bitmap_plot(struct bitmap *bitmap,
struct content_redraw_data *data,
const struct rect *clip,
const struct redraw_context *ctx);
 
#endif
/contrib/network/netsurf/netsurf/image/image_cache.c
0,0 → 1,800
/*
* Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
 
#include "utils/schedule.h"
#include "utils/log.h"
#include "content/content_protected.h"
 
#include "image/image_cache.h"
#include "image/image.h"
 
/** Age of an entry within the cache
*
* type deffed away so it can be readily changed later perhaps to a
* wallclock time structure.
*/
typedef unsigned int cache_age;
 
/** Image cache entry
*/
struct image_cache_entry_s {
struct image_cache_entry_s *next; /* next cache entry in list */
struct image_cache_entry_s *prev; /* previous cache entry in list */
 
struct content *content; /** content is used as a key */
struct bitmap *bitmap; /** associated bitmap entry */
/** Conversion routine */
image_cache_convert_fn *convert;
 
/* Statistics for replacement algorithm */
 
unsigned int redraw_count; /**< number of times object has been drawn */
cache_age redraw_age; /**< Age of last redraw */
size_t bitmap_size; /**< size if storage occupied by bitmap */
cache_age bitmap_age; /**< Age of last conversion to a bitmap by cache*/
 
int conversion_count; /**< Number of times image has been converted */
};
 
/** Current state of the cache.
*
* Global state of the cache. entries "age" is determined based on a
* monotonically incrementing operation count. This avoids issues with
* using wall clock time while allowing the LRU algorithm to work
* sensibly.
*/
struct image_cache_s {
/** Cache parameters */
struct image_cache_parameters params;
 
/** The "age" of the current operation */
cache_age current_age;
 
/* The objects the cache holds */
struct image_cache_entry_s *entries;
 
 
/* Statistics for management algorithm */
 
/** total size of bitmaps currently allocated */
size_t total_bitmap_size;
 
/** Total count of bitmaps currently allocated */
int bitmap_count;
 
/** Maximum size of bitmaps allocated at any one time */
size_t max_bitmap_size;
/** The number of objects when maximum bitmap usage occoured */
int max_bitmap_size_count;
 
/** Maximum count of bitmaps allocated at any one time */
int max_bitmap_count;
/** The size of the bitmaps when the max count occoured */
size_t max_bitmap_count_size;
 
/** Bitmap was not available at plot time required conversion */
int miss_count;
uint64_t miss_size;
/** Bitmap was available at plot time required no conversion */
int hit_count;
uint64_t hit_size;
/** Bitmap was not available at plot time and required
* conversion which failed.
*/
int fail_count;
uint64_t fail_size;
 
/* Cache entry freed without ever being redrawn */
int total_unrendered;
/** Bitmap was available but never required - wasted conversions */
int specultive_miss_count;
 
/** Total number of additional (after the first) conversions */
int total_extra_conversions;
/** counts total number of images with more than one conversion */
int total_extra_conversions_count;
 
/** Bitmap with most conversions was converted this many times */
int peak_conversions;
/** Size of bitmap with most conversions */
unsigned int peak_conversions_size;
};
 
/** image cache state */
static struct image_cache_s *image_cache = NULL;
 
 
/** Find the nth cache entry
*/
static struct image_cache_entry_s *image_cache__findn(int entryn)
{
struct image_cache_entry_s *found;
 
found = image_cache->entries;
while ((found != NULL) && (entryn > 0)) {
entryn--;
found = found->next;
}
return found;
}
 
/** Find the cache entry for a content
*/
static struct image_cache_entry_s *image_cache__find(const struct content *c)
{
struct image_cache_entry_s *found;
 
found = image_cache->entries;
while ((found != NULL) && (found->content != c)) {
found = found->next;
}
return found;
}
 
static void image_cache_stats_bitmap_add(struct image_cache_entry_s *centry)
{
centry->bitmap_age = image_cache->current_age;
centry->conversion_count++;
 
image_cache->total_bitmap_size += centry->bitmap_size;
image_cache->bitmap_count++;
 
if (image_cache->total_bitmap_size > image_cache->max_bitmap_size) {
image_cache->max_bitmap_size = image_cache->total_bitmap_size;
image_cache->max_bitmap_size_count = image_cache->bitmap_count;
 
}
 
if (image_cache->bitmap_count > image_cache->max_bitmap_count) {
image_cache->max_bitmap_count = image_cache->bitmap_count;
image_cache->max_bitmap_count_size = image_cache->total_bitmap_size;
}
 
if (centry->conversion_count == 2) {
image_cache->total_extra_conversions_count++;
}
 
if (centry->conversion_count > 1) {
image_cache->total_extra_conversions++;
}
 
if ((centry->conversion_count > image_cache->peak_conversions) ||
(centry->conversion_count == image_cache->peak_conversions &&
centry->bitmap_size > image_cache->peak_conversions_size)) {
image_cache->peak_conversions = centry->conversion_count;
image_cache->peak_conversions_size = centry->bitmap_size;
}
}
 
static void image_cache__link(struct image_cache_entry_s *centry)
{
centry->next = image_cache->entries;
centry->prev = NULL;
if (centry->next != NULL) {
centry->next->prev = centry;
}
image_cache->entries = centry;
}
 
static void image_cache__unlink(struct image_cache_entry_s *centry)
{
/* unlink entry */
if (centry->prev == NULL) {
/* first in list */
if (centry->next != NULL) {
centry->next->prev = centry->prev;
image_cache->entries = centry->next;
} else {
/* empty list */
image_cache->entries = NULL;
}
} else {
centry->prev->next = centry->next;
 
if (centry->next != NULL) {
centry->next->prev = centry->prev;
}
}
}
 
static void image_cache__free_bitmap(struct image_cache_entry_s *centry)
{
if (centry->bitmap != NULL) {
#ifdef IMAGE_CACHE_VERBOSE
LOG(("Freeing bitmap %p size %d age %d redraw count %d",
centry->bitmap,
centry->bitmap_size,
image_cache->current_age - centry->bitmap_age,
centry->redraw_count));
#endif
bitmap_destroy(centry->bitmap);
centry->bitmap = NULL;
image_cache->total_bitmap_size -= centry->bitmap_size;
image_cache->bitmap_count--;
if (centry->redraw_count == 0) {
image_cache->specultive_miss_count++;
}
}
 
}
 
/* free cache entry */
static void image_cache__free_entry(struct image_cache_entry_s *centry)
{
#ifdef IMAGE_CACHE_VERBOSE
LOG(("freeing %p ", centry));
#endif
 
if (centry->redraw_count == 0) {
image_cache->total_unrendered++;
}
 
image_cache__free_bitmap(centry);
 
image_cache__unlink(centry);
 
free(centry);
}
 
/** Cache cleaner */
static void image_cache__clean(struct image_cache_s *icache)
{
struct image_cache_entry_s *centry = icache->entries;
 
while (centry != NULL) {
if ((icache->current_age - centry->redraw_age) >
icache->params.bg_clean_time) {
/* only consider older entries, avoids active entries */
if ((icache->total_bitmap_size >
(icache->params.limit - icache->params.hysteresis)) &&
(rand() > (RAND_MAX / 2))) {
image_cache__free_bitmap(centry);
}
}
centry=centry->next;
}
}
 
/** Cache background scheduled callback. */
static void image_cache__background_update(void *p)
{
struct image_cache_s *icache = p;
 
/* increment current cache age */
icache->current_age += icache->params.bg_clean_time;
 
#ifdef IMAGE_CACHE_VERBOSE
LOG(("Cache age %ds", icache->current_age / 1000));
#endif
 
image_cache__clean(icache);
 
schedule((icache->params.bg_clean_time / 10),
image_cache__background_update,
icache);
}
 
/* exported interface documented in image_cache.h */
struct bitmap *image_cache_get_bitmap(const struct content *c)
{
struct image_cache_entry_s *centry;
 
centry = image_cache__find(c);
if (centry == NULL) {
return NULL;
}
 
if (centry->bitmap == NULL) {
if (centry->convert != NULL) {
centry->bitmap = centry->convert(centry->content);
}
 
if (centry->bitmap != NULL) {
image_cache_stats_bitmap_add(centry);
image_cache->miss_count++;
image_cache->miss_size += centry->bitmap_size;
} else {
image_cache->fail_count++;
image_cache->fail_size += centry->bitmap_size;
}
} else {
image_cache->hit_count++;
image_cache->hit_size += centry->bitmap_size;
}
 
return centry->bitmap;
}
 
/* exported interface documented in image_cache.h */
bool image_cache_speculate(struct content *c)
{
bool decision = false;
 
/* If the cache is below its target usage and the bitmap is
* small enough speculate.
*/
if ((image_cache->total_bitmap_size < image_cache->params.limit) &&
(c->size <= image_cache->params.speculative_small)) {
#ifdef IMAGE_CACHE_VERBOSE
LOG(("content size (%d) is smaller than minimum (%d)", c->size, SPECULATE_SMALL));
#endif
decision = true;
}
 
#ifdef IMAGE_CACHE_VERBOSE
LOG(("returning %d", decision));
#endif
return decision;
}
 
/* exported interface documented in image_cache.h */
struct bitmap *image_cache_find_bitmap(struct content *c)
{
struct image_cache_entry_s *centry;
 
centry = image_cache__find(c);
if (centry == NULL) {
return NULL;
}
 
return centry->bitmap;
}
 
/* exported interface documented in image_cache.h */
nserror
image_cache_init(const struct image_cache_parameters *image_cache_parameters)
{
image_cache = calloc(1, sizeof(struct image_cache_s));
if (image_cache == NULL) {
return NSERROR_NOMEM;
}
 
image_cache->params = *image_cache_parameters;
 
schedule((image_cache->params.bg_clean_time / 10),
image_cache__background_update,
image_cache);
 
LOG(("Image cache initilised with a limit of %d hysteresis of %d",
image_cache->params.limit, image_cache->params.hysteresis));
 
return NSERROR_OK;
}
 
/* exported interface documented in image_cache.h */
nserror image_cache_fini(void)
{
unsigned int op_count;
 
schedule_remove(image_cache__background_update, image_cache);
 
LOG(("Size at finish %d (in %d)",
image_cache->total_bitmap_size,
image_cache->bitmap_count));
 
while (image_cache->entries != NULL) {
image_cache__free_entry(image_cache->entries);
}
 
op_count = image_cache->hit_count +
image_cache->miss_count +
image_cache->fail_count;
 
LOG(("Age %ds", image_cache->current_age / 1000));
LOG(("Peak size %d (in %d)",
image_cache->max_bitmap_size,
image_cache->max_bitmap_size_count ));
LOG(("Peak image count %d (size %d)",
image_cache->max_bitmap_count,
image_cache->max_bitmap_count_size));
 
if (op_count > 0) {
uint64_t op_size;
 
op_size = image_cache->hit_size +
image_cache->miss_size +
image_cache->fail_size;
 
LOG(("Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)",
op_count,
image_cache->hit_count,
image_cache->miss_count,
image_cache->fail_count,
(image_cache->hit_count * 100) / op_count,
(image_cache->miss_count * 100) / op_count,
(image_cache->fail_count * 100) / op_count));
LOG(("Cache total/hit/miss/fail (size) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)",
op_size,
image_cache->hit_size,
image_cache->miss_size,
image_cache->fail_size,
(image_cache->hit_size * 100) / op_size,
(image_cache->miss_size * 100) / op_size,
(image_cache->fail_size * 100) / op_size));
}
 
LOG(("Total images never rendered: %d (includes %d that were converted)",
image_cache->total_unrendered,
image_cache->specultive_miss_count));
 
LOG(("Total number of excessive conversions: %d (from %d images converted more than once)",
image_cache->total_extra_conversions,
image_cache->total_extra_conversions_count));
 
LOG(("Bitmap of size %d had most (%d) conversions",
image_cache->peak_conversions_size,
image_cache->peak_conversions));
 
free(image_cache);
 
return NSERROR_OK;
}
 
/* exported interface documented in image_cache.h */
nserror image_cache_add(struct content *content,
struct bitmap *bitmap,
image_cache_convert_fn *convert)
{
struct image_cache_entry_s *centry;
 
/* bump the cache age by a ms to ensure multiple items are not
* added at exactly the same time
*/
image_cache->current_age++;
 
centry = image_cache__find(content);
if (centry == NULL) {
/* new cache entry, content not previously added */
centry = calloc(1, sizeof(struct image_cache_entry_s));
if (centry == NULL) {
return NSERROR_NOMEM;
}
image_cache__link(centry);
centry->content = content;
 
centry->bitmap_size = content->width * content->height * 4;
}
 
LOG(("centry %p, content %p, bitmap %p", centry, content, bitmap));
 
centry->convert = convert;
 
/* set bitmap entry if one is passed, free extant one if present */
if (bitmap != NULL) {
if (centry->bitmap != NULL) {
bitmap_destroy(centry->bitmap);
} else {
image_cache_stats_bitmap_add(centry);
}
centry->bitmap = bitmap;
} else {
/* no bitmap, check to see if we should speculatively convert */
if ((centry->convert != NULL) &&
(image_cache_speculate(content) == true)) {
centry->bitmap = centry->convert(centry->content);
 
if (centry->bitmap != NULL) {
image_cache_stats_bitmap_add(centry);
} else {
image_cache->fail_count++;
}
}
}
 
 
 
return NSERROR_OK;
}
 
/* exported interface documented in image_cache.h */
nserror image_cache_remove(struct content *content)
{
struct image_cache_entry_s *centry;
 
/* get the cache entry */
centry = image_cache__find(content);
if (centry == NULL) {
LOG(("Could not find cache entry for content (%p)", content));
return NSERROR_NOT_FOUND;
}
 
image_cache__free_entry(centry);
 
return NSERROR_OK;
}
 
/* exported interface documented in image_cache.h */
int image_cache_snsummaryf(char *string, size_t size, const char *fmt)
{
size_t slen = 0; /* current output string length */
int fmtc = 0; /* current index into format string */
bool pct;
unsigned int op_count;
uint64_t op_size;
 
op_count = image_cache->hit_count +
image_cache->miss_count +
image_cache->fail_count;
 
op_size = image_cache->hit_size +
image_cache->miss_size +
image_cache->fail_size;
 
while((slen < size) && (fmt[fmtc] != 0)) {
if (fmt[fmtc] == '%') {
fmtc++;
 
/* check for percentage modifier */
if (fmt[fmtc] == 'p') {
fmtc++;
pct = true;
} else {
pct = false;
}
 
#define FMTCHR(chr,fmt,var) case chr : \
slen += snprintf(string + slen, size - slen, "%"fmt, image_cache->var); break
 
#define FMTPCHR(chr,fmt,var,div) \
case chr : \
if (pct) { \
if (div > 0) { \
slen += snprintf(string + slen, size - slen, "%"PRId64, (uint64_t)((image_cache->var * 100) / div)); \
} else { \
slen += snprintf(string + slen, size - slen, "100"); \
} \
} else { \
slen += snprintf(string + slen, size - slen, "%"fmt, image_cache->var); \
} break
 
 
switch (fmt[fmtc]) {
case '%':
string[slen] = '%';
slen++;
break;
 
FMTCHR('a', SSIZET_FMT, params.limit);
FMTCHR('b', SSIZET_FMT, params.hysteresis);
FMTCHR('c', SSIZET_FMT, total_bitmap_size);
FMTCHR('d', "d", bitmap_count);
FMTCHR('e', "d", current_age / 1000);
FMTCHR('f', SSIZET_FMT, max_bitmap_size);
FMTCHR('g', "d", max_bitmap_size_count);
FMTCHR('h', "d", max_bitmap_count);
FMTCHR('i', SSIZET_FMT, max_bitmap_count_size);
 
 
case 'j':
slen += snprintf(string + slen, size - slen,
"%d", pct?100:op_count);
break;
 
FMTPCHR('k', "d", hit_count, op_count);
FMTPCHR('l', "d", miss_count, op_count);
FMTPCHR('m', "d", fail_count, op_count);
 
case 'n':
slen += snprintf(string + slen, size - slen,
"%"PRId64, pct?100:op_size);
break;
 
FMTPCHR('o', PRId64, hit_size, op_size);
FMTPCHR('q', PRId64, miss_size, op_size);
FMTPCHR('r', PRId64, fail_size, op_size);
 
FMTCHR('s', "d", total_unrendered);
FMTCHR('t', "d", specultive_miss_count);
FMTCHR('u', "d", total_extra_conversions);
FMTCHR('v', "d", total_extra_conversions_count);
FMTCHR('w', "d", peak_conversions_size);
FMTCHR('x', "d", peak_conversions);
 
 
}
#undef FMTCHR
#undef FMTPCHR
 
fmtc++;
} else {
string[slen] = fmt[fmtc];
slen++;
fmtc++;
}
}
 
/* Ensure that we NUL-terminate the output */
string[min(slen, size - 1)] = '\0';
 
return slen;
}
 
/* exported interface documented in image_cache.h */
int image_cache_snentryf(char *string, size_t size, unsigned int entryn,
const char *fmt)
{
struct image_cache_entry_s *centry;
size_t slen = 0; /* current output string length */
int fmtc = 0; /* current index into format string */
lwc_string *origin; /* current entry's origin */
 
centry = image_cache__findn(entryn);
if (centry == NULL)
return -1;
 
while((slen < size) && (fmt[fmtc] != 0)) {
if (fmt[fmtc] == '%') {
fmtc++;
switch (fmt[fmtc]) {
case 'e':
slen += snprintf(string + slen, size - slen,
"%d", entryn);
break;
 
case 'r':
slen += snprintf(string + slen, size - slen,
"%u", centry->redraw_count);
break;
 
case 'a':
slen += snprintf(string + slen, size - slen,
"%.2f", (float)((image_cache->current_age - centry->redraw_age)) / 1000);
break;
 
 
case 'c':
slen += snprintf(string + slen, size - slen,
"%d", centry->conversion_count);
break;
 
case 'g':
slen += snprintf(string + slen, size - slen,
"%.2f", (float)((image_cache->current_age - centry->bitmap_age)) / 1000);
break;
 
case 'k':
slen += snprintf(string + slen, size - slen,
"%p", centry->content);
break;
 
case 'U':
slen += snprintf(string + slen, size - slen,
"%s", nsurl_access(llcache_handle_get_url(centry->content->llcache)));
break;
 
case 'o':
if (nsurl_has_component(llcache_handle_get_url(
centry->content->llcache),
NSURL_HOST)) {
origin = nsurl_get_component(
llcache_handle_get_url(
centry->content->
llcache),
NSURL_HOST);
slen += snprintf(string + slen,
size - slen, "%s",
lwc_string_data(
origin));
 
lwc_string_unref(origin);
} else {
slen += snprintf(string + slen,
size - slen, "%s",
"localhost");
}
break;
case 's':
if (centry->bitmap != NULL) {
slen += snprintf(string + slen,
size - slen,
"%"SSIZET_FMT,
centry->bitmap_size);
} else {
slen += snprintf(string + slen,
size - slen,
"0");
}
break;
}
fmtc++;
} else {
string[slen] = fmt[fmtc];
slen++;
fmtc++;
}
}
 
/* Ensure that we NUL-terminate the output */
string[min(slen, size - 1)] = '\0';
 
return slen;
}
 
 
/* exported interface documented in image_cache.h */
bool image_cache_redraw(struct content *c,
struct content_redraw_data *data,
const struct rect *clip,
const struct redraw_context *ctx)
{
struct image_cache_entry_s *centry;
 
/* get the cache entry */
centry = image_cache__find(c);
if (centry == NULL) {
LOG(("Could not find cache entry for content (%p)", c));
return false;
}
 
if (centry->bitmap == NULL) {
if (centry->convert != NULL) {
centry->bitmap = centry->convert(centry->content);
}
 
if (centry->bitmap != NULL) {
image_cache_stats_bitmap_add(centry);
image_cache->miss_count++;
image_cache->miss_size += centry->bitmap_size;
} else {
image_cache->fail_count++;
image_cache->fail_size += centry->bitmap_size;
return false;
}
} else {
image_cache->hit_count++;
image_cache->hit_size += centry->bitmap_size;
}
 
 
/* update statistics */
centry->redraw_count++;
centry->redraw_age = image_cache->current_age;
 
return image_bitmap_plot(centry->bitmap, data, clip, ctx);
}
 
void image_cache_destroy(struct content *content)
{
struct image_cache_entry_s *centry;
 
/* get the cache entry */
centry = image_cache__find(content);
if (centry == NULL) {
LOG(("Could not find cache entry for content (%p)", content));
} else {
image_cache__free_entry(centry);
}
}
 
void *image_cache_get_internal(const struct content *c, void *context)
{
return image_cache_get_bitmap(c);
}
 
content_type image_cache_content_type(void)
{
return CONTENT_IMAGE;
}
/contrib/network/netsurf/netsurf/image/image_cache.h
0,0 → 1,188
/*
* Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* The image content handler intermediate image cache.
*
* This cache allows netsurf to use a generic intermediate bitmap
* format without keeping the
* intermediate representation in memory.
*
* The bitmap structure is opaque to the rest of netsurf and is
* controlled by the platform-specific code (see image/bitmap.h for
* detials). All image content handlers convert into this format and
* pass it to the plot functions for display,
*
* This cache maintains a link between the underlying original content
* and the intermediate representation. It is intended to be flexable
* and either manage the bitmap plotting completely or give the image
* content handler complete control.
*/
 
#ifndef NETSURF_IMAGE_IMAGE_CACHE_H_
#define NETSURF_IMAGE_IMAGE_CACHE_H_
 
#include "utils/errors.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
 
typedef struct bitmap * (image_cache_convert_fn) (struct content *content);
 
struct image_cache_parameters {
/** How frequently the background cache clean process is run (ms) */
unsigned int bg_clean_time;
 
/** The target upper bound for the image cache size */
size_t limit;
 
/** The hysteresis allowed round the target size */
size_t hysteresis;
 
/** The speculative conversion "small" size */
size_t speculative_small;
};
 
/** Initialise the image cache
*
* @param image_cache_parameters The control parameters for the image cache
*/
nserror image_cache_init(const struct image_cache_parameters *image_cache_parameters);
nserror image_cache_fini(void);
 
/** adds an image content to be cached.
*
* @param content The content handle used as a key
* @param bitmap A bitmap representing the already converted content or NULL.
* @param convert A function pointer to convert the content into a bitmap or NULL.
* @return A netsurf error code.
*/
nserror image_cache_add(struct content *content,
struct bitmap *bitmap,
image_cache_convert_fn *convert);
 
nserror image_cache_remove(struct content *content);
 
 
/** Obtain a bitmap from a content converting from source if neccessary. */
struct bitmap *image_cache_get_bitmap(const struct content *c);
 
/** Obtain a bitmap from a content with no conversion */
struct bitmap *image_cache_find_bitmap(struct content *c);
 
/** Decide if a content should be speculatively converted.
*
* This allows for image content handlers to ask the cache if a bitmap
* should be generated before it is added to the cache. This is the
* same decision logic used to decide to perform an immediate
* conversion when a content is initially added to the cache.
*
* @param c The content to be considered.
* @return true if a speculative conversion is desired false otehrwise.
*/
bool image_cache_speculate(struct content *c);
 
/**
* Fill a buffer with information about a cache entry using a format.
*
* The format string is copied into the output buffer with the
* following replaced:
* %e - The entry number
* %k - The content key
* %r - The number of redraws of this bitmap
* %c - The number of times this bitmap has been converted
* %s - The size of the current bitmap allocation
*
* \param string The buffer in which to place the results.
* \param size The size of the string buffer.
* \param entryn The opaque entry number.
* \param fmt The format string.
* \return The number of bytes written to \a string or -1 on error
*/
int image_cache_snentryf(char *string, size_t size, unsigned int entryn,
const char *fmt);
 
/**
* Fill a buffer with information about the image cache using a format.
*
* The format string is copied into the output buffer with the
* following replaced:
*
* a Configured cache limit size
* b Configured cache hysteresis size
* c Current caches total consumed size
* d Number of images currently in the cache
* e The age of the cache
* f The largest amount of space the cache has occupied since initialisation
* g The number of objetcs when the cache was at its largest
* h The largest number of images in the cache since initialisation
* i The size of the cache when the largest number of objects occoured
* j The total number of read operations performed on the cache
* k The total number of read operations satisfied from the cache without
* conversion.
* l The total number of read operations satisfied from the cache which
* required a conversion.
* m The total number of read operations which could not be sucessfully
* returned. ie. not available in cache and conversion failed.
* n The total size of read operations performed on the cache
* o The total size of read operations satisfied from the cache without
* conversion.
* q The total size of read operations satisfied from the cache which
* required a conversion.
* r The total size of read operations which could not be sucessfully
* returned. ie. not available in cache and conversion failed.
* s The number of images which were placed in the cache but never read.
* t The number of images that were converted on insertion into teh cache which were subsequently never used.
* u The number of times an image was converted after the first
* v The number of images that had extra conversions performed.
* w Size of the image that was converted (read missed cache) highest number
* of times.
* x The number of times the image that was converted (read missed cache)
* highest number of times.
*
* format modifiers:
* A p before the value modifies the replacement to be a percentage.
*
*
* \param string The buffer in which to place the results.
* \param size The size of the string buffer.
* \param fmt The format string.
* \return The number of bytes written to \a string or -1 on error
*/
 
int image_cache_snsummaryf(char *string, size_t size, const char *fmt);
 
/********* Image content handler generic cache callbacks ************/
 
/** Generic content redraw callback
*
* May be used by image content handlers as their redraw
* callback. Performs all neccissary cache lookups and conversions and
* calls the bitmap plot function in the redraw context.
*/
bool image_cache_redraw(struct content *c,
struct content_redraw_data *data,
const struct rect *clip,
const struct redraw_context *ctx);
 
void image_cache_destroy(struct content *c);
 
void *image_cache_get_internal(const struct content *c, void *context);
 
content_type image_cache_content_type(void);
 
#endif
/contrib/network/netsurf/netsurf/image/jpeg.c
0,0 → 1,395
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \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>
 
#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/image_cache.h"
 
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/types.h"
#include "utils/utils.h"
 
#define JPEG_INTERNAL_OPTIONS
#include "jpeglib.h"
#include "image/jpeg.h"
 
/** absolute minimum size of a jpeg below which it is not even worth
* trying to read header data
*/
#define MIN_JPEG_SIZE 20
 
#ifdef riscos
/* 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
/* but we don't care if we're not on RISC OS */
#endif
 
static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];
 
static unsigned char nsjpeg_eoi[] = { 0xff, JPEG_EOI };
 
/**
* Content create entry point.
*/
static nserror nsjpeg_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)
{
struct content *jpeg;
nserror error;
 
jpeg = calloc(1, sizeof(struct content));
if (jpeg == NULL)
return NSERROR_NOMEM;
 
error = content__init(jpeg, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(jpeg);
return error;
}
 
*c = jpeg;
 
return NSERROR_OK;
}
 
/**
* JPEG data source manager: initialize source.
*/
static void nsjpeg_init_source(j_decompress_ptr cinfo)
{
}
 
 
/**
* 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.
*/
static 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.
*/
 
static 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.
*/
static void nsjpeg_term_source(j_decompress_ptr cinfo)
{
}
 
 
/**
* Error output handler for JPEG library.
*
* This logs to NetSurf log instead of stderr.
* Warnings only - fatal errors are trapped by nsjpeg_error_exit
* and do not call the output handler.
*/
static void nsjpeg_error_log(j_common_ptr cinfo)
{
cinfo->err->format_message(cinfo, nsjpeg_error_buffer);
LOG(("%s", nsjpeg_error_buffer));
}
 
 
/**
* Fatal error handler for JPEG library.
*
* This prevents jpeglib calling exit() on a fatal error.
*/
static void nsjpeg_error_exit(j_common_ptr cinfo)
{
jmp_buf *setjmp_buffer = (jmp_buf *) cinfo->client_data;
 
cinfo->err->format_message(cinfo, nsjpeg_error_buffer);
LOG(("%s", nsjpeg_error_buffer));
 
longjmp(*setjmp_buffer, 1);
}
 
static struct bitmap *
jpeg_cache_convert(struct content *c)
{
uint8_t *source_data; /* Jpeg source data */
unsigned long source_size; /* length of Jpeg source data */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
jmp_buf setjmp_buffer;
unsigned int height;
unsigned int width;
struct bitmap * volatile bitmap = NULL;
uint8_t * volatile pixels = NULL;
size_t rowstride;
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 };
 
/* obtain jpeg source data and perfom minimal sanity checks */
source_data = (uint8_t *)content__get_source_data(c, &source_size);
 
if ((source_data == NULL) ||
(source_size < MIN_JPEG_SIZE)) {
return NULL;
}
 
/* setup a JPEG library error handler */
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = nsjpeg_error_exit;
jerr.output_message = nsjpeg_error_log;
 
/* handler for fatal errors during decompression */
if (setjmp(setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
return bitmap;
}
 
jpeg_create_decompress(&cinfo);
cinfo.client_data = &setjmp_buffer;
 
/* setup data source */
source_mgr.next_input_byte = source_data;
source_mgr.bytes_in_buffer = source_size;
cinfo.src = &source_mgr;
 
/* read JPEG header information */
jpeg_read_header(&cinfo, TRUE);
 
/* set output processing parameters */
cinfo.out_color_space = JCS_RGB;
cinfo.dct_method = JDCT_ISLOW;
 
/* commence the decompression, output parameters now valid */
jpeg_start_decompress(&cinfo);
 
width = cinfo.output_width;
height = cinfo.output_height;
 
/* create opaque bitmap (jpegs cannot be transparent) */
bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE);
if (bitmap == NULL) {
/* empty bitmap could not be created */
jpeg_destroy_decompress(&cinfo);
return NULL;
}
 
pixels = bitmap_get_buffer(bitmap);
if (pixels == NULL) {
/* bitmap with no buffer available */
bitmap_destroy(bitmap);
jpeg_destroy_decompress(&cinfo);
return NULL;
}
 
/* Convert scanlines from jpeg into 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
{
/* Missmatch between configured libjpeg pixel format and
* NetSurf pixel format. Convert to RGBA */
int i;
for (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);
bitmap_modified(bitmap);
 
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
 
return bitmap;
}
 
/**
* Convert a CONTENT_JPEG for display.
*/
static bool nsjpeg_convert(struct content *c)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
jmp_buf setjmp_buffer;
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 };
union content_msg_data msg_data;
const char *data;
unsigned long size;
char *title;
 
/* check image header is valid and get width/height */
data = content__get_source_data(c, &size);
 
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = nsjpeg_error_exit;
jerr.output_message = nsjpeg_error_log;
 
if (setjmp(setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
 
msg_data.error = nsjpeg_error_buffer;
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
jpeg_create_decompress(&cinfo);
cinfo.client_data = &setjmp_buffer;
source_mgr.next_input_byte = (unsigned char *) data;
source_mgr.bytes_in_buffer = size;
cinfo.src = &source_mgr;
jpeg_read_header(&cinfo, TRUE);
cinfo.out_color_space = JCS_RGB;
cinfo.dct_method = JDCT_ISLOW;
 
jpeg_calc_output_dimensions(&cinfo);
 
c->width = cinfo.output_width;
c->height = cinfo.output_height;
c->size = c->width * c->height * 4;
 
jpeg_destroy_decompress(&cinfo);
 
image_cache_add(c, NULL, jpeg_cache_convert);
 
/* set title text */
title = messages_get_buff("JPEGTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
content_set_ready(c);
content_set_done(c);
content_set_status(c, ""); /* Done: update status bar */
 
return true;
}
 
 
 
/**
* Clone content.
*/
static nserror nsjpeg_clone(const struct content *old, struct content **newc)
{
struct content *jpeg_c;
nserror error;
 
jpeg_c = calloc(1, sizeof(struct content));
if (jpeg_c == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, jpeg_c);
if (error != NSERROR_OK) {
content_destroy(jpeg_c);
return error;
}
 
/* re-convert if the content is ready */
if ((old->status == CONTENT_STATUS_READY) ||
(old->status == CONTENT_STATUS_DONE)) {
if (nsjpeg_convert(jpeg_c) == false) {
content_destroy(jpeg_c);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = jpeg_c;
 
return NSERROR_OK;
}
 
static const content_handler nsjpeg_content_handler = {
.create = nsjpeg_create,
.data_complete = nsjpeg_convert,
.destroy = image_cache_destroy,
.redraw = image_cache_redraw,
.clone = nsjpeg_clone,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
.no_share = false,
};
 
static const char *nsjpeg_types[] = {
"image/jpeg",
"image/jpg",
"image/pjpeg"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsjpeg, nsjpeg_types, nsjpeg_content_handler);
/contrib/network/netsurf/netsurf/image/jpeg.h
0,0 → 1,28
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/jpeg (interface).
*/
 
#ifndef _NETSURF_IMAGE_JPEG_H_
#define _NETSURF_IMAGE_JPEG_H_
 
nserror nsjpeg_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/make.image
0,0 → 1,21
CFLAGS += -O2 -DWITH_PNG -DWITH_BMP -DWITH_JPEG -DWITH_GIF
NETSURF_FB_FRONTEND := sdl
NETSURF_FB_FONTLIB := internal
 
NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin/
 
# Default resource install path
NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf/
 
# Default framebuffer search path
NETSURF_FB_RESPATH := $${HOME}/.netsurf/:$${NETSURFRES}:$(NETSURF_FRAMEBUFFER_RESOURCES):./framebuffer/res
 
# freetype compiled in font serch path
NETSURF_FB_FONTPATH := /usr/share/fonts/truetype/ttf-dejavu:/usr/share/fonts/truetype/msttcorefonts
OBJS := image.o image_cache.o bmp.o ico.o gif.o jpeg.o png.o
 
 
OUTFILE = TEST.o
CFLAGS += -I ../include/ -I ../ -I../../ -I./ -I/home/sourcerer/kos_src/newenginek/kolibri/include
include $(MENUETDEV)/makefiles/Makefile_for_o_lib
/contrib/network/netsurf/netsurf/image/mng.c
0,0 → 1,832
/*
* Copyright 2005 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \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 "content/content_protected.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/mng.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
#include "utils/utils.h"
 
/* This implementation does not currently support dynamic MNGs or any
* form of colour/gamma correction,
*/
 
typedef struct nsmng_content
{
struct content base;
bool opaque_test_pending;
bool read_start;
bool read_resume;
int read_size;
bool waiting;
bool displayed;
void *handle;
 
struct bitmap *bitmap; /**< Created NetSurf bitmap */
} nsmng_content;
 
 
#ifndef MNG_INTERNAL_MEMMNGMT
 
/**
* Memory allocation callback for libmng.
*/
 
static mng_ptr nsmng_alloc(mng_size_t n)
{
return calloc(1, n);
}
 
 
/**
* Memory free callback for libmng.
*/
 
static void nsmng_free(mng_ptr p, mng_size_t n)
{
free(p);
}
 
#endif
 
/**
* Broadcasts an error message and returns false
*
* \param c the content to broadcast for
* \return Appropriate error
*/
static nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code)
{
union content_msg_data msg_data;
char error[100];
 
assert(c != NULL);
 
if (code == MNG_OUTOFMEMORY) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
 
snprintf(error, sizeof error, messages_get("MNGError"), code);
msg_data.error = error;
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_MNG_ERROR;
}
 
/* CALLBACKS REQUIRED FOR libmng READING */
 
static mng_bool nsmng_openstream(mng_handle mng)
{
assert(mng != NULL);
return MNG_TRUE;
}
 
static mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size,
mng_uint32 *bytesread)
{
nsmng_content *c;
const char *data;
unsigned long data_size;
 
assert(mng != NULL);
assert(buffer != NULL);
assert(bytesread != NULL);
 
/* Get our content back
*/
c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
 
/* Copy any data we have (maximum of 'size')
*/
data = content__get_source_data(&c->base, &data_size);
 
*bytesread = ((data_size - c->read_size) < size) ?
(data_size - c->read_size) : size;
 
if ((*bytesread) > 0) {
memcpy(buffer, data + c->read_size, *bytesread);
c->read_size += *bytesread;
}
 
/* Return success
*/
return MNG_TRUE;
}
 
static mng_bool nsmng_closestream(mng_handle mng)
{
assert(mng != NULL);
return MNG_TRUE;
}
 
static mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width,
mng_uint32 height)
{
nsmng_content *c;
union content_msg_data msg_data;
uint8_t *buffer;
 
assert(mng != NULL);
 
/* This function is called when the header has been read and we
know the dimensions of the canvas.
*/
c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
 
c->bitmap = bitmap_create(width, height, BITMAP_NEW);
if (c->bitmap == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
LOG(("Insufficient memory to create canvas."));
return MNG_FALSE;
}
 
/* Get the buffer to ensure that it is allocated and the calls in
* nsmng_getcanvasline() succeed. */
buffer = bitmap_get_buffer(c->bitmap);
if (buffer == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
LOG(("Insufficient memory to create canvas."));
return MNG_FALSE;
}
 
/* Initialise the content size
*/
c->base.width = width;
c->base.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
*/
 
 
static bool nsmng_process_data(struct content *c, const char *data, unsigned int size)
{
nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
 
assert(c != NULL);
assert(data != NULL);
 
/* We only need to do any processing if we're starting/resuming reading.
*/
if ((!mng->read_resume) && (!mng->read_start))
return true;
 
/* Try to start processing, or process some more data
*/
if (mng->read_start) {
status = mng_read(mng->handle);
mng->read_start = false;
} else {
status = mng_read_resume(mng->handle);
}
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(mng, status) == NSERROR_OK;
}
 
/* Continue onwards
*/
return true;
}
 
/* START OF CALLBACKS REQUIRED FOR DISPLAYING
*/
 
 
static mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line)
{
nsmng_content *c;
 
assert(mng != NULL);
 
/* Get our content back
*/
c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
 
/* Calculate the address
*/
return bitmap_get_buffer(c->bitmap) +
bitmap_get_rowstride(c->bitmap) * line;
}
 
static mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
mng_uint32 w, mng_uint32 h)
{
union content_msg_data data;
nsmng_content *c;
 
assert(mng != NULL);
 
/* Get our content back
*/
c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
 
/* 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->base;
data.redraw.object_x = 0;
data.redraw.object_y = 0;
data.redraw.object_width = c->base.width;
data.redraw.object_height = c->base.height;
 
/* Only attempt to force the redraw if we've been requested to
* display the image in the first place (i.e. nsmng_redraw has
* been called). This avoids the situation of forcibly redrawing
* an image that shouldn't be shown (e.g. if the image is a fallback
* for an object that can't be rendered)
*/
if (c->displayed)
content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
 
return MNG_TRUE;
}
 
/**
* Animates to the next frame
*/
static void nsmng_animate(void *p)
{
nsmng_content *c;
 
assert(p != NULL);
 
c = (nsmng_content *) p;
 
/* If we used the last animation we advance, if not we try again later
*/
if (c->base.user_list->next == NULL) {
c->waiting = true;
} else {
c->waiting = false;
mng_display_resume(c->handle);
c->opaque_test_pending = true;
if (c->bitmap)
bitmap_modified(c->bitmap);
}
}
 
static mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs)
{
nsmng_content *c;
 
assert(mng != NULL);
 
/* Get our content back
*/
c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
 
/* Perform the scheduling
*/
schedule(msecs / 10, nsmng_animate, c);
return MNG_TRUE;
}
 
/**
* Get the wall-clock time in milliseconds since some fixed time.
*/
 
static mng_uint32 nsmng_gettickcount(mng_handle mng)
{
static bool start = true;
static time_t t0;
struct timeval tv;
#if defined(__SVR4) && defined(__sun) || defined(__NetBSD__) || \
defined(__APPLE__)
/* Solaris, NetBSD, and OS X don't have this structure, and ignore the
* second parameter to gettimeofday()
*/
int tz;
#else
struct timezone tz;
#endif
assert(mng != NULL);
 
gettimeofday(&tv, &tz);
if (start) {
t0 = tv.tv_sec;
start = false;
}
 
return (tv.tv_sec - t0) * 1000 + tv.tv_usec / 1000;
}
 
/* END OF CALLBACKS REQUIRED FOR DISPLAYING
*/
 
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)
{
nsmng_content *c;
char chunk[5];
 
assert(mng != NULL);
 
c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
 
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):",
content_get_url(&c->base), chunk, chunkseq));
LOG(("code %d severity %d extra1 %d extra2 %d text:'%s'", code,
severity, extra1, extra2, text));
 
return (0);
}
 
static nserror nsmng_create_mng_data(nsmng_content *c)
{
mng_retcode code;
union content_msg_data msg_data;
 
assert(c != NULL);
 
/* Initialise the library
*/
#ifdef MNG_INTERNAL_MEMMNGMT
c->handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL);
#else
c->handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL);
#endif
if (c->handle == MNG_NULL) {
LOG(("Unable to initialise MNG library."));
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
 
/* We need to decode in suspension mode
*/
code = mng_set_suspensionmode(c->handle, MNG_TRUE);
if (code) {
LOG(("Unable to set suspension mode."));
return nsmng_broadcast_error(c, code);
}
 
/* We need to register our callbacks
*/
code = mng_setcb_openstream(c->handle, nsmng_openstream);
if (code) {
LOG(("Unable to set openstream callback."));
return nsmng_broadcast_error(c, code);
}
code = mng_setcb_readdata(c->handle, nsmng_readdata);
if (code) {
LOG(("Unable to set readdata callback."));
return nsmng_broadcast_error(c, code);
}
code = mng_setcb_closestream(c->handle, nsmng_closestream);
if (code) {
LOG(("Unable to set closestream callback."));
return nsmng_broadcast_error(c, code);
}
code = mng_setcb_processheader(c->handle, nsmng_processheader);
if (code) {
LOG(("Unable to set processheader callback."));
return nsmng_broadcast_error(c, code);
}
 
/* Register our callbacks for displaying
*/
code = mng_setcb_getcanvasline(c->handle, nsmng_getcanvasline);
if (code) {
LOG(("Unable to set getcanvasline callback."));
return nsmng_broadcast_error(c, code);
}
code = mng_setcb_refresh(c->handle, nsmng_refresh);
if (code) {
LOG(("Unable to set refresh callback."));
return nsmng_broadcast_error(c, code);
}
code = mng_setcb_gettickcount(c->handle, nsmng_gettickcount);
if (code) {
LOG(("Unable to set gettickcount callback."));
return nsmng_broadcast_error(c, code);
}
code = mng_setcb_settimer(c->handle, nsmng_settimer);
if (code) {
LOG(("Unable to set settimer callback."));
return nsmng_broadcast_error(c, code);
}
 
/* register error handling function */
code = mng_setcb_errorproc(c->handle, nsmng_errorproc);
if (code) {
LOG(("Unable to set errorproc"));
return nsmng_broadcast_error(c, code);
}
 
/* Initialise the reading
*/
c->read_start = true;
c->read_resume = false;
c->read_size = 0;
c->waiting = false;
 
c->displayed = false;
 
return NSERROR_OK;
}
 
static nserror nsmng_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
{
nsmng_content *mng;
nserror error;
 
mng = calloc(1, sizeof(nsmng_content));
if (mng == NULL)
return NSERROR_NOMEM;
 
error = content__init(&mng->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(mng);
return error;
}
 
error = nsmng_create_mng_data(mng);
if (error != NSERROR_OK) {
free(mng);
return error;
}
 
*c = (struct content *) mng;
 
return NSERROR_OK;
}
 
 
 
static bool nsmng_convert(struct content *c)
{
nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
unsigned long size;
char *title;
 
assert(c != NULL);
 
content__get_source_data(c, &size);
 
/* by this point, the png should have been parsed
* and the bitmap created, so ensure that's the case
*/
if (mng->bitmap == NULL) {
return nsmng_broadcast_error(mng, -1) == NSERROR_OK;
}
 
 
/* set title text */
title = messages_get_buff("MNGTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
c->size += c->width * c->height * 4;
content_set_ready(c);
content_set_done(c);
/* Done: update status bar */
content_set_status(c, "");
 
/* jmb: I'm really not sure that this should be here.
* The *_convert functions are for converting a content into a
* displayable format. They should not, however, do anything which
* could cause the content to be displayed; the content may have
* hidden visibility or be a fallback for an object; this
* information is not available here (nor is there any need for it
* to be).
* The specific issue here is that mng_display calls the display
* callbacks, which include nsmng_refresh. nsmng_refresh forces
* a content to be redrawn regardless of whether it should be
* displayed or not.
*/
/* Start displaying
*/
status = mng_display(mng->handle);
if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) {
LOG(("Unable to start display (%i)", status));
return nsmng_broadcast_error(mng, status) == NSERROR_OK;
}
bitmap_modified(mng->bitmap);
 
/* Optimise the plotting of MNG */
mng->opaque_test_pending = false;
 
return true;
}
 
static bool nsjpng_convert(struct content *c)
{
nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
unsigned long size;
char *title;
mng_handle handle;
 
assert(c != NULL);
 
content__get_source_data(c, &size);
 
/* by this point, the png should have been parsed
* and the bitmap created, so ensure that's the case
*/
if (mng->bitmap == NULL) {
return nsmng_broadcast_error(mng, -1) == NSERROR_OK;
}
 
/* set title text */
title = messages_get_buff("PNGTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
c->size += c->width * c->height * 4;
content_set_ready(c);
content_set_done(c);
/* Done: update status bar */
content_set_status(c, "");
 
/* jmb: I'm really not sure that this should be here.
* The *_convert functions are for converting a content into a
* displayable format. They should not, however, do anything which
* could cause the content to be displayed; the content may have
* hidden visibility or be a fallback for an object; this
* information is not available here (nor is there any need for it
* to be).
* The specific issue here is that mng_display calls the display
* callbacks, which include nsmng_refresh. nsmng_refresh forces
* a content to be redrawn regardless of whether it should be
* displayed or not.
*/
/* Start displaying
*/
status = mng_display(mng->handle);
if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) {
LOG(("Unable to start display (%i)", status));
return nsmng_broadcast_error(mng, status) == NSERROR_OK;
}
bitmap_modified(mng->bitmap);
 
/* Optimise the plotting of JNG/PNGs
*/
mng->opaque_test_pending = true;
bitmap_set_opaque(mng->bitmap, false);
 
/* free associated memory */
 
handle = mng->handle;
 
mng_cleanup(&handle);
 
mng->handle = NULL;
 
return true;
}
 
static void nsmng_destroy(struct content *c)
{
nsmng_content *mng = (nsmng_content *) c;
 
assert (c != NULL);
 
/* Cleanup the MNG structure and release the canvas memory
*/
schedule_remove(nsmng_animate, c);
 
if (mng->handle != NULL) {
mng_handle handle = mng->handle;
 
mng_cleanup(&handle);
 
mng->handle = NULL;
}
 
if (mng->bitmap) {
bitmap_destroy(mng->bitmap);
}
}
 
 
static bool nsmng_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
nsmng_content *mng = (nsmng_content *) c;
bool ret;
bitmap_flags_t flags = BITMAPF_NONE;
 
/* mark image as having been requested to display */
mng->displayed = true;
 
if ((mng->bitmap) &&
(mng->opaque_test_pending)) {
bitmap_set_opaque(mng->bitmap, bitmap_test_opaque(mng->bitmap));
mng->opaque_test_pending = false;
}
 
if (data->repeat_x)
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
 
ret = ctx->plot->bitmap(data->x, data->y, data->width, data->height,
mng->bitmap, data->background_colour, flags);
 
/* Check if we need to restart the animation */
if ((mng->waiting) &&
(nsoption_bool(animate_images))) {
nsmng_animate(c);
}
 
return ret;
}
 
 
static nserror nsmng_clone(const struct content *old, struct content **newc)
{
nsmng_content *mng;
nserror error;
const char *data;
unsigned long size;
 
mng = calloc(1, sizeof(nsmng_content));
if (mng == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &mng->base);
if (error != NSERROR_OK) {
content_destroy(&mng->base);
return error;
}
 
/* Simply replay create/process/convert */
error = nsmng_create_mng_data(mng);
if (error != NSERROR_OK) {
content_destroy(&mng->base);
return error;
}
 
data = content__get_source_data(&mng->base, &size);
if (size > 0) {
if (nsmng_process_data(&mng->base, data, size) == false) {
content_destroy(&mng->base);
return NSERROR_CLONE_FAILED;
}
}
 
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (nsmng_convert(&mng->base) == false) {
content_destroy(&mng->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) mng;
 
return NSERROR_OK;
}
 
static void *nsmng_get_internal(const struct content *c, void *context)
{
nsmng_content *mng = (nsmng_content *)c;
 
return mng->bitmap;
}
 
static content_type nsmng_content_type(void)
{
return CONTENT_IMAGE;
}
 
/* register handler for mng types */
static const content_handler nsmng_content_handler = {
.create = nsmng_create,
.process_data = nsmng_process_data,
.data_complete = nsmng_convert,
.destroy = nsmng_destroy,
.redraw = nsmng_redraw,
.clone = nsmng_clone,
.get_internal = nsmng_get_internal,
.type = nsmng_content_type,
.no_share = false,
};
 
static const char *nsmng_types[] = {
/* MNG types*/
"image/mng",
"image/x-mng",
"video/mng",
"video/x-mng",
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsmng, nsmng_types, nsmng_content_handler);
 
/* register handler for jng and png types */
static const content_handler nsjpng_content_handler = {
.create = nsmng_create,
.process_data = nsmng_process_data,
.data_complete = nsjpng_convert,
.destroy = nsmng_destroy,
.redraw = nsmng_redraw,
.clone = nsmng_clone,
.get_internal = nsmng_get_internal,
.type = nsmng_content_type,
.no_share = false,
};
 
 
static const char *nsjpng_types[] = {
/* JNG types*/
"image/jng",
"image/x-jng",
/* PNG types*/
"image/png",
"image/x-png"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsjpng, nsjpng_types, nsjpng_content_handler);
/contrib/network/netsurf/netsurf/image/mng.h
0,0 → 1,29
/*
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/mng, image/png, and image/jng (interface).
*/
 
#ifndef _NETSURF_IMAGE_MNG_H_
#define _NETSURF_IMAGE_MNG_H_
 
nserror nsmng_init(void);
nserror nsjpng_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/nssprite.c
0,0 → 1,258
/*
* Copyright 2008 James Shaw <js102@zepler.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/x-riscos-sprite (librosprite implementation).
*
*/
 
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <librosprite.h>
#include "utils/config.h"
#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/nssprite.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
typedef struct nssprite_content {
struct content base;
struct bitmap *bitmap; /**< Created NetSurf bitmap */
 
struct rosprite_area* sprite_area;
} nssprite_content;
 
 
#define ERRCHK(x) do { \
rosprite_error err = x; \
if (err == ROSPRITE_EOF) { \
LOG(("Got ROSPRITE_EOF when loading sprite file")); \
return false; \
} else if (err == ROSPRITE_BADMODE) { \
LOG(("Got ROSPRITE_BADMODE when loading sprite file")); \
return false; \
} else if (err == ROSPRITE_OK) { \
} else { \
return false; \
} \
} while(0)
 
 
 
 
static nserror nssprite_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)
{
nssprite_content *sprite;
nserror error;
 
sprite = calloc(1, sizeof(nssprite_content));
if (sprite == NULL)
return NSERROR_NOMEM;
 
error = content__init(&sprite->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(sprite);
return error;
}
 
*c = (struct content *) sprite;
 
return NSERROR_OK;
}
 
/**
* Convert a CONTENT_SPRITE for display.
*
* No conversion is necessary. We merely read the sprite dimensions.
*/
 
static bool nssprite_convert(struct content *c)
{
nssprite_content *nssprite = (nssprite_content *) c;
union content_msg_data msg_data;
 
struct rosprite_mem_context* ctx;
 
const char *data;
unsigned long size;
char *title;
 
data = content__get_source_data(c, &size);
 
ERRCHK(rosprite_create_mem_context((uint8_t *) data, size, &ctx));
 
struct rosprite_area* sprite_area;
ERRCHK(rosprite_load(rosprite_mem_reader, ctx, &sprite_area));
rosprite_destroy_mem_context(ctx);
nssprite->sprite_area = sprite_area;
 
assert(sprite_area->sprite_count > 0);
 
struct rosprite* sprite = sprite_area->sprites[0];
 
nssprite->bitmap = bitmap_create(sprite->width, sprite->height, BITMAP_NEW);
if (!nssprite->bitmap) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
uint32_t* imagebuf = (uint32_t *)bitmap_get_buffer(nssprite->bitmap);
if (!imagebuf) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
unsigned char *spritebuf = (unsigned char *)sprite->image;
 
/* reverse byte order of each word */
for (uint32_t y = 0; y < sprite->height; y++) {
for (uint32_t x = 0; x < sprite->width; x++) {
int offset = 4 * (y * sprite->width + x);
 
*imagebuf = (spritebuf[offset] << 24) |
(spritebuf[offset + 1] << 16) |
(spritebuf[offset + 2] << 8) |
(spritebuf[offset + 3]);
 
imagebuf++;
}
}
 
c->width = sprite->width;
c->height = sprite->height;
 
/* set title text */
title = messages_get_buff("SpriteTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
bitmap_modified(nssprite->bitmap);
 
content_set_ready(c);
content_set_done(c);
content_set_status(c, ""); /* Done: update status bar */
 
return true;
}
 
 
/**
* Destroy a CONTENT_SPRITE and free all resources it owns.
*/
 
static void nssprite_destroy(struct content *c)
{
nssprite_content *nssprite = (nssprite_content *) c;
 
if (nssprite->sprite_area != NULL)
rosprite_destroy_sprite_area(nssprite->sprite_area);
if (nssprite->bitmap != NULL)
bitmap_destroy(nssprite->bitmap);
}
 
 
/**
* Redraw a CONTENT_SPRITE.
*/
 
static bool nssprite_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
nssprite_content *nssprite = (nssprite_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
 
if (data->repeat_x)
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
 
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
nssprite->bitmap, data->background_colour, flags);
}
 
 
static nserror nssprite_clone(const struct content *old, struct content **newc)
{
nssprite_content *sprite;
nserror error;
 
sprite = calloc(1, sizeof(nssprite_content));
if (sprite == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &sprite->base);
if (error != NSERROR_OK) {
content_destroy(&sprite->base);
return error;
}
 
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (nssprite_convert(&sprite->base) == false) {
content_destroy(&sprite->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) sprite;
 
return NSERROR_OK;
}
 
static void *nssprite_get_internal(const struct content *c, void *context)
{
nssprite_content *nssprite = (nssprite_content *) c;
 
return nssprite->bitmap;
}
 
static content_type nssprite_content_type(void)
{
return CONTENT_IMAGE;
}
 
 
static const content_handler nssprite_content_handler = {
.create = nssprite_create,
.data_complete = nssprite_convert,
.destroy = nssprite_destroy,
.redraw = nssprite_redraw,
.clone = nssprite_clone,
.get_internal = nssprite_get_internal,
.type = nssprite_content_type,
.no_share = false,
};
 
static const char *nssprite_types[] = {
"image/x-riscos-sprite"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nssprite, nssprite_types, nssprite_content_handler);
/contrib/network/netsurf/netsurf/image/nssprite.h
0,0 → 1,28
/*
* Copyright 2008 James Shaw <js102@zepler.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/x-riscos-sprite (librosprite interface).
*/
 
#ifndef _NETSURF_NS_SPRITE_H_
#define _NETSURF_NS_SPRITE_H_
 
nserror nssprite_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/png.c
0,0 → 1,608
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2004 Richard Wilson <not_ginger_matt@hotmail.com>
* Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
 
#include <png.h>
 
#include "desktop/plotters.h"
 
#include "content/content_protected.h"
 
#include "image/bitmap.h"
#include "image/image_cache.h"
#include "image/png.h"
 
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
/* accommodate for old versions of libpng (beware security holes!) */
 
#ifndef png_jmpbuf
#warning you have an antique libpng
#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)
#endif
 
typedef struct nspng_content {
struct content base; /**< base content type */
 
bool no_process_data; /**< Do not continue to process data as it arrives */
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 */
} nspng_content;
 
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};
 
/** Callbak error numbers*/
enum nspng_cberr {
CBERR_NONE = 0, /* no error */
CBERR_LIBPNG, /* error from png library */
CBERR_NOPRE, /* no pre-conversion performed */
};
 
/**
* nspng_warning -- callback for libpng warnings
*/
static void nspng_warning(png_structp png_ptr, png_const_charp warning_message)
{
LOG(("%s", warning_message));
}
 
/**
* nspng_error -- callback for libpng errors
*/
static void nspng_error(png_structp png_ptr, png_const_charp error_message)
{
LOG(("%s", error_message));
longjmp(png_jmpbuf(png_ptr), CBERR_LIBPNG);
}
 
static void nspng_setup_transforms(png_structp png_ptr, png_infop info_ptr)
{
int bit_depth, color_type, intent;
double gamma;
 
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
 
/* Set up our transformations */
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
 
if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) {
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
 
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_ptr);
}
 
if (bit_depth == 16) {
png_set_strip_16(png_ptr);
}
 
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(png_ptr);
}
 
if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
png_set_filler(png_ptr, 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_ptr, info_ptr, &intent)) {
png_set_gamma(png_ptr, 2.2, 0.45455);
} else {
if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
png_set_gamma(png_ptr, 2.2, gamma);
} else {
png_set_gamma(png_ptr, 2.2, 0.45455);
}
}
 
png_read_update_info(png_ptr, info_ptr);
}
 
/**
* info_callback -- PNG header has been completely received, prepare to process
* image data
*/
static void info_callback(png_structp png_s, png_infop info)
{
int interlace;
png_uint_32 width, height;
nspng_content *png_c = png_get_progressive_ptr(png_s);
 
width = png_get_image_width(png_s, info);
height = png_get_image_height(png_s, info);
interlace = png_get_interlace_type(png_s, info);
 
png_c->base.width = width;
png_c->base.height = height;
png_c->base.size += width * height * 4;
 
/* see if progressive-conversion should continue */
if (image_cache_speculate((struct content *)png_c) == false) {
longjmp(png_jmpbuf(png_s), CBERR_NOPRE);
}
 
/* Claim the required memory for the converted PNG */
png_c->bitmap = bitmap_create(width, height, BITMAP_NEW);
if (png_c->bitmap == NULL) {
/* Failed to create bitmap skip pre-conversion */
longjmp(png_jmpbuf(png_s), CBERR_NOPRE);
}
 
png_c->rowstride = bitmap_get_rowstride(png_c->bitmap);
png_c->bpp = bitmap_get_bpp(png_c->bitmap);
 
nspng_setup_transforms(png_s, info);
 
png_c->rowbytes = png_get_rowbytes(png_s, info);
png_c->interlace = (interlace == PNG_INTERLACE_ADAM7);
 
LOG(("size %li * %li, rowbytes %zu", (unsigned long)width,
(unsigned long)height, png_c->rowbytes));
}
 
static void row_callback(png_structp png_s, png_bytep new_row,
png_uint_32 row_num, int pass)
{
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 (png_c->bitmap == NULL)
return;
 
/* Abort if we've not got any data */
if (new_row == NULL)
return;
 
/* Get bitmap buffer */
buffer = bitmap_get_buffer(png_c->bitmap);
if (buffer == NULL) {
/* No buffer, bail out */
longjmp(png_jmpbuf(png_s), 1);
}
 
/* Calculate address of row start */
row = buffer + (png_c->rowstride * row_num);
 
/* Handle interlaced sprites using the Adam7 algorithm */
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;
 
/* Copy the data to our current row taking interlacing
* into consideration */
row = buffer + (png_c->rowstride * row_num);
 
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 */
memcpy(row, new_row, rowbytes);
}
}
 
 
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_set_error_fn(png_c->png, NULL, nspng_error, nspng_warning);
 
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 = calloc(1, sizeof(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) {
free(png_c);
return error;
}
 
error = nspng_create_png_data(png_c);
if (error != NSERROR_OK) {
free(png_c);
return error;
}
 
*c = (struct content *)png_c;
 
return NSERROR_OK;
}
 
 
static bool nspng_process_data(struct content *c, const char *data,
unsigned int size)
{
nspng_content *png_c = (nspng_content *)c;
union content_msg_data msg_data;
volatile bool ret = true;
 
if (png_c->no_process_data) {
return ret;
}
 
switch (setjmp(png_jmpbuf(png_c->png))) {
case CBERR_NONE: /* direct return */
png_process_data(png_c->png, png_c->info, (uint8_t *)data, size);
break;
 
case CBERR_NOPRE: /* not going to progressive convert */
png_c->no_process_data = true;
break;
 
default: /* fatal error from library processing png */
if (png_c->bitmap != NULL) {
/* A bitmap managed to get created so
* operation is past header and possibly some
* conversion happened before faliure.
*
* In this case keep the partial
* conversion. This is usually seen if a png
* has been truncated (often jsut lost its
* last byte and hence end of image marker)
*/
png_c->no_process_data = true;
} else {
/* not managed to progress past header, clean
* up png conversion and signal the content
* error
*/
LOG(("Fatal PNG error during header, error content"));
 
png_destroy_read_struct(&png_c->png, &png_c->info, 0);
png_c->png = NULL;
png_c->info = NULL;
 
msg_data.error = messages_get("PNGError");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
 
ret = false;
 
}
break;
}
 
return ret;
}
 
struct png_cache_read_data_s {
const char *data;
unsigned long size;
};
 
/** PNG library read fucntion to read data from a memory array
*/
static void
png_cache_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)
{
struct png_cache_read_data_s *png_cache_read_data;
png_cache_read_data = png_get_io_ptr(png_ptr);
 
if (length > png_cache_read_data->size) {
length = png_cache_read_data->size;
}
 
if (length == 0) {
png_error(png_ptr, "Read Error");
}
 
memcpy(data, png_cache_read_data->data, length);
 
png_cache_read_data->data += length;
png_cache_read_data->size -= length;
}
 
/** calculate an array of row pointers into a bitmap data area
*/
static png_bytep *calc_row_pointers(struct bitmap *bitmap)
{
int height = bitmap_get_height(bitmap);
unsigned char *buffer= bitmap_get_buffer(bitmap);
size_t rowstride = bitmap_get_rowstride(bitmap);
png_bytep *row_ptrs;
int hloop;
 
row_ptrs = malloc(sizeof(png_bytep) * height);
 
if (row_ptrs != NULL) {
for (hloop = 0; hloop < height; hloop++) {
row_ptrs[hloop] = buffer + (rowstride * hloop);
}
}
 
return row_ptrs;
}
 
/** PNG content to bitmap conversion.
*
* This routine generates a bitmap object from a PNG image content
*/
static struct bitmap *
png_cache_convert(struct content *c)
{
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
volatile struct bitmap *bitmap = NULL;
struct png_cache_read_data_s png_cache_read_data;
png_uint_32 width, height;
volatile png_bytep *row_pointers = NULL;
 
png_cache_read_data.data =
content__get_source_data(c, &png_cache_read_data.size);
 
if ((png_cache_read_data.data == NULL) ||
(png_cache_read_data.size <= 8)) {
return NULL;
}
 
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL,
nspng_error,
nspng_warning);
if (png_ptr == NULL) {
return NULL;
}
 
info_ptr = png_create_info_struct(png_ptr);
if (png_ptr == NULL) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
return NULL;
}
 
end_info = png_create_info_struct(png_ptr);
if (png_ptr == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return NULL;
}
 
/* setup error exit path */
if (setjmp(png_jmpbuf(png_ptr))) {
/* cleanup and bail */
goto png_cache_convert_error;
}
 
/* read from a buffer instead of stdio */
png_set_read_fn(png_ptr, &png_cache_read_data, png_cache_read_fn);
 
/* ensure the png info structure is populated */
png_read_info(png_ptr, info_ptr);
 
/* setup output transforms */
nspng_setup_transforms(png_ptr, info_ptr);
 
width = png_get_image_width(png_ptr, info_ptr);
height = png_get_image_height(png_ptr,info_ptr);
 
/* Claim the required memory for the converted PNG */
bitmap = bitmap_create(width, height, BITMAP_NEW);
if (bitmap == NULL) {
/* cleanup and bail */
goto png_cache_convert_error;
}
 
row_pointers = calc_row_pointers((struct bitmap *) bitmap);
 
if (row_pointers != NULL) {
png_read_image(png_ptr, (png_bytep *) row_pointers);
}
 
png_cache_convert_error:
 
/* cleanup png read */
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
 
free((png_bytep *) row_pointers);
 
if (bitmap != NULL)
bitmap_modified((struct bitmap *)bitmap);
 
return (struct bitmap *)bitmap;
}
 
static bool nspng_convert(struct content *c)
{
nspng_content *png_c = (nspng_content *) c;
char *title;
 
assert(png_c->png != NULL);
assert(png_c->info != NULL);
 
/* clean up png structures */
png_destroy_read_struct(&png_c->png, &png_c->info, 0);
 
/* set title text */
title = messages_get_buff("PNGTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
if (png_c->bitmap != NULL) {
bitmap_set_opaque(png_c->bitmap, bitmap_test_opaque(png_c->bitmap));
bitmap_modified(png_c->bitmap);
}
 
image_cache_add(c, png_c->bitmap, png_cache_convert);
 
content_set_ready(c);
content_set_done(c);
content_set_status(c, "");
 
return true;
}
 
 
static nserror nspng_clone(const struct content *old_c, struct content **new_c)
{
nspng_content *clone_png_c;
nserror error;
const char *data;
unsigned long size;
 
clone_png_c = calloc(1, sizeof(nspng_content));
if (clone_png_c == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old_c, &clone_png_c->base);
if (error != NSERROR_OK) {
content_destroy(&clone_png_c->base);
return error;
}
 
/* Simply replay create/process/convert */
error = nspng_create_png_data(clone_png_c);
if (error != NSERROR_OK) {
content_destroy(&clone_png_c->base);
return error;
}
 
data = content__get_source_data(&clone_png_c->base, &size);
if (size > 0) {
if (nspng_process_data(&clone_png_c->base, data, size) == false) {
content_destroy(&clone_png_c->base);
return NSERROR_NOMEM;
}
}
 
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;
}
}
 
*new_c = (struct content *)clone_png_c;
 
return NSERROR_OK;
}
 
static const content_handler nspng_content_handler = {
.create = nspng_create,
.process_data = nspng_process_data,
.data_complete = nspng_convert,
.clone = nspng_clone,
.destroy = image_cache_destroy,
.redraw = image_cache_redraw,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
.no_share = false,
};
 
static const char *nspng_types[] = {
"image/png",
"image/x-png"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nspng, nspng_types, nspng_content_handler);
/contrib/network/netsurf/netsurf/image/png.h
0,0 → 1,25
/*
* Copyright 2003 James Bursa <bursa@users.sourceforge.net>
* Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _NETSURF_RISCOS_PNG_H_
#define _NETSURF_RISCOS_PNG_H_
 
nserror nspng_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/rsvg.c
0,0 → 1,322
/*
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content handler for image/svg using librsvg (implementation).
*
* SVG files are rendered to a NetSurf bitmap by creating a Cairo rendering
* surface (content_rsvg_data.cs) over the bitmap's data, creating a Cairo
* drawing context using that surface, and then passing that drawing context
* to librsvg which then uses Cairo calls to plot the graphic to the bitmap.
* We store this in content->bitmap, and then use the usual bitmap plotter
* function to render it for redraw requests.
*/
 
#include <stdbool.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
 
#include <librsvg/rsvg.h>
#include <librsvg/rsvg-cairo.h>
 
#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "utils/log.h"
#include "utils/utils.h"
#include "utils/messages.h"
 
#include "image/rsvg.h"
 
typedef struct rsvg_content {
struct content base;
 
RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
cairo_surface_t *cs; /**< The surface built inside a nsbitmap */
cairo_t *ct; /**< Cairo drawing context */
struct bitmap *bitmap; /**< Created NetSurf bitmap */
} rsvg_content;
 
static nserror rsvg_create_svg_data(rsvg_content *c)
{
union content_msg_data msg_data;
 
c->rsvgh = NULL;
c->cs = NULL;
c->ct = NULL;
c->bitmap = NULL;
 
if ((c->rsvgh = rsvg_handle_new()) == NULL) {
LOG(("rsvg_handle_new() returned NULL."));
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
 
return NSERROR_OK;
}
 
 
static nserror rsvg_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)
{
rsvg_content *svg;
nserror error;
 
svg = calloc(1, sizeof(rsvg_content));
if (svg == NULL)
return NSERROR_NOMEM;
 
error = content__init(&svg->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(svg);
return error;
}
 
error = rsvg_create_svg_data(svg);
if (error != NSERROR_OK) {
free(svg);
return error;
}
 
*c = (struct content *) svg;
 
return NSERROR_OK;
}
 
 
static bool rsvg_process_data(struct content *c, const char *data,
unsigned int size)
{
rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
GError *err = NULL;
 
if (rsvg_handle_write(d->rsvgh, (const guchar *)data, (gsize)size,
&err) == FALSE) {
LOG(("rsvg_handle_write returned an error: %s", err->message));
msg_data.error = err->message;
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
return true;
}
 
/** Convert Cairo's ARGB output to NetSurf's favoured ABGR format. It converts
* the data in-place.
*
* \param pixels Pixel data, in the form of ARGB. This will
* be overwritten with new data in the form of ABGR.
* \param width Width of the bitmap
* \param height Height of the bitmap
* \param rowstride Number of bytes to skip after each row (this
* implementation requires this to be a multiple of 4.)
*/
static inline void rsvg_argb_to_abgr(uint8_t *pixels,
int width, int height, size_t rowstride)
{
uint8_t *p = pixels;
 
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
/* Swap R and B */
const uint8_t r = p[x+3];
 
p[x+3] = p[x];
 
p[x] = r;
}
 
p += rowstride;
}
}
 
static bool rsvg_convert(struct content *c)
{
rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
RsvgDimensionData rsvgsize;
GError *err = NULL;
 
if (rsvg_handle_close(d->rsvgh, &err) == FALSE) {
LOG(("rsvg_handle_close returned an error: %s", err->message));
msg_data.error = err->message;
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
assert(err == NULL);
 
/* we should now be able to query librsvg for the natural size of the
* graphic, so we can create our bitmap.
*/
 
rsvg_handle_get_dimensions(d->rsvgh, &rsvgsize);
c->width = rsvgsize.width;
c->height = rsvgsize.height;
 
if ((d->bitmap = bitmap_create(c->width, c->height,
BITMAP_NEW)) == NULL) {
LOG(("Failed to create bitmap for rsvg render."));
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
if ((d->cs = cairo_image_surface_create_for_data(
(unsigned char *)bitmap_get_buffer(d->bitmap),
CAIRO_FORMAT_ARGB32,
c->width, c->height,
bitmap_get_rowstride(d->bitmap))) == NULL) {
LOG(("Failed to create Cairo image surface for rsvg render."));
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
if ((d->ct = cairo_create(d->cs)) == NULL) {
LOG(("Failed to create Cairo drawing context for rsvg render."));
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
rsvg_handle_render_cairo(d->rsvgh, d->ct);
rsvg_argb_to_abgr(bitmap_get_buffer(d->bitmap),
c->width, c->height,
bitmap_get_rowstride(d->bitmap));
 
bitmap_modified(d->bitmap);
content_set_ready(c);
content_set_done(c);
/* Done: update status bar */
content_set_status(c, "");
 
return true;
}
 
static bool rsvg_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
rsvg_content *rsvgcontent = (rsvg_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
 
assert(rsvgcontent->bitmap != NULL);
 
if (data->repeat_x)
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
 
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
rsvgcontent->bitmap, data->background_colour, flags);
}
 
static void rsvg_destroy(struct content *c)
{
rsvg_content *d = (rsvg_content *) c;
 
if (d->bitmap != NULL) bitmap_destroy(d->bitmap);
if (d->rsvgh != NULL) g_object_unref(d->rsvgh);
if (d->ct != NULL) cairo_destroy(d->ct);
if (d->cs != NULL) cairo_surface_destroy(d->cs);
 
return;
}
 
static nserror rsvg_clone(const struct content *old, struct content **newc)
{
rsvg_content *svg;
nserror error;
const char *data;
unsigned long size;
 
svg = calloc(1, sizeof(rsvg_content));
if (svg == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &svg->base);
if (error != NSERROR_OK) {
content_destroy(&svg->base);
return error;
}
 
/* Simply replay create/process/convert */
error = rsvg_create_svg_data(svg);
if (error != NSERROR_OK) {
content_destroy(&svg->base);
return error;
}
 
data = content__get_source_data(&svg->base, &size);
if (size > 0) {
if (rsvg_process_data(&svg->base, data, size) == false) {
content_destroy(&svg->base);
return NSERROR_NOMEM;
}
}
 
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (rsvg_convert(&svg->base) == false) {
content_destroy(&svg->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) svg;
 
return NSERROR_OK;
}
 
static void *rsvg_get_internal(const struct content *c, void *context)
{
rsvg_content *d = (rsvg_content *) c;
 
return d->bitmap;
}
 
static content_type rsvg_content_type(void)
{
return CONTENT_IMAGE;
}
 
static const content_handler rsvg_content_handler = {
.create = rsvg_create,
.process_data = rsvg_process_data,
.data_complete = rsvg_convert,
.destroy = rsvg_destroy,
.redraw = rsvg_redraw,
.clone = rsvg_clone,
.get_internal = rsvg_get_internal,
.type = rsvg_content_type,
.no_share = false,
};
 
static const char *rsvg_types[] = {
"image/svg",
"image/svg+xml"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsrsvg, rsvg_types, rsvg_content_handler);
 
/contrib/network/netsurf/netsurf/image/rsvg.h
0,0 → 1,28
/*
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content handler for image/svg using librsvg (interface).
*/
 
#ifndef _NETSURF_IMAGE_RSVG_H_
#define _NETSURF_IMAGE_RSVG_H_
 
nserror nsrsvg_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/svg.c
0,0 → 1,352
/*
* Copyright 2007-2008 James Bursa <bursa@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/svg (implementation).
*/
 
#include <assert.h>
#include <limits.h>
#include <string.h>
 
#include <svgtiny.h>
 
#include "content/content_protected.h"
#include "css/css.h"
#include "desktop/plotters.h"
#include "image/svg.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
typedef struct svg_content {
struct content base;
 
struct svgtiny_diagram *diagram;
 
int current_width;
int current_height;
} svg_content;
 
 
 
static nserror svg_create_svg_data(svg_content *c)
{
union content_msg_data msg_data;
 
c->diagram = svgtiny_create();
if (c->diagram == NULL)
goto no_memory;
 
c->current_width = INT_MAX;
c->current_height = INT_MAX;
 
return NSERROR_OK;
 
no_memory:
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return NSERROR_NOMEM;
}
 
 
/**
* Create a CONTENT_SVG.
*/
 
static nserror svg_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)
{
svg_content *svg;
nserror error;
 
svg = calloc(1, sizeof(svg_content));
if (svg == NULL)
return NSERROR_NOMEM;
 
error = content__init(&svg->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(svg);
return error;
}
 
error = svg_create_svg_data(svg);
if (error != NSERROR_OK) {
free(svg);
return error;
}
 
*c = (struct content *) svg;
 
return NSERROR_OK;
}
 
 
 
/**
* Convert a CONTENT_SVG for display.
*/
 
static bool svg_convert(struct content *c)
{
/*c->title = malloc(100);
if (c->title)
snprintf(c->title, 100, messages_get("svgTitle"),
width, height, c->source_size);*/
//c->size += ?;
content_set_ready(c);
content_set_done(c);
/* Done: update status bar */
content_set_status(c, "");
 
return true;
}
 
/**
* Reformat a CONTENT_SVG.
*/
 
static void svg_reformat(struct content *c, int width, int height)
{
svg_content *svg = (svg_content *) c;
const char *source_data;
unsigned long source_size;
 
assert(svg->diagram);
 
/* Avoid reformats to same width/height as we already reformatted to */
if (width != svg->current_width || height != svg->current_height) {
source_data = content__get_source_data(c, &source_size);
 
svgtiny_parse(svg->diagram, source_data, source_size,
nsurl_access(content_get_url(c)),
width, height);
 
svg->current_width = width;
svg->current_height = height;
}
 
c->width = svg->diagram->width;
c->height = svg->diagram->height;
}
 
 
/**
* Redraw a CONTENT_SVG.
*/
 
static bool svg_redraw_internal(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
const struct redraw_context *ctx, float scale,
colour background_colour)
{
svg_content *svg = (svg_content *) c;
float transform[6];
struct svgtiny_diagram *diagram = svg->diagram;
bool ok;
int px, py;
unsigned int i;
plot_font_style_t fstyle = *plot_style_font;
 
assert(diagram);
 
transform[0] = (float) width / (float) c->width;
transform[1] = 0;
transform[2] = 0;
transform[3] = (float) height / (float) c->height;
transform[4] = x;
transform[5] = y;
 
#define BGR(c) ((c) == svgtiny_TRANSPARENT ? NS_TRANSPARENT : \
((svgtiny_RED((c))) | \
(svgtiny_GREEN((c)) << 8) | \
(svgtiny_BLUE((c)) << 16)))
 
for (i = 0; i != diagram->shape_count; i++) {
if (diagram->shape[i].path) {
ok = ctx->plot->path(diagram->shape[i].path,
diagram->shape[i].path_length,
BGR(diagram->shape[i].fill),
diagram->shape[i].stroke_width,
BGR(diagram->shape[i].stroke),
transform);
if (!ok)
return false;
 
} else if (diagram->shape[i].text) {
px = transform[0] * diagram->shape[i].text_x +
transform[2] * diagram->shape[i].text_y +
transform[4];
py = transform[1] * diagram->shape[i].text_x +
transform[3] * diagram->shape[i].text_y +
transform[5];
 
fstyle.background = 0xffffff;
fstyle.foreground = 0x000000;
fstyle.size = (8 * FONT_SIZE_SCALE) * scale;
 
ok = ctx->plot->text(px, py,
diagram->shape[i].text,
strlen(diagram->shape[i].text),
&fstyle);
if (!ok)
return false;
}
}
 
#undef BGR
 
return true;
}
 
 
/**
* Redraw a CONTENT_SVG.
*/
 
static bool svg_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
int x = data->x;
int y = data->y;
 
if ((data->width <= 0) && (data->height <= 0)) {
/* No point trying to plot SVG if it does not occupy a valid
* area */
return true;
}
 
if ((data->repeat_x == false) && (data->repeat_y == false)) {
/* Simple case: SVG is not tiled */
return svg_redraw_internal(c, x, y,
data->width, data->height,
clip, ctx, data->scale,
data->background_colour);
} else {
/* Tiled redraw required. SVG repeats to extents of clip
* rectangle, in x, y or both directions */
int x0, y0, x1, y1;
 
/* Find the redraw boundaries to loop within */
x0 = x;
if (data->repeat_x) {
for (; x0 > clip->x0; x0 -= data->width);
x1 = clip->x1;
} else {
x1 = x + 1;
}
y0 = y;
if (data->repeat_y) {
for (; y0 > clip->y0; y0 -= data->height);
y1 = clip->y1;
} else {
y1 = y + 1;
}
 
/* Repeatedly plot the SVG across the area */
for (y = y0; y < y1; y += data->height) {
for (x = x0; x < x1; x += data->width) {
if (!svg_redraw_internal(c, x, y,
data->width, data->height,
clip, ctx, data->scale,
data->background_colour)) {
return false;
}
}
}
}
 
return true;
}
 
 
/**
* Destroy a CONTENT_SVG and free all resources it owns.
*/
 
static void svg_destroy(struct content *c)
{
svg_content *svg = (svg_content *) c;
 
if (svg->diagram != NULL)
svgtiny_free(svg->diagram);
}
 
 
static nserror svg_clone(const struct content *old, struct content **newc)
{
svg_content *svg;
nserror error;
 
svg = calloc(1, sizeof(svg_content));
if (svg == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &svg->base);
if (error != NSERROR_OK) {
content_destroy(&svg->base);
return error;
}
 
/* Simply replay create/convert */
error = svg_create_svg_data(svg);
if (error != NSERROR_OK) {
content_destroy(&svg->base);
return error;
}
 
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (svg_convert(&svg->base) == false) {
content_destroy(&svg->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) svg;
 
return NSERROR_OK;
}
 
static content_type svg_content_type(void)
{
return CONTENT_IMAGE;
}
 
static const content_handler svg_content_handler = {
.create = svg_create,
.data_complete = svg_convert,
.reformat = svg_reformat,
.destroy = svg_destroy,
.redraw = svg_redraw,
.clone = svg_clone,
.type = svg_content_type,
.no_share = true
};
 
static const char *svg_types[] = {
"image/svg",
"image/svg+xml"
};
 
 
CONTENT_FACTORY_REGISTER_TYPES(svg, svg_types, svg_content_handler);
 
 
/contrib/network/netsurf/netsurf/image/svg.h
0,0 → 1,28
/*
* Copyright 2007-2008 James Bursa <bursa@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/svg (interface).
*/
 
#ifndef _NETSURF_IMAGE_SVG_H_
#define _NETSURF_IMAGE_SVG_H_
 
nserror svg_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/video.c
0,0 → 1,201
/*
* Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#include <gst/gst.h>
 
#include "content/content_factory.h"
#include "content/content_protected.h"
#include "image/video.h"
 
typedef struct nsvideo_content {
struct content base;
 
GstElement *playbin;
GstElement *appsrc;
} nsvideo_content;
 
static gboolean nsvideo_bus_call(GstBus *bus, GstMessage *msg,
nsvideo_content *video)
{
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_ERROR:
break;
case GST_MESSAGE_EOS:
break;
default:
break;
}
 
return TRUE;
}
 
static void nsvideo_need_data_event(GstElement *playbin, guint size,
nsvideo_content *video)
{
}
 
static void nsvideo_enough_data_event(GstElement *playbin,
nsvideo_content *video)
{
}
 
static void nsvideo_source_event(GObject *object, GObject *orig,
GParamSpec *pspec, nsvideo_content *video)
{
g_object_get(orig, pspec->name, &video->appsrc, NULL);
 
g_signal_connect(video->appsrc, "need-data",
G_CALLBACK(nsvideo_need_data_event), video);
g_signal_connect(video->appsrc, "enough-data",
G_CALLBACK(nsvideo_enough_data_event), video);
}
 
static nserror nsvideo_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)
{
nsvideo_content *video;
nserror error;
GstBus *bus;
 
video = calloc(1, sizeof(nsvideo_content));
if (video == NULL)
return NSERROR_NOMEM;
 
error = content__init(&video->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(video);
return error;
}
 
error = llcache_handle_force_stream(llcache);
if (error != NSERROR_OK) {
free(video);
return error;
}
 
video->playbin = gst_element_factory_make("playbin2", NULL);
if (video->playbin == NULL) {
free(video);
return NSERROR_NOMEM;
}
 
bus = gst_pipeline_get_bus(GST_PIPELINE(video->playbin));
gst_bus_add_watch(bus, (GstBusFunc) nsvideo_bus_call, video);
gst_object_unref(bus);
 
g_object_set(video->playbin, "uri", "appsrc://", NULL);
g_signal_connect(video->playbin, "deep-notify::source",
G_CALLBACK(nsvideo_source_event), video);
 
/** \todo Create appsink & register with playbin */
 
gst_element_set_state(video->playbin, GST_STATE_PLAYING);
*c = (struct content *) video;
 
return NSERROR_OK;
}
 
static bool nsvideo_process_data(struct content *c, const char *data,
unsigned int size)
{
nsvideo_content *video = (nsvideo_content *) c;
GstBuffer *buffer;
GstFlowReturn ret;
 
buffer = gst_buffer_new();
GST_BUFFER_DATA(buffer) = (guint8 *) data;
GST_BUFFER_SIZE(buffer) = (gsize) size;
 
/* Send data to appsrc */
g_signal_emit_by_name(video->appsrc, "push-buffer", buffer, &ret);
 
return ret == GST_FLOW_OK;
}
 
static bool nsvideo_convert(struct content *c)
{
nsvideo_content *video = (nsvideo_content *) c;
GstFlowReturn ret;
 
/* Tell appsrc we're done */
g_signal_emit_by_name(video->appsrc, "end-of-stream", &ret);
 
/* Appsink will flag DONE on receipt of first frame */
 
return ret == GST_FLOW_OK;
}
 
static void nsvideo_destroy(struct content *c)
{
nsvideo_content *video = (nsvideo_content *) c;
 
gst_element_set_state(video->playbin, GST_STATE_NULL);
gst_object_unref(video->playbin);
}
 
static bool nsvideo_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
/** \todo Implement */
return true;
}
 
static nserror nsvideo_clone(const struct content *old, struct content **newc)
{
/** \todo Implement */
return NSERROR_CLONE_FAILED;
}
 
static content_type nsvideo_type(void)
{
/** \todo Lies */
return CONTENT_IMAGE;
}
 
static void *nsvideo_get_internal(const struct content *c, void *context)
{
/** \todo Return pointer to bitmap containing current frame, if any? */
return NULL;
}
 
static const content_handler nsvideo_content_handler = {
.create = nsvideo_create,
.process_data = nsvideo_process_data,
.data_complete = nsvideo_convert,
.destroy = nsvideo_destroy,
.redraw = nsvideo_redraw,
.clone = nsvideo_clone,
.type = nsvideo_type,
.get_internal = nsvideo_get_internal,
/* Can't share videos because we stream them */
.no_share = true
};
 
static const char *nsvideo_types[] = {
"video/mp4",
"video/webm"
};
 
CONTENT_FACTORY_REGISTER_TYPES(nsvideo, nsvideo_types,
nsvideo_content_handler);
 
/contrib/network/netsurf/netsurf/image/video.h
0,0 → 1,26
/*
* Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef NETSURF_IMAGE_VIDEO_H_
#define NETSURF_IMAGE_VIDEO_H_
 
#include "utils/errors.h"
 
nserror nsvideo_init(void);
 
#endif
/contrib/network/netsurf/netsurf/image/webp.c
0,0 → 1,229
/*
* Copyright 2010 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/webp (libwebp implementation).
*
*/
 
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <webp/decode.h>
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "content/content_protected.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
 
typedef struct webp_content
{
struct content base;
 
struct bitmap *bitmap; /**< Created NetSurf bitmap */
} webp_content;
 
 
static nserror webp_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)
{
webp_content *webp;
nserror error;
 
webp = calloc(1, sizeof(webp_content));
if (webp == NULL)
return NSERROR_NOMEM;
 
error = content__init(&webp->base, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
free(webp);
return error;
}
 
*c = (struct content *) webp;
 
return NSERROR_OK;
}
 
/**
* Convert a CONTENT_WEBP for display.
*
* No conversion is necessary. We merely read the WebP dimensions.
*/
 
static bool webp_convert(struct content *c)
{
webp_content *webp = (webp_content *)c;
union content_msg_data msg_data;
const uint8_t *data;
unsigned char *imagebuf = NULL;
unsigned long size;
int width = 0, height = 0;
char *title;
int res = 0;
uint8_t *res_p = NULL;
 
data = (uint8_t *)content__get_source_data(c, &size);
 
res = WebPGetInfo(data, size, &width, &height);
if (res == 0) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
webp->bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE);
if (!webp->bitmap) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
imagebuf = bitmap_get_buffer(webp->bitmap);
if (!imagebuf) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
unsigned int row_width = bitmap_get_rowstride(webp->bitmap);
 
res_p = WebPDecodeRGBAInto(data, size, imagebuf,
row_width * height, row_width);
if (res_p == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
 
c->width = width;
c->height = height;
 
/* set title */
title = messages_get_buff("WebPTitle",
nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
c->width, c->height);
if (title != NULL) {
content__set_title(c, title);
free(title);
}
 
bitmap_modified(webp->bitmap);
 
content_set_ready(c);
content_set_done(c);
 
content_set_status(c, "");
return true;
}
 
 
/**
* Destroy a CONTENT_WEBP and free all resources it owns.
*/
 
static void webp_destroy(struct content *c)
{
webp_content *webp = (webp_content *)c;
 
if (webp->bitmap != NULL)
bitmap_destroy(webp->bitmap);
}
 
 
/**
* Redraw a CONTENT_WEBP.
*/
 
static bool webp_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
webp_content *webp = (webp_content *)c;
bitmap_flags_t flags = BITMAPF_NONE;
 
if (data->repeat_x)
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
 
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
webp->bitmap, data->background_colour, flags);
}
 
 
static nserror webp_clone(const struct content *old, struct content **newc)
{
webp_content *webp;
nserror error;
 
webp = calloc(1, sizeof(webp_content));
if (webp == NULL)
return NSERROR_NOMEM;
 
error = content__clone(old, &webp->base);
if (error != NSERROR_OK) {
content_destroy(&webp->base);
return error;
}
 
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
if (webp_convert(&webp->base) == false) {
content_destroy(&webp->base);
return NSERROR_CLONE_FAILED;
}
}
 
*newc = (struct content *) webp;
 
return NSERROR_OK;
}
 
static void *webp_get_internal(const struct content *c, void *context)
{
webp_content *webp = (webp_content *)c;
 
return webp->bitmap;
}
 
static content_type webp_content_type(void)
{
return CONTENT_IMAGE;
}
 
static const content_handler webp_content_handler = {
.create = webp_create,
.data_complete = webp_convert,
.destroy = webp_destroy,
.redraw = webp_redraw,
.clone = webp_clone,
.get_internal = webp_get_internal,
.type = webp_content_type,
.no_share = false,
};
 
static const char *webp_types[] = {
"image/webp"
};
 
CONTENT_FACTORY_REGISTER_TYPES(webp, webp_types, webp_content_handler);
 
/contrib/network/netsurf/netsurf/image/webp.h
0,0 → 1,28
/*
* Copyright 2010 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/** \file
* Content for image/webp (libwebp interface).
*/
 
#ifndef _NETSURF_WEBP_H_
#define _NETSURF_WEBP_H_
 
nserror webp_init(void);
 
#endif