diff --git a/src/image_modifications.cpp b/src/image_modifications.cpp index 8fa83b3a7d8e..c5961b0943c3 100644 --- a/src/image_modifications.cpp +++ b/src/image_modifications.cpp @@ -12,36 +12,33 @@ See the COPYING file for more details. */ -#include "color_range.hpp" +#include "image_modifications.hpp" + +#include "color.hpp" #include "config.hpp" -#include "display.hpp" #include "game_config.hpp" #include "image.hpp" -#include "image_modifications.hpp" +#include "lexical_cast.hpp" #include "log.hpp" -#include "color.hpp" #include "serialization/string_utils.hpp" #include "formula/formula.hpp" #include "formula/callable.hpp" -#include - #define GETTEXT_DOMAIN "wesnoth-lib" static lg::log_domain log_display("display"); #define ERR_DP LOG_STREAM(err, log_display) -#define LOG_DP LOG_STREAM(info, log_display) namespace image { - /** Adds @a mod to the queue (unless mod is nullptr). */ void modification_queue::push(modification * mod) { // Null pointers do not get stored. (Shouldn't happen, but just in case.) - if ( mod != nullptr ) + if(mod != nullptr) { priorities_[mod->priority()].push_back(mod); + } } /** Removes the top element from the queue */ @@ -52,17 +49,20 @@ void modification_queue::pop() // Erase the top element. top_vector.erase(top_vector.begin()); - if ( top_vector.empty() ) + if(top_vector.empty()) { // We need to keep the map clean. priorities_.erase(top_pair); + } } /** Returns the number of elements in the queue. */ size_t modification_queue::size() const { size_t count = 0; - for (const map_type::value_type & pair : priorities_) + for(const map_type::value_type& pair : priorities_) { count += pair.second.size(); + } + return count; } @@ -97,8 +97,7 @@ modification* decode_modification(const std::string& encoded_mod) std::vector split = utils::parenthetical_split(encoded_mod); if(split.size() != 2) { - ERR_DP << "error parsing image modifications: " - << encoded_mod << "\n"; + ERR_DP << "error parsing image modifications: " << encoded_mod << "\n"; return nullptr; } @@ -106,13 +105,13 @@ modification* decode_modification(const std::string& encoded_mod) std::string args = split[1]; if(mod_parsers.find(mod_type) == mod_parsers.end()) { - ERR_DP << "unknown image function in path: " - << mod_type << '\n'; + ERR_DP << "unknown image function in path: " << mod_type << '\n'; return nullptr; } return (*mod_parsers[mod_type])(args); } + } // end anon namespace @@ -122,7 +121,7 @@ modification::imod_exception::imod_exception(const std::stringstream& message_st } modification::imod_exception::imod_exception(const std::string& message) - : message(message) + : message(message) { } @@ -160,16 +159,12 @@ surface fl_modification::operator()(const surface& src) const { surface ret = src; - if ( horiz_ && vert_ ) { + if(horiz_ && vert_ ) { // Slightly faster than doing both a flip and a flop. ret = rotate_180_surface(ret); - } - - else if(horiz_) { + } else if(horiz_) { ret = flip_surface(ret); - } - - else if(vert_) { + } else if(vert_) { ret = flop_surface(ret); } @@ -180,8 +175,8 @@ surface rotate_modification::operator()(const surface& src) const { // Convert the number of degrees to the interval [0,360]. const int normalized = degrees_ >= 0 ? - degrees_ - 360*(degrees_/360) : - degrees_ + 360*(1 + (-degrees_)/360); // In case compilers disagree as to what -90/360 is. + degrees_ - 360 * (degrees_ / 360) : + degrees_ + 360 * (1 + (-degrees_) / 360); // In case compilers disagree as to what -90/360 is. switch ( normalized ) { @@ -226,20 +221,27 @@ surface wipe_alpha_modification::operator()(const surface& src) const } // TODO: Is this useful enough to move into formula/callable_objects? -class pixel_callable : public game_logic::formula_callable { +class pixel_callable : public game_logic::formula_callable +{ public: - pixel_callable(SDL_Point p, color_t clr, Uint32 w, Uint32 h) : p(p), clr(clr), w(w), h(h) {} - void get_inputs(std::vector* inputs) const override { - inputs->push_back(game_logic::formula_input("x", game_logic::FORMULA_READ_ONLY)); - inputs->push_back(game_logic::formula_input("y", game_logic::FORMULA_READ_ONLY)); - inputs->push_back(game_logic::formula_input("red", game_logic::FORMULA_READ_ONLY)); - inputs->push_back(game_logic::formula_input("green", game_logic::FORMULA_READ_ONLY)); - inputs->push_back(game_logic::formula_input("blue", game_logic::FORMULA_READ_ONLY)); - inputs->push_back(game_logic::formula_input("alpha", game_logic::FORMULA_READ_ONLY)); + pixel_callable(SDL_Point p, color_t clr, Uint32 w, Uint32 h) + : p(p), clr(clr), w(w), h(h) + {} + + void get_inputs(std::vector* inputs) const override + { + inputs->push_back(game_logic::formula_input("x", game_logic::FORMULA_READ_ONLY)); + inputs->push_back(game_logic::formula_input("y", game_logic::FORMULA_READ_ONLY)); + inputs->push_back(game_logic::formula_input("red", game_logic::FORMULA_READ_ONLY)); + inputs->push_back(game_logic::formula_input("green", game_logic::FORMULA_READ_ONLY)); + inputs->push_back(game_logic::formula_input("blue", game_logic::FORMULA_READ_ONLY)); + inputs->push_back(game_logic::formula_input("alpha", game_logic::FORMULA_READ_ONLY)); inputs->push_back(game_logic::formula_input("height", game_logic::FORMULA_READ_ONLY)); - inputs->push_back(game_logic::formula_input("width", game_logic::FORMULA_READ_ONLY)); + inputs->push_back(game_logic::formula_input("width", game_logic::FORMULA_READ_ONLY)); } - variant get_value(const std::string& key) const override { + + variant get_value(const std::string& key) const override + { if(key == "x") { return variant(p.x); } else if(key == "y") { @@ -257,8 +259,10 @@ class pixel_callable : public game_logic::formula_callable { } else if(key == "height") { return variant(h); } + return variant(); } + private: SDL_Point p; color_t clr; @@ -285,8 +289,8 @@ surface adjust_alpha_modification::operator()(const surface & src) const { surface_lock lock(nsurf); Uint32* cur = lock.pixels(); - Uint32*const end = cur + nsurf->w * src->h; - Uint32*const beg = cur; + Uint32* const end = cur + nsurf->w * src->h; + Uint32* const beg = cur; while(cur != end) { color_t pixel; @@ -334,8 +338,8 @@ surface adjust_channels_modification::operator()(const surface & src) const { surface_lock lock(nsurf); Uint32* cur = lock.pixels(); - Uint32*const end = cur + nsurf->w * src->h; - Uint32*const beg = cur; + Uint32* const end = cur + nsurf->w * src->h; + Uint32* const beg = cur; while(cur != end) { color_t pixel; @@ -369,6 +373,7 @@ surface crop_modification::operator()(const surface& src) const if(area.w == 0) { area.w = src->w; } + if(area.h == 0) { area.h = src->h; } @@ -426,16 +431,18 @@ surface blit_modification::operator()(const surface& src) const surface nsrc = make_neutral_surface(src); surface nsurf = make_neutral_surface(surf_); - SDL_Rect r = sdl::create_rect(x_, y_, 0, 0); + SDL_Rect r = {x_, y_, 0, 0}; sdl_blit(nsurf, nullptr, nsrc, &r); return nsrc; } surface mask_modification::operator()(const surface& src) const { - if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) + if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) { return mask_surface(src, mask_); - SDL_Rect r = sdl::create_rect(x_, y_, 0, 0); + } + + SDL_Rect r = {x_, y_, 0, 0}; surface new_mask = create_neutral_surface(src->w, src->h); sdl_blit(mask_, nullptr, new_mask, &r); return mask_surface(src, new_mask); @@ -444,12 +451,14 @@ surface mask_modification::operator()(const surface& src) const surface light_modification::operator()(const surface& src) const { if(src == nullptr) { return nullptr; } - //light_surface wants a neutral surface having same dimensions + // light_surface wants a neutral surface having same dimensions surface nsurf; - if(surf_->w != src->w || surf_->h != src->h) + if(surf_->w != src->w || surf_->h != src->h) { nsurf = scale_surface(surf_, src->w, src->h, false); - else + } else { nsurf = make_neutral_surface(surf_); + } + return light_surface(src, nsurf);; } @@ -477,6 +486,7 @@ std::pair scale_exact_modification::calculate_size(const surface& src) } w = old_w; } + if(h <= 0) { if(h < 0) { ERR_DP << "height of " << fn_ << " is negative - resetting to original height" << std::endl; @@ -484,7 +494,7 @@ std::pair scale_exact_modification::calculate_size(const surface& src) h = old_h; } - return std::make_pair(w, h); + return {w, h}; } std::pair scale_into_modification::calculate_size(const surface& src) const @@ -500,6 +510,7 @@ std::pair scale_into_modification::calculate_size(const surface& src) c } w = old_w; } + if(h <= 0) { if(h < 0) { ERR_DP << "height of SCALE_INTO is negative - resetting to original height" << std::endl; @@ -509,12 +520,12 @@ std::pair scale_into_modification::calculate_size(const surface& src) c long double ratio = std::min(w / old_w, h / old_h); - return std::make_pair(old_w * ratio, old_h * ratio); + return {old_w * ratio, old_h * ratio}; } surface xbrz_modification::operator()(const surface& src) const { - if (z_ == 1) { + if(z_ == 1) { return src; } @@ -539,7 +550,7 @@ surface o_modification::operator()(const surface& src) const { surface_lock lock(nsurf); Uint32* beg = lock.pixels(); - Uint32* end = beg + nsurf->w*src->h; + Uint32* end = beg + nsurf->w * src->h; while(beg != end) { Uint8 alpha = (*beg) >> 24; @@ -550,7 +561,7 @@ surface o_modification::operator()(const surface& src) const g = (*beg) >> 8; b = (*beg); - alpha = std::min(unsigned(fxpmult(alpha,amount)),255); + alpha = std::min(unsigned(fxpmult(alpha,amount)), 255); *beg = (alpha << 24) + (r << 16) + (g << 8) + b; } @@ -563,10 +574,9 @@ surface o_modification::operator()(const surface& src) const surface cs_modification::operator()(const surface& src) const { - return( - (r_ != 0 || g_ != 0 || b_ != 0) ? - adjust_surface_color(src, r_, g_, b_) : - src + return((r_ != 0 || g_ != 0 || b_ != 0) + ? adjust_surface_color(src, r_, g_, b_) + : src ); } @@ -591,7 +601,6 @@ surface background_modification::operator()(const surface &src) const return ret; } - surface swap_modification::operator()(const surface &src) const { return swap_channels_image(src, red_, green_, blue_, alpha_); @@ -634,15 +643,13 @@ REGISTER_MOD_PARSER(TC, args) int side_n = lexical_cast_default(params[0], -1); std::string team_color; - if (side_n < 1) { + if(side_n < 1) { ERR_DP << "invalid team (" << side_n << ") passed to the ~TC() function\n"; return nullptr; - } - else if (side_n <= static_cast(image::get_team_colors().size())) { + } else if(side_n <= static_cast(image::get_team_colors().size())) { team_color = image::get_team_colors()[side_n - 1]; - } - else { + } else { // This side is not initialized; use default "n" try { team_color = std::to_string(side_n); @@ -670,8 +677,7 @@ REGISTER_MOD_PARSER(TC, args) const std::vector& old_color = game_config::tc_info(params[1]); rc_map = recolor_range(new_color,old_color); - } - catch(config::error const& e) { + } catch(config::error const& e) { ERR_DP << "caught config::error while processing TC: " << e.message << '\n' @@ -688,31 +694,30 @@ REGISTER_MOD_PARSER(RC, args) { const std::vector recolor_params = utils::split(args,'>'); - if(recolor_params.size()>1){ - // - // recolor source palette to color range - // - color_range_map rc_map; - try { - const color_range& new_color = game_config::color_info(recolor_params[1]); - const std::vector& old_color = game_config::tc_info(recolor_params[0]); + if(recolor_params.size() <= 1) { + return nullptr; + } - rc_map = recolor_range(new_color,old_color); - } - catch (config::error& e) { - ERR_DP - << "caught config::error while processing color-range RC: " - << e.message - << '\n'; - ERR_DP - << "bailing out from RC\n"; - rc_map.clear(); - } + // + // recolor source palette to color range + // + color_range_map rc_map; + try { + const color_range& new_color = game_config::color_info(recolor_params[1]); + const std::vector& old_color = game_config::tc_info(recolor_params[0]); - return new rc_modification(rc_map); + rc_map = recolor_range(new_color,old_color); + } catch (config::error& e) { + ERR_DP + << "caught config::error while processing color-range RC: " + << e.message + << '\n'; + ERR_DP + << "bailing out from RC\n"; + rc_map.clear(); } - return nullptr; + return new rc_modification(rc_map); } // Palette switch @@ -721,13 +726,11 @@ REGISTER_MOD_PARSER(PAL, args) const std::vector remap_params = utils::split(args,'>'); if(remap_params.size() < 2) { - ERR_DP << "not enough arguments passed to the ~PAL() function: " - << args << "\n"; + ERR_DP << "not enough arguments passed to the ~PAL() function: " << args << "\n"; return nullptr; } - try { color_range_map rc_map; const std::vector& old_palette = game_config::tc_info(remap_params[0]); @@ -738,8 +741,7 @@ REGISTER_MOD_PARSER(PAL, args) } return new rc_modification(rc_map); - } - catch(config::error& e) { + } catch(config::error& e) { ERR_DP << "caught config::error while processing PAL function: " << e.message @@ -766,24 +768,24 @@ REGISTER_MOD_PARSER(ROTATE, args) std::vector const& slice_params = utils::split(args, ',', utils::STRIP_SPACES); const size_t s = slice_params.size(); - switch (s) { + switch(s) { case 0: return new rotate_modification(); break; case 1: return new rotate_modification( - lexical_cast_default(slice_params[0])); + lexical_cast_default(slice_params[0])); break; case 2: return new rotate_modification( - lexical_cast_default(slice_params[0]), - lexical_cast_default(slice_params[1])); + lexical_cast_default(slice_params[0]), + lexical_cast_default(slice_params[1])); break; case 3: return new rotate_modification( - lexical_cast_default(slice_params[0]), - lexical_cast_default(slice_params[1]), - lexical_cast_default(slice_params[2])); + lexical_cast_default(slice_params[0]), + lexical_cast_default(slice_params[1]), + lexical_cast_default(slice_params[2])); break; } return nullptr; @@ -799,24 +801,22 @@ REGISTER_MOD_PARSER(GS, ) REGISTER_MOD_PARSER(BW, args) { const std::vector& params = utils::split(args, ','); - if (params.size() == 1) { - try { - int threshold = std::stoi(params[0]); - if (threshold < 0 || threshold > 255) { - ERR_DP << "~BW() argument out of range 0 - 255" << std::endl; - return nullptr; - } - else { - return new bw_modification(threshold); - } - } - catch (std::invalid_argument) { - ERR_DP << "unsupported argument in ~BW() function" << std::endl; + + if(params.size() != 1) { + ERR_DP << "~BW() requires exactly one argument" << std::endl; + return nullptr; + } + + try { + int threshold = std::stoi(params[0]); + if(threshold < 0 || threshold > 255) { + ERR_DP << "~BW() argument out of range 0 - 255" << std::endl; return nullptr; + } else { + return new bw_modification(threshold); } - } - else { - ERR_DP << "~BW() requires exactly one argument" << std::endl; + } catch (std::invalid_argument) { + ERR_DP << "unsupported argument in ~BW() function" << std::endl; return nullptr; } } @@ -842,15 +842,13 @@ REGISTER_MOD_PARSER(NEG, args) case 1: try { int threshold = std::stoi(params[0]); - if (threshold < -1 || threshold > 255) { + if(threshold < -1 || threshold > 255) { ERR_DP << "unsupported argument value in ~NEG() function" << std::endl; return nullptr; - } - else { + } else { return new negative_modification(threshold, threshold, threshold); } - } - catch (std::invalid_argument) { + } catch (std::invalid_argument) { ERR_DP << "unsupported argument value in ~NEG() function" << std::endl; return nullptr; } @@ -860,15 +858,13 @@ REGISTER_MOD_PARSER(NEG, args) int thresholdRed = std::stoi(params[0]); int thresholdGreen = std::stoi(params[1]); int thresholdBlue = std::stoi(params[2]); - if (thresholdRed < -1 || thresholdRed > 255 || thresholdGreen < -1 || thresholdGreen > 255 || thresholdBlue < -1 || thresholdBlue > 255) { + if(thresholdRed < -1 || thresholdRed > 255 || thresholdGreen < -1 || thresholdGreen > 255 || thresholdBlue < -1 || thresholdBlue > 255) { ERR_DP << "unsupported argument value in ~NEG() function" << std::endl; return nullptr; - } - else { + } else { return new negative_modification(thresholdRed, thresholdGreen, thresholdBlue); } - } - catch (std::invalid_argument) { + } catch (std::invalid_argument) { ERR_DP << "unsupported argument value in ~NEG() function" << std::endl; return nullptr; } @@ -938,10 +934,10 @@ REGISTER_MOD_PARSER(CS, args) r = lexical_cast_default(factors[0]); - if( s > 1 ) { + if(s > 1 ) { g = lexical_cast_default(factors[1]); } - if( s > 2 ) { + if(s > 2 ) { b = lexical_cast_default(factors[2]); } @@ -1182,7 +1178,7 @@ REGISTER_MOD_PARSER(SCALE_INTO_SHARP, args) REGISTER_MOD_PARSER(XBRZ, args) { int z = lexical_cast_default(args); - if (z < 1 || z > 5) { + if(z < 1 || z > 5) { z = 5; //only values 2 - 5 are permitted for xbrz scaling factors. } @@ -1204,9 +1200,9 @@ REGISTER_MOD_PARSER(O, args) { const std::string::size_type p100_pos = args.find('%'); float num = 0.0f; - if(p100_pos == std::string::npos) + if(p100_pos == std::string::npos) { num = lexical_cast_default(args); - else { + } else { // make multiplier const std::string parsed_field = args.substr(0, p100_pos); num = lexical_cast_default(parsed_field); @@ -1262,7 +1258,7 @@ REGISTER_MOD_PARSER(BG, args) int c[4] = { 0, 0, 0, SDL_ALPHA_OPAQUE }; std::vector factors = utils::split(args, ','); - for (int i = 0; i < std::min(factors.size(), 4); ++i) { + for(int i = 0; i < std::min(factors.size(), 4); ++i) { c[i] = lexical_cast_default(factors[i]); } @@ -1275,20 +1271,20 @@ REGISTER_MOD_PARSER(SWAP, args) std::vector params = utils::split(args, ',', utils::STRIP_SPACES); // accept 3 arguments (rgb) or 4 (rgba) - if (params.size() != 3 && params.size() != 4) { + if(params.size() != 3 && params.size() != 4) { ERR_DP << "incorrect number of arguments in ~SWAP() function, they must be 3 or 4" << std::endl; return nullptr; } channel redValue, greenValue, blueValue, alphaValue; // compare the parameter's value with the constants defined in the channels enum - if (params[0] == "red") { + if(params[0] == "red") { redValue = RED; - } else if (params[0] == "green") { + } else if(params[0] == "green") { redValue = GREEN; - } else if (params[0] == "blue") { + } else if(params[0] == "blue") { redValue = BLUE; - } else if (params[0] == "alpha") { + } else if(params[0] == "alpha") { redValue = ALPHA; } else { ERR_DP << "unsupported argument value in ~SWAP() function: " << params[0] << std::endl; @@ -1296,26 +1292,26 @@ REGISTER_MOD_PARSER(SWAP, args) } // wash, rinse and repeat for the other three channels - if (params[1] == "red") { + if(params[1] == "red") { greenValue = RED; - } else if (params[1] == "green") { + } else if(params[1] == "green") { greenValue = GREEN; - } else if (params[1] == "blue") { + } else if(params[1] == "blue") { greenValue = BLUE; - } else if (params[1] == "alpha") { + } else if(params[1] == "alpha") { greenValue = ALPHA; } else { ERR_DP << "unsupported argument value in ~SWAP() function: " << params[0] << std::endl; return nullptr; } - if (params[2] == "red") { + if(params[2] == "red") { blueValue = RED; - } else if (params[2] == "green") { + } else if(params[2] == "green") { blueValue = GREEN; - } else if (params[2] == "blue") { + } else if(params[2] == "blue") { blueValue = BLUE; - } else if (params[2] == "alpha") { + } else if(params[2] == "alpha") { blueValue = ALPHA; } else { ERR_DP << "unsupported argument value in ~SWAP() function: " << params[0] << std::endl; @@ -1324,17 +1320,16 @@ REGISTER_MOD_PARSER(SWAP, args) // additional check: the params vector may not have a fourth elementh // if so, default to the same channel - if (params.size() == 3) { + if(params.size() == 3) { alphaValue = ALPHA; - } - else { - if (params[3] == "red") { + } else { + if(params[3] == "red") { alphaValue = RED; - } else if (params[3] == "green") { + } else if(params[3] == "green") { alphaValue = GREEN; - } else if (params[3] == "blue") { + } else if(params[3] == "blue") { alphaValue = BLUE; - } else if (params[3] == "alpha") { + } else if(params[3] == "alpha") { alphaValue = ALPHA; } else { ERR_DP << "unsupported argument value in ~SWAP() function: " << params[3] << std::endl; diff --git a/src/image_modifications.hpp b/src/image_modifications.hpp index 0630c12740e3..4434d62ec5da 100644 --- a/src/image_modifications.hpp +++ b/src/image_modifications.hpp @@ -12,8 +12,6 @@ See the COPYING file for more details. */ -/** @file */ - #ifndef IMAGE_MODIFICATIONS_HPP_INCLUDED #define IMAGE_MODIFICATIONS_HPP_INCLUDED @@ -21,17 +19,19 @@ #include "lua_jailbreak_exception.hpp" #include "sdl/surface.hpp" #include "sdl/utils.hpp" + +#include #include namespace image { class modification; - /// A modified priority queue used to order image modifications. /// The priorities for this queue are to order modifications by priority(), /// then by the order they are added to the queue. -class modification_queue { +class modification_queue +{ // Invariant for this class: // At the beginning and end of each member function call, there // are no empty vectors in priorities_. @@ -49,14 +49,13 @@ class modification_queue { size_t size() const; modification * top() const; -private: // data +private: /// Map from a mod's priority() to the mods having that priority. typedef std::map, std::greater > map_type; /// Map from a mod's priority() to the mods having that priority. map_type priorities_; }; - /// Base abstract class for an image-path modification class modification { @@ -249,11 +248,11 @@ struct sepia_modification : modification */ class negative_modification : public modification { - public: - negative_modification(int r, int g, int b): red_(r), green_(g), blue_(b) {} - virtual surface operator()(const surface &src) const; - private: - int red_, green_, blue_; +public: + negative_modification(int r, int g, int b): red_(r), green_(g), blue_(b) {} + virtual surface operator()(const surface &src) const; +private: + int red_, green_, blue_; }; /**