Refactor more of RasterDrawMethods
This commit is contained in:
parent
5daeced716
commit
984b67eb96
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user