33 #include <SDL2/SDL_image.h> 37 #include <boost/algorithm/string.hpp> 38 #include <boost/functional/hash_fwd.hpp> 43 #define ERR_DP LOG_STREAM(err, log_display) 44 #define LOG_DP LOG_STREAM(info, log_display) 47 #define ERR_CFG LOG_STREAM(err, log_config) 73 struct hash<
image::locator::value>
77 std::size_t hash = std::hash<unsigned>{}(val.
type_);
84 boost::hash_combine(hash, val.
loc_.
x);
85 boost::hash_combine(hash, val.
loc_.
y);
109 if(static_cast<unsigned>(index) >= content_.size())
110 content_.resize(index + 1);
111 return content_[
index];
126 return index_ < 0 ? false : cache.
get_element(index_).loaded;
157 image::image_cache images_, scaled_to_zoom_, hexed_images_, scaled_to_hex_images_, tod_colored_images_,
173 std::map<std::string, bool> image_existence_map;
176 std::set<std::string> precached_dirs;
178 std::map<surface, surface> reversed_images_;
180 int red_adjust = 0, green_adjust = 0, blue_adjust = 0;
183 unsigned int cached_zoom = 0;
185 const std::string data_uri_prefix =
"data:";
186 struct parsed_data_URI{
196 const std::size_t colon = data_URI.find(
':');
199 const std::size_t comma = after_scheme.find(
',');
202 const std::size_t semicolon = type_info.find(
';');
204 scheme = data_URI.substr(0, colon);
205 base64 = type_info.substr(semicolon + 1);
206 mime = type_info.substr(0, semicolon);
207 data = after_scheme.substr(comma + 1);
208 good = (scheme ==
"data" &&
base64 ==
"base64" && mime.length() > 0 && data.length() > 0);
225 hexed_images_.flush();
226 tod_colored_images_.flush();
227 scaled_to_zoom_.flush();
228 scaled_to_hex_images_.flush();
229 brightened_images_.flush();
231 lit_scaled_images_.flush();
232 in_hex_info_.flush();
233 is_empty_hex_.flush();
234 mini_terrain_cache.clear();
235 mini_fogged_terrain_cache.clear();
236 mini_highlighted_terrain_cache.clear();
237 reversed_images_.clear();
238 image_existence_map.clear();
239 precached_dirs.clear();
247 void locator::init_index()
249 auto i = locator_finder.find(
val_);
251 if(
i == locator_finder.end()) {
252 index_ = last_index_++;
253 locator_finder.emplace(
val_, index_);
259 void locator::parse_arguments()
261 std::string& fn =
val_.filename_;
266 if(boost::algorithm::starts_with(fn, data_uri_prefix)) {
267 parsed_data_URI parsed{fn};
272 ERR_DP <<
"Invalid data URI: " << stripped << std::endl;
275 val_.is_data_uri_ =
true;
278 std::size_t markup_field = fn.find(
'~');
280 if(markup_field != std::string::npos) {
281 val_.type_ = SUB_FILE;
282 val_.modifications_ = fn.substr(markup_field, fn.size() - markup_field);
283 fn = fn.substr(0, markup_field);
324 ,
val_(filename, modifications)
335 ,
val_(filename, loc, center_x, center_y, modifications)
350 , is_data_uri_(false)
446 surface ovr_surf = IMG_Load_RW(rwops.release(),
true);
451 SDL_Rect area {0, 0, ovr_surf->w, ovr_surf->h};
453 sdl_blit(ovr_surf, 0, orig_surf, &area);
463 if(!location.empty()) {
466 if(!loc_location.empty()) {
467 location = loc_location;
471 res = IMG_Load_RW(rwops.release(),
true);
474 if(res && loc_location.empty()) {
476 if(!ovr_location.empty()) {
495 if(surf ==
nullptr) {
501 while(!mods.
empty()) {
507 std::ostringstream ss;
511 ss <<
"\t" << mod_name <<
"\n";
514 ERR_CFG <<
"Failed to apply a modification to an image:\n" 516 <<
"Modifications: " << ss.str() <<
"\n" 517 <<
"Error: " << e.
message <<
"\n";
539 bool is_empty =
false;
565 ERR_DP <<
"Invalid data URI: " << stripped << std::endl;
566 }
else if(parsed.mime.substr(0, 5) !=
"image") {
567 ERR_DP <<
"Data URI not of image MIME type: " << parsed.mime << std::endl;
569 const std::vector<uint8_t> image_data =
base64::decode(parsed.data);
572 if(image_data.empty()) {
573 ERR_DP <<
"Invalid encoding in data URI" << std::endl;
574 }
else if(parsed.mime ==
"image/png") {
575 surf = IMG_LoadTyped_RW(rwops.release(),
true,
"PNG");
576 }
else if(parsed.mime ==
"image/jpeg") {
577 surf = IMG_LoadTyped_RW(rwops.release(),
true,
"JPG");
579 ERR_DP <<
"Invalid image MIME type: " << parsed.mime << std::endl;
589 return static_cast<signed char>(std::min<int>(127, std::max<int>(-128, i / 2)));
610 int m = ls[0] == -1 ? 2 : 1;
616 auto i = lightmaps_.find(ls);
617 if(
i != lightmaps_.end()) {
618 lightmap =
i->second;
621 static const std::string
p =
"terrain/light/light";
622 static const std::string lm_img[19] {
624 p +
"-concave-2-tr.png", p +
"-concave-2-r.png", p +
"-concave-2-br.png",
625 p +
"-concave-2-bl.png", p +
"-concave-2-l.png", p +
"-concave-2-tl.png",
626 p +
"-convex-br-bl.png", p +
"-convex-bl-l.png", p +
"-convex-l-tl.png",
627 p +
"-convex-tl-tr.png", p +
"-convex-tr-r.png", p +
"-convex-r-br.png",
628 p +
"-convex-l-bl.png", p +
"-convex-tl-l.png", p +
"-convex-tr-tl.png",
629 p +
"-convex-r-tr.png", p +
"-convex-br-r.png", p +
"-convex-bl-br.png" 633 for(std::size_t
c = 0;
c + 3 < ls.size();
c += 4) {
642 if(lightmap ==
nullptr) {
644 lightmap = lts.
clone();
646 sdl_blit(lts,
nullptr, lightmap,
nullptr);
651 lightmaps_[ls] = lightmap;
692 if(r != red_adjust || g != green_adjust || b != blue_adjust) {
696 tod_colored_images_.flush();
697 brightened_images_.flush();
699 lit_scaled_images_.flush();
700 reversed_images_.clear();
708 tod_colored_images_.flush();
709 brightened_images_.flush();
710 reversed_images_.clear();
715 if(zoom !=
tile_size && zoom != cached_zoom) {
716 scaled_to_zoom_.flush();
717 scaled_to_hex_images_.flush();
718 lit_scaled_images_.flush();
728 bool is_empty =
false;
794 if(red_adjust == 0 && green_adjust == 0 && blue_adjust == 0) {
832 imap = &tod_colored_images_;
835 imap = &scaled_to_zoom_;
838 imap = &hexed_images_;
841 imap = &scaled_to_hex_images_;
844 imap = &brightened_images_;
851 bool tmp = i_locator.
in_cache(*imap);
902 imap = &lit_scaled_images_;
913 auto lvi = lvar.find(ls);
914 if(lvi != lvar.end()) {
950 if(i_locator.
in_cache(in_hex_info_)) {
971 if(!i_locator.
in_cache(is_empty_hex_)) {
975 if(!i_locator.
in_cache(is_empty_hex_)) {
979 bool is_empty =
false;
990 if(surf ==
nullptr) {
994 const auto itor = reversed_images_.find(surf);
995 if(itor != reversed_images_.end()) {
1001 if(rev ==
nullptr) {
1005 reversed_images_.emplace(surf, rev);
1014 if(type != loc::FILE && type != loc::SUB_FILE) {
1022 bool&
cache = iter->second;
1025 cache = parsed_data_URI{i_locator.
get_filename()}.good;
1036 const std::string checked_dir = dir +
"/" + subdir;
1037 if(precached_dirs.find(checked_dir) != precached_dirs.end()) {
1041 precached_dirs.insert(checked_dir);
1047 std::vector<std::string> files_found;
1048 std::vector<std::string> dirs_found;
1052 for(
const auto&
f : files_found) {
1053 image_existence_map[subdir +
f] =
true;
1056 for(
const auto&
d : dirs_found) {
1065 for(
const auto&
p : paths) {
1072 const auto b = image_existence_map.find(file);
1073 if(
b != image_existence_map.end()) {
1092 LOG_DP <<
"Writing a JPG image to " << filename << std::endl;
1099 LOG_DP <<
"Writing a PNG image to " << filename << std::endl;
1106 LOG_DP <<
"Writing a BMP image to " << filename << std::endl;
1107 const int err = SDL_SaveBMP(surf, filename.c_str()) == 0;
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
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)
Populates 'files' with all the files and 'dirs' with all the directories in dir.
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
#define ftofxp(x)
IN: float or int - OUT: fixed_t.
Image rescaled according to the zoom settings.
Encapsulates the map of the game.
std::vector< uint8_t > decode(utils::string_view in)
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.
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.
surface brighten_image(const surface &surf, fixed_t amount)
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
boost::string_view string_view
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.
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.