fix: restore clock display and fix placeholder cover generation
- Add clock rendering to BaseTheme::drawHeader() and LyraTheme::drawHeader() after battery, before title. Respects clockFormat (OFF/AM-PM/24H) and clockSize (Small/Medium/Large) settings. - Fix PlaceholderCoverGenerator splitWords() to treat newlines, tabs, and carriage returns as whitespace delimiters (not just spaces), preventing one-character-per-line output from EPUB metadata with embedded newlines. - Remove drawBorder() from placeholder covers since the UI already draws its own frame around book cards. Made-with: Cursor
This commit is contained in:
@@ -235,12 +235,12 @@ int getCharAdvance(const EpdFontData* font, uint32_t cp) {
|
||||
return glyph->advanceX;
|
||||
}
|
||||
|
||||
/// Split a string into words (splitting on spaces).
|
||||
/// Split a string into words (splitting on whitespace: space, newline, tab, CR).
|
||||
std::vector<std::string> splitWords(const std::string& text) {
|
||||
std::vector<std::string> words;
|
||||
std::string current;
|
||||
for (size_t i = 0; i < text.size(); i++) {
|
||||
if (text[i] == ' ') {
|
||||
if (text[i] == ' ' || text[i] == '\n' || text[i] == '\r' || text[i] == '\t') {
|
||||
if (!current.empty()) {
|
||||
words.push_back(current);
|
||||
current.clear();
|
||||
@@ -324,23 +324,17 @@ bool PlaceholderCoverGenerator::generate(const std::string& outputPath, const st
|
||||
}
|
||||
|
||||
// Proportional layout constants based on cover dimensions.
|
||||
// The device bezel covers ~2-3px on each edge, so we pad inward from the edge.
|
||||
const int edgePadding = std::max(3, width / 48); // ~10px at 480w, ~3px at 136w
|
||||
const int borderWidth = std::max(2, width / 96); // ~5px at 480w, ~2px at 136w
|
||||
const int innerPadding = std::max(4, width / 32); // ~15px at 480w, ~4px at 136w
|
||||
|
||||
// Text scaling: 2x for full-size covers, 1x for thumbnails
|
||||
const int titleScale = (height >= 600) ? 2 : 1;
|
||||
const int authorScale = (height >= 600) ? 2 : 1; // Author also larger on full covers
|
||||
const int authorScale = (height >= 600) ? 2 : 1;
|
||||
// Icon: 2x for full cover, 1x for medium thumb, skip for small
|
||||
const int iconScale = (height >= 600) ? 2 : (height >= 350 ? 1 : 0);
|
||||
|
||||
// Draw border inset from edge
|
||||
buf.drawBorder(edgePadding, edgePadding, width - 2 * edgePadding, height - 2 * edgePadding, borderWidth);
|
||||
|
||||
// Content area (inside border + inner padding)
|
||||
const int contentX = edgePadding + borderWidth + innerPadding;
|
||||
const int contentY = edgePadding + borderWidth + innerPadding;
|
||||
// Content area (the UI draws its own border around book cards)
|
||||
const int contentX = innerPadding;
|
||||
const int contentY = innerPadding;
|
||||
const int contentW = width - 2 * contentX;
|
||||
const int contentH = height - 2 * contentY;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <Logging.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include "I18n.h"
|
||||
@@ -266,6 +267,27 @@ void BaseTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t
|
||||
Rect{batteryX, rect.y + 5, BaseMetrics::values.batteryWidth, BaseMetrics::values.batteryHeight},
|
||||
showBatteryPercentage);
|
||||
|
||||
if (SETTINGS.clockFormat != CrossPointSettings::CLOCK_OFF) {
|
||||
time_t now = time(nullptr);
|
||||
struct tm* t = localtime(&now);
|
||||
if (t != nullptr && t->tm_year > 100) {
|
||||
char timeBuf[16];
|
||||
if (SETTINGS.clockFormat == CrossPointSettings::CLOCK_24H) {
|
||||
snprintf(timeBuf, sizeof(timeBuf), "%02d:%02d", t->tm_hour, t->tm_min);
|
||||
} else {
|
||||
int hour12 = t->tm_hour % 12;
|
||||
if (hour12 == 0) hour12 = 12;
|
||||
snprintf(timeBuf, sizeof(timeBuf), "%d:%02d %s", hour12, t->tm_min, t->tm_hour >= 12 ? "PM" : "AM");
|
||||
}
|
||||
int clockFont = SMALL_FONT_ID;
|
||||
if (SETTINGS.clockSize == CrossPointSettings::CLOCK_SIZE_MEDIUM)
|
||||
clockFont = UI_10_FONT_ID;
|
||||
else if (SETTINGS.clockSize == CrossPointSettings::CLOCK_SIZE_LARGE)
|
||||
clockFont = UI_12_FONT_ID;
|
||||
renderer.drawText(clockFont, rect.x + 12, rect.y + 5, timeBuf, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (title) {
|
||||
int padding = rect.width - batteryX + BaseMetrics::values.batteryWidth;
|
||||
auto truncatedTitle = renderer.truncatedText(UI_12_FONT_ID, title,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <I18n.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -174,6 +175,27 @@ void LyraTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t
|
||||
Rect{batteryX, rect.y + 5, LyraMetrics::values.batteryWidth, LyraMetrics::values.batteryHeight},
|
||||
showBatteryPercentage);
|
||||
|
||||
if (SETTINGS.clockFormat != CrossPointSettings::CLOCK_OFF) {
|
||||
time_t now = time(nullptr);
|
||||
struct tm* t = localtime(&now);
|
||||
if (t != nullptr && t->tm_year > 100) {
|
||||
char timeBuf[16];
|
||||
if (SETTINGS.clockFormat == CrossPointSettings::CLOCK_24H) {
|
||||
snprintf(timeBuf, sizeof(timeBuf), "%02d:%02d", t->tm_hour, t->tm_min);
|
||||
} else {
|
||||
int hour12 = t->tm_hour % 12;
|
||||
if (hour12 == 0) hour12 = 12;
|
||||
snprintf(timeBuf, sizeof(timeBuf), "%d:%02d %s", hour12, t->tm_min, t->tm_hour >= 12 ? "PM" : "AM");
|
||||
}
|
||||
int clockFont = SMALL_FONT_ID;
|
||||
if (SETTINGS.clockSize == CrossPointSettings::CLOCK_SIZE_MEDIUM)
|
||||
clockFont = UI_10_FONT_ID;
|
||||
else if (SETTINGS.clockSize == CrossPointSettings::CLOCK_SIZE_LARGE)
|
||||
clockFont = UI_12_FONT_ID;
|
||||
renderer.drawText(clockFont, rect.x + 12, rect.y + 5, timeBuf, true);
|
||||
}
|
||||
}
|
||||
|
||||
int maxTitleWidth =
|
||||
rect.width - LyraMetrics::values.contentSidePadding * 2 - (subtitle != nullptr ? maxSubtitleWidth : 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user