diff options
| author | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:05:14 +0000 | 
|---|---|---|
| committer | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:05:14 +0000 | 
| commit | 72f72d64a422d6628c4796f5c0bf2e508f134214 (patch) | |
| tree | 0c9ea90cc53310832c977265521fb44db24a515e /w3mimg/x11 | |
| parent | Adding upstream version 0.3 (diff) | |
| download | w3m-72f72d64a422d6628c4796f5c0bf2e508f134214.tar.gz w3m-72f72d64a422d6628c4796f5c0bf2e508f134214.zip | |
Adding upstream version 0.5.1upstream/0.5.1
Diffstat (limited to 'w3mimg/x11')
| -rw-r--r-- | w3mimg/x11/.cvsignore | 1 | ||||
| -rw-r--r-- | w3mimg/x11/Makefile.in | 29 | ||||
| -rw-r--r-- | w3mimg/x11/x11_w3mimg.c | 723 | 
3 files changed, 753 insertions, 0 deletions
| diff --git a/w3mimg/x11/.cvsignore b/w3mimg/x11/.cvsignore new file mode 100644 index 0000000..f3c7a7c --- /dev/null +++ b/w3mimg/x11/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/w3mimg/x11/Makefile.in b/w3mimg/x11/Makefile.in new file mode 100644 index 0000000..fb30e3a --- /dev/null +++ b/w3mimg/x11/Makefile.in @@ -0,0 +1,29 @@ +# +# w3mimg/x11/Makefile +# +# +@SET_MAKE@ +SHELL=@SHELL@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = $(srcdir):. +CFLAGS=$(OPTS) -I../.. -I$(top_srcdir) -I$(srcdir) @CFLAGS@ @CPPFLAGS@ @DEFS@ $(IMGCFLAGS) +RM=rm + +IMGCFLAGS=@IMGX11CFLAGS@ +OBJS=x11_w3mimg.o + +all: x11_w3mimg.o + +x11_w3mimg.o: x11_w3mimg.c +	$(CC) $(CFLAGS) -c $< + +clean: +	@-$(RM) -f *.o + +distclean: clean +	-$(RM) -f Makefile + +# + + diff --git a/w3mimg/x11/x11_w3mimg.c b/w3mimg/x11/x11_w3mimg.c new file mode 100644 index 0000000..8c9cef2 --- /dev/null +++ b/w3mimg/x11/x11_w3mimg.c @@ -0,0 +1,723 @@ +/* $Id: x11_w3mimg.c,v 1.25 2003/07/13 16:19:10 ukai Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include "config.h" + +#if defined(USE_IMLIB) +#include <Imlib.h> +#elif defined(USE_IMLIB2) +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <Imlib2.h> +#elif defined(USE_GDKPIXBUF) +#include <gdk-pixbuf/gdk-pixbuf-xlib.h> +#else +#error no Imlib and GdkPixbuf support +#endif + +#include "w3mimg/w3mimg.h" + +#define OFFSET_X	2 +#define OFFSET_Y	2 + +struct x11_info { +    Display *display; +    Window window, parent; +    unsigned long background_pixel; +    GC imageGC; +#if defined(USE_IMLIB) +    ImlibData *id; +#elif defined(USE_GDKPIXBUF) +    int init_flag; +#endif +}; + +#if defined(USE_GDKPIXBUF) +struct x11_image { +    int total; +    int no; +    int wait; +    int delay; +    Pixmap *pixmap; +}; + +static void +get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) +{ +    GList *frames; +    int iw, ih, n, i, d = -1; + +    frames = gdk_pixbuf_animation_get_frames(animation); +    n = gdk_pixbuf_animation_get_num_frames(animation); +    *w = gdk_pixbuf_animation_get_width(animation); +    *h = gdk_pixbuf_animation_get_height(animation); +    for (i = 0; i < n; i++) { +	GdkPixbufFrame *frame; +	GdkPixbuf *pixbuf; +	int tmp; + +	frame = (GdkPixbufFrame *) g_list_nth_data(frames, i); +	tmp = gdk_pixbuf_frame_get_delay_time(frame); +	if (tmp > d) +	    d = tmp; +	pixbuf = gdk_pixbuf_frame_get_pixbuf(frame); +	iw = gdk_pixbuf_frame_get_x_offset(frame) +	    + gdk_pixbuf_get_width(pixbuf); +	ih = gdk_pixbuf_frame_get_y_offset(frame) +	    + gdk_pixbuf_get_height(pixbuf); +	if (iw > *w) +	    *w = iw; +	if (ih > *h) +	    *h = ih; +    } +    if (delay) +	*delay = d; +} + +#endif + +static int +x11_init(w3mimg_op * self) +{ +    struct x11_info *xi; +    if (self == NULL) +	return 0; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; +#if defined(USE_IMLIB) +    if (!xi->id) { +	xi->id = Imlib_init(xi->display); +	if (!xi->id) +	    return 0; +    } +#elif defined(USE_GDKPIXBUF) +    if (!xi->init_flag) { +	gdk_pixbuf_xlib_init(xi->display, 0); +	xi->init_flag = TRUE; +    } +#endif +    if (!xi->imageGC) { +	xi->imageGC = XCreateGC(xi->display, xi->parent, 0, NULL); +	if (!xi->imageGC) +	    return 0; +    } +    return 1; +} + +static int +x11_finish(w3mimg_op * self) +{ +    struct x11_info *xi; +    if (self == NULL) +	return 0; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; +    if (xi->imageGC) { +	XFreeGC(xi->display, xi->imageGC); +	xi->imageGC = NULL; +    } +    return 1; +} + +static int +x11_clear(w3mimg_op * self, int x, int y, int w, int h) +{ +    struct x11_info *xi; +    if (self == NULL) +	return 0; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; + +    if (x < 0) +	x = 0; +    if (y < 0) +	y = 0; + +    XClearArea(xi->display, xi->window, x, y, w, h, False); +    return 1; +} + +static int +x11_active(w3mimg_op * self) +{ +    struct x11_info *xi; +    if (self == NULL) +	return 0; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; +    if (!xi->imageGC) +	return 0; +    return 1; +} + +static void +x11_set_background(w3mimg_op * self, char *background) +{ +    XColor screen_def, exact_def; +    struct x11_info *xi; +    if (self == NULL) +	return; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return; + +    if (background && +	XAllocNamedColor(xi->display, DefaultColormap(xi->display, 0), +			 background, &screen_def, &exact_def)) +	xi->background_pixel = screen_def.pixel; +    else { +	Pixmap p; +	GC gc; +	XImage *i; + +	p = XCreatePixmap(xi->display, xi->window, 1, 1, +			  DefaultDepth(xi->display, 0)); +	gc = XCreateGC(xi->display, xi->window, 0, NULL); +	if (!p || !gc) +	    exit(1);		/* XXX */ +	XCopyArea(xi->display, xi->window, p, gc, +		  (self->offset_x >= 1) ? (self->offset_x - 1) : 0, +		  (self->offset_y >= 1) ? (self->offset_y - 1) : 0, +		  1, 1, 0, 0); +	i = XGetImage(xi->display, p, 0, 0, 1, 1, -1, ZPixmap); +	if (!i) +	    exit(1); +	xi->background_pixel = XGetPixel(i, 0, 0); +	XDestroyImage(i); +	XFreeGC(xi->display, gc); +	XFreePixmap(xi->display, p); +    } +} + +static void +x11_sync(w3mimg_op * self) +{ +    struct x11_info *xi; +    if (self == NULL) +	return; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return; +    XSync(xi->display, False); +} + +static void +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; +    img->delay = -1; + +    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) +{ +    struct x11_info *xi; +#if defined(USE_IMLIB) +    ImlibImage *im; +#elif defined(USE_IMLIB2) +    Imlib_Image im; +#elif defined(USE_GDKPIXBUF) +    GdkPixbufAnimation *animation; +    GList *frames; +    int i, j, iw, ih, n, frame_num, delay, max_anim; +    double ratio_w, ratio_h; +    struct x11_image *ximg; +    Pixmap tmp_pixmap; +#endif + +    if (self == NULL) +	return 0; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; + +#if defined(USE_IMLIB) +    im = Imlib_load_image(xi->id, fname); +    if (!im) +	return 0; +    if (w <= 0) +	w = im->rgb_width; +    if (h <= 0) +	h = im->rgb_height; +    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); +    Imlib_paste_image(xi->id, im, (Pixmap) img->pixmap, 0, 0, w, h); +    Imlib_kill_image(xi->id, im); +#elif defined(USE_IMLIB2) +    im = imlib_load_image(fname); +    if (!im) +	return 0; +    imlib_context_set_image(im); +    if (w <= 0) +	w = imlib_image_get_width(); +    if (h <= 0) +	h = imlib_image_get_height(); +    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); +    imlib_context_set_display(xi->display); +    imlib_context_set_visual(DefaultVisual(xi->display, 0)); +    imlib_context_set_colormap(DefaultColormap(xi->display, 0)); +    imlib_context_set_drawable((Drawable) img->pixmap); +    imlib_render_image_on_drawable_at_size(0, 0, w, h); +    imlib_free_image(); +#elif defined(USE_GDKPIXBUF) +    max_anim = self->max_anim; +    animation = gdk_pixbuf_animation_new_from_file(fname); +    if (!animation) +	return 0; +    frames = gdk_pixbuf_animation_get_frames(animation); +    frame_num = n = gdk_pixbuf_animation_get_num_frames(animation); + +    get_animation_size(animation, &iw, &ih, &delay); +    if (delay <= 0) +	max_anim = -1; + +    if (max_anim < 0) { +	frame_num = (-max_anim > n) ? n : -max_anim; +    } +    else if (max_anim > 0) { +	frame_num = n = (max_anim > n) ? n : max_anim; +    } + +    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; +    } +    tmp_pixmap = XCreatePixmap(xi->display, xi->parent, w, h, +			       DefaultDepth(xi->display, 0)); +    XFillRectangle(xi->display, (Pixmap) tmp_pixmap, xi->imageGC, 0, 0, w, h); +    if (!tmp_pixmap) { +	gdk_pixbuf_animation_unref(animation); +	return 0; +    } +    ximg = x11_img_new(xi, w, h, frame_num); +    if (!ximg) { +	XFreePixmap(xi->display, tmp_pixmap); +	gdk_pixbuf_animation_unref(animation); +	return 0; +    } +    for (j = 0; j < n; j++) { +	GdkPixbufFrame *frame; +	GdkPixbuf *org_pixbuf, *pixbuf; +	int width, height, ofstx, ofsty; + +	if (max_anim < 0) { +	    i = (j - n + frame_num > 0) ? (j - n + frame_num) : 0; +	} +	else { +	    i = j; +	} +	frame = (GdkPixbufFrame *) g_list_nth_data(frames, j); +	org_pixbuf = gdk_pixbuf_frame_get_pixbuf(frame); +	ofstx = gdk_pixbuf_frame_get_x_offset(frame); +	ofsty = gdk_pixbuf_frame_get_y_offset(frame); +	delay = gdk_pixbuf_frame_get_delay_time(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 (delay > ximg->delay) +	    ximg->delay = delay; + +	XCopyArea(xi->display, tmp_pixmap, ximg->pixmap[i], +		  xi->imageGC, 0, 0, w, h, 0, 0); +	gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, +						 (Drawable) ximg->pixmap[i], 0, +						 0, ofstx, ofsty, width, +						 height, +						 GDK_PIXBUF_ALPHA_BILEVEL, 1, +						 XLIB_RGB_DITHER_NORMAL, 0, 0); + +	switch (gdk_pixbuf_frame_get_action(frame)) { +	case GDK_PIXBUF_FRAME_RETAIN: +	    XCopyArea(xi->display, ximg->pixmap[i], tmp_pixmap, +		      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], tmp_pixmap, +		      xi->imageGC, 0, 0, w, h, 0, 0); +	    break; +	default: +	    XCopyArea(xi->display, ximg->pixmap[0], tmp_pixmap, +		      xi->imageGC, 0, 0, w, h, 0, 0); +	    break; +	} + + +	if (org_pixbuf != pixbuf) +	    gdk_pixbuf_finalize(pixbuf); + +    } +    XFreePixmap(xi->display, tmp_pixmap); +    gdk_pixbuf_animation_unref(animation); +    img->pixmap = ximg; +#endif + +    img->width = w; +    img->height = h; +    return 1; +} + +static int +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; + +    if (img->pixmap == NULL) +	return 0; + +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; + +#if defined(USE_IMLIB) || defined(USE_IMLIB2) +    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 +    if (ximg->delay <= 0) +	i = ximg->total - 1; +    else +	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; +} + +static void +x11_free_image(w3mimg_op * self, W3MImage * img) +{ +    struct x11_info *xi; +    if (self == NULL) +	return; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return; +#if defined(USE_IMLIB) || defined(USE_IMLIB2) +    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 +x11_get_image_size(w3mimg_op * self, W3MImage * img, char *fname, int *w, +		   int *h) +{ +    struct x11_info *xi; +#if defined(USE_IMLIB) +    ImlibImage *im; +#elif defined(USE_IMLIB2) +    Imlib_Image im; +#elif defined(USE_GDKPIXBUF) +    GdkPixbufAnimation *animation; +#endif + +    if (self == NULL) +	return 0; +    xi = (struct x11_info *)self->priv; +    if (xi == NULL) +	return 0; + +#if defined(USE_IMLIB) +    im = Imlib_load_image(xi->id, fname); +    if (!im) +	return 0; + +    *w = im->rgb_width; +    *h = im->rgb_height; +    Imlib_kill_image(xi->id, im); +#elif defined(USE_IMLIB2) +    im = imlib_load_image(fname); +    if (im == NULL) +	return 0; + +    imlib_context_set_image(im); +    *w = imlib_image_get_width(); +    *h = imlib_image_get_height(); +    imlib_free_image(); +#elif defined(USE_GDKPIXBUF) +    animation = gdk_pixbuf_animation_new_from_file(fname); +    if (!animation) +	return 0; + +    get_animation_size(animation, w, h, NULL); +    gdk_pixbuf_animation_unref(animation); +#endif +    return 1; +} + +/* *INDENT-OFF* */ +/* +  xterm/kterm/hanterm/cxterm +    top window (WINDOWID) +      +- text window +           +- scrollbar +  rxvt/aterm/Eterm/wterm +    top window (WINDOWID) +      +- text window +      +- scrollbar +      +- menubar (etc.) +  gnome-terminal +    top window +      +- text window (WINDOWID) +      +- scrollbar +      +- menubar +  mlterm (-s) +    top window +      +- text window (WINDOWID) +      +- scrollbar +  mlterm +    top window = text window (WINDOWID) + +  powershell +    top window +      +- window +      |    +- text window +      |    +- scrollbar +      +- menubar (etc.) +  dtterm +    top window +      +- window +           +- window +           |    +- window +           |         +- text window +           |         +- scrollbar +           +- menubar +  hpterm +    top window +      +- window +           +- text window +           +- scrollbar +           +- (etc.) +*/ +/* *INDENT-ON* */ + +w3mimg_op * +w3mimg_x11open() +{ +    w3mimg_op *wop = NULL; +    struct x11_info *xi = NULL; +    char *id; +    int revert, i; +    unsigned int nchildren; +    XWindowAttributes attr; +    Window root, *children; + +    wop = (w3mimg_op *) malloc(sizeof(w3mimg_op)); +    if (wop == NULL) +	return NULL; +    memset(wop, 0, sizeof(w3mimg_op)); + +    xi = (struct x11_info *)malloc(sizeof(struct x11_info)); +    if (xi == NULL) +	goto error; +    memset(xi, 0, sizeof(struct x11_info)); + +    xi->display = XOpenDisplay(NULL); +    if (xi->display == NULL) { +	goto error; +    } +    if ((id = getenv("WINDOWID")) != NULL) +	xi->window = (Window) atoi(id); +    else +	XGetInputFocus(xi->display, &xi->window, &revert); +    if (!xi->window) +	exit(1); + +    XGetWindowAttributes(xi->display, xi->window, &attr); +    wop->width = attr.width; +    wop->height = attr.height; + +    while (1) { +	Window p_window; + +	XQueryTree(xi->display, xi->window, &root, &xi->parent, +		   &children, &nchildren); +	p_window = xi->window; +	for (i = 0; i < nchildren; i++) { +	    XGetWindowAttributes(xi->display, children[i], &attr); +	    if (attr.width > wop->width * 0.7 && +		attr.height > wop->height * 0.7) { +		/* maybe text window */ +		wop->width = attr.width; +		wop->height = attr.height; +		xi->window = children[i]; +	    } +	} +	if (p_window == xi->window) +	    break; +    } +    wop->offset_x = OFFSET_X; +    for (i = 0; i < nchildren; i++) { +	XGetWindowAttributes(xi->display, children[i], &attr); +	if (attr.x <= 0 && attr.width < 30 && attr.height > wop->height * 0.7) { +	    /* scrollbar of xterm/kterm ? */ +	    wop->offset_x += attr.x + attr.width + attr.border_width * 2; +	    break; +	} +    } +    wop->offset_y = OFFSET_Y; + +    wop->priv = xi; + +    wop->init = x11_init; +    wop->finish = x11_finish; +    wop->active = x11_active; +    wop->set_background = x11_set_background; +    wop->sync = x11_sync; +    wop->close = x11_close; +    wop->clear = x11_clear; + +    wop->load_image = x11_load_image; +    wop->show_image = x11_show_image; +    wop->free_image = x11_free_image; +    wop->get_image_size = x11_get_image_size; + +    return wop; +  error: +    if (xi) +	free(xi); +    free(wop); +    return NULL; +} | 
