Refactor raster draw methods
This commit is contained in:
parent
e93db9c06a
commit
caab738184
@ -88,10 +88,12 @@ public:
|
|||||||
|
|
||||||
PlaneAdapter(PlaneAdapter &&) = default;
|
PlaneAdapter(PlaneAdapter &&) = default;
|
||||||
|
|
||||||
|
// PlaneAdapter<T> can be constructed from (Vec2, T &&)
|
||||||
|
// PlaneAdapter<T &> can be constructed from (Vec2, T &)
|
||||||
PlaneAdapter(Vec2<int> size, T &&base):
|
PlaneAdapter(Vec2<int> size, T &&base):
|
||||||
xExtent<Width>(size.X),
|
xExtent<Width>(size.X),
|
||||||
yExtent<Height>(size.Y),
|
yExtent<Height>(size.Y),
|
||||||
Base(std::move(base))
|
Base(std::forward<T>(base))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bzlib.h>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include "common/platform/Platform.h"
|
#include "common/platform/Platform.h"
|
||||||
#include "FontReader.h"
|
#include "FontReader.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "resampler/resampler.h"
|
#include "resampler/resampler.h"
|
||||||
#include "SimulationConfig.h"
|
#include "SimulationConfig.h"
|
||||||
|
#include "RasterDrawMethodsImpl.h"
|
||||||
|
|
||||||
VideoBuffer::VideoBuffer(Vec2<int> size):
|
VideoBuffer::VideoBuffer(Vec2<int> size):
|
||||||
video(size)
|
video(size)
|
||||||
@ -128,6 +129,8 @@ int VideoBuffer::AddCharacter(int x, int y, String::value_type c, int r, int g,
|
|||||||
return x + reader.GetWidth();
|
return x + reader.GetWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class RasterDrawMethods<VideoBuffer>;
|
||||||
|
|
||||||
pixel *Graphics::resample_img_nn(pixel * src, int sw, int sh, int rw, int rh)
|
pixel *Graphics::resample_img_nn(pixel * src, int sw, int sh, int rw, int rh)
|
||||||
{
|
{
|
||||||
int y, x;
|
int y, x;
|
||||||
|
@ -61,6 +61,8 @@ public:
|
|||||||
[[deprecated("Use Crop(Rect<int>)")]]
|
[[deprecated("Use Crop(Rect<int>)")]]
|
||||||
void Crop(int width, int height, int x, int y);
|
void Crop(int width, int height, int x, int y);
|
||||||
|
|
||||||
|
using RasterDrawMethods<VideoBuffer>::BlendPixel;
|
||||||
|
[[deprecated("Use BlendPixel(Vec2<int>, RGBA<uint8_t>)")]]
|
||||||
TPT_INLINE void BlendPixel(int x, int y, int r, int g, int b, int a)
|
TPT_INLINE void BlendPixel(int x, int y, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
pixel t;
|
pixel t;
|
||||||
@ -76,6 +78,7 @@ public:
|
|||||||
Buffer[y*(Width)+x] = PIXRGB(r,g,b);
|
Buffer[y*(Width)+x] = PIXRGB(r,g,b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[deprecated("Use DrawPixel")]]
|
||||||
TPT_INLINE void SetPixel(int x, int y, int r, int g, int b, int a)
|
TPT_INLINE void SetPixel(int x, int y, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
if (x<0 || y<0 || x>=Width || y>=Height)
|
if (x<0 || y<0 || x>=Width || y>=Height)
|
||||||
@ -83,6 +86,8 @@ public:
|
|||||||
Buffer[y*(Width)+x] = PIXRGB((r*a)>>8, (g*a)>>8, (b*a)>>8);
|
Buffer[y*(Width)+x] = PIXRGB((r*a)>>8, (g*a)>>8, (b*a)>>8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using RasterDrawMethods<VideoBuffer>::AddPixel;
|
||||||
|
[[deprecated("Use AddPixel(Vec2<int>, RGBA<uint8_t>)")]]
|
||||||
TPT_INLINE void AddPixel(int x, int y, int r, int g, int b, int a)
|
TPT_INLINE void AddPixel(int x, int y, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
pixel t;
|
pixel t;
|
||||||
@ -100,8 +105,11 @@ public:
|
|||||||
b = 255;
|
b = 255;
|
||||||
Buffer[y*(Width)+x] = PIXRGB(r,g,b);
|
Buffer[y*(Width)+x] = PIXRGB(r,g,b);
|
||||||
}
|
}
|
||||||
|
[[deprecated("Use BlendChar")]]
|
||||||
int SetCharacter(int x, int y, String::value_type c, int r, int g, int b, int a);
|
int SetCharacter(int x, int y, String::value_type c, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use BlendChar")]]
|
||||||
int BlendCharacter(int x, int y, String::value_type c, int r, int g, int b, int a);
|
int BlendCharacter(int x, int y, String::value_type c, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use AddChar")]]
|
||||||
int AddCharacter(int x, int y, String::value_type c, int r, int g, int b, int a);
|
int AddCharacter(int x, int y, String::value_type c, int r, int g, int b, int a);
|
||||||
|
|
||||||
bool WritePNG(const ByteString &path) const;
|
bool WritePNG(const ByteString &path) const;
|
||||||
|
@ -10,23 +10,79 @@ class VideoBuffer;
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
struct RasterDrawMethods
|
struct RasterDrawMethods
|
||||||
{
|
{
|
||||||
|
void DrawPixel(Vec2<int>, RGB<uint8_t>);
|
||||||
|
void BlendPixel(Vec2<int>, RGBA<uint8_t>);
|
||||||
|
void AddPixel(Vec2<int>, RGBA<uint8_t>);
|
||||||
|
void XorPixel(Vec2<int>);
|
||||||
|
|
||||||
|
void DrawLine(Vec2<int>, Vec2<int>, RGB<uint8_t>);
|
||||||
|
void BlendLine(Vec2<int>, Vec2<int>, RGBA<uint8_t>);
|
||||||
|
void AddLine(Vec2<int>, Vec2<int>, RGBA<uint8_t>);
|
||||||
|
void XorLine(Vec2<int>, Vec2<int>);
|
||||||
|
|
||||||
|
void DrawRect(Rect<int>, RGB<uint8_t>);
|
||||||
|
void BlendRect(Rect<int>, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
void XorDottedRect(Rect<int>);
|
||||||
|
|
||||||
|
void DrawFilledRect(Rect<int>, RGB<uint8_t>);
|
||||||
|
void BlendFilledRect(Rect<int>, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
void BlendEllipse(Vec2<int> center, Vec2<int> size, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
void BlendFilledEllipse(Vec2<int> center, Vec2<int> size, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
void BlendImage(pixel const *, uint8_t alpha, Rect<int>);
|
||||||
|
void BlendImage(pixel const *, uint8_t alpha, Rect<int>, size_t rowStride);
|
||||||
|
void XorImage(unsigned char const *, Rect<int>);
|
||||||
|
void XorImage(unsigned char const *, Rect<int>, size_t rowStride);
|
||||||
|
|
||||||
|
// Returns width of character
|
||||||
|
int BlendChar(Vec2<int>, String::value_type, RGBA<uint8_t>);
|
||||||
|
int AddChar(Vec2<int>, String::value_type, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
// Returns the offset between the first character and the
|
||||||
|
// would-be-next character
|
||||||
|
Vec2<int> BlendText(Vec2<int>, String const &, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
Vec2<int> BlendTextOutline(Vec2<int>, String const &, RGBA<uint8_t>);
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
[[deprecated("Use BlendTextOutline")]]
|
||||||
int drawtext_outline(int x, int y, const String &, int r, int g, int b, int a);
|
int drawtext_outline(int x, int y, const String &, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use BlendText")]]
|
||||||
int drawtext(int x, int y, const String &, int r, int g, int b, int a);
|
int drawtext(int x, int y, const String &, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use BlendChar")]]
|
||||||
int drawchar(int x, int y, String::value_type, int r, int g, int b, int a);
|
int drawchar(int x, int y, String::value_type, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use AddChar")]]
|
||||||
int addchar(int x, int y, String::value_type, int r, int g, int b, int a);
|
int addchar(int x, int y, String::value_type, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use XorPixel")]]
|
||||||
void xor_pixel(int x, int y);
|
void xor_pixel(int x, int y);
|
||||||
|
[[deprecated("Use DrawPixel/BlendPixel")]]
|
||||||
void blendpixel(int x, int y, int r, int g, int b, int a);
|
void blendpixel(int x, int y, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use AddPixel")]]
|
||||||
void addpixel(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);
|
||||||
|
[[deprecated("Use XorLine")]]
|
||||||
void xor_line(int x1, int y1, int x2, int y2);
|
void xor_line(int x1, int y1, int x2, int y2);
|
||||||
|
[[deprecated("Use XorDottedRect")]]
|
||||||
void xor_rect(int x, int y, int w, int h);
|
void xor_rect(int x, int y, int w, int h);
|
||||||
|
[[deprecated("Use XorImage")]]
|
||||||
void xor_bitmap(unsigned char *bitmap, int x, int y, int w, int h);
|
void xor_bitmap(unsigned char *bitmap, int x, int y, int w, int h);
|
||||||
|
[[deprecated("Use DrawLine/BlendLine")]]
|
||||||
void draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a);
|
void draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a);
|
||||||
|
[[deprecated("Use DrawRect/BlendRect")]]
|
||||||
void drawrect(int x, int y, int w, int h, 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);
|
||||||
|
[[deprecated("Use DrawFilledRect/BlendFilledRect")]]
|
||||||
void fillrect(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);
|
||||||
|
[[deprecated("Use BlendEllipse")]]
|
||||||
void drawcircle(int x, int y, int rx, int ry, 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);
|
||||||
|
[[deprecated("Use BlendFilledEllipse")]]
|
||||||
void fillcircle(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);
|
[[deprecated("Use DrawFilledRect (beware off by 1)")]]
|
||||||
void clearrect(int x, int y, int w, int h);
|
void clearrect(int x, int y, int w, int h);
|
||||||
|
[[deprecated("Use BlendImage")]]
|
||||||
void draw_image(pixel const *, int x, int y, int w, int h, int a);
|
void draw_image(pixel const *, int x, int y, int w, int h, int a);
|
||||||
|
[[deprecated("Use BlendImage")]]
|
||||||
void draw_image(VideoBuffer const *, int x, int y, int a);
|
void draw_image(VideoBuffer const *, int x, int y, int a);
|
||||||
};
|
};
|
||||||
|
@ -1,118 +1,327 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "RasterDrawMethods.h"
|
#include "common/RasterGeometry.h"
|
||||||
#include "Graphics.h"
|
|
||||||
#include "FontReader.h"
|
#include "FontReader.h"
|
||||||
|
#include "Graphics.h"
|
||||||
|
#include "RasterDrawMethods.h"
|
||||||
|
|
||||||
#define vid() (static_cast<Derived &>(*this).video.RowIterator(Vec2(0, 0)))
|
#define video() (static_cast<Derived &>(*this).video)
|
||||||
#define clipRect() (static_cast<Derived const &>(*this).getClipRect())
|
#define clipRect() (static_cast<Derived const &>(*this).getClipRect())
|
||||||
#define VIDXRES (static_cast<Derived const &>(*this).video.Size().X)
|
|
||||||
#define VIDYRES (static_cast<Derived const &>(*this).video.Size().Y)
|
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived, typename V>
|
||||||
int RasterDrawMethods<Derived>::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a)
|
static inline void drawPixelUnchecked(RasterDrawMethods<Derived> &self, V Derived::*video, Vec2<int> pos, RGB<uint8_t> colour)
|
||||||
{
|
{
|
||||||
drawtext(x-1, y-1, s, 0, 0, 0, 120);
|
(static_cast<Derived &>(self).*video)[pos] = colour.Pack();
|
||||||
drawtext(x+1, y+1, s, 0, 0, 0, 120);
|
}
|
||||||
|
|
||||||
drawtext(x-1, y+1, s, 0, 0, 0, 120);
|
template<typename Derived, typename V>
|
||||||
drawtext(x+1, y-1, s, 0, 0, 0, 120);
|
static inline void blendPixelUnchecked(RasterDrawMethods<Derived> &self, V Derived::*video, Vec2<int> pos, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
pixel &px = (static_cast<Derived &>(self).*video)[pos];
|
||||||
|
px = RGB<uint8_t>::Unpack(px).Blend(colour).Pack();
|
||||||
|
}
|
||||||
|
|
||||||
return drawtext(x, y, s, r, g, b, a);
|
template<typename Derived, typename V>
|
||||||
|
static inline void xorPixelUnchecked(RasterDrawMethods<Derived> &self, V Derived::*video, Vec2<int> pos)
|
||||||
|
{
|
||||||
|
pixel &px = (static_cast<Derived &>(self).*video)[pos];
|
||||||
|
auto const c = RGB<uint8_t>::Unpack(px);
|
||||||
|
if (2 * c.Red + 3 * c.Green + c.Blue < 512)
|
||||||
|
px = 0xC0C0C0_rgb .Pack();
|
||||||
|
else
|
||||||
|
px = 0x404040_rgb .Pack();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
int RasterDrawMethods<Derived>::drawtext(int x, int y, const String &str, int r, int g, int b, int a)
|
inline void RasterDrawMethods<Derived>::DrawPixel(Vec2<int> pos, RGB<uint8_t> colour)
|
||||||
{
|
{
|
||||||
if(!str.size())
|
if (clipRect().Contains(pos))
|
||||||
return 0;
|
drawPixelUnchecked(*this, &Derived::video, pos, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
inline void RasterDrawMethods<Derived>::BlendPixel(Vec2<int> pos, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
if (clipRect().Contains(pos))
|
||||||
|
blendPixelUnchecked(*this, &Derived::video, pos, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
inline void RasterDrawMethods<Derived>::AddPixel(Vec2<int> pos, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
if (clipRect().Contains(pos))
|
||||||
|
{
|
||||||
|
pixel &px = (static_cast<Derived &>(*this).video)[pos];
|
||||||
|
px = RGB<uint8_t>::Unpack(px).Add(colour).Pack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
inline void RasterDrawMethods<Derived>::XorPixel(Vec2<int> pos)
|
||||||
|
{
|
||||||
|
if (clipRect().Contains(pos))
|
||||||
|
xorPixelUnchecked(*this, &Derived::video, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::DrawLine(Vec2<int> pos1, Vec2<int> pos2, RGB<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeLine<false>(pos1, pos2, [this, colour](Vec2<int> pos) {
|
||||||
|
DrawPixel(pos, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendLine(Vec2<int> pos1, Vec2<int> pos2, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeLine<false>(pos1, pos2, [this, colour](Vec2<int> pos) {
|
||||||
|
BlendPixel(pos, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::AddLine(Vec2<int> pos1, Vec2<int> pos2, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeLine<false>(pos1, pos2, [this, colour](Vec2<int> pos) {
|
||||||
|
AddPixel(pos, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::XorLine(Vec2<int> pos1, Vec2<int> pos2)
|
||||||
|
{
|
||||||
|
RasterizeLine<false>(pos1, pos2, [this](Vec2<int> pos) {
|
||||||
|
XorPixel(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::DrawRect(Rect<int> rect, RGB<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeRect(rect, [this, colour](Vec2<int> pos) {
|
||||||
|
DrawPixel(pos, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendRect(Rect<int> rect, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeRect(rect, [this, colour](Vec2<int> pos) {
|
||||||
|
BlendPixel(pos, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::XorDottedRect(Rect<int> rect)
|
||||||
|
{
|
||||||
|
RasterizeDottedRect(rect, [this](Vec2<int> pos) {
|
||||||
|
XorPixel(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::DrawFilledRect(Rect<int> rect, RGB<uint8_t> colour)
|
||||||
|
{
|
||||||
|
rect &= clipRect();
|
||||||
|
pixel packed = colour.Pack();
|
||||||
|
auto &video = static_cast<Derived &>(*this).video;
|
||||||
|
if (rect)
|
||||||
|
for (int y = rect.TopLeft.Y; y <= rect.BottomRight.Y; y++)
|
||||||
|
std::fill_n(video.RowIterator(Vec2(rect.TopLeft.X, y)), rect.Size().X, packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendFilledRect(Rect<int> rect, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
for (auto pos : rect & clipRect())
|
||||||
|
blendPixelUnchecked(*this, &Derived::video, pos, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendEllipse(Vec2<int> center, Vec2<int> size, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeEllipsePoints(Vec2(float(size.X * size.X), float(size.Y * size.Y)), [this, center, colour](Vec2<int> delta) {
|
||||||
|
BlendPixel(center + delta, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendFilledEllipse(Vec2<int> center, Vec2<int> size, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
RasterizeEllipseRows(Vec2(float(size.X * size.X), float(size.Y * size.Y)), [this, center, colour](int xLim, int dy) {
|
||||||
|
for (auto pos : clipRect() & RectBetween(center + Vec2(-xLim, dy), center + Vec2(xLim, dy)))
|
||||||
|
blendPixelUnchecked(*this, &Derived::video, pos, colour);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendImage(pixel const *data, uint8_t alpha, Rect<int> rect)
|
||||||
|
{
|
||||||
|
BlendImage(data, alpha, rect, rect.Size().X);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::BlendImage(pixel const *data, uint8_t alpha, Rect<int> rect, size_t rowStride)
|
||||||
|
{
|
||||||
|
auto origin = rect.TopLeft;
|
||||||
|
rect &= clipRect();
|
||||||
|
if (alpha == 0xFF)
|
||||||
|
{
|
||||||
|
auto &video = static_cast<Derived &>(*this).video;
|
||||||
|
for (int y = rect.TopLeft.Y; y <= rect.BottomRight.Y; y++)
|
||||||
|
std::copy_n(
|
||||||
|
data + (rect.TopLeft.X - origin.X) + (y - origin.Y) * rowStride,
|
||||||
|
rect.Size().X,
|
||||||
|
video.RowIterator(Vec2(rect.TopLeft.X, y))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto pos : rect)
|
||||||
|
{
|
||||||
|
pixel const px = data[(pos.X - origin.X) + (pos.Y - origin.Y) * rowStride];
|
||||||
|
blendPixelUnchecked(*this, &Derived::video, pos, RGB<uint8_t>::Unpack(px).WithAlpha(alpha));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::XorImage(unsigned char const *data, Rect<int> rect)
|
||||||
|
{
|
||||||
|
XorImage(data, rect, rect.Size().X);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::XorImage(unsigned char const *data, Rect<int> rect, size_t rowStride)
|
||||||
|
{
|
||||||
|
auto origin = rect.TopLeft;
|
||||||
|
rect &= clipRect();
|
||||||
|
for (auto pos : rect)
|
||||||
|
if (data[(pos.X - origin.X) + (pos.Y - origin.Y) * rowStride])
|
||||||
|
xorPixelUnchecked(*this, &Derived::video, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
int RasterDrawMethods<Derived>::BlendChar(Vec2<int> pos, String::value_type ch, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
FontReader reader(ch);
|
||||||
|
auto const rect = RectSized(Vec2(0, -2), Vec2(reader.GetWidth(), FONT_H));
|
||||||
|
for (auto off : rect.template Range<TOP_TO_BOTTOM, LEFT_TO_RIGHT>())
|
||||||
|
BlendPixel(pos + off, colour.NoAlpha().WithAlpha(reader.NextPixel() * colour.Alpha / 3));
|
||||||
|
return reader.GetWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
int RasterDrawMethods<Derived>::AddChar(Vec2<int> pos, String::value_type ch, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
FontReader reader(ch);
|
||||||
|
RGB<uint8_t> const c = colour.NoAlpha();
|
||||||
|
auto const rect = RectSized(Vec2(0, -2), Vec2(reader.GetWidth(), FONT_H));
|
||||||
|
for (auto off : rect.template Range<TOP_TO_BOTTOM, LEFT_TO_RIGHT>())
|
||||||
|
AddPixel(pos + off, c.WithAlpha(reader.NextPixel() * colour.Alpha / 3));
|
||||||
|
return reader.GetWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
Vec2<int> RasterDrawMethods<Derived>::BlendText(Vec2<int> orig_pos, String const &str, RGBA<uint8_t> orig_colour)
|
||||||
|
{
|
||||||
bool underline = false;
|
bool underline = false;
|
||||||
int invert = 0;
|
bool invert = false;
|
||||||
int oR = r, oG = g, oB = b;
|
RGB<uint8_t> colour = orig_colour.NoAlpha();
|
||||||
int characterX = x, characterY = y;
|
uint8_t alpha = orig_colour.Alpha;
|
||||||
int startX = characterX;
|
Vec2<int> pos = orig_pos;
|
||||||
for (size_t i = 0; i < str.length(); i++)
|
for (size_t i = 0; i < str.length(); i++)
|
||||||
{
|
{
|
||||||
if (str[i] == '\n')
|
if (str[i] == '\n')
|
||||||
{
|
{
|
||||||
characterX = startX;
|
pos.X = orig_pos.X;
|
||||||
characterY += FONT_H;
|
pos.Y += FONT_H;
|
||||||
}
|
}
|
||||||
else if (str[i] == '\x0F')
|
else if (str[i] == '\x0F')
|
||||||
{
|
{
|
||||||
if (str.length() <= i+3)
|
if (str.length() <= i + 3)
|
||||||
break;
|
break;
|
||||||
oR = r;
|
colour.Red = str[i + 1];
|
||||||
oG = g;
|
colour.Green = str[i + 2];
|
||||||
oB = b;
|
colour.Blue = str[i + 3];
|
||||||
r = (unsigned char)str[i + 1];
|
|
||||||
g = (unsigned char)str[i + 2];
|
|
||||||
b = (unsigned char)str[i + 3];
|
|
||||||
i += 3;
|
i += 3;
|
||||||
}
|
}
|
||||||
else if (str[i] == '\x0E')
|
else if (str[i] == '\x0E')
|
||||||
{
|
{
|
||||||
r = oR;
|
colour = orig_colour.NoAlpha();
|
||||||
g = oG;
|
|
||||||
b = oB;
|
|
||||||
}
|
}
|
||||||
else if (str[i] == '\x01')
|
else if (str[i] == '\x01')
|
||||||
{
|
{
|
||||||
invert = !invert;
|
invert = !invert;
|
||||||
r = 255-r;
|
colour = colour.Inverse();
|
||||||
g = 255-g;
|
|
||||||
b = 255-b;
|
|
||||||
}
|
}
|
||||||
else if (str[i] == '\b')
|
else if (str[i] == '\b')
|
||||||
{
|
{
|
||||||
if (str.length() <= i + 1)
|
if (str.length() <= i + 1)
|
||||||
break;
|
break;
|
||||||
auto colorCode = false;
|
bool colourCode = true;
|
||||||
switch (str[i + 1])
|
switch (str[i + 1])
|
||||||
{
|
{
|
||||||
case 'U': underline = !underline; break;
|
case 'U': underline = !underline; colourCode = false; break;
|
||||||
case 'w': r = 255; g = 255; b = 255; colorCode = true; break;
|
case 'w': colour = 0xFFFFFF_rgb; break;
|
||||||
case 'g': r = 192; g = 192; b = 192; colorCode = true; break;
|
case 'g': colour = 0xC0C0C0_rgb; break;
|
||||||
case 'o': r = 255; g = 216; b = 32; colorCode = true; break;
|
case 'o': colour = 0xFFD820_rgb; break;
|
||||||
case 'r': r = 255; g = 0; b = 0; colorCode = true; break;
|
case 'r': colour = 0xFF0000_rgb; break;
|
||||||
case 'l': r = 255; g = 75; b = 75; colorCode = true; break;
|
case 'l': colour = 0xFF4B4B_rgb; break;
|
||||||
case 'b': r = 0; g = 0; b = 255; colorCode = true; break;
|
case 'b': colour = 0x0000FF_rgb; break;
|
||||||
case 't': b = 255; g = 170; r = 32; colorCode = true; break;
|
case 't': colour = 0x20AAFF_rgb; break;
|
||||||
case 'u': r = 147; g = 83; b = 211; colorCode = true; break;
|
case 'u': colour = 0x9353D3_rgb; break;
|
||||||
}
|
|
||||||
if (colorCode && invert)
|
|
||||||
{
|
|
||||||
r = 255-r;
|
|
||||||
g = 255-g;
|
|
||||||
b = 255-b;
|
|
||||||
}
|
}
|
||||||
|
if (colourCode && invert)
|
||||||
|
colour = colour.Inverse();
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto newCharacterX = drawchar(characterX, characterY, str[i], r, g, b, a);
|
int dx = BlendChar(pos, str[i], colour.WithAlpha(alpha));
|
||||||
if (underline)
|
if (underline)
|
||||||
{
|
for (int i = 0; i < dx; i++)
|
||||||
for (int i = characterX; i < newCharacterX; ++i)
|
BlendPixel(pos + Vec2(i, FONT_H), colour.WithAlpha(alpha));
|
||||||
{
|
pos.X += dx;
|
||||||
blendpixel(i, y + FONT_H, r, g, b, a);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
characterX = newCharacterX;
|
return pos - orig_pos;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return x;
|
template<typename Derived>
|
||||||
|
Vec2<int> RasterDrawMethods<Derived>::BlendTextOutline(Vec2<int> pos, String const &str, RGBA<uint8_t> colour)
|
||||||
|
{
|
||||||
|
BlendText(pos + Vec2(-1, -1), str, 0x000000_rgb .WithAlpha(0x78));
|
||||||
|
BlendText(pos + Vec2(-1, +1), str, 0x000000_rgb .WithAlpha(0x78));
|
||||||
|
BlendText(pos + Vec2(+1, -1), str, 0x000000_rgb .WithAlpha(0x78));
|
||||||
|
BlendText(pos + Vec2(+1, +1), str, 0x000000_rgb .WithAlpha(0x78));
|
||||||
|
|
||||||
|
return BlendText(pos, str, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
void RasterDrawMethods<Derived>::Clear()
|
||||||
|
{
|
||||||
|
auto &video = static_cast<Derived &>(*this).video;
|
||||||
|
std::fill_n(video.data(), video.Size().X * video.Size().Y, 0x000000_rgb .Pack());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
int RasterDrawMethods<Derived>::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a)
|
||||||
|
{
|
||||||
|
return x + BlendTextOutline(Vec2(x, y), s, RGBA<uint8_t>(r, g, b, a)).X;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
int RasterDrawMethods<Derived>::drawtext(int x, int y, const String &str, int r, int g, int b, int a)
|
||||||
|
{
|
||||||
|
return x + BlendText(Vec2(x, y), str, RGBA<uint8_t>(r, g, b, a)).X;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
int RasterDrawMethods<Derived>::drawchar(int x, int y, String::value_type c, int r, int g, int b, int a)
|
int RasterDrawMethods<Derived>::drawchar(int x, int y, String::value_type c, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
FontReader reader(c);
|
return x + BlendChar(Vec2(x, y), c, RGBA<uint8_t>(r, g, b, a));
|
||||||
for (int j = -2; j < FONT_H - 2; j++)
|
|
||||||
for (int i = 0; i < reader.GetWidth(); i++)
|
|
||||||
blendpixel(x + i, y + j, r, g, b, reader.NextPixel() * a / 3);
|
|
||||||
return x + reader.GetWidth();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@ -128,359 +337,91 @@ int RasterDrawMethods<Derived>::addchar(int x, int y, String::value_type c, int
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::xor_pixel(int x, int y)
|
void RasterDrawMethods<Derived>::xor_pixel(int x, int y)
|
||||||
{
|
{
|
||||||
int c;
|
XorPixel(Vec2(x, y));
|
||||||
if (!clipRect().Contains(Vec2(x, y)))
|
|
||||||
return;
|
|
||||||
c = vid()[y*(VIDXRES)+x];
|
|
||||||
c = PIXB(c) + 3*PIXG(c) + 2*PIXR(c);
|
|
||||||
if (c<512)
|
|
||||||
vid()[y*(VIDXRES)+x] = PIXPACK(0xC0C0C0);
|
|
||||||
else
|
|
||||||
vid()[y*(VIDXRES)+x] = PIXPACK(0x404040);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::blendpixel(int x, int y, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::blendpixel(int x, int y, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
pixel t;
|
if (a == 0xFF)
|
||||||
if (!clipRect().Contains(Vec2(x, y)))
|
DrawPixel(Vec2(x, y), RGB<uint8_t>(r, g, b));
|
||||||
return;
|
else
|
||||||
if (a!=255)
|
BlendPixel(Vec2(x, y), RGBA<uint8_t>(r, g, b, a));
|
||||||
{
|
|
||||||
t = vid()[y*(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::addpixel(int x, int y, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::addpixel(int x, int y, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
pixel t;
|
AddPixel(Vec2(x, y), RGBA<uint8_t>(r, g, b, a));
|
||||||
if (!clipRect().Contains(Vec2(x, y)))
|
|
||||||
return;
|
|
||||||
t = vid()[y*(VIDXRES)+x];
|
|
||||||
r = (a*r + 255*PIXR(t)) >> 8;
|
|
||||||
g = (a*g + 255*PIXG(t)) >> 8;
|
|
||||||
b = (a*b + 255*PIXB(t)) >> 8;
|
|
||||||
if (r>255)
|
|
||||||
r = 255;
|
|
||||||
if (g>255)
|
|
||||||
g = 255;
|
|
||||||
if (b>255)
|
|
||||||
b = 255;
|
|
||||||
vid()[y*(VIDXRES)+x] = PIXRGB(r,g,b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::xor_line(int x1, int y1, int x2, int y2)
|
void RasterDrawMethods<Derived>::xor_line(int x1, int y1, int x2, int y2)
|
||||||
{
|
{
|
||||||
int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy;
|
XorLine(Vec2(x1, y1), Vec2(x2, y2));
|
||||||
float e, de;
|
|
||||||
if (cp)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = y1;
|
|
||||||
y1 = y;
|
|
||||||
y = x2;
|
|
||||||
x2 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
if (x1 > x2)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = y;
|
|
||||||
y = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
dx = x2 - x1;
|
|
||||||
dy = abs(y2 - y1);
|
|
||||||
e = 0.0f;
|
|
||||||
if (dx)
|
|
||||||
de = dy/(float)dx;
|
|
||||||
else
|
|
||||||
de = 0.0f;
|
|
||||||
y = y1;
|
|
||||||
sy = (y1<y2) ? 1 : -1;
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
if (cp)
|
|
||||||
xor_pixel(y, x);
|
|
||||||
else
|
|
||||||
xor_pixel(x, y);
|
|
||||||
e += de;
|
|
||||||
if (e >= 0.5f)
|
|
||||||
{
|
|
||||||
y += sy;
|
|
||||||
e -= 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::xor_rect(int x, int y, int w, int h)
|
void RasterDrawMethods<Derived>::xor_rect(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
int i;
|
XorDottedRect(RectSized(Vec2(x, y), Vec2(w, h)));
|
||||||
for (i=0; i<w; i+=2)
|
|
||||||
{
|
|
||||||
xor_pixel(x+i, y);
|
|
||||||
}
|
|
||||||
if (h != 1)
|
|
||||||
{
|
|
||||||
if (h%2 == 1) i = 2;
|
|
||||||
else i = 1;
|
|
||||||
for (; i<w; i+=2)
|
|
||||||
{
|
|
||||||
xor_pixel(x+i, y+h-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=2; i<h; i+=2)
|
|
||||||
{
|
|
||||||
xor_pixel(x, y+i);
|
|
||||||
}
|
|
||||||
if (w != 1)
|
|
||||||
{
|
|
||||||
if (w%2 == 1) i = 2;
|
|
||||||
else i = 1;
|
|
||||||
for (; i<h-1; i+=2)
|
|
||||||
{
|
|
||||||
xor_pixel(x+w-1, y+i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h)
|
void RasterDrawMethods<Derived>::xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
for(int x1 = 0; x1 < w; x1++)
|
XorImage(bitmap, RectSized(Vec2(x, y), Vec2(w, h)));
|
||||||
{
|
|
||||||
for(int y1 = 0; y1 < h; y1++)
|
|
||||||
{
|
|
||||||
if(bitmap[y1*w+x1])
|
|
||||||
xor_pixel(x+x1, y+y1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy;
|
if (a == 0xFF)
|
||||||
float e, de;
|
DrawLine(Vec2(x1, y1), Vec2(x2, y2), RGB<uint8_t>(r, g, b));
|
||||||
if (cp)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = y1;
|
|
||||||
y1 = y;
|
|
||||||
y = x2;
|
|
||||||
x2 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
if (x1 > x2)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = y;
|
|
||||||
y = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
dx = x2 - x1;
|
|
||||||
dy = abs(y2 - y1);
|
|
||||||
e = 0.0f;
|
|
||||||
if (dx)
|
|
||||||
de = dy/(float)dx;
|
|
||||||
else
|
else
|
||||||
de = 0.0f;
|
BlendLine(Vec2(x1, y1), Vec2(x2, y2), RGBA<uint8_t>(r, g, b, a));
|
||||||
y = y1;
|
|
||||||
sy = (y1<y2) ? 1 : -1;
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
if (cp)
|
|
||||||
blendpixel(y, x, r, g, b, a);
|
|
||||||
else
|
|
||||||
blendpixel(x, y, r, g, b, a);
|
|
||||||
e += de;
|
|
||||||
if (e >= 0.5f)
|
|
||||||
{
|
|
||||||
y += sy;
|
|
||||||
e -= 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::drawrect(int x, int y, int w, int h, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::drawrect(int x, int y, int w, int h, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
int i;
|
if (a == 0xFF)
|
||||||
w--;
|
DrawRect(RectSized(Vec2(x, y), Vec2(w, h)), RGB<uint8_t>(r, g, b));
|
||||||
h--;
|
else
|
||||||
for (i=0; i<=w; i++)
|
BlendRect(RectSized(Vec2(x, y), Vec2(w, h)), RGBA<uint8_t>(r, g, b, a));
|
||||||
{
|
|
||||||
blendpixel(x+i, y, r, g, b, a);
|
|
||||||
blendpixel(x+i, y+h, r, g, b, a);
|
|
||||||
}
|
|
||||||
for (i=1; i<h; i++)
|
|
||||||
{
|
|
||||||
blendpixel(x, y+i, r, g, b, a);
|
|
||||||
blendpixel(x+w, y+i, r, g, b, a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::fillrect(int x, int y, int w, int h, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::fillrect(int x, int y, int w, int h, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
int i,j;
|
if (a == 0xFF)
|
||||||
for (j=0; j<h; j++)
|
DrawFilledRect(RectSized(Vec2(x, y), Vec2(w, h)), RGB<uint8_t>(r, g, b));
|
||||||
for (i=0; i<w; i++)
|
else
|
||||||
blendpixel(x+i, y+j, r, g, b, a);
|
BlendFilledRect(RectSized(Vec2(x, y), Vec2(w, h)), RGBA<uint8_t>(r, g, b, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
int yTop = ry, yBottom, i, j;
|
BlendEllipse(Vec2(x, y), Vec2(rx, ry), RGBA<uint8_t>(r, g, b, a));
|
||||||
if (!rx)
|
|
||||||
{
|
|
||||||
for (j = -ry; j <= ry; j++)
|
|
||||||
blendpixel(x, y+j, r, g, b, a);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0; i <= rx; i++) {
|
|
||||||
yBottom = yTop;
|
|
||||||
while (pow(i-rx,2.0)*pow(ry,2.0) + pow(yTop-ry,2.0)*pow(rx,2.0) <= pow(rx,2.0)*pow(ry,2.0))
|
|
||||||
yTop++;
|
|
||||||
if (yBottom != yTop)
|
|
||||||
yTop--;
|
|
||||||
for (int j = yBottom; j <= yTop; j++)
|
|
||||||
{
|
|
||||||
blendpixel(x+i-rx, y+j-ry, r, g, b, a);
|
|
||||||
if (i != rx)
|
|
||||||
blendpixel(x-i+rx, y+j-ry, r, g, b, a);
|
|
||||||
if (j != ry)
|
|
||||||
{
|
|
||||||
blendpixel(x+i-rx, y-j+ry, r, g, b, a);
|
|
||||||
if (i != rx)
|
|
||||||
blendpixel(x-i+rx, y-j+ry, r, g, b, a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
|
void RasterDrawMethods<Derived>::fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a)
|
||||||
{
|
{
|
||||||
int yTop = ry+1, yBottom, i, j;
|
BlendFilledEllipse(Vec2(x, y), Vec2(rx, ry), RGBA<uint8_t>(r, g, b, a));
|
||||||
if (!rx)
|
|
||||||
{
|
|
||||||
for (j = -ry; j <= ry; j++)
|
|
||||||
blendpixel(x, y+j, r, g, b, a);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0; i <= rx; i++)
|
|
||||||
{
|
|
||||||
while (pow(i-rx,2.0)*pow(ry,2.0) + pow(yTop-ry,2.0)*pow(rx,2.0) <= pow(rx,2.0)*pow(ry,2.0))
|
|
||||||
yTop++;
|
|
||||||
yBottom = 2*ry - yTop;
|
|
||||||
for (int j = yBottom+1; j < yTop; j++)
|
|
||||||
{
|
|
||||||
blendpixel(x+i-rx, y+j-ry, r, g, b, a);
|
|
||||||
if (i != rx)
|
|
||||||
blendpixel(x-i+rx, y+j-ry, r, g, b, a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::clearrect(int x, int y, int w, int h)
|
void RasterDrawMethods<Derived>::clearrect(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
int i;
|
DrawFilledRect(RectSized(Vec2(x + 1, y + 1), Vec2(w - 1, h - 1)), 0x000000_rgb);
|
||||||
|
|
||||||
// TODO: change calls to clearrect to use sensible meanings of x, y, w, h then remove these 4 lines
|
|
||||||
x += 1;
|
|
||||||
y += 1;
|
|
||||||
w -= 1;
|
|
||||||
h -= 1;
|
|
||||||
|
|
||||||
Rect rect = clipRect() & RectSized(Vec2(x, y), Vec2(w, h));
|
|
||||||
x = rect.TopLeft.X;
|
|
||||||
y = rect.TopLeft.Y;
|
|
||||||
w = rect.Size().X;
|
|
||||||
h = rect.Size().Y;
|
|
||||||
|
|
||||||
if (w<0 || h<0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i=0; i<h; i++)
|
|
||||||
memset(vid()+(x+(VIDXRES)*(y+i)), 0, PIXELSIZE*w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
void RasterDrawMethods<Derived>::draw_image(const pixel *img, int x, int y, int w, int h, int a)
|
void RasterDrawMethods<Derived>::draw_image(const pixel *img, int x, int y, int w, int h, int a)
|
||||||
{
|
{
|
||||||
int startX = 0;
|
BlendImage(img, a, RectSized(Vec2(x, y), Vec2(w, h)));
|
||||||
if (!img)
|
|
||||||
return;
|
|
||||||
// Adjust height to prevent drawing off the bottom
|
|
||||||
if (y + h > VIDYRES)
|
|
||||||
h = ((VIDYRES)-y)-1;
|
|
||||||
// Too big
|
|
||||||
if (x + w > VIDXRES)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Starts off the top of the screen, adjust
|
|
||||||
if (y < 0 && -y < h)
|
|
||||||
{
|
|
||||||
img += -y*w;
|
|
||||||
h += y;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
// Starts off the left side of the screen, adjust
|
|
||||||
if (x < 0 && -x < w)
|
|
||||||
{
|
|
||||||
startX = -x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!h || y < 0 || !w)
|
|
||||||
return;
|
|
||||||
if (a >= 255)
|
|
||||||
for (int j = 0; j < h; j++)
|
|
||||||
{
|
|
||||||
img += startX;
|
|
||||||
for (int i = startX; i < w; i++)
|
|
||||||
{
|
|
||||||
if (clipRect().Contains(Vec2(x + i, y + j)))
|
|
||||||
vid()[(y+j)*(VIDXRES)+(x+i)] = *img;
|
|
||||||
img++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int r, g, b;
|
|
||||||
for (int j = 0; j < h; j++)
|
|
||||||
{
|
|
||||||
img += startX;
|
|
||||||
for (int i = startX; i < w; i++)
|
|
||||||
{
|
|
||||||
r = PIXR(*img);
|
|
||||||
g = PIXG(*img);
|
|
||||||
b = PIXB(*img);
|
|
||||||
blendpixel(x+i, y+j, r, g, b, a);
|
|
||||||
img++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@ -488,3 +429,6 @@ void RasterDrawMethods<Derived>::draw_image(const VideoBuffer * vidBuf, int x, i
|
|||||||
{
|
{
|
||||||
draw_image(vidBuf->Buffer.data(), x, y, vidBuf->Width, vidBuf->Height, a);
|
draw_image(vidBuf->Buffer.data(), x, y, vidBuf->Width, vidBuf->Height, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef video
|
||||||
|
#undef clipRect
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
#include "simulation/ElementGraphics.h"
|
#include "simulation/ElementGraphics.h"
|
||||||
#include "simulation/Simulation.h"
|
#include "simulation/Simulation.h"
|
||||||
|
|
||||||
#undef VIDXRES
|
|
||||||
#undef VIDYRES
|
|
||||||
|
|
||||||
constexpr auto VIDXRES = WINDOWW;
|
constexpr auto VIDXRES = WINDOWW;
|
||||||
constexpr auto VIDYRES = WINDOWH;
|
constexpr auto VIDYRES = WINDOWH;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user