34 #include <SDL2/SDL_image.h> 38 #include <boost/algorithm/string.hpp> 39 #include <boost/functional/hash_fwd.hpp> 44 #define ERR_DP LOG_STREAM(err, log_display) 45 #define WRN_DP LOG_STREAM(warn, log_display) 46 #define LOG_DP LOG_STREAM(info, log_display) 49 #define ERR_CFG LOG_STREAM(err, log_config) 75 struct hash<
image::locator::value>
79 std::size_t hash = std::hash<unsigned>{}(val.
type_);
86 boost::hash_combine(hash, val.
loc_.
x);
87 boost::hash_combine(hash, val.
loc_.
y);
111 if(static_cast<unsigned>(index) >= content_.size())
112 content_.resize(index + 1);
113 return content_[
index];
128 return index_ < 0 ? false : cache.
get_element(index_).loaded;
135 return index_ < 0 ? dummy : cache.
get_element(index_).item;
142 return index_ < 0 ? dummy : cache.
get_element(index_).item;
159 image::image_cache images_, scaled_to_zoom_, hexed_images_, scaled_to_hex_images_, tod_colored_images_,
175 std::map<std::string, bool> image_existence_map;
178 std::set<std::string> precached_dirs;
180 std::map<surface, surface> reversed_images_;
182 int red_adjust = 0, green_adjust = 0, blue_adjust = 0;
185 unsigned int cached_zoom = 0;
187 const std::string data_uri_prefix =
"data:";
188 struct parsed_data_URI{
189 explicit parsed_data_URI(std::string_view data_URI);
190 std::string_view scheme;
191 std::string_view mime;
193 std::string_view data;
196 parsed_data_URI::parsed_data_URI(std::string_view data_URI)
198 const std::size_t colon = data_URI.find(
':');
199 const std::string_view after_scheme = data_URI.substr(colon + 1);
201 const std::size_t comma = after_scheme.find(
',');
202 const std::string_view type_info = after_scheme.substr(0, comma);
204 const std::size_t semicolon = type_info.find(
';');
206 scheme = data_URI.substr(0, colon);
207 base64 = type_info.substr(semicolon + 1);
208 mime = type_info.substr(0, semicolon);
209 data = after_scheme.substr(comma + 1);
210 good = (scheme ==
"data" &&
base64 ==
"base64" && mime.length() > 0 && data.length() > 0);
227 hexed_images_.flush();
228 tod_colored_images_.flush();
229 scaled_to_zoom_.flush();
230 scaled_to_hex_images_.flush();
231 brightened_images_.flush();
233 lit_scaled_images_.flush();
234 in_hex_info_.flush();
235 is_empty_hex_.flush();
236 mini_terrain_cache.clear();
237 mini_fogged_terrain_cache.clear();
238 mini_highlighted_terrain_cache.clear();
239 reversed_images_.clear();
240 image_existence_map.clear();
241 precached_dirs.clear();
249 void locator::init_index()
251 auto i = locator_finder.find(val_);
253 if(
i == locator_finder.end()) {
254 index_ = last_index_++;
255 locator_finder.emplace(val_, index_);
261 void locator::parse_arguments()
263 std::string& fn = val_.filename_;
268 if(boost::algorithm::starts_with(fn, data_uri_prefix)) {
269 parsed_data_URI parsed{fn};
272 std::string_view view{ fn };
273 std::string_view stripped = view.substr(0, view.find(
","));
274 ERR_DP <<
"Invalid data URI: " << stripped << std::endl;
277 val_.is_data_uri_ =
true;
280 std::size_t markup_field = fn.find(
'~');
282 if(markup_field != std::string::npos) {
283 val_.type_ = SUB_FILE;
284 val_.modifications_ = fn.substr(markup_field, fn.size() - markup_field);
285 fn = fn.substr(0, markup_field);
326 ,
val_(filename, modifications)
337 ,
val_(filename, loc, center_x, center_y, modifications)
352 , is_data_uri_(false)
448 surface ovr_surf = IMG_Load_RW(rwops.release(),
true);
453 SDL_Rect area {0, 0, ovr_surf->w, ovr_surf->h};
455 sdl_blit(ovr_surf, 0, orig_surf, &area);
469 std::string webp_name = name.substr(0, name.size() - 4) +
".webp";
471 if(!location.empty()) {
472 WRN_DP <<
"Replaced missing '" << name <<
"' with found '" 473 << webp_name <<
"'." << std::endl;
478 if(!location.empty()) {
481 if(!loc_location.empty()) {
482 location = loc_location;
486 res = IMG_Load_RW(rwops.release(),
true);
489 if(res && loc_location.empty()) {
491 if(!ovr_location.empty()) {
498 if(!res && !name.empty()) {
499 ERR_DP <<
"could not open image '" << name <<
"'" << std::endl;
510 if(surf ==
nullptr) {
516 while(!mods.
empty()) {
522 std::ostringstream ss;
526 ss <<
"\t" << mod_name <<
"\n";
529 ERR_CFG <<
"Failed to apply a modification to an image:\n" 531 <<
"Modifications: " << ss.str() <<
"\n" 532 <<
"Error: " << e.
message <<
"\n";
554 bool is_empty =
false;
579 std::string_view stripped = fn.substr(0, fn.find(
","));
580 ERR_DP <<
"Invalid data URI: " << stripped << std::endl;
581 }
else if(parsed.mime.substr(0, 5) !=
"image") {
582 ERR_DP <<
"Data URI not of image MIME type: " << parsed.mime << std::endl;
584 const std::vector<uint8_t> image_data =
base64::decode(parsed.data);
587 if(image_data.empty()) {
588 ERR_DP <<
"Invalid encoding in data URI" << std::endl;
589 }
else if(parsed.mime ==
"image/png") {
590 surf = IMG_LoadTyped_RW(rwops.release(),
true,
"PNG");
591 }
else if(parsed.mime ==
"image/jpeg") {
592 surf = IMG_LoadTyped_RW(rwops.release(),
true,
"JPG");
594 ERR_DP <<
"Invalid image MIME type: " << parsed.mime << std::endl;
604 return static_cast<signed char>(std::min<int>(127, std::max<int>(-128, i / 2)));
625 int m = ls[0] == -1 ? 2 : 1;
631 auto i = lightmaps_.find(ls);
632 if(
i != lightmaps_.end()) {
633 lightmap =
i->second;
636 static const std::string
p =
"terrain/light/light";
637 static const std::string lm_img[19] {
639 p +
"-concave-2-tr.png", p +
"-concave-2-r.png", p +
"-concave-2-br.png",
640 p +
"-concave-2-bl.png", p +
"-concave-2-l.png", p +
"-concave-2-tl.png",
641 p +
"-convex-br-bl.png", p +
"-convex-bl-l.png", p +
"-convex-l-tl.png",
642 p +
"-convex-tl-tr.png", p +
"-convex-tr-r.png", p +
"-convex-r-br.png",
643 p +
"-convex-l-bl.png", p +
"-convex-tl-l.png", p +
"-convex-tr-tl.png",
644 p +
"-convex-r-tr.png", p +
"-convex-br-r.png", p +
"-convex-bl-br.png" 648 for(std::size_t
c = 0;
c + 3 < ls.size();
c += 4) {
657 if(lightmap ==
nullptr) {
659 lightmap = lts.
clone();
661 sdl_blit(lts,
nullptr, lightmap,
nullptr);
666 lightmaps_[ls] = lightmap;
707 if(r != red_adjust || g != green_adjust || b != blue_adjust) {
711 tod_colored_images_.flush();
712 brightened_images_.flush();
714 lit_scaled_images_.flush();
715 reversed_images_.clear();
723 tod_colored_images_.flush();
724 brightened_images_.flush();
725 reversed_images_.clear();
730 if(zoom !=
tile_size && zoom != cached_zoom) {
731 scaled_to_zoom_.flush();
732 scaled_to_hex_images_.flush();
733 lit_scaled_images_.flush();
743 bool is_empty =
false;
809 if(red_adjust == 0 && green_adjust == 0 && blue_adjust == 0) {
847 imap = &tod_colored_images_;
850 imap = &scaled_to_zoom_;
853 imap = &hexed_images_;
856 imap = &scaled_to_hex_images_;
859 imap = &brightened_images_;
866 bool tmp = i_locator.
in_cache(*imap);
917 imap = &lit_scaled_images_;
928 auto lvi = lvar.find(ls);
929 if(lvi != lvar.end()) {
965 if(i_locator.
in_cache(in_hex_info_)) {
986 if(!i_locator.
in_cache(is_empty_hex_)) {
990 if(!i_locator.
in_cache(is_empty_hex_)) {
994 bool is_empty =
false;
1005 if(surf ==
nullptr) {
1009 const auto itor = reversed_images_.find(surf);
1010 if(itor != reversed_images_.end()) {
1012 return itor->second;
1016 if(rev ==
nullptr) {
1020 reversed_images_.emplace(surf, rev);
1029 if(type != loc::FILE && type != loc::SUB_FILE) {
1037 bool&
cache = iter->second;
1040 cache = parsed_data_URI{i_locator.
get_filename()}.good;
1051 const std::string checked_dir = dir +
"/" + subdir;
1052 if(precached_dirs.find(checked_dir) != precached_dirs.end()) {
1056 precached_dirs.insert(checked_dir);
1062 std::vector<std::string> files_found;
1063 std::vector<std::string> dirs_found;
1067 for(
const auto&
f : files_found) {
1068 image_existence_map[subdir +
f] =
true;
1071 for(
const auto&
d : dirs_found) {
1080 for(
const auto&
p : paths) {
1087 const auto b = image_existence_map.find(file);
1088 if(
b != image_existence_map.end()) {
1107 LOG_DP <<
"Writing a JPG image to " << filename << std::endl;
1114 LOG_DP <<
"Writing a PNG image to " << filename << std::endl;
TYPE
Used to specify the rendering format of images.
static surface load_image_file(const image::locator &loc)
surface get_image(const image::locator &i_locator, TYPE type)
Caches and returns an image.
const std::string & get_modifications() const
surface brighten_image(const surface &surf, int32_t amount)
void precache_file_existence(const std::string &subdir)
Precache the existence of files in a binary path subdirectory (e.g.
void add_to_cache(cache_type< T > &cache, const T &data) const
static lg::log_domain log_display("display")
surface adjust_surface_color(const surface &surf, int red, int green, int blue)
static surface get_scaled_to_hex(const locator &i_locator)
static surface get_hexed(const locator &i_locator)
bool precached_file_exists(const std::string &file)
surface reverse_image(const surface &surf)
Horizontally flips an image.
A modified priority queue used to order image modifications.
bool ends_with(const std::string &str, const std::string &suffix)
mini_terrain_cache_map mini_fogged_terrain_cache
static surface load_image_data_uri(const image::locator &loc)
cache_item< T > & get_element(int index)
rwops_ptr make_read_RWops(const std::string &path)
static signed char col_to_uchar(int i)
save_result save_image(const locator &i_locator, const std::string &filename)
bool in_mask_surface(const surface &surf, const surface &mask)
Check if a surface fit into a mask.
T & access_in_cache(cache_type< T > &cache) const
static surface get_scaled_to_zoom(const locator &i_locator)
std::map< t_translation::terrain_code, surface > mini_terrain_cache_map
std::string get_binary_file_location(const std::string &type, const std::string &filename)
Returns a complete path to the actual file of a given type or an empty string if the file isn't prese...
Standard hexagonal tile mask applied, removing portions that don't fit.
surface flip_surface(const surface &surf)
Definitions for the interface to Wesnoth Markup Language (WML).
Same as SCALED_TO_HEX, but with Time of Day color tint applied.
surface clone() const
Makes a copy of this surface.
void flush_cache()
Purges all image caches.
static TYPE simplify_type(const image::locator &i_locator, TYPE type)
translate type to a simpler one when possible
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
surface mask_surface(const surface &surf, const surface &mask, bool *empty_result, const std::string &filename)
Applies a mask on a surface.
const T & locate_in_cache(cache_type< T > &cache) const
static surface get_brightened(const locator &i_locator)
static surface load_image_sub_file(const image::locator &loc)
rwops_ptr make_write_RWops(const std::string &path)
static surface get_tod_colored(const locator &i_locator)
light_string get_light_string(int op, int r, int g, int b)
Returns the light_string for one light operation.
std::string modifications_
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
std::unordered_map< value, int > locator_finder_t
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
void set_zoom(unsigned int amount)
Sets the scaling factor for images.
std::map< light_string, surface > lit_variants
Type used to pair light possibilities with the corresponding lit surface.
std::vector< cache_item< T > > content_
surface cut_surface(const surface &surf, const SDL_Rect &r)
Cuts a rectangle from a surface.
map_display and display: classes which take care of displaying the map and game-data on the screen...
Base abstract class for an image-path modification.
static void precache_file_existence_internal(const std::string &dir, const std::string &subdir)
surface scale_surface_nn(const surface &surf, int w, int h)
Scale a surface using the nearest neighbor algorithm (provided by xBRZ lib)
Generic locator abstracting the location of an image.
static modification_queue decode(const std::string &)
Decodes modifications from a modification string.
void set_color_adjustment(int r, int g, int b)
Changes Time of Day color tint for all applicable image types.
std::size_t operator()(const image::locator::value &val) const
Image rescaled according to the zoom settings.
Encapsulates the map of the game.
surface load_from_disk(const locator &loc)
const std::vector< std::string > & get_binary_paths(const std::string &type)
Returns a vector with all possible paths to a given type of binary, e.g.
std::vector< uint8_t > decode(std::string_view in)
static lg::log_domain log_config("config")
locator & operator=(const locator &a)
surface get_hexmask()
Retrieves the standard hexagonal tile mask.
std::basic_string< signed char > light_string
Type used to store color information of central and adjacent hexes.
mini_terrain_cache_map mini_highlighted_terrain_cache
Declarations for File-IO.
std::unique_ptr< SDL_RWops, void(*)(SDL_RWops *)> rwops_ptr
std::string get_localized_path(const std::string &file, const std::string &suff)
Returns the localized version of the given filename, if it exists.
const std::string & get_filename() const
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
bool is_in_hex(const locator &i_locator)
Checks if an image fits into a single hex.
bool operator<(const value &a) const
surface light_surface(const surface &surf, const surface &lightmap)
Light surf using lightmap.
mini_terrain_cache_map mini_terrain_cache
cache_item(const T &item)
surface get_lighted_image(const image::locator &i_locator, const light_string &ls, TYPE type)
Caches and returns an image with a lightmap applied to it.
SDL_Rect create_rect(const int x, const int y, const int w, const int h)
Creates an SDL_Rect with the given dimensions.
const std::vector< std::string > & modifications(bool mp)
Image rescaled to fit into a hexagonal tile according to the zoom settings.
Contains the SDL_Rect helper code.
const map_location & get_loc() const
bool is_empty_hex(const locator &i_locator)
Checks if an image is empty after hex masking.
static void add_localized_overlay(const std::string &ovr_file, surface &orig_surf)
Functions to load and save images from/to disk.
Standard logging facilities (interface).
modification * top() const
Returns the top element in the queue .
bool operator==(const value &a) const
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)
bool is_void() const
Returns true if the locator does not correspond to an actual image.
bool in_cache(cache_type< T > &cache) const
Unmodified original-size image.
constexpr int32_t floating_to_fixed_point(double n)
Converts a double to a fixed point.
Exception thrown by the operator() when an error occurs.
bool file_exists() const
Tests whether the file the locator points at exists.
static surface apply_light(surface surf, const light_string &ls)
Same as TOD_COLORED, but also brightened.
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.