The Battle for Wesnoth  1.19.8+dev
draw.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2022 - 2024
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 /** @file
18  * Drawing functions, for drawing things on the screen.
19  *
20  * This includes pixel drawing for lines, rectangles and circles;
21  * fill and clear routines; and commands to render SDL surfaces and
22  * textures, in full or in part.
23  *
24  * For the most part draw commands take coordinates in what is called
25  * "draw space", or "game-native coordinates". These are the coordinates
26  * that are used in WML, and can be thought of as pixels.
27  *
28  * High-DPI textures and fonts will automatically use their full
29  * resolution when possible, without any extra handling required.
30  */
31 
32 #include "sdl/rect.hpp"
33 #include "sdl/texture.hpp"
34 
35 #include <vector>
36 
37 #include <SDL2/SDL_render.h>
38 #include <array>
39 
40 struct color_t;
41 
42 namespace draw
43 {
44 
45 /**************************************/
46 /* basic drawing and pixel primatives */
47 /**************************************/
48 
49 /**
50  * Clear the current render target.
51  *
52  * Sets all pixel values in the current render target to (0, 0, 0, 0),
53  * that is both black and fully transparent.
54  *
55  * To clear to a fully opaque colour in stead, use fill().
56  */
57 void clear();
58 
59 /**
60  * Fill an area with the given colour.
61  *
62  * If the alpha component is not specified, it defaults to fully opaque.
63  * If not fully opaque, the fill colour will apply according to the current
64  * blend mode, by default SDL_BLENDMODE_BLEND.
65  *
66  * If a fill area is not specified, it will fill the entire render target.
67  *
68  * @param rect The area to fill, in drawing coordinates.
69  * @param r The red component of the fill colour, 0-255.
70  * @param g The green component of the fill colour, 0-255.
71  * @param b The blue component of the fill colour, 0-255.
72  * @param a The alpha component of the fill colour, 0-255.
73  */
74 void fill(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
75 void fill(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b);
76 void fill(const SDL_Rect& rect, const color_t& color);
77 void fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
78 void fill(uint8_t r, uint8_t g, uint8_t b);
79 void fill(const color_t& color);
80 
81 void fill(const SDL_FRect& rect, const color_t& color);
82 
83 /**
84  * Fill an area.
85  *
86  * Uses the current drawing colour set by set_draw_color().
87  * Coordinates are given in draw space.
88  *
89  * If a fill area is not specified, it will fill the entire render target.
90  *
91  * @param rect The area to fill, in drawing coordinates.
92  */
93 void fill(const SDL_Rect& rect);
94 void fill();
95 
96 /**
97  * Set the drawing colour.
98  *
99  * This is the colour used by fill(), line(), points(), etc..
100  *
101  * If the alpha component is not specified, it defaults to fully opaque.
102  *
103  * @param r The red component of the drawing colour, 0-255.
104  * @param g The green component of the drawing colour, 0-255.
105  * @param b The blue component of the drawing colour, 0-255.
106  * @param a The alpha component of the drawing colour, 0-255.
107  */
108 void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
109 void set_color(uint8_t r, uint8_t g, uint8_t b);
110 void set_color(const color_t& c);
111 
112 /**
113  * Set the blend mode used for drawing operations such as fill() and line().
114  *
115  * This does not affect texture drawing operations such as blit(). For those,
116  * use texture::set_blend_mode() on the texture before blitting.
117  */
118 void set_blend_mode(SDL_BlendMode b);
119 
120 /**
121  * Draw a rectangle.
122  *
123  * Uses the current drawing colour set by set_color().
124  * Coordinates are given in draw space.
125  *
126  * @param rect The rectangle to draw, in drawing coordinates.
127  */
128 void rect(const SDL_Rect& rect);
129 
130 /**
131  * Draw a rectangle using the given colour.
132  *
133  * @param rect The rectangle to draw, in drawing coordinates.
134  * @param r The red component of the drawing colour, 0-255.
135  * @param g The green component of the drawing colour, 0-255.
136  * @param b The blue component of the drawing colour, 0-255.
137  * @param a The alpha component of the drawing colour, 0-255.
138  */
139 void rect(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
140 void rect(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b);
141 void rect(const SDL_Rect& rect, const color_t& color);
142 
143 /**
144  * Draw a line.
145  *
146  * Uses the current drawing colour set by set_color().
147  * Coordinates are given in draw space.
148  *
149  * @param from_x The X coordinate of the start point, in draw space.
150  * @param from_y The Y coordinate of the start point, in draw space.
151  * @param to_x The X coordinate of the end point, in draw space.
152  * @param to_y The Y coordinate of the end point, in draw space.
153  */
154 void line(int from_x, int from_y, int to_x, int to_y);
155 
156 /**
157  * Draw a line of the given colour.
158  *
159  * @param from_x The X coordinate of the start point, in draw space.
160  * @param from_y The Y coordinate of the start point, in draw space.
161  * @param to_x The X coordinate of the end point, in draw space.
162  * @param to_y The Y coordinate of the end point, in draw space.
163  * @param c The RGBA colour of the line.
164  */
165 void line(int from_x, int from_y, int to_x, int to_y, const color_t& c);
166 
167 /** Draw a set of points. */
168 void points(const std::vector<SDL_Point>& points);
169 
170 /** Draw a single point. */
171 void point(int x, int y);
172 
173 // TODO: enum for common octant choices - nice but not necessary
174 /**
175  * Draw a circle of the given colour.
176  *
177  * Only the outline of the circle is drawn. To draw a filled circle,
178  * use draw::disc().
179  *
180  * The octants bitfield can be used to draw only certain octants
181  * of the circle, resulting in one or more arcs.
182  *
183  * If no colour is specified, the current drawing colour will be used.
184  *
185  * @param x The x coordinate of the center of the circle.
186  * @param y The y coordinate of the center of the circle.
187  * @param r The radius of the circle.
188  * @param c The colour of the circle.
189  * @param octants A bitfield indicating which octants to draw,
190  * starting at twelve o'clock and moving clockwise.
191  */
192 void circle(int x, int y, int r, const color_t& c, uint8_t octants = 0xff);
193 void circle(int x, int y, int r, uint8_t octants = 0xff);
194 
195 /**
196  * Draw a solid disc of the given colour.
197  *
198  * The octants bitfield can be used to draw only certain octants
199  * of the disc, resulting in one or more filled wedges.
200  *
201  * If no colour is specified, the current drawing colour will be used.
202  *
203  * @param x The x coordinate of the center of the circle.
204  * @param y The y coordinate of the center of the circle.
205  * @param r The radius of the circle.
206  * @param c The colour of the circle.
207  * @param octants A bitfield indicating which octants to draw,
208  * starting at twelve o'clock and moving clockwise.
209  */
210 void disc(int x, int y, int r, const color_t& c, uint8_t octants = 0xff);
211 void disc(int x, int y, int r, uint8_t octants = 0xff);
212 
213 
214 /*******************/
215 /* texture drawing */
216 /*******************/
217 
218 
219 /**
220  * Draws a texture, or part of a texture, at the given location.
221  *
222  * The portion of the texture to be drawn will be scaled to fill
223  * the target rectangle.
224  *
225  * This version takes coordinates in game-native resolution,
226  * which may be lower than the final output resolution in high-dpi
227  * contexts or if pixel scaling is used. The texture will be copied
228  * in high-resolution if possible.
229  *
230  * @param tex The texture to be copied / drawn.
231  * @param dst The target location to copy the texture to,
232  * in low-resolution game-native drawing coordinates.
233  * If null, this fills the entire render target.
234  */
235 void blit(const texture& tex, const SDL_Rect& dst);
236 void blit(const texture& tex);
237 
238 /**
239  * Draws a texture, or part of a texture, at the given location,
240  * also mirroring/flipping the texture horizontally and/or vertically.
241  *
242  * By default the texture will be flipped horizontally.
243  *
244  * @param tex The texture to be copied / drawn.
245  * @param dst The target location to copy the texture to,
246  * in low-resolution game-native drawing coordinates.
247  * If not given, the entire render target will be filled.
248  * @param flip_h Whether to flip/mirror the texture horizontally.
249  * @param flip_v Whether to flip/mirror the texture vertically.
250  */
251 void flipped(const texture& tex,
252  const SDL_Rect& dst,
253  bool flip_h = true,
254  bool flip_v = false
255 );
256 void flipped(const texture& tex, bool flip_h = true, bool flip_v = false);
257 
258 /**
259  * Tile a texture to fill a region.
260  *
261  * This function tiles the texture in draw-space.
262  *
263  * The texture may be aligned either with its center at the center
264  * of the region, or with its top-left corner at the top-left corner
265  * of the region.
266  *
267  * @param tex The texture to use to fill the region.
268  * @param dst The region to fill, in draw space.
269  * @param centered If true the tiled texture will be centered.
270  * If false, it will align at the top-left.
271  * @param mirrored If true the texture will be mirrored in such a way that
272  * adjacent tiles always share a common edge. This can look
273  * better for images that are not perfect tiles.
274  */
275 void tiled(const texture& tex,
276  const SDL_Rect& dst,
277  bool centered = false,
278  bool mirrored = false
279 );
280 
281 /** Tile a texture to fill a region.
282  *
283  * This function tiles the texture in output space. It is otherwise
284  * identical to draw::tiled().
285  */
286 void tiled_highres(const texture& tex,
287  const SDL_Rect& dst,
288  bool centered = false,
289  bool mirrored = false
290 );
291 
292 /**
293  * Draw a texture with smoothly varying colour and alpha modification,
294  * specified at the four corners of the drawing destination.
295  *
296  * The UV texture coordinates at each corner may also be specified.
297  * If unspecified, the full texture will be drawn.
298  *
299  * Colour modifiers multiply the output colour and alpha by their value
300  * after mapping to the range [0,1]. A value of 255 will have no effect.
301  *
302  * @param tex The texture to draw
303  * @param dst Where to draw the texture, in draw space
304  * @param cTL The colour modifier at the top-left corner
305  * @param cTR The colour modifier at the top-right corner
306  * @param cBL The colour modifier at the bottom-left corner
307  * @param cBR The colour modifier at the bottom-right corner
308  * @param uvTL The UV texture coordinate at the top-left corner
309  * @param uvTR The UV texture coordinate at the top-right corner
310  * @param uvBL The UV texture coordinate at the bottom-left corner
311  * @param uvBR The UV texture coordinate at the bottom-right corner
312  */
313 void smooth_shaded(const texture& tex, const SDL_Rect& dst,
314  const SDL_Color& cTL, const SDL_Color& cTR,
315  const SDL_Color& cBL, const SDL_Color& cBR,
316  const SDL_FPoint& uvTL, const SDL_FPoint& uvTR,
317  const SDL_FPoint& uvBL, const SDL_FPoint& uvBR
318 );
319 void smooth_shaded(const texture& tex, const SDL_Rect& dst,
320  const SDL_Color& cTL, const SDL_Color& cTR,
321  const SDL_Color& cBL, const SDL_Color& cBR
322 );
323 void smooth_shaded(const texture& tex,
324  const std::array<SDL_Vertex, 4>& verts
325 );
326 
327 /***************************/
328 /* RAII state manipulation */
329 /***************************/
330 
331 
332 /** A class to manage automatic restoration of the clipping region.
333  *
334  * This can be constructed on its own, or one of the utility functions
335  * override_clip() and reduce_clip() can be used. Constructing a clip_setter
336  * or using override_clip() will completely override the current clipping area.
337  * To intersect with the current clipping area in stead, use reduce_clip().
338  */
340 {
341 public:
342  explicit clip_setter(const SDL_Rect& clip);
343  ~clip_setter();
344 private:
345  SDL_Rect c_;
347 };
348 
349 /**
350  * Override the clipping area. All draw calls will be clipped to this region.
351  *
352  * The clipping area is specified in draw-space coordinates.
353  *
354  * The returned object will reset the clipping area when it is destroyed,
355  * so it should be kept in scope until drawing is complete.
356  *
357  * @param clip The clipping region in draw-space coordinates.
358  * @returns A clip_setter object. When this object is destroyed
359  * the clipping region will be restored to whatever
360  * it was before this call.
361  */
362 [[nodiscard]] clip_setter override_clip(const SDL_Rect& clip);
363 
364 /**
365  * Set the clipping area to the intersection of the current clipping
366  * area and the given rectangle.
367  *
368  * Otherwise acts as override_clip().
369  */
370 [[nodiscard]] clip_setter reduce_clip(const SDL_Rect& clip);
371 
372 /**
373  * Set the clipping area, without any provided way of setting it back.
374  *
375  * @param clip The clipping area, in draw-space coordinates.
376  */
377 void force_clip(const SDL_Rect& clip);
378 
379 /**
380  * Get the current clipping area, in draw coordinates.
381  *
382  * The clipping area is interpreted relative to the current viewport.
383  *
384  * If clipping is disabled, this will return the full drawing area.
385  */
386 ::rect get_clip();
387 
388 /** Whether clipping is enabled. */
389 bool clip_enabled();
390 
391 /** Disable clipping. To enable clipping, use set_clip() or force_clip(). */
392 void disable_clip();
393 
394 /**
395  * Whether the current clipping region will disallow drawing.
396  *
397  * This returns true for any clipping region with negative or zero width
398  * or height.
399  */
400 bool null_clip();
401 
402 
403 /** A class to manage automatic restoration of the viewport region.
404  *
405  * This will also translate the current clipping region into the space
406  * of the viewport, if a clipping region is set.
407  *
408  * This can be constructed on its own, or the draw::set_viewport()
409  * utility function can be used.
410  */
412 {
413 public:
414  explicit viewport_setter(const SDL_Rect& viewport);
416 private:
417  SDL_Rect v_;
418  SDL_Rect c_;
420 };
421 
422 /**
423  * Set the viewport. Drawing operations will have their coordinates
424  * adjusted to the viewport.
425  *
426  * The top-left corner of the viewport will be interpreted as (0,0) in
427  * draw space coordinates while the returned object is in scope.
428  *
429  * The new viewport is specified in absolute coordinates, relative to the
430  * full drawing surface.
431  *
432  * The returned object will reset the viewport when it is destroyed, so
433  * it should be kept in scope until viewport-relative drawing is complete.
434  *
435  * @param viewport The new viewport region, relative to the current
436  * viewport.
437  * @returns A viewport_setter object. When this object is
438  * destroyed the viewport will be restored to whatever
439  * it was before this call.
440  */
441 [[nodiscard]] viewport_setter set_viewport(const SDL_Rect& viewport);
442 
443 /**
444  * Set the viewport, without any provided way of setting it back.
445  *
446  * The new viewport is specified in absolute coordinates, relative to the
447  * full drawing surface.
448  *
449  * @param viewport The viewport, in absolute draw-space coordinates.
450  * If null, the viewport is reset to the full draw area.
451  */
452 void force_viewport(const SDL_Rect& viewport);
453 
454 /**
455  * Get the current viewport.
456  *
457  * @returns The current viewport, in the coordinate space of
458  * the original drawing surface
459  */
460 SDL_Rect get_viewport();
461 
462 
463 /**
464  * A class to manage automatic restoration of the render target.
465  *
466  * It will also cache and restore the current viewport.
467  *
468  * This can be constructed on its own, or the draw::set_render_target()
469  * utility function can be used.
470  */
472 {
473 public:
474  explicit render_target_setter(const texture& t);
476 
477 private:
481 };
482 
483 /**
484  * Set the given texture as the active render target.
485  *
486  * The current viewport will also be cached and restored along with the
487  * render target.
488  *
489  * All draw calls will draw to this texture until the returned object
490  * goes out of scope. Do not retain the render_target_setter longer
491  * than necessary.
492  *
493  * The provided texture must have been created with the
494  * SDL_TEXTUREACCESS_TARGET access mode.
495  *
496  * @param t The new render target. This must be a texture created
497  * with SDL_TEXTUREACCESS_TARGET, or an empty texture.
498  * If empty, it will set the render target to Wesnoth's
499  * primary render buffer.
500  * @returns A render_target_setter object. When this object is
501  * destroyed the render target will be restored to
502  * whatever it was before this call.
503  */
504 [[nodiscard]] render_target_setter set_render_target(const texture& t);
505 
506 
507 } // namespace draw
double t
Definition: astarsearch.cpp:63
double g
Definition: astarsearch.cpp:63
A class to manage automatic restoration of the clipping region.
Definition: draw.hpp:340
SDL_Rect c_
Definition: draw.hpp:345
bool clip_enabled_
Definition: draw.hpp:346
clip_setter(const SDL_Rect &clip)
Definition: draw.cpp:489
A class to manage automatic restoration of the render target.
Definition: draw.hpp:472
render_target_setter(const texture &t)
Definition: draw.cpp:635
A class to manage automatic restoration of the viewport region.
Definition: draw.hpp:412
viewport_setter(const SDL_Rect &viewport)
Definition: draw.cpp:576
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
Definition: draw.hpp:43
viewport_setter set_viewport(const SDL_Rect &viewport)
Set the viewport.
Definition: draw.cpp:603
void force_viewport(const SDL_Rect &viewport)
Set the viewport, without any provided way of setting it back.
Definition: draw.cpp:608
render_target_setter set_render_target(const texture &t)
Set the given texture as the active render target.
Definition: draw.cpp:671
clip_setter override_clip(const SDL_Rect &clip)
Override the clipping area.
Definition: draw.cpp:504
void circle(int x, int y, int r, const color_t &c, uint8_t octants=0xff)
Draw a circle of the given colour.
Definition: draw.cpp:215
void points(const std::vector< SDL_Point > &points)
Draw a set of points.
Definition: draw.cpp:203
void force_clip(const SDL_Rect &clip)
Set the clipping area, without any provided way of setting it back.
Definition: draw.cpp:517
SDL_Rect get_viewport()
Get the current viewport.
Definition: draw.cpp:619
bool null_clip()
Whether the current clipping region will disallow drawing.
Definition: draw.cpp:562
clip_setter reduce_clip(const SDL_Rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
Definition: draw.cpp:509
bool clip_enabled()
Whether clipping is enabled.
Definition: draw.cpp:545
void tiled(const texture &tex, const SDL_Rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
Definition: draw.cpp:376
void disc(int x, int y, int r, const color_t &c, uint8_t octants=0xff)
Draw a solid disc of the given colour.
Definition: draw.cpp:257
void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Set the drawing colour.
Definition: draw.cpp:107
void flipped(const texture &tex, const SDL_Rect &dst, bool flip_h=true, bool flip_v=false)
Draws a texture, or part of a texture, at the given location, also mirroring/flipping the texture hor...
Definition: draw.cpp:347
void fill(const SDL_Rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
Definition: draw.cpp:50
void point(int x, int y)
Draw a single point.
Definition: draw.cpp:209
void clear()
Clear the current render target.
Definition: draw.cpp:40
void set_blend_mode(SDL_BlendMode b)
Set the blend mode used for drawing operations such as fill() and line().
Definition: draw.cpp:125
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:317
void tiled_highres(const texture &tex, const SDL_Rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
Definition: draw.cpp:404
::rect get_clip()
Get the current clipping area, in draw coordinates.
Definition: draw.cpp:529
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:157
void disable_clip()
Disable clipping.
Definition: draw.cpp:553
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:187
void smooth_shaded(const texture &tex, const SDL_Rect &dst, const SDL_Color &cTL, const SDL_Color &cTR, const SDL_Color &cBL, const SDL_Color &cBR, const SDL_FPoint &uvTL, const SDL_FPoint &uvTR, const SDL_FPoint &uvBL, const SDL_FPoint &uvBR)
Draw a texture with smoothly varying colour and alpha modification, specified at the four corners of ...
Definition: draw.cpp:438
Contains the SDL_Rect helper code.
rect dst
Location on the final composed sheet.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:49
mock_char c
#define b