Replace source-level inclusion of RasterDrawMethods.inl with CRTP

This commit is contained in:
mniip 2023-02-21 18:20:48 +01:00
parent 0bfa40299c
commit 7fc046c57d
6 changed files with 146 additions and 118 deletions

View File

@ -2,8 +2,10 @@
#include "common/Geometry.h"
#include "common/String.h"
#include "common/tpt-inline.h"
#include "Pixel.h"
#include "Icons.h"
#include "Pixel.h"
#include "RasterDrawMethods.h"
#include "SimulationConfig.h"
//"Graphics lite" - slightly lower performance due to variable size,
class VideoBuffer
@ -67,11 +69,15 @@ public:
bool WritePNG(const ByteString &path) const;
};
class Graphics
class Graphics: public RasterDrawMethods<Graphics>
{
Rect<int> clip;
public:
Rect<int> clip;
constexpr static bool DoClipCheck = true;
constexpr static int VIDXRES = WINDOWW;
constexpr static int VIDYRES = WINDOWH;
constexpr static auto VIDRES = WINDOW;
pixel *vid;
int sdl_scale;
@ -96,34 +102,11 @@ public:
VideoBuffer DumpFrame();
void blendpixel(int x, int y, int r, int g, int b, int a);
void addpixel(int x, int y, int r, int g, int b, int a);
void draw_icon(int x, int y, Icon icon, unsigned char alpha = 255, bool invert = false);
void Clear();
void Finalise();
//
int drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a);
int drawtext(int x, int y, const String &s, int r, int g, int b, int a);
int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a);
int addchar(int x, int y, String::value_type c, int r, int g, int b, int a);
void xor_pixel(int x, int y);
void xor_line(int x, int y, int x2, int y2);
void xor_rect(int x, int y, int width, int height);
void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
void draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a);
void drawrect(int x, int y, int width, int height, int r, int g, int b, int a);
void fillrect(int x, int y, int width, int height, int r, int g, int b, int a);
void drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a);
void fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a);
void clearrect(int x, int y, int width, int height);
void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
void draw_image(const pixel *img, int x, int y, int w, int h, int a);
void draw_image(const VideoBuffer * vidBuf, int x, int y, int a);
void draw_rgba_image(const pixel *data, int w, int h, int x, int y, float alpha);
Graphics();

View File

@ -0,0 +1,29 @@
#pragma once
#include "common/String.h"
class VideoBuffer;
// The "Curiously Recurring Template Trick"
template<typename Derived>
struct RasterDrawMethods
{
int drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a);
int drawtext(int x, int y, const String &str, int r, int g, int b, int a);
int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a);
int addchar(int x, int y, String::value_type c, int r, int g, int b, int a);
void xor_pixel(int x, int y);
void blendpixel(int x, int y, int r, int g, int b, int a);
void addpixel(int x, int y, int r, int g, int b, int a);
void xor_line(int x1, int y1, int x2, int y2);
void xor_rect(int x, int y, int w, int h);
void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
void draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a);
void drawrect(int x, int y, int w, int h, int r, int g, int b, int a);
void fillrect(int x, int y, int w, int h, int r, int g, int b, int a);
void drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a);
void fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a);
void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
void clearrect(int x, int y, int w, int h);
void draw_image(const pixel *img, int x, int y, int w, int h, int a);
void draw_image(const VideoBuffer * vidBuf, int x, int y, int a);
};

View File

