initial commit
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
#include "NoSignalFeed.hpp"
|
||||
#include "PixelFormat.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr uint32_t TileBorderPixels = 0;
|
||||
|
||||
uint32_t glyphRows(char c, uint32_t row)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
case 'G':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x0E, 0x11, 0x10, 0x17, 0x11, 0x11, 0x0E};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
case 'I':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1F};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
case 'N':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x11, 0x19, 0x15, 0x13, 0x11, 0x11, 0x11};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
case 'O':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
case 'S':
|
||||
{
|
||||
constexpr uint32_t rows[] =
|
||||
{0x0F, 0x10, 0x10, 0x0E, 0x01, 0x01, 0x1E};
|
||||
return rows[row];
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void drawText(
|
||||
VideoFrame& frame,
|
||||
const char* text,
|
||||
uint32_t originX,
|
||||
uint32_t originY,
|
||||
uint32_t scale,
|
||||
RgbColor color)
|
||||
{
|
||||
for (uint32_t charIndex = 0; text[charIndex] != '\0'; ++charIndex)
|
||||
{
|
||||
const char c = text[charIndex];
|
||||
|
||||
if (c == ' ')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t charX =
|
||||
originX + charIndex * 6 * scale;
|
||||
|
||||
for (uint32_t gy = 0; gy < 7; ++gy)
|
||||
{
|
||||
const uint32_t bits = glyphRows(c, gy);
|
||||
|
||||
for (uint32_t gx = 0; gx < 5; ++gx)
|
||||
{
|
||||
if ((bits & (1u << (4 - gx))) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint32_t sy = 0; sy < scale; ++sy)
|
||||
{
|
||||
for (uint32_t sx = 0; sx < scale; ++sx)
|
||||
{
|
||||
const uint32_t x =
|
||||
charX + gx * scale + sx;
|
||||
const uint32_t y =
|
||||
originY + gy * scale + sy;
|
||||
|
||||
if (x < frame.width && y < frame.height)
|
||||
{
|
||||
frame.pixels[y * frame.width + x] =
|
||||
packRgba8(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fillNoSignalFrame(VideoFrame& frame)
|
||||
{
|
||||
frame.pixels.resize(frame.width * frame.height);
|
||||
|
||||
for (uint32_t y = 0; y < frame.height; ++y)
|
||||
{
|
||||
for (uint32_t x = 0; x < frame.width; ++x)
|
||||
{
|
||||
const bool isBorder =
|
||||
x < TileBorderPixels ||
|
||||
y < TileBorderPixels ||
|
||||
x >= frame.width - TileBorderPixels ||
|
||||
y >= frame.height - TileBorderPixels;
|
||||
|
||||
const bool hatch =
|
||||
((x + y) / 18) % 2 == 0;
|
||||
|
||||
const RgbColor color =
|
||||
isBorder
|
||||
? RgbColor{95, 100, 110}
|
||||
: (hatch
|
||||
? RgbColor{18, 20, 24}
|
||||
: RgbColor{12, 14, 18});
|
||||
|
||||
frame.pixels[y * frame.width + x] =
|
||||
packRgba8(color);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t scale =
|
||||
frame.width >= 512 ? 5 : 3;
|
||||
constexpr uint32_t textChars = 9;
|
||||
const uint32_t textWidth =
|
||||
(textChars * 6 - 1) * scale;
|
||||
const uint32_t textHeight = 7 * scale;
|
||||
const uint32_t textX =
|
||||
frame.width > textWidth
|
||||
? (frame.width - textWidth) / 2
|
||||
: 0;
|
||||
const uint32_t textY =
|
||||
frame.height > textHeight
|
||||
? (frame.height - textHeight) / 2
|
||||
: 0;
|
||||
|
||||
drawText(
|
||||
frame,
|
||||
"NO SIGNAL",
|
||||
textX,
|
||||
textY,
|
||||
scale,
|
||||
{210, 215, 225}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
NoSignalFeed::NoSignalFeed(
|
||||
uint32_t feedIndex,
|
||||
uint32_t frameWidth,
|
||||
uint32_t frameHeight)
|
||||
{
|
||||
configure(
|
||||
feedIndex,
|
||||
frameWidth,
|
||||
frameHeight
|
||||
);
|
||||
}
|
||||
|
||||
void NoSignalFeed::configure(
|
||||
uint32_t feedIndex,
|
||||
uint32_t frameWidth,
|
||||
uint32_t frameHeight)
|
||||
{
|
||||
(void)feedIndex;
|
||||
generated = false;
|
||||
version = 0;
|
||||
frame.width = frameWidth;
|
||||
frame.height = frameHeight;
|
||||
frame.pixels.resize(frame.width * frame.height);
|
||||
}
|
||||
|
||||
const VideoFrame& NoSignalFeed::getFrame(uint32_t frameCounter)
|
||||
{
|
||||
(void)frameCounter;
|
||||
|
||||
if (!generated)
|
||||
{
|
||||
fillNoSignalFrame(frame);
|
||||
generated = true;
|
||||
++version;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
FeedRuntimeStatus NoSignalFeed::status() const
|
||||
{
|
||||
return FeedRuntimeStatus::NoSignal;
|
||||
}
|
||||
|
||||
std::string NoSignalFeed::displayName() const
|
||||
{
|
||||
return "NO SIGNAL";
|
||||
}
|
||||
Reference in New Issue
Block a user