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