diff --git a/lib/GfxRenderer/GfxRenderer.cpp b/lib/GfxRenderer/GfxRenderer.cpp index 171bd80..d7afd28 100644 --- a/lib/GfxRenderer/GfxRenderer.cpp +++ b/lib/GfxRenderer/GfxRenderer.cpp @@ -132,13 +132,19 @@ void GfxRenderer::displayBuffer(const EInkDisplay::RefreshMode refreshMode) cons einkDisplay.displayBuffer(refreshMode); } -// TODO: Support partial window update -// void GfxRenderer::flushArea(const int x, const int y, const int width, const int height) const { -// const int rotatedX = y; -// const int rotatedY = EInkDisplay::DISPLAY_HEIGHT - 1 - x; -// -// einkDisplay.displayBuffer(EInkDisplay::FAST_REFRESH, rotatedX, rotatedY, height, width); -// } +void GfxRenderer::displayWindow(const int x, const int y, const int width, const int height) const { + // Rotate coordinates from portrait (480x800) to landscape (800x480) + // Rotation: 90 degrees clockwise + // Portrait coordinates: (x, y) with dimensions (width, height) + // Landscape coordinates: (rotatedX, rotatedY) with dimensions (rotatedWidth, rotatedHeight) + + const int rotatedX = y; + const int rotatedY = EInkDisplay::DISPLAY_HEIGHT - 1 - x - width + 1; + const int rotatedWidth = height; + const int rotatedHeight = width; + + einkDisplay.displayWindow(rotatedX, rotatedY, rotatedWidth, rotatedHeight); +} // Note: Internal driver treats screen in command orientation, this library treats in portrait orientation int GfxRenderer::getScreenWidth() { return EInkDisplay::DISPLAY_HEIGHT; } diff --git a/lib/GfxRenderer/GfxRenderer.h b/lib/GfxRenderer/GfxRenderer.h index e5760a2..cb8b588 100644 --- a/lib/GfxRenderer/GfxRenderer.h +++ b/lib/GfxRenderer/GfxRenderer.h @@ -28,6 +28,8 @@ class GfxRenderer { static int getScreenWidth(); static int getScreenHeight(); void displayBuffer(EInkDisplay::RefreshMode refreshMode = EInkDisplay::FAST_REFRESH) const; + // EXPERIMENTAL: Windowed update - display only a rectangular region (portrait coordinates) + void displayWindow(int x, int y, int width, int height) const; void invertScreen() const; void clearScreen(uint8_t color = 0xFF) const; diff --git a/open-x4-sdk b/open-x4-sdk index fba6220..98a5aa1 160000 --- a/open-x4-sdk +++ b/open-x4-sdk @@ -1 +1 @@ -Subproject commit fba62200e2eb49590bb499d9d940bb0fe715d9d9 +Subproject commit 98a5aa1f8969ccd317c9b45bf0fa84b6c82e167f diff --git a/src/screens/EpubReaderScreen.cpp b/src/screens/EpubReaderScreen.cpp index fade5da..4e13f3d 100644 --- a/src/screens/EpubReaderScreen.cpp +++ b/src/screens/EpubReaderScreen.cpp @@ -31,7 +31,6 @@ void EpubReaderScreen::onEnter() { epub->setupCacheDir(); - // TODO: Move this to a state object if (SD.exists((epub->getCachePath() + "/progress.bin").c_str())) { File f = SD.open((epub->getCachePath() + "/progress.bin").c_str()); uint8_t data[4]; @@ -210,19 +209,20 @@ void EpubReaderScreen::renderScreen() { Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis()); { - const int textWidth = renderer.getTextWidth(READER_FONT_ID, "Indexing..."); - constexpr int margin = 20; - const int x = (GfxRenderer::getScreenWidth() - textWidth - margin * 2) / 2; - constexpr int y = 50; - const int w = textWidth + margin * 2; - const int h = renderer.getLineHeight(READER_FONT_ID) + margin * 2; renderer.grayscaleRevert(); - // TODO: This looks like garbage again, need to implement windowed updates - renderer.fillRect(x, y, w, h, 0); + const int textWidth = renderer.getTextWidth(READER_FONT_ID, "Indexing..."); + constexpr int margin = 20; + // Round all coordinates to 8 pixel boundaries + const int x = ((GfxRenderer::getScreenWidth() - textWidth - margin * 2) / 2 + 7) / 8 * 8; + constexpr int y = 56; + const int w = (textWidth + margin * 2 + 7) / 8 * 8; + const int h = (renderer.getLineHeight(READER_FONT_ID) + margin * 2 + 7) / 8 * 8; + renderer.fillRect(x, y, w, h, false); renderer.drawText(READER_FONT_ID, x + margin, y + margin, "Indexing..."); renderer.drawRect(x + 5, y + 5, w - 10, h - 10); - renderer.displayBuffer(); + // EXPERIMENTAL: Still suffers from ghosting + renderer.displayWindow(x, y, w, h); pagesUntilFullRefresh = 0; }