diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index 877102c8..fb946ab7 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -694,8 +694,8 @@ bool Epub::generateThumbBmp(int height) const { } int THUMB_TARGET_WIDTH = height * 0.6; int THUMB_TARGET_HEIGHT = height; - const bool success = - PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(coverPng, thumbBmp, THUMB_TARGET_WIDTH, THUMB_TARGET_HEIGHT); + const bool success = PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(coverPng, thumbBmp, THUMB_TARGET_WIDTH, + THUMB_TARGET_HEIGHT); coverPng.close(); thumbBmp.close(); Storage.remove(coverPngTempPath.c_str()); diff --git a/lib/Epub/Epub/Page.h b/lib/Epub/Epub/Page.h index 504de418..756322a1 100644 --- a/lib/Epub/Epub/Page.h +++ b/lib/Epub/Epub/Page.h @@ -43,8 +43,8 @@ class PageLine final : public PageElement { /// Data for a single cell within a PageTableRow. struct PageTableCellData { std::vector> lines; // Laid-out text lines for this cell - uint16_t columnWidth = 0; // Width of this column in pixels - uint16_t xOffset = 0; // X offset of this cell within the row + uint16_t columnWidth = 0; // Width of this column in pixels + uint16_t xOffset = 0; // X offset of this cell within the row }; /// A table row element that renders cells in a column-aligned grid with borders. diff --git a/lib/Epub/Epub/TableData.h b/lib/Epub/Epub/TableData.h index c1b89b70..1725fe1a 100644 --- a/lib/Epub/Epub/TableData.h +++ b/lib/Epub/Epub/TableData.h @@ -9,9 +9,9 @@ /// A single cell in a table row. struct TableCell { std::unique_ptr content; - bool isHeader = false; // true for , false for - int colspan = 1; // number of logical columns this cell spans - CssLength widthHint; // width hint from HTML attribute or CSS (if hasWidthHint) + bool isHeader = false; // true for , false for + int colspan = 1; // number of logical columns this cell spans + CssLength widthHint; // width hint from HTML attribute or CSS (if hasWidthHint) bool hasWidthHint = false; }; diff --git a/lib/Epub/Epub/css/CssStyle.h b/lib/Epub/Epub/css/CssStyle.h index d2c2f47d..2fb4f6ee 100644 --- a/lib/Epub/Epub/css/CssStyle.h +++ b/lib/Epub/Epub/css/CssStyle.h @@ -118,7 +118,7 @@ struct CssStyle { CssLength paddingBottom; // Padding after CssLength paddingLeft; // Padding left CssLength paddingRight; // Padding right - CssLength width; // Element width (used for table columns/cells) + CssLength width; // Element width (used for table columns/cells) CssPropertyFlags defined; // Tracks which properties were explicitly set diff --git a/lib/Epub/Epub/hyphenation/LanguageRegistry.cpp b/lib/Epub/Epub/hyphenation/LanguageRegistry.cpp index 98058357..10c4476f 100644 --- a/lib/Epub/Epub/hyphenation/LanguageRegistry.cpp +++ b/lib/Epub/Epub/hyphenation/LanguageRegistry.cpp @@ -88,6 +88,4 @@ const LanguageHyphenator* getLanguageHyphenatorForPrimaryTag(const std::string& return (it != allEntries.end()) ? it->hyphenator : nullptr; } -LanguageEntryView getLanguageEntries() { - return entries(); -} +LanguageEntryView getLanguageEntries() { return entries(); } diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index d7adb4fa..e8c02cf4 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -214,7 +214,8 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* // (e.g. whitespace between tags) doesn't crash auto tableBlockStyle = BlockStyle(); tableBlockStyle.alignment = CssTextAlign::Left; - self->currentTextBlock.reset(new ParsedText(self->extraParagraphSpacing, self->hyphenationEnabled, tableBlockStyle)); + self->currentTextBlock.reset( + new ParsedText(self->extraParagraphSpacing, self->hyphenationEnabled, tableBlockStyle)); self->depth += 1; return; @@ -393,86 +394,86 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* // Check format support before any file I/O ImageToFramebufferDecoder* decoder = ImageDecoderFactory::getDecoder(resolvedPath); if (decoder) { - // Create a unique filename for the cached image - std::string ext; - size_t extPos = resolvedPath.rfind('.'); - if (extPos != std::string::npos) { - ext = resolvedPath.substr(extPos); - } - std::string cachedImagePath = self->imageBasePath + std::to_string(self->imageCounter++) + ext; - - // Extract image to cache file - FsFile cachedImageFile; - bool extractSuccess = false; - if (Storage.openFileForWrite("EHP", cachedImagePath, cachedImageFile)) { - extractSuccess = self->epub->readItemContentsToStream(resolvedPath, cachedImageFile, 4096); - cachedImageFile.flush(); - cachedImageFile.close(); - delay(50); // Give SD card time to sync - } - - if (extractSuccess) { - // Get image dimensions - ImageDimensions dims = {0, 0}; - if (decoder->getDimensions(cachedImagePath, dims)) { - LOG_DBG("EHP", "Image dimensions: %dx%d", dims.width, dims.height); - - // Scale to fit viewport while maintaining aspect ratio - int maxWidth = self->viewportWidth; - int maxHeight = self->viewportHeight; - float scaleX = (dims.width > maxWidth) ? (float)maxWidth / dims.width : 1.0f; - float scaleY = (dims.height > maxHeight) ? (float)maxHeight / dims.height : 1.0f; - float scale = (scaleX < scaleY) ? scaleX : scaleY; - if (scale > 1.0f) scale = 1.0f; - - int displayWidth = (int)(dims.width * scale); - int displayHeight = (int)(dims.height * scale); - - LOG_DBG("EHP", "Display size: %dx%d (scale %.2f)", displayWidth, displayHeight, scale); - - // Create page for image - only break if image won't fit remaining space - if (self->currentPage && !self->currentPage->elements.empty() && - (self->currentPageNextY + displayHeight > self->viewportHeight)) { - self->completePageFn(std::move(self->currentPage)); - self->currentPage.reset(new Page()); - if (!self->currentPage) { - LOG_ERR("EHP", "Failed to create new page"); - return; - } - self->currentPageNextY = 0; - } else if (!self->currentPage) { - self->currentPage.reset(new Page()); - if (!self->currentPage) { - LOG_ERR("EHP", "Failed to create initial page"); - return; - } - self->currentPageNextY = 0; - } - - // Create ImageBlock and add to page - auto imageBlock = std::make_shared(cachedImagePath, displayWidth, displayHeight); - if (!imageBlock) { - LOG_ERR("EHP", "Failed to create ImageBlock"); - return; - } - int xPos = (self->viewportWidth - displayWidth) / 2; - auto pageImage = std::make_shared(imageBlock, xPos, self->currentPageNextY); - if (!pageImage) { - LOG_ERR("EHP", "Failed to create PageImage"); - return; - } - self->currentPage->elements.push_back(pageImage); - self->currentPageNextY += displayHeight; - - self->depth += 1; - return; - } else { - LOG_ERR("EHP", "Failed to get image dimensions"); - Storage.remove(cachedImagePath.c_str()); + // Create a unique filename for the cached image + std::string ext; + size_t extPos = resolvedPath.rfind('.'); + if (extPos != std::string::npos) { + ext = resolvedPath.substr(extPos); + } + std::string cachedImagePath = self->imageBasePath + std::to_string(self->imageCounter++) + ext; + + // Extract image to cache file + FsFile cachedImageFile; + bool extractSuccess = false; + if (Storage.openFileForWrite("EHP", cachedImagePath, cachedImageFile)) { + extractSuccess = self->epub->readItemContentsToStream(resolvedPath, cachedImageFile, 4096); + cachedImageFile.flush(); + cachedImageFile.close(); + delay(50); // Give SD card time to sync + } + + if (extractSuccess) { + // Get image dimensions + ImageDimensions dims = {0, 0}; + if (decoder->getDimensions(cachedImagePath, dims)) { + LOG_DBG("EHP", "Image dimensions: %dx%d", dims.width, dims.height); + + // Scale to fit viewport while maintaining aspect ratio + int maxWidth = self->viewportWidth; + int maxHeight = self->viewportHeight; + float scaleX = (dims.width > maxWidth) ? (float)maxWidth / dims.width : 1.0f; + float scaleY = (dims.height > maxHeight) ? (float)maxHeight / dims.height : 1.0f; + float scale = (scaleX < scaleY) ? scaleX : scaleY; + if (scale > 1.0f) scale = 1.0f; + + int displayWidth = (int)(dims.width * scale); + int displayHeight = (int)(dims.height * scale); + + LOG_DBG("EHP", "Display size: %dx%d (scale %.2f)", displayWidth, displayHeight, scale); + + // Create page for image - only break if image won't fit remaining space + if (self->currentPage && !self->currentPage->elements.empty() && + (self->currentPageNextY + displayHeight > self->viewportHeight)) { + self->completePageFn(std::move(self->currentPage)); + self->currentPage.reset(new Page()); + if (!self->currentPage) { + LOG_ERR("EHP", "Failed to create new page"); + return; + } + self->currentPageNextY = 0; + } else if (!self->currentPage) { + self->currentPage.reset(new Page()); + if (!self->currentPage) { + LOG_ERR("EHP", "Failed to create initial page"); + return; + } + self->currentPageNextY = 0; + } + + // Create ImageBlock and add to page + auto imageBlock = std::make_shared(cachedImagePath, displayWidth, displayHeight); + if (!imageBlock) { + LOG_ERR("EHP", "Failed to create ImageBlock"); + return; + } + int xPos = (self->viewportWidth - displayWidth) / 2; + auto pageImage = std::make_shared(imageBlock, xPos, self->currentPageNextY); + if (!pageImage) { + LOG_ERR("EHP", "Failed to create PageImage"); + return; + } + self->currentPage->elements.push_back(pageImage); + self->currentPageNextY += displayHeight; + + self->depth += 1; + return; + } else { + LOG_ERR("EHP", "Failed to get image dimensions"); + Storage.remove(cachedImagePath.c_str()); + } + } else { + LOG_ERR("EHP", "Failed to extract image"); } - } else { - LOG_ERR("EHP", "Failed to extract image"); - } } // if (decoder) } } @@ -1353,11 +1354,11 @@ void ChapterHtmlSlimParser::processTable() { } // Row height = max lines * lineHeight + top/bottom border + asymmetric vertical padding - const int16_t rowHeight = static_cast( - static_cast(maxLinesInRow) * lh + 2 + TABLE_CELL_PAD_TOP + TABLE_CELL_PAD_BOTTOM); + const int16_t rowHeight = + static_cast(static_cast(maxLinesInRow) * lh + 2 + TABLE_CELL_PAD_TOP + TABLE_CELL_PAD_BOTTOM); - auto pageTableRow = std::make_shared( - std::move(cellDataVec), rowHeight, totalTableWidth, static_cast(lh), 0, 0); + auto pageTableRow = std::make_shared(std::move(cellDataVec), rowHeight, totalTableWidth, + static_cast(lh), 0, 0); addTableRowToPage(std::move(pageTableRow)); } diff --git a/lib/GfxRenderer/GfxRenderer.cpp b/lib/GfxRenderer/GfxRenderer.cpp index ffe7f0e7..ffc3b482 100644 --- a/lib/GfxRenderer/GfxRenderer.cpp +++ b/lib/GfxRenderer/GfxRenderer.cpp @@ -756,10 +756,8 @@ void GfxRenderer::displayBuffer(const HalDisplay::RefreshMode refreshMode) const } // EXPERIMENTAL: Display only a rectangular region with specified refresh mode -void GfxRenderer::displayWindow(int x, int y, int width, int height, - HalDisplay::RefreshMode mode) const { - LOG_DBG("GFX", "Displaying window at (%d,%d) size (%dx%d) with mode %d", x, y, width, height, - static_cast(mode)); +void GfxRenderer::displayWindow(int x, int y, int width, int height, HalDisplay::RefreshMode mode) const { + LOG_DBG("GFX", "Displaying window at (%d,%d) size (%dx%d) with mode %d", x, y, width, height, static_cast(mode)); // Validate bounds if (x < 0 || y < 0 || x + width > getScreenWidth() || y + height > getScreenHeight()) { @@ -767,9 +765,8 @@ void GfxRenderer::displayWindow(int x, int y, int width, int height, return; } - display.displayWindow(static_cast(x), static_cast(y), - static_cast(width), static_cast(height), mode, - fadingFix); + display.displayWindow(static_cast(x), static_cast(y), static_cast(width), + static_cast(height), mode, fadingFix); } std::string GfxRenderer::truncatedText(const int fontId, const char* text, const int maxWidth, diff --git a/lib/PlaceholderCover/BookIcon.h b/lib/PlaceholderCover/BookIcon.h index 344efaf0..162cbaf2 100644 --- a/lib/PlaceholderCover/BookIcon.h +++ b/lib/PlaceholderCover/BookIcon.h @@ -6,22 +6,20 @@ static constexpr int BOOK_ICON_WIDTH = 48; static constexpr int BOOK_ICON_HEIGHT = 48; static const uint8_t BookIcon[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, - 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, - 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, - 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1c, 0x00, 0x00, 0x01, 0x9f, 0xfc, 0x1f, - 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, - 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1c, 0x00, 0x01, - 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, - 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, - 0xfc, 0x1c, 0x00, 0x00, 0x1f, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, - 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, - 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, - 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, - 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, - 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1c, 0x00, 0x00, 0x01, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1c, 0x00, 0x01, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1c, 0x00, 0x00, 0x1f, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x9f, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; diff --git a/lib/PlaceholderCover/PlaceholderCoverGenerator.cpp b/lib/PlaceholderCover/PlaceholderCoverGenerator.cpp index b0dfa7a9..2752b093 100644 --- a/lib/PlaceholderCover/PlaceholderCoverGenerator.cpp +++ b/lib/PlaceholderCover/PlaceholderCoverGenerator.cpp @@ -123,15 +123,13 @@ class PixelBuffer { /// Draw a rectangular border in black. void drawBorder(int x, int y, int w, int h, int thickness) { fillRect(x, y, w, thickness); // Top - fillRect(x, y + h - thickness, w, thickness); // Bottom - fillRect(x, y, thickness, h); // Left - fillRect(x + w - thickness, y, thickness, h); // Right + fillRect(x, y + h - thickness, w, thickness); // Bottom + fillRect(x, y, thickness, h); // Left + fillRect(x + w - thickness, y, thickness, h); // Right } /// Draw a horizontal line in black with configurable thickness. - void drawHLine(int x, int y, int length, int thickness = 1) { - fillRect(x, y, length, thickness); - } + void drawHLine(int x, int y, int length, int thickness = 1) { fillRect(x, y, length, thickness); } /// Render a single glyph at (cursorX, baselineY) with integer scaling. Returns advance in X (scaled). int renderGlyph(const EpdFontData* font, uint32_t codepoint, int cursorX, int baselineY, int scale = 1) { @@ -321,16 +319,15 @@ bool PlaceholderCoverGenerator::generate(const std::string& outputPath, const st PixelBuffer buf(width, height); if (!buf.isValid()) { - LOG_ERR("PHC", "Failed to allocate %dx%d pixel buffer (%d bytes)", width, height, - (width + 31) / 32 * 4 * height); + LOG_ERR("PHC", "Failed to allocate %dx%d pixel buffer (%d bytes)", width, height, (width + 31) / 32 * 4 * height); return false; } // 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 + 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; @@ -373,7 +370,7 @@ bool PlaceholderCoverGenerator::generate(const std::string& outputPath, const st // --- Icon dimensions (needed for title text wrapping) --- const int iconW = (iconScale > 0) ? BOOK_ICON_WIDTH * iconScale : 0; const int iconGap = (iconScale > 0) ? std::max(8, width / 40) : 0; // Gap between icon and title text - const int titleTextW = contentW - iconW - iconGap; // Title wraps in narrower area beside icon + const int titleTextW = contentW - iconW - iconGap; // Title wraps in narrower area beside icon // --- Prepare title text (wraps within the area to the right of the icon) --- const std::string displayTitle = title.empty() ? "Untitled" : title; @@ -403,9 +400,8 @@ bool PlaceholderCoverGenerator::generate(const std::string& outputPath, const st const int numTitleLines = static_cast(titleLines.size()); // Visual height: distance from top of first line to bottom of last line's glyphs. // Use ascender (not full advanceY) for the last line since trailing line-gap isn't visible. - const int titleVisualH = (numTitleLines > 0) - ? (numTitleLines - 1) * titleLineH + titleFont->ascender * titleScale - : 0; + const int titleVisualH = + (numTitleLines > 0) ? (numTitleLines - 1) * titleLineH + titleFont->ascender * titleScale : 0; const int titleBlockH = std::max(iconH, titleVisualH); // Taller of icon or text int titleStartY = contentY + (titleZoneH - titleBlockH) / 2; @@ -416,9 +412,7 @@ bool PlaceholderCoverGenerator::generate(const std::string& outputPath, const st // If title fits within icon height, center it vertically against the icon. // Otherwise top-align so extra lines overflow below. const int iconY = titleStartY; - const int titleTextY = (iconH > 0 && titleVisualH <= iconH) - ? titleStartY + (iconH - titleVisualH) / 2 - : titleStartY; + const int titleTextY = (iconH > 0 && titleVisualH <= iconH) ? titleStartY + (iconH - titleVisualH) / 2 : titleStartY; // --- Horizontal centering: measure the widest title line, then center icon+gap+text block --- int maxTitleLineW = 0; diff --git a/lib/hal/HalDisplay.cpp b/lib/hal/HalDisplay.cpp index 6145eea7..efdb7398 100644 --- a/lib/hal/HalDisplay.cpp +++ b/lib/hal/HalDisplay.cpp @@ -38,8 +38,8 @@ void HalDisplay::displayBuffer(HalDisplay::RefreshMode mode, bool turnOffScreen) } // EXPERIMENTAL: Display only a rectangular region -void HalDisplay::displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h, - HalDisplay::RefreshMode mode, bool turnOffScreen) { +void HalDisplay::displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h, HalDisplay::RefreshMode mode, + bool turnOffScreen) { (void)mode; // EInkDisplay::displayWindow does not take mode yet einkDisplay.displayWindow(x, y, w, h, turnOffScreen); } diff --git a/lib/hal/HalDisplay.h b/lib/hal/HalDisplay.h index 97dd5143..92b6bcad 100644 --- a/lib/hal/HalDisplay.h +++ b/lib/hal/HalDisplay.h @@ -37,8 +37,8 @@ class HalDisplay { void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); // EXPERIMENTAL: Display only a rectangular region - void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h, - RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); + void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h, RefreshMode mode = RefreshMode::FAST_REFRESH, + bool turnOffScreen = false); // Power management void deepSleep(); diff --git a/open-x4-sdk b/open-x4-sdk index c8ce3949..91e7e2be 160000 --- a/open-x4-sdk +++ b/open-x4-sdk @@ -1 +1 @@ -Subproject commit c8ce3949b3368329c290ca1858e65dc3416fc591 +Subproject commit 91e7e2bef7df514abc7b50aef763d0965abc00a6 diff --git a/src/SettingsList.h b/src/SettingsList.h index fe254ee7..6ad2f193 100644 --- a/src/SettingsList.h +++ b/src/SettingsList.h @@ -58,17 +58,16 @@ inline std::vector getSettingsList() { {StrId::STR_NONE_OPT, StrId::STR_FILTER_CONTRAST, StrId::STR_INVERTED}, "sleepScreenCoverFilter", StrId::STR_CAT_DISPLAY), SettingInfo::Enum(StrId::STR_LETTERBOX_FILL, &CrossPointSettings::sleepScreenLetterboxFill, - {StrId::STR_DITHERED, StrId::STR_SOLID, StrId::STR_NONE_OPT}, - "sleepScreenLetterboxFill", StrId::STR_CAT_DISPLAY), + {StrId::STR_DITHERED, StrId::STR_SOLID, StrId::STR_NONE_OPT}, "sleepScreenLetterboxFill", + StrId::STR_CAT_DISPLAY), SettingInfo::Enum( StrId::STR_STATUS_BAR, &CrossPointSettings::statusBar, {StrId::STR_NONE_OPT, StrId::STR_NO_PROGRESS, StrId::STR_STATUS_BAR_FULL_PERCENT, StrId::STR_STATUS_BAR_FULL_BOOK, StrId::STR_STATUS_BAR_BOOK_ONLY, StrId::STR_STATUS_BAR_FULL_CHAPTER}, "statusBar", StrId::STR_CAT_DISPLAY), - SettingInfo::Enum( - StrId::STR_INDEXING_DISPLAY, &CrossPointSettings::indexingDisplay, - {StrId::STR_INDEXING_POPUP, StrId::STR_INDEXING_STATUS_TEXT, StrId::STR_INDEXING_STATUS_ICON}, - "indexingDisplay", StrId::STR_CAT_DISPLAY), + SettingInfo::Enum(StrId::STR_INDEXING_DISPLAY, &CrossPointSettings::indexingDisplay, + {StrId::STR_INDEXING_POPUP, StrId::STR_INDEXING_STATUS_TEXT, StrId::STR_INDEXING_STATUS_ICON}, + "indexingDisplay", StrId::STR_CAT_DISPLAY), SettingInfo::Enum(StrId::STR_HIDE_BATTERY, &CrossPointSettings::hideBatteryPercentage, {StrId::STR_NEVER, StrId::STR_IN_READER, StrId::STR_ALWAYS}, "hideBatteryPercentage", StrId::STR_CAT_DISPLAY), @@ -135,9 +134,7 @@ inline std::vector getSettingsList() { "preferredPortrait", StrId::STR_CAT_READER), SettingInfo::DynamicEnum( StrId::STR_PREFERRED_LANDSCAPE, {StrId::STR_LANDSCAPE_CW, StrId::STR_LANDSCAPE_CCW}, - [] { - return static_cast(SETTINGS.preferredLandscape == CrossPointSettings::LANDSCAPE_CCW ? 1 : 0); - }, + [] { return static_cast(SETTINGS.preferredLandscape == CrossPointSettings::LANDSCAPE_CCW ? 1 : 0); }, [](uint8_t idx) { SETTINGS.preferredLandscape = (idx == 1) ? CrossPointSettings::LANDSCAPE_CCW : CrossPointSettings::LANDSCAPE_CW; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index e848e471..7aaf0e62 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -15,10 +15,10 @@ #include "CrossPointSettings.h" #include "CrossPointState.h" -#include "util/BookSettings.h" #include "components/UITheme.h" #include "fontIds.h" #include "images/Logo120.h" +#include "util/BookSettings.h" #include "util/StringUtils.h" namespace { @@ -80,9 +80,7 @@ uint8_t quantizeBayerDither(int gray, int x, int y) { // creating a high-frequency checkerboard that causes e-ink display crosstalk // and washes out adjacent content during HALF_REFRESH. // Gray values 171-254 produce a level-2/level-3 mix via Bayer dithering. -bool bayerCrossesBwBoundary(uint8_t gray) { - return gray > 170 && gray < 255; -} +bool bayerCrossesBwBoundary(uint8_t gray) { return gray > 170 && gray < 255; } // Hash-based block dithering for BW-boundary gray values (171-254). // Each blockSize×blockSize pixel block gets a single uniform level (2 or 3), @@ -301,9 +299,12 @@ void drawLetterboxFill(GfxRenderer& renderer, const LetterboxFillData& data, uin for (int y = 0; y < data.letterboxA; y++) for (int x = 0; x < renderer.getScreenWidth(); x++) { uint8_t lv; - if (isSolid) lv = levelA; - else if (hashA) lv = hashBlockDither(data.avgA, x, y); - else lv = quantizeBayerDither(data.avgA, x, y); + if (isSolid) + lv = levelA; + else if (hashA) + lv = hashBlockDither(data.avgA, x, y); + else + lv = quantizeBayerDither(data.avgA, x, y); renderer.drawPixelGray(x, y, lv); } } @@ -312,9 +313,12 @@ void drawLetterboxFill(GfxRenderer& renderer, const LetterboxFillData& data, uin for (int y = start; y < renderer.getScreenHeight(); y++) for (int x = 0; x < renderer.getScreenWidth(); x++) { uint8_t lv; - if (isSolid) lv = levelB; - else if (hashB) lv = hashBlockDither(data.avgB, x, y); - else lv = quantizeBayerDither(data.avgB, x, y); + if (isSolid) + lv = levelB; + else if (hashB) + lv = hashBlockDither(data.avgB, x, y); + else + lv = quantizeBayerDither(data.avgB, x, y); renderer.drawPixelGray(x, y, lv); } } @@ -323,9 +327,12 @@ void drawLetterboxFill(GfxRenderer& renderer, const LetterboxFillData& data, uin for (int x = 0; x < data.letterboxA; x++) for (int y = 0; y < renderer.getScreenHeight(); y++) { uint8_t lv; - if (isSolid) lv = levelA; - else if (hashA) lv = hashBlockDither(data.avgA, x, y); - else lv = quantizeBayerDither(data.avgA, x, y); + if (isSolid) + lv = levelA; + else if (hashA) + lv = hashBlockDither(data.avgA, x, y); + else + lv = quantizeBayerDither(data.avgA, x, y); renderer.drawPixelGray(x, y, lv); } } @@ -334,9 +341,12 @@ void drawLetterboxFill(GfxRenderer& renderer, const LetterboxFillData& data, uin for (int x = start; x < renderer.getScreenWidth(); x++) for (int y = 0; y < renderer.getScreenHeight(); y++) { uint8_t lv; - if (isSolid) lv = levelB; - else if (hashB) lv = hashBlockDither(data.avgB, x, y); - else lv = quantizeBayerDither(data.avgB, x, y); + if (isSolid) + lv = levelB; + else if (hashB) + lv = hashBlockDither(data.avgB, x, y); + else + lv = quantizeBayerDither(data.avgB, x, y); renderer.drawPixelGray(x, y, lv); } } @@ -523,9 +533,8 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap, const std::str } } if (fillData.valid) { - LOG_DBG("SLP", "Letterbox fill: %s, horizontal=%d, avgA=%d, avgB=%d, letterboxA=%d, letterboxB=%d", - fillModeName, fillData.horizontal, fillData.avgA, fillData.avgB, fillData.letterboxA, - fillData.letterboxB); + LOG_DBG("SLP", "Letterbox fill: %s, horizontal=%d, avgA=%d, avgB=%d, letterboxA=%d, letterboxB=%d", fillModeName, + fillData.horizontal, fillData.avgA, fillData.avgB, fillData.letterboxA, fillData.letterboxB); } } diff --git a/src/activities/home/HomeActivity.cpp b/src/activities/home/HomeActivity.cpp index f6e2ca15..418015e4 100644 --- a/src/activities/home/HomeActivity.cpp +++ b/src/activities/home/HomeActivity.cpp @@ -5,8 +5,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/activities/reader/DictionaryDefinitionActivity.cpp b/src/activities/reader/DictionaryDefinitionActivity.cpp index 6771b350..83d5096c 100644 --- a/src/activities/reader/DictionaryDefinitionActivity.cpp +++ b/src/activities/reader/DictionaryDefinitionActivity.cpp @@ -17,9 +17,7 @@ void DictionaryDefinitionActivity::onEnter() { requestUpdate(); } -void DictionaryDefinitionActivity::onExit() { - Activity::onExit(); -} +void DictionaryDefinitionActivity::onExit() { Activity::onExit(); } // --------------------------------------------------------------------------- // Check if a Unicode codepoint is likely renderable by the e-ink bitmap font. @@ -27,12 +25,12 @@ void DictionaryDefinitionActivity::onExit() { // Skips IPA extensions, Greek, Cyrillic, Arabic, CJK, and other non-Latin scripts. // --------------------------------------------------------------------------- bool DictionaryDefinitionActivity::isRenderableCodepoint(uint32_t cp) { - if (cp <= 0x024F) return true; // Basic Latin + Latin Extended-A/B - if (cp >= 0x0300 && cp <= 0x036F) return true; // Combining Diacritical Marks - if (cp >= 0x2000 && cp <= 0x206F) return true; // General Punctuation - if (cp >= 0x20A0 && cp <= 0x20CF) return true; // Currency Symbols - if (cp >= 0x2100 && cp <= 0x214F) return true; // Letterlike Symbols - if (cp >= 0x2190 && cp <= 0x21FF) return true; // Arrows + if (cp <= 0x024F) return true; // Basic Latin + Latin Extended-A/B + if (cp >= 0x0300 && cp <= 0x036F) return true; // Combining Diacritical Marks + if (cp >= 0x2000 && cp <= 0x206F) return true; // General Punctuation + if (cp >= 0x20A0 && cp <= 0x20CF) return true; // Currency Symbols + if (cp >= 0x2100 && cp <= 0x214F) return true; // Letterlike Symbols + if (cp >= 0x2190 && cp <= 0x21FF) return true; // Arrows return false; } @@ -48,7 +46,7 @@ std::string DictionaryDefinitionActivity::decodeEntity(const std::string& entity if (entity == "apos") return "'"; if (entity == "nbsp" || entity == "thinsp" || entity == "ensp" || entity == "emsp") return " "; if (entity == "ndash") return "\xE2\x80\x93"; // U+2013 - if (entity == "mdash") return "\xE2\x80\x94"; // U+2014 + if (entity == "mdash") return "\xE2\x80\x94"; // U+2014 if (entity == "lsquo") return "\xE2\x80\x98"; if (entity == "rsquo") return "\xE2\x80\x99"; if (entity == "ldquo") return "\xE2\x80\x9C"; @@ -502,11 +500,11 @@ void DictionaryDefinitionActivity::render(Activity::RenderLock&&) { const int tw = renderer.getTextWidth(SMALL_FONT_ID, truncated.c_str()); if (useCCW) { - renderer.drawTextRotated90CCW(SMALL_FONT_ID, sideX, - sideButtonY[i] + (sideButtonHeight - tw) / 2, truncated.c_str()); + renderer.drawTextRotated90CCW(SMALL_FONT_ID, sideX, sideButtonY[i] + (sideButtonHeight - tw) / 2, + truncated.c_str()); } else { - renderer.drawTextRotated90CW(SMALL_FONT_ID, sideX, - sideButtonY[i] + (sideButtonHeight + tw) / 2, truncated.c_str()); + renderer.drawTextRotated90CW(SMALL_FONT_ID, sideX, sideButtonY[i] + (sideButtonHeight + tw) / 2, + truncated.c_str()); } } diff --git a/src/activities/reader/DictionarySuggestionsActivity.cpp b/src/activities/reader/DictionarySuggestionsActivity.cpp index 3f0d84be..2209b714 100644 --- a/src/activities/reader/DictionarySuggestionsActivity.cpp +++ b/src/activities/reader/DictionarySuggestionsActivity.cpp @@ -13,9 +13,7 @@ void DictionarySuggestionsActivity::onEnter() { requestUpdate(); } -void DictionarySuggestionsActivity::onExit() { - ActivityWithSubactivity::onExit(); -} +void DictionarySuggestionsActivity::onExit() { ActivityWithSubactivity::onExit(); } void DictionarySuggestionsActivity::loop() { if (subActivity) { @@ -66,8 +64,8 @@ void DictionarySuggestionsActivity::loop() { } enterNewActivity(new DictionaryDefinitionActivity( - renderer, mappedInput, selected, definition, readerFontId, orientation, - [this]() { pendingBackFromDef = true; }, [this]() { pendingExitToReader = true; })); + renderer, mappedInput, selected, definition, readerFontId, orientation, [this]() { pendingBackFromDef = true; }, + [this]() { pendingExitToReader = true; })); return; } diff --git a/src/activities/reader/DictionaryWordSelectActivity.cpp b/src/activities/reader/DictionaryWordSelectActivity.cpp index ad8be929..958091f7 100644 --- a/src/activities/reader/DictionaryWordSelectActivity.cpp +++ b/src/activities/reader/DictionaryWordSelectActivity.cpp @@ -25,9 +25,7 @@ void DictionaryWordSelectActivity::onEnter() { requestUpdate(); } -void DictionaryWordSelectActivity::onExit() { - ActivityWithSubactivity::onExit(); -} +void DictionaryWordSelectActivity::onExit() { ActivityWithSubactivity::onExit(); } bool DictionaryWordSelectActivity::isLandscape() const { return orientation == CrossPointSettings::ORIENTATION::LANDSCAPE_CW || @@ -368,8 +366,8 @@ void DictionaryWordSelectActivity::loop() { if (!definition.empty()) { enterNewActivity(new DictionaryDefinitionActivity( - renderer, mappedInput, cleaned, definition, fontId, orientation, - [this]() { pendingBackFromDef = true; }, [this]() { pendingExitToReader = true; })); + renderer, mappedInput, cleaned, definition, fontId, orientation, [this]() { pendingBackFromDef = true; }, + [this]() { pendingExitToReader = true; })); return; } @@ -379,8 +377,8 @@ void DictionaryWordSelectActivity::loop() { std::string stemDef = Dictionary::lookup(stem); if (!stemDef.empty()) { enterNewActivity(new DictionaryDefinitionActivity( - renderer, mappedInput, stem, stemDef, fontId, orientation, - [this]() { pendingBackFromDef = true; }, [this]() { pendingExitToReader = true; })); + renderer, mappedInput, stem, stemDef, fontId, orientation, [this]() { pendingBackFromDef = true; }, + [this]() { pendingExitToReader = true; })); return; } } @@ -459,7 +457,7 @@ void DictionaryWordSelectActivity::drawHints() { renderer.setOrientation(origOrientation); // Bottom button constants (match LyraTheme::drawButtonHints) - constexpr int buttonHeight = 40; // LyraMetrics::values.buttonHintsHeight + constexpr int buttonHeight = 40; // LyraMetrics::values.buttonHintsHeight constexpr int buttonWidth = 80; constexpr int cornerRadius = 6; constexpr int textYOffset = 7; @@ -467,35 +465,43 @@ void DictionaryWordSelectActivity::drawHints() { constexpr int buttonPositions[] = {58, 146, 254, 342}; // Side button constants (match LyraTheme::drawSideButtonHints) - constexpr int sideButtonWidth = 30; // LyraMetrics::values.sideButtonHintsWidth + constexpr int sideButtonWidth = 30; // LyraMetrics::values.sideButtonHintsWidth constexpr int sideButtonHeight = 78; constexpr int sideButtonGap = 5; - constexpr int sideTopY = 345; // topHintButtonY + constexpr int sideTopY = 345; // topHintButtonY const int sideX = portW - sideButtonWidth; const int sideButtonY[2] = {sideTopY, sideTopY + sideButtonHeight + sideButtonGap}; // Labels for face and side buttons depend on orientation, // because the physical-to-logical mapping rotates with the screen. - const char* facePrev; // label for physical Left face button - const char* faceNext; // label for physical Right face button - const char* sideTop; // label for physical top side button (PageBack) - const char* sideBottom; // label for physical bottom side button (PageForward) + const char* facePrev; // label for physical Left face button + const char* faceNext; // label for physical Right face button + const char* sideTop; // label for physical top side button (PageBack) + const char* sideBottom; // label for physical bottom side button (PageForward) const bool landscape = isLandscape(); const bool inverted = isInverted(); if (landscape && orientation == CrossPointSettings::ORIENTATION::LANDSCAPE_CW) { - facePrev = "Line Up"; faceNext = "Line Dn"; - sideTop = "Word \xC2\xBB"; sideBottom = "\xC2\xAB Word"; + facePrev = "Line Up"; + faceNext = "Line Dn"; + sideTop = "Word \xC2\xBB"; + sideBottom = "\xC2\xAB Word"; } else if (landscape) { // LANDSCAPE_CCW - facePrev = "Line Dn"; faceNext = "Line Up"; - sideTop = "\xC2\xAB Word"; sideBottom = "Word \xC2\xBB"; + facePrev = "Line Dn"; + faceNext = "Line Up"; + sideTop = "\xC2\xAB Word"; + sideBottom = "Word \xC2\xBB"; } else if (inverted) { - facePrev = "Word \xC2\xBB"; faceNext = "\xC2\xAB Word"; - sideTop = "Line Dn"; sideBottom = "Line Up"; + facePrev = "Word \xC2\xBB"; + faceNext = "\xC2\xAB Word"; + sideTop = "Line Dn"; + sideBottom = "Line Up"; } else { // Portrait (default) - facePrev = "\xC2\xAB Word"; faceNext = "Word \xC2\xBB"; - sideTop = "Line Up"; sideBottom = "Line Dn"; + facePrev = "\xC2\xAB Word"; + faceNext = "Word \xC2\xBB"; + sideTop = "Line Up"; + sideBottom = "Line Dn"; } const auto labels = mappedInput.mapLabels("\xC2\xAB Back", "Select", facePrev, faceNext); @@ -622,12 +628,12 @@ void DictionaryWordSelectActivity::drawHints() { if (useCCW) { // Text reads top-to-bottom (90° CCW rotation): y starts near top of button - renderer.drawTextRotated90CCW(SMALL_FONT_ID, sideX, - sideButtonY[i] + (sideButtonHeight - tw) / 2, truncated.c_str()); + renderer.drawTextRotated90CCW(SMALL_FONT_ID, sideX, sideButtonY[i] + (sideButtonHeight - tw) / 2, + truncated.c_str()); } else { // Text reads bottom-to-top (90° CW rotation): y starts near bottom of button - renderer.drawTextRotated90CW(SMALL_FONT_ID, sideX, - sideButtonY[i] + (sideButtonHeight + tw) / 2, truncated.c_str()); + renderer.drawTextRotated90CW(SMALL_FONT_ID, sideX, sideButtonY[i] + (sideButtonHeight + tw) / 2, + truncated.c_str()); } } diff --git a/src/activities/reader/DictionaryWordSelectActivity.h b/src/activities/reader/DictionaryWordSelectActivity.h index dbaec852..667e5b2c 100644 --- a/src/activities/reader/DictionaryWordSelectActivity.h +++ b/src/activities/reader/DictionaryWordSelectActivity.h @@ -13,8 +13,7 @@ class DictionaryWordSelectActivity final : public ActivityWithSubactivity { explicit DictionaryWordSelectActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr page, int fontId, int marginLeft, int marginTop, const std::string& cachePath, uint8_t orientation, - const std::function& onBack, - const std::string& nextPageFirstWord = "") + const std::function& onBack, const std::string& nextPageFirstWord = "") : ActivityWithSubactivity("DictionaryWordSelect", renderer, mappedInput), page(std::move(page)), fontId(fontId), diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 968fc43a..2da34d12 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -6,7 +6,6 @@ #include #include #include - #include #include "CrossPointSettings.h" @@ -242,8 +241,7 @@ void EpubReaderActivity::loop() { } // Long press CONFIRM opens Table of Contents directly (skip menu) - if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && - mappedInput.getHeldTime() >= longPressConfirmMs) { + if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() >= longPressConfirmMs) { ignoreNextConfirmRelease = true; if (epub && epub->getTocItemsCount() > 0) { openChapterSelection(true); // skip the stale release from this long-press @@ -266,8 +264,8 @@ void EpubReaderActivity::loop() { } const int bookProgressPercent = clampPercent(static_cast(bookProgress + 0.5f)); const bool hasDictionary = Dictionary::exists(); - const bool isBookmarked = BookmarkStore::hasBookmark( - epub->getCachePath(), currentSpineIndex, section ? section->currentPage : 0); + const bool isBookmarked = + BookmarkStore::hasBookmark(epub->getCachePath(), currentSpineIndex, section ? section->currentPage : 0); exitActivity(); enterNewActivity(new EpubReaderMenuActivity( this->renderer, this->mappedInput, epub->getTitle(), currentPage, totalPages, bookProgressPercent, @@ -935,13 +933,11 @@ void EpubReaderActivity::render(Activity::RenderLock&& lock) { silentIndexingActive = false; const bool textOnlyPage = !p->hasImages(); - if (textOnlyPage && - SETTINGS.indexingDisplay != CrossPointSettings::INDEXING_DISPLAY::INDEXING_POPUP && + if (textOnlyPage && SETTINGS.indexingDisplay != CrossPointSettings::INDEXING_DISPLAY::INDEXING_POPUP && section->pageCount >= 1 && ((section->pageCount == 1 && section->currentPage == 0) || (section->pageCount >= 2 && section->currentPage == section->pageCount - 2)) && - currentSpineIndex + 1 < epub->getSpineItemsCount() && - preIndexedNextSpine != currentSpineIndex + 1) { + currentSpineIndex + 1 < epub->getSpineItemsCount() && preIndexedNextSpine != currentSpineIndex + 1) { Section probe(epub, currentSpineIndex + 1, renderer); if (probe.loadSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(), SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth, @@ -971,9 +967,8 @@ bool EpubReaderActivity::silentIndexNextChapterIfNeeded(const uint16_t viewportW return false; } - const bool shouldPreIndex = - (section->pageCount == 1 && section->currentPage == 0) || - (section->pageCount >= 2 && section->currentPage == section->pageCount - 2); + const bool shouldPreIndex = (section->pageCount == 1 && section->currentPage == 0) || + (section->pageCount >= 2 && section->currentPage == section->pageCount - 2); if (!epub || !section || !shouldPreIndex) { silentIndexingActive = false; return false; @@ -1065,8 +1060,8 @@ void EpubReaderActivity::renderContents(std::unique_ptr page, const int or if (page->getImageBoundingBox(imgX, imgY, imgW, imgH)) { int screenX = imgX + orientedMarginLeft; int screenY = imgY + orientedMarginTop; - LOG_DBG("ERS", "Image page: fast double-refresh (page bbox: %d,%d %dx%d, screen: %d,%d %dx%d)", - imgX, imgY, imgW, imgH, screenX, screenY, imgW, imgH); + LOG_DBG("ERS", "Image page: fast double-refresh (page bbox: %d,%d %dx%d, screen: %d,%d %dx%d)", imgX, imgY, imgW, + imgH, screenX, screenY, imgW, imgH); #if USE_IMAGE_DOUBLE_FAST_REFRESH == 0 // Method A: Fill blank area + two FAST_REFRESH operations @@ -1233,8 +1228,7 @@ void EpubReaderActivity::renderStatusBar(const int orientedMarginRight, const in if (SETTINGS.indexingDisplay == CrossPointSettings::INDEXING_DISPLAY::INDEXING_STATUS_TEXT) { renderer.drawText(SMALL_FONT_ID, indicatorX, textY, tr(STR_INDEXING)); } else if (SETTINGS.indexingDisplay == CrossPointSettings::INDEXING_DISPLAY::INDEXING_STATUS_ICON) { - renderer.drawIcon(kIndexingIcon, indicatorX, textY - kIndexingIconSize + 2, kIndexingIconSize, - kIndexingIconSize); + renderer.drawIcon(kIndexingIcon, indicatorX, textY - kIndexingIconSize + 2, kIndexingIconSize, kIndexingIconSize); } } } diff --git a/src/activities/reader/EpubReaderActivity.h b/src/activities/reader/EpubReaderActivity.h index 589825d6..bec036db 100644 --- a/src/activities/reader/EpubReaderActivity.h +++ b/src/activities/reader/EpubReaderActivity.h @@ -20,13 +20,13 @@ class EpubReaderActivity final : public ActivityWithSubactivity { bool pendingPercentJump = false; // Normalized 0.0-1.0 progress within the target spine item, computed from book percentage. float pendingSpineProgress = 0.0f; - bool pendingSubactivityExit = false; // Defer subactivity exit to avoid use-after-free - bool pendingGoHome = false; // Defer go home to avoid race condition with display task - bool skipNextButtonCheck = false; // Skip button processing for one frame after subactivity exit - bool ignoreNextConfirmRelease = false; // Suppress short-press after long-press Confirm - volatile bool loadingSection = false; // True during the entire !section block (read from main loop) - bool silentIndexingActive = false; // True while silently pre-indexing the next chapter - int preIndexedNextSpine = -1; // Spine index already pre-indexed (prevents re-render loop) + bool pendingSubactivityExit = false; // Defer subactivity exit to avoid use-after-free + bool pendingGoHome = false; // Defer go home to avoid race condition with display task + bool skipNextButtonCheck = false; // Skip button processing for one frame after subactivity exit + bool ignoreNextConfirmRelease = false; // Suppress short-press after long-press Confirm + volatile bool loadingSection = false; // True during the entire !section block (read from main loop) + bool silentIndexingActive = false; // True while silently pre-indexing the next chapter + int preIndexedNextSpine = -1; // Spine index already pre-indexed (prevents re-render loop) const std::function onGoBack; const std::function onGoHome; diff --git a/src/activities/reader/EpubReaderBookmarkSelectionActivity.cpp b/src/activities/reader/EpubReaderBookmarkSelectionActivity.cpp index 44351aa1..cbb47d0b 100644 --- a/src/activities/reader/EpubReaderBookmarkSelectionActivity.cpp +++ b/src/activities/reader/EpubReaderBookmarkSelectionActivity.cpp @@ -47,9 +47,7 @@ void EpubReaderBookmarkSelectionActivity::onEnter() { requestUpdate(); } -void EpubReaderBookmarkSelectionActivity::onExit() { - ActivityWithSubactivity::onExit(); -} +void EpubReaderBookmarkSelectionActivity::onExit() { ActivityWithSubactivity::onExit(); } void EpubReaderBookmarkSelectionActivity::loop() { if (subActivity) { @@ -207,8 +205,8 @@ void EpubReaderBookmarkSelectionActivity::render(Activity::RenderLock&&) { if (!bookmarks.empty()) { const char* deleteHint = "Hold select to delete"; const int hintWidth = renderer.getTextWidth(SMALL_FONT_ID, deleteHint); - renderer.drawText(SMALL_FONT_ID, (renderer.getScreenWidth() - hintWidth) / 2, - renderer.getScreenHeight() - 70, deleteHint); + renderer.drawText(SMALL_FONT_ID, (renderer.getScreenWidth() - hintWidth) / 2, renderer.getScreenHeight() - 70, + deleteHint); } const auto labels = mappedInput.mapLabels("\xC2\xAB Back", "Select", "Up", "Down"); diff --git a/src/activities/reader/EpubReaderBookmarkSelectionActivity.h b/src/activities/reader/EpubReaderBookmarkSelectionActivity.h index 48703a84..a9818455 100644 --- a/src/activities/reader/EpubReaderBookmarkSelectionActivity.h +++ b/src/activities/reader/EpubReaderBookmarkSelectionActivity.h @@ -26,12 +26,10 @@ class EpubReaderBookmarkSelectionActivity final : public ActivityWithSubactivity static std::string getPageSuffix(const Bookmark& bookmark); public: - explicit EpubReaderBookmarkSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, - const std::shared_ptr& epub, - std::vector bookmarks, - const std::string& cachePath, - const std::function& onGoBack, - const std::function& onSelectBookmark) + explicit EpubReaderBookmarkSelectionActivity( + GfxRenderer& renderer, MappedInputManager& mappedInput, const std::shared_ptr& epub, + std::vector bookmarks, const std::string& cachePath, const std::function& onGoBack, + const std::function& onSelectBookmark) : ActivityWithSubactivity("EpubReaderBookmarkSelection", renderer, mappedInput), epub(epub), bookmarks(std::move(bookmarks)), diff --git a/src/activities/reader/EpubReaderMenuActivity.cpp b/src/activities/reader/EpubReaderMenuActivity.cpp index ad7206ac..265c6b2e 100644 --- a/src/activities/reader/EpubReaderMenuActivity.cpp +++ b/src/activities/reader/EpubReaderMenuActivity.cpp @@ -40,13 +40,13 @@ void EpubReaderMenuActivity::loop() { return; } buttonNavigator.onNext([this] { - orientationSelectIndex = ButtonNavigator::nextIndex(orientationSelectIndex, - static_cast(orientationLabels.size())); + orientationSelectIndex = + ButtonNavigator::nextIndex(orientationSelectIndex, static_cast(orientationLabels.size())); requestUpdate(); }); buttonNavigator.onPrevious([this] { - orientationSelectIndex = ButtonNavigator::previousIndex(orientationSelectIndex, - static_cast(orientationLabels.size())); + orientationSelectIndex = + ButtonNavigator::previousIndex(orientationSelectIndex, static_cast(orientationLabels.size())); requestUpdate(); }); return; @@ -92,8 +92,8 @@ void EpubReaderMenuActivity::loop() { // Toggle between the two preferred orientations. // If currently in a portrait-category orientation (Portrait/Inverted), switch to preferredLandscape. // If currently in a landscape-category orientation (CW/CCW), switch to preferredPortrait. - const bool isCurrentlyPortrait = (pendingOrientation == CrossPointSettings::PORTRAIT || - pendingOrientation == CrossPointSettings::INVERTED); + const bool isCurrentlyPortrait = + (pendingOrientation == CrossPointSettings::PORTRAIT || pendingOrientation == CrossPointSettings::INVERTED); if (isCurrentlyPortrait) { pendingOrientation = SETTINGS.preferredLandscape; } else { diff --git a/src/activities/reader/EpubReaderMenuActivity.h b/src/activities/reader/EpubReaderMenuActivity.h index a8b9e853..ac7b205b 100644 --- a/src/activities/reader/EpubReaderMenuActivity.h +++ b/src/activities/reader/EpubReaderMenuActivity.h @@ -33,8 +33,7 @@ class EpubReaderMenuActivity final : public ActivityWithSubactivity { explicit EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& title, const int currentPage, const int totalPages, const int bookProgressPercent, const uint8_t currentOrientation, const uint8_t currentFontSize, - const bool hasDictionary, const bool isBookmarked, - const std::string& bookCachePath, + const bool hasDictionary, const bool isBookmarked, const std::string& bookCachePath, const std::function& onBack, const std::function& onAction) : ActivityWithSubactivity("EpubReaderMenu", renderer, mappedInput), @@ -74,14 +73,13 @@ class EpubReaderMenuActivity final : public ActivityWithSubactivity { uint8_t pendingFontSize = 0; const std::vector orientationLabels = {StrId::STR_PORTRAIT, StrId::STR_LANDSCAPE_CW, StrId::STR_INVERTED, StrId::STR_LANDSCAPE_CCW}; - const std::vector fontSizeLabels = {StrId::STR_SMALL, StrId::STR_MEDIUM, StrId::STR_LARGE, - StrId::STR_X_LARGE}; + const std::vector fontSizeLabels = {StrId::STR_SMALL, StrId::STR_MEDIUM, StrId::STR_LARGE, StrId::STR_X_LARGE}; std::string bookCachePath; // Letterbox fill override: 0xFF = Default (use global), 0 = Dithered, 1 = Solid, 2 = None uint8_t pendingLetterboxFill = BookSettings::USE_GLOBAL; static constexpr int LETTERBOX_FILL_OPTION_COUNT = 4; // Default + 3 modes const std::vector letterboxFillLabels = {StrId::STR_DEFAULT_OPTION, StrId::STR_DITHERED, StrId::STR_SOLID, - StrId::STR_NONE_OPT}; + StrId::STR_NONE_OPT}; int currentPage = 0; int totalPages = 0; int bookProgressPercent = 0; @@ -100,7 +98,7 @@ class EpubReaderMenuActivity final : public ActivityWithSubactivity { // Map the internal override value to an index into letterboxFillLabels. int letterboxFillToIndex() const { if (pendingLetterboxFill == BookSettings::USE_GLOBAL) return 0; // "Default" - return pendingLetterboxFill + 1; // 0->1 (Dithered), 1->2 (Solid), 2->3 (None) + return pendingLetterboxFill + 1; // 0->1 (Dithered), 1->2 (Solid), 2->3 (None) } // Map an index from letterboxFillLabels back to an override value. @@ -137,5 +135,4 @@ class EpubReaderMenuActivity final : public ActivityWithSubactivity { items.push_back({MenuAction::DELETE_CACHE, StrId::STR_DELETE_CACHE}); return items; } - }; diff --git a/src/activities/reader/LookedUpWordsActivity.cpp b/src/activities/reader/LookedUpWordsActivity.cpp index c301d96f..a221ca0a 100644 --- a/src/activities/reader/LookedUpWordsActivity.cpp +++ b/src/activities/reader/LookedUpWordsActivity.cpp @@ -23,9 +23,7 @@ void LookedUpWordsActivity::onEnter() { requestUpdate(); } -void LookedUpWordsActivity::onExit() { - ActivityWithSubactivity::onExit(); -} +void LookedUpWordsActivity::onExit() { ActivityWithSubactivity::onExit(); } void LookedUpWordsActivity::loop() { if (subActivity) { @@ -83,8 +81,8 @@ void LookedUpWordsActivity::loop() { // Detect long press on Confirm to trigger delete (only for real word entries, not sentinel) constexpr unsigned long DELETE_HOLD_MS = 700; - if (selectedIndex != deleteDictCacheIndex && - mappedInput.isPressed(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() >= DELETE_HOLD_MS) { + if (selectedIndex != deleteDictCacheIndex && mappedInput.isPressed(MappedInputManager::Button::Confirm) && + mappedInput.getHeldTime() >= DELETE_HOLD_MS) { deleteConfirmMode = true; ignoreNextConfirmRelease = true; pendingDeleteIndex = selectedIndex; @@ -150,11 +148,10 @@ void LookedUpWordsActivity::loop() { Activity::RenderLock lock(*this); popupLayout = GUI.drawPopup(renderer, "Looking up..."); } - std::string definition = Dictionary::lookup( - headword, [this, &popupLayout](int percent) { - Activity::RenderLock lock(*this); - GUI.fillPopupProgress(renderer, popupLayout, percent); - }); + std::string definition = Dictionary::lookup(headword, [this, &popupLayout](int percent) { + Activity::RenderLock lock(*this); + GUI.fillPopupProgress(renderer, popupLayout, percent); + }); if (!definition.empty()) { enterNewActivity(new DictionaryDefinitionActivity( @@ -169,8 +166,8 @@ void LookedUpWordsActivity::loop() { std::string stemDef = Dictionary::lookup(stem); if (!stemDef.empty()) { enterNewActivity(new DictionaryDefinitionActivity( - renderer, mappedInput, stem, stemDef, readerFontId, orientation, - [this]() { pendingBackFromDef = true; }, [this]() { pendingExitToReader = true; })); + renderer, mappedInput, stem, stemDef, readerFontId, orientation, [this]() { pendingBackFromDef = true; }, + [this]() { pendingExitToReader = true; })); return; } } diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index 9e3819a0..9af68d00 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -3,11 +3,10 @@ #include #include #include +#include #include #include -#include - #include "CrossPointSettings.h" #include "CrossPointState.h" #include "MappedInputManager.h" @@ -85,7 +84,7 @@ void TxtReaderActivity::onEnter() { const int thumbHeight = PRERENDER_THUMB_HEIGHTS[i]; const int thumbWidth = static_cast(thumbHeight * 0.6); PlaceholderCoverGenerator::generate(txt->getThumbBmpPath(thumbHeight), txt->getTitle(), "", thumbWidth, - thumbHeight); + thumbHeight); updateProgress(); } } diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 7622ff3d..1181ce3e 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -11,7 +11,6 @@ #include #include #include - #include #include "CrossPointSettings.h" @@ -73,7 +72,7 @@ void XtcReaderActivity::onEnter() { const int thumbHeight = PRERENDER_THUMB_HEIGHTS[i]; const int thumbWidth = static_cast(thumbHeight * 0.6); PlaceholderCoverGenerator::generate(xtc->getThumbBmpPath(thumbHeight), xtc->getTitle(), xtc->getAuthor(), - thumbWidth, thumbHeight); + thumbWidth, thumbHeight); } updateProgress(); } diff --git a/src/activities/settings/CalibreSettingsActivity.cpp b/src/activities/settings/CalibreSettingsActivity.cpp index b37b140f..d6981e9f 100644 --- a/src/activities/settings/CalibreSettingsActivity.cpp +++ b/src/activities/settings/CalibreSettingsActivity.cpp @@ -142,7 +142,6 @@ void CalibreSettingsActivity::render(Activity::RenderLock&&) { }, true); - const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN)); GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); diff --git a/src/activities/settings/KOReaderSettingsActivity.cpp b/src/activities/settings/KOReaderSettingsActivity.cpp index ee1c7aa1..577584cd 100644 --- a/src/activities/settings/KOReaderSettingsActivity.cpp +++ b/src/activities/settings/KOReaderSettingsActivity.cpp @@ -168,7 +168,6 @@ void KOReaderSettingsActivity::render(Activity::RenderLock&&) { }, true); - const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN)); GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); diff --git a/src/activities/settings/SetTimeActivity.cpp b/src/activities/settings/SetTimeActivity.cpp index af7626a0..097b14a3 100644 --- a/src/activities/settings/SetTimeActivity.cpp +++ b/src/activities/settings/SetTimeActivity.cpp @@ -2,10 +2,10 @@ #include #include +#include #include #include -#include #include "CrossPointSettings.h" #include "MappedInputManager.h" @@ -106,8 +106,8 @@ void SetTimeActivity::render(Activity::RenderLock&&) { renderer.fillRoundedRect(startX - highlightPad, timeY - 4, digitWidth + highlightPad * 2, lineHeight12 + 8, 6, Color::LightGray); } else { - renderer.fillRoundedRect(startX + digitWidth + colonWidth - highlightPad, timeY - 4, - digitWidth + highlightPad * 2, lineHeight12 + 8, 6, Color::LightGray); + renderer.fillRoundedRect(startX + digitWidth + colonWidth - highlightPad, timeY - 4, digitWidth + highlightPad * 2, + lineHeight12 + 8, 6, Color::LightGray); } // Draw the time digits and colon diff --git a/src/activities/settings/SetTimeActivity.h b/src/activities/settings/SetTimeActivity.h index 193330b7..a74760b1 100644 --- a/src/activities/settings/SetTimeActivity.h +++ b/src/activities/settings/SetTimeActivity.h @@ -6,8 +6,7 @@ class SetTimeActivity final : public Activity { public: - explicit SetTimeActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, - const std::function& onBack) + explicit SetTimeActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::function& onBack) : Activity("SetTime", renderer, mappedInput), onBack(onBack) {} void onEnter() override; diff --git a/src/components/UITheme.cpp b/src/components/UITheme.cpp index 5f40d17a..b0fb8021 100644 --- a/src/components/UITheme.cpp +++ b/src/components/UITheme.cpp @@ -8,7 +8,6 @@ #include "MappedInputManager.h" #include "RecentBooksStore.h" #include "components/themes/BaseTheme.h" -#include "components/themes/lyra/Lyra3CoversTheme.h" #include "components/themes/lyra/LyraTheme.h" #include "util/StringUtils.h" @@ -42,8 +41,8 @@ void UITheme::setTheme(CrossPointSettings::UI_THEME type) { break; case CrossPointSettings::UI_THEME::LYRA_3_COVERS: LOG_DBG("UI", "Using Lyra 3 Covers theme"); - currentTheme = new Lyra3CoversTheme(); - currentMetrics = &Lyra3CoversMetrics::values; + currentTheme = std::make_unique(); + currentMetrics = &LyraMetrics::values; break; } } diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index 2bee8141..4336a073 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -283,8 +283,10 @@ void BaseTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t 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; + 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); } } diff --git a/src/components/themes/lyra/Lyra3CoversTheme.h b/src/components/themes/lyra/Lyra3CoversTheme.h deleted file mode 100644 index c02b4320..00000000 --- a/src/components/themes/lyra/Lyra3CoversTheme.h +++ /dev/null @@ -1,41 +0,0 @@ - - -#pragma once - -#include "components/themes/lyra/LyraTheme.h" - -class GfxRenderer; - -// Lyra theme metrics (zero runtime cost) -namespace Lyra3CoversMetrics { -constexpr ThemeMetrics values = {.batteryWidth = 16, - .batteryHeight = 12, - .topPadding = 5, - .batteryBarHeight = 40, - .headerHeight = 84, - .verticalSpacing = 16, - .contentSidePadding = 20, - .listRowHeight = 40, - .listWithSubtitleRowHeight = 60, - .menuRowHeight = 64, - .menuSpacing = 8, - .tabSpacing = 8, - .tabBarHeight = 40, - .scrollBarWidth = 4, - .scrollBarRightOffset = 5, - .homeTopPadding = 56, - .homeCoverHeight = 226, - .homeCoverTileHeight = 287, - .homeRecentBooksCount = 3, - .buttonHintsHeight = 40, - .sideButtonHintsWidth = 30, - .progressBarHeight = 16, - .bookProgressBarHeight = 4}; -} - -class Lyra3CoversTheme : public LyraTheme { - public: - void drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std::vector& recentBooks, - const int selectorIndex, bool& coverRendered, bool& coverBufferStored, bool& bufferRestored, - std::function storeCoverBuffer) const override; -}; diff --git a/src/components/themes/lyra/LyraTheme.cpp b/src/components/themes/lyra/LyraTheme.cpp index a8d0b263..fefb02fa 100644 --- a/src/components/themes/lyra/LyraTheme.cpp +++ b/src/components/themes/lyra/LyraTheme.cpp @@ -190,8 +190,10 @@ void LyraTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t 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; + 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); } } @@ -534,8 +536,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: if (!coverRendered) { renderer.drawRect(cardX + hPaddingInSelection, tileY + hPaddingInSelection, coverSlotWidth, coverHeight); if (!recentBooks[0].coverBmpPath.empty()) { - const std::string coverBmpPath = - UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, coverHeight); + const std::string coverBmpPath = UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, coverHeight); renderCoverBitmap(coverBmpPath, cardX + hPaddingInSelection, tileY + hPaddingInSelection, coverSlotWidth); } coverBufferStored = storeCoverBuffer(); @@ -598,8 +599,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: if (bookSelected) { renderer.fillRoundedRect(tileX, tileY, tileWidth, hPaddingInSelection, cornerRadius, true, true, false, false, Color::LightGray); - renderer.fillRectDither(tileX, tileY + hPaddingInSelection, hPaddingInSelection, coverHeight, - Color::LightGray); + renderer.fillRectDither(tileX, tileY + hPaddingInSelection, hPaddingInSelection, coverHeight, Color::LightGray); renderer.fillRectDither(tileX + tileWidth - hPaddingInSelection, tileY + hPaddingInSelection, hPaddingInSelection, coverHeight, Color::LightGray); renderer.fillRoundedRect(tileX, tileY + coverHeight + hPaddingInSelection, tileWidth, bottomSectionHeight, diff --git a/src/util/BookmarkStore.cpp b/src/util/BookmarkStore.cpp index bdedfd29..ed818636 100644 --- a/src/util/BookmarkStore.cpp +++ b/src/util/BookmarkStore.cpp @@ -138,10 +138,9 @@ bool BookmarkStore::addBookmark(const std::string& cachePath, int spineIndex, in bool BookmarkStore::removeBookmark(const std::string& cachePath, int spineIndex, int page) { auto bookmarks = load(cachePath); - auto it = std::remove_if(bookmarks.begin(), bookmarks.end(), - [spineIndex, page](const Bookmark& b) { - return b.spineIndex == spineIndex && b.pageNumber == page; - }); + auto it = std::remove_if(bookmarks.begin(), bookmarks.end(), [spineIndex, page](const Bookmark& b) { + return b.spineIndex == spineIndex && b.pageNumber == page; + }); if (it == bookmarks.end()) { return false; // Not found diff --git a/src/util/Dictionary.cpp b/src/util/Dictionary.cpp index 8e75b202..58da4c38 100644 --- a/src/util/Dictionary.cpp +++ b/src/util/Dictionary.cpp @@ -351,7 +351,7 @@ std::vector Dictionary::getStemVariants(const std::string& word) { if (endsWith("ves")) { add(word.substr(0, len - 3) + "f"); // wolves -> wolf add(word.substr(0, len - 3) + "fe"); // knives -> knife - add(word.substr(0, len - 1)); // misgives -> misgive + add(word.substr(0, len - 1)); // misgives -> misgive } if (endsWith("men")) add(word.substr(0, len - 3) + "man"); // firemen -> fireman if (endsWith("es") && !endsWith("sses") && !endsWith("ies") && !endsWith("ves")) { @@ -390,11 +390,11 @@ std::vector Dictionary::getStemVariants(const std::string& word) { // Adverb if (endsWith("ically")) { add(word.substr(0, len - 6) + "ic"); // historically -> historic - add(word.substr(0, len - 4)); // basically -> basic + add(word.substr(0, len - 4)); // basically -> basic } if (endsWith("ally") && !endsWith("ically")) { add(word.substr(0, len - 4) + "al"); // accidentally -> accidental - add(word.substr(0, len - 2)); // naturally -> natur... (fallback to -ly strip) + add(word.substr(0, len - 2)); // naturally -> natur... (fallback to -ly strip) } if (endsWith("ily") && !endsWith("ally")) { add(word.substr(0, len - 3) + "y"); @@ -439,18 +439,18 @@ std::vector Dictionary::getStemVariants(const std::string& word) { add(word.substr(0, len - 4) + "e"); } if (endsWith("ation")) { - add(word.substr(0, len - 5)); // information -> inform - add(word.substr(0, len - 5) + "e"); // exploration -> explore - add(word.substr(0, len - 5) + "ate"); // donation -> donate + add(word.substr(0, len - 5)); // information -> inform + add(word.substr(0, len - 5) + "e"); // exploration -> explore + add(word.substr(0, len - 5) + "ate"); // donation -> donate } if (endsWith("tion") && !endsWith("ation")) { add(word.substr(0, len - 4) + "te"); // completion -> complete - add(word.substr(0, len - 3)); // action -> act + add(word.substr(0, len - 3)); // action -> act add(word.substr(0, len - 3) + "e"); // reduction -> reduce } if (endsWith("ion") && !endsWith("tion")) { - add(word.substr(0, len - 3)); // revision -> revis (-> revise via +e) - add(word.substr(0, len - 3) + "e"); // revision -> revise + add(word.substr(0, len - 3)); // revision -> revis (-> revise via +e) + add(word.substr(0, len - 3) + "e"); // revision -> revise } if (endsWith("al") && !endsWith("ial")) { add(word.substr(0, len - 2)); @@ -461,24 +461,24 @@ std::vector Dictionary::getStemVariants(const std::string& word) { add(word.substr(0, len - 3) + "e"); } if (endsWith("ous")) { - add(word.substr(0, len - 3)); // dangerous -> danger - add(word.substr(0, len - 3) + "e"); // famous -> fame + add(word.substr(0, len - 3)); // dangerous -> danger + add(word.substr(0, len - 3) + "e"); // famous -> fame } if (endsWith("ive")) { - add(word.substr(0, len - 3)); // active -> act - add(word.substr(0, len - 3) + "e"); // creative -> create + add(word.substr(0, len - 3)); // active -> act + add(word.substr(0, len - 3) + "e"); // creative -> create } if (endsWith("ize")) { - add(word.substr(0, len - 3)); // modernize -> modern + add(word.substr(0, len - 3)); // modernize -> modern add(word.substr(0, len - 3) + "e"); } if (endsWith("ise")) { - add(word.substr(0, len - 3)); // advertise -> advert + add(word.substr(0, len - 3)); // advertise -> advert add(word.substr(0, len - 3) + "e"); } if (endsWith("en")) { - add(word.substr(0, len - 2)); // darken -> dark - add(word.substr(0, len - 2) + "e"); // widen -> wide + add(word.substr(0, len - 2)); // darken -> dark + add(word.substr(0, len - 2) + "e"); // widen -> wide } // Prefix removal