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 = fxmalloc(n_src_w * n_src_h * sizeof(XColor));
472 	if (dest_fim)
473 	{
474 		dest_colors = fxmalloc(w * h * sizeof(XColor));
475 	}
476 	am = fxmalloc(n_src_w * n_src_h * sizeof(unsigned short));
477 
478 	if (tint_percent > 0)
479 	{
480 		tint_color.pixel = tint;
481 		XQueryColor(dpy, Pcmap, &tint_color);
482 	}
483 
484 	for (j = 0; j < n_src_h; j++)
485 	{
486 		for (i = 0; i < n_src_w; i++, m++)
487 		{
488 			if (mask_fim != NULL &&
489 			    (XGetPixel(mask_fim->im, i, j) == 0))
490 			{
491 				am[m] = 0;
492 			}
493 			else if (alpha_fim != NULL)
494 			{
495 				am[m] = XGetPixel(alpha_fim->im, i, j);
496 				if (am[m] == 0 && !dest_fim)
497 				{
498 					make_new_mask = True;
499 				}
500 			}
501 			else
502 			{
503 				am[m] = 255;
504 			}
505 			if (added_alpha_percent < 100)
506 			{
507 				am[m] = (unsigned short)
508 					((am[m] * added_alpha_percent) / 100);
509 			}
510 			if (am[m] > 0)
511 			{
512 				if (!dest_fim)
513 				{
514 					if (am[m] < 130)
515 					{
516 						am[m] = 0;
517 						make_new_mask = True;
518 					}
519 					else
520 					{
521 						am[m] = 255;
522 					}
523 				}
524 				else if (am[m] < 255)
525 				{
526 					dest_colors[l++].pixel =
527 						XGetPixel(dest_fim->im, i, j);
528 				}
529 				if (am[m] > 0)
530 				{
531 					colors[k++].pixel =
532 						XGetPixel(pixmap_fim->im, i, j);
533 				}
534 			}
535 		}
536 	}
537 
538 	for (i = 0; i < k; i += 256)
539 		XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
540 
541 	if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w))
542 	{
543 		for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h)
544 		{
545 			for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w)
546 			{
547 				for(j = 0;
548 				    !(i1==0 && j1==0) && j < n_src_h && j+j1 < h;
549 				    j++)
550 				{
551 					for(i = 0; i < n_src_w && i+i1 < w; i++)
552 					{
553 						m = j*n_src_w + i;
554 						if (am[m] > 0 && am[m] < 255)
555 						{
556 							dest_colors[l++].pixel =
557 								XGetPixel(
558 									dest_fim
559 									->im,
560 									i1+i,
561 									j1+j);
562 						}
563 					}
564 				}
565 			}
566 		}
567 	}
568 
569 	for (i = 0; i < l; i += 256)
570 		XQueryColors(dpy, Pcmap, &dest_colors[i], min(l - i, 256));
571 
572 	if (make_new_mask)
573 	{
574 		 *new_mask = XCreatePixmap(dpy, win, w, h, 1);
575 		 if (*new_mask)
576 		 {
577 			 new_mask_fim = FCreateFImage(
578 				 dpy, Pvisual, 1, ZPixmap, w, h);
579 			if (!new_mask_fim)
580 			{
581 				error = True;
582 				goto bail;
583 			}
584 			 if (mono_gc == None)
585 			 {
586 				 mono_gc = fvwmlib_XCreateGC(
587 					 dpy, *new_mask, 0, NULL);
588 				 do_free_mono_gc = True;
589 			 }
590 		 }
591 	}
592 
593 	l = 0; m = 0; k = 0;
594 	c.flags = DoRed | DoGreen | DoBlue;
595 	for (j = 0; j < n_src_h; j++)
596 	{
597 		for (i = 0; i < n_src_w; i++, m++)
598 		{
599 			if (am[m] > 0)
600 			{
601 				if (*new_mask)
602 				{
603 					XPutPixel(new_mask_fim->im, i, j, 1);
604 				}
605 				if (tint_percent > 0)
606 				{
607 					colors[k].blue = (unsigned short)
608 						(((100-tint_percent)*
609 						  colors[k].blue +
610 						  tint_color.blue *
611 						  tint_percent) /
612 						 100);
613 					colors[k].green = (unsigned short)
614 						(((100-tint_percent)*
615 						  colors[k].green +
616 						  tint_color.green *
617 						  tint_percent) /
618 						 100);
619 					colors[k].red = (unsigned short)
620 						(((100-tint_percent)*
621 						  colors[k].red +
622 						  tint_color.red *
623 						  tint_percent) /
624 						 100);
625 				}
626 				c.blue = colors[k].blue;
627 				c.green = colors[k].green;
628 				c.red = colors[k].red;
629 				if (am[m] < 255 && dest_fim)
630 				{
631 					c.blue = (unsigned short)
632 						(((255 - am[m])*
633 						  dest_colors[l].blue +
634 						  c.blue * am[m]) /
635 						 255);
636 					c.green = (unsigned short)
637 						(((255 - am[m])*
638 						  dest_colors[l].green +
639 						  c.green * am[m]) /
640 						 255);
641 					c.red = (unsigned short)
642 						(((255 - am[m])*
643 						  dest_colors[l].red +
644 						  c.red * am[m]) /
645 						 255);
646 					l++;
647 				}
648 				PictureAllocColor(Pdpy, Pcmap, &c, False);
649 				colors[k].pixel = c.pixel;
650 				k++;
651 			}
652 			else
653 			{
654 				if (dest_fim)
655 				{
656 					c.pixel = XGetPixel(dest_fim->im, i, j);
657 				}
658 				else
659 				{
660 					c.pixel = XGetPixel(
661 						pixmap_fim->im, i, j);
662 				}
663 				if (*new_mask)
664 				{
665 					XPutPixel(new_mask_fim->im, i, j, 0);
666 				}
667 			}
668 			XPutPixel(out_fim->im, i, j, c.pixel);
669 		}
670 	}
671 
672 	/* tile: editor ligne width limit  107 !!*/
673 	if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w))
674 	{
675 		for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h)
676 		{
677 			for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w)
678 			{
679 				k = 0;
680 				for(j = 0;
681 				    !(i1==0 && j1==0) && j < n_src_h; j++)
682 				{
683 					for(i = 0; i < n_src_w; i++)
684 					{
685 						m = j*n_src_w + i;
686 						if (!(i+i1 < w && j+j1 < h))
687 						{
688 							if (am[m] > 0)
689 							{
690 								k++;
691 							}
692 						}
693 						else
694 						{
695 							if (am[m] > 0)
696 							{
697 								if (*new_mask)
698 								{
699 									XPutPixel(
700 										new_mask_fim->im, i+i1,
701 										j+j1, 1);
702 								}
703 								c.blue = colors[k].blue;
704 								c.green = colors[k].green;
705 								c.red = colors[k].red;
706 								c.pixel = colors[k].pixel;
707 								k++;
708 								if (am[m] < 255)
709 								{
710 									c.blue = (unsigned short)
711 										(((255 - am[m])*
712 										  dest_colors[l].blue +
713 										  c.blue * am[m]) /
714 										 255);
715 									c.green = (unsigned short)
716 										(((255 - am[m])*
717 										  dest_colors[l].green +
718 										  c.green * am[m]) /
719 										 255);
720 									c.red = (unsigned short)
721 										(((255 - am[m])*
722 										  dest_colors[l].red +
723 										  c.red * am[m]) /
724 										 255);
725 									l++;
726 									PictureAllocColor(
727 										Pdpy, Pcmap, &c, False);
728 								}
729 							}
730 							else
731 							{
732 								c.pixel = XGetPixel(
733 									dest_fim->im, i+i1, j+j1);
734 								if (*new_mask)
735 								{
736 									XPutPixel(
737 										new_mask_fim->im, i+i1,
738 										j+j1, 0);
739 								}
740 							}
741 							XPutPixel(out_fim->im, i+i1, j+j1, c.pixel);
742 						}
743 					}
744 				}
745 			}
746 		}
747 	}
748 
749 	FPutFImage(dpy, out_pix, gc, out_fim, 0, 0, 0, 0, w, h);
750 	if (*new_mask && mono_gc)
751 	{
752 		FPutFImage(
753 			dpy, *new_mask, mono_gc, new_mask_fim,
754 			0, 0, 0, 0, w, h);
755 	}
756 
757  bail:
758 	if (colors)
759 	{
760 		free(colors);
761 	}
762 	if (dest_colors)
763 	{
764 		free(dest_colors);
765 	}
766 	if (am)
767 	{
768 		free(am);
769 	}
770 	if (pixmap_copy)
771 	{
772 		XFreePixmap(dpy, pixmap_copy);
773 	}
774 	if (pixmap_fim)
775 	{
776 		FDestroyFImage(dpy, pixmap_fim);
777 	}
778 	if (mask_fim)
779 	{
780 		FDestroyFImage(dpy, mask_fim);
781 	}
782 	if (alpha_fim)
783 	{
784 		FDestroyFImage(dpy, alpha_fim);
785 	}
786 	if (dest_fim)
787 	{
788 		FDestroyFImage(dpy, dest_fim);
789 	}
790 	if (new_mask_fim)
791 	{
792 		FDestroyFImage(dpy, new_mask_fim);
793 	}
794 	if (do_free_mono_gc && mono_gc)
795 	{
796 		XFreeGC(dpy, mono_gc);
797 	}
798 	if (out_fim)
799 	{
800 		FDestroyFImage(dpy, out_fim);
801 	}
802 	if (error)
803 	{
804 		if (out_pix != None)
805 		{
806 			XFreePixmap(dpy, out_pix);
807 			out_pix = None;
808 		}
809 		if (*new_mask != None)
810 		{
811 			XFreePixmap(dpy, *new_mask);
812 			*new_mask = None;
813 		}
814 	}
815 
816 	return out_pix;
817 }
818 
819 /* never used and tested */
820 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)821 Pixmap PCreateDitherPixmap(
822 	Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc,
823 	int in_width, int in_height, int out_width, int out_height)
824 {
825 	FImage *src_fim;
826 	FImage *mask_fim = NULL;
827 	FImage *out_fim;
828 	Pixmap out_pix = None;
829 	unsigned char *cm;
830 	XColor *colors;
831 	XColor c;
832 	int j, i, m = 0, k = 0, x = 0, y = 0;
833 
834 	if (depth != Pdepth)
835 		return None;
836 
837 	if (!(src_fim =
838 	      FGetFImage(
839 		      dpy, src, Pvisual, depth, 0, 0, in_width, in_height,
840 		      AllPlanes, ZPixmap)))
841 	{
842 		return None;
843 	}
844 	if (mask != None)
845 	{
846 		mask_fim = FGetFImage(
847 			dpy, mask, Pvisual, 1, 0, 0, in_width, in_height,
848 			AllPlanes, ZPixmap);
849 		if (!mask_fim)
850 		{
851 			FDestroyFImage(dpy, mask_fim);
852 			return None;
853 		}
854 	}
855 	out_pix = XCreatePixmap(dpy, win, out_width, out_height, Pdepth);
856 	out_fim = FCreateFImage(
857 		dpy, Pvisual, Pdepth, ZPixmap, out_width, out_height);
858 	if (gc == None)
859 	{
860 		gc = PictureDefaultGC(dpy, win);
861 	}
862 
863 	if (!out_pix || !out_fim || !gc)
864 	{
865 		FDestroyFImage(dpy, src_fim);
866 		if (mask_fim)
867 		{
868 			FDestroyFImage(dpy, mask_fim);
869 		}
870 		if (out_pix)
871 		{
872 			XFreePixmap(dpy, out_pix);
873 		}
874 		if (out_fim)
875 		{
876 			FDestroyFImage(dpy, out_fim);
877 		}
878 		return None;
879 	}
880 
881 	colors = fxmalloc(out_width * out_height * sizeof(XColor));
882 	cm = fxmalloc(out_width * out_height * sizeof(char));
883 
884 	x = y = 0;
885 	for (j = 0; j < out_height; j++,y++)
886 	{
887 		if (y == in_height)
888 			y = 0;
889 		for (i = 0; i < out_width; i++,x++)
890 		{
891 			if (x == in_width)
892 				x = 0;
893 			if (mask_fim != NULL &&
894 			    (XGetPixel(mask_fim->im, x, y) == 0))
895 			{
896 				cm[m++] = 0;
897 			}
898 			else
899 			{
900 				cm[m++] = 255;
901 				colors[k++].pixel = XGetPixel(src_fim->im, x, y);
902 			}
903 		}
904 	}
905 
906 	for (i = 0; i < k; i += 256)
907 		XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
908 
909 	k = 0;m = 0;
910 	for (j = 0; j < out_height; j++)
911 	{
912 		for (i = 0; i < out_width; i++)
913 		{
914 
915 			if (cm[m] > 0)
916 			{
917 				c = colors[k++];
918 				PictureAllocColorAllProp(
919 					Pdpy, Pcmap, &c, i, j, False, False,
920 					True);
921 			}
922 			else
923 			{
924 				c.pixel = XGetPixel(src_fim->im, i, j);
925 			}
926 			XPutPixel(out_fim->im, i, j, c.pixel);
927 			m++;
928 		}
929 	}
930 	free(colors);
931 	free(cm);
932 	FDestroyFImage(dpy, src_fim);
933 	if (mask_fim)
934 	{
935 		FDestroyFImage(dpy, mask_fim);
936 	}
937 	FPutFImage(
938 		dpy, out_pix, gc, out_fim, 0, 0, 0, 0, out_width, out_height);
939 	FDestroyFImage(dpy, out_fim);
940 
941 	return out_pix;
942 }
943 
944 /* ---------------------------- interface functions ------------------------ */
945 
PictureBitmapToPixmap(Display * dpy,Window win,Pixmap src,int depth,GC gc,int src_x,int src_y,int src_w,int src_h)946 Pixmap PictureBitmapToPixmap(
947 	Display *dpy, Window win, Pixmap src, int depth, GC gc,
948 	int src_x, int src_y, int src_w, int src_h)
949 {
950 	Pixmap dest = None;
951 
952 	dest = XCreatePixmap(dpy, win, src_w, src_h, depth);
953 	if (dest && gc == None)
954 	{
955 		gc = PictureDefaultGC(dpy, win);
956 	}
957 	if (dest && gc)
958 	{
959 		XCopyPlane(
960 			dpy, src, dest, gc,
961 			src_x, src_y, src_w, src_h, 0, 0, 1);
962 	}
963 
964 	return dest;
965 }
966 
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)967 void PGraphicsRenderPixmaps(
968 	Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
969 	int depth, FvwmRenderAttributes *fra, Drawable d,
970 	GC gc, GC mono_gc, GC alpha_gc,
971 	int src_x, int src_y, int src_w, int src_h,
972 	int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat)
973 {
974 	FvwmRenderAttributes t_fra;
975 	Pixmap xrs_pixmap = None;
976 	Pixmap xrs_mask = None;
977 	Pixmap tmp_pixmap, tmp_mask;
978 	Bool d_is_a_window;
979 
980 	t_fra.added_alpha_percent = 100;
981 	t_fra.tint_percent = 0;
982 	t_fra.mask = 0;
983 	t_fra.tint = None;
984 
985 	if (fra)
986 	{
987 		t_fra.mask = fra->mask;
988 		if (fra->mask & FRAM_HAVE_ICON_CSET)
989 		{
990 			t_fra.added_alpha_percent =
991 				fra->colorset->icon_alpha_percent;
992 			t_fra.tint_percent = fra->colorset->icon_tint_percent;
993 			t_fra.tint = fra->colorset->icon_tint;
994 		}
995 		if (fra->mask & FRAM_HAVE_ADDED_ALPHA)
996 		{
997 			t_fra.added_alpha_percent = fra->added_alpha_percent;
998 		}
999 		if (fra->mask & FRAM_HAVE_TINT)
1000 		{
1001 			t_fra.tint_percent = fra->tint_percent;
1002 			t_fra.tint = fra->tint;
1003 		}
1004 	}
1005 	if (dest_w == 0 && dest_h == 0)
1006 	{
1007 		dest_w = src_w; dest_h = src_h;
1008 	}
1009 
1010 	/* use XRender only when "needed" (backing store pbs) */
1011 	if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100
1012 	    || alpha != None)
1013 	{
1014 		/* for testing XRender simulation add && 0 */
1015 		if (FRenderRender(
1016 			dpy, win, pixmap, mask, alpha, depth,
1017 			t_fra.added_alpha_percent, t_fra.tint,
1018 			t_fra.tint_percent,
1019 			d, gc, alpha_gc, src_x, src_y, src_w, src_h,
1020 			dest_x, dest_y, dest_w, dest_h, do_repeat))
1021 		{
1022 			return;
1023 		}
1024 	}
1025 
1026 	/* no render extension or something strange happen */
1027 	if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100
1028 	    || alpha != None)
1029 	{
1030 		int new_w, new_h, new_do_repeat;
1031 
1032 		d_is_a_window = !!(t_fra.mask & FRAM_DEST_IS_A_WINDOW);
1033 		xrs_pixmap = PCreateRenderPixmap(
1034 			dpy, win, pixmap, mask, alpha, depth,
1035 			t_fra.added_alpha_percent, t_fra.tint,
1036 			t_fra.tint_percent, d_is_a_window, d,
1037 			gc, mono_gc, alpha_gc,
1038 			src_x, src_y, src_w, src_h,
1039 			dest_x, dest_y, dest_w, dest_h, do_repeat,
1040 			&new_w, &new_h, &new_do_repeat, &xrs_mask);
1041 		if (xrs_pixmap)
1042 		{
1043 			src_x = 0;
1044 			src_y = 0;
1045 			src_w = new_w;
1046 			src_h = new_h;
1047 			depth = Pdepth;
1048 			do_repeat = new_do_repeat;
1049 		}
1050 	}
1051 	tmp_pixmap = (xrs_pixmap != None)? xrs_pixmap:pixmap;
1052 	tmp_mask = (xrs_mask != None)? xrs_mask:mask;
1053 	if (do_repeat)
1054 	{
1055 		PTileRectangle(
1056 			dpy, win, tmp_pixmap, tmp_mask, depth,
1057 			src_x, src_y, d, gc, mono_gc, dest_x, dest_y, dest_w,
1058 			dest_h);
1059 	}
1060 	else
1061 	{
1062 		PCopyArea(
1063 			dpy, tmp_pixmap, tmp_mask, depth, d, gc,
1064 			src_x, src_y, src_w, src_h, dest_x, dest_y);
1065 	}
1066 	if (xrs_pixmap)
1067 	{
1068 		XFreePixmap(dpy, xrs_pixmap);
1069 	}
1070 	if (xrs_mask)
1071 	{
1072 		XFreePixmap(dpy, xrs_mask);
1073 	}
1074 }
1075 
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)1076 void PGraphicsRenderPicture(
1077 	Display *dpy, Window win, FvwmPicture *p, FvwmRenderAttributes *fra,
1078 	Drawable d, GC gc, GC mono_gc, GC alpha_gc,
1079 	int src_x, int src_y, int src_w, int src_h,
1080 	int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat)
1081 {
1082 	PGraphicsRenderPixmaps(
1083 		dpy, win, p->picture, p->mask, p->alpha, p->depth, fra,
1084 		d, gc, mono_gc, alpha_gc,
1085 		src_x, src_y, src_w, src_h,
1086 		dest_x, dest_y, dest_w, dest_h, do_repeat);
1087 }
1088 
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)1089 void PGraphicsCopyPixmaps(
1090 	Display *dpy, Pixmap pixmap, Pixmap mask, Pixmap alpha,
1091 	int depth, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h,
1092 	int dest_x, int dest_y)
1093 {
1094 	PGraphicsRenderPixmaps(
1095 		dpy,  None, pixmap, mask, alpha, depth, 0, d, gc, None, None,
1096 		src_x, src_y, src_w, src_h, dest_x, dest_y, src_w, src_h, False);
1097 }
1098 
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)1099 void PGraphicsCopyFvwmPicture(
1100 	Display *dpy, FvwmPicture *p, Drawable d, GC gc,
1101 	int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y)
1102 {
1103 	PGraphicsRenderPicture(
1104 		dpy, None, p, 0, d, gc, None, None, src_x, src_y, src_w, src_h,
1105 		dest_x, dest_y, src_w, src_h, False);
1106 }
1107 
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)1108 void PGraphicsTileRectangle(
1109 	Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
1110 	int depth, Drawable d, GC gc, GC mono_gc,
1111 	int src_x, int src_y,  int src_w, int src_h,
1112 	int dest_x, int dest_y, int dest_w, int dest_h)
1113 {
1114 	PGraphicsRenderPixmaps(
1115 		dpy, win, pixmap, mask, alpha, depth, 0, d, gc, mono_gc, None,
1116 		src_x, src_y, dest_w, dest_h, dest_x, dest_y, dest_w, dest_h,
1117 		True);
1118 }
1119 
PGraphicsCreateStretchPicture(Display * dpy,Window win,FvwmPicture * src,int dest_width,int dest_height,GC gc,GC mono_gc,GC alpha_gc)1120 FvwmPicture *PGraphicsCreateStretchPicture(
1121 	Display *dpy, Window win, FvwmPicture *src,
1122 	int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc)
1123 {
1124 	Pixmap pixmap = None, mask = None, alpha = None;
1125 	FvwmPicture *q;
1126 
1127 	if (src == NULL || src->picture == None)
1128 	{
1129 		return NULL;
1130 	}
1131 	pixmap = CreateStretchPixmap(
1132 		dpy, src->picture, src->width, src->height, src->depth,
1133 		dest_width, dest_height, gc);
1134 	if (!pixmap)
1135 	{
1136 		return NULL;
1137 	}
1138 	if (src->mask)
1139 	{
1140 		mask = CreateStretchPixmap(
1141 			dpy, src->mask, src->width, src->height, 1,
1142 			dest_width, dest_height, mono_gc);
1143 	}
1144 	if (src->alpha)
1145 	{
1146 		alpha = CreateStretchPixmap(
1147 			dpy, src->alpha, src->width, src->height,
1148 			FRenderGetAlphaDepth(),
1149 			dest_width, dest_height, alpha_gc);
1150 	}
1151 
1152 	q = fxcalloc(1, sizeof(FvwmPicture));
1153 	q->count = 1;
1154 	q->name = NULL;
1155 	q->next = NULL;
1156 	q->stamp = pixmap;
1157 	q->picture = pixmap;
1158 	q->mask = mask;
1159 	q->alpha = alpha;
1160 	q->width = dest_width;
1161 	q->height = dest_height;
1162 	q->depth = src->depth;
1163 	q->alloc_pixels = 0;
1164 	q->nalloc_pixels = 0;
1165 
1166 	return q;
1167 }
1168 
PGraphicsCreateTiledPicture(Display * dpy,Window win,FvwmPicture * src,int dest_width,int dest_height,GC gc,GC mono_gc,GC alpha_gc)1169 FvwmPicture *PGraphicsCreateTiledPicture(
1170 	Display *dpy, Window win, FvwmPicture *src,
1171 	int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc)
1172 {
1173 	Pixmap pixmap = None, mask = None, alpha = None;
1174 	FvwmPicture *q;
1175 
1176 	if (src == NULL || src->picture == None)
1177 	{
1178 		return NULL;
1179 	}
1180 	pixmap = CreateTiledPixmap(
1181 		dpy, src->picture, src->width, src->height, dest_width,
1182 		dest_height, src->depth, gc);
1183 	if (!pixmap)
1184 	{
1185 		return NULL;
1186 	}
1187 	if (src->mask)
1188 	{
1189 		mask = CreateTiledPixmap(
1190 			dpy, src->mask, src->width, src->height, dest_width,
1191 			dest_height, 1, mono_gc);
1192 	}
1193 	if (src->alpha)
1194 	{
1195 		alpha = CreateTiledPixmap(
1196 			dpy, src->alpha, src->width, src->height, dest_width,
1197 			dest_height, FRenderGetAlphaDepth(), alpha_gc);
1198 	}
1199 
1200 	q = fxcalloc(1, 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;
1213 
1214 	return q;
1215 }
1216 
PGraphicsCreateTransparency(Display * dpy,Window win,FvwmRenderAttributes * fra,GC gc,int x,int y,int width,int height,Bool parent_relative)1217 Pixmap PGraphicsCreateTransparency(
1218 	Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
1219 	int x, int y, int width, int height, Bool parent_relative)
1220 {
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;
1227 
1228 	if (parent_relative)
1229 	{
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);
1234 	}
1235 
1236 	if (parent_relative)
1237 	{
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))
1243 		{
1244 			goto bail;
1245 		}
1246 		XTranslateCoordinates(
1247 			dpy, win, DefaultRootWindow(dpy), x, y, &sx, &sy, &junk);
1248 		if (sx >= DisplayWidth(dpy, DefaultScreen(dpy)))
1249 		{
1250 			goto bail;
1251 		}
1252 		if (sy >= DisplayHeight(dpy, DefaultScreen(dpy)))
1253 		{
1254 			goto bail;
1255 		}
1256 		if (sx < 0)
1257 		{
1258 			gx = gx - sx;
1259 			gw = width + sx;
1260 			sx = 0;
1261 			if (gw <= 0)
1262 			{
1263 				goto bail;
1264 			}
1265 		}
1266 		if (sy < 0)
1267 		{
1268 			gy = gy - sy;
1269 			gh = height + sy;
1270 			sy = 0;
1271 			if (gh <= 0)
1272 			{
1273 				goto bail;
1274 			}
1275 		}
1276 		if (sx + gw > DisplayWidth(dpy, DefaultScreen(dpy)))
1277 		{
1278 			gw = DisplayWidth(dpy, DefaultScreen(dpy)) - sx;
1279 		}
1280 		if (sy + gh > DisplayHeight(dpy, DefaultScreen(dpy)))
1281 		{
1282 			gh = DisplayHeight(dpy, DefaultScreen(dpy)) - sy;
1283 		}
1284 	}
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())
1291 	{
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))
1297 		{
1298 			goto bail;
1299 		}
1300 		XFreePixmap(dpy, r);
1301 	}
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);
1308 
1309  bail:
1310 	if (old_backing_store >= 0)
1311 	{
1312 		FSetBackingStore(dpy, win, old_backing_store);
1313 	}
1314 	return r;
1315 }
1316 
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)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)
1321 {
1322 	Pixmap p;
1323 	FvwmRenderAttributes fra;
1324 
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))
1330 	{
1331 		return;
1332 	}
1333 #else
1334 
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))
1340 	{
1341 
1342 		return;
1343 	}
1344 #endif
1345 
1346 	if (dest_is_a_window)
1347 	{
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)
1355 		{
1356 			XCopyArea(
1357 				dpy, p, dest, gc, 0, 0, dest_w, dest_h,
1358 				dest_x, dest_y);
1359 			XFreePixmap(dpy, p);
1360 		}
1361 	}
1362 }
1363 
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)
1368 {
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;
1375 
1376 	t_fra.added_alpha_percent = 100;
1377 	t_fra.tint_percent = 0;
1378 	t_fra.tint = 0;
1379 	t_fra.mask = 0;
1380 
1381 	if (fra)
1382 	{
1383 		if (fra->mask & FRAM_HAVE_TINT)
1384 		{
1385 			t_fra.tint_percent = fra->tint_percent;
1386 			t_fra.tint = fra->tint;
1387 			t_fra.mask = FRAM_HAVE_TINT;
1388 		}
1389 	}
1390 
1391 	if (x >= DisplayWidth(dpy, DefaultScreen(dpy)))
1392 	{
1393 		goto bail;
1394 	}
1395 	if (y >= DisplayHeight(dpy, DefaultScreen(dpy)))
1396 	{
1397 		goto bail;
1398 	}
1399 	if (x < 0)
1400 	{
1401 		gx = 0;
1402 		gw = width + x;
1403 		if (gw <= 0)
1404 		{
1405 			goto bail;
1406 		}
1407 	}
1408 	if (y < 0)
1409 	{
1410 		gy = 0;
1411 		gh = gh+y;
1412 		if (gh <= 0)
1413 		{
1414 			goto bail;
1415 		}
1416 	}
1417 	if (gx + gw > DisplayWidth(dpy, DefaultScreen(dpy)))
1418 	{
1419 		gw = DisplayWidth(dpy, DefaultScreen(dpy)) - gx;
1420 	}
1421 	if (gy + gh > DisplayHeight(dpy, DefaultScreen(dpy)))
1422 	{
1423 		gh = DisplayHeight(dpy, DefaultScreen(dpy)) - gy;
1424 	}
1425 	{
1426 		/* make a screen shoot */
1427 		GC my_gc;
1428 		unsigned long valuemask = GCSubwindowMode;
1429 		XGCValues values;
1430 
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);
1441 	}
1442 	if (XRenderSupport && FRenderGetExtensionSupported())
1443 	{
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))
1450 		{
1451 			goto bail;
1452 		}
1453 		XFreePixmap(dpy, r);
1454 		r = None;
1455 	}
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);
1461 
1462  bail:
1463 	if (root_pix)
1464 	{
1465 		XFreePixmap(dpy, root_pix);
1466 	}
1467 	if (dp)
1468 	{
1469 		XFreePixmap(dpy, dp);
1470 	}
1471 	return r;
1472 }
1473 #endif
1474 
1475 
1476 /* 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)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)
1480 {
1481 	return PCreateDitherPixmap(
1482 		dpy, win, src, mask, depth, gc,
1483 		in_width, in_height, out_width, out_height);
1484 }
1485