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.
7  *
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.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, see: <http://www.gnu.org/licenses/>
15  */
16 
17 /* ---------------------------- included header files ---------------------- */
18 
19 #include "config.h"
20 
21 #include <stdio.h>
22 
23 #include <X11/Xlib.h>
24 
25 #include <fvwmlib.h>
26 #include "PictureBase.h"
27 #include "Colorset.h"
28 #include "FRenderInit.h"
29 #include "FRenderInterface.h"
30 #include "Graphics.h"
31 #include "PictureGraphics.h"
32 #include "PictureUtils.h"
33 #include "FImage.h"
34 #include "Grab.h"
35 
36 /* ---------------------------- local definitions -------------------------- */
37 
38 /* ---------------------------- local macros ------------------------------- */
39 
40 /* ---------------------------- imports ------------------------------------ */
41 
42 /* ---------------------------- included code files ------------------------ */
43 
44 /* ---------------------------- local types -------------------------------- */
45 
46 /* ---------------------------- forward declarations ----------------------- */
47 
48 /* ---------------------------- local variables ---------------------------- */
49 
50 static Bool PGrabImageError = True;
51 
52 /* ---------------------------- exported variables (globals) --------------- */
53 
54 /* ---------------------------- local functions ---------------------------- */
55 static
FSetBackingStore(Display * dpy,Window win,int backing_store)56 int FSetBackingStore(Display *dpy, Window win, int backing_store)
57 {
58 	XWindowAttributes attributes;
59 	XSetWindowAttributes set_attributes;
60 	int old_bs;
61 
62 	XGetWindowAttributes(dpy, win, &attributes);
63 	if (attributes.backing_store == backing_store)
64 	{
65 		return -1;
66 	}
67 	old_bs = attributes.backing_store;
68 	set_attributes.backing_store = backing_store;
69 	XChangeWindowAttributes(dpy, win, CWBackingStore, &set_attributes);
70 	return old_bs;
71 }
72 
73 static
PCopyArea(Display * dpy,Pixmap pixmap,Pixmap mask,int depth,Drawable d,GC gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y)74 void PCopyArea(Display *dpy, Pixmap pixmap, Pixmap mask, int depth,
75 	       Drawable d, GC gc,
76 	       int src_x, int src_y, int src_w, int src_h,
77 	       int dest_x, int dest_y)
78 {
79 	XGCValues gcv;
80 	unsigned long gcm;
81 	GC my_gc = None;
82 
83 	if (gc == None)
84 	{
85 		my_gc = fvwmlib_XCreateGC(dpy, d, 0, NULL);
86 	}
87 	gcm = GCClipMask | GCClipXOrigin | GCClipYOrigin;
88 	gcv.clip_x_origin = dest_x - src_x; /* */
89 	gcv.clip_y_origin = dest_y - src_y; /* */
90 	if (depth == Pdepth)
91 	{
92 		gcv.clip_mask = mask;
93 		if (my_gc != None)
94 		{
95 			XChangeGC(dpy,my_gc,gcm,&gcv);
96 		}
97 		else
98 		{
99 			XChangeGC(dpy,gc,gcm,&gcv);
100 		}
101 		XCopyArea(dpy, pixmap, d,
102 			  (my_gc != None)? my_gc:gc,
103 			  src_x, src_y, src_w, src_h,
104 			  dest_x, dest_y);
105 	}
106 	else
107 	{
108 		/* monochrome bitmap */
109 		gcv.clip_mask = mask;
110 		if (my_gc != None)
111 		{
112 			gcv.foreground = PictureWhitePixel();
113 			gcv.background = PictureBlackPixel();
114 			gcm |= GCBackground|GCForeground;
115 			XChangeGC(dpy,my_gc,gcm,&gcv);
116 		}
117 		else
118 		{
119 			XChangeGC(dpy,gc,gcm,&gcv);
120 		}
121 		XCopyPlane(dpy, pixmap, d,
122 			   (my_gc != None)? my_gc:gc,
123 			   src_x, src_y, src_w, src_h,
124 			   dest_x, dest_y, 1);
125 	}
126 	if (my_gc != None)
127 	{
128 		XFreeGC(dpy, my_gc);
129 	}
130 	else
131 	{
132 		gcm = GCClipMask;
133 		gcv.clip_mask = None;
134 		XChangeGC(dpy, gc, gcm, &gcv);
135 	}
136 }
137 
138 static
PTileRectangle(Display * dpy,Window win,Pixmap pixmap,Pixmap mask,int depth,int src_x,int src_y,Drawable d,GC gc,GC mono_gc,int dest_x,int dest_y,int dest_w,int dest_h)139 void PTileRectangle(Display *dpy, Window win, Pixmap pixmap, Pixmap mask,
140 		    int depth,
141 		    int src_x, int src_y,
142 		    Drawable d, GC gc, GC mono_gc,
143 		    int dest_x, int dest_y, int dest_w, int dest_h)
144 {
145 	Pixmap tile_mask = None;
146 	XGCValues gcv;
147 	unsigned long gcm;
148 	GC my_gc = None;
149 	GC my_mono_gc = None;
150 
151 	if (gc == None)
152 	{
153 		my_gc = fvwmlib_XCreateGC(dpy, d, 0, NULL);
154 	}
155 	if (mono_gc == None && (mask != None || Pdepth != depth))
156 	{
157 		if (mask != None)
158 			my_mono_gc = fvwmlib_XCreateGC(dpy, mask, 0, NULL);
159 		else if (depth != Pdepth)
160 			my_mono_gc = fvwmlib_XCreateGC(dpy, pixmap, 0, NULL);
161 	}
162 	gcm = 0;
163 	if (mask != None)
164 	{
165 		/* create a till mask */
166 		tile_mask = XCreatePixmap(dpy, win, dest_w, dest_h, 1);
167 		gcv.tile = mask;
168 		gcv.ts_x_origin = src_x;
169 		gcv.ts_y_origin = src_y;
170 		gcv.fill_style = FillTiled;
171 		gcm = GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin |
172 			GCTile;
173 		if (mono_gc != None)
174 		{
175 			XChangeGC(dpy, mono_gc, gcm, &gcv);
176 		}
177 		else
178 		{
179 			gcv.foreground = 1;
180 			gcv.background = 0;
181 			gcm |= GCBackground|GCForeground;
182 			XChangeGC(dpy, my_mono_gc, gcm, &gcv);
183 		}
184 		XFillRectangle(dpy, tile_mask,
185 			       (mono_gc != None)? mono_gc:my_mono_gc,
186 			       src_x, src_y, dest_w, dest_h);
187 		if (mono_gc != None)
188 		{
189 			gcv.fill_style = FillSolid;
190 			gcm = GCFillStyle;
191 			XChangeGC(dpy, mono_gc, gcm, &gcv);
192 		}
193 	}
194 
195 	gcv.tile = pixmap;
196 	gcv.ts_x_origin = dest_x - src_x;
197 	gcv.ts_y_origin = dest_y - src_y;
198 	gcv.fill_style = FillTiled;
199 	gcm = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
200 	gcv.clip_mask = tile_mask;
201 	gcv.clip_x_origin = dest_x;
202 	gcv.clip_y_origin = dest_y;;
203 	gcm |= GCClipMask | GCClipXOrigin | GCClipYOrigin;
204 	if (depth != Pdepth)
205 	{
206 		Pixmap my_pixmap = None;
207 
208 		XChangeGC(dpy,
209 			  (mono_gc != None)? mono_gc:my_mono_gc, gcm, &gcv);
210 		my_pixmap = XCreatePixmap(dpy, win, dest_w, dest_h, 1);
211 		XFillRectangle(dpy, my_pixmap,
212 			       (mono_gc != None)? mono_gc:my_mono_gc,
213 			       0, 0, dest_w, dest_h);
214 		gcv.clip_mask = my_pixmap;
215 		gcv.fill_style = FillSolid;
216 		gcm = GCFillStyle | GCClipMask;
217 		XChangeGC(dpy,
218 			  (mono_gc != None)? mono_gc:my_mono_gc,
219 			  gcm, &gcv);
220 		XCopyPlane(dpy, my_pixmap, d,
221 			  (my_gc != None)? my_gc:gc,
222 			  0, 0, dest_w, dest_h, dest_x, dest_y, 1);
223 		if (my_pixmap != None)
224 		{
225 			XFreePixmap(dpy, my_pixmap);
226 		}
227 	}
228 	else
229 	{
230 		XChangeGC(dpy, (gc != None)? gc:my_gc, gcm, &gcv);
231 		XFillRectangle(dpy, d,
232 			       (gc != None)? gc:my_gc,
233 			       dest_x, dest_y, dest_w, dest_h);
234 	}
235 	if (my_gc != None)
236 	{
237 		XFreeGC(dpy, my_gc);
238 	}
239 	else
240 	{
241 		gcv.clip_mask = None;
242 		gcv.fill_style = FillSolid;
243 		gcm = GCFillStyle | GCClipMask;
244 		XChangeGC(dpy, gc, gcm, &gcv);
245 	}
246 	if (my_mono_gc != None)
247 	{
248 		XFreeGC(dpy, my_mono_gc);
249 	}
250 	else if (mono_gc != None)
251 	{
252 		gcv.clip_mask = None;
253 		gcv.fill_style = FillSolid;
254 		gcm = GCFillStyle | GCClipMask;
255 		XChangeGC(dpy, mono_gc, gcm, &gcv);
256 	}
257 	if (tile_mask != None)
258 	{
259 		XFreePixmap(dpy, tile_mask);
260 	}
261 }
262 
263 static
PGrabImageErrorHandler(void)264 void PGrabImageErrorHandler(void)
265 {
266 	PGrabImageError = True;
267 }
268 
269 static
PGrabXImage(Display * dpy,Drawable d,int x,int y,int w,int h,Bool d_is_a_window)270 FImage *PGrabXImage(
271 	Display *dpy, Drawable d, int x, int y, int w, int h, Bool d_is_a_window)
272 {
273 
274 	Bool try_to_grab = True;
275 	XWindowAttributes   xwa;
276 	XErrorHandler saved_eh = NULL;
277 	FImage *fim = NULL;
278 
279 	PGrabImageError = 0;
280 	if (d_is_a_window)
281 	{
282 		MyXGrabServer(dpy);
283 		XGetWindowAttributes(dpy, d, &xwa);
284 		XSync(dpy, False);
285 
286 		if (xwa.map_state != IsViewable &&
287 		    xwa.backing_store == NotUseful)
288 		{
289 			try_to_grab = False;
290 #if 0
291 			fprintf(stderr, "Bad attribute! %i,%i\n",
292 				xwa.map_state != IsViewable,
293 				xwa.backing_store == NotUseful);
294 #endif
295 		}
296 		else
297 		{
298 			saved_eh = XSetErrorHandler(
299 				(XErrorHandler) PGrabImageErrorHandler);
300 #if 0
301 			fprintf(stderr, "Attribute ok! %i,%i\n",
302 				xwa.map_state != IsViewable,
303 				xwa.backing_store == NotUseful);
304 #endif
305 		}
306 	}
307 	if (try_to_grab)
308 	{
309 		fim = FGetFImage(dpy, d, Pvisual, Pdepth, x, y, w, h, AllPlanes,
310 				 ZPixmap);
311 		if (PGrabImageError)
312 		{
313 #if 0
314 			fprintf(stderr, "XGetImage error during the grab\n");
315 #endif
316 			if (fim != NULL)
317 			{
318 				FDestroyFImage(dpy, fim);
319 				fim = NULL;
320 			}
321 		}
322 		if (d_is_a_window)
323 		{
324 			XSetErrorHandler((XErrorHandler) saved_eh);
325 		}
326 	}
327 
328 	if (d_is_a_window)
329 	{
330 		MyXUngrabServer(dpy);
331 	}
332 	return fim;
333 }
334 
335 static
PCreateRenderPixmap(Display * dpy,Window win,Pixmap pixmap,Pixmap mask,Pixmap alpha,int depth,int added_alpha_percent,Pixel tint,int tint_percent,Bool d_is_a_window,Drawable d,GC gc,GC mono_gc,GC alpha_gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y,int dest_w,int dest_h,Bool do_repeat,int * new_w,int * new_h,Bool * new_do_repeat,Pixmap * new_mask)336 Pixmap PCreateRenderPixmap(
337 	Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
338 	int depth, int added_alpha_percent, Pixel tint, int tint_percent,
339 	Bool d_is_a_window, Drawable d, GC gc, GC mono_gc, GC alpha_gc,
340 	int src_x, int src_y, int src_w, int src_h,
341 	int dest_x, int dest_y, int dest_w, int dest_h, Bool do_repeat,
342 	int *new_w, int *new_h, Bool *new_do_repeat,
343 	Pixmap *new_mask)
344 {
345 	FImage *pixmap_fim = NULL;
346 	FImage *mask_fim = NULL;
347 	FImage *alpha_fim = NULL;
348 	FImage *dest_fim = NULL;
349 	FImage *new_mask_fim = NULL;
350 	FImage *out_fim = NULL;
351 	Pixmap pixmap_copy = None;
352 	Pixmap src_pix = None;
353 	Pixmap out_pix = None;
354 	unsigned short *am = NULL;
355 	XColor *colors = NULL, *dest_colors = NULL;
356 	XColor tint_color, c;
357 	int w ,h, n_src_w, n_src_h;
358 	int j, i, j1, i1, m = 0, k = 0, l = 0;
359 	Bool do_free_mono_gc = False;
360 	Bool make_new_mask = False;
361 	Bool error = False;
362 
363 	*new_mask = None;
364 	*new_do_repeat = do_repeat;
365 
366 	if (depth != Pdepth)
367 	{
368 		pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth);
369 		if (gc == None)
370 		{
371 			gc = PictureDefaultGC(dpy, win);
372 		}
373 		if (pixmap_copy && gc)
374 		{
375 			XCopyPlane(
376 				dpy, pixmap, pixmap_copy, gc,
377 				src_x, src_y, src_w, src_h,
378 				0, 0, 1);
379 		}
380 		else
381 		{
382 			error = True;
383 			goto bail;
384 		}
385 		src_x = src_y = 0;
386 	}
387 	src_pix = (pixmap_copy)? pixmap_copy:pixmap;
388 
389 	if (src_pix == ParentRelative)
390 	{
391 		pixmap_fim = PGrabXImage(
392 			dpy, d, dest_x, dest_y, dest_w, dest_h, d_is_a_window);
393 	}
394 	else
395 	{
396 		pixmap_fim = FGetFImage(
397 			dpy, src_pix, Pvisual, Pdepth, src_x, src_y, src_w,
398 			src_h, AllPlanes, ZPixmap);
399 	}
400 	if (!pixmap_fim)
401 	{
402 		error = True;
403 		goto bail;
404 	}
405 	if (mask != None)
406 	{
407 		mask_fim = FGetFImage(
408 			dpy, mask, Pvisual, 1, src_x, src_y, src_w, src_h,
409 			AllPlanes, ZPixmap);
410 		if (!mask_fim)
411 		{
412 			error = True;
413 			goto bail;
414 		}
415 		if (src_x != 0 || src_y != 0)
416 			make_new_mask = True;
417 	}
418 	if (alpha != None)
419 	{
420 		alpha_fim = FGetFImage(
421 			dpy, alpha, Pvisual, FRenderGetAlphaDepth(), src_x,
422 			src_y, src_w, src_h, AllPlanes, ZPixmap);
423 		if (!alpha_fim)
424 		{
425 			error = True;
426 			goto bail;
427 		}
428 	}
429 
430 	if (alpha != None || added_alpha_percent < 100)
431 	{
432 		dest_fim = PGrabXImage(
433 			dpy, d, dest_x, dest_y, dest_w, dest_h, d_is_a_window);
434 		/* accept this error */
435 	}
436 
437 	if (dest_fim && do_repeat && (dest_w > src_w || dest_h > src_h))
438 	{
439 		*new_do_repeat = False;
440 		if (mask)
441 		{
442 			make_new_mask = True;
443 		}
444 		w = dest_w;
445 		h = dest_h;
446 		n_src_w = (w < src_w)? w:src_w;
447 		n_src_h = (h < src_h)? h:src_h;
448 	}
449 	else
450 	{
451 		n_src_w = w = (dest_w < src_w)? dest_w:src_w;
452 		n_src_h = h = (dest_h < src_h)? dest_h:src_h;
453 	}
454 	*new_w = w;
455 	*new_h = h;
456 
457 	out_pix = XCreatePixmap(dpy, win, w, h, Pdepth);
458 	out_fim = FCreateFImage(
459 		dpy, Pvisual, Pdepth, ZPixmap, w, h);
460 	if (gc == None)
461 	{
462 		gc = PictureDefaultGC(dpy, win);
463 	}
464 
465 	if (!out_pix || !out_fim || !gc)
466 	{
467 		error = True;
468 		goto bail;
469 	}
470 
471 	colors = (XColor *)safemalloc(n_src_w * n_src_h * sizeof(XColor));
472 	if (dest_fim)
473 	{
474 		dest_colors =
475 			(XColor *)safemalloc(w * h * sizeof(XColor));
476 	}
477 	am = (unsigned short *)safemalloc(
478 		n_src_w * n_src_h * sizeof(unsigned short));
479 
480 	if (tint_percent > 0)
481 	{
482 		tint_color.pixel = tint;
483 		XQueryColor(dpy, Pcmap, &tint_color);
484 	}
485 
486 	for (j = 0; j < n_src_h; j++)
487 	{
488 		for (i = 0; i < n_src_w; i++, m++)
489 		{
490 			if (mask_fim != NULL &&
491 			    (XGetPixel(mask_fim->im, i, j) == 0))
492 			{
493 				am[m] = 0;
494 			}
495 			else if (alpha_fim != NULL)
496 			{
497 				am[m] = XGetPixel(alpha_fim->im, i, j);
498 				if (am[m] == 0 && !dest_fim)
499 				{
500 					make_new_mask = True;
501 				}
502 			}
503 			else
504 			{
505 				am[m] = 255;
506 			}
507 			if (added_alpha_percent < 100)
508 			{
509 				am[m] = (unsigned short)
510 					((am[m] * added_alpha_percent) / 100);
511 			}
512 			if (am[m] > 0)
513 			{
514 				if (!dest_fim)
515 				{
516 					if (am[m] < 130)
517 					{
518 						am[m] = 0;
519 						make_new_mask = True;
520 					}
521 					else
522 					{
523 						am[m] = 255;
524 					}
525 				}
526 				else if (am[m] < 255)
527 				{
528 					dest_colors[l++].pixel =
529 						XGetPixel(dest_fim->im, i, j);
530 				}
531 				if (am[m] > 0)
532 				{
533 					colors[k++].pixel =
534 						XGetPixel(pixmap_fim->im, i, j);
535 				}
536 			}
537 		}
538 	}
539 
540 	for (i = 0; i < k; i += 256)
541 		XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
542 
543 	if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w))
544 	{
545 		for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h)
546 		{
547 			for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w)
548 			{
549 				for(j = 0;
550 				    !(i1==0 && j1==0) && j < n_src_h && j+j1 < h;
551 				    j++)
552 				{
553 					for(i = 0; i < n_src_w && i+i1 < w; i++)
554 					{
555 						m = j*n_src_w + i;
556 						if (am[m] > 0 && am[m] < 255)
557 						{
558 							dest_colors[l++].pixel =
559 								XGetPixel(
560 									dest_fim
561 									->im,
562 									i1+i,
563 									j1+j);
564 						}
565 					}
566 				}
567 			}
568 		}
569 	}
570 
571 	for (i = 0; i < l; i += 256)
572 		XQueryColors(dpy, Pcmap, &dest_colors[i], min(l - i, 256));
573 
574 	if (make_new_mask)
575 	{
576 		 *new_mask = XCreatePixmap(dpy, win, w, h, 1);
577 		 if (*new_mask)
578 		 {
579 			 new_mask_fim = FCreateFImage(
580 				 dpy, Pvisual, 1, ZPixmap, w, h);
581 			 if (mono_gc == None)
582 			 {
583 				 mono_gc = fvwmlib_XCreateGC(
584 					 dpy, *new_mask, 0, NULL);
585 				 do_free_mono_gc = True;
586 			 }
587 		 }
588 	}
589 
590 	l = 0; m = 0; k = 0;
591 	c.flags = DoRed | DoGreen | DoBlue;
592 	for (j = 0; j < n_src_h; j++)
593 	{
594 		for (i = 0; i < n_src_w; i++, m++)
595 		{
596 			if (am[m] > 0)
597 			{
598 				if (*new_mask)
599 				{
600 					XPutPixel(new_mask_fim->im, i, j, 1);
601 				}
602 				if (tint_percent > 0)
603 				{
604 					colors[k].blue = (unsigned short)
605 						(((100-tint_percent)*
606 						  colors[k].blue +
607 						  tint_color.blue *
608 						  tint_percent) /
609 						 100);
610 					colors[k].green = (unsigned short)
611 						(((100-tint_percent)*
612 						  colors[k].green +
613 						  tint_color.green *
614 						  tint_percent) /
615 						 100);
616 					colors[k].red = (unsigned short)
617 						(((100-tint_percent)*
618 						  colors[k].red +
619 						  tint_color.red *
620 						  tint_percent) /
621 						 100);
622 				}
623 				c.blue = colors[k].blue;
624 				c.green = colors[k].green;
625 				c.red = colors[k].red;
626 				if (am[m] < 255 && dest_fim)
627 				{
628 					c.blue = (unsigned short)
629 						(((255 - am[m])*
630 						  dest_colors[l].blue +
631 						  c.blue * am[m]) /
632 						 255);
633 					c.green = (unsigned short)
634 						(((255 - am[m])*
635 						  dest_colors[l].green +
636 						  c.green * am[m]) /
637 						 255);
638 					c.red = (unsigned short)
639 						(((255 - am[m])*
640 						  dest_colors[l].red +
641 						  c.red * am[m]) /
642 						 255);
643 					l++;
644 				}
645 				PictureAllocColor(Pdpy, Pcmap, &c, False);
646 				colors[k].pixel = c.pixel;
647 				k++;
648 			}
649 			else
650 			{
651 				if (dest_fim)
652 				{
653 					c.pixel = XGetPixel(dest_fim->im, i, j);
654 				}
655 				else
656 				{
657 					c.pixel = XGetPixel(
658 						pixmap_fim->im, i, j);
659 				}
660 				if (*new_mask)
661 				{
662 					XPutPixel(new_mask_fim->im, i, j, 0);
663 				}
664 			}
665 			XPutPixel(out_fim->im, i, j, c.pixel);
666 		}
667 	}
668 
669 	/* tile: editor ligne width limit  107 !!*/
670 	if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w))
671 	{
672 		for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h)
673 		{
674 			for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w)
675 			{
676 				k = 0;
677 				for(j = 0;
678 				    !(i1==0 && j1==0) && j < n_src_h; j++)
679 				{
680 					for(i = 0; i < n_src_w; i++)
681 					{
682 						m = j*n_src_w + i;
683 						if (!(i+i1 < w && j+j1 < h))
684 						{
685 							if (am[m] > 0)
686 							{
687 								k++;
688 							}
689 						}
690 						else
691 						{
692 							if (am[m] > 0)
693 							{
694 								if (*new_mask)
695 								{
696 									XPutPixel(
697 										new_mask_fim->im, i+i1,
698 										j+j1, 1);
699 								}
700 								c.blue = colors[k].blue;
701 								c.green = colors[k].green;
702 								c.red = colors[k].red;
703 								c.pixel = colors[k].pixel;
704 								k++;
705 								if (am[m] < 255)
706 								{
707 									c.blue = (unsigned short)
708 										(((255 - am[m])*
709 										  dest_colors[l].blue +
710 										  c.blue * am[m]) /
711 										 255);
712 									c.green = (unsigned short)
713 										(((255 - am[m])*
714 										  dest_colors[l].green +
715 										  c.green * am[m]) /
716 										 255);
717 									c.red = (unsigned short)
718 										(((255 - am[m])*
719 										  dest_colors[l].red +
720 										  c.red * am[m]) /
721 										 255);
722 									l++;
723 									PictureAllocColor(
724 										Pdpy, Pcmap, &c, False);
725 								}
726 							}
727 							else
728 							{
729 								c.pixel = XGetPixel(
730 									dest_fim->im, i+i1, j+j1);
731 								if (*new_mask)
732 								{
733 									XPutPixel(
734 										new_mask_fim->im, i+i1,
735 										j+j1, 0);
736 								}
737 							}
738 							XPutPixel(out_fim->im, i+i1, j+j1, c.pixel);
739 						}
740 					}
741 				}
742 			}
743 		}
744 	}
745 
746 	FPutFImage(dpy, out_pix, gc, out_fim, 0, 0, 0, 0, w, h);
747 	if (*new_mask && mono_gc)
748 	{
749 		FPutFImage(
750 			dpy, *new_mask, mono_gc, new_mask_fim,
751 			0, 0, 0, 0, w, h);
752 	}
753 
754  bail:
755 	if (colors)
756 	{
757 		free(colors);
758 	}
759 	if (dest_colors)
760 	{
761 		free(dest_colors);
762 	}
763 	if (am)
764 	{
765 		free(am);
766 	}
767 	if (pixmap_copy)
768 	{
769 		XFreePixmap(dpy, pixmap_copy);
770 	}
771 	if (pixmap_fim)
772 	{
773 		FDestroyFImage(dpy, pixmap_fim);
774 	}
775 	if (mask_fim)
776 	{
777 		FDestroyFImage(dpy, mask_fim);
778 	}
779 	if (alpha_fim)
780 	{
781 		FDestroyFImage(dpy, alpha_fim);
782 	}
783 	if (dest_fim)
784 	{
785 		FDestroyFImage(dpy, dest_fim);
786 	}
787 	if (new_mask_fim)
788 	{
789 		FDestroyFImage(dpy, new_mask_fim);
790 	}
791 	if (do_free_mono_gc && mono_gc)
792 	{
793 		XFreeGC(dpy, mono_gc);
794 	}
795 	if (out_fim)
796 	{
797 		FDestroyFImage(dpy, out_fim);
798 	}
799 	if (error)
800 	{
801 		if (out_pix != None)
802 		{
803 			XFreePixmap(dpy, out_pix);
804 			out_pix = None;
805 		}
806 		if (*new_mask != None)
807 		{
808 			XFreePixmap(dpy, *new_mask);
809 			*new_mask = None;
810 		}
811 	}
812 
813 	return out_pix;
814 }
815 
816 /* never used and tested */
817 static
PCreateDitherPixmap(Display * dpy,Window win,Drawable src,Pixmap mask,int depth,GC gc,int in_width,int in_height,int out_width,int out_height)818 Pixmap PCreateDitherPixmap(
819 	Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc,
820 	int in_width, int in_height, int out_width, int out_height)
821 {
822 	FImage *src_fim;
823 	FImage *mask_fim = NULL;
824 	FImage *out_fim;
825 	Pixmap out_pix = None;
826 	unsigned char *cm;
827 	XColor *colors;
828 	XColor c;
829 	int j, i, m = 0, k = 0, x = 0, y = 0;
830 
831 	if (depth != Pdepth)
832 		return None;
833 
834 	if (!(src_fim =
835 	      FGetFImage(
836 		      dpy, src, Pvisual, depth, 0, 0, in_width, in_height,
837 		      AllPlanes, ZPixmap)))
838 	{
839 		return None;
840 	}
841 	if (mask != None)
842 	{
843 		mask_fim = FGetFImage(
844 			dpy, mask, Pvisual, 1, 0, 0, in_width, in_height,
845 			AllPlanes, ZPixmap);
846 		if (!mask_fim)
847 		{
848 			FDestroyFImage(dpy, mask_fim);
849 			return None;
850 		}
851 	}
852 	out_pix = XCreatePixmap(dpy, win, out_width, out_height, Pdepth);
853 	out_fim = FCreateFImage(
854 		dpy, Pvisual, Pdepth, ZPixmap, out_width, out_height);
855 	if (gc == None)
856 	{
857 		gc = PictureDefaultGC(dpy, win);
858 	}
859 
860 	if (!out_pix || !out_fim || !gc)
861 	{
862 		FDestroyFImage(dpy, src_fim);
863 		if (mask_fim)
864 		{
865 			FDestroyFImage(dpy, mask_fim);
866 		}
867 		if (out_pix)
868 		{
869 			XFreePixmap(dpy, out_pix);
870 		}
871 		if (out_fim)
872 		{
873 			FDestroyFImage(dpy, out_fim);
874 		}
875 		return None;
876 	}
877 
878 	colors = (XColor *)safemalloc(out_width * out_height * sizeof(XColor));
879 	cm = (unsigned char *)safemalloc(out_width * out_height * sizeof(char));
880 
881 	x = y = 0;
882 	for (j = 0; j < out_height; j++,y++)
883 	{
884 		if (y == in_height)
885 			y = 0;
886 		for (i = 0; i < out_width; i++,x++)
887 		{
888 			if (x == in_width)
889 				x = 0;
890 			if (mask_fim != NULL &&
891 			    (XGetPixel(mask_fim->im, x, y) == 0))
892 			{
893 				cm[m++] = 0;
894 			}
895 			else
896 			{
897 				cm[m++] = 255;
898 				colors[k++].pixel = XGetPixel(src_fim->im, x, y);
899 			}
900 		}
901 	}
902 
903 	for (i = 0; i < k; i += 256)
904 		XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
905 
906 	k = 0;m = 0;
907 	for (j = 0; j < out_height; j++)
908 	{
909 		for (i = 0; i < out_width; i++)
910 		{
911 
912 			if (cm[m] > 0)
913 			{
914 				c = colors[k++];
915 				PictureAllocColorAllProp(
916 					Pdpy, Pcmap, &c, i, j, False, False,
917 					True);
918 			}
919 			else
920 			{
921 				c.pixel = XGetPixel(src_fim->im, i, j);
922 			}
923 			XPutPixel(out_fim->im, i, j, c.pixel);
924 			m++;
925 		}
926 	}
927 	free(colors);
928 	free(cm);
929 	FDestroyFImage(dpy, src_fim);
930 	if (mask_fim)
931 	{
932 		FDestroyFImage(dpy, mask_fim);
933 	}
934 	FPutFImage(
935 		dpy, out_pix, gc, out_fim, 0, 0, 0, 0, out_width, out_height);
936 	FDestroyFImage(dpy, out_fim);
937 
938 	return out_pix;
939 }
940 
941 /* ---------------------------- interface functions ------------------------ */
942 
PictureBitmapToPixmap(Display * dpy,Window win,Pixmap src,int depth,GC gc,int src_x,int src_y,int src_w,int src_h)943 Pixmap PictureBitmapToPixmap(
944 	Display *dpy, Window win, Pixmap src, int depth, GC gc,
945 	int src_x, int src_y, int src_w, int src_h)
946 {
947 	Pixmap dest = None;
948 
949 	dest = XCreatePixmap(dpy, win, src_w, src_h, depth);
950 	if (dest && gc == None)
951 	{
952 		gc = PictureDefaultGC(dpy, win);
953 	}
954 	if (dest && gc)
955 	{
956 		XCopyPlane(
957 			dpy, src, dest, gc,
958 			src_x, src_y, src_w, src_h, 0, 0, 1);
959 	}
960 
961 	return dest;
962 }
963 
PGraphicsRenderPixmaps(Display * dpy,Window win,Pixmap pixmap,Pixmap mask,Pixmap alpha,int depth,FvwmRenderAttributes * fra,Drawable d,GC gc,GC mono_gc,GC alpha_gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y,int dest_w,int dest_h,int do_repeat)964 void PGraphicsRenderPixmaps(
965 	Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
966 	int depth, FvwmRenderAttributes *fra, Drawable d,
967 	GC gc, GC mono_gc, GC alpha_gc,
968 	int src_x, int src_y, int src_w, int src_h,
969 	int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat)
970 {
971 	FvwmRenderAttributes t_fra;
972 	Pixmap xrs_pixmap = None;
973 	Pixmap xrs_mask = None;
974 	Pixmap tmp_pixmap, tmp_mask;
975 	Bool d_is_a_window;
976 
977 	t_fra.added_alpha_percent = 100;
978 	t_fra.tint_percent = 0;
979 	t_fra.mask = 0;
980 	t_fra.tint = None;
981 
982 	if (fra)
983 	{
984 		t_fra.mask = fra->mask;
985 		if (fra->mask & FRAM_HAVE_ICON_CSET)
986 		{
987 			t_fra.added_alpha_percent =
988 				fra->colorset->icon_alpha_percent;
989 			t_fra.tint_percent = fra->colorset->icon_tint_percent;
990 			t_fra.tint = fra->colorset->icon_tint;
991 		}
992 		if (fra->mask & FRAM_HAVE_ADDED_ALPHA)
993 		{
994 			t_fra.added_alpha_percent = fra->added_alpha_percent;
995 		}
996 		if (fra->mask & FRAM_HAVE_TINT)
997 		{
998 			t_fra.tint_percent = fra->tint_percent;
999 			t_fra.tint = fra->tint;
1000 		}
1001 	}
1002 	if (dest_w == 0 && dest_h == 0)
1003 	{
1004 		dest_w = src_w; dest_h = src_h;
1005 	}
1006 
1007 	/* use XRender only when "needed" (backing store pbs) */
1008 	if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100
1009 	    || alpha != None)
1010 	{
1011 		/* for testing XRender simulation add && 0 */
1012 		if (FRenderRender(
1013 			dpy, win, pixmap, mask, alpha, depth,
1014 			t_fra.added_alpha_percent, t_fra.tint,
1015 			t_fra.tint_percent,
1016 			d, gc, alpha_gc, src_x, src_y, src_w, src_h,
1017 			dest_x, dest_y, dest_w, dest_h, do_repeat))
1018 		{
1019 			return;
1020 		}
1021 	}
1022 
1023 	/* no render extension or something strange happen */
1024 	if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100
1025 	    || alpha != None)
1026 	{
1027 		int new_w, new_h, new_do_repeat;
1028 
1029 		d_is_a_window = !!(t_fra.mask & FRAM_DEST_IS_A_WINDOW);
1030 		xrs_pixmap = PCreateRenderPixmap(
1031 			dpy, win, pixmap, mask, alpha, depth,
1032 			t_fra.added_alpha_percent, t_fra.tint,
1033 			t_fra.tint_percent, d_is_a_window, d,
1034 			gc, mono_gc, alpha_gc,
1035 			src_x, src_y, src_w, src_h,
1036 			dest_x, dest_y, dest_w, dest_h, do_repeat,
1037 			&new_w, &new_h, &new_do_repeat, &xrs_mask);
1038 		if (xrs_pixmap)
1039 		{
1040 			src_x = 0;
1041 			src_y = 0;
1042 			src_w = new_w;
1043 			src_h = new_h;
1044 			depth = Pdepth;
1045 			do_repeat = new_do_repeat;
1046 		}
1047 	}
1048 	tmp_pixmap = (xrs_pixmap != None)? xrs_pixmap:pixmap;
1049 	tmp_mask = (xrs_mask != None)? xrs_mask:mask;
1050 	if (do_repeat)
1051 	{
1052 		PTileRectangle(
1053 			dpy, win, tmp_pixmap, tmp_mask, depth,
1054 			src_x, src_y, d, gc, mono_gc, dest_x, dest_y, dest_w,
1055 			dest_h);
1056 	}
1057 	else
1058 	{
1059 		PCopyArea(
1060 			dpy, tmp_pixmap, tmp_mask, depth, d, gc,
1061 			src_x, src_y, src_w, src_h, dest_x, dest_y);
1062 	}
1063 	if (xrs_pixmap)
1064 	{
1065 		XFreePixmap(dpy, xrs_pixmap);
1066 	}
1067 	if (xrs_mask)
1068 	{
1069 		XFreePixmap(dpy, xrs_mask);
1070 	}
1071 }
1072 
PGraphicsRenderPicture(Display * dpy,Window win,FvwmPicture * p,FvwmRenderAttributes * fra,Drawable d,GC gc,GC mono_gc,GC alpha_gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y,int dest_w,int dest_h,int do_repeat)1073 void PGraphicsRenderPicture(
1074 	Display *dpy, Window win, FvwmPicture *p, FvwmRenderAttributes *fra,
1075 	Drawable d, GC gc, GC mono_gc, GC alpha_gc,
1076 	int src_x, int src_y, int src_w, int src_h,
1077 	int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat)
1078 {
1079 	PGraphicsRenderPixmaps(
1080 		dpy, win, p->picture, p->mask, p->alpha, p->depth, fra,
1081 		d, gc, mono_gc, alpha_gc,
1082 		src_x, src_y, src_w, src_h,
1083 		dest_x, dest_y, dest_w, dest_h, do_repeat);
1084 }
1085 
PGraphicsCopyPixmaps(Display * dpy,Pixmap pixmap,Pixmap mask,Pixmap alpha,int depth,Drawable d,GC gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y)1086 void PGraphicsCopyPixmaps(
1087 	Display *dpy, Pixmap pixmap, Pixmap mask, Pixmap alpha,
1088 	int depth, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h,
1089 	int dest_x, int dest_y)
1090 {
1091 	PGraphicsRenderPixmaps(
1092 		dpy,  None, pixmap, mask, alpha, depth, 0, d, gc, None, None,
1093 		src_x, src_y, src_w, src_h, dest_x, dest_y, src_w, src_h, False);
1094 }
1095 
PGraphicsCopyFvwmPicture(Display * dpy,FvwmPicture * p,Drawable d,GC gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y)1096 void PGraphicsCopyFvwmPicture(
1097 	Display *dpy, FvwmPicture *p, Drawable d, GC gc,
1098 	int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y)
1099 {
1100 	PGraphicsRenderPicture(
1101 		dpy, None, p, 0, d, gc, None, None, src_x, src_y, src_w, src_h,
1102 		dest_x, dest_y, src_w, src_h, False);
1103 }
1104 
PGraphicsTileRectangle(Display * dpy,Window win,Pixmap pixmap,Pixmap mask,Pixmap alpha,int depth,Drawable d,GC gc,GC mono_gc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y,int dest_w,int dest_h)1105 void PGraphicsTileRectangle(
1106 	Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
1107 	int depth, Drawable d, GC gc, GC mono_gc,
1108 	int src_x, int src_y,  int src_w, int src_h,
1109 	int dest_x, int dest_y, int dest_w, int dest_h)
1110 {
1111 	PGraphicsRenderPixmaps(
1112 		dpy, win, pixmap, mask, alpha, depth, 0, d, gc, mono_gc, None,
1113 		src_x, src_y, dest_w, dest_h, dest_x, dest_y, dest_w, dest_h,
1114 		True);
1115 }
1116 
PGraphicsCreateStretchPicture(Display * dpy,Window win,FvwmPicture * src,int dest_width,int dest_height,GC gc,GC mono_gc,GC alpha_gc)1117 FvwmPicture *PGraphicsCreateStretchPicture(
1118 	Display *dpy, Window win, FvwmPicture *src,
1119 	int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc)
1120 {
1121 	Pixmap pixmap = None, mask = None, alpha = None;
1122 	FvwmPicture *q;
1123 
1124 	if (src == NULL || src->picture == None)
1125 	{
1126 		return NULL;
1127 	}
1128 	pixmap = CreateStretchPixmap(
1129 		dpy, src->picture, src->width, src->height, src->depth,
1130 		dest_width, dest_height, gc);
1131 	if (!pixmap)
1132 	{
1133 		return NULL;
1134 	}
1135 	if (src->mask)
1136 	{
1137 		mask = CreateStretchPixmap(
1138 			dpy, src->mask, src->width, src->height, 1,
1139 			dest_width, dest_height, mono_gc);
1140 	}
1141 	if (src->alpha)
1142 	{
1143 		alpha = CreateStretchPixmap(
1144 			dpy, src->alpha, src->width, src->height,
1145 			FRenderGetAlphaDepth(),
1146 			dest_width, dest_height, alpha_gc);
1147 	}
1148 
1149 	q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture));
1150 	memset(q, 0, sizeof(FvwmPicture));
1151 	q->count = 1;
1152 	q->name = NULL;
1153 	q->next = NULL;
1154 	q->stamp = pixmap;
1155 	q->picture = pixmap;
1156 	q->mask = mask;
1157 	q->alpha = alpha;
1158 	q->width = dest_width;
1159 	q->height = dest_height;
1160 	q->depth = src->depth;
1161 	q->alloc_pixels = 0;
1162 	q->nalloc_pixels = 0;
1163 
1164 	return q;
1165 }
1166 
PGraphicsCreateTiledPicture(Display * dpy,Window win,FvwmPicture * src,int dest_width,int dest_height,GC gc,GC mono_gc,GC alpha_gc)1167 FvwmPicture *PGraphicsCreateTiledPicture(
1168 	Display *dpy, Window win, FvwmPicture *src,
1169 	int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc)
1170 {
1171 	Pixmap pixmap = None, mask = None, alpha = None;
1172 	FvwmPicture *q;
1173 
1174 	if (src == NULL || src->picture == None)
1175 	{
1176 		return NULL;
1177 	}
1178 	pixmap = CreateTiledPixmap(
1179 		dpy, src->picture, src->width, src->height, dest_width,
1180 		dest_height, src->depth, gc);
1181 	if (!pixmap)
1182 	{
1183 		return NULL;
1184 	}
1185 	if (src->mask)
1186 	{
1187 		mask = CreateTiledPixmap(
1188 			dpy, src->mask, src->width, src->height, dest_width,
1189 			dest_height, 1, mono_gc);
1190 	}
1191 	if (src->alpha)
1192 	{
1193 		alpha = CreateTiledPixmap(
1194 			dpy, src->alpha, src->width, src->height, dest_width,
1195 			dest_height, FRenderGetAlphaDepth(), alpha_gc);
1196 	}
1197 
1198 	q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture));
1199 	memset(q, 0, sizeof(FvwmPicture));
1200 	q->count = 1;
1201 	q->name = NULL;
1202 	q->next = NULL;
1203 	q->stamp = pixmap;
1204 	q->picture = pixmap;
1205 	q->mask = mask;
1206 	q->alpha = alpha;
1207 	q->width = dest_width;
1208 	q->height = dest_height;
1209 	q->depth = src->depth;
1210 	q->alloc_pixels = 0;
1211 	q->nalloc_pixels = 0;
1212 
1213 	return q;
1214 }
1215 
PGraphicsCreateTransparency(Display * dpy,Window win,FvwmRenderAttributes * fra,GC gc,int x,int y,int width,int height,Bool parent_relative)1216 Pixmap PGraphicsCreateTransparency(
1217 	Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
1218 	int x, int y, int width, int height, Bool parent_relative)
1219 {
1220 	Pixmap r = None, dp = None;
1221 	XID junk;
1222 	XID root;
1223 	int dummy, sx, sy, sw, sh;
1224 	int gx = x, gy = y, gh = height, gw = width;
1225 	int old_backing_store = -1;
1226 
1227 	if (parent_relative)
1228 	{
1229 		old_backing_store = FSetBackingStore(dpy, win, Always);
1230 		XSetWindowBackgroundPixmap(dpy, win, ParentRelative);
1231 		XClearArea(dpy, win, x, y, width, height, False);
1232 		XSync(dpy, False);
1233 	}
1234 
1235 	if (parent_relative)
1236 	{
1237 		/* this block is not useful if backing store ... */
1238 		if (!XGetGeometry(
1239 			dpy, win, &root, (int *)&junk, (int *)&junk,
1240 			(unsigned int *)&sw, (unsigned int *)&sh,
1241 			(unsigned int *)&junk, (unsigned int *)&junk))
1242 		{
1243 			goto bail;
1244 		}
1245 		XTranslateCoordinates(
1246 			dpy, win, DefaultRootWindow(dpy), x, y, &sx, &sy, &junk);
1247 		if (sx >= DisplayWidth(dpy, DefaultScreen(dpy)))
1248 		{
1249 			goto bail;
1250 		}
1251 		if (sy >= DisplayHeight(dpy, DefaultScreen(dpy)))
1252 		{
1253 			goto bail;
1254 		}
1255 		if (sx < 0)
1256 		{
1257 			gx = gx - sx;
1258 			gw = width + sx;
1259 			sx = 0;
1260 			if (gw <= 0)
1261 			{
1262 				goto bail;
1263 			}
1264 		}
1265 		if (sy < 0)
1266 		{
1267 			gy = gy - sy;
1268 			gh = height + sy;
1269 			sy = 0;
1270 			if (gh <= 0)
1271 			{
1272 				goto bail;
1273 			}
1274 		}
1275 		if (sx + gw > DisplayWidth(dpy, DefaultScreen(dpy)))
1276 		{
1277 			gw = DisplayWidth(dpy, DefaultScreen(dpy)) - sx;
1278 		}
1279 		if (sy + gh > DisplayHeight(dpy, DefaultScreen(dpy)))
1280 		{
1281 			gh = DisplayHeight(dpy, DefaultScreen(dpy)) - sy;
1282 		}
1283 	}
1284 #if 0
1285 	fprintf(
1286 		stderr,"Geo: %i,%i,%i,%i / %i,%i,%i,%i / %i,%i,%i,%i\n",
1287 		gx,gy,gw,gh, x,y,width,height, sx,sy,sw,sh);
1288 #endif
1289 	if (XRenderSupport && FRenderGetExtensionSupported())
1290 	{
1291 		r = XCreatePixmap(dpy, win, gw, gh, Pdepth);
1292 		if (FRenderRender(
1293 			dpy, win, ParentRelative, None, None, Pdepth, 100,
1294 			fra->tint, fra->tint_percent, r, gc, None,
1295 			gx, gy, gw, gh, 0, 0, gw, gh, False))
1296 		{
1297 			goto bail;
1298 		}
1299 		XFreePixmap(dpy, r);
1300 	}
1301 	r = PCreateRenderPixmap(
1302 		dpy, win, ParentRelative, None, None, Pdepth, 100, fra->tint,
1303 		fra->tint_percent,
1304 		True, win,
1305 		gc, None, None, gx, gy, gw, gh, gx, gy, gw, gh,
1306 		False, &dummy, &dummy, &dummy, &dp);
1307 
1308  bail:
1309 	if (old_backing_store >= 0)
1310 	{
1311 		FSetBackingStore(dpy, win, old_backing_store);
1312 	}
1313 	return r;
1314 }
1315 
PGraphicsTintRectangle(Display * dpy,Window win,Pixel tint,int tint_percent,Drawable dest,Bool dest_is_a_window,GC gc,GC mono_gc,GC alpha_gc,int dest_x,int dest_y,int dest_w,int dest_h)1316 void PGraphicsTintRectangle(
1317 	Display *dpy, Window win, Pixel tint, int tint_percent,
1318 	Drawable dest, Bool dest_is_a_window, GC gc, GC mono_gc, GC alpha_gc,
1319 	int dest_x, int dest_y, int dest_w, int dest_h)
1320 {
1321 	Pixmap p;
1322 	FvwmRenderAttributes fra;
1323 
1324 #if 0
1325 	/* this does not work. why? */
1326 	if (FRenderTintRectangle(
1327 		dpy, win, None, tint, tint_percent, dest,
1328 		dest_x, dest_y, dest_w, dest_h))
1329 	{
1330 		return;
1331 	}
1332 #else
1333 
1334 	if (FRenderRender(
1335 		dpy, win, ParentRelative, None, None, Pdepth, 100,
1336 		tint, tint_percent, win, gc, None,
1337 		dest_x, dest_y, dest_w, dest_h,
1338 		dest_x, dest_y, dest_w, dest_h, False))
1339 	{
1340 
1341 		return;
1342 	}
1343 #endif
1344 
1345 	if (dest_is_a_window)
1346 	{
1347 		fra.tint = tint;
1348 		fra.tint_percent = tint_percent;
1349 		fra.mask = FRAM_DEST_IS_A_WINDOW | FRAM_HAVE_TINT;
1350 		p = PGraphicsCreateTransparency(
1351 			dpy, dest, &fra, gc, dest_x, dest_y, dest_w, dest_h,
1352 			False);
1353 		if (p)
1354 		{
1355 			XCopyArea(
1356 				dpy, p, dest, gc, 0, 0, dest_w, dest_h,
1357 				dest_x, dest_y);
1358 			XFreePixmap(dpy, p);
1359 		}
1360 	}
1361 }
1362 
1363 #if 0 /* humm... maybe useful one day with menus */
1364 Pixmap PGraphicsCreateTranslucent(
1365 	Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
1366 	int x, int y, int width, int height)
1367 {
1368 	Pixmap r = None;
1369 	int gx = x, gy = y, gh = height, gw = width;
1370 	FvwmRenderAttributes t_fra;
1371 	Pixmap root_pix = None;
1372 	Pixmap dp = None;
1373 	int dummy;
1374 
1375 	t_fra.added_alpha_percent = 100;
1376 	t_fra.tint_percent = 0;
1377 	t_fra.tint = 0;
1378 	t_fra.mask = 0;
1379 
1380 	if (fra)
1381 	{
1382 		if (fra->mask & FRAM_HAVE_TINT)
1383 		{
1384 			t_fra.tint_percent = fra->tint_percent;
1385 			t_fra.tint = fra->tint;
1386 			t_fra.mask = FRAM_HAVE_TINT;
1387 		}
1388 	}
1389 
1390 	if (x >= DisplayWidth(dpy, DefaultScreen(dpy)))
1391 	{
1392 		goto bail;
1393 	}
1394 	if (y >= DisplayHeight(dpy, DefaultScreen(dpy)))
1395 	{
1396 		goto bail;
1397 	}
1398 	if (x < 0)
1399 	{
1400 		gx = 0;
1401 		gw = width + x;
1402 		if (gw <= 0)
1403 		{
1404 			goto bail;
1405 		}
1406 	}
1407 	if (y < 0)
1408 	{
1409 		gy = 0;
1410 		gh = gh+y;
1411 		if (gh <= 0)
1412 		{
1413 			goto bail;
1414 		}
1415 	}
1416 	if (gx + gw > DisplayWidth(dpy, DefaultScreen(dpy)))
1417 	{
1418 		gw = DisplayWidth(dpy, DefaultScreen(dpy)) - gx;
1419 	}
1420 	if (gy + gh > DisplayHeight(dpy, DefaultScreen(dpy)))
1421 	{
1422 		gh = DisplayHeight(dpy, DefaultScreen(dpy)) - gy;
1423 	}
1424 	{
1425 		/* make a screen shoot */
1426 		GC my_gc;
1427 		unsigned long valuemask = GCSubwindowMode;
1428 		XGCValues values;
1429 
1430 		values.subwindow_mode = IncludeInferiors;
1431 		root_pix = XCreatePixmap(dpy, win, gw, gh, Pdepth);
1432 		my_gc = fvwmlib_XCreateGC(dpy, win, 0, NULL);
1433 		XChangeGC(dpy, my_gc, valuemask, &values);
1434 		MyXGrabServer(dpy);
1435 		XCopyArea(
1436 			dpy, DefaultRootWindow(dpy), root_pix, my_gc,
1437 			gx, gy, gw, gh, 0, 0);
1438 		MyXUngrabServer(dpy);
1439 		XFreeGC(dpy,my_gc);
1440 	}
1441 	if (XRenderSupport && FRenderGetExtensionSupported())
1442 	{
1443 		r = XCreatePixmap(dpy, win, gw, gh, Pdepth);
1444 		if (FRenderRender(
1445 			dpy, win, root_pix, None, None, Pdepth,
1446 			t_fra.added_alpha_percent, t_fra.tint,
1447 			t_fra.tint_percent, r, gc, None,
1448 			0, 0, gw, gh, 0, 0, gw, gh, False))
1449 		{
1450 			goto bail;
1451 		}
1452 		XFreePixmap(dpy, r);
1453 		r = None;
1454 	}
1455 	r = PCreateRenderPixmap(
1456 		dpy, win, root_pix, None, None, Pdepth, 100,
1457 		fra->tint, fra->tint_percent, True, win,
1458 		gc, None, None, 0, 0, gw, gh, gx, gy, gw, gh,
1459 		False, &dummy, &dummy, &dummy, &dp);
1460 
1461  bail:
1462 	if (root_pix)
1463 	{
1464 		XFreePixmap(dpy, root_pix);
1465 	}
1466 	if (dp)
1467 	{
1468 		XFreePixmap(dpy, dp);
1469 	}
1470 	return r;
1471 }
1472 #endif
1473 
1474 
1475 /* never tested and used ! */
PGraphicsCreateDitherPixmap(Display * dpy,Window win,Drawable src,Pixmap mask,int depth,GC gc,int in_width,int in_height,int out_width,int out_height)1476 Pixmap PGraphicsCreateDitherPixmap(
1477 	Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc,
1478 	int in_width, int in_height, int out_width, int out_height)
1479 {
1480 	return PCreateDitherPixmap(
1481 		dpy, win, src, mask, depth, gc,
1482 		in_width, in_height, out_width, out_height);
1483 }
1484