gtk2/gdk-pixbuf/io-wbmp.c
Havoc Pennington b4e4a0ed9d fix some shell typos
2001-05-04  Havoc Pennington  <hp@redhat.com>

	* configure.in: fix some shell typos

	* gtk/gtkcolorsel.c (gtk_color_selection_destroy): warning fix

	* gtk/gtkimage.c: handle animations

	* gtk/gtkcheckbutton.c (gtk_check_button_size_request): request
	border_width * 2, not just border_width

	* gtk/gtkscale.c: add "format_value" signal to allow people
	to override the way values are drawn.
	(gtk_scale_get_value_size): fix width/height mistake,
	and compute size from actual displayed text, not
	from made-up text.

	* gtk/gtktexttag.c (gtk_text_tag_class_init): fix return type in
	signal registration

	* tests/testtext.c: Add "Remove all tags" menu item for testing

	* gtk/gtktextbuffer.c (gtk_text_buffer_remove_all_tags): implement

	* demos/gtk-demo/main.c (main): add hack so we can find modules
	without installing gtk

	* demos/gtk-demo/textview.c (insert_text): demo font scaling

	* gtk/gtkcellrenderertext.c: Add "scale" property (font scaling
	factor)
	(gtk_cell_renderer_text_set_property): remove some bogus
	g_object_notify

	* gtk/gtktexttag.c: add "scale" property which is a font scaling
	factor

	* gtk/gtktextlayout.c (add_text_attrs): add font scale attribute
	to layout

	* gtk/gtktextiter.c (gtk_text_iter_is_start): rename from
	gtk_text_iter_is_first

2001-05-04  Havoc Pennington  <hp@redhat.com>

	* pixops/pixops.c (pixops_process): merge fix from stable: Patch
	 from hoshem@mel.comcen.com.au to fix nonzero X offsets.  Fixes
	 bug #50371.

        * gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest): merge
	from stable: Patch from OKADA Mitsuru <m-okada@fjb.co.jp> to fix
	confusion of using "src" instead of "p".
        (pixops_composite_color_nearest): Use a more accurate (and
	correct, to begin with) compositing method.  This cures checks
	showing through on images with no alpha.

	* gdk-pixbuf.c (gdk_pixbuf_fill): fix bug that left some trailing
	bytes unfilled.

	* gdk-pixbuf-io.h: fix UpdatedNotifyFunc to use signed ints

	* gdk-pixbuf-loader.h (struct _GdkPixbufLoaderClass): Change
	area_updated signal to use signed ints.  Removed animation-related
	signals.

	* io-gif.c, io-gif-animation.h, io-gif-animation.c: Massive
	rewrite action

	* gdk-pixbuf-animation.c: Add GdkPixbufAnimationIter to abstract
	all the pesky details. Remove old frame-based API. Make
	GdkPixbufAnimation an abstract base class, derived by the loaders.
2001-05-07 15:58:47 +00:00

