diff options
Diffstat (limited to 'w3mimg')
| -rw-r--r-- | w3mimg/x11/x11_w3mimg.c | 232 | 
1 files changed, 202 insertions, 30 deletions
| diff --git a/w3mimg/x11/x11_w3mimg.c b/w3mimg/x11/x11_w3mimg.c index 29aa55d..3b89f92 100644 --- a/w3mimg/x11/x11_w3mimg.c +++ b/w3mimg/x11/x11_w3mimg.c @@ -1,4 +1,4 @@ -/* $Id: x11_w3mimg.c,v 1.9 2002/10/01 15:34:20 ukai Exp $ */ +/* $Id: x11_w3mimg.c,v 1.10 2002/10/05 16:43:10 ukai Exp $ */  #include <stdio.h>  #include <stdlib.h>  #include <ctype.h> @@ -29,6 +29,15 @@ struct x11_info {  #endif  }; +#if defined(USE_GDKPIXBUF) +struct x11_image { +    int total; +    int no; +    int wait; +    Pixmap *pixmap; +}; +#endif +  static int  x11_init(w3mimg_op * self)  { @@ -145,6 +154,73 @@ x11_close(w3mimg_op * self)      /* XCloseDisplay(xi->display); */  } +#if defined(USE_GDKPIXBUF) +static struct x11_image * +x11_img_new(struct x11_info *xi, int w, int h, int n) +{ +    struct x11_image *img = NULL; +    int i; + +    img = malloc(sizeof(*img)); +    if (!img) +	goto ERROR; + +    img->pixmap = calloc(n, sizeof(*(img->pixmap))); +    if (!img->pixmap) +	goto ERROR; + +    for (i = 0; i < n; i++) { +	img->pixmap[i] = XCreatePixmap(xi->display, xi->parent, w, h, +				       DefaultDepth(xi->display, 0)); +	if (!img->pixmap[i]) +	    goto ERROR; + +	XSetForeground(xi->display, xi->imageGC, xi->background_pixel); +	XFillRectangle(xi->display, (Pixmap) img->pixmap[i], xi->imageGC, 0, 0, +		       w, h); +    } + +    img->no = 0; +    img->total = n; +    img->wait = 0; + +    return img; +  ERROR: +    if (img) { +	if (img->pixmap) { +	    for (i = 0; i < n; i++) { +		if (img->pixmap[i]) +		    XFreePixmap(xi->display, (Pixmap) img->pixmap[i]); +	    } +	    free(img->pixmap); +	} +	free(img); +    } +    return NULL; +} + +static GdkPixbuf * +resize_image(GdkPixbuf * pixbuf, int width, int height) +{ +    GdkPixbuf *resized_pixbuf; +    int w, h; + +    if (pixbuf == NULL) +	return NULL; +    w = gdk_pixbuf_get_width(pixbuf); +    h = gdk_pixbuf_get_height(pixbuf); +    if (width < 1 || height < 1) +	return pixbuf; +    if (w == width && h == height) +	return pixbuf; +    resized_pixbuf = +	gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR); +    if (resized_pixbuf == NULL) +	return NULL; +    return resized_pixbuf; +} +#endif +  static int  x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h)  { @@ -152,8 +228,12 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h)  #if defined(USE_IMLIB)      ImlibImage *im;  #elif defined(USE_GDKPIXBUF) -    GdkPixbuf *pixbuf; -    int iw, ih; +    GdkPixbufAnimation *animation; +    GList *frames; +    int i, iw, ih, n; +    double ratio_w, ratio_h; +    struct x11_image *ximg; +    GdkPixbufFrameAction action = GDK_PIXBUF_FRAME_REVERT;  #endif      if (self == NULL) @@ -170,45 +250,95 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h)  	w = im->rgb_width;      if (h <= 0)  	h = im->rgb_height; -#elif defined(USE_GDKPIXBUF) -    pixbuf = gdk_pixbuf_new_from_file(fname); -    if (!pixbuf) -	return 0; -    iw = gdk_pixbuf_get_width(pixbuf); -    ih = gdk_pixbuf_get_height(pixbuf); -    if (w <= 0) -	w = iw; -    if (h <= 0) -	h = ih; -#endif      img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h,  					DefaultDepth(xi->display, 0));      if (!img->pixmap)  	return 0;      XSetForeground(xi->display, xi->imageGC, xi->background_pixel);      XFillRectangle(xi->display, (Pixmap) img->pixmap, xi->imageGC, 0, 0, w, h); -#if defined(USE_IMLIB)      Imlib_paste_image(xi->id, im, (Pixmap) img->pixmap, 0, 0, w, h);      Imlib_kill_image(xi->id, im);  #elif defined(USE_GDKPIXBUF) -    if (w != iw || h != ih) { -	GdkPixbuf *newpixbuf; -	newpixbuf = gdk_pixbuf_scale_simple(pixbuf, w, h, GDK_INTERP_BILINEAR); -	gdk_pixbuf_xlib_render_to_drawable_alpha(newpixbuf, -					   (Drawable) img->pixmap, -					   0, 0, 0, 0, w, h, -					   GDK_PIXBUF_ALPHA_BILEVEL, 1, -					   XLIB_RGB_DITHER_NORMAL, 0, 0); -	gdk_pixbuf_finalize(newpixbuf); -    } else { +    animation = gdk_pixbuf_animation_new_from_file(fname); +    if (!animation) +	return 0; +    frames = gdk_pixbuf_animation_get_frames(animation); +    n = gdk_pixbuf_animation_get_num_frames(animation); +    iw = gdk_pixbuf_animation_get_width(animation); +    ih = gdk_pixbuf_animation_get_height(animation); + +    if (w < 1 || h < 1) { +	w = iw; +	h = ih; +	ratio_w = ratio_h = 1; +    } +    else { +	ratio_w = 1.0 * w / iw; +	ratio_h = 1.0 * h / ih; +    } +    ximg = x11_img_new(xi, w, h, n); +    if (!ximg) { +	gdk_pixbuf_animation_unref(animation); +	return 0; +    } +    for (i = 0; i < n; i++) { +	GdkPixbufFrame *frame; +	GdkPixbuf *org_pixbuf, *pixbuf; +	int width, height, ofstx, ofsty; + +	frame = (GdkPixbufFrame *) g_list_nth_data(frames, i); +	org_pixbuf = gdk_pixbuf_frame_get_pixbuf(frame); +	ofstx = gdk_pixbuf_frame_get_x_offset(frame); +	ofsty = gdk_pixbuf_frame_get_y_offset(frame); +	width = gdk_pixbuf_get_width(org_pixbuf); +	height = gdk_pixbuf_get_height(org_pixbuf); + +	if (ofstx == 0 && ofsty == 0 && width == w && height == h) { +	    pixbuf = resize_image(org_pixbuf, w, h); +	} +	else { +	    pixbuf = +		resize_image(org_pixbuf, width * ratio_w, height * ratio_h); +	    ofstx *= ratio_w; +	    ofsty *= ratio_h; +	} +	width = gdk_pixbuf_get_width(pixbuf); +	height = gdk_pixbuf_get_height(pixbuf); + +	if (i > 0) { +	    switch (action) { +	    case GDK_PIXBUF_FRAME_RETAIN: +		XCopyArea(xi->display, ximg->pixmap[i - 1], ximg->pixmap[i], +			  xi->imageGC, 0, 0, w, h, 0, 0); +		break; +	    case GDK_PIXBUF_FRAME_DISPOSE: +		break; +	    case GDK_PIXBUF_FRAME_REVERT: +		XCopyArea(xi->display, ximg->pixmap[0], ximg->pixmap[i], +			  xi->imageGC, 0, 0, w, h, 0, 0); +		break; +	    default: +		XCopyArea(xi->display, ximg->pixmap[0], ximg->pixmap[i], +			  xi->imageGC, 0, 0, w, h, 0, 0); +		break; +	    } +	} +  	gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, -					   (Drawable) img->pixmap, -					   0, 0, 0, 0, w, h, -					   GDK_PIXBUF_ALPHA_BILEVEL, 1, -					   XLIB_RGB_DITHER_NORMAL, 0, 0); +						 (Drawable) ximg->pixmap[i], 0, +						 0, ofstx, ofsty, width, +						 height, +						 GDK_PIXBUF_ALPHA_BILEVEL, 1, +						 XLIB_RGB_DITHER_NORMAL, 0, 0); +	action = gdk_pixbuf_frame_get_action(frame); +	if (org_pixbuf != pixbuf) +	    gdk_pixbuf_finalize(pixbuf); +      } -    gdk_pixbuf_unref(pixbuf); +    gdk_pixbuf_animation_unref(animation); +    img->pixmap = ximg;  #endif +      img->width = w;      img->height = h;      return 1; @@ -219,16 +349,39 @@ x11_show_image(w3mimg_op * self, W3MImage * img, int sx, int sy, int sw,  	       int sh, int x, int y)  {      struct x11_info *xi; +#if defined(USE_GDKPIXBUF) +    struct x11_image *ximg = img->pixmap; +    int i; +#endif      if (self == NULL)  	return 0;      xi = (struct x11_info *)self->priv;      if (xi == NULL)  	return 0; +#if defined(USE_IMLIB)      XCopyArea(xi->display, (Pixmap) img->pixmap, xi->window, xi->imageGC,  	      sx, sy,  	      (sw ? sw : img->width),  	      (sh ? sh : img->height), x + self->offset_x, y + self->offset_y); +#elif defined(USE_GDKPIXBUF) +#define WAIT_CNT 4 +    i = ximg->no; +    XCopyArea(xi->display, ximg->pixmap[i], xi->window, xi->imageGC, +	      sx, sy, +	      (sw ? sw : img->width), +	      (sh ? sh : img->height), x + self->offset_x, y + self->offset_y); +    if (ximg->total > 1) { +	if (ximg->wait > WAIT_CNT) { +	    ximg->wait = 0; +	    if (i < ximg->total - 1) +		ximg->no = i + 1; +	    else +		ximg->no = 0; +	} +	ximg->wait += 1; +    } +#endif      return 1;  } @@ -241,12 +394,31 @@ x11_free_image(w3mimg_op * self, W3MImage * img)      xi = (struct x11_info *)self->priv;      if (xi == NULL)  	return; +#if defined(USE_IMLIB)      if (img && img->pixmap) {  	XFreePixmap(xi->display, (Pixmap) img->pixmap);  	img->pixmap = NULL;  	img->width = 0;  	img->height = 0;      } +#elif defined(USE_GDKPIXBUF) +    if (img && img->pixmap) { +	struct x11_image *ximg = img->pixmap; +	int i, n; +	if (ximg->pixmap) { +	    n = ximg->total; +	    for (i = 0; i < n; i++) { +		if (ximg->pixmap[i]) +		    XFreePixmap(xi->display, (Pixmap) ximg->pixmap[i]); +	    } +	    free(ximg->pixmap); +	} +	free(ximg); +	img->pixmap = NULL; +	img->width = 0; +	img->height = 0; +    } +#endif  }  static int | 
