The Battle for Wesnoth  1.17.21+dev
picture.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2023
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include "map/location.hpp"
19 #include "terrain/translation.hpp"
20 
21 #include <optional>
22 #include <unordered_map>
23 
24 class surface;
25 class texture;
26 struct point;
27 
28 /**
29  * Functions to load and save images from/to disk.
30  *
31  * image::get_image() and other loading functions implement a pseudo-functional
32  * syntax to apply transformations to image files by including them as a suffix
33  * to the path (Image Path Functions). They also offer the option to choose
34  * between different rendering formats for a single image path according to the
35  * display intent -- unscaled, masked to hex, rescaled to zoom, etc.
36  *
37  * @code
38  * surface surf = image::get_image("units/elves-wood/shyde.png~TC(4,magenta)~FL()",
39  * image::UNSCALED);
40  * @endcode
41  *
42  * Internally, all loading functions utilize a cache to avoid reading
43  * individual images from disk more than once, or wasting valuable CPU time
44  * applying potentially expensive transforms every time (e.g. team colors on
45  * animated units). The cache can be manually invalidated using
46  * image::flush_cache(). Certain functions will invalidate parts of the cache
47  * as needed when relevant configuration parameters change in a way that would
48  * be expected to alter the output (e.g. Time of Day-tinted images).
49  */
50 namespace image {
51 
52 template<typename T>
53 class cache_type;
54 
55 /**
56  * Generic locator abstracting the location of an image.
57  *
58  * Constructing locators is somewhat slow, while accessing images through
59  * locators is fast. The general idea is that callers should store locators
60  * and not strings to construct new ones. (The latter will still work, of
61  * course, even if it is slower.)
62  */
63 class locator
64 {
65 public:
66  enum type { NONE, FILE, SUB_FILE };
67 
68  locator() = default;
69  locator(locator&&) noexcept = default;
70  locator(const locator&) = default;
71 
72  template<typename... Args>
73  locator(Args&&... args) : val_(std::forward<Args>(args)...)
74  {
75  }
76 
77  locator& operator=(const locator& a) = default;
78  locator& operator=(locator&&) = default;
79 
80  /** Returns a copy of this locator with the given IPF */
81  locator clone(const std::string& mods) const;
82 
83  bool operator==(const locator& a) const { return val_ == a.val_; }
84  bool operator!=(const locator& a) const { return !operator==(a); }
85 
86  const std::string& get_filename() const { return val_.filename; }
87  bool is_data_uri() const { return val_.is_data_uri; }
88  const map_location& get_loc() const { return val_.loc ; }
89  int get_center_x() const { return val_.center_x; }
90  int get_center_y() const { return val_.center_y; }
91  const std::string& get_modifications() const { return val_.modifications; }
92  type get_type() const { return val_.type; }
93 
94  /**
95  * Returns @a true if the locator does not correspond to an actual image.
96  */
97  bool is_void() const { return val_.type == NONE; }
98 
99  /**
100  * Tests whether the file the locator points at exists.
101  *
102  * is_void does not work before the image is loaded, and also a placeholder
103  * is returned instead in debug mode. Thus it's not possible to test for
104  * the existence of an actual file without this function.
105  *
106  * @note This does not test whether the image is valid or not.
107  *
108  * @return Whether or not the file exists.
109  */
110  bool file_exists() const;
111 
112  template<typename T>
113  bool in_cache(cache_type<T>& cache) const;
114 
115  template<typename T>
116  T& access_in_cache(cache_type<T>& cache) const;
117 
118  template<typename T>
119  const T& locate_in_cache(cache_type<T>& cache) const;
120 
121  template<typename T>
122  std::optional<T> copy_from_cache(cache_type<T>& cache) const;
123 
124  template<typename T>
125  void add_to_cache(cache_type<T>& cache, T data) const;
126 
127 private:
128  struct value
129  {
130  value() = default;
131 
132  value(const std::string& filename);
133  value(const std::string& filename, const std::string& modifications);
134  value(const std::string& filename, const map_location& loc, int center_x, int center_y, const std::string& modifications = "");
135 
136  bool operator==(const value& a) const;
137  bool operator<(const value& a) const;
138 
140  bool is_data_uri = false;
141  std::string filename{};
142  std::string modifications{};
144  int center_x = 0;
145  int center_y = 0;
146  };
147 
149 
150 public:
151  friend struct std::hash<value>;
152 
153  template<typename T>
154  friend class cache_type;
155 
156  std::size_t hash() const;
157 };
158 
159 // write a readable representation of a locator, mostly for debugging
160 std::ostream& operator<<(std::ostream&, const locator&);
161 
165 
166 typedef std::map<t_translation::terrain_code, surface> mini_terrain_cache_map;
167 
171 
172 /**
173  * Type used to store color information of central and adjacent hexes.
174  *
175  * The structure is one or several 4-char blocks: [L,R,G,B]
176  * The R, G, B values represent the color, and L the lightmap to use:
177  *
178  * -1: none
179  * 0: full hex
180  * 1-6: concave corners
181  * 7-12: convex half-corners 1
182  * 13-19: convex half-corners 2
183  */
184 typedef std::basic_string<signed char> light_string;
185 
186 /** Type used to pair light possibilities with the corresponding lit surface. */
187 typedef std::map<light_string, surface> lit_surface_variants;
188 typedef std::map<light_string, texture> lit_texture_variants;
189 
190 /** Lit variants for each locator. */
193 
194 /**
195  * Returns the light_string for one light operation.
196  *
197  * See light_string for more information.
198  */
199 light_string get_light_string(int op, int r, int g, int b);
200 
201 /**
202  * Purges all image caches.
203  */
204 void flush_cache();
205 
206 /**
207  * Image cache manager.
208  *
209  * This class is responsible for setting up and flushing the image cache. No
210  * more than one instance of it should exist at a time.
211  */
212 struct manager
213 {
214  manager();
215  ~manager();
216 };
217 
218 /**
219  * Changes Time of Day color tint for all applicable image types.
220  *
221  * In particular this affects TOD_COLORED images, as well as
222  * images with lightmaps applied. Changing the previous values automatically
223  * invalidates all cached images of those types.
224  */
225 void set_color_adjustment(int r, int g, int b);
226 
227 /**
228  * Used to specify the rendering format of images.
229  */
230 enum TYPE
231 {
232  /** Unmodified original-size image. */
234  /** Standard hexagonal tile mask applied, removing portions that don't fit. */
236  /** Same as HEXED, but with Time of Day color tint applied. */
238  NUM_TYPES // Equal to the number of types specified above
239 };
240 
241 enum class scale_quality { nearest, linear };
242 
243 /**
244  * Returns an image surface suitable for software manipulation.
245  *
246  * The equivalent get_texture() function should generally be preferred.
247  *
248  * Surfaces will be cached for repeat access, unless skip_cache is set.
249  *
250  * @param i_locator Image path.
251  * @param type Rendering format.
252  * @param skip_cache Skip adding the result to the surface cache.
253  */
254 surface get_surface(const locator& i_locator, TYPE type = UNSCALED,
255  bool skip_cache = false);
256 
257 /**
258  * Returns an image texture suitable for hardware-accelerated rendering.
259  *
260  * Texture pointers are not unique, and will be cached and retained
261  * until no longer needed. Users of the returned texture do not have to
262  * worry about texture management.
263  *
264  * If caching is disabled via @a skip_cache, texture memory will be
265  * automatically freed once the returned object and all other linked
266  * textures (if any) are destroyed.
267  *
268  * @param i_locator Image path.
269  * @param type Rendering format.
270  * @param skip_cache Skip adding the result to the surface cache.
271  */
272 texture get_texture(const locator& i_locator, TYPE type = UNSCALED,
273  bool skip_cache = false);
274 
275 texture get_texture(const image::locator& i_locator, scale_quality quality,
276  TYPE type = UNSCALED, bool skip_cache = false);
277 
278 /**
279  * Caches and returns an image with a lightmap applied to it.
280  *
281  * Images will always be HEXED type.
282  *
283  * @param i_locator Image path.
284  * @param ls Light map to apply to the image.
285  */
286 surface get_lighted_image(const image::locator& i_locator, const light_string& ls);
287 texture get_lighted_texture(const image::locator& i_locator, const light_string& ls);
288 
289 /**
290  * Retrieves the standard hexagonal tile mask.
291  */
293 
294 /**
295  * Returns the width and height of an image.
296  *
297  * If the image is not yet in the surface cache, it will be loaded and cached
298  * unless skip_cache is explicitly set.
299  *
300  * @param i_locator Image path.
301  * @param skip_cache If true, do not cache the image if loaded.
302  */
303 point get_size(const locator& i_locator, bool skip_cache = false);
304 
305 /**
306  * Checks if an image fits into a single hex.
307  */
308 bool is_in_hex(const locator& i_locator);
309 
310 /**
311  * Checks if an image is empty after hex masking.
312  *
313  * This should be only used on terrain images, and it will automatically cache
314  * the hex-masked version if necessary.
315  */
316 bool is_empty_hex(const locator& i_locator);
317 
318 /**
319  * Returns @a true if the given image actually exists, without loading it.
320  */
321 bool exists(const locator& i_locator);
322 
323 /**
324  * Precache the existence of files in a binary path subdirectory (e.g. "terrain/").
325  */
326 void precache_file_existence(const std::string& subdir = "");
327 
328 bool precached_file_exists(const std::string& file);
329 
330 enum class save_result
331 {
332  success,
334  save_failed,
335  no_image
336 };
337 
338 save_result save_image(const locator& i_locator, const std::string& outfile);
339 save_result save_image(const surface& surf, const std::string& outfile);
340 
341 }
double g
Definition: astarsearch.cpp:65
Generic locator abstracting the location of an image.
Definition: picture.hpp:64
locator(locator &&) noexcept=default
int get_center_x() const
Definition: picture.hpp:89
bool is_void() const
Returns true if the locator does not correspond to an actual image.
Definition: picture.hpp:97
T & access_in_cache(cache_type< T > &cache) const
Definition: picture.cpp:133
locator & operator=(const locator &a)=default
locator & operator=(locator &&)=default
bool file_exists() const
Tests whether the file the locator points at exists.
Definition: picture.cpp:577
const std::string & get_filename() const
Definition: picture.hpp:86
bool operator!=(const locator &a) const
Definition: picture.hpp:84
type get_type() const
Definition: picture.hpp:92
bool is_data_uri() const
Definition: picture.hpp:87
const T & locate_in_cache(cache_type< T > &cache) const
Definition: picture.cpp:127
const std::string & get_modifications() const
Definition: picture.hpp:91
int get_center_y() const
Definition: picture.hpp:90
std::optional< T > copy_from_cache(cache_type< T > &cache) const
Definition: picture.cpp:139
bool in_cache(cache_type< T > &cache) const
Definition: picture.cpp:121
const map_location & get_loc() const
Definition: picture.hpp:88
std::size_t hash() const
Definition: picture.cpp:115
locator()=default
bool operator==(const locator &a) const
Definition: picture.hpp:83
locator clone(const std::string &mods) const
Returns a copy of this locator with the given IPF.
Definition: picture.cpp:248
void add_to_cache(cache_type< T > &cache, T data) const
Definition: picture.cpp:146
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
Functions to load and save images from/to disk.
std::map< light_string, surface > lit_surface_variants
Type used to pair light possibilities with the corresponding lit surface.
Definition: picture.hpp:187
mini_terrain_cache_map mini_highlighted_terrain_cache
Definition: picture.cpp:223
bool is_empty_hex(const locator &i_locator)
Checks if an image is empty after hex masking.
Definition: picture.cpp:860
bool precached_file_exists(const std::string &file)
Definition: picture.cpp:939
save_result
Definition: picture.hpp:331
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
Definition: picture.cpp:879
void flush_cache()
Purges all image caches.
Definition: picture.cpp:225
mini_terrain_cache_map mini_terrain_cache
Definition: picture.cpp:221
std::map< light_string, texture > lit_texture_variants
Definition: picture.hpp:188
cache_type< texture > texture_cache
Definition: picture.hpp:163
cache_type< lit_surface_variants > lit_surface_cache
Lit variants for each locator.
Definition: picture.hpp:191
cache_type< lit_texture_variants > lit_texture_cache
Definition: picture.hpp:192
mini_terrain_cache_map mini_fogged_terrain_cache
Definition: picture.cpp:222
surface get_surface(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image surface suitable for software manipulation.
Definition: picture.cpp:686
surface get_hexmask()
Retrieves the standard hexagonal tile mask.
Definition: picture.cpp:821
std::ostream & operator<<(std::ostream &s, const locator &l)
Definition: picture.cpp:259
texture get_lighted_texture(const image::locator &i_locator, const light_string &ls)
Definition: picture.cpp:785
save_result save_image(const locator &i_locator, const std::string &filename)
Definition: picture.cpp:949
cache_type< surface > surface_cache
Definition: picture.hpp:162
std::map< t_translation::terrain_code, surface > mini_terrain_cache_map
Definition: picture.hpp:166
std::basic_string< signed char > light_string
Type used to store color information of central and adjacent hexes.
Definition: picture.hpp:184
void precache_file_existence(const std::string &subdir)
Precache the existence of files in a binary path subdirectory (e.g.
Definition: picture.cpp:930
TYPE
Used to specify the rendering format of images.
Definition: picture.hpp:231
@ HEXED
Standard hexagonal tile mask applied, removing portions that don't fit.
Definition: picture.hpp:235
@ NUM_TYPES
Definition: picture.hpp:238
@ TOD_COLORED
Same as HEXED, but with Time of Day color tint applied.
Definition: picture.hpp:237
@ UNSCALED
Unmodified original-size image.
Definition: picture.hpp:233
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
Definition: picture.cpp:985
point get_size(const locator &i_locator, bool skip_cache)
Returns the width and height of an image.
Definition: picture.cpp:827
surface get_lighted_image(const image::locator &i_locator, const light_string &ls)
Caches and returns an image with a lightmap applied to it.
Definition: picture.cpp:749
void set_color_adjustment(int r, int g, int b)
Changes Time of Day color tint for all applicable image types.
Definition: picture.cpp:609
light_string get_light_string(int op, int r, int g, int b)
Returns the light_string for one light operation.
Definition: picture.cpp:511
bool is_in_hex(const locator &i_locator)
Checks if an image fits into a single hex.
Definition: picture.cpp:837
scale_quality
Definition: picture.hpp:241
cache_type< bool > bool_cache
Definition: picture.hpp:164
std::string_view data
Definition: picture.cpp:199
std::string modifications
Definition: picture.hpp:142
map_location loc
Definition: picture.hpp:143
bool operator<(const value &a) const
Definition: picture.cpp:332
locator::type type
Definition: picture.hpp:139
std::string filename
Definition: picture.hpp:141
bool operator==(const value &a) const
Definition: picture.cpp:318
Image cache manager.
Definition: picture.hpp:213
Encapsulates the map of the game.
Definition: location.hpp:38
Holds a 2D point.
Definition: point.hpp:25
#define a
#define b