Merged revisions 4345-4346,4350-4351,4389,4391,4395,4401-4403,4423,4485-4486 via svnmerge from

svn://semichrome.net/branches/dynis/netsurf

........
  r4345 | dynis | 2008-06-15 18:37:23 -0500 (Sun, 15 Jun 2008) | 1 line
  
  Move NetSurf's gifread.h to libnsgif
........
  r4346 | dynis | 2008-06-15 18:38:38 -0500 (Sun, 15 Jun 2008) | 1 line
  
  Remove NetSurf's gifread.c (replaced by libnsgif)
........
  r4350 | dynis | 2008-06-15 18:57:17 -0500 (Sun, 15 Jun 2008) | 1 line
  
  Added references to libnsgif where necessary; corrected function calls where callbacks were implemented
........
  r4351 | dynis | 2008-06-15 19:00:33 -0500 (Sun, 15 Jun 2008) | 1 line
  
  Updated Makefile to compile with libnsgif
........
  r4389 | dynis | 2008-06-18 13:58:51 -0500 (Wed, 18 Jun 2008) | 1 line
  
  Altered bitmap callback table name for gif images to avoid ambiguity when bmp image library is created
........
  r4391 | dynis | 2008-06-18 14:08:39 -0500 (Wed, 18 Jun 2008) | 1 line
  
  Updated netsurf branch to use new bitmap callback table structure name that was altered in libnsgif
........
  r4395 | dynis | 2008-06-18 14:54:51 -0500 (Wed, 18 Jun 2008) | 1 line
  
  Corrected param comments for bitmap_set_suspendable()
........
  r4401 | dynis | 2008-06-18 18:39:50 -0500 (Wed, 18 Jun 2008) | 1 line
  
  Added references to libnsbmp where necessary; corrected function calls where callbacks were implemented
........
  r4402 | dynis | 2008-06-18 18:40:47 -0500 (Wed, 18 Jun 2008) | 1 line
  
  Updated Makefile to compile with libnsbmp
........
  r4403 | dynis | 2008-06-18 18:41:53 -0500 (Wed, 18 Jun 2008) | 1 line
  
  Remove NetSurf's bmpread.c and bmpread.h (replaced by libnsbmp)
........
  r4423 | dynis | 2008-06-22 14:21:30 -0500 (Sun, 22 Jun 2008) | 1 line
  
  Correct a silly mistake in nsbmp_bitmap_create
........
  r4485 | dynis | 2008-07-01 04:13:48 -0500 (Tue, 01 Jul 2008) | 1 line
  
  Integrated the latest versions of libnsgif and libnsbmp into NetSurf
........
  r4486 | dynis | 2008-07-01 05:27:10 -0500 (Tue, 01 Jul 2008) | 1 line
  
  Altered bitmap functions to receive void pointers for proper utilisation of libnsgif and libnsbmp
........

svn path=/trunk/netsurf/; revision=5071
This commit is contained in:
James Bursa 2008-08-12 03:49:34 +00:00
parent 4c8989a6db
commit 33107b160f
16 changed files with 306 additions and 2141 deletions

View File

