The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
draw.cpp
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#include "draw.hpp"
16
17#include "color.hpp"
18#include "font/cairo.hpp"
19#include "log.hpp"
20#include "sdl/rect.hpp"
21#include "sdl/texture.hpp"
22#include "sdl/utils.hpp" // sdl::runtime_at_least
23#include "video.hpp"
24
25#include <boost/math/constants/constants.hpp>
26#include <SDL3/SDL_rect.h>
27#include <SDL3/SDL_render.h>
28
29static lg::log_domain log_draw("draw");
30#define DBG_D LOG_STREAM(debug, log_draw)
31#define WRN_D LOG_STREAM(warn, log_draw)
32
33static SDL_Renderer* renderer()
34{
35 return video::get_renderer();
36}
37
38static SDL_FRect rect_to_frect(const SDL_Rect& rect)
39{
40 SDL_FRect frect;
41 frect.h = rect.h;
42 frect.w = rect.w;
43 frect.x = rect.x;
44 frect.y = rect.y;
45 return frect;
46}
47
48/**************************************/
49/* basic drawing and pixel primatives */
50/**************************************/
51
53{
54 DBG_D << "clear";
55 SDL_BlendMode b;
56 SDL_GetRenderDrawBlendMode(renderer(), &b);
57 SDL_SetRenderDrawBlendMode(renderer(), SDL_BLENDMODE_NONE);
58 fill(0, 0, 0, 0);
59 SDL_SetRenderDrawBlendMode(renderer(), b);
60}
61
63 const ::rect& area,
64 uint8_t r, uint8_t g, uint8_t b, uint8_t a)
65{
66 DBG_D << "fill " << area << ' ' << color_t{r,g,b,a};
67 SDL_SetRenderDrawColor(renderer(), r, g, b, a);
68 SDL_FRect frect = rect_to_frect(area);
69 SDL_RenderFillRect(renderer(), &frect);
70}
71
73 const ::rect& area,
74 uint8_t r, uint8_t g, uint8_t b)
75{
76 draw::fill(area, r, g, b, SDL_ALPHA_OPAQUE);
77}
78
79void draw::fill(const ::rect& area, const color_t& c)
80{
81 draw::fill(area, c.r, c.g, c.b, c.a);
82}
83
84void draw::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
85{
86 DBG_D << "fill " << color_t{r,g,b,a};
87 SDL_SetRenderDrawColor(renderer(), r, g, b, a);
88 SDL_RenderFillRect(renderer(), nullptr);
89}
90
91void draw::fill(uint8_t r, uint8_t g, uint8_t b)
92{
93 draw::fill(r, g, b, SDL_ALPHA_OPAQUE);
94}
95
96void draw::fill(const color_t& c)
97{
98 draw::fill(c.r, c.g, c.b, c.a);
99}
100
101void draw::fill(const SDL_FRect& rect, const color_t& c)
102{
103 DBG_D << "sub-pixel fill";
104 SDL_SetRenderDrawColor(renderer(), c.r, c.g, c.b, c.a);
105 SDL_RenderFillRect(renderer(), &rect);
106}
107
108void draw::fill(const ::rect& area)
109{
110 DBG_D << "fill " << area;
111 SDL_FRect frect = rect_to_frect(area);
112 SDL_RenderFillRect(renderer(), &frect);
113}
114
116{
117 DBG_D << "fill";
118 SDL_RenderFillRect(renderer(), nullptr);
119}
120
121void draw::set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
122{
123 DBG_D << "set color " << color_t{r,g,b,a};
124 SDL_SetRenderDrawColor(renderer(), r, g, b, a);
125}
126
127void draw::set_color(uint8_t r, uint8_t g, uint8_t b)
128{
129 DBG_D << "set color " << color_t{r,g,b};
130 SDL_SetRenderDrawColor(renderer(), r, g, b, SDL_ALPHA_OPAQUE);
131}
132
134{
135 DBG_D << "set color " << c;
136 SDL_SetRenderDrawColor(renderer(), c.r, c.g, c.b, c.a);
137}
138
139void draw::set_blend_mode(SDL_BlendMode b)
140{
141 SDL_SetRenderDrawBlendMode(renderer(), b);
142}
143
144/** Some versions of SDL have a bad rectangle drawing implementation. */
145static bool sdl_bad_at_rects()
146{
147 // This could be done once at program start and cached,
148 // but it isn't all that heavy.
149 if (sdl::runtime_at_least(2,0,15) && !sdl::runtime_at_least(2,0,18)) {
150 return true;
151 }
152 return false;
153}
154
155/** For some SDL versions, draw rectangles as lines. */
156static void draw_rect_as_lines(const rect& rect)
157{
158 // w and h indicate the final pixel width/height of the box.
159 // This is 1 greater than the difference in corner coordinates.
160 if (rect.w <= 0 || rect.h <= 0) {
161 return;
162 }
163 int x2 = rect.x + rect.w - 1;
164 int y2 = rect.y + rect.h - 1;
165 draw::line(rect.x, rect.y, x2, rect.y);
166 draw::line(rect.x, rect.y, rect.x, y2);
167 draw::line(x2, rect.y, x2, y2);
168 draw::line(rect.x, y2, x2, y2);
169}
170
171void draw::rect(const ::rect& rect)
172{
173 DBG_D << "rect " << rect;
174 if (sdl_bad_at_rects()) {
175 return draw_rect_as_lines(rect);
176 }
177 SDL_FRect frect = rect_to_frect(rect);
178 SDL_RenderRect(renderer(), &frect);
179}
180
181void draw::rect(const ::rect& rect,
182 uint8_t r, uint8_t g, uint8_t b, uint8_t a)
183{
184 DBG_D << "rect " << rect << ' ' << color_t{r,g,b,a};
185 SDL_SetRenderDrawColor(renderer(), r, g, b, a);
186 if (sdl_bad_at_rects()) {
187 return draw_rect_as_lines(rect);
188 }
189 SDL_FRect frect = rect_to_frect(rect);
190 SDL_RenderRect(renderer(), &frect);
191}
192
193void draw::rect(const ::rect& rect, uint8_t r, uint8_t g, uint8_t b)
194{
195 draw::rect(rect, r, g, b, SDL_ALPHA_OPAQUE);
196}
197
198void draw::rect(const ::rect& rect, const color_t& c)
199{
200 draw::rect(rect, c.r, c.g, c.b, c.a);
201}
202
203void draw::line(int from_x, int from_y, int to_x, int to_y)
204{
205 DBG_D << "line from (" << from_x << ',' << from_y
206 << ") to (" << to_x << ',' << to_y << ')';
207 SDL_RenderLine(renderer(), from_x, from_y, to_x, to_y);
208}
209
210void draw::line(int from_x, int from_y, int to_x, int to_y, const color_t& c)
211{
212 DBG_D << "line from (" << from_x << ',' << from_y
213 << ") to (" << to_x << ',' << to_y
214 << ") with colour " << c;
215 SDL_SetRenderDrawColor(renderer(), c.r, c.g, c.b, c.a);
216 SDL_RenderLine(renderer(), from_x, from_y, to_x, to_y);
217}
218
219void draw::points(const std::vector<SDL_FPoint>& points)
220{
221 // We cannot decay vector<point> to SDL_Point* unless the two types are the same size.
222 static_assert(sizeof(::point) == sizeof(SDL_Point));
223
224 DBG_D << points.size() << " points";
225 SDL_RenderPoints(renderer(), points.data(), points.size());
226}
227
228void draw::point(int x, int y)
229{
230 DBG_D << "point (" << x << ',' << y << ')';
231 SDL_RenderPoint(renderer(), x, y);
232}
233
234void draw::circle(int cx, int cy, int r, const color_t& c, uint8_t octants)
235{
237 draw::circle(cx, cy, r, octants);
238}
239
240void draw::circle(int cx, int cy, int r, uint8_t octants)
241{
242 DBG_D << "circle (" << cx << ',' << cy
243 << ") -> " << r << ", oct " << int(octants);
244
245 // Algorithm based on
246 // http://de.wikipedia.org/wiki/Rasterung_von_Kreisen#Methode_von_Horn
247 // version of 2011.02.07.
248 int d = -r;
249 int x = r;
250 int y = 0;
251
252 std::vector<SDL_FPoint> points;
253
254 if(octants & 0x08) {
255 points.push_back({static_cast<float>(cx + y), static_cast<float>(cy + x)});
256 }
257 if(octants & 0x01) {
258 points.push_back({static_cast<float>(cx + y), static_cast<float>(cy - x)});
259 }
260 if(octants & 0x10) {
261 points.push_back({static_cast<float>(cx - y), static_cast<float>(cy + x)});
262 }
263 if(octants & 0x80) {
264 points.push_back({static_cast<float>(cx - y), static_cast<float>(cy - x)});
265 }
266
267 d += 2 * y + 1;
268 ++y;
269 if(d > 0) {
270 d += -2 * x + 2;
271 --x;
272 }
273
275}
276
277void draw::disc(int cx, int cy, int r, const color_t& c, uint8_t octants)
278{
280 draw::disc(cx, cy, r, octants);
281}
282
283void draw::disc(int cx, int cy, int r, uint8_t octants)
284{
285 DBG_D << "disc (" << cx << ',' << cy
286 << ") -> " << r << ", oct " << int(octants);
287
288 int d = -r;
289 int x = r;
290 int y = 0;
291
292 while(!(y > x)) {
293 // I use the formula of Bresenham's line algorithm
294 // to determine the boundaries of a segment.
295 // The slope of the line is always 1 or -1 in this case.
296 if(octants & 0x04)
297 // x2 - 1 = y2 - (cy + 1) + cx
298 draw::line(cx + x, cy + y + 1, cx + y + 1, cy + y + 1);
299 if(octants & 0x02)
300 // x2 - 1 = cy - y2 + cx
301 draw::line(cx + x, cy - y, cx + y + 1, cy - y);
302 if(octants & 0x20)
303 // x2 + 1 = (cy + 1) - y2 + (cx - 1)
304 draw::line(cx - x - 1, cy + y + 1, cx - y - 2, cy + y + 1);
305 if(octants & 0x40)
306 // x2 + 1 = y2 - cy + (cx - 1)
307 draw::line(cx - x - 1, cy - y, cx - y - 2, cy - y);
308
309 if(octants & 0x08)
310 // y2 = x2 - cx + (cy + 1)
311 draw::line(cx + y, cy + x + 1, cx + y, cy + y + 1);
312 if(octants & 0x01)
313 // y2 = cx - x2 + cy
314 draw::line(cx + y, cy - x, cx + y, cy - y);
315 if(octants & 0x10)
316 // y2 = (cx - 1) - x2 + (cy + 1)
317 draw::line(cx - y - 1, cy + x + 1, cx - y - 1, cy + y + 1);
318 if(octants & 0x80)
319 // y2 = x2 - (cx - 1) + cy
320 draw::line(cx - y - 1, cy - x, cx - y - 1, cy - y);
321
322 d += 2 * y + 1;
323 ++y;
324 if(d > 0) {
325 d += -2 * x + 2;
326 --x;
327 }
328 }
329}
330
331/********************/
332/* Cairo primitives */
333/********************/
334
335void draw::cairo_circle(int cx, int cy, int r, const color_t& c, int thickness)
336{
337 if (r <= 0) {
338 return;
339 }
340
341 int draw_size = 2 * r;
342 int pixel_scale = video::get_pixel_scale();
343 int render_size = draw_size * pixel_scale;
344
345 surface sdl_surf(render_size, render_size);
346 auto cairo_surface = cairo::create_surface(
347 reinterpret_cast<uint8_t*>(sdl_surf->pixels), ::point(sdl_surf->w, sdl_surf->h));
348
349 auto cairo_context = cairo::create_context(cairo_surface);
350 cairo_t* ctx = cairo_context.get();
351 cairo_scale(ctx, pixel_scale, pixel_scale);
352
353 cairo_set_antialias(ctx, CAIRO_ANTIALIAS_BEST);
354 cairo_set_source_rgba(ctx, 0.0, 0.0, 0.0, 0.0);
355 cairo_paint(ctx);
356
357 cairo_set_line_width(ctx, thickness);
358 cairo_set_source_rgba(ctx,
359 c.r / 255.0,
360 c.g / 255.0,
361 c.b / 255.0,
362 c.a / 255.0
363 );
364
365 // Reduce the arc radius by half the stroke width so the border stays within the circle
366 double half_thickness = 1.0 * thickness / 2;
367 cairo_arc(ctx, r, r, r - half_thickness, 0, 2 * boost::math::constants::pi<double>());
368 cairo_stroke(ctx);
369
370 draw::blit(texture(sdl_surf), ::rect(cx - r, cy - r, draw_size, draw_size));
371}
372
373void draw::cairo_disc(int cx, int cy, int r, const color_t& c)
374{
375 if (r <= 0) {
376 return;
377 }
378
379 int draw_size = 2 * r;
380 int pixel_scale = video::get_pixel_scale();
381 int render_size = draw_size * pixel_scale;
382
383 surface sdl_surf(render_size, render_size);
384 auto cairo_surface = cairo::create_surface(
385 reinterpret_cast<uint8_t*>(sdl_surf->pixels), ::point(sdl_surf->w, sdl_surf->h));
386
387 auto cairo_context = cairo::create_context(cairo_surface);
388 cairo_t* ctx = cairo_context.get();
389 cairo_scale(ctx, pixel_scale, pixel_scale);
390
391 cairo_set_antialias(ctx, CAIRO_ANTIALIAS_BEST);
392 cairo_set_source_rgba(ctx,
393 c.r / 255.0,
394 c.g / 255.0,
395 c.b / 255.0,
396 c.a / 255.0
397 );
398 cairo_arc(ctx, r, r, r, 0, 2 * boost::math::constants::pi<double>());
399 cairo_fill(ctx);
400
401 draw::blit(texture(sdl_surf), ::rect(cx - r, cy - r, draw_size, draw_size));
402}
403
404/*******************/
405/* texture drawing */
406/*******************/
407
408
409void draw::blit(const texture& tex, const ::rect& dst)
410{
411 if (dst == sdl::empty_rect) {
412 return draw::blit(tex);
413 }
414
415 if (!tex) { DBG_D << "null blit"; return; }
416 DBG_D << "blit " << dst;
417
418 const SDL_Rect* rect = tex.src();
419 SDL_FRect fdst = rect_to_frect(dst);
420 if(rect) {
421 SDL_FRect frect = rect_to_frect(*rect);
422 SDL_RenderTexture(renderer(), tex, &frect, &fdst);
423 } else {
424 SDL_RenderTexture(renderer(), tex, nullptr, &fdst);
425 }
426}
427
428void draw::blit(const texture& tex)
429{
430 if (!tex) { DBG_D << "null blit"; return; }
431 DBG_D << "blit";
432
433 const SDL_Rect* rect = tex.src();
434 if(rect) {
435 SDL_FRect frect = rect_to_frect(*rect);
436 SDL_RenderTexture(renderer(), tex, &frect, nullptr);
437 } else {
438 SDL_RenderTexture(renderer(), tex, nullptr, nullptr);
439 }
440}
441
442
443static SDL_FlipMode get_flip(bool flip_h, bool flip_v)
444{
445 // This should be easier than it is.
446 return static_cast<SDL_FlipMode>(
447 static_cast<int>(flip_h ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE)
448 | static_cast<int>(flip_v ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE)
449 );
450}
451
453 const texture& tex,
454 const ::rect& dst,
455 bool flip_h,
456 bool flip_v)
457{
458 if (dst == sdl::empty_rect) {
459 return draw::flipped(tex, flip_h, flip_v);
460 }
461
462 if (!tex) { DBG_D << "null flipped"; return; }
463 DBG_D << "flipped (" << flip_h << '|' << flip_v
464 << ") to " << dst;
465
466 SDL_FlipMode flip = get_flip(flip_h, flip_v);
467 const SDL_Rect* rect = tex.src();
468 SDL_FRect fdst = rect_to_frect(dst);
469 if(rect) {
470 SDL_FRect frect = rect_to_frect(*rect);
471 SDL_RenderTextureRotated(renderer(), tex, &frect, &fdst, 0.0, nullptr, flip);
472 } else {
473 SDL_RenderTextureRotated(renderer(), tex, nullptr, &fdst, 0.0, nullptr, flip);
474 }
475}
476
477void draw::flipped(const texture& tex, bool flip_h, bool flip_v)
478{
479 if (!tex) { DBG_D << "null flipped"; return; }
480 DBG_D << "flipped (" << flip_h << '|' << flip_v << ')';
481
482 SDL_FlipMode flip = get_flip(flip_h, flip_v);
483 const SDL_Rect* rect = tex.src();
484 if(rect) {
485 SDL_FRect frect = rect_to_frect(*rect);
486 SDL_RenderTextureRotated(renderer(), tex, &frect, nullptr, 0.0, nullptr, flip);
487 } else {
488 SDL_RenderTextureRotated(renderer(), tex, nullptr, nullptr, 0.0, nullptr, flip);
489 }
490}
491
492
493// TODO: highdpi - maybe expose this mirrored mode to WML somehow
494void draw::tiled(const texture& tex, const ::rect& dst, bool centered,
495 bool mirrored)
496{
497 if (!tex) { DBG_D << "null tiled"; return; }
498 DBG_D << "tiled (" << centered << '|' << mirrored
499 << ") " << dst;
500
501 // Reduce clip to dst.
502 auto clipper = draw::reduce_clip(dst);
503
504 const int xoff = centered ? (dst.w - tex.w()) / 2 : 0;
505 const int yoff = centered ? (dst.h - tex.h()) / 2 : 0;
506
507 // Just blit the image however many times is necessary.
508 bool vf = false;
509 ::rect t{dst.x - xoff, dst.y - yoff, tex.w(), tex.h()};
510 for (; t.y < dst.y + dst.h; t.y += t.h, vf = !vf) {
511 bool hf = false;
512 for (t.x = dst.x - xoff; t.x < dst.x + dst.w; t.x += t.w, hf = !hf) {
513 if (mirrored) {
514 draw::flipped(tex, t, hf, vf);
515 } else {
516 draw::blit(tex, t);
517 }
518 }
519 }
520}
521
522void draw::tiled_highres(const texture& tex, const ::rect& dst,
523 bool centered, bool mirrored)
524{
525 if (!tex) { DBG_D << "null tiled_highres"; return; }
526 DBG_D << "tiled_highres (" << centered << '|' << mirrored
527 << ") " << dst;
528
529 const int pixel_scale = video::get_pixel_scale();
530
531 // Reduce clip to dst.
532 auto clipper = draw::reduce_clip(dst);
533
534 const ::point size = tex.get_raw_size();
535 const float w = float(size.x) / float(pixel_scale);
536 const float h = float(size.y) / float(pixel_scale);
537 const float xoff = centered ? (dst.w - w) / 2 : 0.0f;
538 const float yoff = centered ? (dst.h - h) / 2 : 0.0f;
539
540 // Just blit the image however many times is necessary.
541 bool vf = false;
542 SDL_FRect t{dst.x - xoff, dst.y - yoff, w, h};
543 for (; t.y < dst.y + dst.h; t.y += t.h, vf = !vf) {
544 bool hf = false;
545 for (t.x = dst.x - xoff; t.x < dst.x + dst.w; t.x += t.w, hf = !hf) {
546 if (mirrored) {
547 SDL_FlipMode flip = get_flip(hf, vf);
548 SDL_RenderTextureRotated(renderer(), tex, nullptr, &t, 0.0, nullptr, flip);
549 } else {
550 SDL_RenderTexture(renderer(), tex, nullptr, &t);
551 }
552 }
553 }
554}
555
557 const std::array<SDL_Vertex, 4>& verts)
558{
559 DBG_D << "smooth shade, verts:";
560 for (const SDL_Vertex& v : verts) {
561 DBG_D << " {(" << v.position.x << ',' << v.position.y << ") "
562 << v.color.r << "," << v.color.g << "," << v.color.b << "," << v.color.a
563 << " (" << v.tex_coord.x << ',' << v.tex_coord.y
564 << ")}";
565 }
566 int indices[6] = {0, 1, 2, 2, 1, 3};
567 SDL_RenderGeometry(renderer(), tex, &verts[0], 4, indices, 6);
568}
569
570/***************************/
571/* RAII state manipulation */
572/***************************/
573
574
576 : c_(draw::get_clip()), clip_enabled_(draw::clip_enabled())
577{
578 draw::force_clip(clip);
579}
580
582{
583 if (clip_enabled_) {
585 } else {
587 }
588}
589
591{
592 return draw::clip_setter(clip);
593}
594
596{
597 if (!draw::clip_enabled()) {
598 return draw::clip_setter(clip);
599 }
600 return draw::clip_setter(draw::get_clip().intersect(clip));
601}
602
603void draw::force_clip(const ::rect& clip)
604{
605 // TODO: highdpi - fix whatever reason there is for this guard (CI fail)
606 if (!renderer()) {
607 WRN_D << "trying to force clip will null renderer";
608 return;
609 }
610 DBG_D << "forcing clip to " << clip;
611
612 SDL_SetRenderClipRect(renderer(), &clip);
613}
614
616{
617 // TODO: highdpi - fix whatever reason there is for this guard (CI fail)
618 if (!renderer()) {
619 return {};
620 }
621
622 if (!SDL_RenderClipEnabled(renderer())) {
623 return draw::get_viewport();
624 }
625
626 ::rect clip;
627 SDL_GetRenderClipRect(renderer(), &clip);
628 return clip;
629}
630
632{
633 if (!renderer()) {
634 return false;
635 }
636 return SDL_RenderClipEnabled(renderer());
637}
638
640{
641 if (!renderer()) {
642 return;
643 }
644 SDL_SetRenderClipRect(renderer(), nullptr);
645 DBG_D << "clip disabled";
646}
647
649{
650 if (!renderer()) {
651 return true;
652 }
653 if (!SDL_RenderClipEnabled(renderer())) {
654 return false;
655 }
656 ::rect clip;
657 SDL_GetRenderClipRect(renderer(), &clip);
658 return clip.w <= 0 || clip.h <= 0;
659}
660
661
663 : v_(), c_(), clip_enabled_(draw::clip_enabled())
664{
667 if (clip_enabled_) {
668 c_ = draw::get_clip();
669 // adjust clip for difference in viewport position
670 ::rect c_view = {
671 c_.x + v_.x - view.x,
672 c_.y + v_.y - view.y,
673 c_.w, c_.h
674 };
675 draw::force_clip(c_view);
676 }
677}
678
680{
682 if (clip_enabled_) {
684 } else {
686 }
687}
688
690{
691 return draw::viewport_setter(viewport);
692}
693
694void draw::force_viewport(const ::rect& viewport)
695{
696 if (!renderer()) {
697 WRN_D << "trying to force viewport will null renderer";
698 return;
699 }
700 DBG_D << "forcing viewport to " << viewport;
701
702 SDL_SetRenderViewport(renderer(), &viewport);
703}
704
706{
707 if (!renderer()) {
708 WRN_D << "no renderer available to get viewport";
709 return {};
710 }
711
712 ::rect viewport;
713 SDL_GetRenderViewport(renderer(), &viewport);
714
715 if (viewport == sdl::empty_rect) {
716 return video::draw_area();
717 }
718 return viewport;
719}
720
722 : target_()
723 , viewport_()
724 , clip_()
725{
726 // Validate we can render to this texture.
727 assert(!t || t.get_access() == SDL_TEXTUREACCESS_TARGET);
728
729 if (!renderer()) {
730 WRN_D << "can't set render target with null renderer";
731 return;
732 }
733
735 SDL_GetRenderViewport(renderer(), &viewport_);
736 SDL_GetRenderClipRect(renderer(), &clip_);
737
738 if (t) {
740 } else {
742 }
743}
744
746{
747 if (!renderer()) {
748 WRN_D << "can't reset render target with null renderer";
749 return;
750 }
752 SDL_SetRenderViewport(renderer(), &viewport_);
753 if(clip_ == sdl::empty_rect) return;
754 SDL_SetRenderClipRect(renderer(), &clip_);
755}
756
758{
759 if (t) {
760 DBG_D << "setting render target to "
761 << t.w() << 'x' << t.h() << " texture";
762 } else {
763 DBG_D << "setting render target to main render buffer";
764 }
766}
double t
A class to manage automatic restoration of the clipping region.
Definition draw.hpp:328
clip_setter(const ::rect &clip)
Definition draw.cpp:575
A class to manage automatic restoration of the render target.
Definition draw.hpp:460
render_target_setter(const texture &t)
Definition draw.cpp:721
A class to manage automatic restoration of the viewport region.
Definition draw.hpp:400
viewport_setter(const ::rect &viewport)
Definition draw.cpp:662
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:109
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 SDL_Renderer * renderer()
Definition draw.cpp:33
static bool sdl_bad_at_rects()
Some versions of SDL have a bad rectangle drawing implementation.
Definition draw.cpp:145
static void draw_rect_as_lines(const rect &rect)
For some SDL versions, draw rectangles as lines.
Definition draw.cpp:156
static SDL_FlipMode get_flip(bool flip_h, bool flip_v)
Definition draw.cpp:443
#define WRN_D
Definition draw.cpp:31
static SDL_FRect rect_to_frect(const SDL_Rect &rect)
Definition draw.cpp:38
#define DBG_D
Definition draw.cpp:30
Drawing functions, for drawing things on the screen.
const gui2::tracked_drawable & target_
The drawable whose render calls we are tracking.
Standard logging facilities (interface).
context_ptr create_context(const surface_ptr &surf)
Definition cairo.hpp:41
surface_ptr create_surface(uint8_t *buffer, const point &size)
Definition cairo.hpp:30
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 rect(const ::rect &rect)
Draw a rectangle.
Definition draw.cpp:171
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 point(int x, int y)
Draw a single point.
Definition draw.cpp:228
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
void fill(const ::rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
Definition draw.cpp:62
::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
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:48
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:558
void force_render_target(const texture &t)
Set the render target, without any provided way of setting it back.
Definition video.cpp:522
int get_pixel_scale()
Get the current active pixel scale multiplier.
Definition video.cpp:480
SDL_Renderer * get_renderer()
Definition video.cpp:703
texture get_render_target()
Get the current render target.
Definition video.cpp:563
int w
Definition pathfind.cpp:188
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 d
#define h
#define c
#define b