FifeGUI 0.2.0
A C++ GUI library designed for games.
backends/sdl2/graphics.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2004 - 2008 Olof Naessén and Per Larsson
3// SPDX-FileCopyrightText: 2016 - 2019 Gwilherm Baudic
4// SPDX-FileCopyrightText: 2013 - 2026 Fifengine contributors
5
6#include "fifechan/backends/sdl2/graphics.hpp"
7
8#include <SDL2/SDL_render.h>
9
10#include <algorithm>
11#include <cstdio>
12#include <memory>
13#include <numbers>
14#include <string>
15#include <utility>
16#include <vector>
17
18#include "fifechan/backends/sdl2/image.hpp"
19#include "fifechan/backends/sdl2/truetypefont.hpp"
20#include "fifechan/exception.hpp"
21#include "fifechan/font.hpp"
22#include "fifechan/image.hpp"
23
24namespace fcn::sdl2
25{
26
27 Graphics::Graphics() : mAlpha(false) { }
28
29 Graphics::~Graphics() = default;
30
32 {
33 Rectangle area;
34 area.x = 0;
35 area.y = 0;
36 area.width = mWidth;
37 area.height = mHeight;
38 pushClipArea(area);
39 }
40
42 {
44 }
45
46 void Graphics::setTarget(SDL_Renderer* renderer, int width, int height)
47 {
48 mRenderTarget = renderer;
49 mWidth = width;
50 mHeight = height;
51 }
52
54 {
55 bool const result = fcn::Graphics::pushClipArea(area);
56
57 if (result) {
58 ClipRectangle const & clip_rect = mClipStack.top();
59
60 SDL_Rect rect;
61 rect.x = clip_rect.x;
62 rect.y = clip_rect.y;
63 rect.w = clip_rect.width;
64 rect.h = clip_rect.height;
65 SDL_RenderSetClipRect(mRenderTarget, &rect);
66 }
67
68 return result;
69 }
70
72 {
74
75 if (mClipStack.empty()) {
76 return;
77 }
78
79 ClipRectangle const & clip_rect = mClipStack.top();
80
81 SDL_Rect rect;
82 rect.x = clip_rect.x;
83 rect.y = clip_rect.y;
84 rect.w = clip_rect.width;
85 rect.h = clip_rect.height;
86
87 SDL_RenderSetClipRect(mRenderTarget, &rect);
88 }
89
90 SDL_Renderer* Graphics::getRenderTarget() const
91 {
92 return mRenderTarget;
93 }
94
95 void Graphics::drawImage(fcn::Image const * image, int srcX, int srcY, int dstX, int dstY, int width, int height)
96 {
97 if (mClipStack.empty()) {
98 throwException(
99 "Clip stack is empty, perhaps you"
100 "called a draw function outside of _beginDraw() and _endDraw()?");
101 }
102
103 ClipRectangle const & top = mClipStack.top();
104 SDL_Rect src;
105 SDL_Rect dst;
106 src.x = srcX;
107 src.y = srcY;
108 src.w = width;
109 src.h = height;
110 dst.x = dstX + top.xOffset;
111 dst.y = dstY + top.yOffset;
112 dst.w = width;
113 dst.h = height;
114
115 auto const * srcImage = dynamic_cast<Image const *>(image);
116
117 if (srcImage == nullptr) {
118 throwException("Trying to draw an image of unknown format, must be an Image.");
119 }
120
121 SDL_Texture* texture = srcImage->getTexture();
122 if (texture != nullptr) {
123 SDL_RenderCopy(mRenderTarget, texture, &src, &dst);
124 }
125 }
126
127 void Graphics::fillRectangle(Rectangle const & rectangle)
128 {
129 if (mClipStack.empty()) {
130 throwException(
131 "Clip stack is empty, perhaps you"
132 "called a draw function outside of _beginDraw() and _endDraw()?");
133 }
134
135 ClipRectangle const & top = mClipStack.top();
136
137 Rectangle area = rectangle;
138 area.x += top.xOffset;
139 area.y += top.yOffset;
140
141 if (!area.isIntersecting(top)) {
142 return;
143 }
144
145 SDL_Rect rect;
146 rect.x = area.x;
147 rect.y = area.y;
148 rect.w = area.width;
149 rect.h = area.height;
150
152 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
153 SDL_RenderFillRect(mRenderTarget, &rect);
155 }
156
157 void Graphics::drawPoint(int x, int y)
158 {
159 if (mClipStack.empty()) {
160 throwException(
161 "Clip stack is empty, perhaps you"
162 "called a draw function outside of _beginDraw() and _endDraw()?");
163 }
164
165 ClipRectangle const & top = mClipStack.top();
166
167 x += top.xOffset;
168 y += top.yOffset;
169
170 if (!top.isContaining(x, y)) {
171 return;
172 }
173
175 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
176 SDL_RenderDrawPoint(mRenderTarget, x, y);
178 }
179
180 void Graphics::drawHorizontalLine(int x1, int y, int x2)
181 {
182 if (mClipStack.empty()) {
183 throwException(
184 "Clip stack is empty, perhaps you"
185 "called a draw function outside of _beginDraw() and _endDraw()?");
186 }
187 ClipRectangle const & top = mClipStack.top();
188
189 x1 += top.xOffset;
190 y += top.yOffset;
191 x2 += top.xOffset;
192
193 if (y < top.y || y >= top.y + top.height) {
194 return;
195 }
196
197 if (x1 > x2) {
198 x1 ^= x2;
199 x2 ^= x1;
200 x1 ^= x2;
201 }
202
203 if (top.x > x1) {
204 if (top.x > x2) {
205 return;
206 }
207 x1 = top.x;
208 }
209
210 if (top.x + top.width <= x2) {
211 if (top.x + top.width <= x1) {
212 return;
213 }
214 x2 = top.x + top.width - 1;
215 }
216
218 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
219 SDL_RenderDrawLine(mRenderTarget, x1, y, x2, y);
221 }
222
223 void Graphics::drawVerticalLine(int x, int y1, int y2)
224 {
225 if (mClipStack.empty()) {
226 throwException(
227 "Clip stack is empty, perhaps you"
228 "called a draw function outside of _beginDraw() and _endDraw()?");
229 }
230 ClipRectangle const & top = mClipStack.top();
231
232 x += top.xOffset;
233 y1 += top.yOffset;
234 y2 += top.yOffset;
235
236 if (x < top.x || x >= top.x + top.width) {
237 return;
238 }
239
240 if (y1 > y2) {
241 y1 ^= y2;
242 y2 ^= y1;
243 y1 ^= y2;
244 }
245
246 if (top.y > y1) {
247 if (top.y > y2) {
248 return;
249 }
250 y1 = top.y;
251 }
252
253 if (top.y + top.height <= y2) {
254 if (top.y + top.height <= y1) {
255 return;
256 }
257 y2 = top.y + top.height - 1;
258 }
259
261 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
262 SDL_RenderDrawLine(mRenderTarget, x, y1, x, y2);
264 }
265
266 void Graphics::drawRectangle(Rectangle const & rectangle)
267 {
268 int const x1 = rectangle.x;
269 int const x2 = rectangle.x + rectangle.width - 1;
270 int const y1 = rectangle.y;
271 int const y2 = rectangle.y + rectangle.height - 1;
272
273 drawHorizontalLine(x1, y1, x2);
274 drawHorizontalLine(x1, y2, x2);
275
276 drawVerticalLine(x1, y1, y2);
277 drawVerticalLine(x2, y1, y2);
278 }
279
280 void Graphics::drawLine(int x1, int y1, int x2, int y2)
281 {
282
283 if (mClipStack.empty()) {
284 throwException(
285 "Clip stack is empty, perhaps you"
286 "called a draw function outside of _beginDraw() and _endDraw()?");
287 }
288 ClipRectangle const & top = mClipStack.top();
289
290 x1 += top.xOffset;
291 y1 += top.yOffset;
292 x2 += top.xOffset;
293 y2 += top.yOffset;
294
296 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
297 SDL_RenderDrawLine(mRenderTarget, x1, y1, x2, y2);
299 }
300
301 void Graphics::drawLine(int x1, int y1, int x2, int y2, unsigned int width)
302 {
303 if (mClipStack.empty()) {
304 throwException(
305 "Clip stack is empty, perhaps you"
306 "called a draw function outside of _beginDraw() and _endDraw()?");
307 }
308 ClipRectangle const & top = mClipStack.top();
309
310 x1 += top.xOffset;
311 y1 += top.yOffset;
312 x2 += top.xOffset;
313 y2 += top.yOffset;
314
315 if (width <= 1) {
316 drawLine(x1 - top.xOffset, y1 - top.yOffset, x2 - top.xOffset, y2 - top.yOffset);
317 return;
318 }
319
320 if (x1 == x2 && y1 == y2) {
321 drawRoundStroke(x1 - top.xOffset, y1 - top.yOffset, x2 - top.xOffset, y2 - top.yOffset, width);
322 return;
323 }
324
326 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
327
328 auto const dx = static_cast<float>(x2 - x1);
329 auto const dy = static_cast<float>(y2 - y1);
330 float const length = std::sqrt((dx * dx) + (dy * dy));
331 float const offsetX = (dy / length) * (static_cast<float>(width) / 2.0F);
332 float const offsetY = (dx / length) * (static_cast<float>(width) / 2.0F);
333
334 for (int i = -static_cast<int>(width) / 2; i <= static_cast<int>(width) / 2; ++i) {
335 int const startX = static_cast<int>(x1 + (static_cast<float>(i) * offsetX));
336 int const startY = static_cast<int>(y1 - (static_cast<float>(i) * offsetY));
337 int const endX = static_cast<int>(x2 + (static_cast<float>(i) * offsetX));
338 int const endY = static_cast<int>(y2 - (static_cast<float>(i) * offsetY));
339 SDL_RenderDrawLine(mRenderTarget, startX, startY, endX, endY);
340 }
341
343 }
344
345 void Graphics::drawRoundStroke(int x1, int y1, int x2, int y2, unsigned int width)
346 {
347 if (mClipStack.empty()) {
348 throwException(
349 "Clip stack is empty, perhaps you"
350 "called a draw function outside of _beginDraw() and _endDraw()?");
351 }
352 ClipRectangle const & top = mClipStack.top();
353
354 x1 += top.xOffset;
355 y1 += top.yOffset;
356 x2 += top.xOffset;
357 y2 += top.yOffset;
358
359 if (width <= 1) {
360 drawLine(x1 - top.xOffset, y1 - top.yOffset, x2 - top.xOffset, y2 - top.yOffset);
361 return;
362 }
363
365 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
366
367 int const dx = x2 - x1;
368 int const dy = y2 - y1;
369 int const radius = std::max(1, static_cast<int>(width) / 2);
370 int const stepCount = std::max(std::abs(dx), std::abs(dy));
371
372 auto drawFilledDisk = [&](int centerX, int centerY) {
373 for (int offsetY = -radius; offsetY <= radius; ++offsetY) {
374 for (int offsetX = -radius; offsetX <= radius; ++offsetX) {
375 if ((offsetX * offsetX) + (offsetY * offsetY) <= (radius * radius)) {
376 SDL_RenderDrawPoint(mRenderTarget, centerX + offsetX, centerY + offsetY);
377 }
378 }
379 }
380 };
381
382 if (stepCount == 0) {
383 drawFilledDisk(x1, y1);
385 return;
386 }
387
388 for (int step = 0; step <= stepCount; ++step) {
389 int const centerX = x1 + ((dx * step) / stepCount);
390 int const centerY = y1 + ((dy * step) / stepCount);
391 drawFilledDisk(centerX, centerY);
392 }
393
395 }
396
397 void Graphics::drawFillCircle(fcn::Point const & center, unsigned int radius)
398 {
399 if (mClipStack.empty()) {
400 throwException(
401 "Clip stack is empty, perhaps you"
402 "called a draw function outside of _beginDraw() and _endDraw()?");
403 }
404 ClipRectangle const & top = mClipStack.top();
405
406 int const x0 = center.x + top.xOffset;
407 int const y0 = center.y + top.yOffset;
408
410 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
411
412 for (int y = -radius; std::cmp_less_equal(y, radius); y++) {
413 for (int x = -radius; std::cmp_less_equal(x, radius); x++) {
414 if (x * x + y * y <= radius * radius) {
415 SDL_RenderDrawPoint(mRenderTarget, x0 + x, y0 + y);
416 }
417 }
418 }
419
421 }
422
423 namespace
424 {
425 fcn::Point bezierPoint(std::vector<fcn::Point> const & controlPoints, float t)
426 {
427 std::vector<fcn::Point> points = controlPoints;
428 while (points.size() > 1) {
429 std::vector<fcn::Point> nextPoints;
430 for (size_t i = 0; i < points.size() - 1; ++i) {
431 int const x = static_cast<int>(((1 - t) * points[i].x) + (t * points[i + 1].x));
432 int const y = static_cast<int>(((1 - t) * points[i].y) + (t * points[i + 1].y));
433 nextPoints.emplace_back(x, y);
434 }
435 points = nextPoints;
436 }
437 return points[0];
438 }
439
440 constexpr float degToRad(float degrees)
441 {
442 return degrees * std::numbers::pi_v<float> / 180.0F;
443 }
444 } // namespace
445
446 void Graphics::drawFillCircleSegment(fcn::Point const & center, unsigned int radius, int startAngle, int endAngle)
447 {
448 if (mClipStack.empty()) {
449 throwException(
450 "Clip stack is empty, perhaps you"
451 "called a draw function outside of _beginDraw() and _endDraw()?");
452 }
453 ClipRectangle const & top = mClipStack.top();
454
455 int const x0 = center.x + top.xOffset;
456 int const y0 = center.y + top.yOffset;
457
459 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
460
461 startAngle = startAngle % 360;
462 endAngle = endAngle % 360;
463
464 if (endAngle < startAngle) {
465 endAngle += 360;
466 }
467
468 for (int y = -radius; std::cmp_less_equal(y, radius); y++) {
469 for (int x = -radius; std::cmp_less_equal(x, radius); x++) {
470 if (x * x + y * y <= radius * radius) {
471 float angle = std::atan2(y, x) * 180.0F / std::numbers::pi_v<float>;
472 if (angle < 0) {
473 angle += 360;
474 }
475
476 if (angle >= startAngle && angle <= endAngle) {
477 SDL_RenderDrawPoint(mRenderTarget, x0 + x, y0 + y);
478 }
479 }
480 }
481 }
482
484 }
485
486 namespace
487 {
488 int normalizeAngle(int angle)
489 {
490 angle %= 360;
491 if (angle < 0) {
492 angle += 360;
493 }
494 return angle;
495 }
496 } // namespace
497
498 void Graphics::drawCircle(fcn::Point const & center, unsigned int radius)
499 {
500 if (mClipStack.empty()) {
501 throwException(
502 "Clip stack is empty, perhaps you"
503 "called a draw function outside of _beginDraw() and _endDraw()?");
504 }
505 ClipRectangle const & top = mClipStack.top();
506
507 int const x0 = center.x + top.xOffset;
508 int const y0 = center.y + top.yOffset;
509
511 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
512
513 int x = radius;
514 int y = 0;
515 int p = 1 - radius;
516
517 while (x >= y) {
518 SDL_RenderDrawPoint(mRenderTarget, x0 + x, y0 + y);
519 SDL_RenderDrawPoint(mRenderTarget, x0 - x, y0 + y);
520 SDL_RenderDrawPoint(mRenderTarget, x0 + x, y0 - y);
521 SDL_RenderDrawPoint(mRenderTarget, x0 - x, y0 - y);
522 SDL_RenderDrawPoint(mRenderTarget, x0 + y, y0 + x);
523 SDL_RenderDrawPoint(mRenderTarget, x0 - y, y0 + x);
524 SDL_RenderDrawPoint(mRenderTarget, x0 + y, y0 - x);
525 SDL_RenderDrawPoint(mRenderTarget, x0 - y, y0 - x);
526
527 y++;
528
529 if (p <= 0) {
530 p = p + 2 * y + 1;
531 } else {
532 x--;
533 p = p + 2 * y - 2 * x + 1;
534 }
535 }
536
538 }
539
540 void Graphics::drawCircleSegment(fcn::Point const & center, unsigned int radius, int startAngle, int endAngle)
541 {
542 if (mClipStack.empty()) {
543 throwException(
544 "Clip stack is empty, perhaps you"
545 "called a draw function outside of _beginDraw() and _endDraw()?");
546 }
547 ClipRectangle const & top = mClipStack.top();
548
549 int const x0 = center.x + top.xOffset;
550 int const y0 = center.y + top.yOffset;
551
553 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
554
555 startAngle = normalizeAngle(startAngle);
556 endAngle = normalizeAngle(endAngle);
557
558 if (endAngle < startAngle) {
559 endAngle += 360;
560 }
561
562 int x = radius;
563 int y = 0;
564 int p = 1 - radius;
565
566 auto isInSegment = [&](int x, int y) {
567 float angle = std::atan2(static_cast<float>(y), static_cast<float>(x)) * 180.0F / std::numbers::pi_v<float>;
568 if (angle < 0) {
569 angle += 360;
570 }
571 return angle >= startAngle && angle <= endAngle;
572 };
573
574 while (x >= y) {
575 if (isInSegment(x, y)) {
576 SDL_RenderDrawPoint(mRenderTarget, x0 + x, y0 + y);
577 }
578 if (isInSegment(-x, y)) {
579 SDL_RenderDrawPoint(mRenderTarget, x0 - x, y0 + y);
580 }
581 if (isInSegment(x, -y)) {
582 SDL_RenderDrawPoint(mRenderTarget, x0 + x, y0 - y);
583 }
584 if (isInSegment(-x, -y)) {
585 SDL_RenderDrawPoint(mRenderTarget, x0 - x, y0 - y);
586 }
587 if (isInSegment(y, x)) {
588 SDL_RenderDrawPoint(mRenderTarget, x0 + y, y0 + x);
589 }
590 if (isInSegment(-y, x)) {
591 SDL_RenderDrawPoint(mRenderTarget, x0 - y, y0 + x);
592 }
593 if (isInSegment(y, -x)) {
594 SDL_RenderDrawPoint(mRenderTarget, x0 + y, y0 - x);
595 }
596 if (isInSegment(-y, -x)) {
597 SDL_RenderDrawPoint(mRenderTarget, x0 - y, y0 - x);
598 }
599
600 y++;
601 if (p <= 0) {
602 p = p + 2 * y + 1;
603 } else {
604 x--;
605 p = p + 2 * y - 2 * x + 1;
606 }
607 }
608
610 }
611
612 void Graphics::drawBezier(PointVector const & controlPoints, int segments, unsigned int width)
613 {
614 if (mClipStack.empty()) {
615 throwException(
616 "Clip stack is empty, perhaps you"
617 "called a draw function outside of _beginDraw() and _endDraw()?");
618 }
620 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
621
622 fcn::Point previousPoint = bezierPoint(controlPoints, 0.0F);
623
624 for (int i = 1; i <= segments; ++i) {
625 float const t = static_cast<float>(i) / static_cast<float>(segments);
626 fcn::Point const currentPoint = bezierPoint(controlPoints, t);
627
628 drawLine(previousPoint.x, previousPoint.y, currentPoint.x, currentPoint.y, width);
629
630 previousPoint = currentPoint;
631 }
632
634 }
635
636 void Graphics::drawPolyLine(PointVector const & points, unsigned int width)
637 {
638 if (mClipStack.empty()) {
639 throwException(
640 "Clip stack is empty, perhaps you"
641 "called a draw function outside of _beginDraw() and _endDraw()?");
642 }
643
644 if (points.size() < 2) {
645 return;
646 }
647
649 SDL_SetRenderDrawColor(mRenderTarget, mColor.r, mColor.g, mColor.b, mColor.a);
650
651 for (size_t i = 0; i < points.size() - 1; ++i) {
652 drawLine(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y, width);
653 }
654
656 }
657
658 void Graphics::setColor(Color const & color)
659 {
660 mColor = color;
661
662 mAlpha = color.a != 255;
663 }
664
665 Color const & Graphics::getColor() const
666 {
667 return mColor;
668 }
669
670 std::shared_ptr<Font> Graphics::createFont(std::string const & filename, int size)
671 {
672 return std::make_shared<TrueTypeFont>(filename, size);
673 }
674
675 void Graphics::drawSDLTexture(SDL_Texture* texture, SDL_Rect source, SDL_Rect destination)
676 {
677 if (mClipStack.empty()) {
678 throwException(
679 "Clip stack is empty, perhaps you"
680 "called a draw function outside of _beginDraw() and _endDraw()?");
681 }
682
683 ClipRectangle const & top = mClipStack.top();
684
685 destination.x += top.xOffset;
686 destination.y += top.yOffset;
687 destination.w = source.w;
688 destination.h = source.h;
689
690 SDL_RenderCopy(mRenderTarget, texture, &source, &destination);
691 }
692
694 {
695 SDL_GetRenderDrawColor(mRenderTarget, &r, &g, &b, &a);
696 }
697
699 {
700 SDL_SetRenderDrawColor(mRenderTarget, r, g, b, a);
701 }
702
703} // namespace fcn::sdl2
A rectangle specifically used for clipping rendering regions.
int xOffset
Holds the x offset of the x coordinate.
int yOffset
Holds the y offset of the y coordinate.
Color.
Definition color.hpp:56
uint8_t a
Alpha color component (0-255).
Definition color.hpp:322
virtual void popClipArea()
Removes the top most clip area from the stack.
Definition graphics.cpp:55
virtual bool pushClipArea(Rectangle area)
Pushes a clip area onto the stack.
Definition graphics.cpp:18
std::stack< ClipRectangle > mClipStack
Holds the clip area stack.
Definition graphics.hpp:382
Abstract holder for image data.
Definition image.hpp:32
Represents a 2D coordinate (X, Y).
Definition point.hpp:29
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:20
bool isContaining(int x, int y) const
Checks the rectangle contains a point.
Definition rectangle.cpp:52
int width
Holds the width of the rectangle.
int y
Holds the x coordinate of the rectangle.
int x
Holds the x coordinate of the rectangle.
int height
Holds the height of the rectangle.
bool isIntersecting(Rectangle const &rectangle) const
Checks if another rectangle intersects with the rectangle.
Definition rectangle.cpp:23
Color mColor
Current drawing color.
void drawPolyLine(PointVector const &points, unsigned int width) override
Draws lines between points with given width.
Uint8 r
Cached renderer color components (previous renderer color).
Uint8 a
Previous alpha component from renderer.
virtual void drawSDLTexture(SDL_Texture *texture, SDL_Rect source, SDL_Rect destination)
Draws an SDL_Texture on the target surface.
void drawLine(int x1, int y1, int x2, int y2) override
Draws a line.
void popClipArea() override
Removes the top most clip area from the stack.
void drawFillCircleSegment(Point const &center, unsigned int radius, int startAngle, int endAngle) override
Draws a filled circle segment.
void restoreRenderColor()
Restore the rendering color after drawing.
void drawRoundStroke(int x1, int y1, int x2, int y2, unsigned int width) override
Draws a round brush stroke along the line segment.
void _beginDraw() override
Initializes drawing.
virtual void setTarget(SDL_Renderer *renderer, int width, int height)
Sets the target SDL_Renderer to use for drawing.
void drawHorizontalLine(int x1, int y, int x2)
Draws a horizontal line.
void saveRenderColor()
Save the current rendering color before drawing.
void drawFillCircle(Point const &center, unsigned int radius) override
Draws a filled circle.
void drawImage(fcn::Image const *image, int srcX, int srcY, int dstX, int dstY, int width, int height) override
Draws a part of an image.
std::shared_ptr< Font > createFont(std::string const &filename, int size) override
Creates a font for this graphics backend.
Uint8 g
Previous green component from renderer.
SDL_Renderer * mRenderTarget
The SDL_Renderer used for accelerated drawing.
bool pushClipArea(fcn::Rectangle area) override
Pushes a clip area onto the stack.
void drawPoint(int x, int y) override
Draws a single point/pixel.
Color const & getColor() const override
Gets the color to use when drawing.
void drawCircleSegment(Point const &center, unsigned int radius, int startAngle, int endAngle) override
Draws a simple, non-filled circle segment with a one pixel width.
Uint8 b
Previous blue component from renderer.
void setColor(Color const &color) override
Sets the color to use when drawing.
void drawVerticalLine(int x, int y1, int y2)
Draws a vertical line.
bool mAlpha
Whether alpha blending is enabled.
void drawRectangle(Rectangle const &rectangle) override
Draws a simple, non-filled rectangle with a one pixel width.
virtual SDL_Renderer * getRenderTarget() const
Gets the target SDL_Renderer.
void _endDraw() override
Deinitializes the drawing process.
void fillRectangle(Rectangle const &rectangle) override
Draws a filled rectangle.
void drawCircle(Point const &center, unsigned int radius) override
Draws a simple, non-filled circle with a one pixel width.
void drawBezier(PointVector const &points, int segments, unsigned int width) override
Draws a bezier curve.
SDL2-specific implementation of Image.
virtual SDL_Texture * getTexture() const
Gets the SDL texture for the image.
Unified header for the SDL backend.