diff options
Diffstat (limited to 'src/FbTk/FbPixmap.cc')
-rw-r--r-- | src/FbTk/FbPixmap.cc | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/FbTk/FbPixmap.cc b/src/FbTk/FbPixmap.cc new file mode 100644 index 0000000..bbc8fcb --- /dev/null +++ b/src/FbTk/FbPixmap.cc | |||
@@ -0,0 +1,291 @@ | |||
1 | // FbPixmap.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: FbPixmap.cc,v 1.10 2004/01/11 12:48:46 fluxgen Exp $ | ||
23 | |||
24 | #include "FbPixmap.hh" | ||
25 | #include "App.hh" | ||
26 | #include "GContext.hh" | ||
27 | |||
28 | #include <X11/Xutil.h> | ||
29 | #include <iostream> | ||
30 | using namespace std; | ||
31 | |||
32 | namespace FbTk { | ||
33 | |||
34 | FbPixmap::FbPixmap():m_pm(0), | ||
35 | m_width(0), m_height(0), | ||
36 | m_depth(0) { } | ||
37 | |||
38 | FbPixmap::FbPixmap(const FbPixmap &the_copy):m_pm(0), | ||
39 | m_width(0), m_height(0), | ||
40 | m_depth(0) { | ||
41 | copy(the_copy); | ||
42 | } | ||
43 | |||
44 | FbPixmap::FbPixmap(Pixmap pm):m_pm(0), | ||
45 | m_width(0), m_height(0), | ||
46 | m_depth(0) { | ||
47 | if (pm == 0) | ||
48 | return; | ||
49 | // assign X pixmap to this | ||
50 | (*this) = pm; | ||
51 | } | ||
52 | |||
53 | FbPixmap::FbPixmap(const FbDrawable &src, | ||
54 | unsigned int width, unsigned int height, | ||
55 | int depth):m_pm(0), | ||
56 | m_width(0), m_height(0), | ||
57 | m_depth(0) { | ||
58 | |||
59 | create(src.drawable(), width, height, depth); | ||
60 | } | ||
61 | |||
62 | FbPixmap::FbPixmap(Drawable src, | ||
63 | unsigned int width, unsigned int height, | ||
64 | int depth):m_pm(0), | ||
65 | m_width(0), m_height(0), | ||
66 | m_depth(0) { | ||
67 | |||
68 | create(src, width, height, depth); | ||
69 | } | ||
70 | |||
71 | FbPixmap::~FbPixmap() { | ||
72 | free(); | ||
73 | } | ||
74 | |||
75 | FbPixmap &FbPixmap::operator = (const FbPixmap &the_copy) { | ||
76 | copy(the_copy); | ||
77 | return *this; | ||
78 | } | ||
79 | |||
80 | FbPixmap &FbPixmap::operator = (Pixmap pm) { | ||
81 | // free pixmap before we set new | ||
82 | free(); | ||
83 | |||
84 | if (pm == 0) | ||
85 | return *this; | ||
86 | |||
87 | // get width, height and depth for the pixmap | ||
88 | Window root; | ||
89 | int x, y; | ||
90 | unsigned int border_width, bpp; | ||
91 | XGetGeometry(FbTk::App::instance()->display(), | ||
92 | pm, | ||
93 | &root, | ||
94 | &x, &y, | ||
95 | &m_width, &m_height, | ||
96 | &border_width, | ||
97 | &bpp); | ||
98 | |||
99 | m_depth = bpp; | ||
100 | |||
101 | m_pm = pm; | ||
102 | |||
103 | return *this; | ||
104 | } | ||
105 | |||
106 | void FbPixmap::copy(const FbPixmap &the_copy) { | ||
107 | |||
108 | bool create_new = false; | ||
109 | |||
110 | if (the_copy.width() != width() || | ||
111 | the_copy.height() != height() || | ||
112 | the_copy.depth() != depth() || | ||
113 | drawable() == 0) | ||
114 | create_new = true; | ||
115 | |||
116 | if (create_new) | ||
117 | free(); | ||
118 | |||
119 | if (the_copy.drawable() != 0) { | ||
120 | if (create_new) { | ||
121 | create(the_copy.drawable(), | ||
122 | the_copy.width(), the_copy.height(), | ||
123 | the_copy.depth()); | ||
124 | } | ||
125 | |||
126 | if (drawable()) { | ||
127 | GContext gc(drawable()); | ||
128 | |||
129 | copyArea(the_copy.drawable(), | ||
130 | gc.gc(), | ||
131 | 0, 0, | ||
132 | 0, 0, | ||
133 | width(), height()); | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | void FbPixmap::copy(Pixmap pm) { | ||
139 | free(); | ||
140 | if (pm == 0) | ||
141 | return; | ||
142 | |||
143 | // get width, height and depth for the pixmap | ||
144 | Window root; | ||
145 | int x, y; | ||
146 | unsigned int border_width, bpp; | ||
147 | unsigned int new_width, new_height; | ||
148 | |||
149 | XGetGeometry(FbTk::App::instance()->display(), | ||
150 | pm, | ||
151 | &root, | ||
152 | &x, &y, | ||
153 | &new_width, &new_height, | ||
154 | &border_width, | ||
155 | &bpp); | ||
156 | // create new pixmap and copy area | ||
157 | create(root, new_width, new_height, bpp); | ||
158 | |||
159 | Display *disp = FbTk::App::instance()->display(); | ||
160 | |||
161 | GC gc = XCreateGC(disp, drawable(), 0, 0); | ||
162 | |||
163 | XCopyArea(disp, pm, drawable(), gc, | ||
164 | 0, 0, | ||
165 | width(), height(), | ||
166 | 0, 0); | ||
167 | |||
168 | XFreeGC(disp, gc); | ||
169 | } | ||
170 | |||
171 | void FbPixmap::rotate() { | ||
172 | |||
173 | Display *dpy = FbTk::App::instance()->display(); | ||
174 | |||
175 | // make an image copy | ||
176 | XImage *src_image = XGetImage(dpy, drawable(), | ||
177 | 0, 0, // pos | ||
178 | width(), height(), // size | ||
179 | ~0, // plane mask | ||
180 | ZPixmap); // format | ||
181 | // reverse height/width for new pixmap | ||
182 | FbPixmap new_pm(drawable(), height(), width(), depth()); | ||
183 | |||
184 | GContext gc(drawable()); | ||
185 | |||
186 | // copy new area | ||
187 | for (int y = 0; y < static_cast<signed>(height()); ++y) { | ||
188 | for (int x = 0; x < static_cast<signed>(width()); ++x) { | ||
189 | gc.setForeground(XGetPixel(src_image, x, y)); | ||
190 | // revers coordinates | ||
191 | XDrawPoint(dpy, new_pm.drawable(), gc.gc(), y, x); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | XDestroyImage(src_image); | ||
196 | // free old pixmap and set new from new_pm | ||
197 | free(); | ||
198 | |||
199 | m_width = new_pm.width(); | ||
200 | m_height = new_pm.height(); | ||
201 | m_depth = new_pm.depth(); | ||
202 | m_pm = new_pm.release(); | ||
203 | } | ||
204 | |||
205 | void FbPixmap::scale(unsigned int dest_width, unsigned int dest_height) { | ||
206 | if (drawable() == 0 || | ||
207 | (dest_width == width() && dest_height == height())) | ||
208 | return; | ||
209 | |||
210 | Display *dpy = FbTk::App::instance()->display(); | ||
211 | |||
212 | XImage *src_image = XGetImage(dpy, drawable(), | ||
213 | 0, 0, // pos | ||
214 | width(), height(), // size | ||
215 | ~0, // plane mask | ||
216 | ZPixmap); // format | ||
217 | if (src_image == 0) | ||
218 | return; | ||
219 | |||
220 | // create new pixmap with dest size | ||
221 | FbPixmap new_pm(drawable(), dest_width, dest_height, depth()); | ||
222 | |||
223 | GContext gc(drawable()); | ||
224 | // calc zoom | ||
225 | float zoom_x = static_cast<float>(width())/static_cast<float>(dest_width); | ||
226 | float zoom_y = static_cast<float>(height())/static_cast<float>(dest_height); | ||
227 | |||
228 | // start scaling | ||
229 | float src_x = 0, src_y = 0; | ||
230 | for (int tx=0; tx < static_cast<signed>(dest_width); ++tx, src_x += zoom_x) { | ||
231 | src_y = 0; | ||
232 | for (int ty=0; ty < static_cast<signed>(dest_height); ++ty, src_y += zoom_y) { | ||
233 | gc.setForeground(XGetPixel(src_image, | ||
234 | static_cast<int>(src_x), | ||
235 | static_cast<int>(src_y))); | ||
236 | XDrawPoint(dpy, new_pm.drawable(), gc.gc(), tx, ty); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | XDestroyImage(src_image); | ||
241 | |||
242 | // free old pixmap and set new from new_pm | ||
243 | free(); | ||
244 | |||
245 | m_width = new_pm.width(); | ||
246 | m_height = new_pm.height(); | ||
247 | m_depth = new_pm.depth(); | ||
248 | m_pm = new_pm.release(); | ||
249 | } | ||
250 | |||
251 | void FbPixmap::resize(unsigned int width, unsigned int height) { | ||
252 | FbPixmap pm(drawable(), width, height, depth()); | ||
253 | *this = pm.release(); | ||
254 | } | ||
255 | |||
256 | Pixmap FbPixmap::release() { | ||
257 | Pixmap ret = m_pm; | ||
258 | m_pm = 0; | ||
259 | m_width = 0; | ||
260 | m_height = 0; | ||
261 | m_depth = 0; | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | void FbPixmap::free() { | ||
266 | if (m_pm != 0) { | ||
267 | XFreePixmap(FbTk::App::instance()->display(), m_pm); | ||
268 | m_pm = 0; | ||
269 | } | ||
270 | m_width = 0; | ||
271 | m_height = 0; | ||
272 | m_depth = 0; | ||
273 | } | ||
274 | |||
275 | void FbPixmap::create(Drawable src, | ||
276 | unsigned int width, unsigned int height, | ||
277 | int depth) { | ||
278 | if (src == 0) | ||
279 | return; | ||
280 | |||
281 | m_pm = XCreatePixmap(FbTk::App::instance()->display(), | ||
282 | src, width, height, depth); | ||
283 | if (m_pm == 0) | ||
284 | return; | ||
285 | |||
286 | m_width = width; | ||
287 | m_height = height; | ||
288 | m_depth = depth; | ||
289 | } | ||
290 | |||
291 | }; // end namespace FbTk | ||