Lots of cleanups to fvwm-menu-desktop
[fvwm.git] / libs / FRender.c
blob67e99c7a818addf0cdf7ffc9f512edd20450a2cc
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 "Graphics.h"
29 #include "PictureGraphics.h"
30 #include "FRenderInit.h"
31 #include "FRender.h"
32 #include "FRenderInterface.h"
34 /* ---------------------------- local definitions -------------------------- */
36 /* ---------------------------- local macros ------------------------------- */
38 /* ---------------------------- imports ------------------------------------ */
40 /* ---------------------------- included code files ------------------------ */
42 /* ---------------------------- local types -------------------------------- */
44 /* ---------------------------- forward declarations ----------------------- */
46 /* ---------------------------- local variables ---------------------------- */
48 static FRenderPictFormat *PFrenderVisualFormat = NULL;
49 static FRenderPictFormat *PFrenderAlphaFormat = NULL;
50 static FRenderPictFormat *PFrenderMaskFormat = NULL;
51 static FRenderPictFormat *PFrenderDirectFormat = NULL;
52 static FRenderPictFormat *PFrenderAbsoluteFormat = NULL;
53 Bool FRenderVisualInitialized = False;
55 /* #define USE_ABSOLUTE_FORMAT 1*/
57 /* ---------------------------- exported variables (globals) --------------- */
59 /* ---------------------------- local functions ---------------------------- */
61 static
62 void FRenderVisualInit(Display *dpy)
64 FRenderPictFormat pf;
66 if (!XRenderSupport || !FRenderGetExtensionSupported())
68 return;
71 PFrenderVisualFormat = FRenderFindVisualFormat (dpy, Pvisual);
72 if (!PFrenderVisualFormat)
74 fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: "
75 "fail to create XRender Visual Format\n");
76 return;
78 pf.depth = 8;
79 pf.type = FRenderPictTypeDirect;
80 pf.direct.alpha = 0;
81 pf.direct.alphaMask = 0xff;
82 PFrenderAlphaFormat = FRenderFindFormat(
83 dpy, FRenderPictFormatType| FRenderPictFormatDepth|
84 FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0);
85 if (!PFrenderAlphaFormat)
87 fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: "
88 "fail to create XRender Alpha Format\n");
89 return;
91 pf.depth = 1;
92 pf.type = FRenderPictTypeDirect;
93 pf.direct.alpha = 0;
94 pf.direct.alphaMask = 1;
95 PFrenderMaskFormat = FRenderFindFormat(
96 dpy, FRenderPictFormatType| FRenderPictFormatDepth|
97 FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0);
98 if (!PFrenderMaskFormat)
100 fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: "
101 "fail to create XRender Mask Format\n");
102 return;
104 pf.depth = 24;
105 pf.type = FRenderPictTypeDirect;
106 pf.direct.alpha = 0;
107 pf.direct.alphaMask = 0;
108 pf.direct.red = 16;
109 pf.direct.redMask = 0xff;
110 pf.direct.green = 8;
111 pf.direct.greenMask = 0xff;
112 pf.direct.blue = 0;
113 pf.direct.blueMask = 0xff;
114 PFrenderDirectFormat = FRenderFindFormat(
115 dpy, FRenderPictFormatType| FRenderPictFormatDepth|
116 FRenderPictFormatRed| FRenderPictFormatRedMask|
117 FRenderPictFormatGreen| FRenderPictFormatGreenMask|
118 FRenderPictFormatBlue| FRenderPictFormatBlueMask|
119 FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0);
120 if (!PFrenderDirectFormat)
122 fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: "
123 "fail to create XRender Direct Format\n");
124 return;
126 pf.depth = 32;
127 pf.type = FRenderPictTypeDirect;
128 pf.direct.alpha = 24;
129 pf.direct.alphaMask = 0xff;
130 pf.direct.red = 16;
131 pf.direct.redMask = 0xff;
132 pf.direct.green = 8;
133 pf.direct.greenMask = 0xff;
134 pf.direct.blue = 0;
135 pf.direct.blueMask = 0xff;
136 PFrenderAbsoluteFormat = FRenderFindFormat(
137 dpy, FRenderPictFormatType| FRenderPictFormatDepth|
138 FRenderPictFormatRed| FRenderPictFormatRedMask|
139 FRenderPictFormatGreen| FRenderPictFormatGreenMask|
140 FRenderPictFormatBlue| FRenderPictFormatBlueMask|
141 FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0);
142 if (!PFrenderAbsoluteFormat)
144 fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: "
145 "fail to create XRender Absolute Format\n");
146 return;
150 static
151 Bool FRenderCompositeAndCheck(
152 Display *dpy, int op, FRenderPicture src, FRenderPicture alpha,
153 FRenderPicture dest, int x, int y, int a_x, int a_y,
154 int d_x, int d_y, int d_w, int d_h)
156 FRenderComposite(
157 dpy, op, src, alpha, dest, x, y, a_x, a_y, d_x, d_y, d_w, d_h);
159 return True;
163 static
164 Bool FRenderCreateShadePicture(
165 Display *dpy, Window win, int alpha_percent)
167 static Pixmap shade_pixmap = None;
168 static FRenderPicture shade_picture = None;
169 static int saved_alpha_percent = 0;
170 Bool force_update = False;
171 FRenderColor frc;
173 if (!XRenderSupport || !FRenderGetExtensionSupported())
175 return 0;
178 /* FRender Visuals should be already initialized */
180 if (!shade_pixmap || !shade_picture)
182 FRenderPictureAttributes pa;
184 if (!shade_pixmap)
186 shade_pixmap = XCreatePixmap(dpy, win, 1, 1, 8);
188 pa.repeat = True;
189 if (shade_pixmap)
191 shade_picture = FRenderCreatePicture(
192 dpy, shade_pixmap, PFrenderAlphaFormat,
193 FRenderCPRepeat, &pa);
195 force_update = True;
197 if (shade_picture &&
198 (alpha_percent != saved_alpha_percent || force_update))
200 frc.red = frc.green = frc.blue = 0;
201 frc.alpha = 0xffff * (alpha_percent)/100;
202 FRenderFillRectangle(
203 dpy, FRenderPictOpSrc, shade_picture, &frc,
204 0, 0, 1, 1);
205 saved_alpha_percent = alpha_percent;
208 return shade_picture;
211 static
212 Bool FRenderTintPicture(
213 Display *dpy, Window win, Pixel tint, int tint_percent,
214 FRenderPicture dest_picture,
215 int dest_x, int dest_y, int dest_w, int dest_h)
217 static Pixel saved_tint = 0;
218 static int saved_tint_percent = 0;
219 static Pixmap tint_pixmap = None;
220 static FRenderPicture tint_picture = None;
221 FRenderPicture shade_picture = None;
222 FRenderColor frc_tint;
223 Bool force_update = False;
224 FRenderPictureAttributes pa;
225 int rv = 0;
227 if (!XRenderSupport)
229 return 0;
232 if (!tint_pixmap || !tint_picture)
234 pa.repeat = True;
235 if (!tint_pixmap)
237 tint_pixmap = XCreatePixmap(dpy, win, 1, 1, 32);
239 if (tint_pixmap)
241 tint_picture = FRenderCreatePicture(
242 dpy, tint_pixmap,
243 PFrenderAbsoluteFormat,
244 FRenderCPRepeat, &pa);
245 if (!tint_picture)
247 goto bail;
250 else
252 goto bail;
254 force_update = True;
256 if (tint_picture &&
257 (tint != saved_tint || tint_percent != saved_tint_percent ||
258 force_update))
260 XColor color;
261 float alpha_factor = (float)tint_percent/100;
263 force_update = False;
264 color.pixel = tint;
265 XQueryColor(dpy, Pcmap, &color);
266 frc_tint.red = color.red * alpha_factor;
267 frc_tint.green = color.green * alpha_factor;
268 frc_tint.blue = color.blue * alpha_factor;
269 frc_tint.alpha = 0xffff * alpha_factor;
270 FRenderFillRectangle(
271 dpy, FRenderPictOpSrc, tint_picture, &frc_tint,
272 0, 0, 1, 1);
273 saved_tint = tint;
274 saved_tint_percent = tint_percent;
276 if (!shade_picture)
278 shade_picture = FRenderCreateShadePicture(dpy, win, 100);
281 rv = FRenderCompositeAndCheck(
282 dpy, FRenderPictOpOver, tint_picture, shade_picture,
283 dest_picture, 0, 0, 0, 0, dest_x, dest_y, dest_w, dest_h);
285 bail:
286 return rv;
289 /* ---------------------------- interface functions ------------------------ */
292 Bool FRenderTintRectangle(
293 Display *dpy, Window win, Pixmap mask, Pixel tint, int tint_percent,
294 Drawable d, int dest_x, int dest_y, int dest_w, int dest_h)
296 FRenderPicture dest_picture = None;
297 FRenderPictureAttributes pa;
298 unsigned int val = 0;
299 Bool rv = True;
302 if (!XRenderSupport || !FRenderGetExtensionSupported())
304 return 0;
307 if (!FRenderVisualInitialized)
309 FRenderVisualInitialized = True;
310 FRenderVisualInit(dpy);
313 if (!PFrenderVisualFormat || !PFrenderAlphaFormat ||
314 !PFrenderAbsoluteFormat || !PFrenderMaskFormat)
316 return 0;
319 pa.clip_mask = mask;
320 val = FRenderCPClipMask;
322 if (!(dest_picture = FRenderCreatePicture(
323 dpy, d, PFrenderVisualFormat, val, &pa)))
325 return 0;
328 rv = FRenderTintPicture(
329 dpy, win, tint_percent, tint, dest_picture, dest_x, dest_y,
330 dest_w, dest_h);
332 FRenderFreePicture(dpy, dest_picture);
333 return rv;
336 int FRenderRender(
337 Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha,
338 int depth, int added_alpha_percent, Pixel tint, int tint_percent,
339 Drawable d, GC 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,
342 Bool do_repeat)
344 FRenderColor frc;
345 Pixmap pixmap_copy = None;
346 Pixmap alpha_copy = None;
347 FRenderPicture shade_picture = None;
348 FRenderPicture alpha_picture = None;
349 FRenderPicture mask_picture = None;
350 FRenderPicture src_picture = None;
351 FRenderPicture dest_picture = None;
352 FRenderPicture root_picture = None;
353 FRenderPictureAttributes pa;
354 unsigned long pam = 0;
355 int alpha_x = src_x;
356 int alpha_y = src_y;
357 Bool rv = False;
358 Bool free_alpha_gc = False;
360 if (!XRenderSupport || !FRenderGetExtensionSupported())
362 return 0;
365 if (!FRenderVisualInitialized)
367 FRenderVisualInitialized = True;
368 FRenderVisualInit(dpy);
371 if (!PFrenderVisualFormat || !PFrenderAlphaFormat ||
372 !PFrenderAbsoluteFormat || !PFrenderMaskFormat)
374 return 0;
377 /* it is a bitmap ? */
378 if (Pdepth != depth && pixmap)
380 pixmap_copy = PictureBitmapToPixmap(
381 dpy, win, pixmap, Pdepth, gc, src_x, src_y, src_w,
382 src_h);
383 src_x = src_y = 0;
386 pam = FRenderCPRepeat;
387 if (do_repeat)
389 pa.repeat = True;
391 else
393 pa.repeat = False;
397 * build the src_picture
399 if (pixmap == ParentRelative)
401 /* need backing store and good preparation of the win */
402 if (gc == None)
404 gc = PictureDefaultGC(dpy, win);
406 pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth);
407 if (pixmap_copy && gc)
409 XCopyArea(
410 dpy, win, pixmap_copy, gc,
411 src_x, src_y, src_w, src_h, 0, 0);
413 src_x = src_y = 0;
415 else if (tint_percent > 0 && !pixmap_copy)
417 if (gc == None)
419 gc = PictureDefaultGC(dpy, win);
421 pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth);
422 if (pixmap_copy && gc)
424 XCopyArea(
425 dpy, pixmap, pixmap_copy, gc,
426 src_x, src_y, src_w, src_h, 0, 0);
428 src_x = src_y = 0;
430 else if (!pixmap_copy)
432 src_picture = FRenderCreatePicture(
433 dpy, pixmap, PFrenderVisualFormat, pam, &pa);
436 if (!src_picture && pixmap_copy)
438 src_picture = FRenderCreatePicture(
439 dpy, pixmap_copy, PFrenderVisualFormat, pam, &pa);
442 if (!src_picture)
444 goto bail;
447 /* tint the src, it is why we have done a pixmap copy */
448 if (tint_percent > 0)
450 FRenderTintPicture(
451 dpy, win, tint, tint_percent, src_picture,
452 src_x, src_y, src_w, src_h);
455 if (added_alpha_percent >= 100)
457 if (alpha != None)
459 alpha_picture = FRenderCreatePicture(
460 dpy, alpha, PFrenderAlphaFormat, pam, &pa);
462 else if (mask != None)
464 alpha_picture = FRenderCreatePicture(
465 dpy, mask, PFrenderMaskFormat, pam, &pa);
467 else
469 /* fix a bug in certain XRender server implementation?
471 if (!(shade_picture = FRenderCreateShadePicture(
472 dpy, win, 100)))
474 goto bail;
476 alpha_x = alpha_y = 0;
479 else
481 if (alpha != None)
483 alpha_copy = XCreatePixmap(dpy, win, src_w, src_h, 8);
484 if (!alpha_gc)
486 alpha_gc = fvwmlib_XCreateGC(
487 dpy, alpha, 0, NULL);
488 free_alpha_gc = True;
490 if (alpha_copy && alpha_gc)
492 XCopyArea(dpy, alpha, alpha_copy, alpha_gc,
493 alpha_x, alpha_y, src_w, src_h, 0, 0);
494 alpha_picture = FRenderCreatePicture(
495 dpy, alpha_copy, PFrenderAlphaFormat,
496 pam, &pa);
498 if (alpha_gc && free_alpha_gc)
500 XFreeGC(dpy, alpha_gc);
502 alpha_x = alpha_y = 0;
504 else if (mask != None)
506 alpha_copy = XCreatePixmap(dpy, win, src_w, src_h, 8);
507 if (alpha_copy)
509 alpha_picture = FRenderCreatePicture(
510 dpy, alpha_copy, PFrenderAlphaFormat,
511 pam, &pa);
513 if (alpha_picture)
515 frc.red = frc.green = frc.blue = frc.alpha = 0;
516 FRenderFillRectangle(
517 dpy, FRenderPictOpSrc, alpha_picture,
518 &frc, 0, 0, src_w, src_h);
520 mask_picture = FRenderCreatePicture(
521 dpy, mask, PFrenderMaskFormat, pam, &pa);
523 else
525 alpha_x = alpha_y = 0;
528 if (!(shade_picture = FRenderCreateShadePicture(
529 dpy, win, added_alpha_percent)))
531 goto bail;
535 if (alpha != None && alpha_picture && shade_picture)
537 if (!FRenderCompositeAndCheck(
538 dpy, FRenderPictOpAtopReverse, shade_picture,
539 alpha_picture, alpha_picture,
540 0, 0, alpha_x, alpha_y, 0, 0, src_w, src_h))
542 goto bail;
544 alpha_x = alpha_y = 0;
546 else if (mask != None && alpha_picture && shade_picture)
548 if (!FRenderCompositeAndCheck(
549 dpy, FRenderPictOpAtopReverse, shade_picture,
550 mask_picture, alpha_picture,
551 0, 0, alpha_x, alpha_y, 0, 0, src_w, src_h))
553 goto bail;
555 alpha_x = alpha_y = 0;
559 if (alpha_picture == None)
561 alpha_picture = shade_picture;
564 dest_picture = FRenderCreatePicture(
565 dpy, d, PFrenderVisualFormat, 0, &pa);
567 if (dest_picture)
569 rv = FRenderCompositeAndCheck(
570 dpy, FRenderPictOpOver, src_picture, alpha_picture,
571 dest_picture, src_x, src_y, alpha_x, alpha_y,
572 dest_x, dest_y, dest_w, dest_h);
575 bail:
576 if (dest_picture)
578 FRenderFreePicture(dpy, dest_picture);
580 if (src_picture)
582 FRenderFreePicture(dpy, src_picture);
584 if (alpha_picture && alpha_picture != shade_picture)
586 FRenderFreePicture(dpy, alpha_picture);
588 if (mask_picture)
590 FRenderFreePicture(dpy, mask_picture);
592 if (root_picture)
594 FRenderFreePicture(dpy, root_picture);
596 if (alpha_copy)
598 XFreePixmap(dpy, alpha_copy);
600 if (pixmap_copy)
602 XFreePixmap(dpy, pixmap_copy);
604 return rv;