1 /*
2    Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "map/location.hpp"
18 #include "terrain/translation.hpp"
19 #include "game_config.hpp"
20 
21 #include <SDL2/SDL.h>
22 #include <unordered_map>
23 
24 class surface;
25 
26 ///this module manages the cache of images. With an image name, you can get
27 ///the surface corresponding to that image.
28 //
29 namespace image {
30 	template<typename T>
31 	class cache_type;
32 
33 	//a generic image locator. Abstracts the location of an image.
34 	class locator
35 	{
36 	public:
37 		enum type { NONE, FILE, SUB_FILE };
38 	private:
39 		// Called by each constructor after actual construction to
40 		// initialize the index_ field
41 		void init_index();
42 		void parse_arguments();
43 		struct value {
44 			value();
45 			value(const char *filename);
46 			value(const std::string& filename);
47 			value(const std::string& filename, const std::string& modifications);
48 			value(const std::string& filename, const map_location& loc, int center_x, int center_y, const std::string& modifications);
49 
50 			bool operator==(const value& a) const;
51 			bool operator<(const value& a) const;
52 
53 			type type_;
54 			bool is_data_uri_;
55 			std::string filename_;
56 			map_location loc_;
57 			std::string modifications_;
58 			int center_x_;
59 			int center_y_;
60 		};
61 
62 		friend struct std::hash<value>;
63 
64 	public:
65 
66 		typedef std::unordered_map<value, int> locator_finder_t;
67 
68 		// Constructing locators is somewhat slow, accessing image
69 		// through locators is fast. The idea is that calling functions
70 		// should store locators, and not strings to construct locators
71 		// (the second will work, of course, but will be slower)
72 		locator();
73 		locator(const locator &a, const std::string &mods ="");
74 		locator(const char *filename);
75 		locator(const std::string& filename);
76 		locator(const std::string& filename, const std::string& modifications);
77 		locator(const std::string &filename, const map_location &loc,
78 		int center_x, int center_y, const std::string& modifications = "");
79 
80 		locator& operator=(const locator &a);
operator ==(const locator & a) const81 		bool operator==(const locator &a) const { return index_ == a.index_; }
operator !=(const locator & a) const82 		bool operator!=(const locator &a) const { return index_ != a.index_; }
operator <(const locator & a) const83 		bool operator<(const locator &a) const { return index_ < a.index_; }
84 
get_filename() const85 		const std::string &get_filename() const { return val_.filename_; }
is_data_uri() const86 		bool is_data_uri() const { return val_.is_data_uri_; }
get_loc() const87 		const map_location& get_loc() const { return val_.loc_ ; }
get_center_x() const88 		int get_center_x() const { return val_.center_x_; }
get_center_y() const89 		int get_center_y() const { return val_.center_y_; }
get_modifications() const90 		const std::string& get_modifications() const {return val_.modifications_;}
get_type() const91 		type get_type() const { return val_.type_; }
92 		// const int get_index() const { return index_; };
93 
94 		// returns true if the locator does not correspond to any
95 		// actual image
is_void() const96 		bool is_void() const { return val_.type_ == NONE; }
97 
98 		/**
99 		 * Tests whether the file the locater points at exists.
100 		 *
101 		 * is_void doesn't seem to work before the image is loaded and also in
102 		 * debug mode a placeholder is returned. So it's not possible to test
103 		 * for the existence of a file. So this function does that. (Note it
104 		 * tests for existence not whether or not it's a valid image.)
105 		 *
106 		 * @return                Whether or not the file exists.
107 		 */
108 		bool file_exists() const;
109 
110 		template <typename T>
111 		bool in_cache(cache_type<T> &cache) const;
112 		template <typename T>
113 		T &access_in_cache(cache_type<T> &cache) const;
114 		template <typename T>
115 		const T &locate_in_cache(cache_type<T> &cache) const;
116 		template <typename T>
117 		void add_to_cache(cache_type<T> &cache, const T &data) const;
118 
119 	private:
120 
121 		int index_;
122 		value val_;
123 	};
124 
125 	surface load_from_disk(const locator &loc);
126 
127 
128 	typedef cache_type<surface> image_cache;
129 	typedef cache_type<bool> bool_cache;
130 
131 	typedef std::map<t_translation::terrain_code, surface> mini_terrain_cache_map;
132 	extern mini_terrain_cache_map mini_terrain_cache;
133 	extern mini_terrain_cache_map mini_fogged_terrain_cache;
134 	extern mini_terrain_cache_map mini_highlighted_terrain_cache;
135 
136 	///light_string store colors info of central and adjacent hexes.
137 	///The structure is one or several 4 chars blocks (L,R,G,B)
138 	///where RGB is the color and L is the lightmap to use:
139     ///   -1: none
140     ///    0: full hex
141     ///  1-6: concave corners
142     /// 7-12: convex half-corners 1
143     ///13-19: convex half-corners 2
144 	typedef std::basic_string<signed char> light_string;
145 	///return light_string of one light operation(see above)
146 	light_string get_light_string(int op, int r, int g, int b);
147 
148 	// pair each light possibility with its lighted surface
149 	typedef std::map<light_string, surface> lit_variants;
150 	// lighted variants for each locator
151 	typedef cache_type<lit_variants> lit_cache;
152 
153 	void flush_cache();
154 
155 	///the image manager is responsible for setting up images, and destroying
156 	///all images when the program exits. It should probably
157 	///be created once for the life of the program
158 	struct manager
159 	{
160 		manager();
161 		~manager();
162 	};
163 
164 	///will make all scaled images have these rgb values added to all
165 	///their pixels. i.e. add a certain color hint to images. useful
166 	///for representing day/night. Invalidates all scaled images.
167 	void set_color_adjustment(int r, int g, int b);
168 
169 	///set the team colors used by the TC image modification
170 	///use a vector with one string for each team
171 	///using nullptr will reset to default TC
172 	void set_team_colors(const std::vector<std::string>* colors = nullptr);
173 
174 	const std::vector<std::string>& get_team_colors();
175 
176 	///sets the amount scaled images should be scaled. Invalidates all
177 	///scaled images.
178 	void set_zoom(unsigned int zoom);
179 
180 	/// UNSCALED : image will be drawn "as is" without changing size, even in case of redraw
181 	/// SCALED_TO_ZOOM : image will be scaled taking zoom into account
182 	/// HEXED : the hex mask is applied on the image
183 	/// SCALED_TO_HEX : image will be scaled to fit into a hex, taking zoom into account
184 	/// TOD_COLORED : same as SCALED_TO_HEX but ToD coloring is also applied
185 	/// BRIGHTENED  : same as TOD_COLORED but also brightened
186 	enum TYPE { UNSCALED, SCALED_TO_ZOOM, HEXED, SCALED_TO_HEX, TOD_COLORED, BRIGHTENED};
187 
188 	///function to get the surface corresponding to an image.
189 	surface get_image(const locator& i_locator, TYPE type=UNSCALED);
190 
191 	///function to get the surface corresponding to an image.
192 	///after applying the lightmap encoded in ls
193 	///type should be HEXED or SCALED_TO_HEX
194 	surface get_lighted_image(const image::locator& i_locator, const light_string& ls, TYPE type);
195 
196 	///function to get the standard hex mask
197 	surface get_hexmask();
198 
199 	///function to check if an image fit into an hex
200 	///return false if the image has not the standard size.
201 	bool is_in_hex(const locator& i_locator);
202 
203 	///function to check if an image is empty after hex cut
204 	///should be only used on terrain image (cache the hex cut version)
205 	bool is_empty_hex(const locator& i_locator);
206 
207 	///function to reverse an image. The image MUST have originally been returned from
208 	///an image:: function. Returned images have the same semantics as for get_image()
209 	surface reverse_image(const surface &surf);
210 
211 	///returns true if the given image actually exists, without loading it.
212 	bool exists(const locator& i_locator);
213 
214 	/// precache the existence of files in the subdir (ex: "terrain/")
215 	void precache_file_existence(const std::string& subdir = "");
216 	bool precached_file_exists(const std::string& file);
217 
218 	/// initialize any private data, e.g. algorithm choices from preferences
219 	bool update_from_preferences();
220 
221 	enum class save_result {success, unsupported_format, save_failed, no_image};
222 
223 	save_result save_image(const locator& i_locator, const std::string& outfile);
224 	save_result save_image(const surface& surf, const std::string& outfile);
225 }
226