00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "mxsurface.h"
00018 #include "mx_types.h"
00019 #include "mxinterface.h"
00020 #include<sstream>
00021 #ifdef HAVE_CONFIG_H
00022 #include<config.h>
00023 #endif
00024 #include<cmath>
00025
00026
00027
00028 #if (HAVE_SDL_STRETCH == 1)
00029 extern "C" {
00030 #include<SDL_stretch.h>
00031 }
00032 #endif
00033
00034
00035 namespace mx
00036 {
00037
00038
00039 int stretchX(int cur_w ,int x, int nw) {
00040 float xp = (float)x * (float)cur_w / (float)nw;
00041 return (int)xp;
00042 }
00043
00044 int stretchY(int cur_h, int y, int nh) {
00045 float yp = (float)y * (float)cur_h / (float)nh;
00046 return (int)yp;
00047 }
00048
00049
00050
00051
00052 mxSurface::mxSurface(SDL_Surface *surface) : is_locked(false)
00053 {
00054 p_buffer = 0;
00055
00056 object_surface = surface;
00057 noZero(false);
00058 }
00059
00060 mxSurface::mxSurface(const mxSurface &c) : is_locked(false)
00061 {
00062
00063 p_buffer = 0;
00064 clean_up();
00065 object_surface = c.object_surface;
00066 noZero(false);
00067 }
00068
00069
00070 mxSurface::~mxSurface()
00071 {
00072 clean_up();
00073 }
00074
00075
00076 mxSurface &mxSurface::operator=(const mxSurface &c)
00077 {
00078 clean_up();
00079 object_surface = c.object_surface;
00080 return *this;
00081 }
00082
00083
00084 void mxSurface::setCopySurface(SDL_Surface *surface)
00085 {
00086 clean_up();
00087 createSurface(surface->w, surface->h);
00088 copySurface(surface, 0, 0);
00089 }
00090
00091
00092
00093 mxSurface &mxSurface::operator=(SDL_Surface *surface)
00094 {
00095
00096 if(surface == 0) throw mx::mxException<std::string>("libmx: error operator= on mxsurface: surface is null");
00097
00098
00099 clean_up();
00100 object_surface = surface;
00101 return *this;
00102 }
00103
00104 SDL_Surface *mxSurface::getSurface() const
00105 {
00106 return object_surface;
00107 }
00108
00109 bool mxSurface::createSurface( Size &s )
00110 {
00111 return createSurface(s.width, s.height);
00112 }
00113
00114 bool mxSurface::createSurface(int w, int h)
00115 {
00116
00117 static int rmask, gmask, bmask, amask;
00118
00119 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00120 rmask = 0xff000000;
00121 gmask = 0x00ff0000;
00122 bmask = 0x0000ff00;
00123 amask = 0x000000ff;
00124 #else
00125 rmask = 0x000000ff;
00126 gmask = 0x0000ff00;
00127 bmask = 0x00ff0000;
00128 amask = 0xff000000;
00129 #endif
00130
00131
00132 clean_up();
00133
00134 object_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,w,h,32, rmask, gmask, bmask, amask);
00135
00136 std::cout << "libmx: created surface @" << w << "/" << h << "\n";
00137
00138 if(object_surface)
00139 return true;
00140
00141 throw mx::mxException<std::string>("libmx: Error surface creation failed\n");
00142
00143 return false;
00144 }
00145
00146 bool mxSurface::copySurface(const mxSurface &c, SDL_Rect *source, SDL_Rect *dest)
00147 {
00148
00149 if(object_surface == 0) {
00150
00151 throw mx::mxException<std::string>("libmx: Error cannot copy null surface\n");
00152
00153 return false;
00154 }
00155
00156 SDL_BlitSurface(c.object_surface, source, object_surface, dest);
00157 return true;
00158
00159 }
00160
00161 bool mxSurface::copySurfaceColorKey(const mxSurface &c, SDL_Rect *source, SDL_Rect *dest, SDL_Color color_key)
00162 {
00163
00164 if(object_surface == 0) return false;
00165
00166 SDL_SetColorKey(c.object_surface, SDL_SRCCOLORKEY, SDL_MapRGB(c.object_surface->format, color_key.r, color_key.g, color_key.b));
00167 copySurface(c, source, dest);
00168
00169 return true;
00170
00171 }
00172
00173 void mxSurface::cleanSurface()
00174 {
00175 clean_up();
00176 }
00177
00178 void mxSurface::clean_up()
00179 {
00180
00181 if(p_buffer != 0)
00182 {
00183
00184 int i;
00185 for(i = 0; i < getSurface()->w; i++)
00186 {
00187
00188 delete [] p_buffer[i];
00189 }
00190
00191 delete [] p_buffer;
00192 p_buffer = 0;
00193 }
00194
00195
00196
00197 if(object_surface && protected_noremove == false)
00198 {
00199
00200 cout << "libmx: removing surface: " << (unsigned long) object_surface << " ";
00201 SDL_FreeSurface(object_surface);
00202 object_surface = 0;
00203 cout << "removed\n";
00204 }
00205
00206
00207 }
00208
00209 void mxSurface::Flip() const
00210 {
00211 SDL_Flip(object_surface);
00212 }
00213
00214 mxSurface::operator SDL_Surface *()
00215 {
00216 return object_surface;
00217 }
00218
00219 mxSurface::operator SDL_PixelFormat *()
00220 {
00221 if(object_surface == 0) throw mx::mxException<std::string>( " error null surface trying to use pixel format for implicit conversion");
00222
00223 return object_surface->format;
00224
00225 }
00226
00227
00228 void mxSurface::noZero(bool zero)
00229 {
00230 protected_noremove = zero;
00231 }
00232
00233
00234
00235
00236
00237 mxPoint **mxSurface::buildResizeTable(int nw, int nh, int w, int h, mxPoint **buffer)
00238 {
00239
00240 int i,z;
00241
00242 std::cout << "building resize table\n";
00243
00244 buffer = new mxPoint*[w];
00245
00246 for(i = 0; i < w; i++)
00247 {
00248
00249 buffer[i] = new mxPoint[ h ];
00250
00251 }
00252
00253
00254 for(i = 0; i < w; i++)
00255 {
00256
00257 for(z = 0; z < h; z++)
00258 {
00259 mxPoint *ptr = &buffer[i][z];
00260 ptr->x = stretchX(nw, i, w);
00261 ptr->y = stretchY(nh, z, h);
00262
00263 }
00264
00265 }
00266
00267 return buffer;
00268
00269 }
00270
00271
00272 bool mxSurface::copyResizeSurface(const mxSurface &c)
00273 {
00274
00275 #if (HAVE_SDL_STRETCH == 0)
00276
00277 if(p_buffer == 0)
00278 {
00279 p_buffer = buildResizeTable(c.getSurface()->w, c.getSurface()->h, getSurface()->w, getSurface()->h, p_buffer);
00280 }
00281
00282 mx::mxPainter pobj1(c), pobj2(*this);
00283
00284 register int i,z;
00285
00286 pobj1.lock(); pobj2.lock();
00287
00288 for(i = 0; i < object_surface->w; i++)
00289 {
00290
00291 for(z = 0; z < object_surface->h; z++)
00292 {
00293
00294 static Color color;
00295 mxPoint *cur_pixel = &p_buffer[i][z];
00296 color = pobj1.getpixel(cur_pixel->x, cur_pixel->y);
00297 pobj2.setpixel(i,z, color);
00298 }
00299 }
00300
00301 pobj1.unlock(); pobj2.unlock();
00302
00303 #else
00304 SDL_StretchSurfaceRect( c.getSurface(), 0, getSurface(), 0);
00305 #endif
00306
00307 return true;
00308 }
00309
00310 bool mxSurface::copyResizeSurface(const mxSurface &c, SDL_Rect *src, SDL_Rect *dst) {
00311
00312 #if (HAVE_SDL_STRETCH == 0)
00313 #warning "you should have sdl-stretch compiled for this function to work\n"
00314
00315 return false;
00316 #else
00317 SDL_StretchSurfaceRect( c.getSurface(), src, getSurface(), dst );
00318 #endif
00319
00320 return true;
00321 }
00322
00323 void mxSurface::updateRect(unsigned int x, unsigned int y, unsigned int w, unsigned int h) const
00324 {
00325 SDL_UpdateRect(object_surface, x, y, w, h);
00326 }
00327
00328 void mxSurface::Clear() const
00329 {
00330 SDL_FillRect(object_surface, 0, SDL_MapRGB(object_surface->format, 0, 0, 0));
00331 }
00332
00333 void mxSurface::lockSurface()
00334 {
00335
00336 if(object_surface == 0) throw mx::mxException<std::string>(" null surface passed to lock operation\n ");
00337
00338
00339 if(SDL_MUSTLOCK(object_surface))
00340 {
00341 SDL_LockSurface(object_surface);
00342 }
00343
00344 is_locked = true;
00345
00346 }
00347
00348 const bool mxSurface::isLocked() const
00349 {
00350 return (is_locked);
00351 }
00352
00353 void mxSurface::unlockSurface()
00354 {
00355 if(object_surface == 0) throw mx::mxException<std::string>(" null surface passed to unlock operation\n ");
00356
00357 if(SDL_MUSTLOCK(object_surface))
00358 {
00359 SDL_UnlockSurface(object_surface);
00360 }
00361 is_locked = false;
00362 }
00363
00364
00365 void *mxSurface::rawData()
00366 {
00367 if(is_locked == true) return object_surface->pixels;
00368 return 0;
00369 }
00370
00371
00372 const bool mxSurface::loadBitmapFromMemory(void *memory)
00373 {
00374 SDL_RWops *opz;
00375 opz = SDL_RWFromMem(memory, sizeof(memory));
00376 if(opz == 0) throw mx::mxException<std::string>(" Error loading memory chunk to bitmap ");
00377 object_surface = SDL_LoadBMP_RW(opz, 1);
00378 SDL_FreeRW(opz);
00379 return true;
00380 }
00381
00382
00383
00384 unsigned int &mxSurface::operator[](unsigned int pos)
00385 {
00386 if(is_locked == false) throw mx::mxException<std::string>( " Error trying to manipulate pixels on surface which is not locked ");
00387 void *r = rawData();
00388 unsigned int *ptr = (unsigned int *)r;
00389 return ptr[pos];
00390 }
00391
00392
00393
00394 const int mxSurface::width() const
00395 {
00396 if(object_surface == 0) return 0;
00397 return object_surface->w;
00398 }
00399
00400 const int mxSurface::height() const
00401 {
00402 if(object_surface == 0) return 0;
00403 return object_surface->h;
00404 }
00405
00406 const int mxSurface::pitch() const
00407 {
00408 if(object_surface == 0) return 0;
00409 return object_surface->pitch;
00410 }
00411
00412 Size mxSurface::size()
00413 {
00414 return Size(width(), height());
00415 }
00416
00417
00418 mxSurface *mxSurface::copySurface()
00419 {
00420
00421 mxSurface *surf = 0;
00422
00423 try
00424 {
00425
00426 surf = new mxSurface();
00427 surf->createSurface(width(), height());
00428 surf->copySurface(*this, 0, 0);
00429 return surf;
00430
00431 }
00432 catch(...)
00433 {
00434 delete surf;
00435 }
00436
00437 return 0;
00438 }
00439
00440 }
00441