diff options
| author | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:05:14 +0000 | 
|---|---|---|
| committer | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:05:14 +0000 | 
| commit | 72f72d64a422d6628c4796f5c0bf2e508f134214 (patch) | |
| tree | 0c9ea90cc53310832c977265521fb44db24a515e /w3mimg/fb | |
| parent | Adding upstream version 0.3 (diff) | |
| download | w3m-72f72d64a422d6628c4796f5c0bf2e508f134214.tar.gz w3m-72f72d64a422d6628c4796f5c0bf2e508f134214.zip | |
Adding upstream version 0.5.1upstream/0.5.1
Diffstat (limited to 'w3mimg/fb')
| -rw-r--r-- | w3mimg/fb/.cvsignore | 1 | ||||
| -rw-r--r-- | w3mimg/fb/Makefile.in | 35 | ||||
| -rw-r--r-- | w3mimg/fb/fb.c | 663 | ||||
| -rw-r--r-- | w3mimg/fb/fb.h | 34 | ||||
| -rw-r--r-- | w3mimg/fb/fb_gdkpixbuf.c | 209 | ||||
| -rw-r--r-- | w3mimg/fb/fb_img.c | 32 | ||||
| -rw-r--r-- | w3mimg/fb/fb_img.h | 11 | ||||
| -rw-r--r-- | w3mimg/fb/fb_imlib2.c | 126 | ||||
| -rw-r--r-- | w3mimg/fb/fb_w3mimg.c | 202 | ||||
| -rw-r--r-- | w3mimg/fb/readme.txt | 73 | 
10 files changed, 1386 insertions, 0 deletions
| 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/ | 
