1 /* 2 Copyright (C) 1999/2000/2001/2004 Alexandre Courbot 3 Copyright (C) 2016 Kai Sterker 4 Part of the Adonthell Project <http://adonthell.nongnu.org> 5 6 Adonthell is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 Adonthell is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with Adonthell. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 21 /** 22 * @file surface.h 23 * @author Alexandre Courbot <alexandrecourbot@linuxgames.com> 24 * @author Kai Sterker 25 * 26 * @brief Declares the surface class. 27 * 28 * 29 */ 30 31 32 #ifndef SURFACE_H_ 33 #define SURFACE_H_ 34 35 36 #include "drawable.h" 37 38 #ifdef __BIG_ENDIAN__ 39 # define R_MASK 0x00ff0000 40 # define G_MASK 0x0000ff00 41 # define B_MASK 0x000000ff 42 # define A_MASK 0xff000000 43 #else 44 # define R_MASK 0x000000ff 45 # define G_MASK 0x0000ff00 46 # define B_MASK 0x00ff0000 47 # define A_MASK 0xff000000 48 #endif 49 #define BYTES_PER_PIXEL 4 50 51 52 class pixel_info 53 { 54 public: pixel_info()55 pixel_info() : Pixels(NULL), Pitch(0), Format(0), BytesPerPixel(0) 56 { } 57 58 /// the pixel data of the locked Surface 59 void *Pixels; 60 /// the pitch of the locked Surface 61 int Pitch; 62 /// the format of the surface 63 u_int32 Format; 64 /// number of bytes used to represent the format 65 u_int32 BytesPerPixel; 66 }; 67 68 /** 69 * Class where drawables can actually be drawn to. 70 * Another name for a surface could eventually be "pixmap". A surface 71 * is nothing more than an array of pixels where drawables can put their 72 * %image to. This class has only two purposes: to group methods shared by 73 * image and screen, and to ensure that every drawing operation can be performed 74 * on the screen or on an image. 75 * 76 * Every surface has two special parameters: 77 * @li a mask parameter, indicating whether the transparent color (which hex 78 * triplet is 0xFF00FF, and you can get with screen::trans_col ()) should 79 * be drawn or not. 80 * @li an alpha parameter, indicating the level of translucency of the surface. 81 * it's range go from 0 to 255, 0 being totally invisible and 255 totally 82 * opaque. 83 * 84 */ 85 class surface : public drawable 86 { 87 public: 88 89 /** 90 * Default constructor. 91 * The surface will be totally empty, that is 92 * (0, 0) sized, no mask, alpha value of 255 (opaque). 93 * 94 */ 95 surface (const u_int8 & scale = 1); 96 97 /** 98 * Destructor. 99 * 100 */ 101 virtual ~surface (); 102 103 104 /** 105 * @name Settings. 106 * These methods sets the parameters of the surface. 107 * 108 */ 109 //@{ 110 111 112 /** 113 * 114 * Returns whether a surface is masked or not. 115 * 116 * @return true if the surface is masked, false if it isn't. 117 */ is_masked()118 bool is_masked () const 119 { 120 return is_masked_; 121 } 122 123 /** 124 * Sets the mask parameter of the surface. 125 * 126 * @param m true if the surface should be masked, false otherwise. 127 */ 128 void set_mask (bool m); 129 130 /** 131 * Returns the alpha value of the surface. 132 * 133 * 134 * @return the alpha value of the surface. 135 */ alpha()136 u_int8 alpha () const 137 { 138 return alpha_; 139 } 140 141 /** 142 * Sets the alpha value of the surface. If alpha_channel is set to true, 143 * then the surface_alpha value will be silently ignored. Needs to 144 * be called before surface::resize to take effect. 145 * 146 * @param surface_alpha The new alpha value for this surface. 147 * @param alpha_channel Whether to enable per-pixel alpha for the surface. 148 */ 149 void set_alpha (u_int8 a, const bool & alpha_channel = false); 150 151 /** 152 * Returns whether the surface has an alpha channel. 153 * @return true if it has an alpha channel, false otherwise. 154 */ has_alpha_channel()155 bool has_alpha_channel () const 156 { 157 return alpha_channel_; 158 } 159 160 /** 161 * Get the surfaces current scaling factor. 162 */ scale()163 u_int8 scale () const { return scale_; } 164 165 /** 166 * Change the scale of the surface to the given value, 167 * resizing the internal texture appropriately. 168 * @param scale the new scale to set. 169 */ 170 void set_scale (const u_int8 & scale); 171 172 //@} 173 174 175 /** 176 * @name Drawing Methods. 177 * 178 */ 179 180 //@{ 181 182 183 /** 184 * Draw the surface. 185 * 186 * @param x X position where to draw. 187 * @param y Y position where to draw. 188 * @param da_opt optional drawing_area to use during the drawing operation. 189 * @param target pointer to the surface where to draw the drawable. If NULL, draw on the screen. 190 */ 191 void draw (s_int16 x, s_int16 y, const drawing_area * da_opt = NULL, 192 surface * target = NULL) const 193 { 194 draw (x, y, 0, 0, length (), height (), da_opt, target); 195 } 196 197 #ifndef SWIG 198 /** 199 * Draw a part of the surface. 200 * 201 * @param x X position where to draw. 202 * @param y Y position where to draw. 203 * @param sx X position where to start drawing from this image. 204 * @param sy Y position where to start drawing from this image. 205 * @param sl length of the part of this image to draw. 206 * @param sh height of the part of this image to draw. 207 * @param da_opt optional drawing_area to use during the drawing operation. 208 * @param target pointer to the surface where to draw the drawable. If NULL, draw on the screen. 209 * 210 * @attention Not accessible from Python. Use draw_part () from Python instead. 211 * @sa draw_part () 212 * 213 */ 214 void draw (s_int16 x, s_int16 y, s_int16 sx, s_int16 sy, u_int16 sl, 215 u_int16 sh, const drawing_area * da_opt = NULL, 216 surface * target = NULL) const; 217 #endif 218 219 /** 220 * Synonym of draw () to guarantee its access from Python. 221 * 222 * @sa draw () 223 * 224 */ 225 void draw_part (s_int16 x, s_int16 y, s_int16 sx, s_int16 sy, u_int16 sl, 226 u_int16 sh, const drawing_area * da_opt = NULL, 227 surface * target = NULL) const 228 { 229 draw (x, y, sx, sy, sl, sh, da_opt, target); 230 } 231 232 /** 233 * Fills an area of the surface with a given color. 234 * 235 * The color you pass to this function MUST come from a game's function 236 * (like surface::get_pix () or screen::trans_col ()), because of the 237 * screen depth dependant value of the col argument. 238 * 239 * @param x X position where to fill. 240 * @param y Y position where to fill. 241 * @param l length of the area to fill. 242 * @param h height of the area to fill. 243 * @param col color to fill the surface with. 244 * @param da_opt optionnal drawing_area to use during the fill operation. 245 * 246 */ 247 void fillrect (s_int16 x, s_int16 y, u_int16 l, u_int16 h, 248 u_int32 col, drawing_area * da_opt = NULL); 249 //@} 250 251 /** 252 * @name Pixel manipulation Methods. 253 * Use these methods to directly and quickly manipulate 254 * pixels from a surface. 255 * 256 */ 257 //@{ 258 259 u_int32 map_color(const u_int8 & r, const u_int8 & g, const u_int8 & b, const u_int8 & a = 255) const; 260 void unmap_color(u_int32 col, u_int8 & r, u_int8 & g, u_int8 & b, u_int8 & a) const; 261 262 /** 263 * Locks the surface. 264 * Sometimes you may want to access directly the pixels of a surface. This 265 * can be done with the get_pix () and put_pix () methods, thus you must 266 * ABSOLUTELY lock the surface before doing so. This function is made for 267 * that. Note that using get_pix () or put_pix () without locking the surface 268 * may result in unpredictable behavior, crashes included. 269 * 270 */ lock()271 void lock () const 272 { 273 lock(NULL); 274 } 275 276 /** 277 * Unlock the surface after you've worked on it's pixels with the 278 * get_pix () and put_pix () methods. 279 * 280 */ 281 void unlock () const; 282 283 /** 284 * Puts a pixel of a given color. 285 * 286 * The col parameter is specific to the current screen depth, 287 * and must come from a game's function like get_pix or 288 * screen::trans_col (). 289 * 290 * @param x X position of the pixel to change. 291 * @param y Y position of the pixel to change. 292 * @param col color to put. 293 */ 294 void put_pix (u_int16 x, u_int16 y, u_int32 col); 295 296 #ifndef SWIG 297 /** 298 * Puts a pixel of a given color. 299 * 300 * The r, g and b parameters are the hex triplets of the color 301 * to put. 302 * 303 * @param x X position of the pixel to change. 304 * @param y Y position of the pixel to change. 305 * @param r red value of the color to put. 306 * @param g green value of the color to put. 307 * @param b blue value of the color to put. 308 * 309 * @attention Not accessible from Python. Use put_pix_rgb from Python instead. 310 * @sa put_pix_rgb () 311 * 312 */ put_pix(u_int16 x,u_int16 y,u_int8 r,u_int8 g,u_int8 b)313 void put_pix (u_int16 x, u_int16 y, u_int8 r, u_int8 g, u_int8 b) 314 { 315 #ifdef __BIG_ENDIAN__ 316 put_pix (x, y, map_color(b, SDL_ALPHA_OPAQUE, g, r)); 317 #else 318 put_pix (x, y, map_color(r, g, b, SDL_ALPHA_OPAQUE)); 319 #endif 320 } 321 #endif 322 323 /** 324 * Synonym of put_pix () to guarantee its access from Python. 325 * 326 * @sa put_pix () 327 */ put_pix_rgb(u_int16 x,u_int16 y,u_int8 r,u_int8 g,u_int8 b)328 void put_pix_rgb (u_int16 x, u_int16 y, u_int8 r, u_int8 g, u_int8 b) 329 { 330 put_pix (x, y, r, g, b); 331 } 332 333 /** 334 * Gets a pixel from the surface. 335 * 336 * The col parameter is specific to the current screen depth, 337 * and can be used with functions like put_pix (). 338 * 339 * @param x X position of the pixel to change. 340 * @param y Y position of the pixel to change. 341 * @returnl returned color. 342 */ 343 u_int32 get_pix (u_int16 x, u_int16 y) const; 344 345 #ifndef SWIG 346 /** 347 * Gets a pixel from a surface. 348 * 349 * The returned r, g and b values are the hex triplets of the color. 350 * 351 * @param x X position of the pixel to change. 352 * @param y Y position of the pixel to change. 353 * @param r red value of the color. 354 * @param g green value of the color. 355 * @param b blue value of the color. 356 * 357 * @attention Not accessible from Python. Use get_pix_rgb from Python instead. 358 * @sa get_pix_rgb () 359 */ get_pix(u_int16 x,u_int16 y,u_int8 & r,u_int8 & g,u_int8 & b)360 void get_pix (u_int16 x, u_int16 y, u_int8& r, u_int8& g, u_int8& b) const 361 { 362 u_int8 a; 363 u_int32 col = get_pix(x, y); 364 365 #ifdef __BIG_ENDIAN__ 366 unmap_color(col, g, r, a, b); 367 #else 368 unmap_color(col, r, g, b, a); 369 #endif 370 } 371 #endif 372 373 /** 374 * Synonym of get_pix () to guarantee its access from Python. 375 * 376 * @sa get_pix () 377 */ get_pix_rgb(u_int16 x,u_int16 y,u_int8 r,u_int8 g,u_int8 b)378 void get_pix_rgb (u_int16 x, u_int16 y, u_int8 r, u_int8 g, u_int8 b) const 379 { 380 get_pix (x, y, r, g, b); 381 } 382 383 //@} 384 385 386 #ifndef SWIG 387 /** 388 * Surface copy (similar to copy ()). 389 * 390 * @attention Not available from Python. Use copy () from Python instead. 391 * @sa copy () 392 */ 393 surface& operator = (const surface& src); 394 #endif 395 396 /** 397 * Synonym of operator = to guarantee its access from Python. 398 * 399 * @sa operator = 400 */ copy(const surface & src)401 void copy (const surface& src) 402 { 403 *this = src; 404 } 405 406 protected: 407 408 /** 409 * Resize this surface. All the content will be lost. 410 * 411 * @param l new length. 412 * @param h new height. 413 */ 414 void resize (u_int16 l, u_int16 h); 415 416 /** 417 * Resets the surface to it's initial state, that is totally 418 * empty. 419 * 420 */ 421 void clear (); 422 423 void set_data (void * data, u_int16 l, u_int16 h, 424 u_int8 bytes_per_pixel = BYTES_PER_PIXEL, 425 u_int32 red_mask = R_MASK, u_int32 green_mask = G_MASK, 426 u_int32 blue_mask = B_MASK, u_int32 alpha_mask = 0); 427 428 void * get_data (u_int8 bytes_per_pixel, 429 u_int32 red_mask, u_int32 green_mask, 430 u_int32 blue_mask, u_int32 alpha_mask) const; 431 432 433 /// Create a software surface backed by the (streaming) texture data. 434 SDL_Surface *to_sw_surface(SDL_Rect *rect = NULL) const; 435 436 /// lock part of the surface specified by rect 437 void lock (SDL_Rect *rect) const; 438 439 /// the surface 440 SDL_Texture *Surface; 441 442 /// current scale 443 u_int8 scale_; 444 445 /// sub-pixel offset 446 s_int16 offset_x_; 447 private: 448 /** 449 * Forbid copy construction. 450 * 451 */ 452 surface (const surface & src); 453 454 /// some meta-information about the surface 455 pixel_info *Info; 456 457 /// Mask 458 bool is_masked_; 459 460 /// Whether mask has been requested, but not yet set 461 bool mask_changed_; 462 463 /// Per-Surface Alpha value 464 u_int8 alpha_; 465 466 /// Whether Per-Pixel alpha is enabled 467 bool alpha_channel_; 468 469 /// SDL_Rects used in every blitting function. 470 static SDL_Rect srcrect, dstrect; 471 472 /// Used internally for blitting operations with drawing_areas. 473 void setup_rects (s_int16 x, s_int16 y, s_int16 sx, s_int16 sy, 474 u_int16 sl, u_int16 sh, const drawing_area * draw_to) const; 475 476 #ifndef SWIG 477 friend class screen; 478 #endif 479 }; 480 481 #endif 482