1 /*
2 * Copyright (C) 2004-2021 Kim Woelders
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies of the Software, its documentation and marketing & publicity
13 * materials, and acknowledgment shall be given in the documentation, materials
14 * and software packages that this Software was used.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #include "config.h"
24
25 #include <Imlib2.h>
26 #include <X11/Xlib.h>
27 #if USE_XRENDER
28 #include <X11/extensions/Xrender.h>
29 #endif
30
31 #include "E.h"
32 #include "eimage.h"
33 #include "file.h"
34 #include "xwin.h"
35
36 #define IMG_CACHE_DEFAULT_SIZE (2 * 1024 * 1024)
37 #define XIM_CACHE_DEFAULT_COUNT 0
38
39 void
EImageInit(void)40 EImageInit(void)
41 {
42 EImageSetCacheSize(Conf.testing.image_cache_size);
43 EImageSetXImageCacheSize(Conf.testing.ximage_cache_count, -1);
44 imlib_set_font_cache_size(512 * 1024);
45
46 imlib_set_color_usage(128);
47
48 imlib_context_set_display(disp);
49 imlib_context_set_visual(WinGetVisual(VROOT));
50 imlib_context_set_colormap(WinGetCmap(VROOT));
51
52 #ifdef HAVE_IMLIB_CONTEXT_SET_MASK_ALPHA_THRESHOLD
53 imlib_context_set_mask_alpha_threshold(Conf.testing.mask_alpha_threshold);
54 #endif
55
56 imlib_context_set_anti_alias(0);
57 imlib_context_set_dither(1);
58 }
59
60 void
EImageExit(int quit __UNUSED__)61 EImageExit(int quit __UNUSED__)
62 {
63 #if HAVE_IMLIB_CONTEXT_DISCONNECT_DISPLAY
64 imlib_context_disconnect_display();
65 #endif
66 }
67
68 void
EImageSetCacheSize(int size)69 EImageSetCacheSize(int size)
70 {
71 Conf.testing.image_cache_size = size;
72 if (size < 0)
73 size = IMG_CACHE_DEFAULT_SIZE;
74 imlib_set_cache_size(size);
75 }
76
77 void
EImageSetXImageCacheSize(int count,int size __UNUSED__)78 EImageSetXImageCacheSize(int count, int size __UNUSED__)
79 {
80 Conf.testing.ximage_cache_count = count;
81 #if HAVE_IMLIB_XIMAGE_CACHE_CONTROL
82 if (count < 0)
83 count = XIM_CACHE_DEFAULT_COUNT;
84 imlib_set_ximage_cache_count_max(count);
85 #endif
86 }
87
88 void
EImageGetCacheInfo(ECacheInfo * ci)89 EImageGetCacheInfo(ECacheInfo * ci)
90 {
91 memset(ci, 0, sizeof(ECacheInfo));
92 ci->img.max_mem = imlib_get_cache_size();
93 #if HAVE_IMLIB_XIMAGE_CACHE_CONTROL
94 ci->img.used_mem = imlib_get_cache_used();
95 ci->xim.max_mem = imlib_get_ximage_cache_size_max();
96 ci->xim.used_mem = imlib_get_ximage_cache_size_used();
97 ci->xim.max_cnt = imlib_get_ximage_cache_count_max();
98 ci->xim.used_cnt = imlib_get_ximage_cache_count_used();
99 #endif
100 }
101
102 static void
_EImageFlagsSet(int flags)103 _EImageFlagsSet(int flags)
104 {
105 if (flags & EIMAGE_ANTI_ALIAS)
106 imlib_context_set_anti_alias(1);
107 if (flags & EIMAGE_BLEND)
108 imlib_context_set_blend(1);
109 #ifdef HAVE_IMLIB_CONTEXT_SET_MASK_ALPHA_THRESHOLD
110 if (flags & EIMAGE_HIGH_MASK_THR)
111 imlib_context_set_mask_alpha_threshold(128);
112 #endif
113 }
114
115 static void
_EImageFlagsReset(void)116 _EImageFlagsReset(void)
117 {
118 imlib_context_set_anti_alias(0);
119 imlib_context_set_blend(0);
120 #ifdef HAVE_IMLIB_CONTEXT_SET_MASK_ALPHA_THRESHOLD
121 imlib_context_set_mask_alpha_threshold(Conf.testing.mask_alpha_threshold);
122 #endif
123 }
124
125 EImage *
EImageLoad(const char * file)126 EImageLoad(const char *file)
127 {
128 return imlib_load_image(file);
129 }
130
131 EImage *
EImageLoadOrientate(const char * file,int orientation)132 EImageLoadOrientate(const char *file, int orientation)
133 {
134 EImage *im, *im2;
135 char name[2048], path[4096], *s, *s2;
136
137 snprintf(name, sizeof(name), "%s", file);
138 for (s = name, s2 = NULL; *s; s++)
139 {
140 if (*s == '/')
141 *s = '.';
142 else if (*s == '.')
143 s2 = s;
144 }
145 if (s2)
146 *s2 = '\0';
147 snprintf(path, sizeof(path), "%s/cached/cfg/%s-%d.png",
148 EDirUserCache(), name, orientation);
149
150 if (!exists(path))
151 {
152 im = imlib_load_image(file);
153 if (!im)
154 return NULL;
155
156 imlib_context_set_image(im);
157 im2 = imlib_clone_image();
158 imlib_free_image();
159
160 imlib_context_set_image(im2);
161 imlib_image_orientate(orientation);
162 imlib_image_set_format("png");
163 imlib_save_image(path);
164 imlib_free_image();
165 }
166
167 im = imlib_load_image(path);
168
169 return im;
170 }
171
172 void
EImageSave(EImage * im,const char * file)173 EImageSave(EImage * im, const char *file)
174 {
175 imlib_context_set_image(im);
176 imlib_image_set_format("png");
177 imlib_save_image(file);
178 }
179
180 EImage *
EImageCreate(int w,int h)181 EImageCreate(int w, int h)
182 {
183 EImage *im;
184
185 im = imlib_create_image(w, h);
186
187 return im;
188 }
189
190 EImage *
EImageCreateFromData(int w,int h,unsigned int * data)191 EImageCreateFromData(int w, int h, unsigned int *data)
192 {
193 EImage *im;
194
195 im = imlib_create_image_using_copied_data(w, h, data);
196
197 return im;
198 }
199
200 EImage *
EImageCreateScaled(EImage * im,int sx,int sy,int sw,int sh,int dw,int dh)201 EImageCreateScaled(EImage * im, int sx, int sy, int sw, int sh, int dw, int dh)
202 {
203 imlib_context_set_image(im);
204 if (sw <= 0)
205 sw = imlib_image_get_width();
206 if (sh <= 0)
207 sh = imlib_image_get_height();
208 if (dw <= 0)
209 dw = sw;
210 if (dh <= 0)
211 dh = sh;
212 return imlib_create_cropped_scaled_image(sx, sy, sw, sh, dw, dh);
213 }
214
215 void
EImageFree(EImage * im)216 EImageFree(EImage * im)
217 {
218 imlib_context_set_image(im);
219 imlib_free_image();
220 }
221
222 void
EImageDecache(EImage * im)223 EImageDecache(EImage * im)
224 {
225 imlib_context_set_image(im);
226 imlib_free_image_and_decache();
227 }
228
229 static int
_EImageCheckAlpha(void)230 _EImageCheckAlpha(void)
231 {
232 static const short oink = 3; /* For endianness checking */
233 unsigned char *pb, *pe;
234
235 if (!imlib_image_has_alpha())
236 return 0;
237
238 pb = (unsigned char *)imlib_image_get_data_for_reading_only();
239 if (!pb)
240 return 0;
241
242 pe = pb + 4 * imlib_image_get_width() * imlib_image_get_height();
243 pb += *((char *)(&oink));
244 for (; pb < pe; pb += 4)
245 if (*pb != 0xff)
246 return 1;
247
248 return 0;
249 }
250
251 void
EImageCheckAlpha(EImage * im)252 EImageCheckAlpha(EImage * im)
253 {
254 imlib_context_set_image(im);
255
256 if (imlib_image_has_alpha() && !_EImageCheckAlpha())
257 {
258 #if 0
259 Eprintf("Alpha set but no shape %s\n", is->real_file);
260 #endif
261 imlib_image_set_has_alpha(0);
262 }
263 }
264
265 void
EImageSetHasAlpha(EImage * im,int has_alpha)266 EImageSetHasAlpha(EImage * im, int has_alpha)
267 {
268 imlib_context_set_image(im);
269 imlib_image_set_has_alpha(has_alpha);
270 }
271
272 void
EImageSetBorder(EImage * im,EImageBorder * border)273 EImageSetBorder(EImage * im, EImageBorder * border)
274 {
275 Imlib_Border ib;
276
277 ib.left = border->left;
278 ib.right = border->right;
279 ib.top = border->top;
280 ib.bottom = border->bottom;
281 imlib_context_set_image(im);
282 imlib_image_set_border(&ib);
283
284 if (EDebug(1))
285 {
286 int l;
287
288 l = imlib_image_get_width();
289 if ((l < ib.left + ib.right) || (ib.left < 0) || (ib.left < 0))
290 Eprintf("%s: %s: Image W = %d < border L+R = %d+%d\n", __func__,
291 imlib_image_get_filename(), l, ib.left, ib.right);
292 l = imlib_image_get_height();
293 if ((l < ib.top + ib.bottom) || (ib.top < 0) || (ib.bottom < 0))
294 Eprintf("%s: %s: Image H = %d < border T+B = %d+%d\n", __func__,
295 imlib_image_get_filename(), l, ib.top, ib.bottom);
296 }
297 }
298
299 int
EImageHasAlpha(EImage * im)300 EImageHasAlpha(EImage * im)
301 {
302 imlib_context_set_image(im);
303 return imlib_image_has_alpha();
304 }
305
306 void
EImageGetSize(EImage * im,int * pw,int * ph)307 EImageGetSize(EImage * im, int *pw, int *ph)
308 {
309 imlib_context_set_image(im);
310 *pw = imlib_image_get_width();
311 *ph = imlib_image_get_height();
312 }
313
314 void *
EImageGetData(EImage * im)315 EImageGetData(EImage * im)
316 {
317 imlib_context_set_image(im);
318 return imlib_image_get_data_for_reading_only();
319 }
320
321 void
EImageFill(EImage * im,int x,int y,int w,int h,unsigned int color)322 EImageFill(EImage * im, int x, int y, int w, int h, unsigned int color)
323 {
324 int a, r, g, b;
325
326 imlib_context_set_image(im);
327 COLOR32_TO_ARGB(color, a, r, g, b);
328 imlib_context_set_color(r, g, b, a);
329 imlib_context_set_blend(0);
330 imlib_image_fill_rectangle(x, y, w, h);
331 }
332
333 void
EImageOrientate(EImage * im,int orientation)334 EImageOrientate(EImage * im, int orientation)
335 {
336 imlib_context_set_image(im);
337 imlib_image_orientate(orientation);
338 }
339
340 void
EImageBlend(EImage * im,EImage * src,int flags,int sx,int sy,int sw,int sh,int dx,int dy,int dw,int dh,int merge_alpha)341 EImageBlend(EImage * im, EImage * src, int flags,
342 int sx, int sy, int sw, int sh,
343 int dx, int dy, int dw, int dh, int merge_alpha)
344 {
345 imlib_context_set_image(im);
346 if (flags)
347 _EImageFlagsSet(flags);
348 imlib_blend_image_onto_image(src, merge_alpha, sx, sy, sw, sh,
349 dx, dy, dw, dh);
350 if (flags)
351 _EImageFlagsReset();
352 }
353
354 void
EImageTile(EImage * im,EImage * tile,int flags,int tw,int th,int dx,int dy,int dw,int dh,int ox,int oy)355 EImageTile(EImage * im, EImage * tile, int flags, int tw, int th,
356 int dx, int dy, int dw, int dh, int ox, int oy)
357 {
358 Imlib_Image tim;
359 int x, y, tx, ty, ww, hh;
360 int sw, sh;
361
362 if (tw <= 0 || th <= 0)
363 return;
364
365 if (flags)
366 _EImageFlagsSet(flags);
367
368 imlib_context_set_image(tile);
369 sw = imlib_image_get_width();
370 sh = imlib_image_get_height();
371 if (sw == tw && sh == th)
372 {
373 tim = tile;
374 }
375 else
376 {
377 tim = imlib_create_image(tw, th);
378 imlib_context_set_image(tim);
379 imlib_context_set_blend(0);
380 imlib_context_set_anti_alias(1);
381 imlib_blend_image_onto_image(tile, 0, 0, 0, sw, sh, 0, 0, tw, th);
382 imlib_context_set_anti_alias(0);
383 }
384 imlib_context_set_image(im);
385
386 if (ox)
387 {
388 ox = tw - ox;
389 ox %= tw;
390 if (ox < 0)
391 ox += tw;
392 }
393 if (oy)
394 {
395 oy = th - oy;
396 oy %= th;
397 if (oy < 0)
398 oy += th;
399 }
400 dw += dx;
401 dh += dy;
402 y = dy;
403 ty = oy;
404 hh = th - oy;
405 for (;;)
406 {
407 if (y + hh >= dh)
408 hh = dh - y;
409 if (hh <= 0)
410 break;
411 x = dx;
412 tx = ox;
413 ww = tw - ox;
414 for (;;)
415 {
416 if (x + ww >= dw)
417 ww = dw - x;
418 if (ww <= 0)
419 break;
420 imlib_blend_image_onto_image(tim, 0, tx, ty, ww, hh, x, y, ww, hh);
421 tx = 0;
422 x += ww;
423 ww = tw;
424 }
425 ty = 0;
426 y += hh;
427 hh = th;
428 }
429 if (tim != tile)
430 {
431 imlib_context_set_image(tim);
432 imlib_free_image();
433 imlib_context_set_image(im); /* FIXME - Remove */
434 }
435
436 if (flags)
437 _EImageFlagsReset();
438 }
439
440 EImage *
EImageGrabDrawable(EX_Drawable draw,EX_Pixmap mask,int x,int y,int w,int h,int grab)441 EImageGrabDrawable(EX_Drawable draw, EX_Pixmap mask, int x, int y, int w,
442 int h, int grab)
443 {
444 EImage *im;
445 EX_Colormap cm;
446
447 cm = imlib_context_get_colormap();
448 imlib_context_set_colormap(NoXID); /* Fix for grabbing bitmaps */
449 imlib_context_set_drawable(draw);
450 im = imlib_create_image_from_drawable(mask, x, y, w, h, grab);
451 imlib_context_set_colormap(cm);
452
453 return im;
454 }
455
456 EImage *
EImageGrabDrawableScaled(Win win,EX_Drawable draw,EX_Pixmap mask,int x,int y,int w,int h,int iw,int ih,int grab,int get_mask_from_shape)457 EImageGrabDrawableScaled(Win win, EX_Drawable draw, EX_Pixmap mask,
458 int x, int y, int w, int h,
459 int iw, int ih, int grab, int get_mask_from_shape)
460 {
461 EImage *im;
462 Visual *vis;
463
464 imlib_context_set_drawable(draw);
465 vis = (win) ? WinGetVisual(win) : NULL;
466 if (vis)
467 imlib_context_set_visual(vis);
468
469 im = imlib_create_scaled_image_from_drawable(mask, x, y, w, h, iw, ih, grab,
470 get_mask_from_shape);
471
472 if (vis)
473 imlib_context_set_visual(WinGetVisual(VROOT));
474
475 return im;
476 }
477
478 void
EImageRenderOnDrawable(EImage * im,Win win,EX_Drawable draw,int flags,int x,int y,int w,int h)479 EImageRenderOnDrawable(EImage * im, Win win, EX_Drawable draw, int flags,
480 int x, int y, int w, int h)
481 {
482 Visual *vis;
483
484 imlib_context_set_image(im);
485 imlib_context_set_drawable((draw != NoXID) ? draw : WinGetXwin(win));
486 vis = (win) ? WinGetVisual(win) : NULL;
487 if (vis)
488 imlib_context_set_visual(vis);
489
490 if (flags)
491 _EImageFlagsSet(flags);
492 imlib_render_image_on_drawable_at_size(x, y, w, h);
493 if (flags)
494 _EImageFlagsReset();
495
496 if (vis)
497 imlib_context_set_visual(WinGetVisual(VROOT));
498 }
499
500 #if USE_XRENDER
501
502 void
EImageRenderOnDrawableARGB(EImage * im,EX_Drawable draw,int w,int h)503 EImageRenderOnDrawableARGB(EImage * im, EX_Drawable draw, int w, int h)
504 {
505 Visual *vis;
506
507 imlib_context_set_image(im);
508 imlib_context_set_drawable(draw);
509 vis = EVisualFindARGB();
510 if (vis)
511 imlib_context_set_visual(vis);
512
513 imlib_render_image_on_drawable_at_size(0, 0, w, h);
514
515 if (vis)
516 imlib_context_set_visual(WinGetVisual(VROOT));
517 }
518
519 #endif
520
521 void
EImageRenderPixmaps(EImage * im,Win win,int flags,EX_Pixmap * ppmap,EX_Pixmap * pmask,int w,int h)522 EImageRenderPixmaps(EImage * im, Win win, int flags,
523 EX_Pixmap * ppmap, EX_Pixmap * pmask, int w, int h)
524 {
525 Visual *vis;
526 Pixmap pmap, mask, *pm;
527
528 imlib_context_set_image(im);
529 imlib_context_set_drawable((win) ? WinGetXwin(win) : WinGetXwin(VROOT));
530 vis = (win) ? WinGetVisual(win) : NULL;
531 if (vis)
532 imlib_context_set_visual(vis);
533
534 pmap = mask = NoXID;
535 pm = pmask ? &mask : NULL;
536
537 if (flags)
538 _EImageFlagsSet(flags);
539 if (w <= 0 || h <= 0)
540 imlib_render_pixmaps_for_whole_image(&pmap, pm);
541 else
542 imlib_render_pixmaps_for_whole_image_at_size(&pmap, pm, w, h);
543 if (flags)
544 _EImageFlagsReset();
545
546 if (vis)
547 imlib_context_set_visual(WinGetVisual(VROOT));
548
549 *ppmap = pmap;
550 if (pmask)
551 *pmask = mask;
552 }
553
554 void
EImagePixmapsFree(EX_Pixmap pmap,EX_Pixmap mask __UNUSED__)555 EImagePixmapsFree(EX_Pixmap pmap, EX_Pixmap mask __UNUSED__)
556 {
557 imlib_free_pixmap_and_mask(pmap);
558 }
559
560 void
EImageApplyToWin(EImage * im,Win win,int flags,int w,int h)561 EImageApplyToWin(EImage * im, Win win, int flags, int w, int h)
562 {
563 EX_Pixmap pmap, mask;
564
565 EImageRenderPixmaps(im, win, flags, &pmap, &mask, w, h);
566 ESetWindowBackgroundPixmap(win, pmap, 0);
567 if ((mask != NoXID) || (mask == NoXID && WinIsShaped(win)))
568 EShapeSetMask(win, 0, 0, mask);
569 EImagePixmapsFree(pmap, mask);
570 EClearWindow(win);
571 }
572
573 void
ScaleRect(Win wsrc,EX_Drawable src,Win wdst,EX_Pixmap dst,int sx,int sy,int sw,int sh,int dx,int dy,int dw,int dh,int flags)574 ScaleRect(Win wsrc, EX_Drawable src, Win wdst, EX_Pixmap dst,
575 int sx, int sy, int sw, int sh,
576 int dx, int dy, int dw, int dh, int flags)
577 {
578 #if USE_XRENDER
579 if (Conf.testing.use_render_for_scaling)
580 {
581 XTransform tr;
582 EX_Picture psrc, pdst;
583 double scale_x, scale_y;
584
585 scale_x = (double)sw / (double)dw;
586 scale_y = (double)sh / (double)dh;
587 memset(&tr, 0, sizeof(tr));
588 tr.matrix[0][0] = XDoubleToFixed(scale_x);
589 tr.matrix[1][1] = XDoubleToFixed(scale_y);
590 tr.matrix[2][2] = XDoubleToFixed(1.);
591
592 psrc = EPictureCreateII(wsrc, src);
593 pdst = EPictureCreateII(wdst, dst);
594
595 XRenderSetPictureFilter(disp, psrc, (flags & EIMAGE_ANTI_ALIAS) ?
596 FilterBest : FilterNearest, NULL, 0);
597 XRenderSetPictureTransform(disp, psrc, &tr);
598 XRenderComposite(disp, PictOpSrc, psrc, NoXID, pdst,
599 (int)(sx / scale_x + .5), (int)(sy / scale_y + .5),
600 0, 0, dx, dy, dw, dh);
601 XRenderFreePicture(disp, psrc);
602 XRenderFreePicture(disp, pdst);
603 }
604 else
605 #endif
606 {
607 int scale;
608 Imlib_Image im;
609
610 if (flags & (EIMAGE_ISCALE))
611 {
612 scale = (flags & EIMAGE_ISCALE) >> 8;
613 im = EImageGrabDrawableScaled(wsrc, src, NoXID, sx, sy, sw, sh,
614 scale * dw, scale * dh, 0, 0);
615 flags |= EIMAGE_ANTI_ALIAS;
616 }
617 else
618 {
619 im = EImageGrabDrawableScaled(wsrc, src, NoXID, sx, sy, sw, sh,
620 sw, sh, 0, 0);
621 }
622
623 EImageRenderOnDrawable(im, wdst, dst, flags, dx, dy, dw, dh);
624 imlib_free_image();
625 }
626 }
627
628 void
ScaleTile(Win wsrc,EX_Drawable src,Win wdst,EX_Pixmap dst,int dx,int dy,int dw,int dh,int scale)629 ScaleTile(Win wsrc, EX_Drawable src, Win wdst, EX_Pixmap dst,
630 int dx, int dy, int dw, int dh, int scale)
631 {
632 Imlib_Image im, tim;
633 int sw, sh, stw, sth, tw, th;
634
635 sw = WinGetW(wsrc);
636 sh = WinGetH(wsrc);
637 EXGetSize(src, &stw, &sth);
638 if (stw >= sw && sth >= sh)
639 {
640 ScaleRect(wsrc, src, wdst, dst, 0, 0, sw, sh, dx, dy, dw, dh, scale);
641 return;
642 }
643
644 /* Source Drawawble is smaller than source window - do scaled tiling */
645
646 scale = (scale) ? 2 : 1;
647
648 tw = (int)((float)(stw * scale * dw) / sw + .5f);
649 th = (int)((float)(sth * scale * dh) / sh + .5f);
650 #if 0
651 Eprintf("%s: Tile %#x %dx%d -> %dx%d T %dx%d -> %dx%d\n", __func__,
652 src, stw, sth, tw, th, scale * dw, scale * dh, dw, dh);
653 #endif
654 tim =
655 EImageGrabDrawableScaled(wsrc, src, NoXID, 0, 0, stw, sth, tw, th, 0, 0);
656 im = EImageCreate(scale * dw, scale * dh);
657 EImageTile(im, tim, 0, tw, th, 0, 0, scale * dw, scale * dh, 0, 0);
658 EImageFree(tim);
659
660 EImageRenderOnDrawable(im, wdst, dst, EIMAGE_ANTI_ALIAS, dx, dy, dw, dh);
661 imlib_free_image();
662 }
663
664 #if 0 /* Unused */
665 void
666 EDrawableDumpImage(EX_Drawable draw, const char *txt)
667 {
668 static int seqn = 0;
669 char buf[1024];
670 Imlib_Image im;
671 int w, h;
672
673 EXGetSize(draw, &w, &h);
674 if (w <= 0 || h <= 0)
675 return;
676 im = EImageGrabDrawableScaled(ELookupXwin(draw), draw, NoXID,
677 0, 0, w, h, w, h, 0, 0);
678 imlib_context_set_image(im);
679 imlib_image_set_format("png");
680 sprintf(buf, "%s-%#x-%d.png", txt, draw, seqn++);
681 Eprintf("%s: %s\n", __func__, buf);
682 imlib_save_image(buf);
683 imlib_free_image_and_decache();
684 }
685 #endif
686
687 void
PmapMaskInit(PmapMask * pmm,Win win,int w,int h)688 PmapMaskInit(PmapMask * pmm, Win win, int w, int h)
689 {
690 if (pmm->pmap)
691 {
692 if (pmm->w == w && pmm->h == h && pmm->depth == WinGetDepth(win))
693 return;
694 PmapMaskFree(pmm);
695 }
696
697 pmm->type = 0;
698 pmm->depth = WinGetDepth(win);
699 pmm->pmap = ECreatePixmap(win, w, h, 0);
700 pmm->mask = NoXID;
701 pmm->w = w;
702 pmm->h = h;
703 }
704
705 void
PmapMaskFree(PmapMask * pmm)706 PmapMaskFree(PmapMask * pmm)
707 {
708 /* type !=0: Created by imlib_render_pixmaps_for_whole_image... */
709 if (pmm->pmap)
710 {
711 if (pmm->type == 0)
712 EFreePixmap(pmm->pmap);
713 else
714 imlib_free_pixmap_and_mask(pmm->pmap);
715 pmm->pmap = 0;
716 }
717
718 if (pmm->mask)
719 {
720 if (pmm->type == 0)
721 EFreePixmap(pmm->mask);
722 pmm->mask = 0;
723 }
724 }
725
726 #if USE_XRENDER
727
728 EX_Cursor
EImageDefineCursor(EImage * im,int xh,int yh)729 EImageDefineCursor(EImage * im, int xh, int yh)
730 {
731 EX_Cursor curs;
732 int w, h;
733 EX_Pixmap pmap;
734 EX_Picture pict;
735
736 EImageGetSize(im, &w, &h);
737
738 pict = EPictureCreateBuffer(RROOT, w, h, 1, &pmap);
739
740 EImageRenderOnDrawableARGB(im, pmap, w, h);
741 EFreePixmap(pmap);
742
743 curs = XRenderCreateCursor(disp, pict, xh, yh);
744 XRenderFreePicture(disp, pict);
745
746 return curs;
747 }
748
749 #endif /* USE_XRENDER */
750