25 #include <SDL2/SDL_rect.h>
26 #include <SDL2/SDL_render.h>
29 #define DBG_D LOG_STREAM(debug, log_draw)
30 #define WRN_D LOG_STREAM(warn, log_draw)
45 SDL_GetRenderDrawBlendMode(
renderer(), &
b);
46 SDL_SetRenderDrawBlendMode(
renderer(), SDL_BLENDMODE_NONE);
48 SDL_SetRenderDrawBlendMode(
renderer(),
b);
53 uint8_t r, uint8_t
g, uint8_t
b, uint8_t
a)
57 SDL_RenderFillRect(
renderer(), &area);
62 uint8_t r, uint8_t
g, uint8_t
b)
76 SDL_RenderFillRect(
renderer(),
nullptr);
91 DBG_D <<
"fill " << area;
92 SDL_RenderFillRect(
renderer(), &area);
98 SDL_RenderFillRect(
renderer(),
nullptr);
110 SDL_SetRenderDrawColor(
renderer(), r,
g,
b, SDL_ALPHA_OPAQUE);
115 DBG_D <<
"set color " <<
c;
121 SDL_SetRenderDrawBlendMode(
renderer(),
b);
161 uint8_t r, uint8_t
g, uint8_t
b, uint8_t
a)
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);
190 DBG_D <<
"line from (" << from_x <<
',' << from_y
191 <<
") to (" << to_x <<
',' << to_y
192 <<
") with colour " <<
c;
194 SDL_RenderDrawLine(
renderer(), from_x, from_y, to_x, to_y);
205 DBG_D <<
"point (" << x <<
',' << y <<
')';
206 SDL_RenderDrawPoint(
renderer(), x, y);
217 DBG_D <<
"circle (" << cx <<
',' << cy
218 <<
") -> " << r <<
", oct " << int(octants);
227 std::vector<SDL_Point>
points;
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});
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});
259 DBG_D <<
"disc (" << cx <<
',' << cy
260 <<
") -> " << r <<
", oct " << int(octants);
272 draw::line(cx + x, cy + y + 1, cx + y + 1, cy + y + 1);
275 draw::line(cx + x, cy - y, cx + y + 1, cy - y);
278 draw::line(cx - x - 1, cy + y + 1, cx - y - 2, cy + y + 1);
281 draw::line(cx - x - 1, cy - y, cx - y - 2, cy - y);
285 draw::line(cx + y, cy + x + 1, cx + y, cy + y + 1);
291 draw::line(cx - y - 1, cy + x + 1, cx - y - 1, cy + y + 1);
294 draw::line(cx - y - 1, cy - x, cx - y - 1, cy - y);
317 if (!tex) {
DBG_D <<
"null blit";
return; }
318 DBG_D <<
"blit " << dst;
325 if (!tex) {
DBG_D <<
"null blit";
return; }
328 SDL_RenderCopy(
renderer(), tex, tex.
src(),
nullptr);
332 static SDL_RendererFlip
get_flip(
bool flip_h,
bool flip_v)
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)
351 if (!tex) {
DBG_D <<
"null flipped";
return; }
352 DBG_D <<
"flipped (" << flip_h <<
'|' << flip_v
355 SDL_RendererFlip flip =
get_flip(flip_h, flip_v);
356 SDL_RenderCopyEx(
renderer(), tex, tex.
src(), &dst, 0.0,
nullptr, flip);
361 if (!tex) {
DBG_D <<
"null flipped";
return; }
362 DBG_D <<
"flipped (" << flip_h <<
'|' << flip_v <<
')';
364 SDL_RendererFlip flip =
get_flip(flip_h, flip_v);
365 SDL_RenderCopyEx(
renderer(), tex, tex.
src(),
nullptr, 0.0,
nullptr, flip);
373 if (!tex) {
DBG_D <<
"null tiled";
return; }
374 DBG_D <<
"tiled (" << centered <<
'|' << mirrored
380 const int xoff = centered ? (dst.w - tex.
w()) / 2 : 0;
381 const int yoff = centered ? (dst.h - tex.
h()) / 2 : 0;
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) {
388 for (
t.x = dst.x - xoff;
t.x < dst.x + dst.w;
t.x +=
t.w, hf = !hf) {
399 bool centered,
bool mirrored)
401 if (!tex) {
DBG_D <<
"null tiled_highres";
return; }
402 DBG_D <<
"tiled_highres (" << centered <<
'|' << mirrored
413 const float xoff = centered ? (dst.w -
w) / 2 : 0.0f;
414 const float yoff = centered ? (dst.h -
h) / 2 : 0.0f;
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) {
421 for (
t.x = dst.x - xoff;
t.x < dst.x + dst.w;
t.x +=
t.w, hf = !hf) {
423 SDL_RendererFlip flip =
get_flip(hf, vf);
424 SDL_RenderCopyExF(
renderer(), tex,
nullptr, &
t, 0.0,
nullptr, flip);
426 SDL_RenderCopyF(
renderer(), tex,
nullptr, &
t);
470 WRN_D <<
"trying to force clip will null renderer";
473 DBG_D <<
"forcing clip to " << clip;
475 SDL_RenderSetClipRect(
renderer(), &clip);
485 if (!SDL_RenderIsClipEnabled(
renderer())) {
490 SDL_RenderGetClipRect(
renderer(), &clip);
499 return SDL_RenderIsClipEnabled(
renderer());
507 SDL_RenderSetClipRect(
renderer(),
nullptr);
508 DBG_D <<
"clip disabled";
516 if (!SDL_RenderIsClipEnabled(
renderer())) {
520 SDL_RenderGetClipRect(
renderer(), &clip);
521 return clip.w <= 0 || clip.h <= 0;
534 c_.x +
v_.x - view.x,
535 c_.y +
v_.y - view.y,
560 WRN_D <<
"trying to force viewport will null renderer";
563 DBG_D <<
"forcing viewport to " << viewport;
565 SDL_RenderSetViewport(
renderer(), &viewport);
571 WRN_D <<
"no renderer available to get viewport";
576 SDL_RenderGetViewport(
renderer(), &viewport);
590 assert(!
t ||
t.get_access() == SDL_TEXTUREACCESS_TARGET);
593 WRN_D <<
"can't set render target with null renderer";
610 WRN_D <<
"can't reset render target with null renderer";
614 SDL_RenderSetViewport(
renderer(), &viewport_);
620 DBG_D <<
"setting render target to "
621 <<
t.w() <<
'x' <<
t.h() <<
" texture";
623 DBG_D <<
"setting render target to main render buffer";
A class to manage automatic restoration of the clipping region.
clip_setter(const SDL_Rect &clip)
A class to manage automatic restoration of the render target.
render_target_setter(const texture &t)
A class to manage automatic restoration of the viewport region.
viewport_setter(const SDL_Rect &viewport)
Wrapper class to encapsulate creation and management of an SDL_Texture.
int w() const
The draw-space width of the texture, in pixels.
point get_raw_size() const
The raw internal texture size.
const rect * src() const
A pointer to a rect indicating the source region of the underlying SDL_Texture to be used when drawin...
int h() const
The draw-space height of the texture, in pixels.
static lg::log_domain log_draw("draw")
static bool sdl_bad_at_rects()
Some versions of SDL have a bad rectangle drawing implementation.
static SDL_Renderer * renderer()
static void draw_rect_as_lines(const SDL_Rect &rect)
For some SDL versions, draw rectangles as lines.
static SDL_RendererFlip get_flip(bool flip_h, bool flip_v)
Drawing functions, for drawing things on the screen.
Standard logging facilities (interface).
viewport_setter set_viewport(const SDL_Rect &viewport)
Set the viewport.
void force_viewport(const SDL_Rect &viewport)
Set the viewport, without any provided way of setting it back.
render_target_setter set_render_target(const texture &t)
Set the given texture as the active render target.
clip_setter override_clip(const SDL_Rect &clip)
Override the clipping area.
void circle(int x, int y, int r, const color_t &c, uint8_t octants=0xff)
Draw a circle of the given colour.
void points(const std::vector< SDL_Point > &points)
Draw a set of points.
void force_clip(const SDL_Rect &clip)
Set the clipping area, without any provided way of setting it back.
SDL_Rect get_viewport()
Get the current viewport.
bool null_clip()
Whether the current clipping region will disallow drawing.
clip_setter reduce_clip(const SDL_Rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
bool clip_enabled()
Whether clipping is enabled.
void tiled(const texture &tex, const SDL_Rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
void disc(int x, int y, int r, const color_t &c, uint8_t octants=0xff)
Draw a solid disc of the given colour.
void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Set the drawing colour.
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...
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.
void point(int x, int y)
Draw a single point.
void clear()
Clear the current render target.
void set_blend_mode(SDL_BlendMode b)
Set the blend mode used for drawing operations such as fill() and line().
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
void tiled_highres(const texture &tex, const SDL_Rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
::rect get_clip()
Get the current clipping area, in draw coordinates.
void rect(const SDL_Rect &rect)
Draw a rectangle.
void disable_clip()
Disable clipping.
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
constexpr const SDL_Rect empty_rect
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,...
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
rect draw_area()
The current drawable area.
void reset_render_target()
Reset the render target to the primary render buffer.
void force_render_target(const texture &t)
Set the render target, without any provided way of setting it back.
int get_pixel_scale()
Get the current active pixel scale multiplier.
SDL_Renderer * get_renderer()
texture get_render_target()
Get the current render target.
Contains the SDL_Rect helper code.
The basic class for representing 8-bit RGB or RGBA colour values.
An abstract description of a rectangle with integer coordinates.