bwidgets/src/core/draw.cpp

77 lines
2.7 KiB
C++
Raw Normal View History

#include <algorithm>
#include <cmath>
#include <vector>
2021-08-23 00:00:57 +02:00
#include <SDL_render.h>
#include <basic_widgets/core/draw.hpp>
#include <basic_widgets/core/math.hpp>
#include <basic_widgets/core/texture.hpp>
2021-07-14 17:33:54 +02:00
2021-08-06 14:22:56 +02:00
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();
2021-08-27 01:21:25 +02:00
// 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<float>(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<Texture>
2021-07-10 19:55:53 +02:00
{
2021-08-06 14:22:56 +02:00
// clang-format off
2021-08-10 23:48:19 +02:00
auto texture {std::make_shared<Texture>(
r,
2021-08-06 14:22:56 +02:00
SDL_PIXELFORMAT_RGBA32,
SDL_TEXTUREACCESS_STATIC,
resolution,
resolution)};
// clang-format on
const auto radius {resolution / 2};
const SDL_Point center {radius, radius};
2021-08-14 16:37:02 +02:00
set_pixels_color(texture.get(),
[aa_pixels, c, center, radius](
SDL_Point p, const SDL_PixelFormat& format) -> uint32_t {
2021-08-14 16:37:02 +02:00
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,
2021-08-14 16:37:02 +02:00
aa_color().b, aa_color().a);
});
2021-07-23 20:08:52 +02:00
texture->blend_mode(SDL_BLENDMODE_BLEND);
texture->scale_mode(SDL_ScaleModeNearest);
2021-07-10 19:55:53 +02:00
return texture;
}
2021-07-10 19:55:53 +02:00
void set_pixels_color(
Texture& t,
const std::function<uint32_t(SDL_Point, const SDL_PixelFormat&)>& pixel_color)
2021-07-10 19:55:53 +02:00
{
auto attr = t.attributes();
2021-07-16 17:18:13 +02:00
auto pitch = attr.w * attr.format->BytesPerPixel;
std::vector<uint32_t> pixels;
pixels.reserve(attr.h * (std::vector<uint32_t>::size_type)pitch);
2021-08-23 23:50:14 +02:00
// 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));
2021-07-10 19:55:53 +02:00
}
}
t.update(nullptr, (const void*)pixels.data(), pitch);
2021-07-10 19:55:53 +02:00
}
}