1 /* 2 * SDmm - a C++ wrapper for SDL and related libraries 3 * Copyright � 2001 David Hedbor <david@hedbor.org> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 * 19 */ 20 21 22 #ifndef SDLMM_BASESURFACE_H 23 #define SDLMM_BASESURFACE_H 24 #include "sdlmm_config.h" 25 #include "sdlmm_spoint.h" 26 #include "sdlmm_srect.h" 27 #include "sdlmm_color.h" 28 #include "sdlmm_pixelformat.h" 29 #include <string> 30 31 namespace SDLmm { 32 //! An abstract base class for graphical surfaces 33 /*! 34 35 Surfaces represent areas of "graphical" memory, memory that can be 36 drawn to. The video framebuffer is returned as a VideoSurface by 37 SetVideoMode() and GetVideoSurface(). Ordinary (non-framebuffer 38 surfaces) are represented by a Surface. The clipping rectangle 39 returned by clip_rect() can be set with SetClipRect() method. 40 41 \author David Hedbor <david@hedbor.org> 42 */ 43 class DECLSPEC BaseSurface { 44 45 protected: 46 //! The actual SDL_Surface allocated for this BaseSurface. 47 SDL_Surface *me; SetSurface(SDL_Surface * surface)48 virtual void SetSurface(SDL_Surface *surface) { 49 if(me) { 50 SDL_FreeSurface(me); 51 } 52 me = surface; 53 } 54 55 //! Constructor from an SDL_Surface* 56 /*! 57 This creates a new BaseSurface object from an existing 58 SDL_Surface. Note that ownership of the SDL_Surface is passed 59 on to the BaseSurface. It's very important not to free the original 60 surface since that will cause a problem when the object is 61 destructed (SDL_Surface storage freed twice). Use with caution. 62 */ BaseSurface(SDL_Surface * surface)63 explicit BaseSurface(SDL_Surface *surface) 64 : me(surface) { 65 } 66 BaseSurface(const BaseSurface & other)67 BaseSurface(const BaseSurface& other) 68 : me(other.me) { 69 } 70 71 BaseSurface &operator=(const BaseSurface& other) { 72 if(this != &other) 73 SetSurface(other.me); 74 return *this; 75 } 76 77 public: 78 79 //! The destructor. ~BaseSurface()80 virtual ~BaseSurface() { 81 if(me) { 82 SDL_FreeSurface(me); 83 } 84 } 85 GetSurface()86 SDL_Surface *GetSurface() { 87 ASSERT(me); 88 return me; 89 } 90 GetSurface()91 const SDL_Surface *GetSurface() const { 92 ASSERT(me); 93 return me; 94 } 95 96 //! Lock the surface to allow direct access to the surface pixels. 97 //! Returns true if lock succeeded, false otherwise. 98 bool Lock(); 99 100 //! Unlock the surface. 101 void Unlock(); 102 103 //! \name Informational methods 104 //@{ 105 //! Returns true if this surface is initialized, false otherwise. 106 /*! \warning Using an uninitialzied surface can cause many problems. */ valid()107 bool valid() const { return me != 0; } 108 109 //! Returns the surface flags. flags()110 Uint32 flags() const { return GetSurface()->flags; } 111 112 //! Returns the pixel format. GetPixelFormat()113 const PixelFormat GetPixelFormat() const { return PixelFormat(GetSurface()->format); } GetPixelFormat()114 PixelFormat GetPixelFormat() { return PixelFormat(GetSurface()->format); } 115 116 //! Returns the width of the surface. w()117 int w() const { return GetSurface()->w; } 118 119 //! Returns the height of the surface. h()120 int h() const { return GetSurface()->h; } 121 122 //! Returns the scanline length in bytes pitch()123 Uint16 pitch() const { return GetSurface()->pitch; } 124 125 //! Returns the surface clip rectangle clip_rect()126 const SRect clip_rect() const { return SRect(GetSurface()->clip_rect); } 127 128 //! Returns the pixel data, which can be used for low-level manipulation. 129 /*! 130 \warning You can only modify this surface when the surface is locked. 131 */ pixels()132 void *pixels() { return GetSurface()->pixels; } 133 134 //! Returns the pixel data, which can be used for low-level manipulation. 135 /*! 136 \warning You can only modify this surface when the surface is locked. 137 */ pixels()138 const void *pixels() const { return GetSurface()->pixels; } 139 140 //! Returns the hardware-specific surface info. hwdata()141 struct private_hwdata *hwdata() const { return GetSurface()->hwdata; } 142 //@} 143 144 //! Set the pixel to the color 145 /*! 146 \warning You can only use this function when the surface is locked. 147 */ 148 void SetPixel(int x, int y, Color color); 149 150 //! Set the pixel to the color 151 /*! 152 \warning You can only use this function when the surface is locked 153 and when the bytes per pixel is 1. 154 */ 155 void SetPixel1(int x, int y, Color color); 156 157 //! Set the pixel to the color 158 /*! 159 \warning You can only use this function when the surface is locked 160 and when the bytes per pixel is 2. 161 */ 162 void SetPixel2(int x, int y, Color color); 163 164 //! Set the pixel to the color 165 /*! 166 \warning You can only use this function when the surface is locked 167 and when the bytes per pixel is 3. 168 */ 169 void SetPixel3(int x, int y, Color color); 170 171 //! Set the pixel to the color 172 /*! 173 \warning You can only use this function when the surface is locked 174 and when the bytes per pixel is 4. 175 */ 176 void SetPixel4(int x, int y, Color color); 177 178 //! Set the pixel to the color 179 /*! 180 \warning You can only use this function when the surface is locked. 181 */ SetPixel(const SRect & point,Color color)182 void SetPixel(const SRect& point, Color color) { SetPixel(point.x, point.y, color); } 183 184 //! Get the color of the pixel 185 /*! 186 \warning You can only use this function when the surface is locked. 187 */ 188 Color GetPixel(int x, int y) const; 189 190 //! Get the color of the pixel 191 /*! 192 \warning You can only use this function when the surface is locked. 193 */ GetPixel(const SRect & point)194 Color GetPixel(const SRect& point) const { return GetPixel(point.x, point.y); } 195 196 //! Sets the color key (transparent pixel) in a blittable surface 197 //! and enables or disables RLE blit acceleration. 198 /*! 199 RLE acceleration can substantially speed up blitting of images 200 with large horizontal runs of transparent pixels (i.e., pixels 201 that match the \a key value). The key must be of the same pixel 202 format as the surface, MapRGB() is often useful for obtaining an 203 acceptable value. 204 205 \returns Returns true for success, false if there was an error. 206 \param flag If */ 207 bool SetColorKey(Uint32 flag, Color key); 208 209 //! Adjust the alpha properties of this surface 210 /*! 211 212 SetAlpha is used for setting the surface alpha value and / or 213 enabling and disabling alpha blending. 214 215 \param flag used to specify whether alpha blending should be 216 used (SDL_SRCALPHA) and whether the surface should use RLE 217 acceleration for blitting (SDL_RLEACCEL). \a flag can be an OR'd 218 combination of these two options, one of these options or 0. If 219 SDL_SRCALPHA is not passed as a flag then all alpha information 220 is ignored when blitting the surface. 221 222 \param alpha the per-surface alpha value; a surface need not 223 have an alpha channel to use per-surface alpha and blitting can 224 still be accelerated with SDL_RLEACCEL. 225 226 \note The per-surface alpha value of 128 is considered a special 227 case and is optimised, so it's much faster than other 228 per-surface values. 229 230 \returns true for success or false if there was an error. 231 */ 232 bool SetAlpha(Uint32 flag, Uint8 alpha); 233 234 //! \name Clipping Methods 235 //@{ 236 //! Resets the clipping rectangle for the surface. 237 /*! 238 This functions resets the clipping to the full size of the surface. 239 \sa GetClipRect, SetClipRect, Blit 240 */ 241 void ResetClipRect(); 242 243 //! Sets the clipping rectangle for the surface. 244 /*! 245 Sets the clipping rectangle for a surface. When this surface is 246 the destination of a blit, only the area within the clip 247 rectangle will be drawn into. 248 249 \param rect The rectangle pointed to by rect will be clipped to 250 the edges of the surface so that the clip rectangle for a 251 surface can never fall outside the edges of the surface. 252 253 \sa GetClipRect, ResetClipRect, Blit 254 */ 255 void SetClipRect(const SDL_Rect& rect); 256 257 //! Gets the clipping rectangle for the surface. 258 /*! 259 Gets the clipping rectangle for a surface. When this surface is 260 the destination of a blit, only the area within the clip 261 rectangle is drawn into. 262 263 \param rect reference to a rectangle which will be filled with 264 the clipping rectangle of this surface. 265 \sa SetClipRect, ResetClipRect, Blit 266 */ 267 void GetClipRect(SDL_Rect& rect) const; 268 //@} 269 270 //! \name Blitting / Filling 271 //@{ 272 //! Fast blit the entire source surface onto this surface. 273 /*! 274 The source surface will be blitted to this surface. If the 275 source area is larger than the destination, clipping will 276 occur. No scaling will be performed. Blitting should not be used 277 on a locked surface. The entire surface will be copied to this 278 surface using this function. 279 280 \return If the blit is successful, it returns 0, otherwise it 281 returns -1. If either of the surfaces were in video memory, 282 and the blit returns -2, the video memory was lost. It should 283 be reloaded with artwork and re-blitted. 284 285 \param src the surface to blit from. 286 */ 287 int Blit(const BaseSurface& src); 288 289 //! Fast blit the entire source surface onto this surface at the 290 //! specified coordinates. 291 /*! 292 The source surface will be blitted to this surface. If the 293 source area is larger than the destination, clipping will 294 occur. No scaling will be performed. Blitting should not be used 295 on a locked surface. The entire surface will be copied to this 296 surface using this function. The final blit rectangle is saved 297 in \a dstrect after all clipping is performed. 298 299 \return If the blit is successful, it returns 0, otherwise it 300 returns -1. If either of the surfaces were in video memory, 301 and the blit returns -2, the video memory was lost. It should 302 be reloaded with artwork and re-blitted. 303 304 \param src the surface to blit from. 305 \param dstrect the destination coordinates. Only the position 306 is used (i.e width and height are ignored). The width and height are 307 set upon returning. 308 */ 309 int Blit(const BaseSurface& src, SDL_Rect& dstrect); 310 311 //! Fast blit the entire source surface onto this surface at the 312 //! specified coordinates. 313 /*! 314 The source surface will be blitted to this surface. If the 315 source area is larger than the destination, clipping will 316 occur. No scaling will be performed. Blitting should not be used 317 on a locked surface. The entire surface will be copied to this 318 surface using this function. The final blit rectangle is saved 319 in \a dstrect after all clipping is performed. 320 321 \return If the blit is successful, it returns 0, otherwise it 322 returns -1. If either of the surfaces were in video memory, 323 and the blit returns -2, the video memory was lost. It should 324 be reloaded with artwork and re-blitted. 325 326 \param src the surface to blit from. 327 \param dstpoint the destination coordinates. 328 \param dstrect the final position and size is set upon returning. 329 */ Blit(const BaseSurface & src,const SPoint & dstpoint,SDL_Rect & dstrect)330 int Blit(const BaseSurface& src, const SPoint& dstpoint, SDL_Rect& dstrect) { dstrect.x = dstpoint.x; dstrect.y = dstpoint.y; return Blit(src, dstrect); } 331 332 //! Fast blit the entire source surface onto this surface at the 333 //! specified coordinates. 334 /*! 335 The source surface will be blitted to this surface. If the 336 source area is larger than the destination, clipping will 337 occur. No scaling will be performed. Blitting should not be used 338 on a locked surface. The entire surface will be copied to this 339 surface using this function. 340 341 \return If the blit is successful, it returns 0, otherwise it 342 returns -1. If either of the surfaces were in video memory, 343 and the blit returns -2, the video memory was lost. It should 344 be reloaded with artwork and re-blitted. 345 346 \param src the surface to blit from. 347 \param dstpoint the destination coordinates. 348 */ 349 int Blit(const BaseSurface& src, const SPoint& dstpoint); 350 351 //! Fast blit the specified area part of the source surface onto 352 //! this surface at the specified coordinates. 353 /*! 354 The choosen rectangle of the source surface will be blitted to 355 this surface. If the source area is larger than the destination, 356 clipping will occur. No scaling will be performed. Blitting 357 should not be used on a locked surface. The entire surface will 358 be copied to this surface using this function. The final blit 359 rectangle is saved in \a dstrect after all clipping is performed 360 (\a srcrect is not modified). 361 362 \return If the blit is successful, it returns 0, otherwise it 363 returns -1. If either of the surfaces were in video memory, 364 and the blit returns -2, the video memory was lost. It should 365 be reloaded with artwork and re-blitted. 366 367 \param src the surface to blit from. 368 \param srcrect the rectangular area to copy from the source 369 surface. 370 \param dstrect the destination coordinates. Only the position 371 is used (i.e width and height are ignored). The width and height are 372 set upon returning. 373 */ 374 int Blit(const BaseSurface& src, const SDL_Rect& srcrect, SDL_Rect& dstrect); 375 376 //! Fast blit the specified area part of the source surface onto 377 //! this surface at the specified coordinates. 378 /*! 379 The choosen rectangle of the source surface will be blitted to 380 this surface. If the source area is larger than the destination, 381 clipping will occur. No scaling will be performed. Blitting 382 should not be used on a locked surface. The entire surface will 383 be copied to this surface using this function. The final blit 384 rectangle is saved in \a dstrect after all clipping is performed 385 (\a srcrect is not modified). 386 387 \return If the blit is successful, it returns 0, otherwise it 388 returns -1. If either of the surfaces were in video memory, 389 and the blit returns -2, the video memory was lost. It should 390 be reloaded with artwork and re-blitted. 391 392 \param src the surface to blit from. 393 \param srcrect the rectangular area to copy from the source 394 surface. 395 \param dstpoint the destination coordinates. 396 \param dstrect the final position and size is set upon returning. 397 */ Blit(const BaseSurface & src,const SDL_Rect & srcrect,const SPoint & dstpoint,SDL_Rect & dstrect)398 int Blit(const BaseSurface& src, const SDL_Rect& srcrect, const SPoint& dstpoint, SDL_Rect& dstrect) { dstrect.x = dstpoint.x; dstrect.y = dstpoint.y; return Blit(src, srcrect, dstrect); } 399 400 //! Fast blit the specified area part of the source surface onto 401 //! this surface at the specified coordinates. 402 /*! 403 The choosen rectangle of the source surface will be blitted to 404 this surface. If the source area is larger than the destination, 405 clipping will occur. No scaling will be performed. Blitting 406 should not be used on a locked surface. The entire surface will 407 be copied to this surface using this function. 408 409 \return If the blit is successful, it returns 0, otherwise it 410 returns -1. If either of the surfaces were in video memory, 411 and the blit returns -2, the video memory was lost. It should 412 be reloaded with artwork and re-blitted. 413 414 \param src the surface to blit from. 415 \param srcrect the rectangular area to copy from the source 416 surface. 417 \param dstpoint the destination coordinates. 418 */ 419 int Blit(const BaseSurface& src, const SDL_Rect& srcrect, const SPoint& dstpoint); 420 421 //! Fast fill the surface with the specified color 422 /*! 423 If a clipping rectangle has been set using SetClipRect(), only the 424 area within that rectangle will be filled. 425 \returns Returns true for success, false if there was an error. 426 \param color the color to fill with, generated by MapRGB() or MapRGBA(). 427 */ 428 bool Fill(Color color); 429 430 //! Fast fill the surface with the specified color 431 /*! 432 If a clipping rectangle has been set using SetClipRect(), only the 433 area within that rectangle will be filled. 434 \returns Returns true for success, false if there was an error. 435 \param r, g, b the red, green and blue color values. 436 */ Fill(Uint8 r,Uint8 g,Uint8 b)437 bool Fill(Uint8 r, Uint8 g, Uint8 b) { return Fill(GetPixelFormat().MapRGB(r, g, b)); } 438 439 //! Fast fill the surface with the specified color 440 /*! 441 If a clipping rectangle has been set using SetClipRect(), only the 442 area within that rectangle will be filled. 443 \returns Returns true for success, false if there was an error. 444 \param r, g, b the red, green and blue color values. 445 \param a the alpha value 446 */ Fill(Uint8 r,Uint8 g,Uint8 b,Uint8 a)447 bool Fill(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { return Fill(GetPixelFormat().MapRGBA(r, g, b, a)); } 448 449 //! Performs a fast fill of the given rectangle with the specified color 450 /*! 451 If a clipping rectangle has been set using SetClipRect(), the area 452 filled will be the intersection of the clipping rectangle and 453 \a dstrect. 454 \returns Returns true for success, false if there was an error. 455 \param dstrect the rectangle to fill, upon returning it contains the 456 clipped rectangle that was actually filled. 457 \param color the color to fill with, generated by MapRGB() or MapRGBA(). 458 */ 459 bool FillRect(SDL_Rect& dstrect, Color color); 460 461 //! Performs a fast fill of the given rectangle with the specified color 462 /*! 463 If a clipping rectangle has been set using SetClipRect(), the area 464 filled will be the intersection of the clipping rectangle and 465 \a dstrect. 466 \returns Returns true for success, false if there was an error. 467 \param dstrect the rectangle to fill, upon returning it contains the 468 clipped rectangle that was actually filled. 469 \param r, g, b the red, green and blue color values. 470 */ FillRect(SDL_Rect & dstrect,Uint8 r,Uint8 g,Uint8 b)471 bool FillRect(SDL_Rect& dstrect, Uint8 r, Uint8 g, Uint8 b) { return FillRect(dstrect, GetPixelFormat().MapRGB(r, g, b)); } 472 473 //! Performs a fast fill of the given rectangle with the specified color 474 /*! 475 If a clipping rectangle has been set using SetClipRect(), the area 476 filled will be the intersection of the clipping rectangle and 477 \a dstrect. 478 \returns Returns true for success, false if there was an error. 479 \param dstrect the rectangle to fill, upon returning it contains the 480 clipped rectangle that was actually filled. 481 \param r, g, b the red, green and blue color values. 482 \param a the alpha value 483 */ FillRect(SDL_Rect & dstrect,Uint8 r,Uint8 g,Uint8 b,Uint8 a)484 bool FillRect(SDL_Rect& dstrect, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { return FillRect(dstrect, GetPixelFormat().MapRGBA(r, g, b, a)); } 485 486 //@} 487 488 //! Convert the surface to the display format. 489 /*! 490 This function converts the surface to the pixel format and 491 colors of the video framebuffer, making it suitable for fast 492 blitting onto the display surface. 493 494 If you want to take advantage of hardware colorkey or alpha blit 495 acceleration, you should set the colorkey and alpha value before 496 calling this function. 497 498 \returns The functions returns true if the conversion 499 succeeded or false otherwise. If the conversion failed, the 500 BaseSurface object will not have changed. 501 502 \note Please note that this function doesn't return a new, 503 modified object like the SDL_DisplayFormat() function does. Thus 504 there is no need to manually free the old surface. 505 506 \sa SetDisplayFormatAlpha(), SetAlpha(), SetColorKey() 507 */ 508 virtual bool SetDisplayFormat() = 0; 509 510 //! Convert the surface to the display format. 511 /*! 512 This function converts the surface to the pixel format and 513 colors of the video framebuffer plus an alpha channel, making it 514 suitable for fast blitting onto the display surface. 515 516 If you want to take advantage of hardware colorkey or alpha blit 517 acceleration, you should set the colorkey and alpha value before 518 calling this function. 519 520 \returns The functions returns true if the conversion 521 succeeded or false otherwise. If the conversion failed, the 522 BaseSurface object will not have changed. 523 524 \note Please note that this function doesn't return a new, 525 modified object like the SDL_DisplayFormatAlpha() function 526 does. Thus there is no need to manually free the old surface. 527 528 \sa SetDisplayFormat(), SetAlpha(), SetColorKey() 529 */ 530 virtual bool SetDisplayFormatAlpha() = 0; 531 532 //! Save a BaseSurface object as a Windows bitmap file 533 /*! 534 \param file the file name to save to. 535 \returns True if the loading succeeded, false otherwise. 536 */ 537 bool SaveBMP(const char *file) const; 538 539 //! Save a BaseSurface object as a Windows bitmap file 540 /*! 541 \param file the file name to save to. 542 \returns True if the loading succeeded, false otherwise. 543 */ SaveBMP(const std::string & file)544 bool SaveBMP(const std::string& file) const { return SaveBMP(file.c_str()); } 545 546 }; 547 } 548 549 #endif // SDLMM_BASESURFACE_H 550