@ -209,7 +209,7 @@ define pkg_config_find_and_add
$$(info M.CONFIG: auto-enabled $(3) ($(2)).)
endif
else
$$(error Unable to find library for: $(3) ($(2))
$$(error Unable to find library for: $(3) ($(2)))
endif
endif
else
@ -220,8 +220,8 @@ define pkg_config_find_and_add
endef
$(eval $(call feature_enabled,BMP,-DWITH_BMP,,BMP support))
$(eval $(call feature_enabled,GIF,-DWITH_GIF,,GIF support))
$(eval $(call feature_enabled,BMP,-DWITH_BMP,-lnsbmp,BMP support))
$(eval $(call feature_enabled,GIF,-DWITH_GIF,-lnsgif,GIF support))
$(eval $(call feature_enabled,JPEG,-DWITH_JPEG,-ljpeg,JPEG support))
$(eval $(call feature_enabled,MNG,-DWITH_MNG,-lmng,PNG support))
@ -295,9 +295,10 @@ ifeq ($(TARGET),gtk)
-DGTK_RESPATH=\"$(NETSURF_GTK_RESOURCES)\" \
$(WARNFLAGS) -I. -g $(OPT2FLAGS) \
$(shell $(PKG_CONFIG) --cflags libglade-2.0 gtk+-2.0) \
$(shell $(PKG_CONFIG) --cflags libnsgif libnsbmp) \
$(shell xml2-config --cflags)
GTKLDFLAGS := $(shell $(PKG_CONFIG) --cflags --libs libglade-2.0 gtk+-2.0 gthread-2.0 gmodule-2.0 lcms)
GTKLDFLAGS := $(shell $(PKG_CONFIG) --cflags --libs libglade-2.0 gtk+-2.0 gthread-2.0 gmodule-2.0 lcms libnsgif libnsbmp)
CFLAGS += $(GTKCFLAGS)
LDFLAGS += $(GTKLDFLAGS)
@ -414,6 +415,7 @@ ifeq ($(TARGET),debug)
-D_POSIX_C_SOURCE=200112L \
-D_NETBSD_SOURCE \
$(WARNFLAGS) -I. -g $(OPT0FLAGS) \
$(shell $(PKG_CONFIG) --cflags libnsgif libnsbmp) \
$(shell xml2-config --cflags)
LDFLAGS += $(shell $(PKG_CONFIG) --libs libxml-2.0 libcurl openssl)
@ -421,6 +423,7 @@ ifeq ($(TARGET),debug)
$(eval $(call pkg_config_find_and_add,ROSPRITE,librosprite,RISC OS sprite rendering))
$(eval $(call pkg_config_find_and_add,HUBBUB,libhubbub,Hubbub HTML parser))
$(eval $(call pkg_config_find_and_add,HUBBUB,libparserutils,Hubbub HTML parser))
LDFLAGS += $(shell $(PKG_CONFIG) --libs libnsgif libnsbmp)
endif
# ----------------------------------------------------------------------------

View File

@ -23,7 +23,7 @@ S_COMMON := $(addprefix content/,$(S_CONTENT)) \
$(addprefix desktop/,$(S_DESKTOP))
# S_IMAGE are sources related to image management
S_IMAGE := bmp.c bmpread.c gif.c gifread.c ico.c jpeg.c \
S_IMAGE := bmp.c gif.c ico.c jpeg.c \
mng.c nssprite.c svg.c rsvg.c
S_IMAGE := $(addprefix image/,$(S_IMAGE))

View File

@ -54,12 +54,16 @@ struct bitmap {
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
struct bitmap *bitmap_create(int width, int height, unsigned int state)
void *bitmap_create(int width, int height, unsigned int state)
{
struct bitmap *bmp = malloc(sizeof(struct bitmap));
bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
width, height);
// if ((state & BITMAP_OPAQUE) != 0)
// bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false,
// 8, width, height);
// else
bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true,
8, width, height);
/* fill the pixbuf in with 100% transparent black, as the memory
* won't have been cleared.
@ -76,8 +80,9 @@ struct bitmap *bitmap_create(int width, int height, unsigned int state)
* \param bitmap a bitmap, as returned by bitmap_create()
* \param opaque whether the bitmap should be plotted opaque
*/
void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
void bitmap_set_opaque(void *vbitmap, bool opaque)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
/* todo: set bitmap as opaque */
}
@ -89,8 +94,9 @@ void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
* \param bitmap a bitmap, as returned by bitmap_create()
* \return whether the bitmap is opaque
*/
bool bitmap_test_opaque(struct bitmap *bitmap)
bool bitmap_test_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
/* todo: test if bitmap as opaque */
return false;
@ -102,8 +108,9 @@ bool bitmap_test_opaque(struct bitmap *bitmap)
*
* \param bitmap a bitmap, as returned by bitmap_create()
*/
bool bitmap_get_opaque(struct bitmap *bitmap)
bool bitmap_get_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
/* todo: get whether bitmap is opaque */
return false;
@ -120,10 +127,11 @@ bool bitmap_get_opaque(struct bitmap *bitmap)
* of rows. The width of a row in bytes is given by bitmap_get_rowstride().
*/
char *bitmap_get_buffer(struct bitmap *bitmap)
unsigned char *bitmap_get_buffer(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
return (char *)gdk_pixbuf_get_pixels(bitmap->primary);
return (unsigned char *)gdk_pixbuf_get_pixels(bitmap->primary);
}
@ -134,13 +142,29 @@ char *bitmap_get_buffer(struct bitmap *bitmap)
* \return width of a pixel row in the bitmap
*/
size_t bitmap_get_rowstride(struct bitmap *bitmap)
size_t bitmap_get_rowstride(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
return gdk_pixbuf_get_rowstride(bitmap->primary);
}
/**
* Find the bytes per pixel of a bitmap
*
* \param bitmap a bitmap, as returned by bitmap_create()
* \return bytes per pixel
*/
size_t bitmap_get_bpp(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
return 4;
}
static void
gtk_bitmap_free_pretiles(struct bitmap *bitmap)
{
@ -157,8 +181,9 @@ gtk_bitmap_free_pretiles(struct bitmap *bitmap)
* \param bitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_destroy(struct bitmap *bitmap)
void bitmap_destroy(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
gtk_bitmap_free_pretiles(bitmap);
g_object_unref(bitmap->primary);
@ -175,8 +200,9 @@ void bitmap_destroy(struct bitmap *bitmap)
* \return true on success, false on error and error reported
*/
bool bitmap_save(struct bitmap *bitmap, const char *path, unsigned flags)
bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
GError *err = NULL;
gdk_pixbuf_save(bitmap->primary, path, "png", &err, NULL);
@ -194,7 +220,8 @@ bool bitmap_save(struct bitmap *bitmap, const char *path, unsigned flags)
*
* \param bitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_modified(struct bitmap *bitmap) {
void bitmap_modified(void *vbitmap) {
struct bitmap *bitmap = (struct bitmap *)vbitmap;
gtk_bitmap_free_pretiles(bitmap);
}
@ -202,20 +229,21 @@ void bitmap_modified(struct bitmap *bitmap) {
/**
* The bitmap image can be suspended.
*
* \param bitmap a bitmap, as returned by bitmap_create()
* \param private_word a private word to be returned later
* \param suspend the function to be called upon suspension
* \param resume the function to be called when resuming
* \param bitmap a bitmap, as returned by bitmap_create()
* \param private_word a private word to be returned later
* \param invalidate the function to be called upon suspension
*/
void bitmap_set_suspendable(struct bitmap *bitmap, void *private_word,
void (*invalidate)(struct bitmap *bitmap, void *private_word)) {
void bitmap_set_suspendable(void *vbitmap, void *private_word,
void (*invalidate)(void *vbitmap, void *private_word)) {
}
int bitmap_get_width(struct bitmap *bitmap){
int bitmap_get_width(void *vbitmap){
struct bitmap *bitmap = (struct bitmap *)vbitmap;
return gdk_pixbuf_get_width(bitmap->primary);
}
int bitmap_get_height(struct bitmap *bitmap){
int bitmap_get_height(void *vbitmap){
struct bitmap *bitmap = (struct bitmap *)vbitmap;
return gdk_pixbuf_get_height(bitmap->primary);
}
@ -259,9 +287,9 @@ gtk_bitmap_generate_pretile(GdkPixbuf *primary, int repeat_x, int repeat_y)
* \param bitmap a bitmap, as returned by bitmap_create()
*/
GdkPixbuf *
gtk_bitmap_get_primary(struct bitmap* bitmap)
gtk_bitmap_get_primary(struct bitmap *bitmap)
{
return bitmap->primary;
return bitmap->primary;
}
/**

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -19,8 +20,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <libnsgif.h>
#include "utils/log.h"
#include "image/gifread.h"
#include "gtk/gtk_throbber.h"
#include "gtk/gtk_bitmap.h"
@ -98,8 +99,13 @@ bool nsgtk_throbber_initialise_from_gif(const char *fn)
/* disect the GIF provided by filename in *fn into a series of
* GdkPixbuf for use later.
*/
struct gif_animation *gif; /**< structure for gifread.c */
struct nsgtk_throbber *throb; /**< structure we generate */
extern gif_bitmap_callback_vt gif_bitmap_callbacks; /**< external structure containing
* bitmap callback functions */
gif_animation gif;
struct nsgtk_throbber throb; /**< structure we generate */
int res;
size_t size;
unsigned char *data;
int i;
FILE *fh = fopen(fn, "rb");
@ -109,77 +115,88 @@ bool nsgtk_throbber_initialise_from_gif(const char *fn)
return false;
}
gif = (struct gif_animation *)malloc(sizeof(struct gif_animation));
throb = (struct nsgtk_throbber *)malloc(sizeof(struct nsgtk_throbber));
/* discover the size of the data file. */
fseek(fh, 0, SEEK_END);
gif->buffer_size = ftell(fh);
size = ftell(fh);
fseek(fh, 0, SEEK_SET);
/* allocate a block of sufficient size, and load the data in. */
gif->gif_data = (unsigned char *)malloc(gif->buffer_size);
fread(gif->gif_data, gif->buffer_size, 1, fh);
data = (unsigned char *)malloc(size);
fread(data, size, 1, fh);
fclose(fh);
/* set current position within GIF file to beginning, in order to
* signal to gifread that we're brand new.
*/
gif->buffer_position = 0;
/* create our gif animation */
gif_create(&gif, &gif_bitmap_callbacks);
/* initialise the gif_animation structure. */
switch (gif_initialise(gif))
{
case GIF_INSUFFICIENT_FRAME_DATA:
case GIF_FRAME_DATA_ERROR:
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
LOG(("GIF image '%s' appears invalid!", fn));
free(gif->gif_data);
free(gif);
free(throb);
do {
res = gif_initialise(&gif, size, data);
if (res != GIF_OK && res != GIF_WORKING) {
switch (res)
{
case GIF_INSUFFICIENT_FRAME_DATA:
case GIF_FRAME_DATA_ERROR:
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
LOG(("GIF image '%s' appears invalid!", fn));
break;
case GIF_INSUFFICIENT_MEMORY:
LOG(("Ran out of memory decoding GIF image '%s'!", fn));
break;
}
gif_finalise(&gif);
free(data);
free(&throb);
return false;
break;
case GIF_INSUFFICIENT_MEMORY:
LOG(("Ran out of memory decoding GIF image '%s'!", fn));
free(gif->gif_data);
free(gif);
free(throb);
return false;
break;
}
}
} while (res != GIF_OK);
throb->nframes = gif->frame_count;
throb.nframes = gif.frame_count;
if (throb->nframes < 2)
if (throb.nframes < 2)
{
/* we need at least two frames - one for idle, one for active */
LOG(("Insufficent number of frames in throbber image '%s'!",
fn));
LOG(("(GIF contains %d frames, where 2 is a minimum.)",
throb->nframes));
free(gif->gif_data);
free(gif);
free(throb);
throb.nframes));
gif_finalise(&gif);
free(data);
free(&throb);
return false;
}
throb->framedata = (GdkPixbuf **)malloc(sizeof(GdkPixbuf *)
* throb->nframes);
throb.framedata = (GdkPixbuf **)malloc(sizeof(GdkPixbuf *) * throb.nframes);
/* decode each frame in turn, extracting the struct bitmap * for each,
* and put that in our array of frames.
*/
for (i = 0; i < throb->nframes; i++)
for (i = 0; i < throb.nframes; i++)
{
gif_decode_frame(gif, i);
throb->framedata[i] = gdk_pixbuf_copy(
gtk_bitmap_get_primary(gif->frame_image));
res = gif_decode_frame(&gif, i);
if (res != GIF_OK) {
switch (res)
{
case GIF_INSUFFICIENT_FRAME_DATA:
case GIF_FRAME_DATA_ERROR:
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
LOG(("GIF image '%s' appears invalid!", fn));
break;
case GIF_INSUFFICIENT_MEMORY:
LOG(("Ran out of memory decoding GIF image '%s'!", fn));
break;
}
gif_finalise(&gif);
free(data);
free(&throb);
return false;
}
throb.framedata[i] = gdk_pixbuf_copy(gtk_bitmap_get_primary(gif.frame_image));
}
gif_finalise(gif);
free(gif->gif_data);
free(gif);
gif_finalise(&gif);
free(data);
/* debug code: save out each frame as a PNG to make sure decoding is
* working correctly.
@ -191,7 +208,7 @@ bool nsgtk_throbber_initialise_from_gif(const char *fn)
}
*/
nsgtk_throbber = throb;
nsgtk_throbber = &throb;
return true;
}

View File

@ -46,19 +46,20 @@ struct content;
/** An opaque image. */
struct bitmap;
struct bitmap *bitmap_create(int width, int height, unsigned int state);
void bitmap_set_opaque(struct bitmap *bitmap, bool opaque);
bool bitmap_test_opaque(struct bitmap *bitmap);
bool bitmap_get_opaque(struct bitmap *bitmap);
char *bitmap_get_buffer(struct bitmap *bitmap);
size_t bitmap_get_rowstride(struct bitmap *bitmap);
void bitmap_destroy(struct bitmap *bitmap);
bool bitmap_save(struct bitmap *bitmap, const char *path, unsigned flags);
void bitmap_modified(struct bitmap *bitmap);
void bitmap_set_suspendable(struct bitmap *bitmap, void *private_word,
void (*invalidate)(struct bitmap *bitmap, void *private_word));
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);
void bitmap_set_suspendable(void *bitmap, void *private_word,
void (*invalidate)(void *bitmap, void *private_word));
int bitmap_get_width(struct bitmap *bitmap);
int bitmap_get_height(struct bitmap *bitmap);
int bitmap_get_width(void *bitmap);
int bitmap_get_height(void *bitmap);
#endif

View File

@ -1,5 +1,6 @@
/*
* 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/
*
@ -23,16 +24,27 @@
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/bmp.h"
#include "image/bmpread.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
/* 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_set_suspendable = bitmap_set_suspendable,
.bitmap_get_buffer = bitmap_get_buffer,
.bitmap_get_bpp = bitmap_get_bpp
};
bool nsbmp_create(struct content *c, const char *params[]) {
union content_msg_data msg_data;
@ -42,22 +54,22 @@ bool nsbmp_create(struct content *c, const char *params[]) {
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
bmp_create(c->data.bmp.bmp, &bmp_bitmap_callbacks);
return true;
}
bool nsbmp_convert(struct content *c, int iwidth, int iheight) {
bmp_result res;
struct bmp_image *bmp;
bmp_image *bmp;
union content_msg_data msg_data;
uint32_t swidth;
/* set our source data */
/* set the bmp data */
bmp = c->data.bmp.bmp;
bmp->bmp_data = (unsigned char *) c->source_data;
bmp->buffer_size = c->source_size;
/* analyse the BMP */
res = bmp_analyse(bmp);
res = bmp_analyse(bmp, c->source_size, (unsigned char *)c->source_data);
switch (res) {
case BMP_OK:
break;
@ -76,11 +88,13 @@ bool nsbmp_convert(struct content *c, int iwidth, int iheight) {
*/
c->width = bmp->width;
c->height = bmp->height;
LOG(("BMP width %u height %u\n\n", c->width, c->height));
c->title = malloc(100);
if (c->title)
snprintf(c->title, 100, messages_get("BMPTitle"), c->width,
c->height, c->source_size);
c->size += (bmp->width * bmp->height * 4) + 16 + 44 + 100;
swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
c->size += (swidth * bmp->height) + 16 + 44 + 100;
/* exit as a success */
c->bitmap = bmp->bitmap;
@ -97,7 +111,8 @@ bool nsbmp_redraw(struct content *c, int x, int y,
float scale, unsigned long background_colour) {
if (!c->data.bmp.bmp->decoded)
bmp_decode(c->data.bmp.bmp);
if (bmp_decode(c->data.bmp.bmp) != BMP_OK)
return false;
c->bitmap = c->data.bmp.bmp->bitmap;
return plot.bitmap(x, y, width, height, c->bitmap, background_colour, c);
}
@ -110,7 +125,8 @@ bool nsbmp_redraw_tiled(struct content *c, int x, int y,
bool repeat_x, bool repeat_y) {
if (!c->data.bmp.bmp->decoded)
bmp_decode(c->data.bmp.bmp);
if (bmp_decode(c->data.bmp.bmp) != BMP_OK)
return false;
c->bitmap = c->data.bmp.bmp->bitmap;
return plot.bitmap_tile(x, y, width, height, c->bitmap,
background_colour, repeat_x, repeat_y, c);
@ -124,4 +140,24 @@ void nsbmp_destroy(struct content *c)
free(c->title);
}
/**
* 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
*/
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);
}
#endif

View File

@ -1,5 +1,6 @@
/*
* 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/
*
@ -23,12 +24,14 @@
#ifdef WITH_BMP
#include <stdbool.h>
#include "image/bmpread.h"
#include <libnsbmp.h>
#include "image/bitmap.h"
struct content;
struct bitmap;
struct content_bmp_data {
struct bmp_image *bmp; /** BMP image data */
bmp_image *bmp; /** BMP image data */
};
bool nsbmp_create(struct content *c, const char *params[]);
@ -43,6 +46,7 @@ bool nsbmp_redraw_tiled(struct content *c, int x, int y,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, unsigned long background_colour,
bool repeat_x, bool repeat_y);
void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state);
#endif /* WITH_BMP */