341 lines
8.8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* GdkPixbuf library - Wireless Bitmap image loader
*
* Copyright (C) 2000 Red Hat, Inc.
*
* Authors: Elliot Lee <sopwith@redhat.com
*
* Based on io-bmp.c
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
Known bugs:
* Since this is based off the libgd implementation, no extended headers implemented (not required for a WAP client)
*/
#include <config.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include "gdk-pixbuf-private.h"
#include "gdk-pixbuf-io.h"
/* Progressive loading */
struct wbmp_progressive_state {
ModulePreparedNotifyFunc prepared_func;
ModuleUpdatedNotifyFunc updated_func;
gpointer user_data;
gboolean need_type : 1;
gboolean need_header : 1;
gboolean need_width : 1;
gboolean need_height : 1;
gboolean needmore : 1;
gboolean call_progressive_updates : 1;
guchar last_buf[16]; /* Just needs to be big enough to hold the largest datum requestable via 'getin' */
guint last_len;
int type;
int width, height, curx, cury;
GdkPixbuf *pixbuf; /* Our "target" */
};
static gpointer
gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
gpointer user_data,
GError **error);
static gboolean gdk_pixbuf__wbmp_image_stop_load(gpointer data, GError **error);
static gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data,
const guchar * buf,
guint size,
GError **error);
/* Shared library entry point --> This should be removed when
generic_image_load enters gdk-pixbuf-io. */
static GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f, GError **error)
{
size_t length;
char membuf[4096];
struct wbmp_progressive_state *State;
GdkPixbuf *pb;
State = gdk_pixbuf__wbmp_image_begin_load(NULL, NULL, NULL,
error);
if (State == NULL)
return NULL;
while (feof(f) == 0) {
length = fread(membuf, 1, 4096, f);
if (length > 0)
gdk_pixbuf__wbmp_image_load_increment(State,
membuf,
length,
error);
}
if (State->pixbuf != NULL)
gdk_pixbuf_ref(State->pixbuf);
pb = State->pixbuf;
gdk_pixbuf__wbmp_image_stop_load(State, NULL);
return pb;
}
/*
* func - called when we have pixmap created (but no image data)
* user_data - passed as arg 1 to func
* return context (opaque to user)
*/
static gpointer
gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
gpointer user_data,
GError **error)
{
struct wbmp_progressive_state *context;
context = g_new0(struct wbmp_progressive_state, 1);
context->prepared_func = prepared_func;
context->updated_func = updated_func;
context->user_data = user_data;
context->needmore = context->need_type = context->need_header = context->need_width = context->need_height = TRUE;
context->call_progressive_updates = TRUE;
context->pixbuf = NULL;
return (gpointer) context;
}
/*
* context - returned from image_begin_load
*
* free context, unref gdk_pixbuf
*/
static gboolean gdk_pixbuf__wbmp_image_stop_load(gpointer data,
GError **error)
{
struct wbmp_progressive_state *context =
(struct wbmp_progressive_state *) data;
/* FIXME this thing needs to report errors if
* we have unused image data
*/
g_return_val_if_fail(context != NULL, TRUE);
if (context->pixbuf)
gdk_pixbuf_unref(context->pixbuf);
g_free(context);
return TRUE;
}
static gboolean
getin(struct wbmp_progressive_state *context, guchar **buf, guint *buf_size, guchar *ptr, int datum_size)
{
int last_num, buf_num;
if((context->last_len + *buf_size) < datum_size)
return FALSE;
/* We know we can pull it out of there */
last_num = MIN(datum_size, context->last_len);
buf_num = MIN(datum_size-last_num, *buf_size);
memcpy(ptr, context->last_buf, last_num);
memcpy(ptr+last_num, *buf, buf_num);
context->last_len -= last_num;
if(context->last_len)
memmove(context->last_buf, context->last_buf+last_num, context->last_len);
*buf_size -= buf_num;
*buf += buf_num;
return TRUE;
}
static gboolean
save_rest(struct wbmp_progressive_state *context, const guchar *buf, guint buf_size)
{
if(buf_size > (sizeof(context->last_buf) - context->last_len))
return FALSE;
memcpy(context->last_buf+context->last_len, buf, buf_size);
context->last_len += buf_size;
return TRUE;
}
static gboolean
get_mbi(struct wbmp_progressive_state *context, guchar **buf, guint *buf_size, int *val)
{
guchar intbuf[16];
int i, n;
gboolean rv;
*val = 0;
n = i = 0;
do {
rv = getin(context, buf, buf_size, intbuf+n, 1);
if(!rv)
goto out;
*val <<= 7;
*val |= intbuf[n] & 0x7F;
n++;
} while(n < sizeof(intbuf) && (intbuf[n-1] & 0x80));
out:
if(!rv || (intbuf[n-1] & 0x80))
{
rv = save_rest(context, intbuf, n);
if(!rv)
g_error("Couldn't save_rest of intbuf");
return FALSE;
}
return TRUE;
}
/*
* context - from image_begin_load
* buf - new image data
* size - length of new image data
*
* append image data onto inrecrementally built output image
*/
static gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data,
const guchar * buf,
guint size, GError **error)
{
struct wbmp_progressive_state *context =
(struct wbmp_progressive_state *) data;
gboolean bv = FALSE;
do
{
if(context->need_type)
{
guchar val;
bv = getin(context, &buf, &size, &val, 1);
if(bv)
{
context->type = val;
context->need_type = FALSE;
}
}
else if(context->need_header)
{
guchar val;
bv = getin(context, &buf, &size, &val, 1);
if(bv)
{
/* We skip over the extended header - val is unused */
if(!(val & 0x80))
context->need_header = FALSE;
}
}
else if(context->need_width)
{
bv = get_mbi(context, &buf, &size, &context->width);
if(bv)
context->need_width = FALSE;
}
else if(context->need_height)
{
bv = get_mbi(context, &buf, &size, &context->height);
if(bv)
{
context->need_height = FALSE;
context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, context->width, context->height);
g_assert(context->pixbuf);
if(context->prepared_func)
context->prepared_func(context->pixbuf, NULL, context->user_data);
}
}
else if(context->needmore)
{
int first_row;
first_row = context->cury;
for( ; context->cury < context->height; context->cury++, context->curx = 0)
{
for( ; context->curx < context->width; context->curx += 8)
{
guchar byte;
guchar *ptr;
int xoff;
bv = getin(context, &buf, &size, &byte, 1);
if(!bv)
goto out;
ptr = context->pixbuf->pixels + context->pixbuf->rowstride * context->cury + context->curx * 3;
for(xoff = 7; xoff >= 0; xoff--, ptr += 3)
{
guchar pixval;
if(byte & (1<<xoff))
pixval = 0xFF;
else
pixval = 0x0;
ptr[0] = ptr[1] = ptr[2] = pixval;
}
}
}
context->needmore = FALSE;
out:
context->updated_func(context->pixbuf, 0, first_row, context->width, context->cury - first_row + 1,
context->user_data);
}
else
bv = FALSE; /* Nothing left to do, stop feeding me data! */
} while(bv);
if(size)
return save_rest(context, buf, size);
else
return context->needmore;
}
void
gdk_pixbuf__wbmp_fill_vtable (GdkPixbufModule *module)
{
module->load = gdk_pixbuf__wbmp_image_load;
module->begin_load = gdk_pixbuf__wbmp_image_begin_load;
module->stop_load = gdk_pixbuf__wbmp_image_stop_load;
module->load_increment = gdk_pixbuf__wbmp_image_load_increment;
}