29 #define GETTEXT_DOMAIN "wesnoth-lib" 32 #define ERR_DP LOG_STREAM(err, log_display) 49 auto& top_vector = top_pair->second;
52 top_vector.erase(top_vector.begin());
53 if(top_vector.empty()) {
62 std::size_t count = 0;
63 for(
const map_type::value_type& pair :
priorities_) {
64 count += pair.second.size();
80 using mod_parser = std::function<modification*(const std::string&)>;
87 std::map<std::string, mod_parser> mod_parsers;
96 modification* decode_modification(
const std::string& encoded_mod)
100 if(split.size() != 2) {
101 ERR_DP <<
"error parsing image modifications: " << encoded_mod <<
"\n";
105 std::string mod_type = split[0];
106 std::string args = split[1];
108 if(mod_parsers.find(mod_type) == mod_parsers.end()) {
109 ERR_DP <<
"unknown image function in path: " << mod_type <<
'\n';
113 return mod_parsers[mod_type](args);
120 : message(message_stream.str())
163 if(horiz_ && vert_ ) {
178 const int normalized = degrees_ >= 0 ?
179 degrees_ - 360 * (degrees_ / 360) :
180 degrees_ + 360 * (1 + (-degrees_) / 360);
182 switch ( normalized )
188 case 360:
return src;
229 : p(p), clr(clr), w(w), h(h)
234 add_input(inputs,
"x");
235 add_input(inputs,
"y");
236 add_input(inputs,
"u");
237 add_input(inputs,
"v");
238 add_input(inputs,
"red");
239 add_input(inputs,
"green");
240 add_input(inputs,
"blue");
241 add_input(inputs,
"alpha");
242 add_input(inputs,
"height");
243 add_input(inputs,
"width");
251 }
else if(key ==
"y") {
253 }
else if(key ==
"red") {
254 return variant(clr.r);
255 }
else if(key ==
"green") {
256 return variant(clr.g);
257 }
else if(key ==
"blue") {
258 return variant(clr.b);
259 }
else if(key ==
"alpha") {
260 return variant(clr.a);
261 }
else if(key ==
"width") {
263 }
else if(key ==
"height") {
265 }
else if(key ==
"u") {
266 return variant(
p.x / static_cast<float>(
w));
267 }
else if(key ==
"v") {
268 return variant(
p.y / static_cast<float>(
h));
290 if(nsurf ==
nullptr) {
291 std::cerr <<
"could not make neutral surface...\n";
297 uint32_t* cur = lock.
pixels();
298 uint32_t*
const end = cur + nsurf->w * src->h;
299 uint32_t*
const beg = cur;
303 pixel.
a = (*cur) >> 24;
304 pixel.
r = (*cur) >> 16;
305 pixel.
g = (*cur) >> 8;
315 *cur = (pixel.
a << 24) + (pixel.
r << 16) + (pixel.
g << 8) + pixel.
b;
337 if(nsurf ==
nullptr) {
338 std::cerr <<
"could not make neutral surface...\n";
344 uint32_t* cur = lock.
pixels();
345 uint32_t*
const end = cur + nsurf->w * src->h;
346 uint32_t*
const beg = cur;
350 pixel.
a = (*cur) >> 24;
351 pixel.
r = (*cur) >> 16;
352 pixel.
g = (*cur) >> 8;
365 *cur = (pixel.
a << 24) + (pixel.
r << 16) + (pixel.
g << 8) + pixel.
b;
376 SDL_Rect area = slice_;
399 std::stringstream sstr;
400 sstr <<
"~BLIT(): x-coordinate '" 401 << x_ <<
"' larger than destination image's width '" 402 << src->w <<
"' no blitting performed.\n";
408 std::stringstream sstr;
409 sstr <<
"~BLIT(): y-coordinate '" 410 << y_ <<
"' larger than destination image's height '" 411 << src->h <<
"' no blitting performed.\n";
416 if(surf_->w + x_ < 0) {
417 std::stringstream sstr;
418 sstr <<
"~BLIT(): offset and width '" 419 << x_ + surf_->w <<
"' less than zero no blitting performed.\n";
424 if(surf_->h + y_ < 0) {
425 std::stringstream sstr;
426 sstr <<
"~BLIT(): offset and height '" 427 << y_ + surf_->h <<
"' less than zero no blitting performed.\n";
433 SDL_Rect r {x_, y_, 0, 0};
440 if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) {
444 SDL_Rect r {x_, y_, 0, 0};
445 surface new_mask(src->w, src->h);
446 sdl_blit(mask_,
nullptr, new_mask, &r);
451 if(src ==
nullptr) {
return nullptr; }
455 if(surf_->w != src->w || surf_->h != src->h) {
466 std::pair<int,int> sz = calculate_size(src);
477 const int old_w = src->w;
478 const int old_h = src->h;
484 ERR_DP <<
"width of " << fn_ <<
" is negative - resetting to original width" << std::endl;
491 ERR_DP <<
"height of " << fn_ <<
" is negative - resetting to original height" << std::endl;
501 const int old_w = src->w;
502 const int old_h = src->h;
503 long double w = get_w();
504 long double h = get_h();
508 ERR_DP <<
"width of SCALE_INTO is negative - resetting to original width" << std::endl;
515 ERR_DP <<
"height of SCALE_INTO is negative - resetting to original height" << std::endl;
520 long double ratio = std::min(w / old_w, h / old_h);
522 return {
static_cast<int>(old_w * ratio), static_cast<int>(old_h * ratio)};
542 if(nsurf ==
nullptr) {
543 std::cerr <<
"could not make neutral surface...\n";
547 uint16_t amount =
ftofxp(opacity_);
551 uint32_t* beg = lock.
pixels();
552 uint32_t* end = beg + nsurf->w * src->h;
555 uint8_t alpha = (*beg) >> 24;
563 alpha = std::min<unsigned>(
static_cast<unsigned>(
fxpmult(alpha,amount)), 255);
564 *beg = (alpha << 24) + (r << 16) + (g << 8) + b;
576 return((r_ != 0 || g_ != 0 ||
b_ != 0)
595 SDL_FillRect(ret,
nullptr, SDL_MapRGBA(ret->format, color_.r, color_.g,
596 color_.b, color_.a));
597 sdl_blit(src,
nullptr, ret,
nullptr);
608 struct parse_mod_registration
610 parse_mod_registration(
const char* name, mod_parser parser)
612 mod_parsers[name] = parser;
625 #define REGISTER_MOD_PARSER(type, args_var) \ 626 static modification* parse_##type##_mod(const std::string&); \ 627 static parse_mod_registration parse_##type##_mod_registration_aux(#type, &parse_##type##_mod); \ 628 static modification* parse_##type##_mod(const std::string& args_var) \ 633 std::vector<std::string> params =
utils::split(args,
',');
635 if(params.size() < 2) {
636 ERR_DP <<
"too few arguments passed to the ~TC() function" << std::endl;
641 const int side_n = lexical_cast_default<int>(params[0], -1);
643 ERR_DP <<
"Invalid side (" << side_n <<
") passed to the ~TC() function\n";
651 ERR_DP <<
"could not load TC info for '" << params[1]
653 <<
"bailing out from TC\n";
665 ERR_DP <<
"caught config::error while processing TC: " 668 <<
"bailing out from TC\n";
673 return new rc_modification(rc_map);
679 const std::vector<std::string> recolor_params =
utils::split(args,
'>');
681 if(recolor_params.size() <= 1) {
696 <<
"caught config::error while processing color-range RC: " 700 <<
"bailing out from RC\n";
704 return new rc_modification(rc_map);
710 const std::vector<std::string> remap_params =
utils::split(args,
'>');
712 if(remap_params.size() < 2) {
713 ERR_DP <<
"not enough arguments passed to the ~PAL() function: " << args <<
"\n";
723 for(std::size_t
i = 0;
i < old_palette.size() &&
i < new_palette.size(); ++
i) {
724 rc_map[old_palette[
i]] = new_palette[
i];
727 return new rc_modification(rc_map);
730 <<
"caught config::error while processing PAL function: " 734 <<
"bailing out from PAL\n";
743 bool horiz = (args.empty() || args.find(
"horiz") != std::string::npos);
744 bool vert = (args.find(
"vert") != std::string::npos);
746 return new fl_modification(horiz, vert);
753 const std::size_t
s = slice_params.size();
757 return new rotate_modification();
760 return new rotate_modification(
761 lexical_cast_default<int>(slice_params[0]));
764 return new rotate_modification(
765 lexical_cast_default<int>(slice_params[0]),
766 lexical_cast_default<int>(slice_params[1]));
769 return new rotate_modification(
770 lexical_cast_default<int>(slice_params[0]),
771 lexical_cast_default<int>(slice_params[1]),
772 lexical_cast_default<int>(slice_params[2]));
781 return new gs_modification;
787 const std::vector<std::string>& params =
utils::split(args,
',');
789 if(params.size() != 1) {
790 ERR_DP <<
"~BW() requires exactly one argument" << std::endl;
795 int threshold = std::stoi(params[0]);
796 if(threshold < 0 || threshold > 255) {
797 ERR_DP <<
"~BW() argument out of range 0 - 255" << std::endl;
800 return new bw_modification(threshold);
802 }
catch (
const std::invalid_argument&) {
803 ERR_DP <<
"unsupported argument in ~BW() function" << std::endl;
811 return new sepia_modification;
817 const std::vector<std::string>& params =
utils::split(args,
',');
819 switch (params.size()) {
824 return new negative_modification(-1,-1,-1);
828 int threshold = std::stoi(params[0]);
829 if(threshold < -1 || threshold > 255) {
830 ERR_DP <<
"unsupported argument value in ~NEG() function" << std::endl;
833 return new negative_modification(threshold, threshold, threshold);
835 }
catch (
const std::invalid_argument&) {
836 ERR_DP <<
"unsupported argument value in ~NEG() function" << std::endl;
842 int thresholdRed = std::stoi(params[0]);
843 int thresholdGreen = std::stoi(params[1]);
844 int thresholdBlue = std::stoi(params[2]);
845 if(thresholdRed < -1 || thresholdRed > 255 || thresholdGreen < -1 || thresholdGreen > 255 || thresholdBlue < -1 || thresholdBlue > 255) {
846 ERR_DP <<
"unsupported argument value in ~NEG() function" << std::endl;
849 return new negative_modification(thresholdRed, thresholdGreen, thresholdBlue);
851 }
catch (
const std::invalid_argument&) {
852 ERR_DP <<
"unsupported argument value in ~NEG() function" << std::endl;
857 ERR_DP <<
"~NEG() requires 0, 1 or 3 arguments" << std::endl;
867 return new plot_alpha_modification;
873 return new wipe_alpha_modification;
883 if(params.size() != 1) {
884 ERR_DP <<
"~ADJUST_ALPHA() requires exactly 1 arguments" << std::endl;
888 return new adjust_alpha_modification(params.at(0));
898 if(params.size() < 1 || params.size() > 4) {
899 ERR_DP <<
"~CHAN() requires 1 to 4 arguments" << std::endl;
903 return new adjust_channels_modification(params);
909 std::vector<std::string>
const factors =
utils::split(args,
',');
910 const std::size_t
s = factors.size();
913 ERR_DP <<
"no arguments passed to the ~CS() function" << std::endl;
917 int r = 0,
g = 0,
b = 0;
919 r = lexical_cast_default<int>(factors[0]);
922 g = lexical_cast_default<int>(factors[1]);
925 b = lexical_cast_default<int>(factors[2]);
928 return new cs_modification(r,
g,
b);
934 const std::vector<std::string>& params =
utils::split(args,
',');
936 if(params.size() != 4) {
937 ERR_DP <<
"~BLEND() requires exactly 4 arguments" << std::endl;
941 float opacity = 0.0f;
942 const std::string& opacity_str = params[3];
943 const std::string::size_type p100_pos = opacity_str.find(
'%');
945 if(p100_pos == std::string::npos)
946 opacity = lexical_cast_default<float>(opacity_str);
949 const std::string& parsed_field = opacity_str.substr(0, p100_pos);
950 opacity = lexical_cast_default<float>(parsed_field);
954 return new blend_modification(
955 lexical_cast_default<int>(params[0]),
956 lexical_cast_default<int>(params[1]),
957 lexical_cast_default<int>(params[2]),
965 const std::size_t
s = slice_params.size();
967 if(s == 0 || (s == 1 && slice_params[0].empty())) {
968 ERR_DP <<
"no arguments passed to the ~CROP() function" << std::endl;
972 SDL_Rect slice_rect { 0, 0, 0, 0 };
974 slice_rect.x = lexical_cast_default<int16_t, const std::string&>(slice_params[0]);
977 slice_rect.y = lexical_cast_default<int16_t, const std::string&>(slice_params[1]);
980 slice_rect.w = lexical_cast_default<uint16_t, const std::string&>(slice_params[2]);
983 slice_rect.h = lexical_cast_default<uint16_t, const std::string&>(slice_params[3]);
986 return new crop_modification(slice_rect);
992 message <<
" image not found: '" << img.
get_filename() <<
"'\n";
1001 const std::size_t
s = param.size();
1003 if(s == 0 || (s == 1 && param[0].empty())){
1004 ERR_DP <<
"no arguments passed to the ~BLIT() function" << std::endl;
1009 ERR_DP <<
"too many arguments passed to the ~BLIT() function" << std::endl;
1016 x = lexical_cast_default<int>(param[1]);
1017 y = lexical_cast_default<int>(param[2]);
1022 message <<
"~BLIT():";
1023 if(!check_image(img, message))
1027 return new blit_modification(surf, x, y);
1034 const std::size_t
s = param.size();
1036 if(s == 0 || (s == 1 && param[0].empty())){
1037 ERR_DP <<
"no arguments passed to the ~MASK() function" << std::endl;
1044 x = lexical_cast_default<int>(param[1]);
1045 y = lexical_cast_default<int>(param[2]);
1048 if(x < 0 || y < 0) {
1049 ERR_DP <<
"negative position arguments in ~MASK() function" << std::endl;
1055 message <<
"~MASK():";
1056 if(!check_image(img, message))
1060 return new mask_modification(surf, x, y);
1067 ERR_DP <<
"no arguments passed to the ~L() function" << std::endl;
1073 return new light_modification(surf);
1080 const std::size_t
s = scale_params.size();
1082 if(s == 0 || (s == 1 && scale_params[0].empty())) {
1083 ERR_DP <<
"no arguments passed to the ~SCALE() function" << std::endl;
1089 w = lexical_cast_default<int, const std::string&>(scale_params[0]);
1092 h = lexical_cast_default<int, const std::string&>(scale_params[1]);
1095 return new scale_exact_modification(w,
h,
"SCALE",
false);
1101 const std::size_t
s = scale_params.size();
1103 if(s == 0 || (s == 1 && scale_params[0].empty())) {
1104 ERR_DP <<
"no arguments passed to the ~SCALE_SHARP() function" << std::endl;
1110 w = lexical_cast_default<int, const std::string&>(scale_params[0]);
1113 h = lexical_cast_default<int, const std::string&>(scale_params[1]);
1116 return new scale_exact_modification(w,
h,
"SCALE_SHARP",
true);
1122 const std::size_t
s = scale_params.size();
1124 if(s == 0 || (s == 1 && scale_params[0].empty())) {
1125 ERR_DP <<
"no arguments passed to the ~SCALE_INTO() function" << std::endl;
1131 w = lexical_cast_default<int, const std::string&>(scale_params[0]);
1134 h = lexical_cast_default<int, const std::string&>(scale_params[1]);
1137 return new scale_into_modification(w,
h,
"SCALE_INTO",
false);
1143 const std::size_t
s = scale_params.size();
1145 if(s == 0 || (s == 1 && scale_params[0].empty())) {
1146 ERR_DP <<
"no arguments passed to the ~SCALE_INTO_SHARP() function" << std::endl;
1152 w = lexical_cast_default<int, const std::string&>(scale_params[0]);
1155 h = lexical_cast_default<int, const std::string&>(scale_params[1]);
1158 return new scale_into_modification(w,
h,
"SCALE_INTO_SHARP",
true);
1164 int z = lexical_cast_default<int, const std::string &>(args);
1165 if(z < 1 || z > 5) {
1169 return new xbrz_modification(z);
1177 const int depth = std::max<int>(0, lexical_cast_default<int>(args));
1179 return new bl_modification(depth);
1185 const std::string::size_type p100_pos = args.find(
'%');
1187 if(p100_pos == std::string::npos) {
1188 num = lexical_cast_default<float,const std::string&>(args);
1191 const std::string parsed_field = args.substr(0, p100_pos);
1192 num = lexical_cast_default<float,const std::string&>(parsed_field);
1196 return new o_modification(num);
1206 const int r = lexical_cast_default<int>(args);
1208 return new cs_modification(r,0,0);
1214 const int g = lexical_cast_default<int>(args);
1216 return new cs_modification(0,g,0);
1222 const int b = lexical_cast_default<int>(args);
1224 return new cs_modification(0,0,b);
1248 int c[4] { 0, 0, 0, SDL_ALPHA_OPAQUE };
1249 std::vector<std::string> factors =
utils::split(args,
',');
1251 for(
int i = 0; i < std::min<int>(factors.size(), 4); ++
i) {
1252 c[
i] = lexical_cast_default<int>(factors[
i]);
1255 return new background_modification(
color_t(
c[0],
c[1],
c[2],
c[3]));
1264 if(params.size() != 3 && params.size() != 4) {
1265 ERR_DP <<
"incorrect number of arguments in ~SWAP() function, they must be 3 or 4" << std::endl;
1269 channel redValue, greenValue, blueValue, alphaValue;
1271 if(params[0] ==
"red") {
1273 }
else if(params[0] ==
"green") {
1275 }
else if(params[0] ==
"blue") {
1277 }
else if(params[0] ==
"alpha") {
1280 ERR_DP <<
"unsupported argument value in ~SWAP() function: " << params[0] << std::endl;
1285 if(params[1] ==
"red") {
1287 }
else if(params[1] ==
"green") {
1289 }
else if(params[1] ==
"blue") {
1291 }
else if(params[1] ==
"alpha") {
1294 ERR_DP <<
"unsupported argument value in ~SWAP() function: " << params[0] << std::endl;
1298 if(params[2] ==
"red") {
1300 }
else if(params[2] ==
"green") {
1302 }
else if(params[2] ==
"blue") {
1304 }
else if(params[2] ==
"alpha") {
1307 ERR_DP <<
"unsupported argument value in ~SWAP() function: " << params[0] << std::endl;
1313 if(params.size() == 3) {
1316 if(params[3] ==
"red") {
1318 }
else if(params[3] ==
"green") {
1320 }
else if(params[3] ==
"blue") {
1322 }
else if(params[3] ==
"alpha") {
1325 ERR_DP <<
"unsupported argument value in ~SWAP() function: " << params[3] << std::endl;
1330 return new swap_modification(redValue, greenValue, blueValue, alphaValue);
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
surface get_image(const image::locator &i_locator, TYPE type)
Caches and returns an image.
surface recolor_image(surface surf, const color_range_map &map_rgb)
Recolors a surface using a map with source and converted palette values.
surface negative_image(const surface &surf, const int thresholdR, const int thresholdG, const int thresholdB)
surface scale_surface_legacy(const surface &surf, int w, int h)
Scale a surface using simple bilinear filtering (discarding rgb from source pixels with 0 alpha) ...
void get_inputs(wfl::formula_input_vector &inputs) const override
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
surface adjust_surface_color(const surface &surf, int red, int green, int blue)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
New lexcical_cast header.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
static const color_range get_side_color_range(int side)
A modified priority queue used to order image modifications.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual std::pair< int, int > calculate_size(const surface &src) const
surface rotate_180_surface(const surface &surf)
Rotates a surface 180 degrees.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
std::vector< formula_input > formula_input_vector
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
#define REGISTER_MOD_PARSER(type, args_var)
A macro for automatic modification parser registration.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
surface scale_surface(const surface &surf, int w, int h)
Scale a surface using alpha-weighted modified bilinear filtering Note: causes artifacts with alpha gr...
surface blend_surface(const surface &surf, const double amount, const color_t color)
Blends a surface with a color.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
surface flip_surface(const surface &surf)
Definitions for the interface to Wesnoth Markup Language (WML).
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual int priority() const
Specifies the priority of the modification.
surface clone() const
Makes a copy of this surface.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
void push(modification *mod)
Adds mod to the queue (unless mod is nullptr).
std::size_t size() const
Returns the number of elements in the queue.
surface mask_surface(const surface &surf, const surface &mask, bool *empty_result, const std::string &filename)
Applies a mask on a surface.
surface flop_surface(const surface &surf)
imod_exception(const std::stringstream &message_stream)
Constructor.
static lg::log_domain log_display("display")
#define fxpmult(x, y)
IN: unsigned and fixed_t - OUT: unsigned.
surface blur_alpha_surface(const surface &surf, int depth)
Cross-fades a surface with alpha channel.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
surface cut_surface(const surface &surf, const SDL_Rect &r)
Cuts a rectangle from a surface.
Base abstract class for an image-path modification.
color_range_map recolor_range(const color_range &new_range, const std::vector< color_t > &old_rgb)
Converts a source palette using the specified color_range object.
surface rotate_90_surface(const surface &surf, bool clockwise)
Rotates a surface 90 degrees.
Generic locator abstracting the location of an image.
static modification_queue decode(const std::string &)
Decodes modifications from a modification string.
#define ftofxp(x)
IN: float or int - OUT: fixed_t.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
std::unordered_map< color_t, color_t > color_range_map
surface alpha_to_greyscale(const surface &surf)
surface monochrome_image(const surface &surf, const int threshold)
wfl::variant get_value(const std::string &key) const override
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
static map_location::DIRECTION s
surface scale_surface_xbrz(const surface &surf, std::size_t z)
Scale a surface using xBRZ algorithm.
Helper class for pinning SDL surfaces into memory.
A color range definition is made of four reference RGB colors, used for calculating conversions from ...
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
const std::string & get_filename() const
surface greyscale_image(const surface &surf)
surface light_surface(const surface &surf, const surface &lightmap)
Light surf using lightmap.
REMOVE_EMPTY: remove empty elements.
surface wipe_alpha(const surface &surf)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
std::vector< std::string > split(const config_attribute_value &val)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
virtual std::pair< int, int > calculate_size(const surface &src) const
pixel_callable(SDL_Point p, color_t clr, uint32_t w, uint32_t h)
const color_range & color_info(const std::string &name)
Functions to load and save images from/to disk.
surface scale_surface_sharp(const surface &surf, int w, int h)
Scale a surface using modified nearest neighbour algorithm.
Standard logging facilities (interface).
modification * top() const
Returns the top element in the queue .
map_type priorities_
Map from a mod's priority() to the mods having that priority.
const std::vector< color_t > & tc_info(const std::string &name)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
void pop()
Removes the top element from the queue.
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
surface sepia_image(const surface &surf)
surface rotate_any_surface(const surface &surf, float angle, int zoom, int offset)
Rotates a surface by any degrees.
bool file_exists() const
Tests whether the file the locator points at exists.
std::string::const_iterator iterator
surface swap_channels_image(const surface &surf, channel r, channel g, channel b, channel a)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
std::vector< std::string > parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Splits a string based either on a separator, except then the text appears within specified parenthesi...
const std::string message
The error message regarding the failed operation.