View File

@ -1,816 +0,0 @@
/*
* 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/>.
*/
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "image/bmpread.h"
#include "image/bitmap.h"
#include "utils/log.h"
#include "utils/config.h"
#define READ_SHORT(a, o) (a[o]|(a[o+1]<<8))
#define READ_INT(a, o) (a[o]|(a[o+1]<<8)|(a[o+2]<<16)|(a[o+3]<<24))
bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data);
bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes);
bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes);
bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes);
bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes);
bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size);
void bmp_invalidate(struct bitmap *bitmap, void *private_word);
/**
* Analyse a BMP prior to decoding.
*
* This function will scan the data provided and perform simple checks to
* ensure the data is a valid BMP.
*
* This function must be called before bmp_decode() and sets up all the
* relevant values in the bmp structure.
*
* \param bmp the BMP image to analyse
* \return BMP_OK on success
*/
bmp_result bmp_analyse(struct bmp_image *bmp) {
char *data = (char *) bmp->bmp_data;
/* ensure we aren't already initialised */
if (bmp->bitmap)
return BMP_OK;
/* standard 14-byte BMP file header is:
*
* +0 SHORT 'BM'
* +2 INT size of file (in bytes)
* +6 SHORT reserved field (1)
* +8 SHORT reserved field (2)
* +10 INT starting position of image data (in bytes)
*/
if (bmp->buffer_size < 14)
return BMP_INSUFFICIENT_DATA;
if ((data[0] != 'B') || (data[1] != 'M'))
return BMP_DATA_ERROR;
bmp->bitmap_offset = READ_INT(data, 10);
/* decode the BMP header */
return bmp_analyse_header(bmp, data + 14);
}
/**
* Analyse an ICO prior to decoding.
*
* This function will scan the data provided and perform simple checks to
* ensure the data is a valid ICO.
*
* This function must be called before ico_find().
*
* \param ico the ICO image to analyse
* \return BMP_OK on success
*/
bmp_result ico_analyse(struct ico_collection *ico) {
char *data = (char *) ico->ico_data;
unsigned int count, i;
bmp_result result;
struct ico_image *image;
int area, max_area = 0;
/* ensure we aren't already initialised */
if (ico->first)
return BMP_OK;
/* standard 6-byte ICO file header is:
*
* +0 INT 0x00010000
* +4 SHORT number of BMPs to follow
*/
if (ico->buffer_size < 6)
return BMP_INSUFFICIENT_DATA;
if (READ_INT(data, 0) != 0x00010000)
return BMP_DATA_ERROR;
count = READ_SHORT(data, 4);
if (count == 0)
return BMP_DATA_ERROR;
data += 6;
/* decode the BMP files */
if (ico->buffer_size < 6 + (16 * count))
return BMP_INSUFFICIENT_DATA;
for (i = 0; i < count; i++) {
image = calloc(1, sizeof(struct ico_image));
if (!image)
return BMP_INSUFFICIENT_MEMORY;
image->next = ico->first;
ico->first = image;
image->bmp.width = data[0];
image->bmp.height = data[1];
image->bmp.buffer_size = READ_INT(data, 8) + 40;
image->bmp.bmp_data = ico->ico_data + READ_INT(data, 12);
image->bmp.ico = true;
data += 16;
result = bmp_analyse_header(&image->bmp,
(char *) image->bmp.bmp_data);
if (result != BMP_OK)
return result;
area = image->bmp.width * image->bmp.height;
if (area > max_area) {
ico->width = image->bmp.width;
ico->height = image->bmp.height;
max_area = area;
}
}
return BMP_OK;
}
bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
unsigned int header_size;
unsigned int i;
int width, height, j;
int palette_size;
unsigned int flags;
/* a variety of different bitmap headers can follow, depending
* on the BMP variant. A full description of the various headers
* can be found at http://www.fileformat.info/format/bmp/
*/
header_size = READ_INT(data, 0);
if (bmp->buffer_size < (14 + header_size))
return BMP_INSUFFICIENT_DATA;
if (header_size == 12) {
/* the following header is for os/2 and windows 2.x and consists of:
*
* +0 INT size of this header (in bytes)
* +4 SHORT image width (in pixels)
* +6 SHORT image height (in pixels)
* +8 SHORT number of color planes (always 1)
* +10 SHORT number of bits per pixel
*/
width = READ_SHORT(data, 4);
height = READ_SHORT(data, 6);
if (width < 0)
return BMP_DATA_ERROR;
if (height < 0) {
bmp->reversed = true;
height = -height;
}
bmp->width = width;
bmp->height = height;
if (READ_SHORT(data, 8) != 1)
return BMP_DATA_ERROR;
bmp->bpp = READ_SHORT(data, 10);
bmp->colours = (1 << bmp->bpp);
palette_size = 3;
} else if (header_size < 40) {
return BMP_DATA_ERROR;
} else {
/* the following header is for windows 3.x and onwards. it is a
* minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes.
*
* +0 INT size of this header (in bytes)
* +4 INT image width (in pixels)
* +8 INT image height (in pixels)
* +12 SHORT number of color planes (always 1)
* +14 SHORT number of bits per pixel
* +16 INT compression methods used
* +20 INT size of bitmap (in bytes)
* +24 INT horizontal resolution (in pixels per meter)
* +28 INT vertical resolution (in pixels per meter)
* +32 INT number of colors in the image
* +36 INT number of important colors
* +40 INT mask identifying bits of red component
* +44 INT mask identifying bits of green component
* +48 INT mask identifying bits of blue component
* +52 INT mask identifying bits of alpha component
* +56 INT color space type
* +60 INT x coordinate of red endpoint
* +64 INT y coordinate of red endpoint
* +68 INT z coordinate of red endpoint
* +72 INT x coordinate of green endpoint
* +76 INT y coordinate of green endpoint
* +80 INT z coordinate of green endpoint
* +84 INT x coordinate of blue endpoint
* +88 INT y coordinate of blue endpoint
* +92 INT z coordinate of blue endpoint
* +96 INT gamma red coordinate scale value
* +100 INT gamma green coordinate scale value
* +104 INT gamma blue coordinate scale value
*/
if (!bmp->ico) {
width = READ_INT(data, 4);
height = READ_INT(data, 8);
if (width < 0)
return BMP_DATA_ERROR;
if (height < 0) {
bmp->reversed = true;
height = -height;
}
bmp->width = width;
bmp->height = height;
}
if (READ_SHORT(data, 12) != 1)
return BMP_DATA_ERROR;
bmp->bpp = READ_SHORT(data, 14);
if (bmp->bpp == 0)
bmp->bpp = 8;
bmp->encoding = READ_INT(data, 16);
if (bmp->encoding > BMP_ENCODING_BITFIELDS)
return BMP_DATA_ERROR;
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
if ((bmp->bpp != 16) && (bmp->bpp != 32))
return BMP_DATA_ERROR;
if (header_size == 40) {
header_size += 12;
if (bmp->buffer_size < (14 + header_size))
return BMP_INSUFFICIENT_DATA;
for (i = 0; i < 3; i++)
bmp->mask[i] = READ_INT(data, 40 + (i << 2));
} else {
for (i = 0; i < 4; i++)
bmp->mask[i] = READ_INT(data, 40 + (i << 2));
}
for (i = 0; i < 4; i++) {
if (bmp->mask[i] == 0)
break;
for (j = 31; j > 0; j--)
if (bmp->mask[i] & (1 << j)) {
if ((j - 7) > 0)
bmp->mask[i] &= 0xff << (j - 7);
else
bmp->mask[i] &= 0xff >> (-(j - 7));
bmp->shift[i] = (i << 3) - (j - 7);
break;
}
}
}
bmp->colours = READ_INT(data, 32);
if (bmp->colours == 0)
bmp->colours = (1 << bmp->bpp);
palette_size = 4;
}
data += header_size;
/* we only have a palette for <16bpp */
if (bmp->bpp < 16) {
/* we now have a series of palette entries of the format:
*
* +0 BYTE blue
* +1 BYTE green
* +2 BYTE red
*
* if the palette is from an OS/2 or Win2.x file then the entries
* are padded with an extra byte.
*/
if (bmp->buffer_size < (14 + header_size + (4 * bmp->colours)))
return BMP_INSUFFICIENT_DATA;
bmp->colour_table = (unsigned int *)
malloc(bmp->colours * sizeof(int));
if (!bmp->colour_table)
return BMP_INSUFFICIENT_MEMORY;
for (i = 0; i < bmp->colours; i++) {
bmp->colour_table[i] = data[2] | (data[1] << 8) |
(data[0] << 16);
data += palette_size;
}
}
/* create our bitmap */
flags = BITMAP_NEW | BITMAP_CLEAR_MEMORY;
if ((!bmp->ico) && (bmp->mask[3] == 0))
flags |= BITMAP_OPAQUE;
bmp->bitmap = bitmap_create(bmp->width, bmp->height, flags);
if (!bmp->bitmap) {
if (bmp->colour_table)
free(bmp->colour_table);
bmp->colour_table = NULL;
return BMP_INSUFFICIENT_MEMORY;
}
bmp->bitmap_offset = (intptr_t)data - (intptr_t)bmp->bmp_data;
bitmap_set_suspendable(bmp->bitmap, bmp, bmp_invalidate);
return BMP_OK;
}
/*
* Finds the closest BMP within an ICO collection
*
* This function finds the BMP with dimensions as close to a specified set
* as possible from the images in the collection.
*
* \param ico the ICO collection to examine
* \param width the preferred width
* \param height the preferred height
*/
struct bmp_image *ico_find(struct ico_collection *ico, int width, int height) {
struct bmp_image *bmp = NULL;
struct ico_image *image;
int x, y, cur, distance = (1 << 24);
for (image = ico->first; image; image = image->next) {
if (((int)image->bmp.width == width) && ((int)image->bmp.height == height))
return &image->bmp;
x = image->bmp.width - width;
y = image->bmp.height - height;
cur = (x * x) + (y * y);
if (cur < distance) {
distance = cur;
bmp = &image->bmp;
}
}
return bmp;
}
/**
* Invalidates a BMP
*
* This function sets the BMP into a state such that the bitmap image data
* can be released from memory.
*
* \param bmp the BMP image to invalidate
*/
void bmp_invalidate(struct bitmap *bitmap, void *private_word) {
struct bmp_image *bmp = (struct bmp_image *)private_word;
bmp->decoded = false;
}
/**
* Decode a BMP
*
* This function decodes the BMP data such that bmp->bitmap is a valid
* image. The state of bmp->decoded is set to TRUE on exit such that it
* can easily be identified which BMPs are in a fully decoded state.
*
* \param bmp the BMP image to decode
* \return BMP_OK on success
*/
bmp_result bmp_decode(struct bmp_image *bmp) {
char *data;
int bytes;
bmp_result result = BMP_OK;
assert(bmp->bitmap);
data = (char *) bmp->bmp_data + bmp->bitmap_offset;
bytes = bmp->buffer_size - bmp->bitmap_offset;
switch (bmp->encoding) {
case BMP_ENCODING_RGB:
if (bmp->bpp >= 24)
result = bmp_decode_rgb24(bmp, &data, bytes);
else if (bmp->bpp > 8)
result = bmp_decode_rgb16(bmp, &data, bytes);
else
result = bmp_decode_rgb(bmp, &data, bytes);
break;
case BMP_ENCODING_RLE8:
result = bmp_decode_rle(bmp, data, bytes, 8);
break;
case BMP_ENCODING_RLE4:
result = bmp_decode_rle(bmp, data, bytes, 4);
break;
case BMP_ENCODING_BITFIELDS:
if (bmp->bpp == 32)
result = bmp_decode_rgb24(bmp, &data, bytes);
else if (bmp->bpp == 16)
result = bmp_decode_rgb16(bmp, &data, bytes);
else
return BMP_DATA_ERROR;
}
if ((!bmp->ico) || (result != BMP_OK))
return result;
bytes = (intptr_t)bmp->bmp_data + bmp->buffer_size - (intptr_t)data;
return bmp_decode_mask(bmp, data, bytes);
}
/**
* Decode BMP data stored in 24bpp colour.
*
* \param bmp the BMP image to decode
* \param start the data to decode, updated to last byte read on success
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes) {
char *top, *bottom, *end, *data;
unsigned int *scanline;
unsigned int x, y, swidth, skip;
intptr_t addr;
unsigned int i, word;
data = *start;
swidth = bitmap_get_rowstride(bmp->bitmap);
top = bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
bottom = top + swidth * (bmp->height - 1);
end = data + bytes;
addr = ((intptr_t)data) & 3;
skip = bmp->bpp >> 3;
bmp->decoded = true;
for (y = 0; y < bmp->height; y++) {
while (addr != (((intptr_t)data) & 3))
data++;
if ((data + (skip * bmp->width)) > end)
return BMP_INSUFFICIENT_DATA;
if (bmp->reversed)
scanline = (unsigned int *)(top + (y * swidth));
else
scanline = (unsigned int *)(bottom - (y * swidth));
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
for (x = 0; x < bmp->width; x++) {
word = data[0] | (data[1] << 8) | (data[2] << 16) |
(data[3] << 24);
scanline[x] = (0xff << 24);
for (i = 0; i < 4; i++)
if (bmp->shift[i] > 0)
scanline[x] ^= ((word & bmp->mask[i]) <<
bmp->shift[i]);
else
scanline[x] ^= ((word & bmp->mask[i]) >>
(-bmp->shift[i]));
data += 4;
}
} else {
for (x = 0; x < bmp->width; x++) {
scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16) |
(data[3] << 24);
data += skip;
}
}
}
*start = data;
return BMP_OK;
}
/**
* Decode BMP data stored in 16bpp colour.
*
* \param bmp the BMP image to decode
* \param start the data to decode, updated to last byte read on success
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes) {
char *top, *bottom, *end, *data;
unsigned int *scanline;
unsigned int x, y, swidth;
intptr_t addr;
unsigned int word, i;
data = *start;
swidth = bitmap_get_rowstride(bmp->bitmap);
top = bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
bottom = top + swidth * (bmp->height - 1);
end = data + bytes;
addr = ((intptr_t)data) & 3;
bmp->decoded = true;
for (y = 0; y < bmp->height; y++) {
if (addr != (((intptr_t)data) & 3))
data += 2;
if ((data + (2 * bmp->width)) > end)
return BMP_INSUFFICIENT_DATA;
if (bmp->reversed)
scanline = (unsigned int *)(top + (y * swidth));
else
scanline = (unsigned int *)(bottom - (y * swidth));
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
for (x = 0; x < bmp->width; x++) {
word = data[0] | (data[1] << 8);
scanline[x] = (0xff << 24);
for (i = 0; i < 4; i++)
if (bmp->shift[i] > 0)
scanline[x] ^= ((word & bmp->mask[i]) <<
bmp->shift[i]);
else
scanline[x] ^= ((word & bmp->mask[i]) >>
(-bmp->shift[i]));
data += 2;
}
} else {
for (x = 0; x < bmp->width; x++) {
word = data[0] | (data[1] << 8);
scanline[x] = ((word & (31 << 0)) << 19) |
((word & (31 << 5)) << 6) |
((word & (31 << 10)) >> 7);
data += 2;
}
}
}
*start = data;
return BMP_OK;
}
/**
* Decode BMP data stored with a palette and in 8bpp colour or less.
*
* \param bmp the BMP image to decode
* \param start the data to decode, updated to last byte read on success
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes) {
char *top, *bottom, *end, *data;
unsigned int *scanline;
intptr_t addr;
unsigned int x, y, swidth;
int i;
int bit_shifts[8];
int ppb = 8 / bmp->bpp;
int bit_mask = (1 << bmp->bpp) - 1;
int cur_byte = 0, bit;
for (i = 0; i < ppb; i++)
bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
data = *start;
swidth = bitmap_get_rowstride(bmp->bitmap);
top = bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
bottom = top + swidth * (bmp->height - 1);
end = data + bytes;
addr = ((intptr_t)data) & 3;
bmp->decoded = true;
for (y = 0; y < bmp->height; y++) {
while (addr != (((intptr_t)data) & 3))
data++;
bit = 32;
if ((data + (bmp->width / ppb)) > end)
return BMP_INSUFFICIENT_DATA;
if (bmp->reversed)
scanline = (unsigned int *)(top + (y * swidth));
else
scanline = (unsigned int *)(bottom - (y * swidth));
for (x = 0; x < bmp->width; x++) {
if (bit >= ppb) {
bit = 0;
cur_byte = *data++;
}
scanline[x] = bmp->colour_table[(cur_byte >>
bit_shifts[bit++]) & bit_mask];
}
}
*start = data;
return BMP_OK;
}
/**
* Decode a 1bpp mask for an ICO
*
* \param bmp the BMP image to decode
* \param data the data to decode
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes) {
char *top, *bottom, *end;
unsigned int *scanline;
intptr_t addr;
unsigned int x, y, swidth;
int cur_byte = 0;
swidth = bitmap_get_rowstride(bmp->bitmap);
top = bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
bottom = top + swidth * (bmp->height - 1);
end = data + bytes;
addr = ((intptr_t)data) & 3;
for (y = 0; y < bmp->height; y++) {
while (addr != (((intptr_t)data) & 3))
data++;
if ((data + (bmp->width >> 3)) > end)
return BMP_INSUFFICIENT_DATA;
scanline = (unsigned int *)(bottom - (y * swidth));
for (x = 0; x < bmp->width; x++) {
if ((x & 7) == 0)
cur_byte = *data++;
if ((cur_byte & 128) == 0)
scanline[x] |= (0xff << 24);
cur_byte = cur_byte << 1;
}
}
return BMP_OK;
}
/**
* Decode BMP data stored encoded in either RLE4 or RLE8.
*
* \param bmp the BMP image to decode
* \param data the data to decode
* \param bytes the number of bytes of data available
* \param size the size of the RLE tokens (4 or 8)
* \return BMP_OK on success
*/
bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size) {
char *top, *bottom, *end;
unsigned int *scanline;
unsigned int swidth;
int i, length, pixels_left;
unsigned int x = 0, y = 0, last_y = 0;
unsigned int pixel = 0, pixel2;
if (bmp->ico)
return BMP_DATA_ERROR;
swidth = bitmap_get_rowstride(bmp->bitmap);
top = bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
bottom = top + swidth * (bmp->height - 1);
end = data + bytes;
bmp->decoded = true;
do {
if (data + 2 > end)
return BMP_INSUFFICIENT_DATA;
length = *data++;
if (length == 0) {
length = *data++;
if (length == 0) {
/* 00 - 00 means end of scanline */
x = 0;
if (last_y == y) {
if (++y > bmp->height)
return BMP_DATA_ERROR;
}
last_y = y;
} else if (length == 1) {
/* 00 - 01 means end of RLE data */
return BMP_OK;
} else if (length == 2) {
/* 00 - 02 - XX - YY means move cursor */
if (data + 2 > end)
return BMP_INSUFFICIENT_DATA;
x += *data++;
if (x >= bmp->width)
return BMP_DATA_ERROR;
y += *data++;
if (y >= bmp->height)
return BMP_DATA_ERROR;
} else {
/* 00 - NN means escape NN pixels */
if (bmp->reversed) {
pixels_left = (y + 1) * bmp->width - x;
scanline = (unsigned int *)(top + (y * swidth));
} else {
pixels_left = (bmp->height - y + 1) * bmp->width - x;
scanline = (unsigned int *)(bottom - (y * swidth));
}
if (length > pixels_left)
length = pixels_left;
if (data + length > end)
return BMP_INSUFFICIENT_DATA;
/* the following code could be easily optimised by simply
* checking the bounds on entry and using some simply copying
* routines if so */
if (size == 8) {
for (i = 0; i < length; i++) {
if (x >= bmp->width) {
x = 0;
if (++y > bmp->height)
return BMP_DATA_ERROR;
scanline -= bmp->width;
}
scanline[x++] = bmp->colour_table[(int)*data++];
}
} else {
for (i = 0; i < length; i++) {
if (x >= bmp->width) {
x = 0;
if (++y > bmp->height)
return BMP_DATA_ERROR;
scanline -= bmp->width;
}
if ((i & 1) == 0) {
pixel = *data++;
scanline[x++] = bmp->colour_table
[pixel >> 4];
} else {
scanline[x++] = bmp->colour_table
[pixel & 0xf];
}
}
length = (length + 1) >> 1;
}
if ((length & 1) && (*data++ != 0x00))
return BMP_DATA_ERROR;
}
} else {
/* NN means perform RLE for NN pixels */
if (bmp->reversed) {
pixels_left = (y + 1) * bmp->width - x;
scanline = (unsigned int *)(top + (y * swidth));
} else {
pixels_left = (bmp->height - y + 1) * bmp->width - x;
scanline = (unsigned int *)(bottom - (y * swidth));
}
if (length > pixels_left)
length = pixels_left;
/* the following code could be easily optimised by simply
* checking the bounds on entry and using some simply copying
* routines if so */
if (size == 8) {
pixel = bmp->colour_table[(int)*data++];
for (i = 0; i < length; i++) {
if (x >= bmp->width) {
x = 0;
if (++y > bmp->height)
return BMP_DATA_ERROR;
scanline -= bmp->width;
}
scanline[x++] = pixel;
}
} else {
pixel2 = *data++;
pixel = bmp->colour_table[pixel2 >> 4];
pixel2 = bmp->colour_table[pixel2 & 0xf];
for (i = 0; i < length; i++) {
if (x >= bmp->width) {
x = 0;
if (++y > bmp->height)
return BMP_DATA_ERROR;
scanline -= bmp->width;
}
if ((i & 1) == 0)
scanline[x++] = pixel;
else
scanline[x++] = pixel2;
}
}
}
} while (data < end);
return BMP_OK;
}
/**
* Finalise a BMP prior to destruction.
*
* \param bmp the BMP image to finalise
*/
void bmp_finalise(struct bmp_image *bmp) {
if (bmp->bitmap)
bitmap_destroy(bmp->bitmap);
bmp->bitmap = NULL;
if (bmp->colour_table)
free(bmp->colour_table);
bmp->colour_table = NULL;
}
/**
* Finalise an ICO prior to destruction.
*
* \param ico the ICO image to finalise
*/
void ico_finalise(struct ico_collection *ico) {
struct ico_image *image;
for (image = ico->first; image; image = image->next)
bmp_finalise(&image->bmp);
while (ico->first) {
image = ico->first;
ico->first = image->next;
free(image);
}
}

