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