diff options
Diffstat (limited to 'w3mimg')
-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 |
17 files changed, 2265 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; +} |