This commit is contained in:
2025-10-11 16:54:41 +02:00
parent f721ebcb4c
commit a4c2719077
2 changed files with 90 additions and 60 deletions

View File

@@ -102,49 +102,6 @@ void appendEmbeddedRoms(std::vector<RomEntry>& out) {
}
}
int measureVerticalText(std::string_view text, int scale = 1, int letterSpacing = 1) {
if (text.empty())
return 0;
const int advance = (font16x8::kGlyphWidth + letterSpacing) * scale;
return static_cast<int>(text.size()) * advance - letterSpacing * scale;
}
void drawGlyphRotated(Framebuffer& fb, int x, int y, char ch, bool clockwise, int scale = 1, bool on = true) {
const auto& rows = font16x8::glyphBitmap(ch);
for (int row = 0; row < font16x8::kGlyphHeight; ++row) {
const uint8_t rowBits = rows[row];
for (int col = 0; col < font16x8::kGlyphWidth; ++col) {
const uint8_t mask = static_cast<uint8_t>(1u << (font16x8::kGlyphWidth - 1 - col));
if ((rowBits & mask) == 0)
continue;
for (int sx = 0; sx < scale; ++sx) {
for (int sy = 0; sy < scale; ++sy) {
int dstX;
int dstY;
if (clockwise) {
dstX = x + row * scale + sx;
dstY = y + (font16x8::kGlyphWidth - 1 - col) * scale + sy;
} else {
dstX = x + (font16x8::kGlyphHeight - 1 - row) * scale + sx;
dstY = y + col * scale + sy;
}
fb.drawPixel(dstX, dstY, on);
}
}
}
}
}
void drawTextRotated(Framebuffer& fb, int x, int y, std::string_view text, bool clockwise, int scale = 1,
bool on = true, int letterSpacing = 1) {
int cursor = y;
const int advance = (font16x8::kGlyphWidth + letterSpacing) * scale;
for (char ch: text) {
drawGlyphRotated(fb, x, cursor, ch, clockwise, scale, on);
cursor += advance;
}
}
class GameboyApp final : public cardboy::sdk::IApp {
public:
explicit GameboyApp(AppContext& ctx) :
@@ -1081,18 +1038,26 @@ private:
if (!activeRomName.empty()) {
const std::string rotatedRomName(activeRomName.rbegin(), activeRomName.rend());
const int textHeight = measureVerticalText(rotatedRomName, textScale);
const auto textBounds =
font16x8::measureTextBounds(rotatedRomName, textScale, 1,
font16x8::Rotation::Clockwise90);
const int textHeight = textBounds.height;
const int maxOrigin = std::max(0, screenHeight - textHeight);
int leftX = 8;
int leftY = std::clamp((screenHeight - textHeight) / 2, 0, maxOrigin);
drawTextRotated(framebuffer, leftX, leftY, rotatedRomName, true, textScale, true, 1);
font16x8::drawText(framebuffer, leftX, leftY, rotatedRomName, textScale, true, 1,
font16x8::Rotation::Clockwise90);
if (!statusMessage.empty()) {
const std::string rotatedStatusMessage(statusMessage.rbegin(), statusMessage.rend());
const int textHeight = measureVerticalText(rotatedStatusMessage, textScale);
const auto statusBounds =
font16x8::measureTextBounds(rotatedStatusMessage, textScale, 1,
font16x8::Rotation::Clockwise90);
const int textHeight = statusBounds.height;
const int maxOrigin = std::max(0, screenHeight - textHeight);
leftX = leftX + 20;
leftY = std::clamp((screenHeight - textHeight) / 2, 0, maxOrigin);
drawTextRotated(framebuffer, leftX, leftY, rotatedStatusMessage, true, textScale, true, 1);
font16x8::drawText(framebuffer, leftX, leftY, rotatedStatusMessage, textScale, true, 1,
font16x8::Rotation::Clockwise90);
}
}
@@ -1110,7 +1075,10 @@ private:
std::string rotated(text.rbegin(), text.rend());
if (totalRightHeight > 0)
totalRightHeight += gap;
totalRightHeight += measureVerticalText(rotated, textScale);
const auto bounds =
font16x8::measureTextBounds(rotated, textScale, 1,
font16x8::Rotation::Clockwise90);
totalRightHeight += bounds.height;
}
const int maxRightOrigin = std::max(0, screenHeight - totalRightHeight);
@@ -1125,8 +1093,12 @@ private:
if (text.empty())
continue;
std::string rotated(text.rbegin(), text.rend());
rightY = screenHeight - measureVerticalText(rotated, textScale) - 8;
drawTextRotated(framebuffer, rightX, rightY, rotated, true, textScale, true, 1);
const auto bounds =
font16x8::measureTextBounds(rotated, textScale, 1,
font16x8::Rotation::Clockwise90);
rightY = screenHeight - bounds.height - 8;
font16x8::drawText(framebuffer, rightX, rightY, rotated, textScale, true, 1,
font16x8::Rotation::Clockwise90);
rightX -= 20;
}

