diff options
Diffstat (limited to '')
| -rw-r--r-- | w3mimg/.cvsignore | 1 | ||||
| -rw-r--r-- | w3mimg/Makefile.in | 45 | ||||
| -rw-r--r-- | w3mimg/fb/.cvsignore | 1 | ||||
| -rw-r--r-- | w3mimg/fb/Makefile.in | 35 | ||||
| -rw-r--r-- | w3mimg/fb/fb.c | 663 | ||||
| -rw-r--r-- | w3mimg/fb/fb.h | 34 | ||||
| -rw-r--r-- | w3mimg/fb/fb_gdkpixbuf.c | 209 | ||||
| -rw-r--r-- | w3mimg/fb/fb_img.c | 32 | ||||
| -rw-r--r-- | w3mimg/fb/fb_img.h | 11 | ||||
| -rw-r--r-- | w3mimg/fb/fb_imlib2.c | 126 | ||||
| -rw-r--r-- | w3mimg/fb/fb_w3mimg.c | 202 | ||||
| -rw-r--r-- | w3mimg/fb/readme.txt | 73 | ||||
| -rw-r--r-- | w3mimg/w3mimg.c | 34 | ||||
| -rw-r--r-- | w3mimg/w3mimg.h | 46 | ||||
| -rw-r--r-- | w3mimg/x11/.cvsignore | 1 | ||||
| -rw-r--r-- | w3mimg/x11/Makefile.in | 29 | ||||
| -rw-r--r-- | w3mimg/x11/x11_w3mimg.c | 723 | ||||
| -rw-r--r-- | w3mimgdisplay.c | 340 | 
18 files changed, 2605 insertions, 0 deletions
| diff --git a/w3mimg/.cvsignore b/w3mimg/.cvsignore new file mode 100644 index 0000000..f3c7a7c --- /dev/null +++ b/w3mimg/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/w3mimg/Makefile.in b/w3mimg/Makefile.in new file mode 100644 index 0000000..a197352 --- /dev/null +++ b/w3mimg/Makefile.in @@ -0,0 +1,45 @@ +# +# w3mimg/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) +AR=ar +RANLIB=@RANLIB@ +RM=rm + +IMGCFLAGS=@IMGX11CFLAGS@ @IMGFBCFLAGS@ +IMGOBJS=@IMGOBJS@ + +.PHONY: fb x11 +all: @IMGTARGETS@ w3mimg.a + +w3mimg.a: $(IMGOBJS) +	$(AR) rv $@ $(IMGOBJS) +	$(RANLIB) $@ + +w3mimg.o: w3mimg.c +	$(CC) $(CFLAGS) -c $< + +fb x11: +	cd $@ && $(MAKE) CC="$(CC)" OPTS="$(OPTS)" + +clean: +	@-$(RM) -f *.o +	@for dir in fb x11; do \ +		(cd $$dir && $(MAKE) clean RM=$(RM)); \ +	 done +	-$(RM) -f w3mimg.a + +distclean: clean +	for subdir in fb x11; \ +	do \ +		(cd $$subdir && $(MAKE) distclean); \ +	done +	-$(RM) -f Makefile + + +# diff --git a/w3mimg/fb/.cvsignore b/w3mimg/fb/.cvsignore new file mode 100644 index 0000000..f3c7a7c --- /dev/null +++ b/w3mimg/fb/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/w3mimg/fb/Makefile.in b/w3mimg/fb/Makefile.in new file mode 100644 index 0000000..d3ee2e1 --- /dev/null +++ b/w3mimg/fb/Makefile.in @@ -0,0 +1,35 @@ +# +# w3mimg/fb/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=@IMGFBCFLAGS@ +OBJS=fb.o fb_img.o  + +all: fb_w3mimg.o fb.o fb_img.o + +fb_w3mimg.o: fb_w3mimg.c +	$(CC) $(CFLAGS) -c $< + +fb.o: fb.c +	$(CC) $(CFLAGS) -c $< + +fb_img.o: fb_img.c fb_gdkpixbuf.c fb_imlib2.c +	$(CC) $(CFLAGS) -c $< + +clean: +	@-$(RM) -f *.o + +distclean: clean +	-$(RM) -f Makefile + +# + + diff --git a/w3mimg/fb/fb.c b/w3mimg/fb/fb.c new file mode 100644 index 0000000..cd11128 --- /dev/null +++ b/w3mimg/fb/fb.c @@ -0,0 +1,663 @@ +/* $Id: fb.c,v 1.16 2003/07/13 16:19:10 ukai Exp $ */ +/************************************************************************** +                fb.c 0.3 Copyright (C) 2002, hito + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <limits.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <linux/fb.h> + +#include "fb.h" + +#define FB_ENV		"FRAMEBUFFER" +#define	FB_DEFDEV	"/dev/fb0" + +#define MONO_OFFSET_8BIT  0x40 +#define COLORS_MONO_8BIT  0x40 +#define MONO_MASK_8BIT    0xFC +#define MONO_SHIFT_8BIT   2 + +#define COLOR_OFFSET_8BIT 0x80 +#define COLORS_8BIT       0x80 +#define RED_MASK_8BIT     0xC0 +#define GREEN_MASK_8BIT   0xE0 +#define BLUE_MASK_8BIT    0xC0 +#define RED_SHIFT_8BIT    1 +#define GREEN_SHIFT_8BIT  3 +#define BLUE_SHIFT_8BIT   6 + +#define FALSE 0 +#define TRUE  1 + +#define IMAGE_SIZE_MAX 10000 + +static struct fb_cmap *fb_cmap_create(struct fb_fix_screeninfo *, +				      struct fb_var_screeninfo *); +static void fb_cmap_destroy(struct fb_cmap *cmap); +static int fb_fscrn_get(int fbfp, struct fb_fix_screeninfo *scinfo); +static void *fb_mmap(int fbfp, struct fb_fix_screeninfo *scinfo); +static int fb_munmap(void *buf, struct fb_fix_screeninfo *scinfo); +static int fb_vscrn_get(int fbfp, struct fb_var_screeninfo *scinfo); +static int fb_cmap_set(int fbfp, struct fb_cmap *cmap); +static int fb_cmap_get(int fbfp, struct fb_cmap *cmap); +static int fb_cmap_init(void); +static int fb_get_cmap_index(int r, int g, int b); +static unsigned long fb_get_packed_color(int r, int g, int b); + +static struct fb_fix_screeninfo fscinfo; +static struct fb_var_screeninfo vscinfo; +static struct fb_cmap *cmap = NULL, *cmap_org = NULL; +static int is_open = FALSE; +static int fbfp = -1; +static size_t pixel_size = 0; +static unsigned char *buf = NULL; + +int +fb_open(void) +{ +    char *fbdev = { FB_DEFDEV }; + +    if (is_open == TRUE) +	return 1; + +    if (getenv(FB_ENV)) { +	fbdev = getenv(FB_ENV); +    } + +    if ((fbfp = open(fbdev, O_RDWR)) == -1) { +	fprintf(stderr, "open %s error\n", fbdev); +	goto ERR_END; +    } + +    if (fb_fscrn_get(fbfp, &fscinfo)) { +	goto ERR_END; +    } + +    if (fb_vscrn_get(fbfp, &vscinfo)) { +	goto ERR_END; +    } + +    if ((cmap = fb_cmap_create(&fscinfo, &vscinfo)) == (struct fb_cmap *)-1) { +	goto ERR_END; +    } + +    if (!(buf = fb_mmap(fbfp, &fscinfo))) { +	fprintf(stderr, "Can't allocate memory.\n"); +	goto ERR_END; +    } + +    if (fscinfo.type != FB_TYPE_PACKED_PIXELS) { +	fprintf(stderr, "This type of framebuffer is not supported.\n"); +	goto ERR_END; +    } + +    if (fscinfo.visual == FB_VISUAL_PSEUDOCOLOR && vscinfo.bits_per_pixel == 8) { +	if (fb_cmap_get(fbfp, cmap)) { +	    fprintf(stderr, "Can't get color map.\n"); +	    fb_cmap_destroy(cmap); +	    cmap = NULL; +	    goto ERR_END; +	} + +	if (fb_cmap_init()) +	    goto ERR_END; + +	pixel_size = 1; +    } +    else if ((fscinfo.visual == FB_VISUAL_TRUECOLOR || +	      fscinfo.visual == FB_VISUAL_DIRECTCOLOR) && +	     (vscinfo.bits_per_pixel == 15 || +	      vscinfo.bits_per_pixel == 16 || +	      vscinfo.bits_per_pixel == 24 || vscinfo.bits_per_pixel == 32)) { +	pixel_size = (vscinfo.bits_per_pixel + 7) / CHAR_BIT; +    } +    else { +	fprintf(stderr, "This type of framebuffer is not supported.\n"); +	goto ERR_END; +    } + +    is_open = TRUE; +    return 0; + +  ERR_END: +    fb_close(); +    return 1; +} + +void +fb_close(void) +{ +    if (is_open != TRUE) +	return; + +    if (cmap != NULL) { +	fb_cmap_destroy(cmap); +	cmap = NULL; +    } +    if (cmap_org != NULL) { +	fb_cmap_set(fbfp, cmap_org); +	fb_cmap_destroy(cmap_org); +	cmap = NULL; +    } +    if (buf != NULL) { +	fb_munmap(buf, &fscinfo); +	buf = NULL; +    } + +    if (fbfp >= 0) { +	close(fbfp); +    } + +    is_open = FALSE; +} + +/***********   fb_image_*  ***********/ + +FB_IMAGE * +fb_image_new(int width, int height) +{ +    FB_IMAGE *image; + +    if (is_open != TRUE) +	return NULL; + +    if (width > IMAGE_SIZE_MAX || height > IMAGE_SIZE_MAX || width < 1 +	|| height < 1) +	return NULL; + +    image = malloc(sizeof(*image)); +    if (image == NULL) +	return NULL; + +    image->data = calloc(sizeof(*(image->data)), width * height * pixel_size); +    if (image->data == NULL) { +	free(image); +	return NULL; +    } + +    image->num = 1; +    image->id = 0; +    image->delay = 0; + +    image->width = width; +    image->height = height; +    image->rowstride = width * pixel_size; +    image->len = width * height * pixel_size; + +    return image; +} + +void +fb_image_free(FB_IMAGE * image) +{ +    if (image == NULL) +	return; + +    if (image->data != NULL) +	free(image->data); + +    free(image); +} + +void +fb_image_pset(FB_IMAGE * image, int x, int y, int r, int g, int b) +{ +    unsigned long work; + +    if (image == NULL || is_open != TRUE || x >= image->width +	|| y >= image->height) +	return; + +    work = fb_get_packed_color(r, g, b); +    memcpy(image->data + image->rowstride * y + pixel_size * x, &work, +	   pixel_size); +} + +void +fb_image_fill(FB_IMAGE * image, int r, int g, int b) +{ +    unsigned long work; +    int offset; + +    if (image == NULL || is_open != TRUE) +	return; + +    work = fb_get_packed_color(r, g, b); + +    for (offset = 0; offset < image->len; offset += pixel_size) { +	memcpy(image->data + offset, &work, pixel_size); +    } +} + +int +fb_image_draw(FB_IMAGE * image, int x, int y, int sx, int sy, int width, +	      int height) +{ +    int i, offset_fb, offset_img; + +    if (image == NULL || is_open != TRUE || +	sx > image->width || sy > image->height || +	x > fb_width() || y > fb_height()) +	return 1; + +    if (sx + width > image->width) +	width = image->width - sx; + +    if (sy + height > image->height) +	height = image->height - sy; + +    if (x + width > fb_width()) +	width = fb_width() - x; + +    if (y + height > fb_height()) +	height = fb_height() - y; + +    offset_fb = fscinfo.line_length * y + pixel_size * x; +    offset_img = image->rowstride * sy + pixel_size * sx; +    for (i = 0; i < height; i++) { +	memcpy(buf + offset_fb, image->data + offset_img, pixel_size * width); +	offset_fb += fscinfo.line_length; +	offset_img += image->rowstride; +    } + +    return 0; +} + +void +fb_image_copy(FB_IMAGE * dest, FB_IMAGE * src) +{ +    if (dest == NULL || src == NULL) +	return; + +    if (dest->len != src->len) +	return; + +    memcpy(dest->data, src->data, src->len); +} + +/***********   fb_frame_*  ***********/ + +FB_IMAGE ** +fb_frame_new(int w, int h, int n) +{ +    FB_IMAGE **frame; +    int i, error = 0; + +    if (w > IMAGE_SIZE_MAX || h > IMAGE_SIZE_MAX || w < 1 || h < 1 || n < 1) +	return NULL; + +    frame = malloc(sizeof(*frame) * n); +    if (frame == NULL) +	return NULL; + +    for (i = 0; i < n; i++) { +	frame[i] = fb_image_new(w, h); +	frame[i]->num = n; +	frame[i]->id = i; +	frame[i]->delay = 1000; +	if (frame[i] == NULL) +	    error = 1; +    } + +    if (error) { +	fb_frame_free(frame); +	return NULL; +    } + +    return frame; +} + + +void +fb_frame_free(FB_IMAGE ** frame) +{ +    int i, n; + +    if (frame == NULL) +	return; + +    n = frame[0]->num; +    for (i = 0; i < n; i++) { +	fb_image_free(frame[i]); +    } +    free(frame); +} + +int +fb_width(void) +{ +    if (is_open != TRUE) +	return 0; + +    return vscinfo.xres; +} + +int +fb_height(void) +{ +    if (is_open != TRUE) +	return 0; + +    return vscinfo.yres; +} + +int +fb_clear(int x, int y, int w, int h, int r, int g, int b) +{ +    int i, offset_fb; +    static int rr = -1, gg = -1, bb = -1; +    static char *tmp = NULL; + +    if (is_open != TRUE || x > fb_width() || y > fb_height()) +	return 1; + +    if (x < 0) +	x = 0; +    if (y < 0) +	y = 0; + +    if (x + w > fb_width()) +	w = fb_width() - x; +    if (y + h > fb_height()) +	h = fb_height() - y; + +    if (tmp == NULL) { +	tmp = malloc(fscinfo.line_length); +	if (tmp == NULL) +	    return 1; +    } +    if (rr != r || gg != g || bb != b) { +	unsigned long work; +	int ww = fb_width(); + +	work = fb_get_packed_color(r, g, b); +	for (i = 0; i < ww; i++) +	    memcpy(tmp + pixel_size * i, &work, pixel_size); +	rr = r; +	gg = g; +	bb = b; +    } +    offset_fb = fscinfo.line_length * y + pixel_size * x; +    for (i = 0; i < h; i++) { +	memcpy(buf + offset_fb, tmp, pixel_size * w); +	offset_fb += fscinfo.line_length; +    } +    return 0; +} + +/********* static functions **************/ +static unsigned long +fb_get_packed_color(int r, int g, int b) +{ +    if (pixel_size == 1) { +	return fb_get_cmap_index(r, g, b); +    } +    else { +	return +	    ((r >> (CHAR_BIT - vscinfo.red.length)) << vscinfo.red.offset) + +	    ((g >> (CHAR_BIT - vscinfo.green.length)) << vscinfo.green. +	     offset) + +	    ((b >> (CHAR_BIT - vscinfo.blue.length)) << vscinfo.blue.offset); +    } +} + +static int +fb_get_cmap_index(int r, int g, int b) +{ +    int work; +    if ((r & GREEN_MASK_8BIT) == (g & GREEN_MASK_8BIT) +	&& (g & GREEN_MASK_8BIT) == (b & GREEN_MASK_8BIT)) { +	work = (r >> MONO_SHIFT_8BIT) + MONO_OFFSET_8BIT; +    } +    else { +	work = ((r & RED_MASK_8BIT) >> RED_SHIFT_8BIT) +	    + ((g & GREEN_MASK_8BIT) >> GREEN_SHIFT_8BIT) +	    + ((b & BLUE_MASK_8BIT) >> BLUE_SHIFT_8BIT) +	    + COLOR_OFFSET_8BIT; +    } +    return work; +} + +static int +fb_cmap_init(void) +{ +    int lp; + +    if (cmap == NULL) +	return 1; + +    if (cmap->len < COLOR_OFFSET_8BIT + COLORS_8BIT) { +	fprintf(stderr, "Can't allocate enough color.\n"); +	return 1; +    } + +    if (cmap_org == NULL) { +	if ((cmap_org = +	     fb_cmap_create(&fscinfo, &vscinfo)) == (struct fb_cmap *)-1) { +	    return 1; +	} + +	if (fb_cmap_get(fbfp, cmap_org)) { +	    fprintf(stderr, "Can't get color map.\n"); +	    fb_cmap_destroy(cmap_org); +	    cmap_org = NULL; +	    return 1; +	} +    } + +    cmap->start = MONO_OFFSET_8BIT; +    cmap->len = COLORS_8BIT + COLORS_MONO_8BIT; + +    for (lp = 0; lp < COLORS_MONO_8BIT; lp++) { +	int c; +	c = (lp << (MONO_SHIFT_8BIT + 8)) + +	    (lp ? (0xFFFF - (MONO_MASK_8BIT << 8)) : 0); +	if (cmap->red) +	    *(cmap->red + lp) = c; +	if (cmap->green) +	    *(cmap->green + lp) = c; +	if (cmap->blue) +	    *(cmap->blue + lp) = c; +    } + +    for (lp = 0; lp < COLORS_8BIT; lp++) { +	int r, g, b; +	r = lp & (RED_MASK_8BIT >> RED_SHIFT_8BIT); +	g = lp & (GREEN_MASK_8BIT >> GREEN_SHIFT_8BIT); +	b = lp & (BLUE_MASK_8BIT >> BLUE_SHIFT_8BIT); +	if (cmap->red) +	    *(cmap->red + lp + COLORS_MONO_8BIT) +		= (r << (RED_SHIFT_8BIT + 8)) + +		(r ? (0xFFFF - (RED_MASK_8BIT << 8)) : 0); +	if (cmap->green) +	    *(cmap->green + lp + COLORS_MONO_8BIT) +		= (g << (GREEN_SHIFT_8BIT + 8)) + +		(g ? (0xFFFF - (GREEN_MASK_8BIT << 8)) : 0); +	if (cmap->blue) +	    *(cmap->blue + lp + COLORS_MONO_8BIT) +		= (b << (BLUE_SHIFT_8BIT + 8)) + +		(b ? (0xFFFF - (BLUE_MASK_8BIT << 8)) : 0); +    } + +    if (fb_cmap_set(fbfp, cmap)) { +	fb_cmap_destroy(cmap); +	cmap = NULL; +	fprintf(stderr, "Can't set color map.\n"); +	return 1; +    } +    return 0; +} + +/* + * (struct fb_cmap) Device independent colormap information. + *  + * fb_cmap_create()     create colormap information + * fb_cmap_destroy()    destroy colormap information + * fb_cmap_get()        get information + * fb_cmap_set()        set information + */ + +#define	LUT_MAX		(256) + +static struct fb_cmap * +fb_cmap_create(struct fb_fix_screeninfo *fscinfo, +	       struct fb_var_screeninfo *vscinfo) +{ +    struct fb_cmap *cmap; +    int cmaplen = LUT_MAX; + +    /* check the existence of colormap */ +    if (fscinfo->visual == FB_VISUAL_MONO01 || +	fscinfo->visual == FB_VISUAL_MONO10 || +	fscinfo->visual == FB_VISUAL_TRUECOLOR) +	return NULL; + +    cmap = (struct fb_cmap *)malloc(sizeof(struct fb_cmap)); +    if (!cmap) { +	perror("cmap malloc error\n"); +	return (struct fb_cmap *)-1; +    } +    memset(cmap, 0, sizeof(struct fb_cmap)); + +    /* Allocates memory for a colormap */ +    if (vscinfo->red.length) { +	cmap->red = (__u16 *) malloc(sizeof(__u16) * cmaplen); +	if (!cmap->red) { +	    perror("red lut malloc error\n"); +	    return (struct fb_cmap *)-1; +	} +    } +    if (vscinfo->green.length) { +	cmap->green = (__u16 *) malloc(sizeof(__u16) * cmaplen); +	if (!cmap->green) { +	    if (vscinfo->red.length) +		free(cmap->red); +	    perror("green lut malloc error\n"); +	    return (struct fb_cmap *)-1; +	} +    } +    if (vscinfo->blue.length) { +	cmap->blue = (__u16 *) malloc(sizeof(__u16) * cmaplen); +	if (!cmap->blue) { +	    if (vscinfo->red.length) +		free(cmap->red); +	    if (vscinfo->green.length) +		free(cmap->green); +	    perror("blue lut malloc error\n"); +	    return (struct fb_cmap *)-1; +	} +    } +    if (vscinfo->transp.length) { +	cmap->transp = (__u16 *) malloc(sizeof(__u16) * cmaplen); +	if (!cmap->transp) { +	    if (vscinfo->red.length) +		free(cmap->red); +	    if (vscinfo->green.length) +		free(cmap->green); +	    if (vscinfo->blue.length) +		free(cmap->blue); +	    perror("transp lut malloc error\n"); +	    return (struct fb_cmap *)-1; +	} +    } +    cmap->len = cmaplen; +    return cmap; +} + +static void +fb_cmap_destroy(struct fb_cmap *cmap) +{ +    if (cmap->red) +	free(cmap->red); +    if (cmap->green) +	free(cmap->green); +    if (cmap->blue) +	free(cmap->blue); +    if (cmap->transp) +	free(cmap->transp); +    free(cmap); +} + +static int +fb_cmap_get(int fbfp, struct fb_cmap *cmap) +{ +    if (ioctl(fbfp, FBIOGETCMAP, cmap)) { +	perror("ioctl FBIOGETCMAP error\n"); +	return -1; +    } +    return 0; +} + +static int +fb_cmap_set(int fbfp, struct fb_cmap *cmap) +{ +    if (ioctl(fbfp, FBIOPUTCMAP, cmap)) { +	perror("ioctl FBIOPUTCMAP error\n"); +	return -1; +    } +    return 0; +} + +/* + * access to framebuffer + *  + * fb_mmap()            map from framebuffer into memory + * fb_munmap()          deletes the mappings + */ + +static void * +fb_mmap(int fbfp, struct fb_fix_screeninfo *scinfo) +{ +    void *buf; +    if ((buf = (unsigned char *) +	 mmap(NULL, scinfo->smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfp, +	      (off_t) 0)) +	== MAP_FAILED) { +	perror("mmap error"); +	return NULL; +    } +    return buf; +} + +static int +fb_munmap(void *buf, struct fb_fix_screeninfo *scinfo) +{ +    return munmap(buf, scinfo->smem_len); +} + +/* + * (struct fb_fix_screeninfo) device independent fixed information + *  + * fb_fscrn_get()               get information + */ +static int +fb_fscrn_get(int fbfp, struct fb_fix_screeninfo *scinfo) +{ +    if (ioctl(fbfp, FBIOGET_FSCREENINFO, scinfo)) { +	perror("ioctl FBIOGET_FSCREENINFO error\n"); +	return -1; +    } +    return 0; +} + +/* + * (struct fb_var_screeninfo) device independent variable information + *  + * fb_vscrn_get()               get information + */ +static int +fb_vscrn_get(int fbfp, struct fb_var_screeninfo *scinfo) +{ +    if (ioctl(fbfp, FBIOGET_VSCREENINFO, scinfo)) { +	perror("ioctl FBIOGET_VSCREENINFO error\n"); +	return -1; +    } +    return 0; +} diff --git a/w3mimg/fb/fb.h b/w3mimg/fb/fb.h new file mode 100644 index 0000000..1138bb0 --- /dev/null +++ b/w3mimg/fb/fb.h @@ -0,0 +1,34 @@ +/* $Id: fb.h,v 1.7 2003/07/07 15:48:17 ukai Exp $ */ +#ifndef fb_header +#define fb_header +#include <linux/fb.h> + +typedef struct { +    int num; +    int id; +    int delay; +    int width; +    int height; +    int rowstride; +    int len; +    unsigned char *data; +} FB_IMAGE; + +FB_IMAGE *fb_image_new(int width, int height); +void fb_image_pset(FB_IMAGE * image, int x, int y, int r, int g, int b); +void fb_image_fill(FB_IMAGE * image, int r, int g, int b); +int fb_image_draw(FB_IMAGE * image, int x, int y, int sx, int sy, int width, +		  int height); +void fb_image_free(FB_IMAGE * image); +void fb_image_copy(FB_IMAGE * dest, FB_IMAGE * src); + +FB_IMAGE **fb_frame_new(int w, int h, int num); +void fb_frame_free(FB_IMAGE ** frame); + +int fb_open(void); +void fb_close(void); +int fb_width(void); +int fb_height(void); +int fb_clear(int x, int y, int w, int h, int r, int g, int b); + +#endif diff --git a/w3mimg/fb/fb_gdkpixbuf.c b/w3mimg/fb/fb_gdkpixbuf.c new file mode 100644 index 0000000..e615da6 --- /dev/null +++ b/w3mimg/fb/fb_gdkpixbuf.c @@ -0,0 +1,209 @@ +/* $Id: fb_gdkpixbuf.c,v 1.16 2003/06/13 15:03:35 ukai Exp $ */ +/************************************************************************** +                fb_gdkpixbuf.c 0.3 Copyright (C) 2002, hito + **************************************************************************/ + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include "fb.h" +#include "fb_img.h" + +static void draw(FB_IMAGE * img, int bg, int x, int y, int w, int h, +		 GdkPixbuf * pixbuf); +static GdkPixbuf *resize_image(GdkPixbuf * pixbuf, int width, int height); + +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; +} + +int +get_image_size(char *filename, int *w, int *h) +{ +    GdkPixbufAnimation *animation; +    if (filename == NULL) +	return 1; +    animation = gdk_pixbuf_animation_new_from_file(filename); +    if (animation == NULL) +	return 1; +    get_animation_size(animation, w, h, NULL); +    gdk_pixbuf_animation_unref(animation); +    return 0; +} + +FB_IMAGE ** +fb_image_load(char *filename, int w, int h, int max_anim) +{ +    GdkPixbufAnimation *animation; +    GList *frames; +    double ratio_w, ratio_h; +    int n, i, j, fw, fh, frame_num, delay; +    FB_IMAGE **fb_frame = NULL, *tmp_image = NULL; + +    if (filename == NULL) +	return NULL; +    animation = gdk_pixbuf_animation_new_from_file(filename); +    if (animation == NULL) +	return NULL; +    frames = gdk_pixbuf_animation_get_frames(animation); +    get_animation_size(animation, &fw, &fh, &delay); +    frame_num = n = gdk_pixbuf_animation_get_num_frames(animation); +    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 = fw; +	h = fh; +	ratio_w = ratio_h = 1; +    } +    else { +	ratio_w = 1.0 * w / fw; +	ratio_h = 1.0 * h / fh; +    } + +    fb_frame = fb_frame_new(w, h, frame_num); +    if (fb_frame == NULL) +	goto END; + +    tmp_image = fb_image_new(w, h); +    if (tmp_image == NULL) { +	fb_frame_free(fb_frame); +	fb_frame = NULL; +	goto END; +    } + +    if (bg_r != 0 || bg_g != 0 || bg_b != 0) { +	fb_image_fill(tmp_image, bg_r, bg_g, bg_b); +    } + +    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); +	width = gdk_pixbuf_get_width(org_pixbuf); +	height = gdk_pixbuf_get_height(org_pixbuf); +	if (ofstx == 0 && ofsty == 0 && width == fw && height == fh) { +	    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); + +	fb_frame[i]->delay = gdk_pixbuf_frame_get_delay_time(frame); +	fb_image_copy(fb_frame[i], tmp_image); +	draw(fb_frame[i], !i, ofstx, ofsty, width, height, pixbuf); + +	switch (gdk_pixbuf_frame_get_action(frame)) { +	case GDK_PIXBUF_FRAME_RETAIN: +	    fb_image_copy(tmp_image, fb_frame[i]); +	    break; +	case GDK_PIXBUF_FRAME_DISPOSE: +	    break; +	case GDK_PIXBUF_FRAME_REVERT: +	    fb_image_copy(tmp_image, fb_frame[0]); +	    break; +	default: +	    fb_image_copy(tmp_image, fb_frame[0]); +	} + +	if (org_pixbuf != pixbuf) +	    gdk_pixbuf_finalize(pixbuf); +    } +  END: +    if (tmp_image) +	fb_image_free(tmp_image); +    gdk_pixbuf_animation_unref(animation); +    return fb_frame; +} +static void +draw(FB_IMAGE * img, int bg, int x, int y, int w, int h, GdkPixbuf * pixbuf) +{ +    int i, j, r, g, b, offset, bpp, rowstride; +    guchar *pixels; +    gboolean alpha; +    if (img == NULL || pixbuf == NULL) +	return; +    rowstride = gdk_pixbuf_get_rowstride(pixbuf); +    pixels = gdk_pixbuf_get_pixels(pixbuf); +    alpha = gdk_pixbuf_get_has_alpha(pixbuf); +    bpp = rowstride / w; +    for (j = 0; j < h; j++) { +	offset = j * rowstride; +	for (i = 0; i < w; i++, offset += bpp) { +	    r = pixels[offset]; +	    g = pixels[offset + 1]; +	    b = pixels[offset + 2]; +	    if (!alpha || pixels[offset + 3] != 0) { +		fb_image_pset(img, i + x, j + y, r, g, b); +	    } +	} +    } +    return; +} +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_HYPER); +    if (resized_pixbuf == NULL) +	return NULL; +    return resized_pixbuf; +} diff --git a/w3mimg/fb/fb_img.c b/w3mimg/fb/fb_img.c new file mode 100644 index 0000000..3547a00 --- /dev/null +++ b/w3mimg/fb/fb_img.c @@ -0,0 +1,32 @@ +/* $Id: fb_img.c,v 1.6 2003/07/07 15:48:17 ukai Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include "config.h" +#include "fb.h" +#include "fb_img.h" + +static int bg_r = 0, bg_g = 0, bg_b = 0; + +#if defined(USE_IMLIB2) +#include "w3mimg/fb/fb_imlib2.c" +#elif defined(USE_GDKPIXBUF) +#include "w3mimg/fb/fb_gdkpixbuf.c" +#else +#error no Imlib2 and GdkPixbuf support +#endif + +void +fb_image_set_bg(int r, int g, int b) +{ +    bg_r = r; +    bg_g = g; +    bg_b = b; +} + +int +fb_image_clear(int x, int y, int w, int h) +{ +    return fb_clear(x, y, w, h, bg_r, bg_g, bg_b); +} diff --git a/w3mimg/fb/fb_img.h b/w3mimg/fb/fb_img.h new file mode 100644 index 0000000..cd1301b --- /dev/null +++ b/w3mimg/fb/fb_img.h @@ -0,0 +1,11 @@ +/* $Id: fb_img.h,v 1.8 2003/07/09 15:07:11 ukai Exp $ */ +#ifndef fb_img_header +#define fb_img_header +#include "fb.h" + +FB_IMAGE **fb_image_load(char *filename, int w, int h, int n); +void fb_image_set_bg(int r, int g, int b); +int fb_image_clear(int x, int y, int w, int h); +int get_image_size(char *filename, int *w, int *h); + +#endif diff --git a/w3mimg/fb/fb_imlib2.c b/w3mimg/fb/fb_imlib2.c new file mode 100644 index 0000000..972f06e --- /dev/null +++ b/w3mimg/fb/fb_imlib2.c @@ -0,0 +1,126 @@ +/* $Id: fb_imlib2.c,v 1.9 2003/03/24 15:45:59 ukai Exp $ */ +/************************************************************************** +                fb_imlib2.c 0.3 Copyright (C) 2002, hito + **************************************************************************/ + +#include <X11/Xlib.h> +#include <Imlib2.h> +#include "fb.h" +#include "fb_img.h" + +static void draw(FB_IMAGE * img, Imlib_Image image); +static Imlib_Image resize_image(Imlib_Image image, int width, int height); + +int +get_image_size(char *filename, int *w, int *h) +{ +    Imlib_Image image; + +    if (filename == NULL) +	return 1; + +    image = imlib_load_image(filename); +    if (image == NULL) +	return 1; + +    imlib_context_set_image(image); +    *w = imlib_image_get_width(); +    *h = imlib_image_get_height(); +    imlib_free_image(); + +    return 0; +} + +FB_IMAGE ** +fb_image_load(char *filename, int w, int h, int n) +{ +    Imlib_Image image; +    FB_IMAGE **frame; + +    if (filename == NULL) +	return NULL; + +    image = imlib_load_image(filename); +    if (image == NULL) +	return NULL; + +    image = resize_image(image, w, h); +    if (image == NULL) +	return NULL; + +    imlib_context_set_image(image); + +    w = imlib_image_get_width(); +    h = imlib_image_get_height(); + +    frame = fb_frame_new(w, h, 1); + +    if (frame == NULL) { +	imlib_free_image(); +	return NULL; +    } + +    draw(frame[0], image); + +    imlib_free_image(); + +    return frame; +} + +static void +draw(FB_IMAGE * img, Imlib_Image image) +{ +    int i, j, r, g, b, a = 0, offset; +    DATA32 *data; + +    if (img == NULL) +	return; + +    imlib_context_set_image(image); +    data = imlib_image_get_data_for_reading_only(); + +    for (j = 0; j < img->height; j++) { +	offset = img->width * j; +	for (i = 0; i < img->width; i++) { +	    a = (data[offset + i] >> 24) & 0x000000ff; +	    r = (data[offset + i] >> 16) & 0x000000ff; +	    g = (data[offset + i] >> 8) & 0x000000ff; +	    b = (data[offset + i]) & 0x000000ff; + +	    if (a == 0) { +		fb_image_pset(img, i, j, bg_r, bg_g, bg_b); +	    } +	    else { +		fb_image_pset(img, i, j, r, g, b); +	    } +	} +    } +    return; +} + +static Imlib_Image +resize_image(Imlib_Image image, int width, int height) +{ +    Imlib_Image resized_image; +    int w, h; + +    if (image == NULL) +	return NULL; + +    imlib_context_set_image(image); +    w = imlib_image_get_width(); +    h = imlib_image_get_height(); + +    if (width < 1 || height < 1) +	return image; + +    if (w == width && h == height) +	return image; + +    resized_image = +	imlib_create_cropped_scaled_image(0, 0, w, h, width, height); + +    imlib_free_image(); + +    return resized_image; +} diff --git a/w3mimg/fb/fb_w3mimg.c b/w3mimg/fb/fb_w3mimg.c new file mode 100644 index 0000000..b67bad1 --- /dev/null +++ b/w3mimg/fb/fb_w3mimg.c @@ -0,0 +1,202 @@ +/* $Id: fb_w3mimg.c,v 1.13 2003/08/29 15:06:52 ukai Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "w3mimg/fb/fb.h" +#include "w3mimg/fb/fb_img.h" +#include "w3mimg/w3mimg.h" + +static int +w3mfb_init(w3mimg_op * self) +{ +    if (self == NULL) +	return 0; +    return 1; +} + +static int +w3mfb_finish(w3mimg_op * self) +{ +    if (self == NULL) +	return 0; +    return 1; +} + +static int +w3mfb_active(w3mimg_op * self) +{ +    if (self == NULL) +	return 0; +    return 1; +} + +static void +w3mfb_set_background(w3mimg_op * self, char *background) +{ +    if (self == NULL) +	return; +    if (background) { +	int r, g, b; +	if (sscanf(background, "#%02x%02x%02x", &r, &g, &b) == 3) +	    fb_image_set_bg(r, g, b); +    } +} + +static void +w3mfb_sync(w3mimg_op * self) +{ +    return; +} + +static void +w3mfb_close(w3mimg_op * self) +{ +    fb_close(); +} + +static int +w3mfb_clear(w3mimg_op * self, int x, int y, int w, int h) +{ +    if (self == NULL) +	return 0; +    fb_image_clear(x, y, w, h); +    return 1; +} + +static int +w3mfb_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) +{ +    FB_IMAGE **im; + +    if (self == NULL) +	return 0; +    im = fb_image_load(fname, w, h, self->max_anim); +    if (!im) +	return 0; +    img->pixmap = im; +    img->width = im[0]->width; +    img->height = im[0]->height; +    return 1; +} + +static int +w3mfb_show_image(w3mimg_op * self, W3MImage * img, int sx, int sy, +		 int sw, int sh, int x, int y) +{ +    int i; +    FB_IMAGE **frame; +#define WAIT_CNT 4 + +    if (self == NULL) +	return 0; + +    if (img->pixmap == NULL) +	return 0; + +    frame = (FB_IMAGE **) img->pixmap; +    i = frame[0]->id; +    fb_image_draw(frame[i], +		  x + self->offset_x, y + self->offset_y, +		  sx, sy, (sw ? sw : img->width), (sh ? sh : img->height)); +    if (frame[0]->num > 1) { +	if (frame[1]->id > WAIT_CNT) { +	    frame[1]->id = 0; +	    if (i < frame[0]->num - 1) +		frame[0]->id = i + 1; +	    else +		frame[0]->id = 0; +	} +	frame[1]->id += 1; +    } +    return 1; +} + +static void +w3mfb_free_image(w3mimg_op * self, W3MImage * img) +{ +    if (self == NULL) +	return; +    if (img && img->pixmap) { +	fb_frame_free((FB_IMAGE **) img->pixmap); +	img->pixmap = NULL; +	img->width = 0; +	img->height = 0; +    } +} + +static int +w3mfb_get_image_size(w3mimg_op * self, W3MImage * img, +		     char *fname, int *w, int *h) +{ +    int i; + +    if (self == NULL) +	return 0; +    i = get_image_size(fname, w, h); +    if (i) +	return 0; +    return 1; +} + +#ifdef W3MIMGDISPLAY_SETUID +static int +check_tty_console(char *tty) +{ +    if (tty == NULL || *tty == '\0') +	return 0; +    if (strncmp(tty, "/dev/", 5) == 0) +	tty += 5; +    if (strncmp(tty, "tty", 3) == 0 && isdigit(*(tty + 3))) +	return 1; +    if (strncmp(tty, "vc/", 3) == 0 && isdigit(*(tty + 3))) +	return 1; +    return 0; +} +#else +#define check_tty_console(tty)	1 +#endif + +w3mimg_op * +w3mimg_fbopen() +{ +    w3mimg_op *wop = NULL; +    wop = (w3mimg_op *) malloc(sizeof(w3mimg_op)); +    if (wop == NULL) +	return NULL; +    memset(wop, 0, sizeof(w3mimg_op)); + +    if (!check_tty_console(getenv("W3M_TTY")) && strcmp("jfbterm", getenv("TERM")) != 0) { +	fprintf(stderr, "w3mimgdisplay/fb: tty is not console\n"); +	goto error; +    } + +    if (fb_open()) +	goto error; + +    wop->width = fb_width(); +    wop->height = fb_height(); + +    wop->init = w3mfb_init; +    wop->finish = w3mfb_finish; +    wop->active = w3mfb_active; +    wop->set_background = w3mfb_set_background; +    wop->sync = w3mfb_sync; +    wop->close = w3mfb_close; +    wop->clear = w3mfb_clear; + +    wop->load_image = w3mfb_load_image; +    wop->show_image = w3mfb_show_image; +    wop->free_image = w3mfb_free_image; +    wop->get_image_size = w3mfb_get_image_size; + +    return wop; +  error: +    free(wop); +    return NULL; +} diff --git a/w3mimg/fb/readme.txt b/w3mimg/fb/readme.txt new file mode 100644 index 0000000..92e71a5 --- /dev/null +++ b/w3mimg/fb/readme.txt @@ -0,0 +1,73 @@ +Source: http://homepage3.nifty.com/slokar/fb/ +original readme.txt + +■提供するもの +  ・w3mimgdisplayfb w3mimgdisplay (ほぼ)互換の framebuffer 用画像ビューア +  ・w3mimgsizefb    w3mimgsize 互換の画像サイズ報告プログラム + +■必要なもの +  ・GdkPixbuf or Imlib2 +  ・TRUE-COLOR の framebuffer を利用できる環境 + +■コンパイル +  ・Makefile の CFLAGS, LDFLAGS を Imlib2, GdkPixbuf のどちらか利用する +    方を有効にしてから make してださい。 + +■利用法 +  ・w3mimgdisplay, w3mimgsize と同様 + +■制限等 +  ・framebuffer は 15,16,24,32bpp PACKED-PIXELS TRUE-COLOR +    にしか対応していません。 +  ・現在 w3mimgdisplayfb は -bg オプションを使用しない場合の背景色は黒 +    (#000000)と仮定しています。 + +■開発環境 +  ・ w3m version w3m/0.3+cvs-1.353-m17n-20020316 +  ・ linux 2.4.18 (Vine Linux 2.5) +  ・ gcc 2.95.3 +  ・ GdkPixbuf 0.16.0 +  ・ Imlib2 1.0.6 +  ・ $ dmesg |grep vesafb +     vesafb: framebuffer at 0xe2000000, mapped to 0xc880d000, size 8192k +     vesafb: mode is 1024x768x16, linelength=2048, pages=4 +     vesafb: protected mode interface info at c000:4785 +     vesafb: scrolling: redraw +     vesafb: directcolor: size=0:5:6:5, shift=0:11:5:0 +  ・ ビデオカード +    VGA compatible controller: ATI Technologies Inc 3D Rage Pro AGP 1X/2X (rev 92). +      Master Capable.  Latency=64.  Min Gnt=8. +      Non-prefetchable 32 bit memory at 0xe2000000 [0xe2ffffff]. +      I/O at 0xd800 [0xd8ff]. +      Non-prefetchable 32 bit memory at 0xe1800000 [0xe1800fff]. + +■その他 +  ・w3mimgsizefb, w3mimgdisplayfb は坂本浩則さんの w3mimgsize, +    w3mimgdisplay をもとにしています(というかほとんどそのままです)。 +  ・framebuffer 描画関係のコードは、やまさきしんじさんのサンプルプログ +    ラムをもとにしています(というかほとんどそのままです)。 +  ・まだ開発途上であり、動作確認も不十分です。使用される際はご自身の責任 +    でお願いします。 +  ・この配布物に含まれるコードは変更済み BSD ライセンスに従うものとしま +    す。詳細は license.txt を参照してください。 + +■関連 URI +   ・ W3M Homepage  http://w3m.sourceforge.net/ +   ・ w3m-img http://www2u.biglobe.ne.jp/~hsaka/w3m/index-ja.html +   ・ Linux Kernel Hack Japan http://www.sainet.or.jp/~yamasaki/ +   ・ Imlib2 http://www.enlightenment.org/pages/main.html +   ・ GdkPixbuf http://developer.gnome.org/arch/imaging/gdkpixbuf.html + +■履歴 +  ・2002/07/05 開発開始 +  ・2002/07/07 ImageMagick 版動作確認 +  ・2002/07/10 GdkPixbuf 版動作確認 +  ・2002/07/11 Imlib2 版動作確認 +  ・2002/07/15 Version 0.1 +               公開 +  ・2002/07/22 Version 0.2 +               描画の高速化 + +■連絡先 +  ZXB01226@nifty.com +  http://homepage3.nifty.com/slokar/ diff --git a/w3mimg/w3mimg.c b/w3mimg/w3mimg.c new file mode 100644 index 0000000..144a2d9 --- /dev/null +++ b/w3mimg/w3mimg.c @@ -0,0 +1,34 @@ +/* $Id: w3mimg.c,v 1.5 2002/11/06 03:50:49 ukai Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include "w3mimg/w3mimg.h" + +w3mimg_op * +w3mimg_open() +{ +    w3mimg_op *w_op = NULL; +#ifdef W3MIMGDISPLAY_SETUID +    uid_t runner_uid = getuid(); +    uid_t owner_uid = geteuid(); +#endif +#ifdef USE_W3MIMG_X11 +#ifdef W3MIMGDISPLAY_SETUID +    /* run in user privileges */ +    setreuid(owner_uid, runner_uid); +#endif +    if (w_op == NULL) +	w_op = w3mimg_x11open(); +#ifdef W3MIMGDISPLAY_SETUID +    setreuid(runner_uid, owner_uid); +#endif +#endif +#ifdef USE_W3MIMG_FB +    /* run in setuid privileges */ +    if (w_op == NULL) +	w_op = w3mimg_fbopen(); +#endif +    return w_op; +} diff --git a/w3mimg/w3mimg.h b/w3mimg/w3mimg.h new file mode 100644 index 0000000..3807ca5 --- /dev/null +++ b/w3mimg/w3mimg.h @@ -0,0 +1,46 @@ +/* $Id: w3mimg.h,v 1.8 2003/07/13 16:19:10 ukai Exp $ */ +#include "config.h" + +#ifdef USE_W3MIMG_FB +#include "w3mimg/fb/fb.h" +#include "w3mimg/fb/fb_img.h" +#endif + +typedef struct { +    void *pixmap;		/* driver specific */ +    int width; +    int height; +} W3MImage; + +typedef struct _w3mimg_op { +    void *priv;			/* driver specific data */ +    int width, height;		/* window width, height */ +    int offset_x, offset_y;	/* offset */ +    int clear_margin; +    int max_anim; + +    int (*init) (struct _w3mimg_op * self); +    int (*finish) (struct _w3mimg_op * self); +    int (*active) (struct _w3mimg_op * self); +    void (*set_background) (struct _w3mimg_op * self, char *background); +    void (*sync) (struct _w3mimg_op * self); +    void (*close) (struct _w3mimg_op * self); + +    int (*load_image) (struct _w3mimg_op * self, W3MImage * img, char *fname, +		       int w, int h); +    int (*show_image) (struct _w3mimg_op * self, W3MImage * img, +		       int sx, int sy, int sw, int sh, int x, int y); +    void (*free_image) (struct _w3mimg_op * self, W3MImage * img); +    int (*get_image_size) (struct _w3mimg_op * self, W3MImage * img, +			   char *fname, int *w, int *h); +    int (*clear) (struct _w3mimg_op * self, int x, int y, int w, int h); +} w3mimg_op; + +#ifdef USE_W3MIMG_X11 +extern w3mimg_op *w3mimg_x11open(); +#endif +#ifdef USE_W3MIMG_FB +extern w3mimg_op *w3mimg_fbopen(); +#endif + +extern w3mimg_op *w3mimg_open(); 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; +} diff --git a/w3mimgdisplay.c b/w3mimgdisplay.c new file mode 100644 index 0000000..78550e5 --- /dev/null +++ b/w3mimgdisplay.c @@ -0,0 +1,340 @@ +/* $Id: w3mimgdisplay.c,v 1.18 2003/07/13 16:20:42 ukai Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include "config.h" +#include "w3mimg/w3mimg.h" + +w3mimg_op *w_op; +static char *background = NULL; +static int offset_x = 0, offset_y = 0; +static int defined_bg = 0, defined_x = 0, defined_y = 0, defined_test = 0; +static int defined_debug = 0; +static char *defined_size = NULL; + +#define MAX_IMAGE 1000 +static W3MImage *imageBuf = NULL; +static int maxImage = 0, maxAnim = 100, clearMargin = 0; + +static void GetOption(int argc, char **argv); +static void DrawImage(char *buf, int redraw); +static void TermImage(void); +static void ClearImage(char *buf); + +int +main(int argc, char **argv) +{ +    int len; +    char buf[1024 + 128]; +#ifdef W3MIMGDISPLAY_SETUID +    uid_t runner_uid = getuid(); +    uid_t owner_uid = geteuid(); + +    /* swap real and effective */ +    setreuid(owner_uid, runner_uid); +#endif +    GetOption(argc, argv); +    if (!defined_debug) +	freopen(DEV_NULL_PATH, "w", stderr); + +#ifdef W3MIMGDISPLAY_SETUID +    /*  +     * back real and effective +     * run w3mimg_open() in setuid privileges +     */ +    setreuid(runner_uid, owner_uid); +#endif +    w_op = w3mimg_open(); +#ifdef W3MIMGDISPLAY_SETUID +    /* make sure drop privileges now */ +    setreuid(runner_uid, runner_uid); +#endif +    if (w_op == NULL) +	exit(1); +    if (defined_x) +	w_op->offset_x = offset_x; +    if (defined_y) +	w_op->offset_y = offset_y; + +    w_op->max_anim = maxAnim; +    w_op->clear_margin = clearMargin; + +    if (defined_test) { +	printf("%d %d\n", w_op->width - w_op->offset_x, +	       w_op->height - w_op->offset_y); +	exit(0); +    } + +    if (defined_size) { +	if (w_op->init(w_op)) { +	    W3MImage img; +	    int w, h; +	    if (w_op->get_image_size(w_op, &img, defined_size, &w, &h)) +		printf("%d %d\n", w, h); +	} +	exit(0); +    } + +    w_op->set_background(w_op, background); + +    while (fgets(buf, sizeof(buf), stdin) != NULL) { +	if (!(isdigit(buf[0]) && buf[1] == ';')) { +	    fputc('\n', stdout); +	    fflush(stdout); +	    continue; +	} +	len = strlen(buf); +	if (buf[len - 1] == '\n') { +	    buf[--len] = '\0'; +	    if (buf[len - 1] == '\r') +		buf[--len] = '\0'; +	} +	/* +	 * w3mimg protocol +	 *  0  1  2 .... +	 * +--+--+--+--+ ...... +--+--+ +	 * |op|; |args             |\n| +	 * +--+--+--+--+ .......+--+--+ +	 * +	 * args is separeted by ';' +	 * op   args +	 *  0;  params          draw image +	 *  1;  params          redraw image +	 *  2;  -none-          terminate drawing +	 *  3;  -none-          sync drawing +	 *  4;  -none-          nop, sync communication +	 *                      response '\n' +	 *  5;  path            get size of image, +	 *                      response "<width> <height>\n" +	 *  6;  params(6)       clear image +	 * +	 * params +	 *      <n>;<x>;<y>;<w>;<h>;<sx>;<sy>;<sw>;<sh>;<path> +	 * params(6) +	 *      <x>;<y>;<w>;<h> +	 *    +	 */ +	switch (buf[0]) { +	case '0': +	    DrawImage(&buf[2], 0); +	    break; +	case '1': +	    DrawImage(&buf[2], 1); +	    break; +	case '2': +	    TermImage(); +	    break; +	case '3': +	    w_op->sync(w_op); +	    break; +	case '4': +	    fputs("\n", stdout); +	    fflush(stdout); +	    break; +	case '5': +	    if (w_op->init(w_op)) { +		W3MImage img; +		int w, h; +		if (w_op->get_image_size(w_op, &img, &buf[2], &w, &h)) { +		    fprintf(stdout, "%d %d\n", w, h); +		    fflush(stdout); +		} +		else { +		    fprintf(stdout, "\n"); +		    fflush(stdout); +		} +	    } +	    else { +		fprintf(stdout, "\n"); +		fflush(stdout); +	    } +	    break; +	case '6': +	    ClearImage(&buf[2]); +	    break; +	} +    } +    TermImage(); +    w_op->close(w_op); +    exit(0); +} + +static void +GetOption(int argc, char **argv) +{ +    int i; + +    for (i = 1; i < argc; i++) { +	if (!strcmp("-bg", argv[i])) { +	    if (++i >= argc) +		exit(1); +	    background = argv[i]; +	    defined_bg = 1; +	} +	else if (!strcmp("-x", argv[i])) { +	    if (++i >= argc) +		exit(1); +	    offset_x = atoi(argv[i]); +	    defined_x = 1; +	} +	else if (!strcmp("-y", argv[i])) { +	    if (++i >= argc) +		exit(1); +	    offset_y = atoi(argv[i]); +	    defined_y = 1; +	} +	else if (!strcmp("-test", argv[i])) { +	    defined_test = 1; +	} +	else if (!strcmp("-anim", argv[i])) { +	    if (++i >= argc) +		exit(1); +	    maxAnim = atoi(argv[i]); +	} +	else if (!strcmp("-margin", argv[i])) { +	    if (++i >= argc) +		exit(1); +	    clearMargin = atoi(argv[i]); +	    if (clearMargin < 0) +		clearMargin = 0; +	} +	else if (!strcmp("-size", argv[i])) { +	    if (++i >= argc) +		exit(1); +	    defined_size = argv[i]; +	} +	else if (!strcmp("-debug", argv[i])) { +	    defined_debug = 1; +	} +	else { +	    exit(1); +	} +    } +} + +void +DrawImage(char *buf, int redraw) +{ +    char *p = buf; +    int n = 0, x = 0, y = 0, w = 0, h = 0, sx = 0, sy = 0, sw = 0, sh = 0; + +    if (!p) +	return; +    for (; isdigit(*p); p++) +	n = 10 * n + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	x = 10 * x + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	y = 10 * y + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	w = 10 * w + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	h = 10 * h + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	sx = 10 * sx + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	sy = 10 * sy + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	sw = 10 * sw + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	sh = 10 * sh + (*p - '0'); +    if (*(p++) != ';') +	return; + +    n--; +    if (n < 0 || n >= MAX_IMAGE) +	return; +    if (redraw) { +	if (!w_op->active(w_op) || n >= maxImage || !imageBuf[n].pixmap) +	    return; +	goto draw_image; +    } +    w_op->init(w_op); + +    if (n >= maxImage) { +	int i = maxImage; +	maxImage = i ? (i * 2) : 2; +	if (maxImage > MAX_IMAGE) +	    maxImage = MAX_IMAGE; +	else if (n >= maxImage) +	    maxImage = n + 1; +	imageBuf = (W3MImage *) realloc((void *)imageBuf, +					sizeof(W3MImage) * maxImage); +	for (; i < maxImage; i++) +	    imageBuf[i].pixmap = NULL; +    } +    if (imageBuf[n].pixmap) { +	w_op->free_image(w_op, &imageBuf[n]); +	imageBuf[n].pixmap = NULL; +    } + +    if (w_op->load_image(w_op, &imageBuf[n], p, w, h) == 0) +	imageBuf[n].pixmap = NULL; + +  draw_image: +    if (imageBuf[n].pixmap) +	w_op->show_image(w_op, &imageBuf[n], sx, sy, sw, sh, x, y); +} + +void +TermImage(void) +{ +    w_op->finish(w_op); +    if (imageBuf) { +	int i; +	for (i = 0; i < maxImage; i++) { +	    w_op->free_image(w_op, &imageBuf[i]); +	} +	free(imageBuf); +	imageBuf = NULL; +    } +    maxImage = 0; +} + +void +ClearImage(char *buf) +{ +    char *p = buf; +    int x = 0, y = 0, w = 0, h = 0; + +    if (!p) +	return; +    for (; isdigit(*p); p++) +	x = 10 * x + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	y = 10 * y + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	w = 10 * w + (*p - '0'); +    if (*(p++) != ';') +	return; +    for (; isdigit(*p); p++) +	h = 10 * h + (*p - '0'); + +    w_op->clear(w_op, +		x + offset_x - w_op->clear_margin, +		y + offset_y - w_op->clear_margin, +		w + w_op->clear_margin * 2, h + w_op->clear_margin * 2); +} | 
