Apply extremely trivial free() patch to WindowList.
[fvwm.git] / libs / PictureGraphics.c
blob13b8eeac538f227323032b8571de7b0cebccbed9
1 /* -*-c-*- */
2 /* Copyright (C) 2002 Olivier Chapuis */
3 /* This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 /* ---------------------------- included header files ---------------------- */
20 #include "config.h"
22 #include <stdio.h>
24 #include <X11/Xlib.h>
26 #include <fvwmlib.h>
27 #include "PictureBase.h"
28 #include "Colorset.h"
29 #include "FRenderInit.h"
30 #include "FRenderInterface.h"
31 #include "Graphics.h"
32 #include "PictureGraphics.h"
33 #include "PictureUtils.h"
34 #include "FImage.h"
35 #include "Grab.h"
37 /* ---------------------------- local definitions -------------------------- */
39 /* ---------------------------- local macros ------------------------------- */
41 /* ---------------------------- imports ------------------------------------ */
43 /* ---------------------------- included code files ------------------------ */
45 /* ---------------------------- local types -------------------------------- */
47 /* ---------------------------- forward declarations ----------------------- */
49 /* ---------------------------- local variables ---------------------------- */
51 static Bool PGrabImageError = True;
53 /* ---------------------------- exported variables (globals) --------------- */
55 /* ---------------------------- local functions ---------------------------- */
56 static
57 int FSetBackingStore(Display *dpy, Window win, int backing_store)
59 XWindowAttributes attributes;
60 XSetWindowAttributes set_attributes;
61 int old_bs;
63 XGetWindowAttributes(dpy, win, &attributes);
64 if (attributes.backing_store == backing_store)
66 return -1;
68 old_bs = attributes.backing_store;
69 set_attributes.backing_store = backing_store;
70 XChangeWindowAttributes(dpy, win, CWBackingStore, &set_attributes);
71 return old_bs;
74 static
75 void PCopyArea(Display *dpy, Pixmap pixmap, Pixmap mask, int depth,
76 Drawable d, GC gc,
77 int src_x, int src_y, int src_w, int src_h,
78 int dest_x, int dest_y)
80 XGCValues gcv;
81 unsigned long gcm;
82 GC my_gc = None;
84 if (gc == None)
86 my_gc = fvwmlib_XCreateGC(dpy, d, 0, NULL);
88 gcm = GCClipMask | GCClipXOrigin | GCClipYOrigin;
89 gcv.clip_x_origin = dest_x - src_x; /* */
90 gcv.clip_y_origin = dest_y - src_y; /* */
91 if (depth == Pdepth)
93 gcv.clip_mask = mask;
94 if (my_gc != None)
96 XChangeGC(dpy,my_gc,gcm,&gcv);
98 else
100 XChangeGC(dpy,gc,gcm,&gcv);
102 XCopyArea(dpy, pixmap, d,
103 (my_gc != None)? my_gc:gc,
104 src_x, src_y, src_w, src_h,
105 dest_x, dest_y);
107 else
109 /* monochrome bitmap */
110 gcv.clip_mask = mask;
111 if (my_gc != None)
113 gcv.foreground = PictureWhitePixel();
114 gcv.background = PictureBlackPixel();
115 gcm |= GCBackground|GCForeground;
116 XChangeGC(dpy,my_gc,gcm,&gcv);
118 else
120 XChangeGC(dpy,gc,gcm,&gcv);
122 XCopyPlane(dpy, pixmap, d,
123 (my_gc != None)? my_gc:gc,
124 src_x, src_y, src_w, src_h,
125 dest_x, dest_y, 1);
127 if (my_gc != None)
129 XFreeGC(dpy, my_gc);
131 else
133 gcm = GCClipMask;
134 gcv.clip_mask = None;
135 XChangeGC(dpy, gc, gcm, &gcv);
139 static
140 void PTileRectangle(Display *dpy, Window win, Pixmap pixmap, Pixmap mask,
141 int depth,
142 int src_x, int src_y,
143 Drawable d, GC gc, GC mono_gc,
144 int dest_x, int dest_y, int dest_w, int dest_h)
146 Pixmap tile_mask = None;
147 XGCValues gcv;
148 unsigned long gcm;
149 GC my_gc = None;
150 GC my_mono_gc = None;
152 if (gc == None)
154 my_gc = fvwmlib_XCreateGC(dpy, d, 0, NULL);
156 if (mono_gc == None && (mask != None || Pdepth != depth))
158 if (mask != None)
159 my_mono_gc = fvwmlib_XCreateGC(dpy, mask, 0, NULL);
160 else if (depth != Pdepth)
161 my_mono_gc = fvwmlib_XCreateGC(dpy, pixmap, 0, NULL);
163 gcm = 0;
164 if (mask != None)
166 /* create a till mask */
167 tile_mask = XCreatePixmap(dpy, win, dest_w, dest_h, 1);
168 gcv.tile = mask;
169 gcv.ts_x_origin = src_x;
170 gcv.ts_y_origin = src_y;
171 gcv.fill_style = FillTiled;
172 gcm = GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin |
173 GCTile;
174 if (mono_gc != None)
176 XChangeGC(dpy, mono_gc, gcm, &gcv);
178 else
180 gcv.foreground = 1;
181 gcv.background = 0;
182 gcm |= GCBackground|GCForeground;
183 XChangeGC(dpy, my_mono_gc, gcm, &gcv);
185 XFillRectangle(dpy, tile_mask,
186 (mono_gc != None)? mono_gc:my_mono_gc,
187 src_x, src_y, dest_w, dest_h);
188 if (mono_gc != None)
190 gcv.fill_style = FillSolid;
191 gcm = GCFillStyle;
192 XChangeGC(dpy, mono_gc, gcm, &gcv);
196 gcv.tile = pixmap;
197 gcv.ts_x_origin = dest_x - src_x;
198 gcv.ts_y_origin = dest_y - src_y;
199 gcv.fill_style = FillTiled;
200 gcm = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
201 gcv.clip_mask = tile_mask;
202 gcv.clip_x_origin = dest_x;
203 gcv.clip_y_origin = dest_y;;
204 gcm |= GCClipMask | GCClipXOrigin | GCClipYOrigin;
205 if (depth != Pdepth)
207 Pixmap my_pixmap = None;
209 XChangeGC(dpy,
210 (mono_gc != None)? mono_gc:my_mono_gc, gcm, &gcv);
211 my_pixmap = XCreatePixmap(dpy, win, dest_w, dest_h, 1);
212 XFillRectangle(dpy, my_pixmap,
213 (mono_gc != None)? mono_gc:my_mono_gc,
214 0, 0, dest_w, dest_h);
215 gcv.clip_mask = my_pixmap;
216 gcv.fill_style = FillSolid;
217 gcm = GCFillStyle | GCClipMask;
218 XChangeGC(dpy,
219 (mono_gc != None)? mono_gc:my_mono_gc,
220 gcm, &gcv);
221 XCopyPlane(dpy, my_pixmap, d,
222 (my_gc != None)? my_gc:gc,
223 0, 0, dest_w, dest_h, dest_x, dest_y, 1);
224 if (my_pixmap != None)
226 XFreePixmap(dpy, my_pixmap);
229 else
231 XChangeGC(dpy, (gc != None)? gc:my_gc, gcm, &gcv);
232 XFillRectangle(dpy, d,
233 (gc != None)? gc:my_gc,
234 dest_x, dest_y, dest_w, dest_h);
236 if (my_gc != None)
238 XFreeGC(dpy, my_gc);
240 else
242 gcv.clip_mask = None;
243 gcv.fill_style = FillSolid;
244 gcm = GCFillStyle | GCClipMask;
245 XChangeGC(dpy, gc, gcm, &gcv);
247 if (my_mono_gc != None)
249 XFreeGC(dpy, my_mono_gc);
251 else if (mono_gc != None)
253 gcv.clip_mask = None;
254 gcv.fill_style = FillSolid;
255 gcm = GCFillStyle | GCClipMask;
256 XChangeGC(dpy, mono_gc, gcm, &gcv);
258 if (tile_mask != None)
260 XFreePixmap(dpy, tile_mask);
264 static
265 void PGrabImageErrorHandler(void)
267 PGrabImageError = True;
270 static
271 FImage *PGrabXImage(
272 Display *dpy, Drawable d, int x, int y, int w, int h, Bool d_is_a_window)
275 Bool try_to_grab = True;
276 XWindowAttributes xwa;
277 XErrorHandler saved_eh = NULL;
278 FImage *fim = NULL;
280 PGrabImageError = 0;
281 if (d_is_a_window)
283 MyXGrabServer(dpy);
284 XGetWindowAttributes(dpy, d, &xwa);
285 XSync(dpy, False);
287 if (xwa.map_state != IsViewable &&
288 xwa.backing_store == NotUseful)
290 try_to_grab = False;
291 #if 0
292 fprintf(stderr, "Bad attribute! %i,%i\n",
293 xwa.map_state != IsViewable,
294 xwa.backing_store == NotUseful);
295 #endif
297 else
299 saved_eh = XSetErrorHandler(
300 (XErrorHandler) PGrabImageErrorHandler);
301 #if 0
302 fprintf(stderr, "Attribute ok! %i,%i\n",
303 xwa.map_state != IsViewable,
304 xwa.backing_store == NotUseful);
305 #endif
308 if (try_to_grab)
310 fim = FGetFImage(dpy, d, Pvisual, Pdepth, x, y, w, h, AllPlanes,
311 ZPixmap);
312 if (PGrabImageError)
314 #if 0
315 fprintf(stderr, "XGetImage error during the grab\n");
316 #endif
317 if (fim != NULL)
319 FDestroyFImage(dpy, fim);
320 fim = NULL;
323 if (d_is_a_window)
325 XSetErrorHandler((XErrorHandler) saved_eh);
329 if (d_is_a_window)
331 MyXUngrabServer(dpy);
333 return fim;
336 static
337 Pixmap PCreateRenderPixmap(
338 Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
339 int depth, int added_alpha_percent, Pixel tint, int tint_percent,
340 Bool d_is_a_window, Drawable d, GC gc, GC mono_gc, GC alpha_gc,
341 int src_x, int src_y, int src_w, int src_h,
342 int dest_x, int dest_y, int dest_w, int dest_h, Bool do_repeat,
343 int *new_w, int *new_h, Bool *new_do_repeat,
344 Pixmap *new_mask)
346 FImage *pixmap_fim = NULL;
347 FImage *mask_fim = NULL;
348 FImage *alpha_fim = NULL;
349 FImage *dest_fim = NULL;
350 FImage *new_mask_fim = NULL;
351 FImage *out_fim = NULL;
352 Pixmap pixmap_copy = None;
353 Pixmap src_pix = None;
354 Pixmap out_pix = None;
355 unsigned short *am = NULL;
356 XColor *colors = NULL, *dest_colors = NULL;
357 XColor tint_color, c;
358 int w ,h, n_src_w, n_src_h;
359 int j, i, j1, i1, m = 0, k = 0, l = 0;
360 Bool do_free_mono_gc = False;
361 Bool make_new_mask = False;
362 Bool error = False;
364 *new_mask = None;
365 *new_do_repeat = do_repeat;
367 if (depth != Pdepth)
369 pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth);
370 if (gc == None)
372 gc = PictureDefaultGC(dpy, win);
374 if (pixmap_copy && gc)
376 XCopyPlane(
377 dpy, pixmap, pixmap_copy, gc,
378 src_x, src_y, src_w, src_h,
379 0, 0, 1);
381 else
383 error = True;
384 goto bail;
386 src_x = src_y = 0;
388 src_pix = (pixmap_copy)? pixmap_copy:pixmap;
390 if (src_pix == ParentRelative)
392 pixmap_fim = PGrabXImage(
393 dpy, d, dest_x, dest_y, dest_w, dest_h, d_is_a_window);
395 else
397 pixmap_fim = FGetFImage(
398 dpy, src_pix, Pvisual, Pdepth, src_x, src_y, src_w,
399 src_h, AllPlanes, ZPixmap);
401 if (!pixmap_fim)
403 error = True;
404 goto bail;
406 if (mask != None)
408 mask_fim = FGetFImage(
409 dpy, mask, Pvisual, 1, src_x, src_y, src_w, src_h,
410 AllPlanes, ZPixmap);
411 if (!mask_fim)
413 error = True;
414 goto bail;
416 if (src_x != 0 || src_y != 0)
417 make_new_mask = True;
419 if (alpha != None)
421 alpha_fim = FGetFImage(
422 dpy, alpha, Pvisual, FRenderGetAlphaDepth(), src_x,
423 src_y, src_w, src_h, AllPlanes, ZPixmap);
424 if (!alpha_fim)
426 error = True;
427 goto bail;
431 if (alpha != None || added_alpha_percent < 100)
433 dest_fim = PGrabXImage(
434 dpy, d, dest_x, dest_y, dest_w, dest_h, d_is_a_window);
435 /* accept this error */
438 if (dest_fim && do_repeat && (dest_w > src_w || dest_h > src_h))
440 *new_do_repeat = False;
441 if (mask)
443 make_new_mask = True;
445 w = dest_w;
446 h = dest_h;
447 n_src_w = (w < src_w)? w:src_w;
448 n_src_h = (h < src_h)? h:src_h;
450 else
452 n_src_w = w = (dest_w < src_w)? dest_w:src_w;
453 n_src_h = h = (dest_h < src_h)? dest_h:src_h;
455 *new_w = w;
456 *new_h = h;
458 out_pix = XCreatePixmap(dpy, win, w, h, Pdepth);
459 out_fim = FCreateFImage(
460 dpy, Pvisual, Pdepth, ZPixmap, w, h);
461 if (gc == None)
463 gc = PictureDefaultGC(dpy, win);
466 if (!out_pix || !out_fim || !gc)
468 error = True;
469 goto bail;
472 colors = (XColor *)safemalloc(n_src_w * n_src_h * sizeof(XColor));
473 if (dest_fim)
475 dest_colors =
476 (XColor *)safemalloc(w * h * sizeof(XColor));
478 am = (unsigned short *)safemalloc(
479 n_src_w * n_src_h * sizeof(unsigned short));
481 if (tint_percent > 0)
483 tint_color.pixel = tint;
484 XQueryColor(dpy, Pcmap, &tint_color);
487 for (j = 0; j < n_src_h; j++)
489 for (i = 0; i < n_src_w; i++, m++)
491 if (mask_fim != NULL &&
492 (XGetPixel(mask_fim->im, i, j) == 0))
494 am[m] = 0;
496 else if (alpha_fim != NULL)
498 am[m] = XGetPixel(alpha_fim->im, i, j);
499 if (am[m] == 0 && !dest_fim)
501 make_new_mask = True;
504 else
506 am[m] = 255;
508 if (added_alpha_percent < 100)
510 am[m] = (unsigned short)
511 ((am[m] * added_alpha_percent) / 100);
513 if (am[m] > 0)
515 if (!dest_fim)
517 if (am[m] < 130)
519 am[m] = 0;
520 make_new_mask = True;
522 else
524 am[m] = 255;
527 else if (am[m] < 255)
529 dest_colors[l++].pixel =
530 XGetPixel(dest_fim->im, i, j);
532 if (am[m] > 0)
534 colors[k++].pixel =
535 XGetPixel(pixmap_fim->im, i, j);
541 for (i = 0; i < k; i += 256)
542 XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
544 if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w))
546 for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h)
548 for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w)
550 for(j = 0;
551 !(i1==0 && j1==0) && j < n_src_h && j+j1 < h;
552 j++)
554 for(i = 0; i < n_src_w && i+i1 < w; i++)
556 m = j*n_src_w + i;
557 if (am[m] > 0 && am[m] < 255)
559 dest_colors[l++].pixel =
560 XGetPixel(
561 dest_fim
562 ->im,
563 i1+i,
564 j1+j);
572 for (i = 0; i < l; i += 256)
573 XQueryColors(dpy, Pcmap, &dest_colors[i], min(l - i, 256));
575 if (make_new_mask)
577 *new_mask = XCreatePixmap(dpy, win, w, h, 1);
578 if (*new_mask)
580 new_mask_fim = FCreateFImage(
581 dpy, Pvisual, 1, ZPixmap, w, h);
582 if (mono_gc == None)
584 mono_gc = fvwmlib_XCreateGC(
585 dpy, *new_mask, 0, NULL);
586 do_free_mono_gc = True;
591 l = 0; m = 0; k = 0;
592 c.flags = DoRed | DoGreen | DoBlue;
593 for (j = 0; j < n_src_h; j++)
595 for (i = 0; i < n_src_w; i++, m++)
597 if (am[m] > 0)
599 if (*new_mask)
601 XPutPixel(new_mask_fim->im, i, j, 1);
603 if (tint_percent > 0)
605 colors[k].blue = (unsigned short)
606 (((100-tint_percent)*
607 colors[k].blue +
608 tint_color.blue *
609 tint_percent) /
610 100);
611 colors[k].green = (unsigned short)
612 (((100-tint_percent)*
613 colors[k].green +
614 tint_color.green *
615 tint_percent) /
616 100);
617 colors[k].red = (unsigned short)
618 (((100-tint_percent)*
619 colors[k].red +
620 tint_color.red *
621 tint_percent) /
622 100);
624 c.blue = colors[k].blue;
625 c.green = colors[k].green;
626 c.red = colors[k].red;
627 if (am[m] < 255 && dest_fim)
629 c.blue = (unsigned short)
630 (((255 - am[m])*
631 dest_colors[l].blue +
632 c.blue * am[m]) /
633 255);
634 c.green = (unsigned short)
635 (((255 - am[m])*
636 dest_colors[l].green +
637 c.green * am[m]) /
638 255);
639 c.red = (unsigned short)
640 (((255 - am[m])*
641 dest_colors[l].red +
642 c.red * am[m]) /
643 255);
644 l++;
646 PictureAllocColor(Pdpy, Pcmap, &c, False);
647 colors[k].pixel = c.pixel;
648 k++;
650 else
652 if (dest_fim)
654 c.pixel = XGetPixel(dest_fim->im, i, j);
656 else
658 c.pixel = XGetPixel(
659 pixmap_fim->im, i, j);
661 if (*new_mask)
663 XPutPixel(new_mask_fim->im, i, j, 0);
666 XPutPixel(out_fim->im, i, j, c.pixel);
670 /* tile: editor ligne width limit 107 !!*/
671 if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w))
673 for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h)
675 for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w)
677 k = 0;
678 for(j = 0;
679 !(i1==0 && j1==0) && j < n_src_h; j++)
681 for(i = 0; i < n_src_w; i++)
683 m = j*n_src_w + i;
684 if (!(i+i1 < w && j+j1 < h))
686 if (am[m] > 0)
688 k++;
691 else
693 if (am[m] > 0)
695 if (*new_mask)
697 XPutPixel(
698 new_mask_fim->im, i+i1,
699 j+j1, 1);
701 c.blue = colors[k].blue;
702 c.green = colors[k].green;
703 c.red = colors[k].red;
704 c.pixel = colors[k].pixel;
705 k++;
706 if (am[m] < 255)
708 c.blue = (unsigned short)
709 (((255 - am[m])*
710 dest_colors[l].blue +
711 c.blue * am[m]) /
712 255);
713 c.green = (unsigned short)
714 (((255 - am[m])*
715 dest_colors[l].green +
716 c.green * am[m]) /
717 255);
718 c.red = (unsigned short)
719 (((255 - am[m])*
720 dest_colors[l].red +
721 c.red * am[m]) /
722 255);
723 l++;
724 PictureAllocColor(
725 Pdpy, Pcmap, &c, False);
728 else
730 c.pixel = XGetPixel(
731 dest_fim->im, i+i1, j+j1);
732 if (*new_mask)
734 XPutPixel(
735 new_mask_fim->im, i+i1,
736 j+j1, 0);
739 XPutPixel(out_fim->im, i+i1, j+j1, c.pixel);
747 FPutFImage(dpy, out_pix, gc, out_fim, 0, 0, 0, 0, w, h);
748 if (*new_mask && mono_gc)
750 FPutFImage(
751 dpy, *new_mask, mono_gc, new_mask_fim,
752 0, 0, 0, 0, w, h);
755 bail:
756 if (colors)
758 free(colors);
760 if (dest_colors)
762 free(dest_colors);
764 if (am)
766 free(am);
768 if (pixmap_copy)
770 XFreePixmap(dpy, pixmap_copy);
772 if (pixmap_fim)
774 FDestroyFImage(dpy, pixmap_fim);
776 if (mask_fim)
778 FDestroyFImage(dpy, mask_fim);
780 if (alpha_fim)
782 FDestroyFImage(dpy, alpha_fim);
784 if (dest_fim)
786 FDestroyFImage(dpy, dest_fim);
788 if (new_mask_fim)
790 FDestroyFImage(dpy, new_mask_fim);
792 if (do_free_mono_gc && mono_gc)
794 XFreeGC(dpy, mono_gc);
796 if (out_fim)
798 FDestroyFImage(dpy, out_fim);
800 if (error)
802 if (out_pix != None)
804 XFreePixmap(dpy, out_pix);
805 out_pix = None;
807 if (*new_mask != None)
809 XFreePixmap(dpy, *new_mask);
810 *new_mask = None;
814 return out_pix;
817 /* never used and tested */
818 static
819 Pixmap PCreateDitherPixmap(
820 Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc,
821 int in_width, int in_height, int out_width, int out_height)
823 FImage *src_fim;
824 FImage *mask_fim = NULL;
825 FImage *out_fim;
826 Pixmap out_pix = None;
827 unsigned char *cm;
828 XColor *colors;
829 XColor c;
830 int j, i, m = 0, k = 0, x = 0, y = 0;
832 if (depth != Pdepth)
833 return None;
835 if (!(src_fim =
836 FGetFImage(
837 dpy, src, Pvisual, depth, 0, 0, in_width, in_height,
838 AllPlanes, ZPixmap)))
840 return None;
842 if (mask != None)
844 mask_fim = FGetFImage(
845 dpy, mask, Pvisual, 1, 0, 0, in_width, in_height,
846 AllPlanes, ZPixmap);
847 if (!mask_fim)
849 FDestroyFImage(dpy, mask_fim);
850 return None;
853 out_pix = XCreatePixmap(dpy, win, out_width, out_height, Pdepth);
854 out_fim = FCreateFImage(
855 dpy, Pvisual, Pdepth, ZPixmap, out_width, out_height);
856 if (gc == None)
858 gc = PictureDefaultGC(dpy, win);
861 if (!out_pix || !out_fim || !gc)
863 FDestroyFImage(dpy, src_fim);
864 if (mask_fim)
866 FDestroyFImage(dpy, mask_fim);
868 if (out_pix)
870 XFreePixmap(dpy, out_pix);
872 if (out_fim)
874 FDestroyFImage(dpy, out_fim);
876 return None;
879 colors = (XColor *)safemalloc(out_width * out_height * sizeof(XColor));
880 cm = (unsigned char *)safemalloc(out_width * out_height * sizeof(char));
882 x = y = 0;
883 for (j = 0; j < out_height; j++,y++)
885 if (y == in_height)
886 y = 0;
887 for (i = 0; i < out_width; i++,x++)
889 if (x == in_width)
890 x = 0;
891 if (mask_fim != NULL &&
892 (XGetPixel(mask_fim->im, x, y) == 0))
894 cm[m++] = 0;
896 else
898 cm[m++] = 255;
899 colors[k++].pixel = XGetPixel(src_fim->im, x, y);
904 for (i = 0; i < k; i += 256)
905 XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
907 k = 0;m = 0;
908 for (j = 0; j < out_height; j++)
910 for (i = 0; i < out_width; i++)
913 if (cm[m] > 0)
915 c = colors[k++];
916 PictureAllocColorAllProp(
917 Pdpy, Pcmap, &c, i, j, False, False,
918 True);
920 else
922 c.pixel = XGetPixel(src_fim->im, i, j);
924 XPutPixel(out_fim->im, i, j, c.pixel);
925 m++;
928 free(colors);
929 free(cm);
930 FDestroyFImage(dpy, src_fim);
931 if (mask_fim)
933 FDestroyFImage(dpy, mask_fim);
935 FPutFImage(
936 dpy, out_pix, gc, out_fim, 0, 0, 0, 0, out_width, out_height);
937 FDestroyFImage(dpy, out_fim);
939 return out_pix;
942 /* ---------------------------- interface functions ------------------------ */
944 Pixmap PictureBitmapToPixmap(
945 Display *dpy, Window win, Pixmap src, int depth, GC gc,
946 int src_x, int src_y, int src_w, int src_h)
948 Pixmap dest = None;
950 dest = XCreatePixmap(dpy, win, src_w, src_h, depth);
951 if (dest && gc == None)
953 gc = PictureDefaultGC(dpy, win);
955 if (dest && gc)
957 XCopyPlane(
958 dpy, src, dest, gc,
959 src_x, src_y, src_w, src_h, 0, 0, 1);
962 return dest;
965 void PGraphicsRenderPixmaps(
966 Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
967 int depth, FvwmRenderAttributes *fra, Drawable d,
968 GC gc, GC mono_gc, GC alpha_gc,
969 int src_x, int src_y, int src_w, int src_h,
970 int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat)
972 FvwmRenderAttributes t_fra;
973 Pixmap xrs_pixmap = None;
974 Pixmap xrs_mask = None;
975 Pixmap tmp_pixmap, tmp_mask;
976 Bool d_is_a_window;
978 t_fra.added_alpha_percent = 100;
979 t_fra.tint_percent = 0;
980 t_fra.mask = 0;
981 t_fra.tint = None;
983 if (fra)
985 t_fra.mask = fra->mask;
986 if (fra->mask & FRAM_HAVE_ICON_CSET)
988 t_fra.added_alpha_percent =
989 fra->colorset->icon_alpha_percent;
990 t_fra.tint_percent = fra->colorset->icon_tint_percent;
991 t_fra.tint = fra->colorset->icon_tint;
993 if (fra->mask & FRAM_HAVE_ADDED_ALPHA)
995 t_fra.added_alpha_percent = fra->added_alpha_percent;
997 if (fra->mask & FRAM_HAVE_TINT)
999 t_fra.tint_percent = fra->tint_percent;
1000 t_fra.tint = fra->tint;
1003 if (dest_w == 0 && dest_h == 0)
1005 dest_w = src_w; dest_h = src_h;
1008 /* use XRender only when "needed" (backing store pbs) */
1009 if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100
1010 || alpha != None)
1012 /* for testing XRender simulation add && 0 */
1013 if (FRenderRender(
1014 dpy, win, pixmap, mask, alpha, depth,
1015 t_fra.added_alpha_percent, t_fra.tint,
1016 t_fra.tint_percent,
1017 d, gc, alpha_gc, src_x, src_y, src_w, src_h,
1018 dest_x, dest_y, dest_w, dest_h, do_repeat))
1020 return;
1024 /* no render extension or something strange happen */
1025 if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100
1026 || alpha != None)
1028 int new_w, new_h, new_do_repeat;
1030 d_is_a_window = !!(t_fra.mask & FRAM_DEST_IS_A_WINDOW);
1031 xrs_pixmap = PCreateRenderPixmap(
1032 dpy, win, pixmap, mask, alpha, depth,
1033 t_fra.added_alpha_percent, t_fra.tint,
1034 t_fra.tint_percent, d_is_a_window, d,
1035 gc, mono_gc, alpha_gc,
1036 src_x, src_y, src_w, src_h,
1037 dest_x, dest_y, dest_w, dest_h, do_repeat,
1038 &new_w, &new_h, &new_do_repeat, &xrs_mask);
1039 if (xrs_pixmap)
1041 src_x = 0;
1042 src_y = 0;
1043 src_w = new_w;
1044 src_h = new_h;
1045 depth = Pdepth;
1046 do_repeat = new_do_repeat;
1049 tmp_pixmap = (xrs_pixmap != None)? xrs_pixmap:pixmap;
1050 tmp_mask = (xrs_mask != None)? xrs_mask:mask;
1051 if (do_repeat)
1053 PTileRectangle(
1054 dpy, win, tmp_pixmap, tmp_mask, depth,
1055 src_x, src_y, d, gc, mono_gc, dest_x, dest_y, dest_w,
1056 dest_h);
1058 else
1060 PCopyArea(
1061 dpy, tmp_pixmap, tmp_mask, depth, d, gc,
1062 src_x, src_y, src_w, src_h, dest_x, dest_y);
1064 if (xrs_pixmap)
1066 XFreePixmap(dpy, xrs_pixmap);
1068 if (xrs_mask)
1070 XFreePixmap(dpy, xrs_mask);
1074 void PGraphicsRenderPicture(
1075 Display *dpy, Window win, FvwmPicture *p, FvwmRenderAttributes *fra,
1076 Drawable d, GC gc, GC mono_gc, GC alpha_gc,
1077 int src_x, int src_y, int src_w, int src_h,
1078 int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat)
1080 PGraphicsRenderPixmaps(
1081 dpy, win, p->picture, p->mask, p->alpha, p->depth, fra,
1082 d, gc, mono_gc, alpha_gc,
1083 src_x, src_y, src_w, src_h,
1084 dest_x, dest_y, dest_w, dest_h, do_repeat);
1087 void PGraphicsCopyPixmaps(
1088 Display *dpy, Pixmap pixmap, Pixmap mask, Pixmap alpha,
1089 int depth, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h,
1090 int dest_x, int dest_y)
1092 PGraphicsRenderPixmaps(
1093 dpy, None, pixmap, mask, alpha, depth, 0, d, gc, None, None,
1094 src_x, src_y, src_w, src_h, dest_x, dest_y, src_w, src_h, False);
1097 void PGraphicsCopyFvwmPicture(
1098 Display *dpy, FvwmPicture *p, Drawable d, GC gc,
1099 int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y)
1101 PGraphicsRenderPicture(
1102 dpy, None, p, 0, d, gc, None, None, src_x, src_y, src_w, src_h,
1103 dest_x, dest_y, src_w, src_h, False);
1106 void PGraphicsTileRectangle(
1107 Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
1108 int depth, Drawable d, GC gc, GC mono_gc,
1109 int src_x, int src_y, int src_w, int src_h,
1110 int dest_x, int dest_y, int dest_w, int dest_h)
1112 PGraphicsRenderPixmaps(
1113 dpy, win, pixmap, mask, alpha, depth, 0, d, gc, mono_gc, None,
1114 src_x, src_y, dest_w, dest_h, dest_x, dest_y, dest_w, dest_h,
1115 True);
1118 FvwmPicture *PGraphicsCreateStretchPicture(
1119 Display *dpy, Window win, FvwmPicture *src,
1120 int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc)
1122 Pixmap pixmap = None, mask = None, alpha = None;
1123 FvwmPicture *q;
1125 if (src == NULL || src->picture == None)
1127 return NULL;
1129 pixmap = CreateStretchPixmap(
1130 dpy, src->picture, src->width, src->height, src->depth,
1131 dest_width, dest_height, gc);
1132 if (!pixmap)
1134 return NULL;
1136 if (src->mask)
1138 mask = CreateStretchPixmap(
1139 dpy, src->mask, src->width, src->height, 1,
1140 dest_width, dest_height, mono_gc);
1142 if (src->alpha)
1144 alpha = CreateStretchPixmap(
1145 dpy, src->alpha, src->width, src->height,
1146 FRenderGetAlphaDepth(),
1147 dest_width, dest_height, alpha_gc);
1150 q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture));
1151 memset(q, 0, sizeof(FvwmPicture));
1152 q->count = 1;
1153 q->name = NULL;
1154 q->next = NULL;
1155 q->stamp = pixmap;
1156 q->picture = pixmap;
1157 q->mask = mask;
1158 q->alpha = alpha;
1159 q->width = dest_width;
1160 q->height = dest_height;
1161 q->depth = src->depth;
1162 q->alloc_pixels = 0;
1163 q->nalloc_pixels = 0;
1165 return q;
1168 FvwmPicture *PGraphicsCreateTiledPicture(
1169 Display *dpy, Window win, FvwmPicture *src,
1170 int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc)
1172 Pixmap pixmap = None, mask = None, alpha = None;
1173 FvwmPicture *q;
1175 if (src == NULL || src->picture == None)
1177 return NULL;
1179 pixmap = CreateTiledPixmap(
1180 dpy, src->picture, src->width, src->height, dest_width,
1181 dest_height, src->depth, gc);
1182 if (!pixmap)
1184 return NULL;
1186 if (src->mask)
1188 mask = CreateTiledPixmap(
1189 dpy, src->mask, src->width, src->height, dest_width,
1190 dest_height, 1, mono_gc);
1192 if (src->alpha)
1194 alpha = CreateTiledPixmap(
1195 dpy, src->alpha, src->width, src->height, dest_width,
1196 dest_height, FRenderGetAlphaDepth(), alpha_gc);
1199 q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture));
1200 memset(q, 0, sizeof(FvwmPicture));
1201 q->count = 1;
1202 q->name = NULL;
1203 q->next = NULL;
1204 q->stamp = pixmap;
1205 q->picture = pixmap;
1206 q->mask = mask;
1207 q->alpha = alpha;
1208 q->width = dest_width;
1209 q->height = dest_height;
1210 q->depth = src->depth;
1211 q->alloc_pixels = 0;
1212 q->nalloc_pixels = 0;
1214 return q;
1217 Pixmap PGraphicsCreateTransparency(
1218 Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
1219 int x, int y, int width, int height, Bool parent_relative)
1221 Pixmap r = None, dp = None;
1222 XID junk;
1223 XID root;
1224 int dummy, sx, sy, sw, sh;
1225 int gx = x, gy = y, gh = height, gw = width;
1226 int old_backing_store = -1;
1228 if (parent_relative)
1230 old_backing_store = FSetBackingStore(dpy, win, Always);
1231 XSetWindowBackgroundPixmap(dpy, win, ParentRelative);
1232 XClearArea(dpy, win, x, y, width, height, False);
1233 XSync(dpy, False);
1236 if (parent_relative)
1238 /* this block is not useful if backing store ... */
1239 if (!XGetGeometry(
1240 dpy, win, &root, (int *)&junk, (int *)&junk,
1241 (unsigned int *)&sw, (unsigned int *)&sh,
1242 (unsigned int *)&junk, (unsigned int *)&junk))
1244 goto bail;
1246 XTranslateCoordinates(
1247 dpy, win, DefaultRootWindow(dpy), x, y, &sx, &sy, &junk);
1248 if (sx >= DisplayWidth(dpy, DefaultScreen(dpy)))
1250 goto bail;
1252 if (sy >= DisplayHeight(dpy, DefaultScreen(dpy)))
1254 goto bail;
1256 if (sx < 0)
1258 gx = gx - sx;
1259 gw = width + sx;
1260 sx = 0;
1261 if (gw <= 0)
1263 goto bail;
1266 if (sy < 0)
1268 gy = gy - sy;
1269 gh = height + sy;
1270 sy = 0;
1271 if (gh <= 0)
1273 goto bail;
1276 if (sx + gw > DisplayWidth(dpy, DefaultScreen(dpy)))
1278 gw = DisplayWidth(dpy, DefaultScreen(dpy)) - sx;
1280 if (sy + gh > DisplayHeight(dpy, DefaultScreen(dpy)))
1282 gh = DisplayHeight(dpy, DefaultScreen(dpy)) - sy;
1285 #if 0
1286 fprintf(
1287 stderr,"Geo: %i,%i,%i,%i / %i,%i,%i,%i / %i,%i,%i,%i\n",
1288 gx,gy,gw,gh, x,y,width,height, sx,sy,sw,sh);
1289 #endif
1290 if (XRenderSupport && FRenderGetExtensionSupported())
1292 r = XCreatePixmap(dpy, win, gw, gh, Pdepth);
1293 if (FRenderRender(
1294 dpy, win, ParentRelative, None, None, Pdepth, 100,
1295 fra->tint, fra->tint_percent, r, gc, None,
1296 gx, gy, gw, gh, 0, 0, gw, gh, False))
1298 goto bail;
1300 XFreePixmap(dpy, r);
1302 r = PCreateRenderPixmap(
1303 dpy, win, ParentRelative, None, None, Pdepth, 100, fra->tint,
1304 fra->tint_percent,
1305 True, win,
1306 gc, None, None, gx, gy, gw, gh, gx, gy, gw, gh,
1307 False, &dummy, &dummy, &dummy, &dp);
1309 bail:
1310 if (old_backing_store >= 0)
1312 FSetBackingStore(dpy, win, old_backing_store);
1314 return r;
1317 void PGraphicsTintRectangle(
1318 Display *dpy, Window win, Pixel tint, int tint_percent,
1319 Drawable dest, Bool dest_is_a_window, GC gc, GC mono_gc, GC alpha_gc,
1320 int dest_x, int dest_y, int dest_w, int dest_h)
1322 Pixmap p;
1323 FvwmRenderAttributes fra;
1325 #if 0
1326 /* this does not work. why? */
1327 if (FRenderTintRectangle(
1328 dpy, win, None, tint, tint_percent, dest,
1329 dest_x, dest_y, dest_w, dest_h))
1331 return;
1333 #else
1335 if (FRenderRender(
1336 dpy, win, ParentRelative, None, None, Pdepth, 100,
1337 tint, tint_percent, win, gc, None,
1338 dest_x, dest_y, dest_w, dest_h,
1339 dest_x, dest_y, dest_w, dest_h, False))
1342 return;
1344 #endif
1346 if (dest_is_a_window)
1348 fra.tint = tint;
1349 fra.tint_percent = tint_percent;
1350 fra.mask = FRAM_DEST_IS_A_WINDOW | FRAM_HAVE_TINT;
1351 p = PGraphicsCreateTransparency(
1352 dpy, dest, &fra, gc, dest_x, dest_y, dest_w, dest_h,
1353 False);
1354 if (p)
1356 XCopyArea(
1357 dpy, p, dest, gc, 0, 0, dest_w, dest_h,
1358 dest_x, dest_y);
1359 XFreePixmap(dpy, p);
1364 #if 0 /* humm... maybe useful one day with menus */
1365 Pixmap PGraphicsCreateTranslucent(
1366 Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
1367 int x, int y, int width, int height)
1369 Pixmap r = None;
1370 int gx = x, gy = y, gh = height, gw = width;
1371 FvwmRenderAttributes t_fra;
1372 Pixmap root_pix = None;
1373 Pixmap dp = None;
1374 int dummy;
1376 t_fra.added_alpha_percent = 100;
1377 t_fra.tint_percent = 0;
1378 t_fra.tint = 0;
1379 t_fra.mask = 0;
1381 if (fra)
1383 if (fra->mask & FRAM_HAVE_TINT)
1385 t_fra.tint_percent = fra->tint_percent;
1386 t_fra.tint = fra->tint;
1387 t_fra.mask = FRAM_HAVE_TINT;
1391 if (x >= DisplayWidth(dpy, DefaultScreen(dpy)))
1393 goto bail;
1395 if (y >= DisplayHeight(dpy, DefaultScreen(dpy)))
1397 goto bail;
1399 if (x < 0)
1401 gx = 0;
1402 gw = width + x;
1403 if (gw <= 0)
1405 goto bail;
1408 if (y < 0)
1410 gy = 0;
1411 gh = gh+y;
1412 if (gh <= 0)
1414 goto bail;
1417 if (gx + gw > DisplayWidth(dpy, DefaultScreen(dpy)))
1419 gw = DisplayWidth(dpy, DefaultScreen(dpy)) - gx;
1421 if (gy + gh > DisplayHeight(dpy, DefaultScreen(dpy)))
1423 gh = DisplayHeight(dpy, DefaultScreen(dpy)) - gy;
1426 /* make a screen shoot */
1427 GC my_gc;
1428 unsigned long valuemask = GCSubwindowMode;
1429 XGCValues values;
1431 values.subwindow_mode = IncludeInferiors;
1432 root_pix = XCreatePixmap(dpy, win, gw, gh, Pdepth);
1433 my_gc = fvwmlib_XCreateGC(dpy, win, 0, NULL);
1434 XChangeGC(dpy, my_gc, valuemask, &values);
1435 MyXGrabServer(dpy);
1436 XCopyArea(
1437 dpy, DefaultRootWindow(dpy), root_pix, my_gc,
1438 gx, gy, gw, gh, 0, 0);
1439 MyXUngrabServer(dpy);
1440 XFreeGC(dpy,my_gc);
1442 if (XRenderSupport && FRenderGetExtensionSupported())
1444 r = XCreatePixmap(dpy, win, gw, gh, Pdepth);
1445 if (FRenderRender(
1446 dpy, win, root_pix, None, None, Pdepth,
1447 t_fra.added_alpha_percent, t_fra.tint,
1448 t_fra.tint_percent, r, gc, None,
1449 0, 0, gw, gh, 0, 0, gw, gh, False))
1451 goto bail;
1453 XFreePixmap(dpy, r);
1454 r = None;
1456 r = PCreateRenderPixmap(
1457 dpy, win, root_pix, None, None, Pdepth, 100,
1458 fra->tint, fra->tint_percent, True, win,
1459 gc, None, None, 0, 0, gw, gh, gx, gy, gw, gh,
1460 False, &dummy, &dummy, &dummy, &dp);
1462 bail:
1463 if (root_pix)
1465 XFreePixmap(dpy, root_pix);
1467 if (dp)
1469 XFreePixmap(dpy, dp);
1471 return r;
1473 #endif
1476 /* never tested and used ! */
1477 Pixmap PGraphicsCreateDitherPixmap(
1478 Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc,
1479 int in_width, int in_height, int out_width, int out_height)
1481 return PCreateDitherPixmap(
1482 dpy, win, src, mask, depth, gc,
1483 in_width, in_height, out_width, out_height);