From 72f72d64a422d6628c4796f5c0bf2e508f134214 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:05:14 +0900 Subject: Adding upstream version 0.5.1 --- w3mimg/.cvsignore | 1 + w3mimg/Makefile.in | 45 +++ w3mimg/fb/.cvsignore | 1 + w3mimg/fb/Makefile.in | 35 +++ w3mimg/fb/fb.c | 663 +++++++++++++++++++++++++++++++++++++++++++ w3mimg/fb/fb.h | 34 +++ w3mimg/fb/fb_gdkpixbuf.c | 209 ++++++++++++++ w3mimg/fb/fb_img.c | 32 +++ w3mimg/fb/fb_img.h | 11 + w3mimg/fb/fb_imlib2.c | 126 +++++++++ w3mimg/fb/fb_w3mimg.c | 202 +++++++++++++ w3mimg/fb/readme.txt | 73 +++++ w3mimg/w3mimg.c | 34 +++ w3mimg/w3mimg.h | 46 +++ w3mimg/x11/.cvsignore | 1 + w3mimg/x11/Makefile.in | 29 ++ w3mimg/x11/x11_w3mimg.c | 723 +++++++++++++++++++++++++++++++++++++++++++++++ 17 files changed, 2265 insertions(+) create mode 100644 w3mimg/.cvsignore create mode 100644 w3mimg/Makefile.in create mode 100644 w3mimg/fb/.cvsignore create mode 100644 w3mimg/fb/Makefile.in create mode 100644 w3mimg/fb/fb.c create mode 100644 w3mimg/fb/fb.h create mode 100644 w3mimg/fb/fb_gdkpixbuf.c create mode 100644 w3mimg/fb/fb_img.c create mode 100644 w3mimg/fb/fb_img.h create mode 100644 w3mimg/fb/fb_imlib2.c create mode 100644 w3mimg/fb/fb_w3mimg.c create mode 100644 w3mimg/fb/readme.txt create mode 100644 w3mimg/w3mimg.c create mode 100644 w3mimg/w3mimg.h create mode 100644 w3mimg/x11/.cvsignore create mode 100644 w3mimg/x11/Makefile.in create mode 100644 w3mimg/x11/x11_w3mimg.c (limited to 'w3mimg') 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +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 +#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 +#include +#include +#include +#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 +#include +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#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 +#include +#include +#include "config.h" + +#if defined(USE_IMLIB) +#include +#elif defined(USE_IMLIB2) +#include +#include +#include +#elif defined(USE_GDKPIXBUF) +#include +#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; +} -- cgit v1.2.3 From 6db339b3d7a391f196e7c4b725a4ed0bd00f31cf Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:23:02 +0900 Subject: Adding upstream version 0.5.2 --- w3mimg/fb/fb_gdkpixbuf.c | 112 ++++++++++++++++++++++++++++++++++++++---- w3mimg/fb/fb_img.h | 3 +- w3mimg/fb/fb_imlib2.c | 8 ++- w3mimg/fb/fb_w3mimg.c | 6 ++- w3mimg/x11/x11_w3mimg.c | 124 +++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 232 insertions(+), 21 deletions(-) (limited to 'w3mimg') diff --git a/w3mimg/fb/fb_gdkpixbuf.c b/w3mimg/fb/fb_gdkpixbuf.c index e615da6..36e3b62 100644 --- a/w3mimg/fb/fb_gdkpixbuf.c +++ b/w3mimg/fb/fb_gdkpixbuf.c @@ -1,17 +1,51 @@ -/* $Id: fb_gdkpixbuf.c,v 1.16 2003/06/13 15:03:35 ukai Exp $ */ +/* $Id: fb_gdkpixbuf.c,v 1.21 2004/11/08 17:14:06 ukai Exp $ */ /************************************************************************** fb_gdkpixbuf.c 0.3 Copyright (C) 2002, hito **************************************************************************/ +#include "config.h" +#if defined(USE_GTK2) +#include +#include +#endif #include #include "fb.h" #include "fb_img.h" -static void draw(FB_IMAGE * img, int bg, int x, int y, int w, int h, +static void draw(FB_IMAGE * img, int x, int y, int w, int h, GdkPixbuf * pixbuf); static GdkPixbuf *resize_image(GdkPixbuf * pixbuf, int width, int height); -static void +#if defined(USE_GTK2) +static int +get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) +{ + GdkPixbufAnimationIter *iter; + int n, i, d = -1; + GTimeVal time; + + g_get_current_time(&time); + iter = gdk_pixbuf_animation_get_iter(animation, &time); + *w = gdk_pixbuf_animation_get_width(animation); + *h = gdk_pixbuf_animation_get_height(animation); + for (i = 1; + gdk_pixbuf_animation_iter_on_currently_loading_frame(iter) != TRUE; + i++) { + int tmp; + tmp = gdk_pixbuf_animation_iter_get_delay_time(iter); + g_time_val_add(&time, tmp * 1000); + if (tmp > d) + d = tmp; + gdk_pixbuf_animation_iter_advance(iter, &time); + } + if (delay) + *delay = d; + n = i; + g_object_unref(G_OBJECT(iter)); + return n; +} +#else +static int get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) { GList *frames; @@ -42,6 +76,16 @@ get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) } if (delay) *delay = d; + return n; +} +#endif + +void +fb_image_init() +{ +#if defined(USE_GTK2) + g_type_init(); +#endif } int @@ -50,11 +94,19 @@ get_image_size(char *filename, int *w, int *h) GdkPixbufAnimation *animation; if (filename == NULL) return 1; +#if defined(USE_GTK2) + animation = gdk_pixbuf_animation_new_from_file(filename, NULL); +#else animation = gdk_pixbuf_animation_new_from_file(filename); +#endif if (animation == NULL) return 1; get_animation_size(animation, w, h, NULL); +#if defined(USE_GTK2) + g_object_unref(G_OBJECT(animation)); +#else gdk_pixbuf_animation_unref(animation); +#endif return 0; } @@ -62,19 +114,27 @@ FB_IMAGE ** fb_image_load(char *filename, int w, int h, int max_anim) { GdkPixbufAnimation *animation; +#if defined(USE_GTK2) + GdkPixbufAnimationIter *iter; + GTimeVal time; +#else + int i; GList *frames; +#endif double ratio_w, ratio_h; - int n, i, j, fw, fh, frame_num, delay; + int n, j, fw, fh, frame_num, delay; FB_IMAGE **fb_frame = NULL, *tmp_image = NULL; if (filename == NULL) return NULL; +#if defined(USE_GTK2) + animation = gdk_pixbuf_animation_new_from_file(filename, NULL); +#else animation = gdk_pixbuf_animation_new_from_file(filename); +#endif 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); + frame_num = n = get_animation_size(animation, &fw, &fh, &delay); if (delay <= 0) max_anim = -1; if (max_anim < 0) { @@ -108,6 +168,34 @@ fb_image_load(char *filename, int w, int h, int max_anim) fb_image_fill(tmp_image, bg_r, bg_g, bg_b); } +#if defined(USE_GTK2) + g_get_current_time(&time); + iter = gdk_pixbuf_animation_get_iter(animation, &time); + + if (max_anim < 0 && n > -max_anim) { + max_anim = n + max_anim; + for (j = 0; j < max_anim; j++) { + g_time_val_add(&time, + gdk_pixbuf_animation_iter_get_delay_time(iter) * 1000); + gdk_pixbuf_animation_iter_advance(iter, &time); + } + } + for (j = 0; j < n; j++) { + GdkPixbuf *org_pixbuf, *pixbuf; + + org_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter); + pixbuf = resize_image(org_pixbuf, w, h); + + fb_frame[j]->delay = gdk_pixbuf_animation_iter_get_delay_time(iter); + g_time_val_add(&time, fb_frame[j]->delay * 1000); + draw(fb_frame[j], 0, 0, w, h, pixbuf); + if (org_pixbuf != pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + gdk_pixbuf_animation_iter_advance(iter, &time); + } +#else + frames = gdk_pixbuf_animation_get_frames(animation); + for (j = 0; j < n; j++) { GdkPixbufFrame *frame; GdkPixbuf *org_pixbuf, *pixbuf; @@ -139,13 +227,14 @@ fb_image_load(char *filename, int w, int h, int max_anim) 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); + draw(fb_frame[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: + fb_image_fill(tmp_image, bg_r, bg_g, bg_b); break; case GDK_PIXBUF_FRAME_REVERT: fb_image_copy(tmp_image, fb_frame[0]); @@ -157,14 +246,19 @@ fb_image_load(char *filename, int w, int h, int max_anim) if (org_pixbuf != pixbuf) gdk_pixbuf_finalize(pixbuf); } +#endif END: if (tmp_image) fb_image_free(tmp_image); +#if defined(USE_GTK2) + g_object_unref(G_OBJECT(animation)); +#else gdk_pixbuf_animation_unref(animation); +#endif return fb_frame; } static void -draw(FB_IMAGE * img, int bg, int x, int y, int w, int h, GdkPixbuf * pixbuf) +draw(FB_IMAGE * img, int x, int y, int w, int h, GdkPixbuf * pixbuf) { int i, j, r, g, b, offset, bpp, rowstride; guchar *pixels; diff --git a/w3mimg/fb/fb_img.h b/w3mimg/fb/fb_img.h index cd1301b..acdb5a0 100644 --- a/w3mimg/fb/fb_img.h +++ b/w3mimg/fb/fb_img.h @@ -1,8 +1,9 @@ -/* $Id: fb_img.h,v 1.8 2003/07/09 15:07:11 ukai Exp $ */ +/* $Id: fb_img.h,v 1.9 2004/08/04 17:32:28 ukai Exp $ */ #ifndef fb_img_header #define fb_img_header #include "fb.h" +void fb_image_init(); 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); diff --git a/w3mimg/fb/fb_imlib2.c b/w3mimg/fb/fb_imlib2.c index 972f06e..ea36637 100644 --- a/w3mimg/fb/fb_imlib2.c +++ b/w3mimg/fb/fb_imlib2.c @@ -1,4 +1,4 @@ -/* $Id: fb_imlib2.c,v 1.9 2003/03/24 15:45:59 ukai Exp $ */ +/* $Id: fb_imlib2.c,v 1.10 2004/08/04 17:32:28 ukai Exp $ */ /************************************************************************** fb_imlib2.c 0.3 Copyright (C) 2002, hito **************************************************************************/ @@ -11,6 +11,12 @@ static void draw(FB_IMAGE * img, Imlib_Image image); static Imlib_Image resize_image(Imlib_Image image, int width, int height); +void +fb_image_init() +{ + return; +} + int get_image_size(char *filename, int *w, int *h) { diff --git a/w3mimg/fb/fb_w3mimg.c b/w3mimg/fb/fb_w3mimg.c index b67bad1..d3ae5a9 100644 --- a/w3mimg/fb/fb_w3mimg.c +++ b/w3mimg/fb/fb_w3mimg.c @@ -1,4 +1,4 @@ -/* $Id: fb_w3mimg.c,v 1.13 2003/08/29 15:06:52 ukai Exp $ */ +/* $Id: fb_w3mimg.c,v 1.14 2004/08/04 17:32:28 ukai Exp $ */ #include #include #include @@ -17,6 +17,7 @@ w3mfb_init(w3mimg_op * self) { if (self == NULL) return 0; + /* XXX */ return 1; } @@ -195,6 +196,9 @@ w3mimg_fbopen() wop->free_image = w3mfb_free_image; wop->get_image_size = w3mfb_get_image_size; + /* XXX */ + fb_image_init(); + return wop; error: free(wop); diff --git a/w3mimg/x11/x11_w3mimg.c b/w3mimg/x11/x11_w3mimg.c index 8c9cef2..f5be4a8 100644 --- a/w3mimg/x11/x11_w3mimg.c +++ b/w3mimg/x11/x11_w3mimg.c @@ -1,6 +1,7 @@ -/* $Id: x11_w3mimg.c,v 1.25 2003/07/13 16:19:10 ukai Exp $ */ +/* $Id: x11_w3mimg.c,v 1.29 2004/11/08 17:14:06 ukai Exp $ */ #include #include +#include #include #include "config.h" @@ -11,7 +12,13 @@ #include #include #elif defined(USE_GDKPIXBUF) +#if defined(USE_GTK2) +#include +#include +#include +#else #include +#endif #else #error no Imlib and GdkPixbuf support #endif @@ -42,7 +49,36 @@ struct x11_image { Pixmap *pixmap; }; -static void +#if defined(USE_GTK2) +static int +get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) +{ + GdkPixbufAnimationIter *iter; + int n, i, d = -1; + GTimeVal time; + + g_get_current_time(&time); + iter = gdk_pixbuf_animation_get_iter(animation, &time); + *w = gdk_pixbuf_animation_get_width(animation); + *h = gdk_pixbuf_animation_get_height(animation); + for (i = 1; + gdk_pixbuf_animation_iter_on_currently_loading_frame(iter) != TRUE; + i++) { + int tmp; + tmp = gdk_pixbuf_animation_iter_get_delay_time(iter); + g_time_val_add(&time, tmp * 1000); + if (tmp > d) + d = tmp; + gdk_pixbuf_animation_iter_advance(iter, &time); + } + if (delay) + *delay = d; + g_object_unref(G_OBJECT(iter)); + n = i; + return n; +} +#else +static int get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) { GList *frames; @@ -73,8 +109,9 @@ get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) } if (delay) *delay = d; + return n; } - +#endif #endif static int @@ -94,6 +131,9 @@ x11_init(w3mimg_op * self) } #elif defined(USE_GDKPIXBUF) if (!xi->init_flag) { +#if defined(USE_GTK2) + g_type_init(); +#endif gdk_pixbuf_xlib_init(xi->display, 0); xi->init_flag = TRUE; } @@ -290,11 +330,17 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) Imlib_Image im; #elif defined(USE_GDKPIXBUF) GdkPixbufAnimation *animation; - GList *frames; - int i, j, iw, ih, n, frame_num, delay, max_anim; + int j, iw, ih, n, frame_num, delay = -1, max_anim; double ratio_w, ratio_h; struct x11_image *ximg; Pixmap tmp_pixmap; +#if defined(USE_GTK2) + GdkPixbufAnimationIter *iter; + GTimeVal time; +#else + int i; + GList *frames; +#endif #endif if (self == NULL) @@ -342,13 +388,14 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) imlib_free_image(); #elif defined(USE_GDKPIXBUF) max_anim = self->max_anim; +#if defined(USE_GTK2) + animation = gdk_pixbuf_animation_new_from_file(fname, NULL); +#else animation = gdk_pixbuf_animation_new_from_file(fname); +#endif 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); + frame_num = n = get_animation_size(animation, &iw, &ih, &delay); if (delay <= 0) max_anim = -1; @@ -370,17 +417,64 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) } tmp_pixmap = XCreatePixmap(xi->display, xi->parent, w, h, DefaultDepth(xi->display, 0)); + XSetForeground(xi->display, xi->imageGC, xi->background_pixel); XFillRectangle(xi->display, (Pixmap) tmp_pixmap, xi->imageGC, 0, 0, w, h); if (!tmp_pixmap) { +#if defined(USE_GTK2) + g_object_unref(G_OBJECT(animation)); +#else gdk_pixbuf_animation_unref(animation); +#endif return 0; } ximg = x11_img_new(xi, w, h, frame_num); if (!ximg) { XFreePixmap(xi->display, tmp_pixmap); +#if defined(USE_GTK2) + g_object_unref(G_OBJECT(animation)); +#else gdk_pixbuf_animation_unref(animation); +#endif return 0; } +#if defined(USE_GTK2) + g_get_current_time(&time); + iter = gdk_pixbuf_animation_get_iter(animation, &time); + + if (max_anim < 0 && n > -max_anim) { + max_anim = n + max_anim; + for (j = 0; j < max_anim; j++) { + delay = gdk_pixbuf_animation_iter_get_delay_time(iter); + g_time_val_add(&time, delay * 1000); + gdk_pixbuf_animation_iter_advance(iter, &time); + } + } + for (j = 0; j < frame_num; j++) { + GdkPixbuf *org_pixbuf, *pixbuf; + + org_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter); + delay = gdk_pixbuf_animation_iter_get_delay_time(iter); + pixbuf = resize_image(org_pixbuf, w, h); + + if (delay > ximg->delay) + ximg->delay = delay; + + gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, + (Drawable) ximg->pixmap[j], 0, + 0, 0, 0, w, h, + GDK_PIXBUF_ALPHA_BILEVEL, 1, + XLIB_RGB_DITHER_NORMAL, 0, 0); + if (org_pixbuf != pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + g_time_val_add(&time, delay * 1000); + gdk_pixbuf_animation_iter_advance(iter, &time); + } + XFreePixmap(xi->display, tmp_pixmap); + g_object_unref(G_OBJECT(animation)); + +#else + frames = gdk_pixbuf_animation_get_frames(animation); + for (j = 0; j < n; j++) { GdkPixbufFrame *frame; GdkPixbuf *org_pixbuf, *pixbuf; @@ -430,6 +524,9 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) xi->imageGC, 0, 0, w, h, 0, 0); break; case GDK_PIXBUF_FRAME_DISPOSE: + XSetForeground(xi->display, xi->imageGC, xi->background_pixel); + XFillRectangle(xi->display, tmp_pixmap, xi->imageGC, + 0, 0, w, h); break; case GDK_PIXBUF_FRAME_REVERT: XCopyArea(xi->display, ximg->pixmap[0], tmp_pixmap, @@ -448,6 +545,7 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) } XFreePixmap(xi->display, tmp_pixmap); gdk_pixbuf_animation_unref(animation); +#endif img->pixmap = ximg; #endif @@ -577,12 +675,20 @@ x11_get_image_size(w3mimg_op * self, W3MImage * img, char *fname, int *w, *h = imlib_image_get_height(); imlib_free_image(); #elif defined(USE_GDKPIXBUF) +#if defined(USE_GTK2) + animation = gdk_pixbuf_animation_new_from_file(fname, NULL); +#else animation = gdk_pixbuf_animation_new_from_file(fname); +#endif if (!animation) return 0; get_animation_size(animation, w, h, NULL); +#if defined(USE_GTK2) + g_object_unref(G_OBJECT(animation)); +#else gdk_pixbuf_animation_unref(animation); +#endif #endif return 1; } -- cgit v1.2.3 From 5397d09e585a1938fb64bc9c5cd5daed1959eb90 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:41:45 +0900 Subject: Adding upstream version 0.5.3 --- w3mimg/CVS/Entries | 7 + w3mimg/CVS/Repository | 1 + w3mimg/CVS/Root | 1 + w3mimg/Makefile.in | 11 +- w3mimg/fb/CVS/Entries | 11 + w3mimg/fb/CVS/Repository | 1 + w3mimg/fb/CVS/Root | 1 + w3mimg/w3mimg.c | 6 +- w3mimg/w3mimg.h | 17 +- w3mimg/win/.cvsignore | 1 + w3mimg/win/CVS/Entries | 4 + w3mimg/win/CVS/Repository | 1 + w3mimg/win/CVS/Root | 1 + w3mimg/win/Makefile.in | 31 ++ w3mimg/win/win_w3mimg.cpp | 982 ++++++++++++++++++++++++++++++++++++++++++++++ w3mimg/x11/CVS/Entries | 4 + w3mimg/x11/CVS/Repository | 1 + w3mimg/x11/CVS/Root | 1 + 18 files changed, 1075 insertions(+), 7 deletions(-) create mode 100644 w3mimg/CVS/Entries create mode 100644 w3mimg/CVS/Repository create mode 100644 w3mimg/CVS/Root create mode 100644 w3mimg/fb/CVS/Entries create mode 100644 w3mimg/fb/CVS/Repository create mode 100644 w3mimg/fb/CVS/Root create mode 100644 w3mimg/win/.cvsignore create mode 100644 w3mimg/win/CVS/Entries create mode 100644 w3mimg/win/CVS/Repository create mode 100644 w3mimg/win/CVS/Root create mode 100644 w3mimg/win/Makefile.in create mode 100644 w3mimg/win/win_w3mimg.cpp create mode 100644 w3mimg/x11/CVS/Entries create mode 100644 w3mimg/x11/CVS/Repository create mode 100644 w3mimg/x11/CVS/Root (limited to 'w3mimg') diff --git a/w3mimg/CVS/Entries b/w3mimg/CVS/Entries new file mode 100644 index 0000000..ad83b16 --- /dev/null +++ b/w3mimg/CVS/Entries @@ -0,0 +1,7 @@ +/.cvsignore/1.1/Mon Sep 22 22:53:53 2003// +D/fb//// +D/x11//// +/Makefile.in/1.11/Tue Jan 4 09:22:28 2011// +/w3mimg.c/1.6/Tue Jan 4 09:22:28 2011// +/w3mimg.h/1.9/Tue Jan 4 09:22:28 2011// +D/win//// diff --git a/w3mimg/CVS/Repository b/w3mimg/CVS/Repository new file mode 100644 index 0000000..d59666d --- /dev/null +++ b/w3mimg/CVS/Repository @@ -0,0 +1 @@ +w3m/w3mimg diff --git a/w3mimg/CVS/Root b/w3mimg/CVS/Root new file mode 100644 index 0000000..121fa06 --- /dev/null +++ b/w3mimg/CVS/Root @@ -0,0 +1 @@ +:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m diff --git a/w3mimg/Makefile.in b/w3mimg/Makefile.in index a197352..dfc550c 100644 --- a/w3mimg/Makefile.in +++ b/w3mimg/Makefile.in @@ -11,10 +11,11 @@ AR=ar RANLIB=@RANLIB@ RM=rm -IMGCFLAGS=@IMGX11CFLAGS@ @IMGFBCFLAGS@ +SUBDIRS=fb x11 win +IMGCFLAGS=@IMGX11CFLAGS@ @IMGFBCFLAGS@ @IMGWINCFLAGS@ IMGOBJS=@IMGOBJS@ -.PHONY: fb x11 +.PHONY: $(SUBDIRS) all: @IMGTARGETS@ w3mimg.a w3mimg.a: $(IMGOBJS) @@ -24,18 +25,18 @@ w3mimg.a: $(IMGOBJS) w3mimg.o: w3mimg.c $(CC) $(CFLAGS) -c $< -fb x11: +$(SUBDIRS): cd $@ && $(MAKE) CC="$(CC)" OPTS="$(OPTS)" clean: @-$(RM) -f *.o - @for dir in fb x11; do \ + @for dir in $(SUBDIRS); do \ (cd $$dir && $(MAKE) clean RM=$(RM)); \ done -$(RM) -f w3mimg.a distclean: clean - for subdir in fb x11; \ + for subdir in $(SUBDIRS); \ do \ (cd $$subdir && $(MAKE) distclean); \ done diff --git a/w3mimg/fb/CVS/Entries b/w3mimg/fb/CVS/Entries new file mode 100644 index 0000000..549e962 --- /dev/null +++ b/w3mimg/fb/CVS/Entries @@ -0,0 +1,11 @@ +/.cvsignore/1.1/Mon Sep 22 22:53:53 2003// +/Makefile.in/1.4/Mon Apr 26 17:00:38 2004// +/fb.c/1.16/Sun Jul 13 16:19:10 2003// +/fb.h/1.7/Mon Jul 7 15:48:17 2003// +/fb_gdkpixbuf.c/1.21/Mon Nov 8 17:14:06 2004// +/fb_img.c/1.6/Mon Jul 7 15:48:17 2003// +/fb_img.h/1.9/Wed Aug 4 17:32:28 2004// +/fb_imlib2.c/1.10/Wed Aug 4 17:32:28 2004// +/fb_w3mimg.c/1.14/Wed Aug 4 17:32:28 2004// +/readme.txt/1.2/Mon Jul 22 16:17:32 2002// +D diff --git a/w3mimg/fb/CVS/Repository b/w3mimg/fb/CVS/Repository new file mode 100644 index 0000000..336666e --- /dev/null +++ b/w3mimg/fb/CVS/Repository @@ -0,0 +1 @@ +w3m/w3mimg/fb diff --git a/w3mimg/fb/CVS/Root b/w3mimg/fb/CVS/Root new file mode 100644 index 0000000..121fa06 --- /dev/null +++ b/w3mimg/fb/CVS/Root @@ -0,0 +1 @@ +:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m diff --git a/w3mimg/w3mimg.c b/w3mimg/w3mimg.c index 144a2d9..46b5cac 100644 --- a/w3mimg/w3mimg.c +++ b/w3mimg/w3mimg.c @@ -1,4 +1,4 @@ -/* $Id: w3mimg.c,v 1.5 2002/11/06 03:50:49 ukai Exp $ */ +/* $Id: w3mimg.c,v 1.6 2010/12/21 10:13:55 htrb Exp $ */ #include #include @@ -14,6 +14,10 @@ w3mimg_open() uid_t runner_uid = getuid(); uid_t owner_uid = geteuid(); #endif +#ifdef USE_W3MIMG_WIN + if (w_op == NULL) + w_op = w3mimg_winopen(); +#endif #ifdef USE_W3MIMG_X11 #ifdef W3MIMGDISPLAY_SETUID /* run in user privileges */ diff --git a/w3mimg/w3mimg.h b/w3mimg/w3mimg.h index 3807ca5..f6415a9 100644 --- a/w3mimg/w3mimg.h +++ b/w3mimg/w3mimg.h @@ -1,6 +1,13 @@ -/* $Id: w3mimg.h,v 1.8 2003/07/13 16:19:10 ukai Exp $ */ +/* $Id: w3mimg.h,v 1.9 2010/12/21 10:13:55 htrb Exp $ */ +#ifndef W3MIMG_W3MIMG_H +#define W3MIMG_W3MIMG_H + #include "config.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifdef USE_W3MIMG_FB #include "w3mimg/fb/fb.h" #include "w3mimg/fb/fb_img.h" @@ -42,5 +49,13 @@ extern w3mimg_op *w3mimg_x11open(); #ifdef USE_W3MIMG_FB extern w3mimg_op *w3mimg_fbopen(); #endif +#ifdef USE_W3MIMG_WIN +extern w3mimg_op *w3mimg_winopen(); +#endif extern w3mimg_op *w3mimg_open(); + +#ifdef __cplusplus +} +#endif +#endif /* W3MIMG_W3MIMG_H */ diff --git a/w3mimg/win/.cvsignore b/w3mimg/win/.cvsignore new file mode 100644 index 0000000..f3c7a7c --- /dev/null +++ b/w3mimg/win/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/w3mimg/win/CVS/Entries b/w3mimg/win/CVS/Entries new file mode 100644 index 0000000..5025b4b --- /dev/null +++ b/w3mimg/win/CVS/Entries @@ -0,0 +1,4 @@ +/Makefile.in/1.1/Tue Dec 21 10:13:55 2010// +/win_w3mimg.cpp/1.2/Fri Dec 24 09:52:06 2010// +/.cvsignore/1.1/Wed Jan 5 09:52:10 2011// +D diff --git a/w3mimg/win/CVS/Repository b/w3mimg/win/CVS/Repository new file mode 100644 index 0000000..06901a3 --- /dev/null +++ b/w3mimg/win/CVS/Repository @@ -0,0 +1 @@ +w3m/w3mimg/win diff --git a/w3mimg/win/CVS/Root b/w3mimg/win/CVS/Root new file mode 100644 index 0000000..121fa06 --- /dev/null +++ b/w3mimg/win/CVS/Root @@ -0,0 +1 @@ +:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m diff --git a/w3mimg/win/Makefile.in b/w3mimg/win/Makefile.in new file mode 100644 index 0000000..b760a3d --- /dev/null +++ b/w3mimg/win/Makefile.in @@ -0,0 +1,31 @@ +# +# w3mimg/win/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 +CC=@CC@ +CXX=@CXX@ + +IMGCFLAGS=@IMGWINCFLAGS@ +OBJS=win_w3mimg.o + +all: win_w3mimg.o + +win_w3mimg.o: win_w3mimg.cpp + $(CXX) $(CFLAGS) -c $< + +clean: + @-$(RM) -f *.o + +distclean: clean + -$(RM) -f Makefile + +# + + diff --git a/w3mimg/win/win_w3mimg.cpp b/w3mimg/win/win_w3mimg.cpp new file mode 100644 index 0000000..8099860 --- /dev/null +++ b/w3mimg/win/win_w3mimg.cpp @@ -0,0 +1,982 @@ +/* $Id: win_w3mimg.cpp,v 1.2 2010/12/24 09:52:06 htrb Exp $ */ +#include +#include +#include +#include +#include "config.h" +#include +#include + +#include +#include + +#include "w3mimg/w3mimg.h" +#include +#include +#include +#include +/* GDI+ can handle BMP, GIF, JPEG, PNG and TIFF by itself. */ + +#define OFFSET_X 2 +#define OFFSET_Y 2 +#define DEBUG + +#ifdef DEBUG +#define THROW_NONE throw() +#else +#define THROW_NONE +#endif + +struct win_info { + HWND window; + Gdiplus::ARGB background_pixel; + ULONG_PTR gdiplus_token; + FILE *logfile; +}; + +struct window_list { + HWND *wnd; + size_t nwnd; + size_t capacity; +}; + +typedef Gdiplus::CachedBitmap *cache_handle; +class win_image { +private: + win_image(const win_image &); // decl only + win_image &operator=(const win_image &); // decl only + + Gdiplus::Bitmap *gpbitmap; + unsigned int nframe; + unsigned int current; + unsigned long tick; + unsigned long loopcount; // zero = infinite + unsigned long *delay; // unit: millisecond + cache_handle *cache; + +public: + win_image() THROW_NONE; + ~win_image() THROW_NONE; + int load(w3mimg_op *wop, Gdiplus::Bitmap **p_gpbitmap, + int *wreturn, int *hreturn) THROW_NONE; + int show(w3mimg_op *wop, int sx, int sy, int sw, int sh, int x, int y) THROW_NONE; + int animate(w3mimg_op *wop) THROW_NONE; +}; + +static int win_init(w3mimg_op * wop) THROW_NONE; +static int win_finish(w3mimg_op * wop) THROW_NONE; +static int win_active(w3mimg_op * wop) THROW_NONE; +static void win_set_background(w3mimg_op * wop, char *background) THROW_NONE; +static void win_sync(w3mimg_op * wop) THROW_NONE; +static void win_close(w3mimg_op * wop) THROW_NONE; + +static int win_load_image(w3mimg_op * wop, W3MImage * img, char *fname, + int w, int h) THROW_NONE; +static int win_show_image(w3mimg_op * wop, W3MImage * img, + int sx, int sy, int sw, int sh, int x, int y) THROW_NONE; +static void win_free_image(w3mimg_op * wop, W3MImage * img) THROW_NONE; +static int win_get_image_size(w3mimg_op * wop, W3MImage * img, + char *fname, int *w, int *h) THROW_NONE; +static int win_clear(w3mimg_op * wop, int x, int y, int w, int h) THROW_NONE; + +static int window_alive(w3mimg_op *wop) THROW_NONE; +static Gdiplus::Bitmap *read_image_file(w3mimg_op *wop, const char *fname) THROW_NONE; +static BOOL CALLBACK store_to_window_list(HWND hWnd, LPARAM wndlist) THROW_NONE; +static void clear_window_list(struct window_list *wl) THROW_NONE; +static const char *gdip_strerror(Gdiplus::Status status) THROW_NONE; +static void gdip_perror(w3mimg_op *wop, Gdiplus::Status status, const char *func) THROW_NONE; +static char *win32_strerror_alloc(DWORD status) THROW_NONE; +static void win32_perror(w3mimg_op *wop, DWORD status, const char *func) THROW_NONE; +#if 0 /* unused */ +static WCHAR *mb2wstr_alloc(const char *) THROW_NONE; +static char *wstr2mb_alloc(const WCHAR *) THROW_NONE; +#endif + +#define PRELUDE(wop, xi) \ + assert(wop); \ + struct win_info *xi = static_cast(wop->priv); \ + assert(xi) + +win_image::win_image() THROW_NONE + : gpbitmap(NULL), nframe(0) +{} + +win_image::~win_image() THROW_NONE +{ + if (this->cache) { + for (size_t i = 0; i != this->nframe; ++i) { + delete this->cache[i]; + } + delete[] this->cache; + } + delete[] this->delay; + delete this->gpbitmap; +} + +int +win_image::load(w3mimg_op *wop, Gdiplus::Bitmap **p_gpbitmap, int *wreturn, int *hreturn) THROW_NONE +{ + PRELUDE(wop, xi); + Gdiplus::Bitmap *gpbitmap = *p_gpbitmap; + assert(gpbitmap); + Gdiplus::Status status = Gdiplus::Ok; + int retval = 0; + + Gdiplus::PropertyItem *loopcountbuf = NULL; + Gdiplus::PropertyItem *delaybuf = NULL; + unsigned long *delay = NULL; + cache_handle *cache = NULL; + + if (xi->logfile) { + fprintf(xi->logfile, "win_image::load(%p, %p, %p, %p) start\n", + wop, gpbitmap, wreturn, hreturn); + } + { + unsigned int width = gpbitmap->GetWidth(); + unsigned int height = gpbitmap->GetHeight(); + unsigned int nframe = gpbitmap->GetFrameCount(&Gdiplus::FrameDimensionTime); + unsigned long loopcount = 0; + unsigned int first_frame = 0; + + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): size[0]=%ux%u\n", width, height); + if (nframe == 0) { + // Not an animated picture + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): zero frame count\n"); + nframe = 1; + delay = new(std::nothrow) unsigned long[1]; + if (delay == NULL) + goto last; + delay[0] = 0; + } else { + unsigned int loopcountsize = gpbitmap->GetPropertyItemSize(PropertyTagLoopCount); + unsigned int delaysize = gpbitmap->GetPropertyItemSize(PropertyTagFrameDelay); + + // Get loop count + if (loopcountsize != 0) { + loopcountbuf = (Gdiplus::PropertyItem *)malloc(loopcountsize); + if (loopcountbuf == NULL) + goto last; + status = gpbitmap->GetPropertyItem(PropertyTagLoopCount, loopcountsize, loopcountbuf); + if (status != Gdiplus::Ok) + goto gdip_error; + if (loopcountbuf->type == PropertyTagTypeShort && + loopcountbuf->length >= sizeof(unsigned short)) { + loopcount = *(unsigned short *)loopcountbuf->value; + } else if (loopcountbuf->type == PropertyTagTypeLong && + loopcountbuf->length >= sizeof(unsigned long)) { + loopcount = *(unsigned long *)loopcountbuf->value; + } + } + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): loopcount=%lu\n", loopcount); + // Get delay times + if (delaysize != 0) { + delaybuf = (Gdiplus::PropertyItem *)malloc(delaysize); + if (delaybuf == NULL) + goto last; + status = gpbitmap->GetPropertyItem(PropertyTagFrameDelay, delaysize, delaybuf); + if (status != Gdiplus::Ok) + goto gdip_error; + delay = new(std::nothrow) unsigned long[nframe]; + if (delay == NULL) + goto last; + std::fill(delay, delay + nframe, 0); + if (delaybuf->type == PropertyTagTypeShort) { + unsigned int count = delaybuf->length / sizeof(unsigned short); + for (unsigned int i = 0; i != count; ++i) + delay[i] = ((unsigned short *)delaybuf->value)[i] * 10; + } else if (delaybuf->type == PropertyTagTypeLong) { + unsigned int count = delaybuf->length / sizeof(unsigned long); + for (unsigned int i = 0; i != count; ++i) + delay[i] = ((unsigned long *)delaybuf->value)[i] * 10; + } + } + if (xi->logfile) { + for (unsigned int i = 0; i != nframe; ++i) + fprintf(xi->logfile, "win_image::load(): delay[%u]=%lu\n", i, delay[i]); + } + // Get dimensions + for (unsigned int nextframe = 1; nextframe != nframe; ++nextframe) { + status = gpbitmap->SelectActiveFrame(&Gdiplus::FrameDimensionTime, nextframe); + if (status != Gdiplus::Ok) { + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): SelectActiveFrame() to %u failed = %d: %s\n", + nextframe, (int)status, gdip_strerror(status)); + goto last; + } + unsigned int iw = gpbitmap->GetWidth(); + unsigned int ih = gpbitmap->GetHeight(); + if (iw > width) + width = iw; + if (ih > height) + height = ih; + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): size[%u]=%ux%u\n", nextframe, iw, ih); + } + // Go to the first frame + first_frame = (0 < -wop->max_anim && -wop->max_anim < nframe) ? (nframe + wop->max_anim) : 0; + status = gpbitmap->SelectActiveFrame(&Gdiplus::FrameDimensionTime, first_frame); + if (status != Gdiplus::Ok) { + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): SelectActiveFrame() to %u frame = %d: %s\n", + first_frame, (int)status, gdip_strerror(status)); + goto last; + } + } + // Allocate cache array + cache = new(std::nothrow) cache_handle[nframe]; + if (cache == NULL) + goto last; + std::fill(cache, cache + nframe, (cache_handle)NULL); + // Sanity check + if (width > SHRT_MAX || height > SHRT_MAX) { + if (xi->logfile) + fprintf(xi->logfile, "win_image::load(): too big image: %ux%u\n", width, height); + goto last; + } + // Store the results + if (wreturn) + *wreturn = (int)width; + if (hreturn) + *hreturn = (int)height; + this->gpbitmap = gpbitmap; + *p_gpbitmap = NULL; // ownership transfer + this->nframe = nframe; + this->current = first_frame; + this->tick = 0; + this->loopcount = loopcount; + this->delay = delay; + delay = NULL; // ownership transfer + this->cache = cache; + cache = NULL; // ownership transfer + retval = 1; + } + goto last; + +gdip_error: + gdip_perror(wop, status, "win_image::load"); + goto last; +last: + delete[] cache; + delete[] delay; + free(delaybuf); + free(loopcountbuf); + if (xi->logfile) + fprintf(xi->logfile, "win_image::load() = %d\n", retval); + return retval; +} + +int +win_image::show(w3mimg_op *wop, int sx, int sy, int sw, int sh, int x, int y) THROW_NONE +{ + PRELUDE(wop, xi); + int retval = 0; + Gdiplus::Status status = Gdiplus::Ok; + cache_handle newcache = NULL; + + if (xi->logfile) + fprintf(xi->logfile, "win_image::show(%p, %d, %d, %d, %d, %d, %d) start current=%u\n", + wop, sx, sy, sw, sh, x, y, this->current); + if (!window_alive(wop)) + goto last; + { + int xx = x + wop->offset_x; + int yy = y + wop->offset_y; + + // Prepare the Graphics object for painting + Gdiplus::Graphics graphics(xi->window); + if ((status = graphics.GetLastStatus()) != Gdiplus::Ok) + goto gdip_error; + Gdiplus::Rect clip(xx, yy, sw, sh); + status = graphics.SetClip(clip); + if (status != Gdiplus::Ok) + goto gdip_error; + + unsigned int retry_count = 2; + do { + if (this->cache[this->current] == NULL) { + // Cache the image + Gdiplus::Bitmap tmp_bitmap(sw, sh, &graphics); + if ((status = tmp_bitmap.GetLastStatus()) != Gdiplus::Ok) + goto gdip_error; + Gdiplus::Graphics tmp_graphics(&tmp_bitmap); + if ((status = tmp_graphics.GetLastStatus()) != Gdiplus::Ok) + goto gdip_error; + status = tmp_graphics.Clear(Gdiplus::Color(xi->background_pixel)); + if (status != Gdiplus::Ok) + goto gdip_error; + status = tmp_graphics.DrawImage(this->gpbitmap, 0, 0, sw, sh); + if (status != Gdiplus::Ok) + goto gdip_error; + Gdiplus::CachedBitmap *newcache = new Gdiplus::CachedBitmap(&tmp_bitmap, &graphics); + if (newcache == NULL) + goto last; + if ((status = newcache->GetLastStatus()) != Gdiplus::Ok) + goto gdip_error; + this->cache[this->current] = newcache; + newcache = NULL; // ownership transfer + --retry_count; + } + // Draw it + status = graphics.DrawCachedBitmap(this->cache[this->current], xx - sx, yy - sy); + if (status == Gdiplus::Ok) + break; + // maybe the user altered the display configuration + if (xi->logfile) + fprintf(xi->logfile, "win_image::show(): stale cache = %d: %s\n", + (int)status, gdip_strerror(status)); + delete this->cache[this->current]; + this->cache[this->current] = NULL; + if (retry_count == 0) + goto last; + } while (1); + + retval = 1; + } + goto last; +gdip_error: + gdip_perror(wop, status, "win_image::show"); + goto last; +last: + delete newcache; + if (xi->logfile) + fprintf(xi->logfile, "win_image::show() = %d\n", retval); + return retval; +} + +int +win_image::animate(w3mimg_op * wop) THROW_NONE +{ + PRELUDE(wop, xi); + int retval = 0; + Gdiplus::Status status = Gdiplus::Ok; + + if (xi->logfile) + fprintf(xi->logfile, "win_image::animate(%p) start\n", wop); + { + if (this->nframe <= 1) + goto animation_end; +#define UNIT_TICK 50 +#define MIN_DELAY (UNIT_TICK*2) + this->tick += UNIT_TICK; + if (this->tick >= MIN_DELAY && this->tick >= this->delay[this->current]) { + this->tick = 0; + unsigned int nextframe = this->current + 1; + if (wop->max_anim == nextframe) + goto animation_end; + if (nextframe >= this->nframe) { + if (this->loopcount == 1 || wop->max_anim < 0) // end of the loop + goto animation_end; + nextframe = 0; + } + status = this->gpbitmap->SelectActiveFrame(&Gdiplus::FrameDimensionTime, nextframe); + if (status != Gdiplus::Ok) + goto gdip_error; + this->current = nextframe; + if (nextframe == 0 && this->loopcount > 1) + --this->loopcount; + } +animation_end: + retval = 1; + } + goto last; +gdip_error: + gdip_perror(wop, status, "win_image::animate"); + goto last; +last: + if (xi->logfile) + fprintf(xi->logfile, "win_image::animate() = %d\n", retval); + return retval; +} + +static int +window_alive(w3mimg_op *wop) THROW_NONE +{ + PRELUDE(wop, xi); + if (xi->window == NULL) + return 0; + if (IsWindow(xi->window)) + return 1; + xi->window = NULL; + fputs("w3mimgdisplay: target window disappeared\n", stderr); + if (xi->logfile) + fputs("w3mimgdisplay: target window disappeared\n", xi->logfile); + return 0; +} + +static int +win_init(w3mimg_op *) THROW_NONE +{ + // nothing to do + return 1; +} + +static int +win_finish(w3mimg_op *) THROW_NONE +{ + // nothing to do + return 1; +} + +static int +win_clear(w3mimg_op *wop, int x, int y, int w, int h) THROW_NONE +{ + PRELUDE(wop, xi); + Gdiplus::Status status = Gdiplus::Ok; + int retval = 0; + + if (xi->logfile) + fprintf(xi->logfile, "win_clear(%p, %d, %d, %d, %d) start\n", + wop, x, y, w, h); + if (!window_alive(wop)) + goto last; + { + if (x < 0) + x = 0; + if (y < 0) + y = 0; + Gdiplus::SolidBrush brush(Gdiplus::Color(xi->background_pixel)); + if ((status = brush.GetLastStatus()) != Gdiplus::Ok) + goto gdip_error; + Gdiplus::Graphics graphics(xi->window); + if ((status = graphics.GetLastStatus()) != Gdiplus::Ok) + goto gdip_error; + status = graphics.FillRectangle(&brush, x + wop->offset_x, y + wop->offset_y, w, h); + if (status != Gdiplus::Ok) + goto gdip_error; + retval = 1; + } + goto last; +gdip_error: + gdip_perror(wop, status, "win_clear"); + goto last; +last: + if (xi->logfile) + fprintf(xi->logfile, "win_clear() = %d\n", retval); + return retval; +} + +static int +win_active(w3mimg_op * wop) THROW_NONE +{ + return window_alive(wop); +} + +static void +win_set_background(w3mimg_op * wop, char *background) THROW_NONE +{ + PRELUDE(wop, xi); + + HDC windc = NULL; + + if (xi->logfile) + fprintf(xi->logfile, "win_set_background(%p, \"%s\")\n", wop, background ? background : "(auto)"); + { + // Fallback value + // xi->background_pixel = Gdiplus::Color::White; + xi->background_pixel = Gdiplus::Color::Black; + + // Explicit + if (background) { + unsigned int r, g, b; + if (sscanf(background, "#%02x%02x%02x", &r, &g, &b) == 3) { + xi->background_pixel = Gdiplus::Color::MakeARGB((BYTE)255, (BYTE)r, (BYTE)g, (BYTE)b); + goto last; + } + } + + // Auto detect + if (xi->window == NULL || !IsWindow(xi->window)) + goto last; + windc = GetDC(xi->window); + if (windc == NULL) + goto win32_error; + COLORREF c = GetPixel(windc, + (wop->offset_x >= 1) ? (wop->offset_x - 1) : 0, + (wop->offset_y >= 1) ? (wop->offset_y - 1) : 0); + xi->background_pixel = Gdiplus::Color::MakeARGB( + (BYTE)255, GetRValue(c), GetGValue(c), GetBValue(c)); + } + goto last; +win32_error: + win32_perror(wop, GetLastError(), "win_set_background"); + goto last; +last: + if (xi->logfile) + fprintf(xi->logfile, "win_set_background() result = #%06x\n", + (unsigned int)xi->background_pixel); + if (windc) + ReleaseDC(xi->window, windc); +} + +static void +win_sync(w3mimg_op *) THROW_NONE +{ + // nothing to do + return; +} + +static void +win_close(w3mimg_op * wop) THROW_NONE +{ + PRELUDE(wop, xi); + + if (xi->gdiplus_token) + Gdiplus::GdiplusShutdown(xi->gdiplus_token); + if (xi->logfile) { + fprintf(xi->logfile, "win_close(%p)\n", wop); + fclose(xi->logfile); + } + delete xi; + delete wop; +} + +static Gdiplus::Bitmap * +read_image_file(w3mimg_op *wop, const char *fname) THROW_NONE +{ + PRELUDE(wop, xi); + Gdiplus::Status status = Gdiplus::Ok; + Gdiplus::Bitmap *retval = NULL; + + WCHAR *wfname = NULL; + Gdiplus::Bitmap *gpbitmap = NULL; + + if (xi->logfile) + fprintf(xi->logfile, "read_image_file(%p, \"%s\") start\n", wop, fname); + { + wfname = (WCHAR *)cygwin_create_path(CCP_POSIX_TO_WIN_W, fname); + if (wfname == NULL) + goto last; + gpbitmap = new Gdiplus::Bitmap(wfname); + if (gpbitmap == NULL) + goto last; + status = gpbitmap->GetLastStatus(); + switch (status) { + case Gdiplus::Ok: + break; + case Gdiplus::UnknownImageFormat: + case Gdiplus::FileNotFound: + goto last; // fail silently + default: + goto gdip_error; + } + retval = gpbitmap; + gpbitmap = NULL; // ownership transfer + } + goto last; +gdip_error: + gdip_perror(wop, status, "read_image_file"); +last: + delete gpbitmap; + free(wfname); + if (xi->logfile) + fprintf(xi->logfile, "read_image_file() = %p\n", retval); + return retval; +} + +static int +win_load_image(w3mimg_op * wop, W3MImage * img, char *fname, int w, int h) THROW_NONE +{ + PRELUDE(wop, xi); + int retval = 0; + Gdiplus::Bitmap *gpbitmap = NULL; + win_image *wimg = NULL; + + assert(img); + if (xi->logfile) { + fprintf(xi->logfile, "win_load_image(%p, %p, \"%s\", %d, %d) start\n", + wop, img, fname, w, h); + } + { + gpbitmap = read_image_file(wop, fname); + if (gpbitmap == NULL) + goto last; + int iw, ih; + wimg = new(std::nothrow) win_image; + if (!wimg->load(wop, &gpbitmap, &iw, &ih)) + goto last; + img->pixmap = wimg; + wimg = NULL; // ownership transfer + img->width = (0 <= w && w < iw) ? w : iw; + img->height = (0 <= h && h < ih) ? h : ih; + retval = 1; + } + goto last; +last: + delete wimg; + delete gpbitmap; + if (xi->logfile) + fprintf(xi->logfile, "win_load_image() = %d\n", retval); + return retval; +} + +static int +win_show_image(w3mimg_op * wop, W3MImage * img, int sx, int sy, int sw, + int sh, int x, int y) THROW_NONE +{ + PRELUDE(wop, xi); + int retval = 0; + + assert(img); + win_image *wimg = static_cast(img->pixmap); + assert(wimg); + + if (xi->logfile) + fprintf(xi->logfile, "win_show_image(%p, %p, %d, %d, %d, %d, %d, %d) start\n", + wop, img, sx, sy, sw, sh, x, y); + int sww = sw ? sw : img->width; + int shh = sh ? sh : img->height; + retval = wimg->show(wop, sx, sy, sww, shh, x, y) + && wimg->animate(wop); + if (xi->logfile) + fprintf(xi->logfile, "win_show_image() = %d\n", retval); + return retval; +} + +static void +win_free_image(w3mimg_op * wop, W3MImage * img) THROW_NONE +{ + PRELUDE(wop, xi); + + assert(img); + if (xi->logfile) + fprintf(xi->logfile, "win_free_image(%p, %p) pixmap=%p\n", wop, img, img->pixmap); + delete static_cast(img->pixmap); + img->pixmap = NULL; + img->width = 0; + img->height = 0; +} + +static int +win_get_image_size(w3mimg_op * wop, W3MImage *img_unused, char *fname, int *w, int *h) THROW_NONE +{ + PRELUDE(wop, xi); + int retval = 0; + Gdiplus::Bitmap *gpbitmap = NULL; + win_image *wimg = NULL; + + if (xi->logfile) { + fprintf(xi->logfile, "win_get_image_size(%p, %p, \"%s\", %p, %p) start\n", + wop, img_unused, fname, w, h); + } + { + gpbitmap = read_image_file(wop, fname); + if (gpbitmap == NULL) + goto last; + wimg = new(std::nothrow) win_image; + if (wimg == NULL) + goto last; + retval = wimg->load(wop, &gpbitmap, w, h);; + } + goto last; +last: + delete wimg; + delete gpbitmap; + if (xi->logfile) + fprintf(xi->logfile, "win_get_image_size() = %d\n", retval); + return retval; +} + +extern "C" w3mimg_op * +w3mimg_winopen() +{ + w3mimg_op *retval = NULL; + Gdiplus::Status status = Gdiplus::Ok; + + w3mimg_op *wop = NULL; + struct win_info *xi = NULL; + struct window_list children = { NULL, 0, 0 }; + + { + // Quit if running on X + const char *display_name; + if ((display_name = getenv("DISPLAY")) != NULL && + display_name[0] && strcmp(display_name, ":0") != 0) + return NULL; + + // Allocate the context objects + wop = new(std::nothrow) w3mimg_op(); // call the default ctor instead of "new w3mimg_op;" + if (wop == NULL) + return NULL; + wop->priv = xi = new(std::nothrow) win_info(); + if (xi == NULL) + goto last; + + // Debug logging + const char *logging_dir; + if ((logging_dir = getenv("W3MIMG_LOGDIR")) != NULL && + logging_dir[0]) { + size_t l = strlen(logging_dir) + sizeof "/w3mimgXXXXXXXXXX.log"; + char *fname = (char *)malloc(l); + snprintf(fname, l, "%s/w3mimg%d.log", logging_dir, (int)getpid()); + xi->logfile = fopen(fname, "a"); + if (xi->logfile) { + setvbuf(xi->logfile, NULL, _IONBF, 0); + fprintf(xi->logfile, "\nw3mimg_winopen() start pid=%d\n", (int)getpid()); + } + } + + // Look for the window to draw the image + xi->window = NULL; + const char *windowid; + if ((windowid = getenv("WINDOWID")) != NULL) + xi->window = FindWindowA(windowid, NULL); + if (!xi->window) + xi->window = GetForegroundWindow(); + if (!xi->window) + goto win32_error; + + WINDOWINFO winfo = WINDOWINFO(); + winfo.cbSize = sizeof winfo; + GetWindowInfo(xi->window, &winfo); + wop->width = (int)(winfo.rcClient.right - winfo.rcClient.left); + wop->height = (int)(winfo.rcClient.bottom - winfo.rcClient.top); + + // Search decendant windows and find out which is the text window + while (1) { + HWND p_window = xi->window; + + clear_window_list(&children); + EnumChildWindows(xi->window, &store_to_window_list, (LPARAM)&children); + for (unsigned int i = 0; i < children.nwnd; i++) { + int width, height; + + GetWindowInfo(children.wnd[i], &winfo); + width = (int)(winfo.rcClient.right - winfo.rcClient.left); + height = (int)(winfo.rcClient.bottom - winfo.rcClient.top); + if (width > wop->width * 0.7 && + height > wop->height * 0.7) { + /* maybe text window */ + wop->width = width; + wop->height = height; + xi->window = children.wnd[i]; + } + } + if (p_window == xi->window) + break; + } + + // Terminal may leave some border pixels + wop->offset_x = OFFSET_X; + wop->offset_y = OFFSET_Y; + + // Start up the GDI+ + Gdiplus::GdiplusStartupInput startup_input; /// default ctor + status = Gdiplus::GdiplusStartup(&xi->gdiplus_token, &startup_input, NULL); + if (status != Gdiplus::Ok) + goto gdip_error; + + // Fill the context object + wop->init = win_init; + wop->finish = win_finish; + wop->active = win_active; + wop->set_background = win_set_background; + wop->sync = win_sync; + wop->close = win_close; + wop->clear = win_clear; + + wop->load_image = win_load_image; + wop->show_image = win_show_image; + wop->free_image = win_free_image; + wop->get_image_size = win_get_image_size; + + retval = wop; // take care of the object lifetime + } + goto last; +win32_error: + win32_perror(wop, GetLastError(), "w3mimg_winopen"); + goto last; +gdip_error: + gdip_perror(wop, status, "w3mimg_winopen"); + goto last; +last: + if (xi && xi->logfile) + fprintf(xi->logfile, "w3mimg_winopen() = %p\n", retval); + clear_window_list(&children); + if (!retval) { + if (xi) { + if (xi->gdiplus_token) + Gdiplus::GdiplusShutdown(xi->gdiplus_token); + if (xi->logfile) + fclose(xi->logfile); + delete xi; + } + delete wop; + } + return retval; +} + +static BOOL CALLBACK +store_to_window_list(HWND hWnd, LPARAM wndlist) THROW_NONE +{ + struct window_list *wl = (struct window_list *)wndlist; + + if (wl->nwnd >= wl->capacity) { + size_t newsize = (wl->capacity < 4 ) ? 4 : (wl->capacity * 2); + HWND *newbuf = (HWND *)realloc(wl->wnd, newsize * sizeof newbuf[0]); + if (newbuf == NULL) { + clear_window_list(wl); + return FALSE; + } + wl->wnd = newbuf; + wl->capacity = newsize; + } + wl->wnd[wl->nwnd++] = hWnd; + return TRUE; +} + +static void +clear_window_list(struct window_list *wl) THROW_NONE +{ + free(wl->wnd); + wl->wnd = NULL; + wl->nwnd = 0; + wl->capacity = 0; +} + +static const char * +gdip_strerror(Gdiplus::Status status) THROW_NONE +{ + size_t i; + struct status_rec { + Gdiplus::Status code; + const char *str; + }; + static const struct status_rec table[] = { +#define ERRITEM(s) { Gdiplus::s, #s } + ERRITEM(Ok), + ERRITEM(GenericError), + ERRITEM(InvalidParameter), + ERRITEM(OutOfMemory), + ERRITEM(ObjectBusy), + ERRITEM(InsufficientBuffer), + ERRITEM(NotImplemented), + ERRITEM(Win32Error), + ERRITEM(WrongState), + ERRITEM(Aborted), + ERRITEM(FileNotFound), + ERRITEM(ValueOverflow), + ERRITEM(AccessDenied), + ERRITEM(UnknownImageFormat), + ERRITEM(FontFamilyNotFound), + ERRITEM(FontStyleNotFound), + ERRITEM(NotTrueTypeFont), + ERRITEM(UnsupportedGdiplusVersion), + ERRITEM(GdiplusNotInitialized), + ERRITEM(PropertyNotFound), + ERRITEM(PropertyNotSupported), + ERRITEM(ProfileNotFound), +#undef ERRITEM + }; + for (i = 0; i != sizeof table / sizeof table[0]; ++i) + if (table[i].code == status) + return table[i].str; + return "unknown"; +} + +static void +gdip_perror(w3mimg_op *wop, Gdiplus::Status status, const char *func) THROW_NONE +{ + const char *s = gdip_strerror(status); + fprintf(stderr, "w3mimgdisplay: GDI+ error %d: %s\n", (int)status, s); + if (wop && wop->priv) { + struct win_info *xi = (struct win_info *)wop->priv; + if (xi->logfile) { + fprintf(xi->logfile, "%s(): GDI+ error %d: %s\n", func, (int)status, s); + } + } +} + +// Don't free() the result; use LocalFree() instead +static char * +win32_strerror_alloc(DWORD status) THROW_NONE +{ + char *errbuf = NULL; + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, status, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPSTR)&errbuf, 0, NULL); + if (errbuf) { + size_t len = strlen(errbuf); + if (len > 0 && errbuf[len - 1] == '\n') + errbuf[len - 1] = '\0'; + } + return errbuf; +} + +static void +win32_perror(w3mimg_op *wop, DWORD status, const char *func) THROW_NONE +{ + char *errbuf = win32_strerror_alloc(status); + const char *s = errbuf ? errbuf : "(unknown)"; + + fprintf(stderr, "w3mimgdisplay: Win32 error %u: %s\n", (unsigned int)status, s); + if (wop && wop->priv) { + struct win_info *xi = (struct win_info *)wop->priv; + if (xi->logfile) { + fprintf(xi->logfile, "%s(): Win32 error %u: %s\n", + func, (unsigned int)status, s); + } + } + LocalFree(errbuf); +} + +#if 0 /* unused */ +static WCHAR * +mb2wstr_alloc(const char *s) THROW_NONE +{ + int len; + WCHAR *buf = NULL; + + len = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, s, -1, NULL, 0); + if (len <= 0) { + fprintf(stderr, "w3mimgdisplay: unable to convert string ecode=%u\n", + (unsigned int)GetLastError()); + goto error; + } + buf = (WCHAR *)malloc(len * sizeof(WCHAR)); /* including L'\0' */ + if (!buf) + goto error; + len = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, s, -1, buf, len); + if (len <= 0) { + fprintf(stderr, "w3mimgdisplay: unable to convert string ecode=%u\n", + (unsigned int)GetLastError()); + goto error; + } + return buf; +error: + free(buf); + return NULL; +} + +static char * +wstr2mb_alloc(const WCHAR *ws) THROW_NONE +{ + int len; + char *buf = NULL; + + len = WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, ws, -1, NULL, 0, NULL, NULL); + if (len <= 0) { + fprintf(stderr, "w3mimgdisplay: unable to convert string ecode=%u\n", + (unsigned int)GetLastError()); + goto error; + } + buf = (char *)malloc(len); /* including '\0' */ + if (!buf) + goto error; + len = WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, ws, -1, buf, len, NULL, NULL); + if (len <= 0) { + fprintf(stderr, "w3mimgdisplay: unable to convert string ecode=%u\n", + (unsigned int)GetLastError()); + goto error; + } + return buf; +error: + free(buf); + return NULL; +} +#endif /* unused */ diff --git a/w3mimg/x11/CVS/Entries b/w3mimg/x11/CVS/Entries new file mode 100644 index 0000000..a3cf134 --- /dev/null +++ b/w3mimg/x11/CVS/Entries @@ -0,0 +1,4 @@ +/.cvsignore/1.1/Mon Sep 22 22:53:53 2003// +/Makefile.in/1.4/Mon Apr 26 17:00:38 2004// +/x11_w3mimg.c/1.29/Mon Nov 8 17:14:06 2004// +D diff --git a/w3mimg/x11/CVS/Repository b/w3mimg/x11/CVS/Repository new file mode 100644 index 0000000..1268050 --- /dev/null +++ b/w3mimg/x11/CVS/Repository @@ -0,0 +1 @@ +w3m/w3mimg/x11 diff --git a/w3mimg/x11/CVS/Root b/w3mimg/x11/CVS/Root new file mode 100644 index 0000000..121fa06 --- /dev/null +++ b/w3mimg/x11/CVS/Root @@ -0,0 +1 @@ +:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m -- cgit v1.2.3 From 620796f8d750bc58e1cf1327ff54aed32e302c73 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Tue, 22 May 2012 23:06:58 +0900 Subject: Remove garbage files --- w3mimg/CVS/Entries | 7 ------- w3mimg/CVS/Repository | 1 - w3mimg/CVS/Root | 1 - w3mimg/fb/CVS/Entries | 11 ----------- w3mimg/fb/CVS/Repository | 1 - w3mimg/fb/CVS/Root | 1 - w3mimg/win/CVS/Entries | 4 ---- w3mimg/win/CVS/Repository | 1 - w3mimg/win/CVS/Root | 1 - w3mimg/x11/CVS/Entries | 4 ---- w3mimg/x11/CVS/Repository | 1 - w3mimg/x11/CVS/Root | 1 - 12 files changed, 34 deletions(-) delete mode 100644 w3mimg/CVS/Entries delete mode 100644 w3mimg/CVS/Repository delete mode 100644 w3mimg/CVS/Root delete mode 100644 w3mimg/fb/CVS/Entries delete mode 100644 w3mimg/fb/CVS/Repository delete mode 100644 w3mimg/fb/CVS/Root delete mode 100644 w3mimg/win/CVS/Entries delete mode 100644 w3mimg/win/CVS/Repository delete mode 100644 w3mimg/win/CVS/Root delete mode 100644 w3mimg/x11/CVS/Entries delete mode 100644 w3mimg/x11/CVS/Repository delete mode 100644 w3mimg/x11/CVS/Root (limited to 'w3mimg') diff --git a/w3mimg/CVS/Entries b/w3mimg/CVS/Entries deleted file mode 100644 index ad83b16..0000000 --- a/w3mimg/CVS/Entries +++ /dev/null @@ -1,7 +0,0 @@ -/.cvsignore/1.1/Mon Sep 22 22:53:53 2003// -D/fb//// -D/x11//// -/Makefile.in/1.11/Tue Jan 4 09:22:28 2011// -/w3mimg.c/1.6/Tue Jan 4 09:22:28 2011// -/w3mimg.h/1.9/Tue Jan 4 09:22:28 2011// -D/win//// diff --git a/w3mimg/CVS/Repository b/w3mimg/CVS/Repository deleted file mode 100644 index d59666d..0000000 --- a/w3mimg/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -w3m/w3mimg diff --git a/w3mimg/CVS/Root b/w3mimg/CVS/Root deleted file mode 100644 index 121fa06..0000000 --- a/w3mimg/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m diff --git a/w3mimg/fb/CVS/Entries b/w3mimg/fb/CVS/Entries deleted file mode 100644 index 549e962..0000000 --- a/w3mimg/fb/CVS/Entries +++ /dev/null @@ -1,11 +0,0 @@ -/.cvsignore/1.1/Mon Sep 22 22:53:53 2003// -/Makefile.in/1.4/Mon Apr 26 17:00:38 2004// -/fb.c/1.16/Sun Jul 13 16:19:10 2003// -/fb.h/1.7/Mon Jul 7 15:48:17 2003// -/fb_gdkpixbuf.c/1.21/Mon Nov 8 17:14:06 2004// -/fb_img.c/1.6/Mon Jul 7 15:48:17 2003// -/fb_img.h/1.9/Wed Aug 4 17:32:28 2004// -/fb_imlib2.c/1.10/Wed Aug 4 17:32:28 2004// -/fb_w3mimg.c/1.14/Wed Aug 4 17:32:28 2004// -/readme.txt/1.2/Mon Jul 22 16:17:32 2002// -D diff --git a/w3mimg/fb/CVS/Repository b/w3mimg/fb/CVS/Repository deleted file mode 100644 index 336666e..0000000 --- a/w3mimg/fb/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -w3m/w3mimg/fb diff --git a/w3mimg/fb/CVS/Root b/w3mimg/fb/CVS/Root deleted file mode 100644 index 121fa06..0000000 --- a/w3mimg/fb/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m diff --git a/w3mimg/win/CVS/Entries b/w3mimg/win/CVS/Entries deleted file mode 100644 index 5025b4b..0000000 --- a/w3mimg/win/CVS/Entries +++ /dev/null @@ -1,4 +0,0 @@ -/Makefile.in/1.1/Tue Dec 21 10:13:55 2010// -/win_w3mimg.cpp/1.2/Fri Dec 24 09:52:06 2010// -/.cvsignore/1.1/Wed Jan 5 09:52:10 2011// -D diff --git a/w3mimg/win/CVS/Repository b/w3mimg/win/CVS/Repository deleted file mode 100644 index 06901a3..0000000 --- a/w3mimg/win/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -w3m/w3mimg/win diff --git a/w3mimg/win/CVS/Root b/w3mimg/win/CVS/Root deleted file mode 100644 index 121fa06..0000000 --- a/w3mimg/win/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m diff --git a/w3mimg/x11/CVS/Entries b/w3mimg/x11/CVS/Entries deleted file mode 100644 index a3cf134..0000000 --- a/w3mimg/x11/CVS/Entries +++ /dev/null @@ -1,4 +0,0 @@ -/.cvsignore/1.1/Mon Sep 22 22:53:53 2003// -/Makefile.in/1.4/Mon Apr 26 17:00:38 2004// -/x11_w3mimg.c/1.29/Mon Nov 8 17:14:06 2004// -D diff --git a/w3mimg/x11/CVS/Repository b/w3mimg/x11/CVS/Repository deleted file mode 100644 index 1268050..0000000 --- a/w3mimg/x11/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -w3m/w3mimg/x11 diff --git a/w3mimg/x11/CVS/Root b/w3mimg/x11/CVS/Root deleted file mode 100644 index 121fa06..0000000 --- a/w3mimg/x11/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:inu@w3m.cvs.sourceforge.net:/cvsroot/w3m -- cgit v1.2.3 From 1d0ba25a660483da1272a31dd077ed94441e3d9f Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Sat, 2 Jan 2021 09:20:37 +0900 Subject: New upstream version 0.5.3+git20210102 --- w3mimg/.cvsignore | 1 - w3mimg/Makefile.in | 4 +- w3mimg/fb/.cvsignore | 1 - w3mimg/fb/fb.c | 431 +++++++++++++++++++++++++++++++++++++++++++++++ w3mimg/fb/fb.h | 4 + w3mimg/fb/fb_gdkpixbuf.c | 2 +- w3mimg/fb/fb_imlib2.c | 1 - w3mimg/fb/fb_w3mimg.c | 9 +- w3mimg/fb/readme.txt | 98 +++++------ w3mimg/win/.cvsignore | 1 - w3mimg/x11/.cvsignore | 1 - w3mimg/x11/x11_w3mimg.c | 92 ++++++++-- 12 files changed, 572 insertions(+), 73 deletions(-) delete mode 100644 w3mimg/.cvsignore delete mode 100644 w3mimg/fb/.cvsignore delete mode 100644 w3mimg/win/.cvsignore delete mode 100644 w3mimg/x11/.cvsignore (limited to 'w3mimg') diff --git a/w3mimg/.cvsignore b/w3mimg/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/w3mimg/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/w3mimg/Makefile.in b/w3mimg/Makefile.in index dfc550c..8e2ad73 100644 --- a/w3mimg/Makefile.in +++ b/w3mimg/Makefile.in @@ -16,9 +16,9 @@ IMGCFLAGS=@IMGX11CFLAGS@ @IMGFBCFLAGS@ @IMGWINCFLAGS@ IMGOBJS=@IMGOBJS@ .PHONY: $(SUBDIRS) -all: @IMGTARGETS@ w3mimg.a +all: w3mimg.a -w3mimg.a: $(IMGOBJS) +w3mimg.a: w3mimg.o @IMGTARGETS@ $(AR) rv $@ $(IMGOBJS) $(RANLIB) $@ diff --git a/w3mimg/fb/.cvsignore b/w3mimg/fb/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/w3mimg/fb/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/w3mimg/fb/fb.c b/w3mimg/fb/fb.c index cd11128..7960584 100644 --- a/w3mimg/fb/fb.c +++ b/w3mimg/fb/fb.c @@ -12,12 +12,24 @@ #include #include #include +#if defined(__linux__) #include +#elif defined(__FreeBSD__) +#include +#endif +#if defined(__FreeBSD__) +#include +#include +#endif #include "fb.h" #define FB_ENV "FRAMEBUFFER" +#if defined(__linux__) #define FB_DEFDEV "/dev/fb0" +#elif defined(__FreeBSD__) +#define FB_DEFDEV "/dev/ttyv0" +#endif #define MONO_OFFSET_8BIT 0x40 #define COLORS_MONO_8BIT 0x40 @@ -38,22 +50,65 @@ #define IMAGE_SIZE_MAX 10000 +#if defined(__linux__) static struct fb_cmap *fb_cmap_create(struct fb_fix_screeninfo *, struct fb_var_screeninfo *); +#elif defined(__FreeBSD__) +static video_color_palette_t *fb_cmap_create(video_info_t *video_info, + video_adapter_info_t *video_adapter_info); +#endif +#if defined(__linux__) static void fb_cmap_destroy(struct fb_cmap *cmap); +#elif defined(__FreeBSD__) +static void fb_cmap_destroy(video_color_palette_t *cmap); +#endif +#if defined(__linux__) static int fb_fscrn_get(int fbfp, struct fb_fix_screeninfo *scinfo); +#endif +#if defined(__linux__) static void *fb_mmap(int fbfp, struct fb_fix_screeninfo *scinfo); +#elif defined(__FreeBSD__) +static void *fb_mmap(int fbfp, video_adapter_info_t *video_adapter_info); +#endif +#if defined(__linux__) static int fb_munmap(void *buf, struct fb_fix_screeninfo *scinfo); +#elif defined(__FreeBSD__) +static int fb_munmap(void *buf, video_adapter_info_t *video_adapter_info); +#endif +#if defined(__linux__) static int fb_vscrn_get(int fbfp, struct fb_var_screeninfo *scinfo); +#endif +#if defined(__linux__) static int fb_cmap_set(int fbfp, struct fb_cmap *cmap); +#elif defined(__FreeBSD__) +static int fb_cmap_set(int fbfp, video_color_palette_t *cmap); +#endif +#if defined(__linux__) static int fb_cmap_get(int fbfp, struct fb_cmap *cmap); +#elif defined(__FreeBSD__) +static int fb_cmap_get(int fbfp, video_color_palette_t *cmap); +#endif 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); +#if defined(__FreeBSD__) +static int fb_video_mode_get(int fbfp, int *video_mode); +static int fb_video_info_get(int fbfp, video_info_t *video_info); +static int fb_video_adapter_info_get(int fbfp, video_adapter_info_t *video_adapter_info); +#endif +#if defined(__linux__) static struct fb_fix_screeninfo fscinfo; static struct fb_var_screeninfo vscinfo; +#elif defined(__FreeBSD__) +static video_info_t video_info; +static video_adapter_info_t video_adapter_info; +#endif +#if defined(__linux__) static struct fb_cmap *cmap = NULL, *cmap_org = NULL; +#elif defined(__FreeBSD__) +static video_color_palette_t *cmap = NULL, *cmap_org = NULL; +#endif static int is_open = FALSE; static int fbfp = -1; static size_t pixel_size = 0; @@ -63,6 +118,9 @@ int fb_open(void) { char *fbdev = { FB_DEFDEV }; +#if defined(__FreeBSD__) + int video_mode; +#endif if (is_open == TRUE) return 1; @@ -76,6 +134,7 @@ fb_open(void) goto ERR_END; } +#if defined(__linux__) if (fb_fscrn_get(fbfp, &fscinfo)) { goto ERR_END; } @@ -83,22 +142,69 @@ fb_open(void) if (fb_vscrn_get(fbfp, &vscinfo)) { goto ERR_END; } +#elif defined(__FreeBSD__) + if (fb_video_mode_get(fbfp, &video_mode)) { + goto ERR_END; + } + video_info.vi_mode = video_mode; + + if (fb_video_info_get(fbfp, &video_info)) { + goto ERR_END; + } + if (fb_video_adapter_info_get(fbfp, &video_adapter_info)) { + goto ERR_END; + } + if (!(video_info.vi_flags & V_INFO_GRAPHICS) || + !(video_info.vi_flags & V_INFO_LINEAR)) { + goto ERR_END; + } +#endif + +#if defined(__linux__) if ((cmap = fb_cmap_create(&fscinfo, &vscinfo)) == (struct fb_cmap *)-1) { goto ERR_END; } +#elif defined(__FreeBSD__) + if ((cmap = fb_cmap_create(&video_info, &video_adapter_info)) == (video_color_palette_t *)-1) { + goto ERR_END; + } +#endif +#if defined(__linux__) if (!(buf = fb_mmap(fbfp, &fscinfo))) { fprintf(stderr, "Can't allocate memory.\n"); goto ERR_END; } +#elif defined(__FreeBSD__) + if (!(buf = fb_mmap(fbfp, &video_adapter_info))) { + fprintf(stderr, "Can't allocate memory.\n"); + goto ERR_END; + } +#endif +#if defined(__linux__) if (fscinfo.type != FB_TYPE_PACKED_PIXELS) { fprintf(stderr, "This type of framebuffer is not supported.\n"); goto ERR_END; } +#elif defined(__FreeBSD__) + if (!(video_info.vi_mem_model == V_INFO_MM_PACKED || + video_info.vi_mem_model == V_INFO_MM_DIRECT)) { + fprintf(stderr, "This type of framebuffer is not supported.\n"); + goto ERR_END; + } +#endif +#if defined(__linux__) if (fscinfo.visual == FB_VISUAL_PSEUDOCOLOR && vscinfo.bits_per_pixel == 8) { +#elif defined(__FreeBSD__) + if (video_adapter_info.va_flags & V_ADP_PALETTE && + video_info.vi_mem_model == V_INFO_MM_PACKED && + video_info.vi_depth == 8) { +#else + if (0) { +#endif if (fb_cmap_get(fbfp, cmap)) { fprintf(stderr, "Can't get color map.\n"); fb_cmap_destroy(cmap); @@ -111,6 +217,7 @@ fb_open(void) pixel_size = 1; } +#if defined(__linux__) else if ((fscinfo.visual == FB_VISUAL_TRUECOLOR || fscinfo.visual == FB_VISUAL_DIRECTCOLOR) && (vscinfo.bits_per_pixel == 15 || @@ -118,6 +225,14 @@ fb_open(void) vscinfo.bits_per_pixel == 24 || vscinfo.bits_per_pixel == 32)) { pixel_size = (vscinfo.bits_per_pixel + 7) / CHAR_BIT; } +#elif defined(__FreeBSD__) + else if (video_info.vi_mem_model == V_INFO_MM_DIRECT && + (video_info.vi_depth == 15 || + video_info.vi_depth == 16 || + video_info.vi_depth == 24 || video_info.vi_depth == 32)) { + pixel_size = (video_info.vi_depth + 7) / CHAR_BIT; + } +#endif else { fprintf(stderr, "This type of framebuffer is not supported.\n"); goto ERR_END; @@ -147,7 +262,11 @@ fb_close(void) cmap = NULL; } if (buf != NULL) { +#if defined(__linux__) fb_munmap(buf, &fscinfo); +#elif defined(__FreeBSD__) + fb_munmap(buf, &video_adapter_info); +#endif buf = NULL; } @@ -259,11 +378,19 @@ fb_image_draw(FB_IMAGE * image, int x, int y, int sx, int sy, int width, if (y + height > fb_height()) height = fb_height() - y; +#if defined(__linux__) offset_fb = fscinfo.line_length * y + pixel_size * x; +#elif defined(__FreeBSD__) + offset_fb = video_adapter_info.va_line_width * y + pixel_size * x; +#endif 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); +#if defined(__linux__) offset_fb += fscinfo.line_length; +#elif defined(__FreeBSD__) + offset_fb += video_adapter_info.va_line_width; +#endif offset_img += image->rowstride; } @@ -336,7 +463,11 @@ fb_width(void) if (is_open != TRUE) return 0; +#if defined(__linux__) return vscinfo.xres; +#elif defined(__FreeBSD__) + return video_info.vi_width; +#endif } int @@ -345,7 +476,11 @@ fb_height(void) if (is_open != TRUE) return 0; +#if defined(__linux__) return vscinfo.yres; +#elif defined(__FreeBSD__) + return video_info.vi_height; +#endif } int @@ -369,7 +504,11 @@ fb_clear(int x, int y, int w, int h, int r, int g, int b) h = fb_height() - y; if (tmp == NULL) { +#if defined(__linux__) tmp = malloc(fscinfo.line_length); +#elif defined(__FreeBSD__) + tmp = malloc(video_adapter_info.va_line_width); +#endif if (tmp == NULL) return 1; } @@ -384,10 +523,18 @@ fb_clear(int x, int y, int w, int h, int r, int g, int b) gg = g; bb = b; } +#if defined(__linux__) offset_fb = fscinfo.line_length * y + pixel_size * x; +#elif defined(__FreeBSD__) + offset_fb = video_adapter_info.va_line_width * y + pixel_size * x; +#endif for (i = 0; i < h; i++) { memcpy(buf + offset_fb, tmp, pixel_size * w); +#if defined(__linux__) offset_fb += fscinfo.line_length; +#elif defined(__FreeBSD__) + offset_fb += video_adapter_info.va_line_width; +#endif } return 0; } @@ -400,11 +547,21 @@ fb_get_packed_color(int r, int g, int b) return fb_get_cmap_index(r, g, b); } else { +#if defined(__linux__) 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); +#elif defined(__FreeBSD__) + return + ((r >> (CHAR_BIT - video_info.vi_pixel_fsizes[0])) << + video_info.vi_pixel_fields[0]) + + ((g >> (CHAR_BIT - video_info.vi_pixel_fsizes[1])) << + video_info.vi_pixel_fields[1]) + + ((b >> (CHAR_BIT - video_info.vi_pixel_fsizes[2])) << + video_info.vi_pixel_fields[2]); +#endif } } @@ -433,16 +590,31 @@ fb_cmap_init(void) if (cmap == NULL) return 1; +#if defined(__linux__) if (cmap->len < COLOR_OFFSET_8BIT + COLORS_8BIT) { fprintf(stderr, "Can't allocate enough color.\n"); return 1; } +#elif defined(__FreeBSD__) + if (cmap->count < COLOR_OFFSET_8BIT + COLORS_8BIT) { + fprintf(stderr, "Can't allocate enough color.\n"); + return 1; + } +#endif if (cmap_org == NULL) { +#if defined(__linux__) if ((cmap_org = fb_cmap_create(&fscinfo, &vscinfo)) == (struct fb_cmap *)-1) { return 1; } +#elif defined(__FreeBSD__) + if ((cmap_org = + fb_cmap_create(&video_info, &video_adapter_info)) == + (video_color_palette_t *)-1) { + return 1; + } +#endif if (fb_cmap_get(fbfp, cmap_org)) { fprintf(stderr, "Can't get color map.\n"); @@ -452,8 +624,13 @@ fb_cmap_init(void) } } +#if defined(__linux__) cmap->start = MONO_OFFSET_8BIT; cmap->len = COLORS_8BIT + COLORS_MONO_8BIT; +#elif defined(__FreeBSD__) + cmap->index = MONO_OFFSET_8BIT; + cmap->count = COLORS_8BIT + COLORS_MONO_8BIT; +#endif for (lp = 0; lp < COLORS_MONO_8BIT; lp++) { int c; @@ -506,73 +683,223 @@ fb_cmap_init(void) #define LUT_MAX (256) +#if defined(__linux__) static struct fb_cmap * fb_cmap_create(struct fb_fix_screeninfo *fscinfo, struct fb_var_screeninfo *vscinfo) +#elif defined(__FreeBSD__) +static video_color_palette_t * +fb_cmap_create(video_info_t *video_info, + video_adapter_info_t *video_adapter_info) +#endif { +#if defined(__linux__) struct fb_cmap *cmap; +#elif defined(__FreeBSD__) + video_color_palette_t *cmap; +#endif int cmaplen = LUT_MAX; /* check the existence of colormap */ +#if defined(__linux__) if (fscinfo->visual == FB_VISUAL_MONO01 || fscinfo->visual == FB_VISUAL_MONO10 || fscinfo->visual == FB_VISUAL_TRUECOLOR) return NULL; +#elif defined(__FreeBSD__) + if (!(video_adapter_info->va_flags & V_ADP_PALETTE)) + return NULL; +#endif +#if defined(__linux__) cmap = (struct fb_cmap *)malloc(sizeof(struct fb_cmap)); +#elif defined(__FreeBSD__) + cmap = (video_color_palette_t *)malloc(sizeof(video_color_palette_t)); +#endif if (!cmap) { perror("cmap malloc error\n"); +#if defined(__linux__) return (struct fb_cmap *)-1; +#elif defined(__FreeBSD__) + return (video_color_palette_t *)-1; +#endif } +#if defined(__linux__) memset(cmap, 0, sizeof(struct fb_cmap)); +#elif defined(__FreeBSD__) + memset(cmap, 0, sizeof(video_color_palette_t)); +#endif + +#if defined(__FreeBSD__) + if (video_info->vi_mem_model == V_INFO_MM_PACKED) { + cmap->red = (u_char *) malloc(sizeof(u_char) * cmaplen); + if (!cmap->red) { + perror("red lut malloc error\n"); + return (video_color_palette_t *)-1; + } + cmap->green = (u_char *) malloc(sizeof(u_char) * cmaplen); + if (!cmap->green) { + perror("green lut malloc error\n"); + free(cmap->red); + return (video_color_palette_t *)-1; + } + cmap->blue = (u_char *) malloc(sizeof(u_char) * cmaplen); + if (!cmap->blue) { + perror("blue lut malloc error\n"); + free(cmap->red); + free(cmap->green); + return (video_color_palette_t *)-1; + } + cmap->transparent = (u_char *) malloc(sizeof(u_char) * cmaplen); + if (!cmap->transparent) { + perror("transparent lut malloc error\n"); + free(cmap->red); + free(cmap->green); + free(cmap->blue); + return (video_color_palette_t *)-1; + } + cmap->count = cmaplen; + return cmap; + } +#endif /* Allocates memory for a colormap */ +#if defined(__linux__) if (vscinfo->red.length) { cmap->red = (__u16 *) malloc(sizeof(__u16) * cmaplen); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[0]) { + cmap->red = (u_char *) malloc(sizeof(u_char) * cmaplen); +#else + if (0) { +#endif if (!cmap->red) { perror("red lut malloc error\n"); +#if defined(__linux__) return (struct fb_cmap *)-1; +#elif defined(__FreeBSD__) + return (video_color_palette_t *)-1; +#endif } } +#if defined(__linux__) if (vscinfo->green.length) { cmap->green = (__u16 *) malloc(sizeof(__u16) * cmaplen); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[1]) { + cmap->green = (u_char *) malloc(sizeof(u_char) * cmaplen); +#else + if (0) { +#endif if (!cmap->green) { +#if defined(__linux__) if (vscinfo->red.length) free(cmap->red); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[0]) + free(cmap->red); +#endif perror("green lut malloc error\n"); +#if defined(__linux__) return (struct fb_cmap *)-1; +#elif defined(__FreeBSD__) + return (video_color_palette_t *)-1; +#endif } } +#if defined(__linux__) if (vscinfo->blue.length) { cmap->blue = (__u16 *) malloc(sizeof(__u16) * cmaplen); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[2]) { + cmap->blue = (u_char *) malloc(sizeof(u_char) * cmaplen); +#else + if (0) { +#endif if (!cmap->blue) { +#if defined(__linux__) if (vscinfo->red.length) free(cmap->red); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[0]) + free(cmap->red); +#endif +#if defined(__linux__) if (vscinfo->green.length) free(cmap->green); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[1]) + free(cmap->green); +#endif perror("blue lut malloc error\n"); +#if defined(__linux__) return (struct fb_cmap *)-1; +#elif defined(__FreeBSD__) + return (video_color_palette_t *)-1; +#endif } } +#if defined(__linux__) if (vscinfo->transp.length) { cmap->transp = (__u16 *) malloc(sizeof(__u16) * cmaplen); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[3]) { + cmap->transparent = (u_char *) malloc(sizeof(u_char) * cmaplen); +#else + if (0) { +#endif +#if defined(__linux__) if (!cmap->transp) { +#elif defined(__FreeBSD__) + if (!cmap->transparent) { +#else + if (0) { +#endif +#if defined(__linux__) if (vscinfo->red.length) free(cmap->red); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[0]) + free(cmap->red); +#endif +#if defined(__linux__) if (vscinfo->green.length) free(cmap->green); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[1]) + free(cmap->green); +#endif +#if defined(__linux__) if (vscinfo->blue.length) free(cmap->blue); perror("transp lut malloc error\n"); +#elif defined(__FreeBSD__) + if (video_info->vi_pixel_fsizes[2]) + free(cmap->blue); + perror("transparent lut malloc error\n"); +#endif +#if defined(__linux__) return (struct fb_cmap *)-1; +#elif defined(__FreeBSD__) + return (video_color_palette_t *)-1; +#endif } } +#if defined(__linux__) cmap->len = cmaplen; +#elif defined(__FreeBSD__) + cmap->count = cmaplen; +#endif return cmap; } +#if defined(__linux__) static void fb_cmap_destroy(struct fb_cmap *cmap) +#elif defined(__FreeBSD__) +static void +fb_cmap_destroy(video_color_palette_t *cmap) +#endif { if (cmap->red) free(cmap->red); @@ -580,28 +907,57 @@ fb_cmap_destroy(struct fb_cmap *cmap) free(cmap->green); if (cmap->blue) free(cmap->blue); +#if defined(__linux__) if (cmap->transp) free(cmap->transp); +#elif defined(__FreeBSD__) + if (cmap->transparent) + free(cmap->transparent); +#endif free(cmap); } +#if defined(__linux__) static int fb_cmap_get(int fbfp, struct fb_cmap *cmap) +#elif defined(__FreeBSD__) +static int +fb_cmap_get(int fbfp, video_color_palette_t *cmap) +#endif { +#if defined(__linux__) if (ioctl(fbfp, FBIOGETCMAP, cmap)) { perror("ioctl FBIOGETCMAP error\n"); return -1; } +#elif defined(__FreeBSD__) + if (ioctl(fbfp, FBIO_GETPALETTE, cmap) == -1) { + perror("ioctl FBIO_GETPALETTE error\n"); + return -1; + } +#endif return 0; } +#if defined(__linux__) static int fb_cmap_set(int fbfp, struct fb_cmap *cmap) +#elif defined(__FreeBSD__) +static int +fb_cmap_set(int fbfp, video_color_palette_t *cmap) +#endif { +#if defined(__linux__) if (ioctl(fbfp, FBIOPUTCMAP, cmap)) { perror("ioctl FBIOPUTCMAP error\n"); return -1; } +#elif defined(__FreeBSD__) + if (ioctl(fbfp, FBIO_SETPALETTE, cmap) == -1) { + perror("ioctl FBIO_SETPALETTE error\n"); + return -1; + } +#endif return 0; } @@ -612,10 +968,16 @@ fb_cmap_set(int fbfp, struct fb_cmap *cmap) * fb_munmap() deletes the mappings */ +#if defined(__linux__) static void * fb_mmap(int fbfp, struct fb_fix_screeninfo *scinfo) +#elif defined(__FreeBSD__) +static void * +fb_mmap(int fbfp, video_adapter_info_t *video_adapter_info) +#endif { void *buf; +#if defined(__linux__) if ((buf = (unsigned char *) mmap(NULL, scinfo->smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfp, (off_t) 0)) @@ -623,13 +985,41 @@ fb_mmap(int fbfp, struct fb_fix_screeninfo *scinfo) perror("mmap error"); return NULL; } +#elif defined(__FreeBSD__) + size_t mmap_offset; + size_t mmap_length; + mmap_offset = (size_t)(video_adapter_info->va_window) & (PAGE_MASK); + mmap_length = (size_t)(video_adapter_info->va_window_size + + mmap_offset + PAGE_MASK) & (~PAGE_MASK); + if ((buf = (unsigned char *) + mmap(NULL, mmap_length, PROT_READ | PROT_WRITE, MAP_SHARED, fbfp, + (off_t) 0)) + == MAP_FAILED) { + perror("mmap error"); + return NULL; + } +#endif return buf; } +#if defined(__linux__) static int fb_munmap(void *buf, struct fb_fix_screeninfo *scinfo) +#elif defined(__FreeBSD__) +static int +fb_munmap(void *buf, video_adapter_info_t *video_adapter_info) +#endif { +#if defined(__linux__) return munmap(buf, scinfo->smem_len); +#elif defined(__FreeBSD__) + size_t mmap_offset; + size_t mmap_length; + mmap_offset = (size_t)(video_adapter_info->va_window) & (PAGE_MASK); + mmap_length = (size_t)(video_adapter_info->va_window_size + + mmap_offset + PAGE_MASK) & (~PAGE_MASK); + return munmap((void *)((u_long)buf & (~PAGE_MASK)), mmap_length); +#endif } /* @@ -637,6 +1027,7 @@ fb_munmap(void *buf, struct fb_fix_screeninfo *scinfo) * * fb_fscrn_get() get information */ +#if defined(__linux__) static int fb_fscrn_get(int fbfp, struct fb_fix_screeninfo *scinfo) { @@ -646,12 +1037,14 @@ fb_fscrn_get(int fbfp, struct fb_fix_screeninfo *scinfo) } return 0; } +#endif /* * (struct fb_var_screeninfo) device independent variable information * * fb_vscrn_get() get information */ +#if defined(__linux__) static int fb_vscrn_get(int fbfp, struct fb_var_screeninfo *scinfo) { @@ -661,3 +1054,41 @@ fb_vscrn_get(int fbfp, struct fb_var_screeninfo *scinfo) } return 0; } +#endif + +#if defined(__FreeBSD__) +static int +fb_video_mode_get(int fbfp, int *video_mode) +{ + if (ioctl(fbfp, FBIO_GETMODE, video_mode) == -1) { + perror("ioctl FBIO_GETMODE error\n"); + return -1; + } + return 0; +} +#endif + +#if defined(__FreeBSD__) +static int +fb_video_info_get(int fbfp, video_info_t *video_info) +{ + if (ioctl(fbfp, FBIO_MODEINFO, video_info) == -1) { + perror("ioctl FBIO_MODEINFO error\n"); + return -1; + } + return 0; +} +#endif + +#if defined(__FreeBSD__) +static int +fb_video_adapter_info_get(int fbfp, video_adapter_info_t *video_adapter_info) +{ + if (ioctl(fbfp, FBIO_ADPINFO, video_adapter_info) == -1) { + perror("ioctl FBIO_ADPINFO error\n"); + return -1; + } + return 0; +} +#endif + diff --git a/w3mimg/fb/fb.h b/w3mimg/fb/fb.h index 1138bb0..5d86454 100644 --- a/w3mimg/fb/fb.h +++ b/w3mimg/fb/fb.h @@ -1,7 +1,11 @@ /* $Id: fb.h,v 1.7 2003/07/07 15:48:17 ukai Exp $ */ #ifndef fb_header #define fb_header +#if defined(__linux__) #include +#elif defined(__FreeBSD__) +#include +#endif typedef struct { int num; diff --git a/w3mimg/fb/fb_gdkpixbuf.c b/w3mimg/fb/fb_gdkpixbuf.c index 36e3b62..f1e8d97 100644 --- a/w3mimg/fb/fb_gdkpixbuf.c +++ b/w3mimg/fb/fb_gdkpixbuf.c @@ -6,7 +6,7 @@ #include "config.h" #if defined(USE_GTK2) #include -#include +#include #endif #include #include "fb.h" diff --git a/w3mimg/fb/fb_imlib2.c b/w3mimg/fb/fb_imlib2.c index ea36637..1a5151c 100644 --- a/w3mimg/fb/fb_imlib2.c +++ b/w3mimg/fb/fb_imlib2.c @@ -3,7 +3,6 @@ fb_imlib2.c 0.3 Copyright (C) 2002, hito **************************************************************************/ -#include #include #include "fb.h" #include "fb_img.h" diff --git a/w3mimg/fb/fb_w3mimg.c b/w3mimg/fb/fb_w3mimg.c index d3ae5a9..62511f0 100644 --- a/w3mimg/fb/fb_w3mimg.c +++ b/w3mimg/fb/fb_w3mimg.c @@ -153,10 +153,15 @@ check_tty_console(char *tty) return 0; if (strncmp(tty, "/dev/", 5) == 0) tty += 5; +#if defined(__linux__) if (strncmp(tty, "tty", 3) == 0 && isdigit(*(tty + 3))) return 1; if (strncmp(tty, "vc/", 3) == 0 && isdigit(*(tty + 3))) return 1; +#elif defined(__FreeBSD__) + if (strncmp(tty, "ttyv", 4) == 0 && isxdigit(*(tty + 4))) + return 1; +#endif return 0; } #else @@ -172,7 +177,9 @@ w3mimg_fbopen() return NULL; memset(wop, 0, sizeof(w3mimg_op)); - if (!check_tty_console(getenv("W3M_TTY")) && strcmp("jfbterm", getenv("TERM")) != 0) { + if (!check_tty_console(getenv("W3M_TTY")) && + strncmp("fbterm", getenv("TERM"), 6) != 0 && + strncmp("jfbterm", getenv("TERM"), 7) != 0) { fprintf(stderr, "w3mimgdisplay/fb: tty is not console\n"); goto error; } diff --git a/w3mimg/fb/readme.txt b/w3mimg/fb/readme.txt index 92e71a5..c3c43cd 100644 --- a/w3mimg/fb/readme.txt +++ b/w3mimg/fb/readme.txt @@ -1,73 +1,73 @@ Source: http://homepage3.nifty.com/slokar/fb/ original readme.txt -■提供するもの - ・w3mimgdisplayfb w3mimgdisplay (ほぼ)互換の framebuffer 用画像ビューア - ・w3mimgsizefb w3mimgsize 互換の画像サイズ報告プログラム +箴 + w3mimgdisplayfb w3mimgdisplay (祉)篋 framebuffer 糸ャ若 + w3mimgsizefb w3mimgsize 篋糸泣ゃ阪怨違 -■必要なもの - ・GdkPixbuf or Imlib2 - ・TRUE-COLOR の framebuffer を利用できる環境 +綽荀 + GdkPixbuf or Imlib2 + TRUE-COLOR framebuffer с医 -■コンパイル - ・Makefile の CFLAGS, LDFLAGS を Imlib2, GdkPixbuf のどちらか利用する - 方を有効にしてから make してださい。 +潟潟ゃ + Makefile CFLAGS, LDFLAGS Imlib2, GdkPixbuf < + 鴻鴻 make -■利用法 - ・w3mimgdisplay, w3mimgsize と同様 +羈 + w3mimgdisplay, w3mimgsize 罕 -■制限等 - ・framebuffer は 15,16,24,32bpp PACKED-PIXELS TRUE-COLOR - にしか対応していません。 - ・現在 w3mimgdisplayfb は -bg オプションを使用しない場合の背景色は黒 - (#000000)と仮定しています。 +狗膈 + 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 +榊医 + 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 を参照してください。 +篁 + 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 +∫ 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 - 描画の高速化 +絮ユ + 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 + 祉蕭 -■連絡先 +g機 ZXB01226@nifty.com http://homepage3.nifty.com/slokar/ diff --git a/w3mimg/win/.cvsignore b/w3mimg/win/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/w3mimg/win/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/w3mimg/x11/.cvsignore b/w3mimg/x11/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/w3mimg/x11/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/w3mimg/x11/x11_w3mimg.c b/w3mimg/x11/x11_w3mimg.c index f5be4a8..9a539de 100644 --- a/w3mimg/x11/x11_w3mimg.c +++ b/w3mimg/x11/x11_w3mimg.c @@ -14,7 +14,7 @@ #elif defined(USE_GDKPIXBUF) #if defined(USE_GTK2) #include -#include +#include #include #else #include @@ -121,24 +121,32 @@ x11_init(w3mimg_op * self) if (self == NULL) return 0; xi = (struct x11_info *)self->priv; +#if defined(USE_IMLIB) 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) { + if (!xi) { +#if defined(USE_GTK2) + g_type_init(); +#endif + } + else if (!xi->init_flag) { + XWindowAttributes attr; #if defined(USE_GTK2) g_type_init(); #endif - gdk_pixbuf_xlib_init(xi->display, 0); + XGetWindowAttributes(xi->display, xi->parent, &attr); + /* gdk_pixbuf_xlib_init_with_depth() ignores depth, sigh... */ + gdk_pixbuf_xlib_init_with_depth(xi->display, 0, attr.depth); xi->init_flag = TRUE; } #endif - if (!xi->imageGC) { + if (xi && !xi->imageGC) { xi->imageGC = XCreateGC(xi->display, xi->parent, 0, NULL); if (!xi->imageGC) return 0; @@ -200,14 +208,16 @@ x11_set_background(w3mimg_op * self, char *background) { XColor screen_def, exact_def; struct x11_info *xi; + XWindowAttributes attr; if (self == NULL) return; xi = (struct x11_info *)self->priv; if (xi == NULL) return; + XGetWindowAttributes(xi->display, xi->window, &attr); if (background && - XAllocNamedColor(xi->display, DefaultColormap(xi->display, 0), + XAllocNamedColor(xi->display, attr.colormap, background, &screen_def, &exact_def)) xi->background_pixel = screen_def.pixel; else { @@ -216,7 +226,7 @@ x11_set_background(w3mimg_op * self, char *background) XImage *i; p = XCreatePixmap(xi->display, xi->window, 1, 1, - DefaultDepth(xi->display, 0)); + attr.depth); gc = XCreateGC(xi->display, xi->window, 0, NULL); if (!p || !gc) exit(1); /* XXX */ @@ -258,6 +268,7 @@ x11_img_new(struct x11_info *xi, int w, int h, int n) { struct x11_image *img = NULL; int i; + XWindowAttributes attr; img = malloc(sizeof(*img)); if (!img) @@ -267,9 +278,10 @@ x11_img_new(struct x11_info *xi, int w, int h, int n) if (!img->pixmap) goto ERROR; + XGetWindowAttributes(xi->display, xi->window, &attr); for (i = 0; i < n; i++) { img->pixmap[i] = XCreatePixmap(xi->display, xi->parent, w, h, - DefaultDepth(xi->display, 0)); + attr.depth); if (!img->pixmap[i]) goto ERROR; @@ -318,6 +330,41 @@ resize_image(GdkPixbuf * pixbuf, int width, int height) return NULL; return resized_pixbuf; } + +#if defined(USE_GTK2) +static void +render_pixbuf_to_pixmap_32(Display *display, GC gc, Pixmap pixmap, GdkPixbuf * pixbuf) +{ + unsigned int x, y, width, height, rowstride, bytes_per_pixel; + unsigned char *line; + XImage *image; + + width = gdk_pixbuf_get_width(pixbuf) ; + height = gdk_pixbuf_get_height(pixbuf) ; + + if (!(image = XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap))) + return ; + + bytes_per_pixel = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3; + rowstride = gdk_pixbuf_get_rowstride(pixbuf); + line = gdk_pixbuf_get_pixels(pixbuf); + + for (y = 0; y < height; y++) { + u_char *pixel; + + pixel = line; + for (x = 0; x < width; x++) { + XPutPixel(image, x, y, + (pixel[0] <<16) | (pixel[1] <<8) | pixel[2] | 0xff000000); + pixel += bytes_per_pixel; + } + line += rowstride; + } + + XPutImage(display, pixmap, gc, image, 0, 0, 0, 0, width, height); + XDestroyImage(image); +} +#endif #endif static int @@ -342,6 +389,7 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) GList *frames; #endif #endif + XWindowAttributes attr; if (self == NULL) return 0; @@ -349,6 +397,7 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) if (xi == NULL) return 0; + XGetWindowAttributes(xi->display, xi->window, &attr); #if defined(USE_IMLIB) im = Imlib_load_image(xi->id, fname); if (!im) @@ -358,7 +407,7 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) if (h <= 0) h = im->rgb_height; img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h, - DefaultDepth(xi->display, 0)); + attr.depth); if (!img->pixmap) return 0; XSetForeground(xi->display, xi->imageGC, xi->background_pixel); @@ -374,17 +423,21 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) w = imlib_image_get_width(); if (h <= 0) h = imlib_image_get_height(); + + im = imlib_create_cropped_scaled_image(0, 0, imlib_image_get_width(), imlib_image_get_height(), w, h); + imlib_context_set_image(im); + img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h, - DefaultDepth(xi->display, 0)); + attr.depth); 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_visual(attr.visual); + imlib_context_set_colormap(attr.colormap); imlib_context_set_drawable((Drawable) img->pixmap); - imlib_render_image_on_drawable_at_size(0, 0, w, h); + imlib_render_image_on_drawable(0, 0); imlib_free_image(); #elif defined(USE_GDKPIXBUF) max_anim = self->max_anim; @@ -416,7 +469,7 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) ratio_h = 1.0 * h / ih; } tmp_pixmap = XCreatePixmap(xi->display, xi->parent, w, h, - DefaultDepth(xi->display, 0)); + attr.depth); XSetForeground(xi->display, xi->imageGC, xi->background_pixel); XFillRectangle(xi->display, (Pixmap) tmp_pixmap, xi->imageGC, 0, 0, w, h); if (!tmp_pixmap) { @@ -459,7 +512,10 @@ x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) if (delay > ximg->delay) ximg->delay = delay; - gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, + if (attr.depth == 32) + render_pixbuf_to_pixmap_32(xi->display, xi->imageGC, ximg->pixmap[j], pixbuf); + else + gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, (Drawable) ximg->pixmap[j], 0, 0, 0, 0, w, h, GDK_PIXBUF_ALPHA_BILEVEL, 1, @@ -653,9 +709,11 @@ x11_get_image_size(w3mimg_op * self, W3MImage * img, char *fname, int *w, if (self == NULL) return 0; +#if defined(USE_IMLIB) && defined(USE_IMLIB2) xi = (struct x11_info *)self->priv; if (xi == NULL) return 0; +#endif #if defined(USE_IMLIB) im = Imlib_load_image(xi->id, fname); @@ -755,6 +813,9 @@ w3mimg_x11open() return NULL; memset(wop, 0, sizeof(w3mimg_op)); + if (getenv("W3M_USE_REMOTE_IMAGE")) + goto end; + xi = (struct x11_info *)malloc(sizeof(struct x11_info)); if (xi == NULL) goto error; @@ -807,6 +868,7 @@ w3mimg_x11open() wop->priv = xi; + end: wop->init = x11_init; wop->finish = x11_finish; wop->active = x11_active; -- cgit v1.2.3