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