The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
draw.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 - 2025
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 <array>
36#include <vector>
37
38#include <SDL3/SDL_render.h>
39
40struct color_t;
41
42namespace 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 */
57void 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 */
74void fill(const ::rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
75void fill(const ::rect& rect, uint8_t r, uint8_t g, uint8_t b);
76void fill(const ::rect& rect, const color_t& color);
77void fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
78void fill(uint8_t r, uint8_t g, uint8_t b);
79void fill(const color_t& color);
80
81void 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 */
93void fill(const ::rect& rect);
94void 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 */
108void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
109void set_color(uint8_t r, uint8_t g, uint8_t b);
110void 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 */
118void 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 */
128void rect(const ::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 */
139void rect(const ::rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
140void rect(const ::rect& rect, uint8_t r, uint8_t g, uint8_t b);
141void rect(const ::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 */
154void 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 */
165void line(int from_x, int from_y, int to_x, int to_y, const color_t& c);
166
167/** Draw a set of points. */
168void points(const std::vector<SDL_FPoint>& points);
169
170/** Draw a single point. */
171void 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 */
192void circle(int x, int y, int r, const color_t& c, uint8_t octants = 0xff);
193void 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 */
210void disc(int x, int y, int r, const color_t& c, uint8_t octants = 0xff);
211void disc(int x, int y, int r, uint8_t octants = 0xff);
212
213/** Draw outline of circle using Cairo */
214void cairo_circle(int cx, int cy, int r, const color_t& c, int thickness);
215
216/** Draw filled circle using Cairo */
217void cairo_disc(int cx, int cy, int r, const color_t& c);
218
219
220/*******************/
221/* texture drawing */
222/*******************/
223
224
225/**
226 * Draws a texture, or part of a texture, at the given location.
227 *
228 * The portion of the texture to be drawn will be scaled to fill
229 * the target rectangle.
230 *
231 * This version takes coordinates in game-native resolution,
232 * which may be lower than the final output resolution in high-dpi
233 * contexts or if pixel scaling is used. The texture will be copied
234 * in high-resolution if possible.
235 *
236 * @param tex The texture to be copied / drawn.
237 * @param dst The target location to copy the texture to,
238 * in low-resolution game-native drawing coordinates.
239 * If null, this fills the entire render target.
240 */
241void blit(const texture& tex, const ::rect& dst);
242void blit(const texture& tex);
243
244/**
245 * Draws a texture, or part of a texture, at the given location,
246 * also mirroring/flipping the texture horizontally and/or vertically.
247 *
248 * By default the texture will be flipped horizontally.
249 *
250 * @param tex The texture to be copied / drawn.
251 * @param dst The target location to copy the texture to,
252 * in low-resolution game-native drawing coordinates.
253 * If not given, the entire render target will be filled.
254 * @param flip_h Whether to flip/mirror the texture horizontally.
255 * @param flip_v Whether to flip/mirror the texture vertically.
256 */
257void flipped(const texture& tex,
258 const ::rect& dst,
259 bool flip_h = true,
260 bool flip_v = false
261);
262void flipped(const texture& tex, bool flip_h = true, bool flip_v = false);
263
264/**
265 * Tile a texture to fill a region.
266 *
267 * This function tiles the texture in draw-space.
268 *
269 * The texture may be aligned either with its center at the center
270 * of the region, or with its top-left corner at the top-left corner
271 * of the region.
272 *
273 * @param tex The texture to use to fill the region.
274 * @param dst The region to fill, in draw space.
275 * @param centered If true the tiled texture will be centered.
276 * If false, it will align at the top-left.
277 * @param mirrored If true the texture will be mirrored in such a way that
278 * adjacent tiles always share a common edge. This can look
279 * better for images that are not perfect tiles.
280 */
281void tiled(const texture& tex,
282 const ::rect& dst,
283 bool centered = false,
284 bool mirrored = false
285);
286
287/** Tile a texture to fill a region.
288 *
289 * This function tiles the texture in output space. It is otherwise
290 * identical to draw::tiled().
291 */
292void tiled_highres(const texture& tex,
293 const ::rect& dst,
294 bool centered = false,
295 bool mirrored = false
296);
297
298/**
299 * Draw a texture with smoothly varying colour and alpha modification,
300 * specified at the four corners of the drawing destination.
301 *
302 * The UV texture coordinates at each corner may also be specified.
303 * If unspecified, the full texture will be drawn.
304 *
305 * Colour modifiers multiply the output colour and alpha by their value
306 * after mapping to the range [0,1]. A value of 255 will have no effect.
307 *
308 * @param tex The texture to draw
309 * @param verts The SDL_Vertex to use
310 */
311void smooth_shaded(const texture& tex,
312 const std::array<SDL_Vertex, 4>& verts
313);
314
315/***************************/
316/* RAII state manipulation */
317/***************************/
318
319
320/** A class to manage automatic restoration of the clipping region.
321 *
322 * This can be constructed on its own, or one of the utility functions
323 * override_clip() and reduce_clip() can be used. Constructing a clip_setter
324 * or using override_clip() will completely override the current clipping area.
325 * To intersect with the current clipping area in stead, use reduce_clip().
326 */
328{
329public:
330 explicit clip_setter(const ::rect& clip);
331 ~clip_setter();
332private:
335};
336
337/**
338 * Override the clipping area. All draw calls will be clipped to this region.
339 *
340 * The clipping area is specified in draw-space coordinates.
341 *
342 * The returned object will reset the clipping area when it is destroyed,
343 * so it should be kept in scope until drawing is complete.
344 *
345 * @param clip The clipping region in draw-space coordinates.
346 * @returns A clip_setter object. When this object is destroyed
347 * the clipping region will be restored to whatever
348 * it was before this call.
349 */
350[[nodiscard]] clip_setter override_clip(const ::rect& clip);
351
352/**
353 * Set the clipping area to the intersection of the current clipping
354 * area and the given rectangle.
355 *
356 * Otherwise acts as override_clip().
357 */
358[[nodiscard]] clip_setter reduce_clip(const ::rect& clip);
359
360/**
361 * Set the clipping area, without any provided way of setting it back.
362 *
363 * @param clip The clipping area, in draw-space coordinates.
364 */
365void force_clip(const ::rect& clip);
366
367/**
368 * Get the current clipping area, in draw coordinates.
369 *
370 * The clipping area is interpreted relative to the current viewport.
371 *
372 * If clipping is disabled, this will return the full drawing area.
373 */
375
376/** Whether clipping is enabled. */
377bool clip_enabled();
378
379/** Disable clipping. To enable clipping, use set_clip() or force_clip(). */
380void disable_clip();
381
382/**
383 * Whether the current clipping region will disallow drawing.
384 *
385 * This returns true for any clipping region with negative or zero width
386 * or height.
387 */
388bool null_clip();
389
390
391/** A class to manage automatic restoration of the viewport region.
392 *
393 * This will also translate the current clipping region into the space
394 * of the viewport, if a clipping region is set.
395 *
396 * This can be constructed on its own, or the draw::set_viewport()
397 * utility function can be used.
398 */
400{
401public:
402 explicit viewport_setter(const ::rect& viewport);
404private:
408};
409
410/**
411 * Set the viewport. Drawing operations will have their coordinates
412 * adjusted to the viewport.
413 *
414 * The top-left corner of the viewport will be interpreted as (0,0) in
415 * draw space coordinates while the returned object is in scope.
416 *
417 * The new viewport is specified in absolute coordinates, relative to the
418 * full drawing surface.
419 *
420 * The returned object will reset the viewport when it is destroyed, so
421 * it should be kept in scope until viewport-relative drawing is complete.
422 *
423 * @param viewport The new viewport region, relative to the current
424 * viewport.
425 * @returns A viewport_setter object. When this object is
426 * destroyed the viewport will be restored to whatever
427 * it was before this call.
428 */
429[[nodiscard]] viewport_setter set_viewport(const ::rect& viewport);
430
431/**
432 * Set the viewport, without any provided way of setting it back.
433 *
434 * The new viewport is specified in absolute coordinates, relative to the
435 * full drawing surface.
436 *
437 * @param viewport The viewport, in absolute draw-space coordinates.
438 * If null, the viewport is reset to the full draw area.
439 */
440void force_viewport(const ::rect& viewport);
441
442/**
443 * Get the current viewport.
444 *
445 * @returns The current viewport, in the coordinate space of
446 * the original drawing surface
447 */
449
450
451/**
452 * A class to manage automatic restoration of the render target.
453 *
454 * It will also cache and restore the current viewport.
455 *
456 * This can be constructed on its own, or the draw::set_render_target()
457 * utility function can be used.
458 */
460{
461public:
462 explicit render_target_setter(const texture& t);
464
465private:
469};
470
471/**
472 * Set the given texture as the active render target.
473 *
474 * The current viewport will also be cached and restored along with the
475 * render target.
476 *
477 * All draw calls will draw to this texture until the returned object
478 * goes out of scope. Do not retain the render_target_setter longer
479 * than necessary.
480 *
481 * The provided texture must have been created with the
482 * SDL_TEXTUREACCESS_TARGET access mode.
483 *
484 * @param t The new render target. This must be a texture created
485 * with SDL_TEXTUREACCESS_TARGET, or an empty texture.
486 * If empty, it will set the render target to Wesnoth's
487 * primary render buffer.
488 * @returns A render_target_setter object. When this object is
489 * destroyed the render target will be restored to
490 * whatever it was before this call.
491 */
492[[nodiscard]] render_target_setter set_render_target(const texture& t);
493
494
495} // namespace draw
double t
A class to manage automatic restoration of the clipping region.
Definition draw.hpp:328
A class to manage automatic restoration of the render target.
Definition draw.hpp:460
A class to manage automatic restoration of the viewport region.
Definition draw.hpp:400
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition texture.hpp:33
Definition draw.hpp:43
void force_viewport(const ::rect &viewport)
Set the viewport, without any provided way of setting it back.
Definition draw.cpp:694
void tiled_highres(const texture &tex, const ::rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
Definition draw.cpp:522
render_target_setter set_render_target(const texture &t)
Set the given texture as the active render target.
Definition draw.cpp:757
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:234
void tiled(const texture &tex, const ::rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
Definition draw.cpp:494
void points(const std::vector< SDL_FPoint > &points)
Draw a set of points.
Definition draw.cpp:219
void cairo_disc(int cx, int cy, int r, const color_t &c)
Draw filled circle using Cairo.
Definition draw.cpp:373
bool null_clip()
Whether the current clipping region will disallow drawing.
Definition draw.cpp:648
bool clip_enabled()
Whether clipping is enabled.
Definition draw.cpp:631
clip_setter reduce_clip(const ::rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
Definition draw.cpp:595
void flipped(const texture &tex, const ::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:452
void cairo_circle(int cx, int cy, int r, const color_t &c, int thickness)
Draw outline of circle using Cairo.
Definition draw.cpp:335
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:277
void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Set the drawing colour.
Definition draw.cpp:121
clip_setter override_clip(const ::rect &clip)
Override the clipping area.
Definition draw.cpp:590
void clear()
Clear the current render target.
Definition draw.cpp:52
void smooth_shaded(const texture &tex, const std::array< SDL_Vertex, 4 > &verts)
Draw a texture with smoothly varying colour and alpha modification, specified at the four corners of ...
Definition draw.cpp:556
void fill()
Definition draw.cpp:115
void set_blend_mode(SDL_BlendMode b)
Set the blend mode used for drawing operations such as fill() and line().
Definition draw.cpp:139
void force_clip(const ::rect &clip)
Set the clipping area, without any provided way of setting it back.
Definition draw.cpp:603
viewport_setter set_viewport(const ::rect &viewport)
Set the viewport.
Definition draw.cpp:689
::rect get_viewport()
Get the current viewport.
Definition draw.cpp:705
::rect get_clip()
Get the current clipping area, in draw coordinates.
Definition draw.cpp:615
void disable_clip()
Disable clipping.
Definition draw.cpp:639
void blit(const texture &tex, const ::rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition draw.cpp:409
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition draw.cpp:203
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:51
Holds a 2D point.
Definition point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
#define g
#define c
#define b