sdl_utils.hpp

Go to the documentation of this file.
00001 /* $Id: sdl_utils.hpp 54004 2012-04-28 14:17:07Z jamit $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /** @file */
00017 
00018 #ifndef SDL_UTILS_INCLUDED
00019 #define SDL_UTILS_INCLUDED
00020 
00021 #include "scoped_resource.hpp"
00022 #include "util.hpp"
00023 
00024 #include "SDL.h"
00025 
00026 #include <cstdlib>
00027 #include <iosfwd>
00028 #include <map>
00029 #include <string>
00030 
00031 //older versions of SDL don't define the
00032 //mouse wheel macros, so define them ourselves
00033 //if necessary.
00034 #ifndef SDL_BUTTON_WHEELUP
00035 #define SDL_BUTTON_WHEELUP 4
00036 #endif
00037 
00038 #ifndef SDL_BUTTON_WHEELDOWN
00039 #define SDL_BUTTON_WHEELDOWN 5
00040 #endif
00041 
00042 #ifndef SDL_BUTTON_WHEELLEFT
00043 #define SDL_BUTTON_WHEELLEFT 6
00044 #endif
00045 
00046 #ifndef SDL_BUTTON_WHEELRIGHT
00047 #define SDL_BUTTON_WHEELRIGHT 7
00048 #endif
00049 
00050 namespace {
00051 const SDL_Rect empty_rect = { 0, 0, 0, 0 };
00052 }
00053 
00054 SDLKey sdl_keysym_from_name(std::string const &keyname);
00055 
00056 bool point_in_rect(int x, int y, const SDL_Rect& rect);
00057 bool rects_overlap(const SDL_Rect& rect1, const SDL_Rect& rect2);
00058 SDL_Rect intersect_rects(SDL_Rect const &rect1, SDL_Rect const &rect2);
00059 SDL_Rect union_rects(const SDL_Rect &rect1, const SDL_Rect &rect2);
00060 
00061 /**
00062  *  Creates an empty SDL_Rect.
00063  *
00064  *  Since SDL_Rect doesn't have a constructor it's not possible to create it as
00065  *  a temporary for a function parameter. This functions overcomes this limit.
00066  */
00067 SDL_Rect create_rect(const int x, const int y, const int w, const int h);
00068 
00069 struct surface
00070 {
00071 private:
00072     static void sdl_add_ref(SDL_Surface *surf)
00073     {
00074         if (surf != NULL)
00075             ++surf->refcount;
00076     }
00077 
00078     struct free_sdl_surface {
00079         void operator()(SDL_Surface *surf) const
00080         {
00081             if (surf != NULL)
00082                  SDL_FreeSurface(surf);
00083         }
00084     };
00085 
00086     typedef util::scoped_resource<SDL_Surface*,free_sdl_surface> scoped_sdl_surface;
00087 public:
00088     surface() : surface_(NULL)
00089     {}
00090 
00091     surface(SDL_Surface *surf) : surface_(surf)
00092     {}
00093 
00094     surface(const surface& o) : surface_(o.surface_.get())
00095     {
00096         sdl_add_ref(surface_.get());
00097     }
00098 
00099     void assign(const surface& o)
00100     {
00101         SDL_Surface *surf = o.surface_.get();
00102         sdl_add_ref(surf); // need to be done before assign to avoid corruption on "a=a;"
00103         surface_.assign(surf);
00104     }
00105 
00106     surface& operator=(const surface& o)
00107     {
00108         assign(o);
00109         return *this;
00110     }
00111 
00112     operator SDL_Surface*() const { return surface_.get(); }
00113 
00114     SDL_Surface* get() const { return surface_.get(); }
00115 
00116     SDL_Surface* operator->() const { return surface_.get(); }
00117 
00118     void assign(SDL_Surface* surf) { surface_.assign(surf); }
00119 
00120     bool null() const { return surface_.get() == NULL; }
00121 
00122 private:
00123     scoped_sdl_surface surface_;
00124 };
00125 
00126 bool operator<(const surface& a, const surface& b);
00127 
00128 inline void sdl_blit(const surface& src, SDL_Rect* src_rect, surface& dst, SDL_Rect* dst_rect){
00129     SDL_BlitSurface(src, src_rect, dst, dst_rect);
00130 }
00131 
00132 inline void sdl_fill_rect(surface& dst, SDL_Rect* dst_rect, const Uint32 color){
00133     SDL_FillRect(dst, dst_rect, color);
00134 }
00135 
00136 /**
00137  * Check that the surface is neutral bpp 32.
00138  *
00139  * The surface may have an empty alpha channel.
00140  *
00141  * @param surf                    The surface to test.
00142  *
00143  * @returns                       The status @c true if neutral, @c false if not.
00144  */
00145 bool is_neutral(const surface& surf);
00146 
00147 surface make_neutral_surface(const surface &surf);
00148 surface create_neutral_surface(int w, int h);
00149 surface create_optimized_surface(const surface &surf);
00150 
00151 /**
00152  * Stretches a surface in the horizontal direction.
00153  *
00154  *  The stretches a surface it uses the first pixel in the horizontal
00155  *  direction of the original surface and copies that to the destination.
00156  *  This means only the first column of the original is used for the destination.
00157  *  @param surf              The source surface.
00158  *  @param w                 The width of the resulting surface.
00159  *  @param optimize          Should the return surface be RLE optimized.
00160  *
00161  *  @return                  An optimized surface.
00162  *                           returned.
00163  *  @retval 0                Returned upon error.
00164  *  @retval surf             Returned if w == surf->w, note this ignores the
00165  *                           optimize flag.
00166  */
00167 surface stretch_surface_horizontal(
00168     const surface& surf, const unsigned w, const bool optimize = true);
00169 
00170 /**
00171  *  Stretches a surface in the vertical direction.
00172  *
00173  *  The stretches a surface it uses the first pixel in the vertical
00174  *  direction of the original surface and copies that to the destination.
00175  *  This means only the first row of the original is used for the destination.
00176  *  @param surf              The source surface.
00177  *  @param h                 The height of the resulting surface.
00178  *  @param optimize          Should the return surface be RLE optimized.
00179  *
00180  *  @return                  An optimized surface.
00181  *                           returned.
00182  *
00183  *  @retval surf             Returned if h == surf->h, note this ignores the
00184  *                           optimize flag.
00185  */
00186 surface stretch_surface_vertical(
00187     const surface& surf, const unsigned h, const bool optimize = true);
00188 
00189 /** Scale a surface
00190  *  @param surf              The source surface.
00191  *  @param w                 The width of the resulting surface.
00192  *  @param h                 The height of the resulting surface.
00193  *  @param optimize          Should the return surface be RLE optimized.
00194  *  @return                  A surface containing the scaled version of the source.
00195  *  @retval 0                Returned upon error.
00196  *  @retval surf             Returned if w == surf->w and h == surf->h
00197  *                           note this ignores the optimize flag.
00198  */
00199 surface scale_surface(const surface &surf, int w, int h, bool optimize=true);
00200 
00201 surface adjust_surface_color(const surface &surf, int r, int g, int b, bool optimize=true);
00202 surface greyscale_image(const surface &surf, bool optimize=true);
00203 /** create an heavy shadow of the image, by blurring, increasing alpha and darkening */
00204 surface shadow_image(const surface &surf, bool optimize=true);
00205 
00206 /**
00207  * Recolors a surface using a map with source and converted palette values.
00208  * This is most often used for team-coloring.
00209  *
00210  * @param surf               The source surface.
00211  * @param map_rgb            Map of color values, with the keys corresponding to the
00212  *                           source palette, and the values to the recolored palette.
00213  * @param optimize           Whether the new surface should be RLE encoded. Only
00214  *                           useful when the source is not the screen and it is
00215  *                           going to be used multiple times.
00216  * @return                   A recolored surface, or a null surface if there are
00217  *                           problems with the source.
00218  */
00219 surface recolor_image(surface surf, const std::map<Uint32, Uint32>& map_rgb,
00220     bool optimize=true);
00221 
00222 surface brighten_image(const surface &surf, fixed_t amount, bool optimize=true);
00223 
00224 /** Get a portion of the screen.
00225  *  Send NULL if the portion is outside of the screen.
00226  *  @param surf              The source surface.
00227  *  @param rect              The portion of the source surface to copy.
00228  *  @param optimize_format   Optimize by converting to result to display format.
00229  *                           Only useful if the source is not the screen and you
00230  *                           plan to blit the result on screen several times.
00231  *  @return                  A surface containing the portion of the source.
00232  *                           No RLE or Alpha bits are set.
00233  *  @retval 0                if error or the portion is outside of the surface.
00234  */
00235 surface get_surface_portion(const surface &surf, SDL_Rect &rect,
00236     bool optimize_format=false);
00237 
00238 surface adjust_surface_alpha(const surface &surf, fixed_t amount, bool optimize=true);
00239 surface adjust_surface_alpha_add(const surface &surf, int amount, bool optimize=true);
00240 
00241 /** Applies a mask on a surface. */
00242 surface mask_surface(const surface &surf, const surface &mask, bool* empty_result = NULL, const std::string& filename = std::string());
00243 
00244 /** Check if a surface fit into a mask */
00245 bool in_mask_surface(const surface &surf, const surface &mask);
00246 
00247 /** Progressively reduce alpha of bottom part of the surface
00248  *  @param surf              The source surface.
00249  *  @param depth             The height of the bottom part in pixels
00250  *  @param alpha_base        The alpha adjustement at the interface
00251  *  @param alpha_delta       The alpha adjustement reduction rate by pixel depth
00252  *  @param optimize_format   Optimize by converting to result to display
00253 */
00254 surface submerge_alpha(const surface &surf, int depth, float alpha_base, float alpha_delta, bool optimize=true);
00255 
00256 /**
00257  * Light surf using lightmap
00258  * @param surf               The source surface.
00259  * @param lightmap           add/subtract this color to surf
00260  *                           but RGB values are converted to (X-128)*2
00261  *                           to cover the full (-256,256) spectrum.
00262  *                           Should already be neutral
00263  * @param optimize           Whether the new surface should be RLE encoded.
00264 */
00265 surface light_surface(const surface &surf, const surface &lightmap, bool optimize=true);
00266 
00267 /** Cross-fades a surface. */
00268 surface blur_surface(const surface &surf, int depth = 1, bool optimize=true);
00269 
00270 /**
00271  * Cross-fades a surface in place.
00272  *
00273  * @param surf                    The surface to blur, must be not optimized
00274  *                                and have 32 bits per pixel.
00275  * @param rect                    The part of the surface to blur.
00276  * @param depth                   The depth of the blurring.
00277  */
00278 void blur_surface(surface& surf, SDL_Rect rect, unsigned depth = 1);
00279 
00280 /**
00281  * Cross-fades a surface with alpha channel.
00282  *
00283  * @todo FIXME: This is just an adapted copy-paste
00284  * of the normal blur but with blur alpha channel too
00285  */
00286 surface blur_alpha_surface(const surface &surf, int depth = 1, bool optimize=true);
00287 
00288 /** Cuts a rectangle from a surface. */
00289 surface cut_surface(const surface &surf, SDL_Rect const &r);
00290 
00291 /**
00292  * Blends a surface with a colour.
00293  *
00294  * Every pixel in the surface will be blended with the @p color given. The
00295  * final colour of a pixel is amount * @p color + (1 - amount) * original.
00296  *
00297  * @param surf                    The surface to blend.
00298  * @param amount                  The amount of the new colour is determined by
00299  *                                @p color. Must be a number in the range
00300  *                                [0, 1].
00301  * @param color                   The colour to blend width, note its alpha
00302  *                                channel is ignored.
00303  * @param optimize                Should the return surface be RLE optimized.
00304  *
00305  * @return                        The blended surface.
00306  */
00307 surface blend_surface(
00308           const surface &surf
00309         , const double amount
00310         , const Uint32 color
00311         , const bool optimize = true);
00312 
00313 /**
00314  * Rotates a surface 180 degrees.
00315  *
00316  * @param surf                    The surface to rotate.
00317  * @param optimize                Should the return surface be RLE optimized.
00318  *
00319  * @return                        The rotated surface.
00320  */ 
00321 surface rotate_180_surface(const surface &surf, bool optimize=true);
00322 /**
00323  * Rotates a surface 90 degrees.
00324  *
00325  * @param surf                    The surface to rotate.
00326  * @param clockwize               Whether the rotation should be clockwise (true)
00327  *                                or counter-clockwise (false).
00328  * @param optimize                Should the return surface be RLE optimized.
00329  *
00330  * @return                        The rotated surface.
00331  */ 
00332 surface rotate_90_surface(const surface &surf, bool clockwise, bool optimize=true);
00333 
00334 surface flip_surface(const surface &surf, bool optimize=true);
00335 surface flop_surface(const surface &surf, bool optimize=true);
00336 surface create_compatible_surface(const surface &surf, int width = -1, int height = -1);
00337 
00338 /**
00339  * Replacement for sdl_blit.
00340  *
00341  * sdl_blit has problems with blitting partly transparent surfaces so
00342  * this is a replacement. It ignores the SDL_SRCALPHA and SDL_SRCCOLORKEY
00343  * flags. src and dst will have the SDL_RLEACCEL flag removed.
00344  * The return value of SDL_BlistSurface is normally ignored so no return value.
00345  * The rectangles are const and will not be modified.
00346  *
00347  * @pre @p src contains a valid canvas.
00348  * @pre @p dst contains a valid canvas.
00349  * @pre The caller must make sure the @p src fits on the @p dst.
00350  *
00351  * @param src          The surface to blit.
00352  * @param srcrect      The region of the surface to blit
00353  * @param dst          The surface to blit on.
00354  * @param dstrect      The offset to blit the surface on, only x and y are used.
00355  */
00356 void blit_surface(const surface& src,
00357     const SDL_Rect* srcrect, surface& dst, const SDL_Rect* dstrect);
00358 
00359 void fill_rect_alpha(SDL_Rect &rect, Uint32 color, Uint8 alpha, surface &target);
00360 
00361 SDL_Rect get_non_transparent_portion(const surface &surf);
00362 
00363 bool operator==(const SDL_Rect& a, const SDL_Rect& b);
00364 bool operator!=(const SDL_Rect& a, const SDL_Rect& b);
00365 bool operator==(const SDL_Color& a, const SDL_Color& b);
00366 bool operator!=(const SDL_Color& a, const SDL_Color& b);
00367 SDL_Color inverse(const SDL_Color& color);
00368 SDL_Color int_to_color(const Uint32 rgb);
00369 
00370 SDL_Color create_color(const unsigned char red
00371         , unsigned char green
00372         , unsigned char blue
00373         , unsigned char unused = 255);
00374 
00375 /**
00376  * Helper class for pinning SDL surfaces into memory.
00377  * @note This class should be used only with neutral surfaces, so that
00378  *       the pointer returned by #pixels is meaningful.
00379  */
00380 struct surface_lock
00381 {
00382     surface_lock(surface &surf);
00383     ~surface_lock();
00384 
00385     Uint32* pixels() { return reinterpret_cast<Uint32*>(surface_->pixels); }
00386 private:
00387     surface& surface_;
00388     bool locked_;
00389 };
00390 
00391 struct const_surface_lock
00392 {
00393     const_surface_lock(const surface &surf);
00394     ~const_surface_lock();
00395 
00396     const Uint32* pixels() const { return reinterpret_cast<const Uint32*>(surface_->pixels); }
00397 private:
00398     const surface& surface_;
00399     bool locked_;
00400 };
00401 
00402 struct surface_restorer
00403 {
00404     surface_restorer();
00405     surface_restorer(class CVideo* target, const SDL_Rect& rect);
00406     ~surface_restorer();
00407 
00408     void restore() const;
00409     void restore(SDL_Rect const &dst) const;
00410     void update();
00411     void cancel();
00412 
00413     const SDL_Rect& area() const { return rect_; }
00414 
00415 private:
00416     class CVideo* target_;
00417     SDL_Rect rect_;
00418     surface surface_;
00419 };
00420 
00421 struct clip_rect_setter
00422 {
00423     // if r is NULL, clip to the full size of the surface.
00424     clip_rect_setter(const surface &surf, const SDL_Rect* r, bool operate = true) : surface_(surf), rect_(), operate_(operate)
00425     {
00426         if(operate_){
00427             SDL_GetClipRect(surface_, &rect_);
00428             SDL_SetClipRect(surface_, r);
00429         }
00430     }
00431 
00432     ~clip_rect_setter() {
00433         if (operate_)
00434             SDL_SetClipRect(surface_, &rect_);
00435     }
00436 
00437 private:
00438     surface surface_;
00439     SDL_Rect rect_;
00440     const bool operate_;
00441 };
00442 
00443 
00444 void draw_rectangle(int x, int y, int w, int h, Uint32 color, surface tg);
00445 
00446 void draw_solid_tinted_rectangle(int x, int y, int w, int h,
00447                                  int r, int g, int b,
00448                  double alpha, surface target);
00449 
00450 // blit the image on the center of the rectangle
00451 // and a add a colored background
00452 void draw_centered_on_background(surface surf, const SDL_Rect& rect,
00453     const SDL_Color& color, surface target);
00454 
00455 std::ostream& operator<<(std::ostream& s, const SDL_Rect& rect);
00456 
00457 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:09 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs