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