mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-26 08:19:55 +03:00
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:
parent
4c8989a6db
commit
33107b160f
11
Makefile
11
Makefile
@ -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
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
@ -204,18 +231,19 @@ void bitmap_modified(struct bitmap *bitmap) {
|
||||
*
|
||||
* \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 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);
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
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));
|
||||
free(gif->gif_data);
|
||||
free(gif);
|
||||
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;
|
||||
}
|
||||
gif_finalise(&gif);
|
||||
free(data);
|
||||
free(&throb);
|
||||
return false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
54
image/bmp.c
54
image/bmp.c
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
816
image/bmpread.c
816
image/bmpread.c
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
74
image/gif.c
74
image/gif.c
@ -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");
|
||||
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
} 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
|
||||
|
@ -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 */
|
||||
|
||||
|
1004
image/gifread.c
1004
image/gifread.c
File diff suppressed because it is too large
Load Diff
@ -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
|
23
image/ico.c
23
image/ico.c
@ -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);
|
||||
|
@ -23,7 +23,7 @@
|
||||
#ifdef WITH_BMP
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "image/bmpread.h"
|
||||
#include <libnsbmp.h>
|
||||
|
||||
struct content;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user