#include #include #include #include #include #include #include namespace bwidgets { auto aa(const Color base_color, const int aa_pixels, const float d) noexcept -> Color { Color c = [aa_pixels, base_color, d]() -> Color { const auto [r, g, b, a] = base_color(); // AA disabled, returns fully opaque or fully transparent colors if (aa_pixels == 0) { if (d > 0) return {r, g, b, 0}; return {r, g, b, a}; } const auto factor = 1.0 - smoothstep(d, (float)-aa_pixels, 0.); return {r, g, b, (uint8_t)((float)base_color().a * factor)}; }(); return c; } auto filled_circle(const Color c, const int resolution, const Renderer& r, const int aa_pixels) -> std::shared_ptr { // clang-format off auto texture {std::make_shared( r, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, resolution, resolution)}; // clang-format on const auto radius {resolution / 2}; const SDL_Point center {radius, radius}; set_pixels_color(texture.get(), [aa_pixels, c, center, radius]( SDL_Point p, const SDL_PixelFormat& format) -> uint32_t { const auto d_delta = distance(center, p) - (float)radius; const auto aa_color = aa(c, aa_pixels, d_delta); return SDL_MapRGBA(&format, aa_color().r, aa_color().g, aa_color().b, aa_color().a); }); texture->blend_mode(SDL_BLENDMODE_BLEND); texture->scale_mode(SDL_ScaleModeNearest); return texture; } void set_pixels_color( Texture& t, const std::function& pixel_color) { auto attr = t.attributes(); auto pitch = attr.w * attr.format->BytesPerPixel; std::vector pixels; pixels.reserve(attr.h * (std::vector::size_type)pitch); // TODO parallel algo for (auto y = 0; y < attr.h; y++) { for (auto x = 0; x < attr.w; x++) { pixels.emplace_back(pixel_color({x, y}, *attr.format)); } } t.update(nullptr, (const void*)pixels.data(), pitch); } }