Refactor more of RasterDrawMethods

This commit is contained in:
mniip 2023-02-23 19:33:47 +01:00
parent 5daeced716
commit 984b67eb96
3 changed files with 113 additions and 60 deletions

View File

@ -72,8 +72,9 @@ public:
class Graphics: public RasterDrawMethods<Graphics>
{
public:
constexpr static auto VIDXRES = WINDOW.X;
Rect<int> clip;
constexpr static int VIDXRES = WINDOWW;
pixel *vid;
int sdl_scale;

View File

@ -1,8 +1,12 @@
#pragma once
#include <algorithm>
#include <cstdint>
#include <limits>
#include <type_traits>
#include <utility>
// This is always packed with the least significant byte being blue,
// then green, then red, then 0.
typedef uint32_t pixel;
constexpr int PIXELCHANNELS = 3;
@ -29,28 +33,97 @@ constexpr int PIXB(pixel x)
}
template<typename T, typename = std::enable_if<std::is_arithmetic_v<T>, void>>
struct RGB
class RGBA;
template<typename T, typename = std::enable_if<std::is_arithmetic_v<T>, void>>
struct alignas(std::min(alignof(uint32_t), alignof(T))) RGB
{
T Red, Green, Blue;
T Blue, Green, Red;
constexpr RGB(T r, T g, T b):
Red(r),
Blue(b),
Green(g),
Blue(b)
Red(r)
{
}
template<typename S> // Avoid referring to the non-intuitive order of components
RGB(std::initializer_list<S>) = delete;
template<typename = std::enable_if<std::is_same_v<T, uint8_t>, void>>
inline RGB<T> Blend(RGBA<T> other) const
{
if (other.Alpha == 0xFF)
return other.NoAlpha();
return RGB<T>(
// Technically should divide by 0xFF, but >> 8 is close enough
(other.Alpha * other.Red + (0xFF - other.Alpha) * Red ) >> 8,
(other.Alpha * other.Green + (0xFF - other.Alpha) * Green) >> 8,
(other.Alpha * other.Blue + (0xFF - other.Alpha) * Blue ) >> 8
);
}
template<typename = std::enable_if<std::is_same_v<T, uint8_t>, void>>
inline RGB<T> Add(RGBA<T> other) const
{
return RGB<T>(
std::min(0xFF, (other.Alpha * other.Red + 0xFF * Red ) >> 8),
std::min(0xFF, (other.Alpha * other.Green + 0xFF * Green) >> 8),
std::min(0xFF, (other.Alpha * other.Blue + 0xFF * Blue ) >> 8)
);
}
template<typename = std::enable_if<std::is_same_v<T, uint8_t>, void>>
inline RGB<T> Inverse() const
{
return RGB<T>(0xFF - Red, 0xFF - Green, 0xFF - Blue);
}
inline RGBA<T> WithAlpha(T a) const
{
return RGBA<T>(Red, Green, Blue, a);
}
template<typename = std::enable_if<std::is_same_v<T, uint8_t>, void>>
inline pixel Pack() const
{
return PIXRGB(Red, Green, Blue);
}
template<typename = std::enable_if<std::is_same_v<T, uint8_t>, void>>
static inline RGB<T> Unpack(pixel px)
{
return RGB<T>(PIXR(px), PIXG(px), PIXB(px));
}
};
template<typename T, typename = std::enable_if<std::is_arithmetic_v<T>, void>>
struct RGBA
template<typename T, typename>
struct alignas(std::min(alignof(uint32_t), alignof(T))) RGBA
{
T Red, Green, Blue, Alpha;
T Blue, Green, Red, Alpha;
constexpr RGBA(T r, T g, T b, T a = std::numeric_limits<T>::max()):
Red(r),
Green(g),
constexpr RGBA(T r, T g, T b, T a):
Blue(b),
Green(g),
Red(r),
Alpha(a)
{
}
template<typename = std::enable_if<std::is_same_v<T, uint8_t>, void>>
RGBA(T r, T g, T b):
Blue(b),
Green(g),
Red(r),
Alpha(0xFF)
{
}
template<typename S> // Avoid referring to the non-intuitive order of components
RGBA(std::initializer_list<S>) = delete;
RGB<T> NoAlpha() const
{
return RGB<T>(Red, Green, Blue);
}
};

View File

