#include "WidgetRect.h" #include #include "../sdl_helpers.h" using std::vector; WidgetRect::WidgetRect(int x, int y, int width, int height, int radius, int stroke_size, SDL_Color color) : Widget(x, y, width, height), m_color(color), m_stroke_size(stroke_size), m_radius(radius) { } WidgetRect::WidgetRect(int x, int y, int width, int height, int radius, int stroke_size) : Widget(x, y, width, height), m_color{.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE}, m_stroke_size(stroke_size), m_radius(radius) { } void WidgetRect::draw() { if (nullptr == m_surface) { return; } // Clear surface SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT)); if (m_radius > 0) { // Draw rounded corners here draw_circle_corner(m_rect.w - m_radius, m_radius - 1, 1); draw_circle_corner(m_radius - 1, m_radius - 1, 2); draw_circle_corner(m_radius - 1, m_rect.h - m_radius, 3); draw_circle_corner(m_rect.w - m_radius, m_rect.h - m_radius, 4); // Draw X rect if (m_radius * 2 < m_rect.w) { SDL_Rect rect; rect.x = 0; rect.y = m_radius; rect.w = m_rect.w; rect.h = m_rect.h - 2 * m_radius; SDL_FillRect(m_surface, &rect, SDL_MapRGBA(m_surface->format, m_color.r, m_color.g, m_color.b, m_color.a)); if (m_stroke_size > 0) { rect.x = m_stroke_size; rect.y = m_radius; rect.w = m_rect.w - 2 * m_stroke_size; rect.h = m_rect.h - 2 * m_radius; SDL_FillRect(m_surface, &rect, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT)); } } // Draw Y rect if (m_radius * 2 < m_rect.h) { SDL_Rect rect; rect.x = m_radius; rect.y = 0; rect.w = m_rect.w - 2 * m_radius; rect.h = m_rect.h; SDL_FillRect(m_surface, &rect, SDL_MapRGBA(m_surface->format, m_color.r, m_color.g, m_color.b, m_color.a)); if (m_stroke_size > 0) { rect.x = m_radius; rect.y = m_stroke_size; rect.w = m_rect.w - 2 * m_radius; rect.h = m_rect.h - 2 * m_stroke_size; SDL_FillRect(m_surface, &rect, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT)); } } } else { SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = m_rect.w; rect.h = m_rect.h; SDL_FillRect(m_surface, &rect, SDL_MapRGBA(m_surface->format, m_color.r, m_color.g, m_color.b, m_color.a)); if (m_stroke_size > 0) { rect.x = m_stroke_size; rect.y = m_stroke_size; rect.w = m_rect.w - 2 * m_stroke_size; rect.h = m_rect.h - 2 * m_stroke_size; SDL_FillRect(m_surface, &rect, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT)); } } } std::unique_ptr WidgetRect::builder(const nlohmann::json& j) { int x = 0; int y = 0; int width = 0; int height = 0; int radius = 0; int stroke_size = -1; SDL_Color color = {.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE}; json_extract(j, "x", x); json_extract(j, "y", y); json_extract(j, "width", width); json_extract(j, "height", height); json_extract(j, "radius", radius); json_extract(j, "stroke", stroke_size); json_extract(j, "color", color); return std::make_unique(x, y, width, height, radius, stroke_size, color); } void WidgetRect::draw_circle_corner(int x, int y, int quadrant) { if (0 == m_radius) { return; } int x_add; int y_add; switch (quadrant) { case 1: x_add = 1; y_add = -1; break; case 2: x_add = -1; y_add = -1; break; case 3: x_add = -1; y_add = 1; break; case 4: x_add = 1; y_add = 1; break; default: // TODO: Message printing return; break; } // Create renderer SDL_Renderer* renderer = SDL_CreateSoftwareRenderer(m_surface); if (nullptr == renderer) { // TODO: Message printing return; } SDL_SetRenderDrawColor(renderer, m_color.r, m_color.g, m_color.b, m_color.a); vector points; int max_dist = m_radius * m_radius; int min_dist = 0; if (m_stroke_size > 0) { min_dist = (m_radius - m_stroke_size) * (m_radius - m_stroke_size); } for (int i_x = 0; i_x < m_radius; ++i_x) for (int i_y = 0; i_y < m_radius; ++i_y) { bool should_fill = false; // a2 + b2 = c2 int dist = i_x * i_x + i_y * i_y; // <= c2 (max) && > c2 (min) if ((dist <= max_dist) && (dist >= min_dist)) { should_fill = true; } if (should_fill) { SDL_Point point = { .x = x + x_add * i_x, .y = y + y_add * i_y }; points.push_back(point); } } SDL_RenderDrawPoints(renderer, points.data(), points.size()); SDL_DestroyRenderer(renderer); }