aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/Transparent.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/Transparent.cc')
-rw-r--r--src/FbTk/Transparent.cc276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/FbTk/Transparent.cc b/src/FbTk/Transparent.cc
new file mode 100644
index 0000000..ed50e9e
--- /dev/null
+++ b/src/FbTk/Transparent.cc
@@ -0,0 +1,276 @@
1// Transparent.cc for FbTk - Fluxbox Toolkit
2// Copyright (c) 2003 Henrik Kinnunen (fluxgen(at)users.sourceforge.net)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id: Transparent.cc,v 1.5 2003/05/13 20:50:56 fluxgen Exp $
23
24#include "Transparent.hh"
25#include "App.hh"
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif // HAVE_CONFIG_H
30
31#ifdef HAVE_XRENDER
32#include <X11/extensions/Xrender.h>
33#endif // HAVE_XRENDER
34
35#include <iostream>
36using namespace std;
37
38namespace {
39#ifdef HAVE_XRENDER
40Picture createAlphaPic(Window drawable, unsigned char alpha) {
41 Display *disp = FbTk::App::instance()->display();
42
43 // try to find a specific render format
44 XRenderPictFormat pic_format;
45 pic_format.type = PictTypeDirect;
46 pic_format.depth = 8; // alpha with bit depth 8
47 pic_format.direct.alphaMask = 0xff;
48 XRenderPictFormat *format = XRenderFindFormat(disp, PictFormatType |
49 PictFormatDepth | PictFormatAlphaMask,
50 &pic_format, 0);
51 if (format == 0) {
52 cerr<<"Warning! FbTk::Transparent: Failed to find valid format for alpha."<<endl;
53 return 0;
54 }
55
56 // create one pixel pixmap with depth 8 for alpha
57 Pixmap alpha_pm = XCreatePixmap(disp, drawable,
58 1, 1, 8);
59 if (alpha_pm == 0) {
60 cerr<<"Warning! FbTk::Transparent: Failed to create alpha pixmap."<<endl;
61 return 0;
62 }
63
64 // create picture with alpha_pm as repeated background
65 XRenderPictureAttributes attr;
66 attr.repeat = True; // small bitmap repeated
67 Picture alpha_pic = XRenderCreatePicture(disp, alpha_pm,
68 format, CPRepeat, &attr);
69 if (alpha_pic == 0) {
70 XFreePixmap(disp, alpha_pm);
71 cerr<<"Warning! FbTk::Transparent: Failed to create alpha picture."<<endl;
72 return 0;
73 }
74
75 // finaly set alpha and fill with it
76 XRenderColor color;
77 // calculate alpha percent and then scale it to short
78 color.red = 0xFF;
79 color.blue = 0xFF;
80 color.green = 0xFF;
81 color.alpha = ((unsigned short) (255 * alpha) << 8);
82 if (alpha == 0)
83 color.alpha = 0xFF00;
84
85 XRenderFillRectangle(disp, PictOpSrc, alpha_pic, &color,
86 0, 0, 1, 1);
87
88 XFreePixmap(disp, alpha_pm);
89
90 return alpha_pic;
91}
92#endif // HAVE_XRENDER
93};
94
95namespace FbTk {
96
97bool Transparent::s_init = false;
98bool Transparent::s_render = false;
99
100Transparent::Transparent(Drawable src, Drawable dest, unsigned char alpha, int screen_num):
101 m_alpha_pic(0), m_src_pic(0), m_dest_pic(0),
102 m_source(src), m_dest(dest), m_alpha(alpha) {
103
104 Display *disp = FbTk::App::instance()->display();
105
106 // check for RENDER support
107 if (!s_init) {
108 int major_opcode, first_event, first_error;
109 if (XQueryExtension(disp, "RENDER",
110 &major_opcode,
111 &first_event, &first_error) == False) {
112 s_render = false;
113 } else { // we got RENDER support
114 s_render = true;
115 }
116 s_init = true;
117 }
118
119
120#ifdef HAVE_XRENDER
121 if (!s_render)
122 return;
123
124 allocAlpha(m_alpha);
125
126
127 XRenderPictFormat *format =
128 XRenderFindVisualFormat(disp,
129 DefaultVisual(disp, screen_num));
130
131
132 if (src != 0 && format != 0) {
133 m_src_pic = XRenderCreatePicture(disp, src, format,
134 0, 0);
135 }
136
137 if (dest != 0 && format != 0) {
138 m_dest_pic = XRenderCreatePicture(disp, dest, format,
139 0, 0);
140 }
141#endif // HAVE_XRENDER
142}
143
144Transparent::~Transparent() {
145#ifdef HAVE_XRENDER
146 if (m_alpha_pic != 0 && s_render)
147 freeAlpha();
148
149 Display *disp = FbTk::App::instance()->display();
150
151 if (m_dest_pic != 0 && s_render)
152 XRenderFreePicture(disp, m_dest_pic);
153
154 if (m_src_pic != 0 && s_render)
155 XRenderFreePicture(disp, m_src_pic);
156#endif // HAVE_XRENDER
157}
158
159void Transparent::setAlpha(unsigned char alpha) {
160 if (m_source == 0 || !s_render)
161 return;
162
163 freeAlpha();
164 allocAlpha(alpha);
165}
166
167void Transparent::setDest(Drawable dest, int screen_num) {
168#ifdef HAVE_XRENDER
169 if (m_dest == dest || !s_render)
170 return;
171
172 Display *disp = FbTk::App::instance()->display();
173
174 if (m_dest_pic != 0) {
175 XRenderFreePicture(disp, m_dest_pic);
176 m_dest_pic = 0;
177 }
178 // create new dest pic if we have a valid dest drawable
179 if (dest != 0) {
180
181 XRenderPictFormat *format =
182 XRenderFindVisualFormat(disp,
183 DefaultVisual(disp, screen_num));
184 if (format == 0)
185 cerr<<"Warning! FbTk::Transparent: Failed to find format for screen("<<screen_num<<")"<<endl;
186 m_dest_pic = XRenderCreatePicture(disp, dest, format, 0, 0);
187
188
189 }
190 m_dest = dest;
191#endif // HAVE_XRENDER
192}
193
194void Transparent::setSource(Drawable source, int screen_num) {
195#ifdef HAVE_XRENDER
196 if (m_source == source || !s_render)
197 return;
198 // save old alpha value so we can recreate new later
199 // with the same value
200 unsigned char old_alpha = m_alpha;
201 if (m_alpha_pic != 0)
202 freeAlpha();
203
204 Display *disp = FbTk::App::instance()->display();
205
206 if (m_src_pic != 0) {
207 XRenderFreePicture(disp, m_src_pic);
208 m_src_pic = 0;
209 }
210
211 m_source = source;
212
213 // create new source pic if we have a valid source drawable
214 if (m_source != 0) {
215
216 XRenderPictFormat *format =
217 XRenderFindVisualFormat(disp,
218 DefaultVisual(disp, screen_num));
219 if (format == 0)
220 cerr<<"Warning! FbTk::Transparent: Failed to find format for screen("<<screen_num<<")"<<endl;
221 m_src_pic = XRenderCreatePicture(disp, m_source, format,
222 0, 0);
223 }
224
225 // recreate new alpha
226 allocAlpha(old_alpha);
227
228#endif // HAVE_XRENDER
229}
230
231void Transparent::render(int src_x, int src_y,
232 int dest_x, int dest_y,
233 unsigned int width, unsigned int height) const {
234#ifdef HAVE_XRENDER
235 if (m_src_pic == 0 || m_dest_pic == 0 ||
236 m_alpha_pic == 0 || !s_render)
237 return;
238 // render src+alpha to dest picture
239 XRenderComposite(FbTk::App::instance()->display(),
240 PictOpOver,
241 m_src_pic,
242 m_alpha_pic,
243 m_dest_pic,
244 src_x, src_y,
245 0, 0,
246 dest_x, dest_y,
247 width, height);
248
249#endif // HAVE_XRENDER
250}
251
252void Transparent::allocAlpha(unsigned char alpha) {
253#ifdef HAVE_XRENDER
254 if (m_source == 0 || !s_render)
255 return;
256 if (m_alpha_pic != 0)
257 freeAlpha();
258
259 m_alpha_pic = createAlphaPic(m_source, alpha);
260 m_alpha = alpha;
261#endif // HAVE_XRENDER
262}
263
264void Transparent::freeAlpha() {
265#ifdef HAVE_XRENDER
266 if (s_render && m_alpha_pic != 0)
267 XRenderFreePicture(FbTk::App::instance()->display(), m_alpha_pic);
268#endif // HAVE_XRENDER
269 m_alpha_pic = 0;
270 m_alpha = 255;
271}
272
273}; // end namespace FbTk
274
275
276