The Battle for Wesnoth  1.17.23+dev
draw.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2022 - 2023
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 #include "draw.hpp"
16 
17 #include "color.hpp"
18 #include "log.hpp"
19 #include "sdl/rect.hpp"
20 #include "sdl/surface.hpp"
21 #include "sdl/texture.hpp"
22 #include "sdl/utils.hpp" // sdl::runtime_at_least
23 #include "video.hpp"
24 
25 #include <SDL2/SDL_rect.h>
26 #include <SDL2/SDL_render.h>
27 
28 static lg::log_domain log_draw("draw");
29 #define DBG_D LOG_STREAM(debug, log_draw)
30 #define WRN_D LOG_STREAM(warn, log_draw)
31 
32 static SDL_Renderer* renderer()
33 {
34  return video::get_renderer();
35 }
36 
37 /**************************************/
38 /* basic drawing and pixel primatives */
39 /**************************************/
40 
42 {
43  DBG_D << "clear";
44  SDL_BlendMode b;
45  SDL_GetRenderDrawBlendMode(renderer(), &b);
46  SDL_SetRenderDrawBlendMode(renderer(), SDL_BLENDMODE_NONE);
47  fill(0, 0, 0, 0);
48  SDL_SetRenderDrawBlendMode(renderer(), b);
49 }
50 
52  const SDL_Rect& area,
53  uint8_t r, uint8_t g, uint8_t b, uint8_t a)
54 {
55  DBG_D << "fill " << area << ' ' << color_t{r,g,b,a};
56  SDL_SetRenderDrawColor(renderer(), r, g, b, a);
57  SDL_RenderFillRect(renderer(), &area);
58 }
59 
61  const SDL_Rect& area,
62  uint8_t r, uint8_t g, uint8_t b)
63 {
64  draw::fill(area, r, g, b, SDL_ALPHA_OPAQUE);
65 }
66 
67 void draw::fill(const SDL_Rect& area, const color_t& c)
68 {
69  draw::fill(area, c.r, c.g, c.b, c.a);
70 }
71 
72 void draw::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
73 {
74  DBG_D << "fill " << color_t{r,g,b,a};
75  SDL_SetRenderDrawColor(renderer(), r, g, b, a);
76  SDL_RenderFillRect(renderer(), nullptr);
77 }
78 
79 void draw::fill(uint8_t r, uint8_t g, uint8_t b)
80 {
81  draw::fill(r, g, b, SDL_ALPHA_OPAQUE);
82 }
83 
84 void draw::fill(const color_t& c)
85 {
86  draw::fill(c.r, c.g, c.b, c.a);
87 }
88 
89 void draw::fill(const SDL_Rect& area)
90 {
91  DBG_D << "fill " << area;
92  SDL_RenderFillRect(renderer(), &area);
93 }
94 
95 void draw::fill()
96 {
97  DBG_D << "fill";
98  SDL_RenderFillRect(renderer(), nullptr);
99 }
100 
101 void draw::set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
102 {
103  DBG_D << "set color " << color_t{r,g,b,a};
104  SDL_SetRenderDrawColor(renderer(), r, g, b, a);
105 }
106 
107 void draw::set_color(uint8_t r, uint8_t g, uint8_t b)
108 {
109  DBG_D << "set color " << color_t{r,g,b};
110  SDL_SetRenderDrawColor(renderer(), r, g, b, SDL_ALPHA_OPAQUE);
111 }
112 
114 {
115  DBG_D << "set color " << c;
116  SDL_SetRenderDrawColor(renderer(), c.r, c.g, c.b, c.a);
117 }
118 
119 void draw::set_blend_mode(SDL_BlendMode b)
120 {
121  SDL_SetRenderDrawBlendMode(renderer(), b);
122 }
123 
124 /** Some versions of SDL have a bad rectangle drawing implementation. */
125 static bool sdl_bad_at_rects()
126 {
127  // This could be done once at program start and cached,
128  // but it isn't all that heavy.
129  if (sdl::runtime_at_least(2,0,15) && !sdl::runtime_at_least(2,0,18)) {
130  return true;
131  }
132  return false;
133 }
134 
135 /** For some SDL versions, draw rectangles as lines. */
136 static void draw_rect_as_lines(const SDL_Rect& rect)
137 {
138  // w and h indicate the final pixel width/height of the box.
139  // This is 1 greater than the difference in corner coordinates.
140  if (rect.w <= 0 || rect.h <= 0) {
141  return;
142  }
143  int x2 = rect.x + rect.w - 1;
144  int y2 = rect.y + rect.h - 1;
145  draw::line(rect.x, rect.y, x2, rect.y);
146  draw::line(rect.x, rect.y, rect.x, y2);
147  draw::line(x2, rect.y, x2, y2);
148  draw::line(rect.x, y2, x2, y2);
149 }
150 
151 void draw::rect(const SDL_Rect& rect)
152 {
153  DBG_D << "rect " << rect;
154  if (sdl_bad_at_rects()) {
155  return draw_rect_as_lines(rect);
156  }
157  SDL_RenderDrawRect(renderer(), &rect);
158 }
159 
160 void draw::rect(const SDL_Rect& rect,
161  uint8_t r, uint8_t g, uint8_t b, uint8_t a)
162 {
163  DBG_D << "rect " << rect << ' ' << color_t{r,g,b,a};
164  SDL_SetRenderDrawColor(renderer(), r, g, b, a);
165  if (sdl_bad_at_rects()) {
166  return draw_rect_as_lines(rect);
167  }
168  SDL_RenderDrawRect(renderer(), &rect);
169 }
170 
171 void draw::rect(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b)
172 {
173  draw::rect(rect, r, g, b, SDL_ALPHA_OPAQUE);
174 }
175 
176 void draw::rect(const SDL_Rect& rect, const color_t& c)
177 {
178  draw::rect(rect, c.r, c.g, c.b, c.a);
179 }
180 
181 void draw::line(int from_x, int from_y, int to_x, int to_y)
182 {
183  DBG_D << "line from (" << from_x << ',' << from_y
184  << ") to (" << to_x << ',' << to_y << ')';
185  SDL_RenderDrawLine(renderer(), from_x, from_y, to_x, to_y);
186 }
187 
188 void draw::line(int from_x, int from_y, int to_x, int to_y, const color_t& c)
189 {
190  DBG_D << "line from (" << from_x << ',' << from_y
191  << ") to (" << to_x << ',' << to_y
192  << ") with colour " << c;
193  SDL_SetRenderDrawColor(renderer(), c.r, c.g, c.b, c.a);
194  SDL_RenderDrawLine(renderer(), from_x, from_y, to_x, to_y);
195 }
196 
197 void draw::points(const std::vector<SDL_Point>& points)
198 {
199  DBG_D << points.size() << " points";
200  SDL_RenderDrawPoints(renderer(), points.data(), points.size());
201 }
202 
203 void draw::point(int x, int y)
204 {
205  DBG_D << "point (" << x << ',' << y << ')';
206  SDL_RenderDrawPoint(renderer(), x, y);
207 }
208 
209 void draw::circle(int cx, int cy, int r, const color_t& c, uint8_t octants)
210 {
212  draw::circle(cx, cy, r, octants);
213 }
214 
215 void draw::circle(int cx, int cy, int r, uint8_t octants)
216 {
217  DBG_D << "circle (" << cx << ',' << cy
218  << ") -> " << r << ", oct " << int(octants);
219 
220  // Algorithm based on
221  // http://de.wikipedia.org/wiki/Rasterung_von_Kreisen#Methode_von_Horn
222  // version of 2011.02.07.
223  int d = -r;
224  int x = r;
225  int y = 0;
226 
227  std::vector<SDL_Point> points;
228 
229  while(!(y > x)) {
230  if(octants & 0x04) points.push_back({cx + x, cy + y});
231  if(octants & 0x02) points.push_back({cx + x, cy - y});
232  if(octants & 0x20) points.push_back({cx - x, cy + y});
233  if(octants & 0x40) points.push_back({cx - x, cy - y});
234 
235  if(octants & 0x08) points.push_back({cx + y, cy + x});
236  if(octants & 0x01) points.push_back({cx + y, cy - x});
237  if(octants & 0x10) points.push_back({cx - y, cy + x});
238  if(octants & 0x80) points.push_back({cx - y, cy - x});
239 
240  d += 2 * y + 1;
241  ++y;
242  if(d > 0) {
243  d += -2 * x + 2;
244  --x;
245  }
246  }
247 
249 }
250 
251 void draw::disc(int cx, int cy, int r, const color_t& c, uint8_t octants)
252 {
254  draw::disc(cx, cy, r, octants);
255 }
256 
257 void draw::disc(int cx, int cy, int r, uint8_t octants)
258 {
259  DBG_D << "disc (" << cx << ',' << cy
260  << ") -> " << r << ", oct " << int(octants);
261 
262  int d = -r;
263  int x = r;
264  int y = 0;
265 
266  while(!(y > x)) {
267  // I use the formula of Bresenham's line algorithm
268  // to determine the boundaries of a segment.
269  // The slope of the line is always 1 or -1 in this case.
270  if(octants & 0x04)
271  // x2 - 1 = y2 - (cy + 1) + cx
272  draw::line(cx + x, cy + y + 1, cx + y + 1, cy + y + 1);
273  if(octants & 0x02)
274  // x2 - 1 = cy - y2 + cx
275  draw::line(cx + x, cy - y, cx + y + 1, cy - y);
276  if(octants & 0x20)
277  // x2 + 1 = (cy + 1) - y2 + (cx - 1)
278  draw::line(cx - x - 1, cy + y + 1, cx - y - 2, cy + y + 1);
279  if(octants & 0x40)
280  // x2 + 1 = y2 - cy + (cx - 1)
281  draw::line(cx - x - 1, cy - y, cx - y - 2, cy - y);
282 
283  if(octants & 0x08)
284  // y2 = x2 - cx + (cy + 1)
285  draw::line(cx + y, cy + x + 1, cx + y, cy + y + 1);
286  if(octants & 0x01)
287  // y2 = cx - x2 + cy
288  draw::line(cx + y, cy - x, cx + y, cy - y);
289  if(octants & 0x10)
290  // y2 = (cx - 1) - x2 + (cy + 1)
291  draw::line(cx - y - 1, cy + x + 1, cx - y - 1, cy + y + 1);
292  if(octants & 0x80)
293  // y2 = x2 - (cx - 1) + cy
294  draw::line(cx - y - 1, cy - x, cx - y - 1, cy - y);
295 
296  d += 2 * y + 1;
297  ++y;
298  if(d > 0) {
299  d += -2 * x + 2;
300  --x;
301  }
302  }
303 }
304 
305 
306 /*******************/
307 /* texture drawing */
308 /*******************/
309 
310 
311 void draw::blit(const texture& tex, const SDL_Rect& dst)
312 {
313  if (dst == sdl::empty_rect) {
314  return draw::blit(tex);
315  }
316 
317  if (!tex) { DBG_D << "null blit"; return; }
318  DBG_D << "blit " << dst;
319 
320  SDL_RenderCopy(renderer(), tex, tex.src(), &dst);
321 }
322 
323 void draw::blit(const texture& tex)
324 {
325  if (!tex) { DBG_D << "null blit"; return; }
326  DBG_D << "blit";
327 
328  SDL_RenderCopy(renderer(), tex, tex.src(), nullptr);
329 }
330 
331 
332 static SDL_RendererFlip get_flip(bool flip_h, bool flip_v)
333 {
334  // This should be easier than it is.
335  return static_cast<SDL_RendererFlip>(
336  static_cast<int>(flip_h ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE)
337  | static_cast<int>(flip_v ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE)
338  );
339 }
340 
342  const texture& tex,
343  const SDL_Rect& dst,
344  bool flip_h,
345  bool flip_v)
346 {
347  if (dst == sdl::empty_rect) {
348  return draw::flipped(tex, flip_h, flip_v);
349  }
350 
351  if (!tex) { DBG_D << "null flipped"; return; }
352  DBG_D << "flipped (" << flip_h << '|' << flip_v
353  << ") to " << dst;
354 
355  SDL_RendererFlip flip = get_flip(flip_h, flip_v);
356  SDL_RenderCopyEx(renderer(), tex, tex.src(), &dst, 0.0, nullptr, flip);
357 }
358 
359 void draw::flipped(const texture& tex, bool flip_h, bool flip_v)
360 {
361  if (!tex) { DBG_D << "null flipped"; return; }
362  DBG_D << "flipped (" << flip_h << '|' << flip_v << ')';
363 
364  SDL_RendererFlip flip = get_flip(flip_h, flip_v);
365  SDL_RenderCopyEx(renderer(), tex, tex.src(), nullptr, 0.0, nullptr, flip);
366 }
367 
368 
369 // TODO: highdpi - maybe expose this mirrored mode to WML somehow
370 void draw::tiled(const texture& tex, const SDL_Rect& dst, bool centered,
371  bool mirrored)
372 {
373  if (!tex) { DBG_D << "null tiled"; return; }
374  DBG_D << "tiled (" << centered << '|' << mirrored
375  << ") " << dst;
376 
377  // Reduce clip to dst.
378  auto clipper = draw::reduce_clip(dst);
379 
380  const int xoff = centered ? (dst.w - tex.w()) / 2 : 0;
381  const int yoff = centered ? (dst.h - tex.h()) / 2 : 0;
382 
383  // Just blit the image however many times is necessary.
384  bool vf = false;
385  SDL_Rect t{dst.x - xoff, dst.y - yoff, tex.w(), tex.h()};
386  for (; t.y < dst.y + dst.h; t.y += t.h, vf = !vf) {
387  bool hf = false;
388  for (t.x = dst.x - xoff; t.x < dst.x + dst.w; t.x += t.w, hf = !hf) {
389  if (mirrored) {
390  draw::flipped(tex, t, hf, vf);
391  } else {
392  draw::blit(tex, t);
393  }
394  }
395  }
396 }
397 
398 void draw::tiled_highres(const texture& tex, const SDL_Rect& dst,
399  bool centered, bool mirrored)
400 {
401  if (!tex) { DBG_D << "null tiled_highres"; return; }
402  DBG_D << "tiled_highres (" << centered << '|' << mirrored
403  << ") " << dst;
404 
405  const int pixel_scale = video::get_pixel_scale();
406 
407  // Reduce clip to dst.
408  auto clipper = draw::reduce_clip(dst);
409 
411  const float w = float(size.x) / float(pixel_scale);
412  const float h = float(size.y) / float(pixel_scale);
413  const float xoff = centered ? (dst.w - w) / 2 : 0.0f;
414  const float yoff = centered ? (dst.h - h) / 2 : 0.0f;
415 
416  // Just blit the image however many times is necessary.
417  bool vf = false;
418  SDL_FRect t{dst.x - xoff, dst.y - yoff, w, h};
419  for (; t.y < dst.y + dst.h; t.y += t.h, vf = !vf) {
420  bool hf = false;
421  for (t.x = dst.x - xoff; t.x < dst.x + dst.w; t.x += t.w, hf = !hf) {
422  if (mirrored) {
423  SDL_RendererFlip flip = get_flip(hf, vf);
424  SDL_RenderCopyExF(renderer(), tex, nullptr, &t, 0.0, nullptr, flip);
425  } else {
426  SDL_RenderCopyF(renderer(), tex, nullptr, &t);
427  }
428  }
429  }
430 }
431 
432 
433 /***************************/
434 /* RAII state manipulation */
435 /***************************/
436 
437 
438 draw::clip_setter::clip_setter(const SDL_Rect& clip)
439  : c_(draw::get_clip()), clip_enabled_(draw::clip_enabled())
440 {
441  draw::force_clip(clip);
442 }
443 
445 {
446  if (clip_enabled_) {
447  draw::force_clip(c_);
448  } else {
450  }
451 }
452 
454 {
455  return draw::clip_setter(clip);
456 }
457 
459 {
460  if (!draw::clip_enabled()) {
461  return draw::clip_setter(clip);
462  }
463  return draw::clip_setter(draw::get_clip().intersect(clip));
464 }
465 
466 void draw::force_clip(const SDL_Rect& clip)
467 {
468  // TODO: highdpi - fix whatever reason there is for this guard (CI fail)
469  if (!renderer()) {
470  WRN_D << "trying to force clip will null renderer";
471  return;
472  }
473  DBG_D << "forcing clip to " << clip;
474 
475  SDL_RenderSetClipRect(renderer(), &clip);
476 }
477 
479 {
480  // TODO: highdpi - fix whatever reason there is for this guard (CI fail)
481  if (!renderer()) {
482  return sdl::empty_rect;
483  }
484 
485  if (!SDL_RenderIsClipEnabled(renderer())) {
486  return draw::get_viewport();
487  }
488 
489  ::rect clip;
490  SDL_RenderGetClipRect(renderer(), &clip);
491  return clip;
492 }
493 
495 {
496  if (!renderer()) {
497  return false;
498  }
499  return SDL_RenderIsClipEnabled(renderer());
500 }
501 
503 {
504  if (!renderer()) {
505  return;
506  }
507  SDL_RenderSetClipRect(renderer(), nullptr);
508  DBG_D << "clip disabled";
509 }
510 
512 {
513  if (!renderer()) {
514  return true;
515  }
516  if (!SDL_RenderIsClipEnabled(renderer())) {
517  return false;
518  }
519  SDL_Rect clip;
520  SDL_RenderGetClipRect(renderer(), &clip);
521  return clip.w <= 0 || clip.h <= 0;
522 }
523 
524 
526  : v_(), c_(), clip_enabled_(draw::clip_enabled())
527 {
529  draw::force_viewport(view);
530  if (clip_enabled_) {
531  c_ = draw::get_clip();
532  // adjust clip for difference in viewport position
533  SDL_Rect c_view = {
534  c_.x + v_.x - view.x,
535  c_.y + v_.y - view.y,
536  c_.w, c_.h
537  };
538  draw::force_clip(c_view);
539  }
540 }
541 
543 {
545  if (clip_enabled_) {
546  draw::force_clip(c_);
547  } else {
549  }
550 }
551 
552 draw::viewport_setter draw::set_viewport(const SDL_Rect& viewport)
553 {
554  return draw::viewport_setter(viewport);
555 }
556 
557 void draw::force_viewport(const SDL_Rect& viewport)
558 {
559  if (!renderer()) {
560  WRN_D << "trying to force viewport will null renderer";
561  return;
562  }
563  DBG_D << "forcing viewport to " << viewport;
564 
565  SDL_RenderSetViewport(renderer(), &viewport);
566 }
567 
569 {
570  if (!renderer()) {
571  WRN_D << "no renderer available to get viewport";
572  return sdl::empty_rect;
573  }
574 
575  SDL_Rect viewport;
576  SDL_RenderGetViewport(renderer(), &viewport);
577 
578  if (viewport == sdl::empty_rect) {
579  return video::draw_area();
580  }
581  return viewport;
582 }
583 
584 
586  : target_()
587  , viewport_()
588 {
589  // Validate we can render to this texture.
590  assert(!t || t.get_access() == SDL_TEXTUREACCESS_TARGET);
591 
592  if (!renderer()) {
593  WRN_D << "can't set render target with null renderer";
594  return;
595  }
596 
598  SDL_RenderGetViewport(renderer(), &viewport_);
599 
600  if (t) {
602  } else {
604  }
605 }
606 
608 {
609  if (!renderer()) {
610  WRN_D << "can't reset render target with null renderer";
611  return;
612  }
614  SDL_RenderSetViewport(renderer(), &viewport_);
615 }
616 
618 {
619  if (t) {
620  DBG_D << "setting render target to "
621  << t.w() << 'x' << t.h() << " texture";
622  } else {
623  DBG_D << "setting render target to main render buffer";
624  }
626 }
double t
Definition: astarsearch.cpp:65
double g
Definition: astarsearch.cpp:65
A class to manage automatic restoration of the clipping region.
Definition: draw.hpp:304
clip_setter(const SDL_Rect &clip)
Definition: draw.cpp:438
A class to manage automatic restoration of the render target.
Definition: draw.hpp:436
render_target_setter(const texture &t)
Definition: draw.cpp:585
A class to manage automatic restoration of the viewport region.
Definition: draw.hpp:376
viewport_setter(const SDL_Rect &viewport)
Definition: draw.cpp:525
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
int w() const
The draw-space width of the texture, in pixels.
Definition: texture.hpp:105
point get_raw_size() const
The raw internal texture size.
Definition: texture.cpp:112
const rect * src() const
A pointer to a rect indicating the source region of the underlying SDL_Texture to be used when drawin...
Definition: texture.hpp:148
int h() const
The draw-space height of the texture, in pixels.
Definition: texture.hpp:114
static lg::log_domain log_draw("draw")
static bool sdl_bad_at_rects()
Some versions of SDL have a bad rectangle drawing implementation.
Definition: draw.cpp:125
static SDL_Renderer * renderer()
Definition: draw.cpp:32
static void draw_rect_as_lines(const SDL_Rect &rect)
For some SDL versions, draw rectangles as lines.
Definition: draw.cpp:136
#define WRN_D
Definition: draw.cpp:30
static SDL_RendererFlip get_flip(bool flip_h, bool flip_v)
Definition: draw.cpp:332
#define DBG_D
Definition: draw.cpp:29
Drawing functions, for drawing things on the screen.
int w
Standard logging facilities (interface).
Definition: draw.hpp:43
viewport_setter set_viewport(const SDL_Rect &viewport)
Set the viewport.
Definition: draw.cpp:552
void force_viewport(const SDL_Rect &viewport)
Set the viewport, without any provided way of setting it back.
Definition: draw.cpp:557
render_target_setter set_render_target(const texture &t)
Set the given texture as the active render target.
Definition: draw.cpp:617
clip_setter override_clip(const SDL_Rect &clip)
Override the clipping area.
Definition: draw.cpp:453
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:209
void points(const std::vector< SDL_Point > &points)
Draw a set of points.
Definition: draw.cpp:197
void force_clip(const SDL_Rect &clip)
Set the clipping area, without any provided way of setting it back.
Definition: draw.cpp:466
SDL_Rect get_viewport()
Get the current viewport.
Definition: draw.cpp:568
bool null_clip()
Whether the current clipping region will disallow drawing.
Definition: draw.cpp:511
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:458
bool clip_enabled()
Whether clipping is enabled.
Definition: draw.cpp:494
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:370
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:251
void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Set the drawing colour.
Definition: draw.cpp:101
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:341
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:51
void point(int x, int y)
Draw a single point.
Definition: draw.cpp:203
void clear()
Clear the current render target.
Definition: draw.cpp:41
void set_blend_mode(SDL_BlendMode b)
Set the blend mode used for drawing operations such as fill() and line().
Definition: draw.cpp:119
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:311
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:398
::rect get_clip()
Get the current clipping area, in draw coordinates.
Definition: draw.cpp:478
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:151
void disable_clip()
Disable clipping.
Definition: draw.cpp:502
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:181
int pixel_scale()
Definition: general.cpp:408
constexpr const SDL_Rect empty_rect
Definition: rect.hpp:30
bool runtime_at_least(uint8_t major, uint8_t minor=0, uint8_t patch=0)
Returns true if the runtime SDL version is at or greater than the specified version,...
Definition: utils.cpp:41
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
rect draw_area()
The current drawable area.
Definition: video.cpp:448
void reset_render_target()
Reset the render target to the primary render buffer.
Definition: video.cpp:534
void force_render_target(const texture &t)
Set the render target, without any provided way of setting it back.
Definition: video.cpp:498
int get_pixel_scale()
Get the current active pixel scale multiplier.
Definition: video.cpp:487
SDL_Renderer * get_renderer()
Definition: video.cpp:650
texture get_render_target()
Get the current render target.
Definition: video.cpp:539
Contains the SDL_Rect helper code.
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:47
mock_char c
#define d
#define h
#define a
#define b