View File

@ -1,84 +0,0 @@
/*
* 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
* BMP file decoding (interface).
*/
#ifndef _NETSURF_IMAGE_BMPREAD_H_
#define _NETSURF_IMAGE_BMPREAD_H_
#include <stdbool.h>
#include "image/bitmap.h"
/* error return values */
typedef enum {
BMP_OK = 0,
BMP_INSUFFICIENT_MEMORY = 1,
BMP_INSUFFICIENT_DATA = 2,
BMP_DATA_ERROR = 3
} bmp_result;
/* encoding types */
typedef enum {
BMP_ENCODING_RGB = 0,
BMP_ENCODING_RLE8 = 1,
BMP_ENCODING_RLE4 = 2,
BMP_ENCODING_BITFIELDS = 3
} bmp_encoding;
struct bmp_image {
unsigned char *bmp_data; /** pointer to BMP data */
unsigned int buffer_size; /** total number of bytes of BMP data available */
unsigned int width; /** width of BMP (valid after _analyse) */
unsigned int height; /** heigth of BMP (valid after _analyse) */
bmp_encoding encoding; /** pixel encoding type */
unsigned int bitmap_offset; /** offset of bitmap data */
unsigned int bpp; /** bits per pixel */
unsigned int colours; /** number of colours */
unsigned int *colour_table; /** colour table */
bool reversed; /** scanlines are top to bottom */
bool decoded; /** whether the image has been decoded */
bool ico; /** image is part of an ICO, mask follows */
unsigned int mask[4]; /** four bitwise mask */
int shift[4]; /** four bitwise shifts */
struct bitmap *bitmap; /** decoded image */
};
struct ico_image {
struct bmp_image bmp;
struct ico_image *next;
};
struct ico_collection {
unsigned char *ico_data; /** pointer to ICO data */
unsigned int buffer_size; /** total number of bytes of ICO data available */
unsigned int width; /** width of largest BMP */
unsigned int height; /** heigth of largest BMP */
struct ico_image *first;
};
bmp_result bmp_analyse(struct bmp_image *bmp);
bmp_result bmp_decode(struct bmp_image *bmp);
void bmp_finalise(struct bmp_image *bmp);
bmp_result ico_analyse(struct ico_collection *ico);
struct bmp_image *ico_find(struct ico_collection *ico, int width, int height);
void ico_finalise(struct ico_collection *ico);
#endif

