1 /* $Id: x11_w3mimg.c,v 1.29 2004/11/08 17:14:06 ukai Exp $ */
10 #elif defined(USE_IMLIB2)
12 #include <X11/Xutil.h>
14 #elif defined(USE_GDKPIXBUF)
16 #include <glib-object.h>
18 #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
20 #include <gdk-pixbuf/gdk-pixbuf-xlib.h>
23 #error no Imlib and GdkPixbuf support
26 #include "w3mimg/w3mimg.h"
33 Window window, parent;
34 unsigned long background_pixel;
36 #if defined(USE_IMLIB)
38 #elif defined(USE_GDKPIXBUF)
43 #if defined(USE_GDKPIXBUF)
54 get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay)
56 GdkPixbufAnimationIter *iter;
60 g_get_current_time(&time);
61 iter = gdk_pixbuf_animation_get_iter(animation, &time);
62 *w = gdk_pixbuf_animation_get_width(animation);
63 *h = gdk_pixbuf_animation_get_height(animation);
65 gdk_pixbuf_animation_iter_on_currently_loading_frame(iter) != TRUE;
68 tmp = gdk_pixbuf_animation_iter_get_delay_time(iter);
69 g_time_val_add(&time, tmp * 1000);
72 gdk_pixbuf_animation_iter_advance(iter, &time);
76 g_object_unref(G_OBJECT(iter));
82 get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay)
85 int iw, ih, n, i, d = -1;
87 frames = gdk_pixbuf_animation_get_frames(animation);
88 n = gdk_pixbuf_animation_get_num_frames(animation);
89 *w = gdk_pixbuf_animation_get_width(animation);
90 *h = gdk_pixbuf_animation_get_height(animation);
91 for (i = 0; i < n; i++) {
92 GdkPixbufFrame *frame;
96 frame = (GdkPixbufFrame *) g_list_nth_data(frames, i);
97 tmp = gdk_pixbuf_frame_get_delay_time(frame);
100 pixbuf = gdk_pixbuf_frame_get_pixbuf(frame);
101 iw = gdk_pixbuf_frame_get_x_offset(frame)
102 + gdk_pixbuf_get_width(pixbuf);
103 ih = gdk_pixbuf_frame_get_y_offset(frame)
104 + gdk_pixbuf_get_height(pixbuf);
118 x11_init(w3mimg_op * self)
123 xi = (struct x11_info *)self->priv;
126 #if defined(USE_IMLIB)
128 xi->id = Imlib_init(xi->display);
132 #elif defined(USE_GDKPIXBUF)
133 if (!xi->init_flag) {
134 #if defined(USE_GTK2)
137 gdk_pixbuf_xlib_init(xi->display, 0);
138 xi->init_flag = TRUE;
142 xi->imageGC = XCreateGC(xi->display, xi->parent, 0, NULL);
150 x11_finish(w3mimg_op * self)
155 xi = (struct x11_info *)self->priv;
159 XFreeGC(xi->display, xi->imageGC);
166 x11_clear(w3mimg_op * self, int x, int y, int w, int h)
171 xi = (struct x11_info *)self->priv;
180 XClearArea(xi->display, xi->window, x, y, w, h, False);
185 x11_active(w3mimg_op * self)
190 xi = (struct x11_info *)self->priv;
199 x11_set_background(w3mimg_op * self, char *background)
201 XColor screen_def, exact_def;
205 xi = (struct x11_info *)self->priv;
210 XAllocNamedColor(xi->display, DefaultColormap(xi->display, 0),
211 background, &screen_def, &exact_def))
212 xi->background_pixel = screen_def.pixel;
218 p = XCreatePixmap(xi->display, xi->window, 1, 1,
219 DefaultDepth(xi->display, 0));
220 gc = XCreateGC(xi->display, xi->window, 0, NULL);
223 XCopyArea(xi->display, xi->window, p, gc,
224 (self->offset_x >= 1) ? (self->offset_x - 1) : 0,
225 (self->offset_y >= 1) ? (self->offset_y - 1) : 0,
227 i = XGetImage(xi->display, p, 0, 0, 1, 1, -1, ZPixmap);
230 xi->background_pixel = XGetPixel(i, 0, 0);
232 XFreeGC(xi->display, gc);
233 XFreePixmap(xi->display, p);
238 x11_sync(w3mimg_op * self)
243 xi = (struct x11_info *)self->priv;
246 XSync(xi->display, False);
250 x11_close(w3mimg_op * self)
252 /* XCloseDisplay(xi->display); */
255 #if defined(USE_GDKPIXBUF)
256 static struct x11_image *
257 x11_img_new(struct x11_info *xi, int w, int h, int n)
259 struct x11_image *img = NULL;
262 img = malloc(sizeof(*img));
266 img->pixmap = calloc(n, sizeof(*(img->pixmap)));
270 for (i = 0; i < n; i++) {
271 img->pixmap[i] = XCreatePixmap(xi->display, xi->parent, w, h,
272 DefaultDepth(xi->display, 0));
276 XSetForeground(xi->display, xi->imageGC, xi->background_pixel);
277 XFillRectangle(xi->display, (Pixmap) img->pixmap[i], xi->imageGC, 0, 0,
290 for (i = 0; i < n; i++) {
292 XFreePixmap(xi->display, (Pixmap) img->pixmap[i]);
302 resize_image(GdkPixbuf * pixbuf, int width, int height)
304 GdkPixbuf *resized_pixbuf;
309 w = gdk_pixbuf_get_width(pixbuf);
310 h = gdk_pixbuf_get_height(pixbuf);
311 if (width < 1 || height < 1)
313 if (w == width && h == height)
316 gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
317 if (resized_pixbuf == NULL)
319 return resized_pixbuf;
324 x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h)
327 #if defined(USE_IMLIB)
329 #elif defined(USE_IMLIB2)
331 #elif defined(USE_GDKPIXBUF)
332 GdkPixbufAnimation *animation;
333 int j, iw, ih, n, frame_num, delay = -1, max_anim;
334 double ratio_w, ratio_h;
335 struct x11_image *ximg;
337 #if defined(USE_GTK2)
338 GdkPixbufAnimationIter *iter;
348 xi = (struct x11_info *)self->priv;
352 #if defined(USE_IMLIB)
353 im = Imlib_load_image(xi->id, fname);
360 img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h,
361 DefaultDepth(xi->display, 0));
364 XSetForeground(xi->display, xi->imageGC, xi->background_pixel);
365 XFillRectangle(xi->display, (Pixmap) img->pixmap, xi->imageGC, 0, 0, w, h);
366 Imlib_paste_image(xi->id, im, (Pixmap) img->pixmap, 0, 0, w, h);
367 Imlib_kill_image(xi->id, im);
368 #elif defined(USE_IMLIB2)
369 im = imlib_load_image(fname);
372 imlib_context_set_image(im);
374 w = imlib_image_get_width();
376 h = imlib_image_get_height();
377 img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h,
378 DefaultDepth(xi->display, 0));
381 XSetForeground(xi->display, xi->imageGC, xi->background_pixel);
382 XFillRectangle(xi->display, (Pixmap) img->pixmap, xi->imageGC, 0, 0, w, h);
383 imlib_context_set_display(xi->display);
384 imlib_context_set_visual(DefaultVisual(xi->display, 0));
385 imlib_context_set_colormap(DefaultColormap(xi->display, 0));
386 imlib_context_set_drawable((Drawable) img->pixmap);
387 imlib_render_image_on_drawable_at_size(0, 0, w, h);
389 #elif defined(USE_GDKPIXBUF)
390 max_anim = self->max_anim;
391 #if defined(USE_GTK2)
392 animation = gdk_pixbuf_animation_new_from_file(fname, NULL);
394 animation = gdk_pixbuf_animation_new_from_file(fname);
398 frame_num = n = get_animation_size(animation, &iw, &ih, &delay);
403 frame_num = (-max_anim > n) ? n : -max_anim;
405 else if (max_anim > 0) {
406 frame_num = n = (max_anim > n) ? n : max_anim;
409 if (w < 1 || h < 1) {
412 ratio_w = ratio_h = 1;
415 ratio_w = 1.0 * w / iw;
416 ratio_h = 1.0 * h / ih;
418 tmp_pixmap = XCreatePixmap(xi->display, xi->parent, w, h,
419 DefaultDepth(xi->display, 0));
420 XSetForeground(xi->display, xi->imageGC, xi->background_pixel);
421 XFillRectangle(xi->display, (Pixmap) tmp_pixmap, xi->imageGC, 0, 0, w, h);
423 #if defined(USE_GTK2)
424 g_object_unref(G_OBJECT(animation));
426 gdk_pixbuf_animation_unref(animation);
430 ximg = x11_img_new(xi, w, h, frame_num);
432 XFreePixmap(xi->display, tmp_pixmap);
433 #if defined(USE_GTK2)
434 g_object_unref(G_OBJECT(animation));
436 gdk_pixbuf_animation_unref(animation);
440 #if defined(USE_GTK2)
441 g_get_current_time(&time);
442 iter = gdk_pixbuf_animation_get_iter(animation, &time);
444 if (max_anim < 0 && n > -max_anim) {
445 max_anim = n + max_anim;
446 for (j = 0; j < max_anim; j++) {
447 delay = gdk_pixbuf_animation_iter_get_delay_time(iter);
448 g_time_val_add(&time, delay * 1000);
449 gdk_pixbuf_animation_iter_advance(iter, &time);
452 for (j = 0; j < frame_num; j++) {
453 GdkPixbuf *org_pixbuf, *pixbuf;
455 org_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter);
456 delay = gdk_pixbuf_animation_iter_get_delay_time(iter);
457 pixbuf = resize_image(org_pixbuf, w, h);
459 if (delay > ximg->delay)
462 gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf,
463 (Drawable) ximg->pixmap[j], 0,
465 GDK_PIXBUF_ALPHA_BILEVEL, 1,
466 XLIB_RGB_DITHER_NORMAL, 0, 0);
467 if (org_pixbuf != pixbuf)
468 g_object_unref(G_OBJECT(pixbuf));
469 g_time_val_add(&time, delay * 1000);
470 gdk_pixbuf_animation_iter_advance(iter, &time);
472 XFreePixmap(xi->display, tmp_pixmap);
473 g_object_unref(G_OBJECT(animation));
476 frames = gdk_pixbuf_animation_get_frames(animation);
478 for (j = 0; j < n; j++) {
479 GdkPixbufFrame *frame;
480 GdkPixbuf *org_pixbuf, *pixbuf;
481 int width, height, ofstx, ofsty;
484 i = (j - n + frame_num > 0) ? (j - n + frame_num) : 0;
489 frame = (GdkPixbufFrame *) g_list_nth_data(frames, j);
490 org_pixbuf = gdk_pixbuf_frame_get_pixbuf(frame);
491 ofstx = gdk_pixbuf_frame_get_x_offset(frame);
492 ofsty = gdk_pixbuf_frame_get_y_offset(frame);
493 delay = gdk_pixbuf_frame_get_delay_time(frame);
494 width = gdk_pixbuf_get_width(org_pixbuf);
495 height = gdk_pixbuf_get_height(org_pixbuf);
497 if (ofstx == 0 && ofsty == 0 && width == w && height == h) {
498 pixbuf = resize_image(org_pixbuf, w, h);
502 resize_image(org_pixbuf, width * ratio_w, height * ratio_h);
506 width = gdk_pixbuf_get_width(pixbuf);
507 height = gdk_pixbuf_get_height(pixbuf);
509 if (delay > ximg->delay)
512 XCopyArea(xi->display, tmp_pixmap, ximg->pixmap[i],
513 xi->imageGC, 0, 0, w, h, 0, 0);
514 gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf,
515 (Drawable) ximg->pixmap[i], 0,
516 0, ofstx, ofsty, width,
518 GDK_PIXBUF_ALPHA_BILEVEL, 1,
519 XLIB_RGB_DITHER_NORMAL, 0, 0);
521 switch (gdk_pixbuf_frame_get_action(frame)) {
522 case GDK_PIXBUF_FRAME_RETAIN:
523 XCopyArea(xi->display, ximg->pixmap[i], tmp_pixmap,
524 xi->imageGC, 0, 0, w, h, 0, 0);
526 case GDK_PIXBUF_FRAME_DISPOSE:
527 XSetForeground(xi->display, xi->imageGC, xi->background_pixel);
528 XFillRectangle(xi->display, tmp_pixmap, xi->imageGC,
531 case GDK_PIXBUF_FRAME_REVERT:
532 XCopyArea(xi->display, ximg->pixmap[0], tmp_pixmap,
533 xi->imageGC, 0, 0, w, h, 0, 0);
536 XCopyArea(xi->display, ximg->pixmap[0], tmp_pixmap,
537 xi->imageGC, 0, 0, w, h, 0, 0);
542 if (org_pixbuf != pixbuf)
543 gdk_pixbuf_finalize(pixbuf);
546 XFreePixmap(xi->display, tmp_pixmap);
547 gdk_pixbuf_animation_unref(animation);
558 x11_show_image(w3mimg_op * self, W3MImage * img, int sx, int sy, int sw,
559 int sh, int x, int y)
562 #if defined(USE_GDKPIXBUF)
563 struct x11_image *ximg = img->pixmap;
569 if (img->pixmap == NULL)
572 xi = (struct x11_info *)self->priv;
576 #if defined(USE_IMLIB) || defined(USE_IMLIB2)
577 XCopyArea(xi->display, (Pixmap) img->pixmap, xi->window, xi->imageGC,
579 (sw ? sw : img->width),
580 (sh ? sh : img->height), x + self->offset_x, y + self->offset_y);
581 #elif defined(USE_GDKPIXBUF)
583 if (ximg->delay <= 0)
587 XCopyArea(xi->display, ximg->pixmap[i], xi->window, xi->imageGC,
589 (sw ? sw : img->width),
590 (sh ? sh : img->height), x + self->offset_x, y + self->offset_y);
591 if (ximg->total > 1) {
592 if (ximg->wait > WAIT_CNT) {
594 if (i < ximg->total - 1)
606 x11_free_image(w3mimg_op * self, W3MImage * img)
611 xi = (struct x11_info *)self->priv;
614 #if defined(USE_IMLIB) || defined(USE_IMLIB2)
615 if (img && img->pixmap) {
616 XFreePixmap(xi->display, (Pixmap) img->pixmap);
621 #elif defined(USE_GDKPIXBUF)
622 if (img && img->pixmap) {
623 struct x11_image *ximg = img->pixmap;
627 for (i = 0; i < n; i++) {
629 XFreePixmap(xi->display, (Pixmap) ximg->pixmap[i]);
642 x11_get_image_size(w3mimg_op * self, W3MImage * img, char *fname, int *w,
646 #if defined(USE_IMLIB)
648 #elif defined(USE_IMLIB2)
650 #elif defined(USE_GDKPIXBUF)
651 GdkPixbufAnimation *animation;
656 xi = (struct x11_info *)self->priv;
660 #if defined(USE_IMLIB)
661 im = Imlib_load_image(xi->id, fname);
667 Imlib_kill_image(xi->id, im);
668 #elif defined(USE_IMLIB2)
669 im = imlib_load_image(fname);
673 imlib_context_set_image(im);
674 *w = imlib_image_get_width();
675 *h = imlib_image_get_height();
677 #elif defined(USE_GDKPIXBUF)
678 #if defined(USE_GTK2)
679 animation = gdk_pixbuf_animation_new_from_file(fname, NULL);
681 animation = gdk_pixbuf_animation_new_from_file(fname);
686 get_animation_size(animation, w, h, NULL);
687 #if defined(USE_GTK2)
688 g_object_unref(G_OBJECT(animation));
690 gdk_pixbuf_animation_unref(animation);
698 xterm/kterm/hanterm/cxterm
699 top window (WINDOWID)
702 rxvt/aterm/Eterm/wterm
703 top window (WINDOWID)
709 +- text window (WINDOWID)
714 +- text window (WINDOWID)
717 top window = text window (WINDOWID)
745 w3mimg_op *wop = NULL;
746 struct x11_info *xi = NULL;
749 unsigned int nchildren;
750 XWindowAttributes attr;
751 Window root, *children;
753 wop = (w3mimg_op *) malloc(sizeof(w3mimg_op));
756 memset(wop, 0, sizeof(w3mimg_op));
758 xi = (struct x11_info *)malloc(sizeof(struct x11_info));
761 memset(xi, 0, sizeof(struct x11_info));
763 xi->display = XOpenDisplay(NULL);
764 if (xi->display == NULL) {
767 if ((id = getenv("WINDOWID")) != NULL)
768 xi->window = (Window) atoi(id);
770 XGetInputFocus(xi->display, &xi->window, &revert);
774 XGetWindowAttributes(xi->display, xi->window, &attr);
775 wop->width = attr.width;
776 wop->height = attr.height;
781 XQueryTree(xi->display, xi->window, &root, &xi->parent,
782 &children, &nchildren);
783 p_window = xi->window;
784 for (i = 0; i < nchildren; i++) {
785 XGetWindowAttributes(xi->display, children[i], &attr);
786 if (attr.width > wop->width * 0.7 &&
787 attr.height > wop->height * 0.7) {
788 /* maybe text window */
789 wop->width = attr.width;
790 wop->height = attr.height;
791 xi->window = children[i];
794 if (p_window == xi->window)
797 wop->offset_x = OFFSET_X;
798 for (i = 0; i < nchildren; i++) {
799 XGetWindowAttributes(xi->display, children[i], &attr);
800 if (attr.x <= 0 && attr.width < 30 && attr.height > wop->height * 0.7) {
801 /* scrollbar of xterm/kterm ? */
802 wop->offset_x += attr.x + attr.width + attr.border_width * 2;
806 wop->offset_y = OFFSET_Y;
810 wop->init = x11_init;
811 wop->finish = x11_finish;
812 wop->active = x11_active;
813 wop->set_background = x11_set_background;
814 wop->sync = x11_sync;
815 wop->close = x11_close;
816 wop->clear = x11_clear;
818 wop->load_image = x11_load_image;
819 wop->show_image = x11_show_image;
820 wop->free_image = x11_free_image;
821 wop->get_image_size = x11_get_image_size;