View File

@@ -26,22 +26,69 @@ inline const std::array<uint8_t, kGlyphHeight>& glyphBitmap(char ch) {
return fonts_Terminess_Powerline[uc];
}
enum class Rotation {
None,
Clockwise90,
CounterClockwise90,
};
struct TextBounds {
int width = 0;
int height = 0;
};
template<typename Framebuffer>
inline void drawGlyph(Framebuffer& fb, int x, int y, char ch, int scale = 1, bool on = true) {
inline void drawGlyph(Framebuffer& fb, int x, int y, char ch, int scale = 1, bool on = true,
Rotation rotation = Rotation::None) {
const auto& rows = glyphBitmap(ch);
for (int row = 0; row < kGlyphHeight; ++row) {
const uint8_t rowBits = rows[row];
for (int col = 0; col < kGlyphWidth; ++col) {
const uint8_t mask = static_cast<uint8_t>(1u << (kGlyphWidth - 1 - col));
if (rowBits & mask) {
for (int sx = 0; sx < scale; ++sx)
for (int sy = 0; sy < scale; ++sy)
fb.drawPixel(x + col * scale + sx, y + row * scale + sy, on);
if ((rowBits & mask) == 0)
continue;
for (int sx = 0; sx < scale; ++sx) {
for (int sy = 0; sy < scale; ++sy) {
int dstX = x;
int dstY = y;
switch (rotation) {
case Rotation::None:
dstX += col * scale + sx;
dstY += row * scale + sy;
break;
case Rotation::Clockwise90:
dstX += row * scale + sx;
dstY += (kGlyphWidth - 1 - col) * scale + sy;
break;
case Rotation::CounterClockwise90:
dstX += (kGlyphHeight - 1 - row) * scale + sx;
dstY += col * scale + sy;
break;
}
fb.drawPixel(dstX, dstY, on);
}
}
}
}
}
inline TextBounds measureTextBounds(std::string_view text, int scale = 1, int letterSpacing = 1,
Rotation rotation = Rotation::None) {
if (text.empty())
return {};
const int advance = (kGlyphWidth + letterSpacing) * scale;
const int extent = static_cast<int>(text.size()) * advance - letterSpacing * scale;
const int height = kGlyphHeight * scale;
switch (rotation) {
case Rotation::None:
return {extent, height};
case Rotation::Clockwise90:
case Rotation::CounterClockwise90:
return {height, extent};
}
return {extent, height};
}
inline int measureText(std::string_view text, int scale = 1, int letterSpacing = 1) {
if (text.empty())
return 0;
@@ -51,11 +98,22 @@ inline int measureText(std::string_view text, int scale = 1, int letterSpacing =
template<typename Framebuffer>
inline void drawText(Framebuffer& fb, int x, int y, std::string_view text, int scale = 1, bool on = true,
int letterSpacing = 1) {
int cursor = x;
for (char ch: text) {
drawGlyph(fb, cursor, y, ch, scale, on);
cursor += (kGlyphWidth + letterSpacing) * scale;
int letterSpacing = 1, Rotation rotation = Rotation::None) {
if (text.empty())
return;
const int advance = (kGlyphWidth + letterSpacing) * scale;
if (rotation == Rotation::None) {
int cursor = x;
for (char ch: text) {
drawGlyph(fb, cursor, y, ch, scale, on, rotation);
cursor += advance;
}
} else {
int cursor = y;
for (char ch: text) {
drawGlyph(fb, x, cursor, ch, scale, on, rotation);
cursor += advance;
}
}
}