image_modifications.cpp

Go to the documentation of this file.
00001 /* $Id: image_modifications.cpp 54113 2012-05-06 22:06:46Z jamit $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Ignacio R. Morelle <shadowm2006@gmail.com>
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 #include "color_range.hpp"
00017 #include "config.hpp"
00018 #include "display.hpp"
00019 #include "foreach.hpp"
00020 #include "game_config.hpp"
00021 #include "image.hpp"
00022 #include "image_modifications.hpp"
00023 #include "log.hpp"
00024 #include "serialization/string_utils.hpp"
00025 
00026 #include <map>
00027 
00028 #define GETTEXT_DOMAIN "wesnoth-lib"
00029 
00030 static lg::log_domain log_display("display");
00031 #define ERR_DP LOG_STREAM(err, log_display)
00032 #define LOG_DP LOG_STREAM(info, log_display)
00033 
00034 namespace image {
00035 
00036 
00037 namespace {
00038 
00039 /// A function used to parse modification arguments
00040 typedef modification* (*mod_parser)(const std::string&);
00041 
00042 /** A map of all registered mod parsers
00043  *
00044  * The mapping is between the modification name and the parser function pointer
00045  * An example of an entry would be "TC" -> &parse_TC_mod
00046  */
00047 std::map<std::string, mod_parser> mod_parsers;
00048 
00049 /** Decodes a single modification using an appropriate mod_parser
00050  *
00051  * @param encoded_mod A string representing a single modification
00052  *
00053  * @return A pointer to the decoded modification object
00054  * @retval NULL if the string is invalid or a parser isn't found
00055  */
00056 modification* decode_modification(const std::string& encoded_mod)
00057 {
00058     std::vector<std::string> split = utils::parenthetical_split(encoded_mod);
00059 
00060     if(split.size() != 2) {
00061         ERR_DP << "error parsing image modifications: "
00062                << encoded_mod << "\n";
00063         return NULL;
00064     }
00065 
00066     std::string mod_type = split[0];
00067     std::string args = split[1];
00068 
00069     if(mod_parsers.find(mod_type) == mod_parsers.end()) {
00070         ERR_DP << "unknown image function in path: "
00071                << mod_type << '\n';
00072         return NULL;
00073     }
00074 
00075     return (*mod_parsers[mod_type])(args);
00076 }
00077 } // end anon namespace
00078 
00079 
00080 modification::texception::texception(const std::stringstream& message_stream)
00081     : message(message_stream.str())
00082 {
00083 }
00084 
00085 modification::texception::texception(const std::string& message)
00086         : message(message)
00087 {
00088 }
00089 
00090 /** Decodes the modification string
00091  *
00092  * Important:
00093  * It creates new objects which need to be deleted after use
00094  *
00095  * @param encoded_mods A string representing any number of modifications
00096  *
00097  * @return A modification_queue filled with decoded modification pointers
00098  */
00099 modification_queue modification::decode(const std::string& encoded_mods)
00100 {
00101     modification_queue mods;
00102 
00103     foreach(const std::string& encoded_mod,
00104         utils::parenthetical_split(encoded_mods, '~')) {
00105         modification* mod = decode_modification(encoded_mod);
00106 
00107         if(mod) {
00108             mods.push(mod);
00109         }
00110     }
00111 
00112     return mods;
00113 }
00114 
00115 /// Compares two modification pointers, providing descending priority order
00116 bool mod_ptr_comparator_::operator()(const modification* a,
00117                      const modification* b) const
00118 {
00119     return a->priority() < b->priority();
00120 }
00121 
00122 surface rc_modification::operator()(const surface& src) const
00123 {
00124     // unchecked
00125     return recolor_image(src, rc_map_);
00126 }
00127 
00128 surface fl_modification::operator()(const surface& src) const
00129 {
00130     surface ret = src;
00131 
00132     if ( horiz_  && vert_ ) {
00133         // Slightly faster than doing both a flip and a flop.
00134         ret = rotate_180_surface(ret);
00135     }
00136 
00137     else if(horiz_) {
00138         ret = flip_surface(ret);
00139     }
00140 
00141     else if(vert_) {
00142         ret = flop_surface(ret);
00143     }
00144 
00145     return ret;
00146 }
00147 
00148 surface rotate_modification::operator()(const surface& src) const
00149 {
00150     // Convert the number of degrees to the interval [0,360].
00151     const int normalized = degrees_ >= 0 ?
00152         degrees_ - 360*(degrees_/360) :
00153         degrees_ + 360*(1 + (-degrees_)/360); // In case compilers disagree as to what -90/360 is.
00154 
00155     switch ( normalized )
00156     {
00157         case 0:   return src;
00158         case 90:  return rotate_90_surface(src, true);
00159         case 180: return rotate_180_surface(src);
00160         case 270: return rotate_90_surface(src, false);
00161         case 360: return src;
00162     }
00163 
00164     // Other values are not supported. Ignore them.
00165     return src;
00166 }
00167 
00168 surface gs_modification::operator()(const surface& src) const
00169 {
00170     return greyscale_image(src);
00171 }
00172 
00173 surface crop_modification::operator()(const surface& src) const
00174 {
00175     SDL_Rect area = slice_;
00176     if(area.w == 0) {
00177         area.w = src->w;
00178     }
00179     if(area.h == 0) {
00180         area.h = src->h;
00181     }
00182     if(area.x < 0) {
00183         ERR_DP << "start X coordinate of SECTION modification is negative - truncating to zero\n";
00184         area.x = 0;
00185     }
00186     if(area.y < 0) {
00187         ERR_DP << "start Y coordinate of SECTION modification is negative - truncating to zero\n";
00188         area.y = 0;
00189     }
00190     return cut_surface(src, area);
00191 }
00192 
00193 const SDL_Rect& crop_modification::get_slice() const
00194 {
00195     return slice_;
00196 }
00197 
00198 surface blit_modification::operator()(const surface& src) const
00199 {
00200     if(x_ >= src->w) {
00201         std::stringstream sstr;
00202         sstr << "~BLIT(): x-coordinate '"
00203             << x_ << "' larger than destination image's width '"
00204             << src->w << "' no blitting performed.\n";
00205 
00206         throw texception(sstr);
00207     }
00208 
00209     if(y_ >= src->h) {
00210         std::stringstream sstr;
00211         sstr << "~BLIT(): y-coordinate '"
00212             << y_ << "' larger than destination image's height '"
00213             << src->h << "' no blitting performed.\n";
00214 
00215         throw texception(sstr);
00216     }
00217 
00218     if(surf_->w + x_ > src->w) {
00219         std::stringstream sstr;
00220         sstr << "~BLIT(): offset and width '"
00221             << x_ + surf_->w << "' larger than destination image's width '"
00222             << src->w << "' no blitting performed.\n";
00223 
00224         throw texception(sstr);
00225     }
00226 
00227     if(surf_->h + y_ > src->h) {
00228         std::stringstream sstr;
00229         sstr << "~BLIT(): offset and height '"
00230             << y_ + surf_->h << "' larger than destination image's height '"
00231             << src->h << "' no blitting performed.\n";
00232 
00233         throw texception(sstr);
00234     }
00235 
00236     //blit_surface want neutral surfaces
00237     surface nsrc = make_neutral_surface(src);
00238     surface nsurf = make_neutral_surface(surf_);
00239     SDL_Rect r = create_rect(x_, y_, 0, 0);
00240     blit_surface(nsurf, NULL, nsrc, &r);
00241     return nsrc;
00242 }
00243 
00244 const surface& blit_modification::get_surface() const
00245 {
00246     return surf_;
00247 }
00248 
00249 int blit_modification::get_x() const
00250 {
00251     return x_;
00252 }
00253 
00254 int blit_modification::get_y() const
00255 {
00256     return y_;
00257 }
00258 
00259 surface mask_modification::operator()(const surface& src) const
00260 {
00261     if(src->w == mask_->w &&  src->h == mask_->h && x_ == 0 && y_ == 0)
00262         return mask_surface(src, mask_);
00263     SDL_Rect r = create_rect(x_, y_, 0, 0);
00264     surface new_mask = create_neutral_surface(src->w, src->h);
00265     blit_surface(mask_, NULL, new_mask, &r);
00266     return mask_surface(src, new_mask);
00267 }
00268 
00269 const surface& mask_modification::get_mask() const
00270 {
00271     return mask_;
00272 }
00273 
00274 int mask_modification::get_x() const
00275 {
00276     return x_;
00277 }
00278 
00279 int mask_modification::get_y() const
00280 {
00281     return y_;
00282 }
00283 
00284 surface light_modification::operator()(const surface& src) const {
00285     if(src == NULL) { return NULL; }
00286 
00287     //light_surface wants a neutral surface having same dimensions
00288     surface nsurf;
00289     if(surf_->w != src->w || surf_->h != src->h)
00290         nsurf = scale_surface(surf_, src->w, src->h, false);
00291     else
00292         nsurf = make_neutral_surface(surf_);
00293     return light_surface(src, nsurf);;
00294 }
00295 
00296 const surface& light_modification::get_surface() const
00297 {
00298     return surf_;
00299 }
00300 
00301 surface scale_modification::operator()(const surface& src) const
00302 {
00303     const int old_w = src->w;
00304     const int old_h = src->h;
00305     int w = w_;
00306     int h = h_;
00307 
00308     if(w <= 0) {
00309         if(w < 0) {
00310             ERR_DP << "width of SCALE is negative - resetting to original width\n";
00311         }
00312         w = old_w;
00313     }
00314     if(h <= 0) {
00315         if(h < 0) {
00316             ERR_DP << "height of SCALE is negative - resetting to original height\n";
00317         }
00318         h = old_h;
00319     }
00320 
00321     return scale_surface(src, w, h);
00322 }
00323 
00324 int scale_modification::get_w() const
00325 {
00326     return w_;
00327 }
00328 
00329 int scale_modification::get_h() const
00330 {
00331     return h_;
00332 }
00333 
00334 surface o_modification::operator()(const surface& src) const
00335 {
00336     return adjust_surface_alpha(src, ftofxp(opacity_));
00337 }
00338 
00339 float o_modification::get_opacity() const
00340 {
00341     return opacity_;
00342 }
00343 
00344 surface cs_modification::operator()(const surface& src) const
00345 {
00346     return(
00347         (r_ != 0 || g_ != 0 || b_ != 0) ?
00348         adjust_surface_color(src, r_, g_, b_) :
00349         src
00350     );
00351 }
00352 
00353 int cs_modification::get_r() const
00354 {
00355     return r_;
00356 }
00357 
00358 int cs_modification::get_g() const
00359 {
00360     return g_;
00361 }
00362 
00363 int cs_modification::get_b() const
00364 {
00365     return b_;
00366 }
00367 
00368 surface blend_modification::operator()(const surface& src) const
00369 {
00370     return blend_surface(src, a_, display::rgb(r_, g_, b_));
00371 
00372 }
00373 
00374 int blend_modification::get_r() const
00375 {
00376     return r_;
00377 }
00378 
00379 int blend_modification::get_g() const
00380 {
00381     return g_;
00382 }
00383 
00384 int blend_modification::get_b() const
00385 {
00386     return b_;
00387 }
00388 
00389 float blend_modification::get_a() const
00390 {
00391     return a_;
00392 }
00393 
00394 surface bl_modification::operator()(const surface& src) const
00395 {
00396     return blur_alpha_surface(src, depth_);
00397 }
00398 
00399 int bl_modification::get_depth() const
00400 {
00401     return depth_;
00402 }
00403 
00404 surface brighten_modification::operator()(const surface &src) const
00405 {
00406     surface ret = make_neutral_surface(src);
00407     surface tod_bright(image::get_image(game_config::images::tod_bright));
00408     if (tod_bright)
00409         blit_surface(tod_bright, NULL, ret, NULL);
00410     return ret;
00411 }
00412 
00413 surface darken_modification::operator()(const surface &src) const
00414 {
00415     surface ret = make_neutral_surface(src);
00416     surface tod_dark(image::get_image(game_config::images::tod_dark));
00417     if (tod_dark)
00418         blit_surface(tod_dark, NULL, ret, NULL);
00419     return ret;
00420 }
00421 
00422 surface background_modification::operator()(const surface &src) const
00423 {
00424     surface ret = make_neutral_surface(src);
00425     SDL_FillRect(ret, NULL, SDL_MapRGBA(ret->format, color_.r, color_.g,
00426                         color_.b, color_.unused));
00427     SDL_SetAlpha(src, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
00428     SDL_BlitSurface(src, NULL, ret, NULL);
00429     return ret;
00430 }
00431 
00432 const SDL_Color& background_modification::get_color() const
00433 {
00434     return color_;
00435 }
00436 
00437 namespace {
00438 
00439 /** A macro for automatic modification parser registration
00440  *
00441  * It automatically registers the created parser in the mod_parsers map
00442  * It should be used just like a function header (look at the uses below)
00443  * It should only be used within an anonymous namespace
00444  *
00445  * @param type The modification type to be registered (unquoted)
00446  * @param args_var The name for the string argument provided
00447  */
00448 #define REGISTER_MOD_PARSER(type, args_var)                        \
00449     modification* parse_##type##_mod(const std::string&);          \
00450     struct parse_##type##_mod_registration                         \
00451     {                                                              \
00452             parse_##type##_mod_registration()                      \
00453             {                                                      \
00454             mod_parsers[#type] = &parse_##type##_mod;      \
00455                 }                                                      \
00456         } parse_##type##_mod_registration_aux;                         \
00457         modification* parse_##type##_mod(const std::string& args_var)
00458 
00459 // Color-range-based recoloring
00460 REGISTER_MOD_PARSER(TC, args)
00461 {
00462     std::vector<std::string> params = utils::split(args,',');
00463 
00464     if(params.size() < 2) {
00465         ERR_DP << "too few arguments passed to the ~TC() function\n";
00466 
00467         return NULL;
00468     }
00469 
00470     int side_n = lexical_cast_default<int>(params[0], -1);
00471     std::string team_color;
00472     if (side_n < 1) {
00473         ERR_DP << "invalid team (" << side_n
00474                << ") passed to the ~TC() function\n";
00475         return NULL;
00476     }
00477     else if (side_n < static_cast<int>(image::get_team_colors().size())) {
00478         team_color = image::get_team_colors()[side_n - 1];
00479     }
00480     else {
00481         // This side is not initialized; use default "n"
00482         try {
00483             team_color = lexical_cast<std::string>(side_n);
00484         } catch(bad_lexical_cast const&) {
00485             ERR_DP << "bad things happen\n";
00486 
00487             return NULL;
00488         }
00489     }
00490 
00491     //
00492     // Pass argseters for RC functor
00493     //
00494     if(!game_config::tc_info(params[1]).size()){
00495         ERR_DP << "could not load TC info for '" << params[1]
00496                << "' palette\n"
00497                << "bailing out from TC\n";
00498 
00499         return NULL;
00500     }
00501 
00502     std::map<Uint32, Uint32> rc_map;
00503     try {
00504         color_range const& new_color =
00505             game_config::color_info(team_color);
00506         std::vector<Uint32> const& old_color =
00507             game_config::tc_info(params[1]);
00508 
00509         rc_map = recolor_range(new_color,old_color);
00510     }
00511     catch(config::error const& e) {
00512         ERR_DP << "caught config::error while processing TC: "
00513                << e.message
00514                << '\n'
00515                << "bailing out from TC\n";
00516 
00517         return NULL;
00518     }
00519 
00520     return new rc_modification(rc_map);
00521 }
00522 
00523 // Team-color-based color range selection and recoloring
00524 REGISTER_MOD_PARSER(RC, args)
00525 {
00526     const std::vector<std::string> recolor_params = utils::split(args,'>');
00527 
00528     if(recolor_params.size()>1){
00529         //
00530         // recolor source palette to color range
00531         //
00532         std::map<Uint32, Uint32> rc_map;
00533         try {
00534             color_range const& new_color =
00535                 game_config::color_info(recolor_params[1]);
00536             std::vector<Uint32> const& old_color =
00537                 game_config::tc_info(recolor_params[0]);
00538 
00539             rc_map = recolor_range(new_color,old_color);
00540         }
00541         catch (config::error& e) {
00542             ERR_DP
00543                 << "caught config::error while processing color-range RC: "
00544                 << e.message
00545                 << '\n';
00546             ERR_DP
00547                 << "bailing out from RC\n";
00548             rc_map.clear();
00549         }
00550 
00551         return new rc_modification(rc_map);
00552     }
00553     else {
00554         ///@Deprecated 1.6 palette switch syntax
00555         if(args.find('=') != std::string::npos) {
00556             lg::wml_error << "the ~RC() image function cannot be used for palette switch (A=B) in 1.7.x; use ~PAL(A>B) instead\n";
00557         }
00558     }
00559 
00560     return NULL;
00561 }
00562 
00563 // Palette switch
00564 REGISTER_MOD_PARSER(PAL, args)
00565 {
00566     const std::vector<std::string> remap_params = utils::split(args,'>');
00567 
00568     if(remap_params.size() < 2) {
00569         ERR_DP << "not enough arguments passed to the ~PAL() function: "
00570                << args << "\n";
00571 
00572         return NULL;
00573     }
00574 
00575 
00576     try {
00577         std::map<Uint32, Uint32> rc_map;
00578         std::vector<Uint32> const& old_palette =
00579             game_config::tc_info(remap_params[0]);
00580         std::vector<Uint32> const& new_palette =
00581             game_config::tc_info(remap_params[1]);
00582 
00583         for(size_t i = 0; i < old_palette.size() && i < new_palette.size(); ++i) {
00584             rc_map[old_palette[i]] = new_palette[i];
00585         }
00586 
00587         return new rc_modification(rc_map);
00588     }
00589     catch(config::error& e) {
00590         ERR_DP
00591             << "caught config::error while processing PAL function: "
00592             << e.message
00593             << '\n';
00594         ERR_DP
00595             << "bailing out from PAL\n";
00596 
00597         return NULL;
00598     }
00599 }
00600 
00601 // Flip/flop
00602 REGISTER_MOD_PARSER(FL, args)
00603 {
00604     bool horiz = (args.empty() || args.find("horiz") != std::string::npos);
00605     bool vert = (args.find("vert") != std::string::npos);
00606 
00607     return new fl_modification(horiz, vert);
00608 }
00609 
00610 // Rotations
00611 REGISTER_MOD_PARSER(ROTATE, args)
00612 {
00613     return new rotate_modification(lexical_cast_default<int>(args, 90));
00614 }
00615 
00616 // Grayscale
00617 REGISTER_MOD_PARSER(GS, )
00618 {
00619     return new gs_modification;
00620 }
00621 
00622 // Color-shift
00623 REGISTER_MOD_PARSER(CS, args)
00624 {
00625     std::vector<std::string> const factors = utils::split(args, ',');
00626     const size_t s = factors.size();
00627 
00628     if(s == 0) {
00629         ERR_DP << "no arguments passed to the ~CS() function\n";
00630         return NULL;
00631     }
00632 
00633     int r = 0, g = 0, b = 0;
00634 
00635     r = lexical_cast_default<int>(factors[0]);
00636 
00637     if( s > 1 ) {
00638         g = lexical_cast_default<int>(factors[1]);
00639     }
00640     if( s > 2 ) {
00641         b = lexical_cast_default<int>(factors[2]);
00642     }
00643 
00644     return new cs_modification(r, g, b);
00645 }
00646 
00647 // Color blending
00648 REGISTER_MOD_PARSER(BLEND, args)
00649 {
00650     const std::vector<std::string>& params = utils::split(args, ',');
00651 
00652     if(params.size() != 4) {
00653         ERR_DP << "~BLEND() requires exactly 4 arguments\n";
00654         return NULL;
00655     }
00656 
00657     float opacity = 0.0f;
00658     const std::string& opacity_str = params[3];
00659     const std::string::size_type p100_pos = opacity_str.find('%');
00660 
00661     if(p100_pos == std::string::npos)
00662         opacity = lexical_cast_default<float>(opacity_str);
00663     else {
00664         // make multiplier
00665         const std::string& parsed_field = opacity_str.substr(0, p100_pos);
00666         opacity = lexical_cast_default<float>(parsed_field);
00667         opacity /= 100.0f;
00668     }
00669 
00670     return new blend_modification(
00671         lexical_cast_default<int>(params[0]),
00672         lexical_cast_default<int>(params[1]),
00673         lexical_cast_default<int>(params[2]),
00674         opacity);
00675 }
00676 
00677 // Crop/slice
00678 REGISTER_MOD_PARSER(CROP, args)
00679 {
00680     std::vector<std::string> const& slice_params = utils::split(args, ',', utils::STRIP_SPACES);
00681     const size_t s = slice_params.size();
00682 
00683     if(s == 0 || (s == 1 && slice_params[0].empty())) {
00684         ERR_DP << "no arguments passed to the ~CROP() function\n";
00685         return NULL;
00686     }
00687 
00688     SDL_Rect slice_rect = { 0, 0, 0, 0 };
00689 
00690     slice_rect.x = lexical_cast_default<Sint16, const std::string&>(slice_params[0]);
00691 
00692     if(s > 1) {
00693         slice_rect.y = lexical_cast_default<Sint16, const std::string&>(slice_params[1]);
00694     }
00695     if(s > 2) {
00696         slice_rect.w = lexical_cast_default<Uint16, const std::string&>(slice_params[2]);
00697     }
00698     if(s > 3) {
00699         slice_rect.h = lexical_cast_default<Uint16, const std::string&>(slice_params[3]);
00700     }
00701 
00702     return new crop_modification(slice_rect);
00703 }
00704 
00705 static bool check_image(const image::locator& img, std::stringstream & message)
00706 {
00707     if(img.file_exists()) return true;
00708     message << " image not found: '" << img.get_filename() << "'\n";
00709     ERR_DP << message.str();
00710     return false;
00711 }
00712 
00713 // Blit
00714 REGISTER_MOD_PARSER(BLIT, args)
00715 {
00716     std::vector<std::string> param = utils::parenthetical_split(args, ',');
00717     const size_t s = param.size();
00718 
00719     if(s == 0 || (s == 1 && param[0].empty())){
00720         ERR_DP << "no arguments passed to the ~BLIT() function\n";
00721         return NULL;
00722     }
00723 
00724     int x = 0, y = 0;
00725 
00726     if(s == 3) {
00727         x = lexical_cast_default<int>(param[1]);
00728         y = lexical_cast_default<int>(param[2]);
00729     }
00730 
00731     if(x < 0 || y < 0) { //required by blit_surface
00732         ERR_DP << "negative position arguments in ~BLIT() function\n";
00733         return NULL;
00734     }
00735 
00736     const image::locator img(param[0]);
00737     std::stringstream message;
00738     message << "~BLIT():";
00739     if(!check_image(img, message))
00740         return NULL;
00741     surface surf = get_image(img);
00742 
00743     return new blit_modification(surf, x, y);
00744 }
00745 
00746 // Mask
00747 REGISTER_MOD_PARSER(MASK, args)
00748 {
00749     std::vector<std::string> param = utils::parenthetical_split(args, ',');
00750     const size_t s = param.size();
00751 
00752     if(s == 0 || (s == 1 && param[0].empty())){
00753         ERR_DP << "no arguments passed to the ~MASK() function\n";
00754         return NULL;
00755     }
00756 
00757     int x = 0, y = 0;
00758 
00759     if(s == 3) {
00760         x = lexical_cast_default<int>(param[1]);
00761         y = lexical_cast_default<int>(param[2]);
00762     }
00763 
00764     if(x < 0 || y < 0) { //required by blit_surface
00765         ERR_DP << "negative position arguments in ~MASK() function\n";
00766         return NULL;
00767     }
00768 
00769     const image::locator img(param[0]);
00770     std::stringstream message;
00771     message << "~MASK():";
00772     if(!check_image(img, message))
00773         return NULL;
00774     surface surf = get_image(img);
00775 
00776     return new mask_modification(surf, x, y);
00777 }
00778 
00779 // Light
00780 REGISTER_MOD_PARSER(L, args)
00781 {
00782     if(args.empty()){
00783         ERR_DP << "no arguments passed to the ~L() function\n";
00784         return NULL;
00785     }
00786 
00787     surface surf = get_image(args);
00788 
00789     return new light_modification(surf);
00790 }
00791 
00792 // Scale
00793 REGISTER_MOD_PARSER(SCALE, args)
00794 {
00795     std::vector<std::string> const& scale_params = utils::split(args, ',', utils::STRIP_SPACES);
00796     const size_t s = scale_params.size();
00797 
00798     if(s == 0 || (s == 1 && scale_params[0].empty())) {
00799         ERR_DP << "no arguments passed to the ~SCALE() function\n";
00800         return NULL;
00801     }
00802 
00803     int w = 0, h = 0;
00804 
00805     w = lexical_cast_default<int, const std::string&>(scale_params[0]);
00806 
00807     if(s > 1) {
00808         h = lexical_cast_default<int, const std::string&>(scale_params[1]);
00809     }
00810 
00811     return new scale_modification(w, h);
00812 }
00813 
00814 // Gaussian-like blur
00815 REGISTER_MOD_PARSER(BL, args)
00816 {
00817     const int depth = std::max<int>(0, lexical_cast_default<int>(args));
00818 
00819     return new bl_modification(depth);
00820 }
00821 
00822 // Opacity-shift
00823 REGISTER_MOD_PARSER(O, args)
00824 {
00825     const std::string::size_type p100_pos = args.find('%');
00826     float num = 0.0f;
00827     if(p100_pos == std::string::npos)
00828         num = lexical_cast_default<float,const std::string&>(args);
00829     else {
00830         // make multiplier
00831         const std::string parsed_field = args.substr(0, p100_pos);
00832         num = lexical_cast_default<float,const std::string&>(parsed_field);
00833         num /= 100.0f;
00834     }
00835 
00836     return new o_modification(num);
00837 }
00838 
00839 //
00840 // ~R(), ~G() and ~B() are the children of ~CS(). Merely syntatic sugar.
00841 // Hence they are at the end of the evaluation.
00842 //
00843 // Red component color-shift
00844 REGISTER_MOD_PARSER(R, args)
00845 {
00846     const int r = lexical_cast_default<int>(args);
00847 
00848     return new cs_modification(r,0,0);
00849 }
00850 
00851 // Green component color-shift
00852 REGISTER_MOD_PARSER(G, args)
00853 {
00854     const int g = lexical_cast_default<int>(args);
00855 
00856     return new cs_modification(0,g,0);
00857 }
00858 
00859 // Blue component color-shift
00860 REGISTER_MOD_PARSER(B, args)
00861 {
00862     const int b = lexical_cast_default<int>(args);
00863 
00864     return new cs_modification(0,0,b);
00865 }
00866 
00867 REGISTER_MOD_PARSER(NOP, )
00868 {
00869     return NULL;
00870 }
00871 
00872 // Fake image function used by GUI2 portraits until
00873 // Mordante gets rid of it. *tsk* *tsk*
00874 REGISTER_MOD_PARSER(RIGHT, )
00875 {
00876     return NULL;
00877 }
00878 
00879 // Add a bright overlay.
00880 REGISTER_MOD_PARSER(BRIGHTEN, )
00881 {
00882     return new brighten_modification;
00883 }
00884 
00885 // Add a dark overlay.
00886 REGISTER_MOD_PARSER(DARKEN, )
00887 {
00888     return new darken_modification;
00889 }
00890 
00891 // Add a background color.
00892 REGISTER_MOD_PARSER(BG, args)
00893 {
00894     int c[4] = { 0, 0, 0, 255 };
00895     std::vector<std::string> factors = utils::split(args, ',');
00896 
00897     for (int i = 0; i < std::min<int>(factors.size(), 4); ++i) {
00898         c[i] = lexical_cast_default<int>(factors[i]);
00899     }
00900 
00901     return new background_modification(create_color(c[0], c[1], c[2], c[3]));
00902 }
00903 
00904 } // end anon namespace
00905 
00906 } /* end namespace image */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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