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