@ -1,8 +1,11 @@
#include "FontReader.h"
#include "common/RasterGeometry.h"
#include "FontReader.h"
#include "RasterDrawMethods.h"
#include <cmath>
#include <cstring>
int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a)
template<typename Derived>
int RasterDrawMethods<Derived>::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a)
{
drawtext(x-1, y-1, s, 0, 0, 0, 120);
drawtext(x+1, y+1, s, 0, 0, 0, 120);
@ -13,7 +16,8 @@ int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, const String &s, int r, i
return drawtext(x, y, s, r, g, b, a);
}
int PIXELMETHODS_CLASS::drawtext(int x, int y, const String &str, int r, int g, int b, int a)
template<typename Derived>
int RasterDrawMethods<Derived>::drawtext(int x, int y, const String &str, int r, int g, int b, int a)
{
if(!str.size())
return 0;
@ -96,7 +100,8 @@ int PIXELMETHODS_CLASS::drawtext(int x, int y, const String &str, int r, int g,
return x;
}
int PIXELMETHODS_CLASS::drawchar(int x, int y, String::value_type c, int r, int g, int b, int a)
template<typename Derived>
int RasterDrawMethods<Derived>::drawchar(int x, int y, String::value_type c, int r, int g, int b, int a)
{
FontReader reader(c);
for (int j = -2; j < FONT_H - 2; j++)
@ -105,7 +110,8 @@ int PIXELMETHODS_CLASS::drawchar(int x, int y, String::value_type c, int r, int
return x + reader.GetWidth();
}
int PIXELMETHODS_CLASS::addchar(int x, int y, String::value_type c, int r, int g, int b, int a)
template<typename Derived>
int RasterDrawMethods<Derived>::addchar(int x, int y, String::value_type c, int r, int g, int b, int a)
{
FontReader reader(c);
for (int j = -2; j < FONT_H - 2; j++)
@ -114,52 +120,67 @@ int PIXELMETHODS_CLASS::addchar(int x, int y, String::value_type c, int r, int g
return x + reader.GetWidth();
}
TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y)
template<typename Derived>
void RasterDrawMethods<Derived>::xor_pixel(int x, int y)
{
int c;
#ifdef DO_CLIPCHECK
if (!clip.Contains(Vec2<int>(x, y)))
#else
if (!VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
#endif
return;
c = vid[y*(VIDXRES)+x];
if constexpr (Derived::DoClipCheck)
{
if (!(static_cast<Derived *>(this))->clip.Contains(Vec2<int>(x, y)))
return;
}
else
{
if (!Derived::VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
return;
}
c = (static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x];
c = PIXB(c) + 3*PIXG(c) + 2*PIXR(c);
if (c<512)
vid[y*(VIDXRES)+x] = PIXPACK(0xC0C0C0);
(static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x] = PIXPACK(0xC0C0C0);
else
vid[y*(VIDXRES)+x] = PIXPACK(0x404040);
(static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x] = PIXPACK(0x404040);
}
void PIXELMETHODS_CLASS::blendpixel(int x, int y, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::blendpixel(int x, int y, int r, int g, int b, int a)
{
pixel t;
#ifdef DO_CLIPCHECK
if (!clip.Contains(Vec2<int>(x, y)))
#else
if (!VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
#endif
return;
if constexpr (Derived::DoClipCheck)
{
if (!(static_cast<Derived *>(this))->clip.Contains(Vec2<int>(x, y)))
return;
}
else
{
if (!Derived::VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
return;
}
if (a!=255)
{
t = vid[y*(VIDXRES)+x];
t = (static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x];
r = (a*r + (255-a)*PIXR(t)) >> 8;
g = (a*g + (255-a)*PIXG(t)) >> 8;
b = (a*b + (255-a)*PIXB(t)) >> 8;
}
vid[y*(VIDXRES)+x] = PIXRGB(r,g,b);
(static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x] = PIXRGB(r,g,b);
}
void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::addpixel(int x, int y, int r, int g, int b, int a)
{
pixel t;
#ifdef DO_CLIPCHECK
if (!clip.Contains(Vec2<int>(x, y)))
#else
if (!VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
#endif
return;
t = vid[y*(VIDXRES)+x];
if constexpr (Derived::DoClipCheck)
{
if (!(static_cast<Derived *>(this))->clip.Contains(Vec2<int>(x, y)))
return;
}
else
{
if (!Derived::VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
return;
}
t = (static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x];
r = (a*r + 255*PIXR(t)) >> 8;
g = (a*g + 255*PIXG(t)) >> 8;
b = (a*b + 255*PIXB(t)) >> 8;
@ -169,22 +190,25 @@ void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a)
g = 255;
if (b>255)
b = 255;
vid[y*(VIDXRES)+x] = PIXRGB(r,g,b);
(static_cast<Derived *>(this))->vid[y*(Derived::VIDXRES)+x] = PIXRGB(r,g,b);
}
void PIXELMETHODS_CLASS::xor_line(int x1, int y1, int x2, int y2)
template<typename Derived>
void RasterDrawMethods<Derived>::xor_line(int x1, int y1, int x2, int y2)
{
RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
[this](Vec2<int> p) { xor_pixel(p.X, p.Y); });
}
void PIXELMETHODS_CLASS::xor_rect(int x, int y, int w, int h)
template<typename Derived>
void RasterDrawMethods<Derived>::xor_rect(int x, int y, int w, int h)
{
RasterizeDottedRect(RectSized(Vec2<int>(x, y), Vec2<int>(w, h)),
[this](Vec2<int> p) { xor_pixel(p.X, p.Y); });
}
void PIXELMETHODS_CLASS::xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h)
template<typename Derived>
void RasterDrawMethods<Derived>::xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h)
{
for(int x1 = 0; x1 < w; x1++)
{
@ -196,19 +220,22 @@ void PIXELMETHODS_CLASS::xor_bitmap(unsigned char * bitmap, int x, int y, int w,
}
}
void PIXELMETHODS_CLASS::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a)
{
RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
[this, r, g, b, a](Vec2<int> p) { blendpixel(p.X, p.Y, r, g, b, a); });
}
void PIXELMETHODS_CLASS::drawrect(int x, int y, int w, int h, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::drawrect(int x, int y, int w, int h, int r, int g, int b, int a)
{
RasterizeRect(RectSized(Vec2<int>(x, y), Vec2<int>(w, h)),
[this, r, g, b, a](Vec2<int> p) { blendpixel(p.X, p.Y, r, g, b, a); });
}
void PIXELMETHODS_CLASS::fillrect(int x, int y, int w, int h, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::fillrect(int x, int y, int w, int h, int r, int g, int b, int a)
{
int i,j;
for (j=0; j<h; j++)
@ -216,13 +243,15 @@ void PIXELMETHODS_CLASS::fillrect(int x, int y, int w, int h, int r, int g, int
blendpixel(x+i, y+j, r, g, b, a);
}
void PIXELMETHODS_CLASS::drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
{
RasterizeEllipsePoints(Vec2<float>(rx * rx, ry * ry),
[=](Vec2<int> p) { blendpixel(x + p.X, y + p.Y, r, g, b, a); });
}
void PIXELMETHODS_CLASS::fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
{
RasterizeEllipseRows(Vec2<float>(rx * rx, ry * ry), [=](int xLim, int dy)
{
@ -231,12 +260,14 @@ void PIXELMETHODS_CLASS::fillcircle(int x, int y, int rx, int ry, int r, int g,
});
}
void PIXELMETHODS_CLASS::gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2)
template<typename Derived>
void RasterDrawMethods<Derived>::gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2)
{
}
void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h)
template<typename Derived>
void RasterDrawMethods<Derived>::clearrect(int x, int y, int w, int h)
{
int i;
@ -246,11 +277,12 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h)
w -= 1;
h -= 1;
#ifdef DO_CLIPCHECK
auto rect = clip.Clamp(RectSized(Vec2<int>(x, y), Vec2<int>(w, h)));
#else
auto rect = VIDRES.OriginRect().Clamp(RectSized(Vec2<int>(x, y), Vec2<int>(w, h)));
#endif
Rect<int> rect = RectSized(Vec2<int>(x, y), Vec2<int>(w, h));
if constexpr (Derived::DoClipCheck)
rect = (static_cast<Derived *>(this))->clip.Clamp(rect);
else
rect = Derived::VIDRES.OriginRect().Clamp(rect);
x = rect.TopLeft.X;
y = rect.TopLeft.Y;
w = rect.Size().X;
@ -260,19 +292,20 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h)
return;
for (i=0; i<h; i++)
memset(vid+(x+(VIDXRES)*(y+i)), 0, PIXELSIZE*w);
memset((static_cast<Derived *>(this))->vid+(x+(Derived::VIDXRES)*(y+i)), 0, PIXELSIZE*w);
}
void PIXELMETHODS_CLASS::draw_image(const pixel *img, int x, int y, int w, int h, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::draw_image(const pixel *img, int x, int y, int w, int h, int a)
{
int startX = 0;
if (!img)
return;
// Adjust height to prevent drawing off the bottom
if (y + h > VIDYRES)
h = ((VIDYRES)-y)-1;
if (y + h > Derived::VIDYRES)
h = ((Derived::VIDYRES)-y)-1;
// Too big
if (x + w > VIDXRES)
if (x + w > Derived::VIDXRES)
return;
// Starts off the top of the screen, adjust
@ -296,10 +329,15 @@ void PIXELMETHODS_CLASS::draw_image(const pixel *img, int x, int y, int w, int h
img += startX;
for (int i = startX; i < w; i++)
{
#ifdef DO_CLIPCHECK
if (clip.Contains(Vec2<int>(x + i, y + j)))
#endif
vid[(y+j)*(VIDXRES)+(x+i)] = *img;
if constexpr (Derived::DoClipCheck)
{
if ((static_cast<Derived *>(this))->clip.Contains(Vec2<int>(x + i, y + j)))
(static_cast<Derived *>(this))->vid[(y+j)*(Derived::VIDXRES)+(x+i)] = *img;
}
else
{
(static_cast<Derived *>(this))->vid[(y+j)*(Derived::VIDXRES)+(x+i)] = *img;
}
img++;
}
}
@ -321,7 +359,8 @@ void PIXELMETHODS_CLASS::draw_image(const pixel *img, int x, int y, int w, int h
}
}
void PIXELMETHODS_CLASS::draw_image(const VideoBuffer * vidBuf, int x, int y, int a)
template<typename Derived>
void RasterDrawMethods<Derived>::draw_image(const VideoBuffer * vidBuf, int x, int y, int a)
{
draw_image(vidBuf->Buffer, x, y, vidBuf->Width, vidBuf->Height, a);
}

View File

@ -1,4 +1,5 @@
#include "Graphics.h"
#include "RasterDrawMethodsImpl.h"
#include "SimulationConfig.h"
#include <cstdlib>
#include <cstring>
@ -26,9 +27,4 @@ void Graphics::Finalise()
}
constexpr auto VIDXRES = WINDOWW;
constexpr auto VIDYRES = WINDOWH;
#define PIXELMETHODS_CLASS Graphics
#define DO_CLIPCHECK
#include "RasterDrawMethods.inl"
#undef PIXELMETHODS_CLASS
template class RasterDrawMethods<Graphics>;

View File

@ -32,9 +32,14 @@ typedef struct gcache_item gcache_item;
int HeatToColour(float temp);
class Renderer
class Renderer: public RasterDrawMethods<Renderer>
{
public:
constexpr static bool DoClipCheck = false;
constexpr static auto VIDRES = WINDOW;
constexpr static auto VIDXRES = VIDRES.X;
constexpr static auto VIDYRES = VIDRES.Y;
Simulation * sim;
Graphics * g;
gcache_item *graphicscache;
@ -95,32 +100,9 @@ public:
pixel * vid;
pixel * persistentVid;
pixel * warpVid;
void blendpixel(int x, int y, int r, int g, int b, int a);
void addpixel(int x, int y, int r, int g, int b, int a);
void draw_icon(int x, int y, Icon icon);
int drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a);
int drawtext(int x, int y, const String &s, int r, int g, int b, int a);
int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a);
int addchar(int x, int y, String::value_type c, int r, int g, int b, int a);
void xor_pixel(int x, int y);
void xor_line(int x, int y, int x2, int y2);
void xor_rect(int x, int y, int width, int height);
void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
void draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a);
void drawrect(int x, int y, int width, int height, int r, int g, int b, int a);
void fillrect(int x, int y, int width, int height, int r, int g, int b, int a);
void drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a);
void fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a);
void clearrect(int x, int y, int width, int height);
void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
void draw_image(const pixel *img, int x, int y, int w, int h, int a);
void draw_image(const VideoBuffer * vidBuf, int w, int h, int a);
VideoBuffer DumpFrame();
void drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb);

View File

@ -1,4 +1,5 @@
#include "Renderer.h"
#include "RasterDrawMethodsImpl.h"
#include "gui/game/RenderPreset.h"
#include "simulation/Simulation.h"
#include "simulation/ElementGraphics.h"
@ -528,6 +529,4 @@ Renderer::~Renderer()
delete[] graphicscache;
}
#define PIXELMETHODS_CLASS Renderer
#include "RasterDrawMethods.inl"
#undef PIXELMETHODS_CLASS
template class RasterDrawMethods<Renderer>;