@ -7,7 +7,7 @@
template<typename Derived>
pixel &RasterDrawMethods<Derived>::pixelAt(Vec2<int> pos)
{
return static_cast<Derived *>(this)->vid[pos.X + Derived::VIDXRES * pos.Y];
return static_cast<Derived *>(this)->vid[pos.X + static_cast<Derived *>(this)->VIDXRES * pos.Y];
}
template<typename Derived>
@ -29,14 +29,16 @@ int RasterDrawMethods<Derived>::drawtext_outline(int x, int y, const String &s,
}
template<typename Derived>
int RasterDrawMethods<Derived>::drawtext(int x, int y, const String &str, int r, int g, int b, int a)
int RasterDrawMethods<Derived>::drawtext(int x, int y, const String &str, int r, int g, int b, int alpha)
{
if(!str.size())
return 0;
auto colour = RGB<uint8_t>(r, g, b);
bool underline = false;
int invert = 0;
int oR = r, oG = g, oB = b;
bool invert = false;
auto origColour = colour;
int characterX = x, characterY = y;
int startX = characterX;
for (size_t i = 0; i < str.length(); i++)
@ -50,62 +52,48 @@ int RasterDrawMethods<Derived>::drawtext(int x, int y, const String &str, int r,
{
if (str.length() <= i+3)
break;
oR = r;
oG = g;
oB = b;
r = (unsigned char)str[i + 1];
g = (unsigned char)str[i + 2];
b = (unsigned char)str[i + 3];
origColour = colour; // ???
colour.Red = str[i + 1];
colour.Green = str[i + 2];
colour.Blue = str[i + 3];
i += 3;
}
else if (str[i] == '\x0E')
{
r = oR;
g = oG;
b = oB;
colour = origColour;
}
else if (str[i] == '\x01')
{
invert = !invert;
r = 255-r;
g = 255-g;
b = 255-b;
colour = colour.Inverse();
}
else if (str[i] == '\b')
{
if (str.length() <= i + 1)
break;
auto colorCode = false;
bool colourCode = true;
switch (str[i + 1])
{
case 'U': underline = !underline; break;
case 'w': r = 255; g = 255; b = 255; colorCode = true; break;
case 'g': r = 192; g = 192; b = 192; colorCode = true; break;
case 'o': r = 255; g = 216; b = 32; colorCode = true; break;
case 'r': r = 255; g = 0; b = 0; colorCode = true; break;
case 'l': r = 255; g = 75; b = 75; colorCode = true; break;
case 'b': r = 0; g = 0; b = 255; colorCode = true; break;
case 't': b = 255; g = 170; r = 32; colorCode = true; break;
case 'u': r = 147; g = 83; b = 211; colorCode = true; break;
}
if (colorCode && invert)
{
r = 255-r;
g = 255-g;
b = 255-b;
case 'U': underline = !underline; colourCode = false; break;
case 'w': colour = RGB<uint8_t>(0xFF, 0xFF, 0xFF); break;
case 'g': colour = RGB<uint8_t>(0xC0, 0xC0, 0xC0); break;
case 'o': colour = RGB<uint8_t>(0xFF, 0xD8, 0x20); break;
case 'r': colour = RGB<uint8_t>(0xFF, 0x00, 0x00); break;
case 'l': colour = RGB<uint8_t>(0xFF, 0x4B, 0x4B); break;
case 'b': colour = RGB<uint8_t>(0x00, 0x00, 0xFF); break;
case 't': colour = RGB<uint8_t>(0xFF, 0xAA, 0x20); break;
case 'u': colour = RGB<uint8_t>(0x93, 0x53, 0xD3); break;
}
if (colourCode && invert)
colour = colour.Inverse();
i++;
}
else
{
auto newCharacterX = drawchar(characterX, characterY, str[i], r, g, b, a);
auto newCharacterX = drawchar(characterX, characterY, str[i], colour.Red, colour.Green, colour.Blue, alpha);
if (underline)
{
for (int i = characterX; i < newCharacterX; ++i)
{
blendpixel(i, y + FONT_H, r, g, b, a);
}
}
blendpixel(i, y + FONT_H, colour.Red, colour.Green, colour.Blue, alpha);
characterX = newCharacterX;
}
}
@ -150,13 +138,7 @@ void RasterDrawMethods<Derived>::blendpixel(int x, int y, int r, int g, int b, i
if (!clipRect().Contains(Vec2<int>(x, y)))
return;
pixel &t = pixelAt(Vec2<int>(x, y));
if (a != 255)
{
r = (a * r + (255 - a) * PIXR(t)) >> 8;
g = (a * g + (255 - a) * PIXG(t)) >> 8;
b = (a * b + (255 - a) * PIXB(t)) >> 8;
}
t = PIXRGB(r, g, b);
t = RGB<uint8_t>::Unpack(t).Blend(RGBA<uint8_t>(r, g, b, a)).Pack();
}
template<typename Derived>
@ -165,10 +147,7 @@ void RasterDrawMethods<Derived>::addpixel(int x, int y, int r, int g, int b, int
if (!clipRect().Contains(Vec2<int>(x, y)))
return;
pixel &t = pixelAt(Vec2<int>(x, y));
r = std::min(255, (a * r + 255 * PIXR(t)) >> 8);
g = std::min(255, (a * g + 255 * PIXG(t)) >> 8);
b = std::min(255, (a * b + 255 * PIXB(t)) >> 8);
t = PIXRGB(r, g, b);
t = RGB<uint8_t>::Unpack(t).Add(RGBA<uint8_t>(r, g, b, a)).Pack();
}
template<typename Derived>