View File

@ -1,6 +1,7 @@
/*
* 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/
*
@ -24,13 +25,14 @@
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnsgif.h>
#include "utils/config.h"
#include "content/content.h"
#include "desktop/browser.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/gif.h"
#include "image/gifread.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
@ -46,9 +48,21 @@
[rjw] - Sun 4th April 2004
*/
static void nsgif_invalidate(struct bitmap *bitmap, void *private_word);
static void nsgif_invalidate(void *bitmap, void *private_word);
static void nsgif_animate(void *p);
static void nsgif_get_frame(struct content *c);
static gif_result nsgif_get_frame(struct content *c);
/* The Bitmap callbacks function table;
necessary for interaction with nsgiflib.
*/
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
};
bool nsgif_create(struct content *c, const char *params[]) {
@ -61,6 +75,7 @@ bool nsgif_create(struct content *c, const char *params[]) {
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
gif_create(c->data.gif.gif, &gif_bitmap_callbacks);
return true;
}
@ -70,27 +85,31 @@ bool nsgif_convert(struct content *c, int iwidth, int iheight) {
struct gif_animation *gif;
union content_msg_data msg_data;
/* Create our animation
/* Get the animation
*/
gif = c->data.gif.gif;
gif->gif_data = (unsigned char *) c->source_data;
gif->buffer_size = c->source_size;
gif->buffer_position = 0;
/* Initialise the GIF
*/
res = gif_initialise(gif);
switch (res) {
case GIF_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
do {
res = gif_initialise(gif, c->source_size, (unsigned char *)c->source_data);
if (res != GIF_OK && res != GIF_WORKING) {
switch (res)
{
case GIF_INSUFFICIENT_FRAME_DATA:
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;
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
msg_data.error = messages_get("BadGIF");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
}
} while (res != GIF_OK);
/* Abort on bad GIFs
*/
@ -127,7 +146,7 @@ bool nsgif_convert(struct content *c, int iwidth, int iheight) {
return true;
}
void nsgif_invalidate(struct bitmap *bitmap, void *private_word) {
void nsgif_invalidate(void *bitmap, void *private_word) {
struct gif_animation *gif = (struct gif_animation *)private_word;
gif->decoded_frame = -1;
@ -139,7 +158,8 @@ bool nsgif_redraw(struct content *c, int x, int y,
float scale, unsigned long background_colour) {
if (c->data.gif.current_frame != c->data.gif.gif->decoded_frame)
nsgif_get_frame(c);
if (nsgif_get_frame(c) != GIF_OK)
return false;
c->bitmap = c->data.gif.gif->frame_image;
return plot.bitmap(x, y, width, height, c->bitmap, background_colour, c);
}
@ -151,8 +171,11 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
float scale, unsigned long background_colour,
bool repeat_x, bool repeat_y) {
gif_result res;
if (c->data.gif.current_frame != c->data.gif.gif->decoded_frame)
nsgif_get_frame(c);
if (nsgif_get_frame(c) != GIF_OK)
return false;
c->bitmap = c->data.gif.gif->frame_image;
return plot.bitmap_tile(x, y, width, height, c->bitmap, background_colour,
repeat_x, repeat_y, c);
@ -161,6 +184,7 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
void nsgif_destroy(struct content *c)
{
/* Free all the associated memory buffers
*/
schedule_remove(nsgif_animate, c);
@ -175,7 +199,7 @@ void nsgif_destroy(struct content *c)
*
* \param c the content to update
*/
void nsgif_get_frame(struct content *c) {
gif_result nsgif_get_frame(struct content *c) {
int previous_frame, current_frame, frame;
current_frame = c->data.gif.current_frame;
@ -186,7 +210,7 @@ void nsgif_get_frame(struct content *c) {
else
previous_frame = c->data.gif.gif->decoded_frame + 1;
for (frame = previous_frame; frame <= current_frame; frame++)
gif_decode_frame(c->data.gif.gif, frame);
return gif_decode_frame(c->data.gif.gif, frame);
}
@ -229,7 +253,7 @@ void nsgif_animate(void *p)
schedule(delay, nsgif_animate, c);
}
if (!option_animate_images)
if ((!option_animate_images) || (!gif->frames[c->data.gif.current_frame].display))
return;
/* area within gif to redraw */
@ -286,4 +310,16 @@ void nsgif_animate(void *p)
content_broadcast(c, CONTENT_MSG_REDRAW, data);
}
/**
* 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
*/
void *nsgif_bitmap_create(int width, int height) {
return bitmap_create(width, height, BITMAP_NEW);
}
#endif

View File

@ -1,5 +1,6 @@
/*
* 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/
*
@ -23,7 +24,7 @@
#ifdef WITH_GIF
#include <stdbool.h>
#include "image/gifread.h"
#include <libnsgif.h>
struct content;
@ -44,6 +45,7 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, unsigned long background_colour,
bool repeat_x, bool repeat_y);
void *nsgif_bitmap_create(int width, int height);
#endif /* WITH_GIF */

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +0,0 @@
/*
* 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
* Progressive animated GIF file decoding (interface).
*/
#ifndef _NETSURF_IMAGE_GIFREAD_H_
#define _NETSURF_IMAGE_GIFREAD_H_
#include <stdbool.h>
#include "image/bitmap.h"
/* Error return values
*/
#define GIF_INSUFFICIENT_FRAME_DATA -1
#define GIF_FRAME_DATA_ERROR -2
#define GIF_INSUFFICIENT_DATA -3
#define GIF_DATA_ERROR -4
#define GIF_INSUFFICIENT_MEMORY -5
/* Maximum colour table size
*/
#define GIF_MAX_COLOURS 256
/* Maximum LZW bits available
*/
#define GIF_MAX_LZW 12
/* The GIF frame data
*/
typedef struct gif_frame {
unsigned int frame_pointer; /**< offset (in bytes) to the GIF frame data */
unsigned int frame_delay; /**< delay (in cs) before animating the frame */
bool virgin; /**< whether the frame has previously been used */
bool opaque; /**< whether the frame is totally opaque */
bool redraw_required; /**< whether a forcable screen redraw is required */
unsigned int redraw_x; /**< x co-ordinate of redraw rectangle */
unsigned int redraw_y; /**< y co-ordinate of redraw rectangle */
unsigned int redraw_width; /**< width of redraw rectangle */
unsigned int redraw_height; /**< height of redraw rectangle */
} gif_frame;
/* The GIF animation data
*/
typedef struct gif_animation {
unsigned char *gif_data; /**< pointer to GIF data */
unsigned int buffer_position; /**< current index into GIF data */
unsigned int buffer_size; /**< total number of bytes of GIF data available */
unsigned int frame_holders; /**< current number of frame holders */
int decoded_frame; /**< current frame decoded to bitmap */
int loop_count; /**< number of times to loop animation */
gif_frame *frames; /**< decoded frames */
unsigned int width; /**< width of GIF (may increase during decoding) */
unsigned int height; /**< heigth of GIF (may increase during decoding) */
unsigned int frame_count; /**< number of frames decoded */
unsigned int frame_count_partial; /**< number of frames partially decoded */
unsigned int background_colour; /**< image background colour */
unsigned int aspect_ratio; /**< image aspect ratio (ignored) */
unsigned int colour_table_size; /**< size of colour table (in entries) */
bool global_colours; /**< whether the GIF has a global colour table */
unsigned int *global_colour_table; /**< global colour table */
unsigned int *local_colour_table; /**< local colour table */
int dirty_frame; /**< the current dirty frame, or -1 for none */
struct bitmap *frame_image; /**< currently decoded image */
int current_error; /**< current error type, or 0 for none*/
} gif_animation;
int gif_initialise(struct gif_animation *gif);
int gif_decode_frame(struct gif_animation *gif, unsigned int frame);
void gif_finalise(struct gif_animation *gif);
#endif

View File

@ -23,11 +23,11 @@
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/bmpread.h"
#include "image/ico.h"
#include "utils/log.h"
#include "utils/messages.h"
@ -35,13 +35,16 @@
bool nsico_create(struct content *c, const char *params[]) {
union content_msg_data msg_data;
extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /**< external structure containing
* bitmap callback functions */
c->data.ico.ico = calloc(sizeof(struct ico_collection), 1);
c->data.ico.ico = calloc(sizeof(ico_collection), 1);
if (!c->data.ico.ico) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
ico_collection_create(c->data.ico.ico, &bmp_bitmap_callbacks);
return true;
}
@ -49,16 +52,14 @@ bool nsico_create(struct content *c, const char *params[]) {
bool nsico_convert(struct content *c, int iwidth, int iheight) {
struct bmp_image *bmp;
bmp_result res;
struct ico_collection *ico;
ico_collection *ico;
union content_msg_data msg_data;
/* set our source data */
/* set the ico data */
ico = c->data.ico.ico;
ico->ico_data = (unsigned char *) c->source_data;
ico->buffer_size = c->source_size;
/* analyse the BMP */
res = ico_analyse(ico);
/* analyse the ico */
res = ico_analyse(ico, c->source_size, (unsigned char *) c->source_data);
switch (res) {
case BMP_OK:
break;
@ -99,7 +100,8 @@ bool nsico_redraw(struct content *c, int x, int y,
float scale, unsigned long background_colour) {
struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
if (!bmp->decoded)
bmp_decode(bmp);
if (bmp_decode(bmp) != BMP_OK)
return false;
c->bitmap = bmp->bitmap;
return plot.bitmap(x, y, width, height, c->bitmap,
background_colour, c);
@ -113,7 +115,8 @@ bool nsico_redraw_tiled(struct content *c, int x, int y,
bool repeat_x, bool repeat_y) {
struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
if (!bmp->decoded)
bmp_decode(bmp);
if (bmp_decode(bmp) != BMP_OK)
return false;
c->bitmap = bmp->bitmap;
return plot.bitmap_tile(x, y, width, height, c->bitmap,
background_colour, repeat_x, repeat_y, c);

View File

@ -23,7 +23,7 @@
#ifdef WITH_BMP
#include <stdbool.h>
#include "image/bmpread.h"
#include <libnsbmp.h>
struct content;

View File

@ -190,7 +190,7 @@ void bitmap_quit(void)
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
struct bitmap *bitmap_create(int width, int height, unsigned int state)
void *bitmap_create(int width, int height, unsigned int state)
{
struct bitmap *bitmap;
@ -305,7 +305,7 @@ void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s)
dp_offset = bitmap_get_rowstride(bitmap) / 4;
dp = (unsigned*)bitmap_get_buffer(bitmap);
dp = bitmap_get_buffer(bitmap);
if (!dp)
return;
sp = (byte*)s + s->image;
@ -410,8 +410,9 @@ bool bitmap_initialise(struct bitmap *bitmap)
* \param bitmap a bitmap, as returned by bitmap_create()
* \param opaque whether the bitmap should be plotted opaque
*/
void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
void bitmap_set_opaque(void *vbitmap, bool opaque)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
if (opaque)
@ -427,10 +428,11 @@ void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
* \param bitmap a bitmap, as returned by bitmap_create()
* \return whether the bitmap is opaque
*/
bool bitmap_test_opaque(struct bitmap *bitmap)
bool bitmap_test_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
char *sprite = bitmap_get_buffer(bitmap);
unsigned char *sprite = bitmap_get_buffer(bitmap);
if (!sprite)
return false;
unsigned int width = bitmap_get_rowstride(bitmap);
@ -464,8 +466,9 @@ bool bitmap_test_opaque(struct bitmap *bitmap)
*
* \param bitmap a bitmap, as returned by bitmap_create()
*/
bool bitmap_get_opaque(struct bitmap *bitmap)
bool bitmap_get_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
return (bitmap->state & BITMAP_OPAQUE);
}
@ -481,8 +484,9 @@ bool bitmap_get_opaque(struct bitmap *bitmap)
* of rows. The width of a row in bytes is given by bitmap_get_rowstride().
*/
char *bitmap_get_buffer(struct bitmap *bitmap)
unsigned char *bitmap_get_buffer(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
/* move to the head of the list */
@ -534,8 +538,9 @@ char *bitmap_get_buffer(struct bitmap *bitmap)
* \return width of a pixel row in the bitmap
*/
size_t bitmap_get_rowstride(struct bitmap *bitmap)
size_t bitmap_get_rowstride(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->width * 4;
}
@ -546,8 +551,9 @@ size_t bitmap_get_rowstride(struct bitmap *bitmap)
* \param bitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_destroy(struct bitmap *bitmap)
void bitmap_destroy(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
struct bitmap_compressed_header *header;
unsigned int area_size;
@ -590,8 +596,9 @@ void bitmap_destroy(struct bitmap *bitmap)
* \return true on success, false on error and error reported
*/
bool bitmap_save(struct bitmap *bitmap, const char *path, unsigned flags)
bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
os_error *error;
if (!bitmap->sprite_area)
@ -758,7 +765,8 @@ bool bitmap_save(struct bitmap *bitmap, const char *path, unsigned flags)
*
* \param bitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_modified(struct bitmap *bitmap) {
void bitmap_modified(void *vbitmap) {
struct bitmap *bitmap = (struct bitmap *) vbitmap;
bitmap->state |= BITMAP_MODIFIED;
}
@ -770,8 +778,9 @@ void bitmap_modified(struct bitmap *bitmap) {
* \param private_word a private word to be returned later
* \param invalidate the function to be called upon suspension
*/
void bitmap_set_suspendable(struct bitmap *bitmap, void *private_word,
void (*invalidate)(struct bitmap *bitmap, void *private_word)) {
void bitmap_set_suspendable(void *vbitmap, void *private_word,
void (*invalidate)(void *bitmap, void *private_word)) {
struct bitmap *bitmap = (struct bitmap *) vbitmap;
bitmap->private_word = private_word;
bitmap->invalidate = invalidate;
bitmap_suspendable++;
@ -1153,13 +1162,31 @@ void bitmap_delete_file(struct bitmap *bitmap)
}
int bitmap_get_width(struct bitmap *bitmap)
int bitmap_get_width(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->width;
}
int bitmap_get_height(struct bitmap *bitmap)
int bitmap_get_height(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->height;
}
/**
* Find the bytes per pixel of a bitmap
*
* \param bitmap a bitmap, as returned by bitmap_create()
* \return bytes per pixel
*/
size_t bitmap_get_bpp(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
return 4;
}