00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "FbPixmap.hh"
00025 #include "App.hh"
00026 #include "GContext.hh"
00027
00028 #include <X11/Xutil.h>
00029 #include <iostream>
00030 using namespace std;
00031
00032 namespace FbTk {
00033
00034 FbPixmap::FbPixmap():m_pm(0),
00035 m_width(0), m_height(0),
00036 m_depth(0) { }
00037
00038 FbPixmap::FbPixmap(const FbPixmap &the_copy):m_pm(0),
00039 m_width(0), m_height(0),
00040 m_depth(0) {
00041 copy(the_copy);
00042 }
00043
00044 FbPixmap::FbPixmap(Pixmap pm):m_pm(0),
00045 m_width(0), m_height(0),
00046 m_depth(0) {
00047 if (pm == 0)
00048 return;
00049
00050 (*this) = pm;
00051 }
00052
00053 FbPixmap::FbPixmap(const FbDrawable &src,
00054 unsigned int width, unsigned int height,
00055 int depth):m_pm(0),
00056 m_width(0), m_height(0),
00057 m_depth(0) {
00058
00059 create(src.drawable(), width, height, depth);
00060 }
00061
00062 FbPixmap::FbPixmap(Drawable src,
00063 unsigned int width, unsigned int height,
00064 int depth):m_pm(0),
00065 m_width(0), m_height(0),
00066 m_depth(0) {
00067
00068 create(src, width, height, depth);
00069 }
00070
00071 FbPixmap::~FbPixmap() {
00072 free();
00073 }
00074
00075 FbPixmap &FbPixmap::operator = (const FbPixmap &the_copy) {
00076 copy(the_copy);
00077 return *this;
00078 }
00079
00080 FbPixmap &FbPixmap::operator = (Pixmap pm) {
00081
00082 free();
00083
00084 if (pm == 0)
00085 return *this;
00086
00087
00088 Window root;
00089 int x, y;
00090 unsigned int border_width, bpp;
00091 XGetGeometry(FbTk::App::instance()->display(),
00092 pm,
00093 &root,
00094 &x, &y,
00095 &m_width, &m_height,
00096 &border_width,
00097 &bpp);
00098
00099 m_depth = bpp;
00100
00101 m_pm = pm;
00102
00103 return *this;
00104 }
00105
00106 void FbPixmap::copy(const FbPixmap &the_copy) {
00107
00108 bool create_new = false;
00109
00110 if (the_copy.width() != width() ||
00111 the_copy.height() != height() ||
00112 the_copy.depth() != depth() ||
00113 drawable() == 0)
00114 create_new = true;
00115
00116 if (create_new)
00117 free();
00118
00119 if (the_copy.drawable() != 0) {
00120 if (create_new) {
00121 create(the_copy.drawable(),
00122 the_copy.width(), the_copy.height(),
00123 the_copy.depth());
00124 }
00125
00126 if (drawable()) {
00127 GContext gc(drawable());
00128
00129 copyArea(the_copy.drawable(),
00130 gc.gc(),
00131 0, 0,
00132 0, 0,
00133 width(), height());
00134 }
00135 }
00136 }
00137
00138 void FbPixmap::copy(Pixmap pm) {
00139 free();
00140 if (pm == 0)
00141 return;
00142
00143
00144 Window root;
00145 int x, y;
00146 unsigned int border_width, bpp;
00147 unsigned int new_width, new_height;
00148
00149 XGetGeometry(FbTk::App::instance()->display(),
00150 pm,
00151 &root,
00152 &x, &y,
00153 &new_width, &new_height,
00154 &border_width,
00155 &bpp);
00156
00157 create(root, new_width, new_height, bpp);
00158
00159 Display *disp = FbTk::App::instance()->display();
00160
00161 GC gc = XCreateGC(disp, drawable(), 0, 0);
00162
00163 XCopyArea(disp, pm, drawable(), gc,
00164 0, 0,
00165 width(), height(),
00166 0, 0);
00167
00168 XFreeGC(disp, gc);
00169 }
00170
00171 void FbPixmap::rotate() {
00172
00173 Display *dpy = FbTk::App::instance()->display();
00174
00175
00176 XImage *src_image = XGetImage(dpy, drawable(),
00177 0, 0,
00178 width(), height(),
00179 ~0,
00180 ZPixmap);
00181
00182 FbPixmap new_pm(drawable(), height(), width(), depth());
00183
00184 GContext gc(drawable());
00185
00186
00187 for (int y = 0; y < static_cast<signed>(height()); ++y) {
00188 for (int x = 0; x < static_cast<signed>(width()); ++x) {
00189 gc.setForeground(XGetPixel(src_image, x, y));
00190
00191 XDrawPoint(dpy, new_pm.drawable(), gc.gc(), y, x);
00192 }
00193 }
00194
00195 XDestroyImage(src_image);
00196
00197 free();
00198
00199 m_width = new_pm.width();
00200 m_height = new_pm.height();
00201 m_depth = new_pm.depth();
00202 m_pm = new_pm.release();
00203 }
00204
00205 void FbPixmap::scale(unsigned int dest_width, unsigned int dest_height) {
00206 if (drawable() == 0 ||
00207 (dest_width == width() && dest_height == height()))
00208 return;
00209
00210 Display *dpy = FbTk::App::instance()->display();
00211
00212 XImage *src_image = XGetImage(dpy, drawable(),
00213 0, 0,
00214 width(), height(),
00215 ~0,
00216 ZPixmap);
00217 if (src_image == 0)
00218 return;
00219
00220
00221 FbPixmap new_pm(drawable(), dest_width, dest_height, depth());
00222
00223 GContext gc(drawable());
00224
00225 float zoom_x = static_cast<float>(width())/static_cast<float>(dest_width);
00226 float zoom_y = static_cast<float>(height())/static_cast<float>(dest_height);
00227
00228
00229 float src_x = 0, src_y = 0;
00230 for (int tx=0; tx < static_cast<signed>(dest_width); ++tx, src_x += zoom_x) {
00231 src_y = 0;
00232 for (int ty=0; ty < static_cast<signed>(dest_height); ++ty, src_y += zoom_y) {
00233 gc.setForeground(XGetPixel(src_image,
00234 static_cast<int>(src_x),
00235 static_cast<int>(src_y)));
00236 XDrawPoint(dpy, new_pm.drawable(), gc.gc(), tx, ty);
00237 }
00238 }
00239
00240 XDestroyImage(src_image);
00241
00242
00243 free();
00244
00245 m_width = new_pm.width();
00246 m_height = new_pm.height();
00247 m_depth = new_pm.depth();
00248 m_pm = new_pm.release();
00249 }
00250
00251 void FbPixmap::resize(unsigned int width, unsigned int height) {
00252 FbPixmap pm(drawable(), width, height, depth());
00253 *this = pm.release();
00254 }
00255
00256 Pixmap FbPixmap::release() {
00257 Pixmap ret = m_pm;
00258 m_pm = 0;
00259 m_width = 0;
00260 m_height = 0;
00261 m_depth = 0;
00262 return ret;
00263 }
00264
00265 void FbPixmap::free() {
00266 if (m_pm != 0) {
00267 XFreePixmap(FbTk::App::instance()->display(), m_pm);
00268 m_pm = 0;
00269 }
00270 m_width = 0;
00271 m_height = 0;
00272 m_depth = 0;
00273 }
00274
00275 void FbPixmap::create(Drawable src,
00276 unsigned int width, unsigned int height,
00277 int depth) {
00278 if (src == 0)
00279 return;
00280
00281 m_pm = XCreatePixmap(FbTk::App::instance()->display(),
00282 src, width, height, depth);
00283 if (m_pm == 0)
00284 return;
00285
00286 m_width = width;
00287 m_height = height;
00288 m_depth = depth;
00289 }
00290
00291 };