A fork of https://github.com/crosspoint-reader/crosspoint-reader
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Wrap up multiple font styles into EpdFontFamily

+184 -129
+37
lib/EpdFont/EpdFontFamily.cpp
··· 1 + #include "EpdFontFamily.h" 2 + 3 + const EpdFont* EpdFontFamily::getFont(const EpdFontStyle style) const { 4 + if (style == BOLD && bold) { 5 + return bold; 6 + } 7 + if (style == ITALIC && italic) { 8 + return italic; 9 + } 10 + if (style == BOLD_ITALIC) { 11 + if (boldItalic) { 12 + return boldItalic; 13 + } 14 + if (bold) { 15 + return bold; 16 + } 17 + if (italic) { 18 + return italic; 19 + } 20 + } 21 + 22 + return regular; 23 + } 24 + 25 + void EpdFontFamily::getTextDimensions(const char* string, int* w, int* h, const EpdFontStyle style) const { 26 + getFont(style)->getTextDimensions(string, w, h); 27 + } 28 + 29 + bool EpdFontFamily::hasPrintableChars(const char* string, const EpdFontStyle style) const { 30 + return getFont(style)->hasPrintableChars(string); 31 + } 32 + 33 + const EpdFontData* EpdFontFamily::getData(const EpdFontStyle style) const { return getFont(style)->data; } 34 + 35 + const EpdGlyph* EpdFontFamily::getGlyph(const uint32_t cp, const EpdFontStyle style) const { 36 + return getFont(style)->getGlyph(cp); 37 + };
+24
lib/EpdFont/EpdFontFamily.h
··· 1 + #pragma once 2 + #include "EpdFont.h" 3 + 4 + enum EpdFontStyle { REGULAR, BOLD, ITALIC, BOLD_ITALIC }; 5 + 6 + class EpdFontFamily { 7 + const EpdFont* regular; 8 + const EpdFont* bold; 9 + const EpdFont* italic; 10 + const EpdFont* boldItalic; 11 + 12 + const EpdFont* getFont(EpdFontStyle style) const; 13 + 14 + public: 15 + explicit EpdFontFamily(const EpdFont* regular, const EpdFont* bold = nullptr, const EpdFont* italic = nullptr, 16 + const EpdFont* boldItalic = nullptr) 17 + : regular(regular), bold(bold), italic(italic), boldItalic(boldItalic) {} 18 + ~EpdFontFamily() = default; 19 + void getTextDimensions(const char* string, int* w, int* h, EpdFontStyle style = REGULAR) const; 20 + bool hasPrintableChars(const char* string, EpdFontStyle style = REGULAR) const; 21 + 22 + const EpdFontData* getData(EpdFontStyle style = REGULAR) const; 23 + const EpdGlyph* getGlyph(uint32_t cp, EpdFontStyle style = REGULAR) const; 24 + };
+19 -22
lib/EpdFontRenderer/EpdFontRenderer.hpp
··· 1 1 #pragma once 2 - #include <EpdFont.h> 2 + #include <EpdFontFamily.h> 3 3 #include <HardwareSerial.h> 4 4 #include <Utf8.h> 5 5 #include <miniz.h> ··· 12 12 template <typename Renderable> 13 13 class EpdFontRenderer { 14 14 Renderable* renderer; 15 - void renderChar(uint32_t cp, int* x, const int* y, uint16_t color); 15 + void renderChar(uint32_t cp, int* x, const int* y, uint16_t color, EpdFontStyle style = REGULAR); 16 16 17 17 public: 18 - const EpdFont* font; 19 - explicit EpdFontRenderer(const EpdFont* font, Renderable* renderer); 18 + const EpdFontFamily* fontFamily; 19 + explicit EpdFontRenderer(const EpdFontFamily* fontFamily, Renderable* renderer) 20 + : fontFamily(fontFamily), renderer(renderer) {} 20 21 ~EpdFontRenderer() = default; 21 - void renderString(const char* string, int* x, int* y, uint16_t color); 22 + void renderString(const char* string, int* x, int* y, uint16_t color, EpdFontStyle style = REGULAR); 22 23 }; 23 24 24 25 inline int uncompress(uint8_t* dest, size_t uncompressedSize, const uint8_t* source, size_t sourceSize) { ··· 38 39 } 39 40 40 41 template <typename Renderable> 41 - EpdFontRenderer<Renderable>::EpdFontRenderer(const EpdFont* font, Renderable* renderer) { 42 - this->font = font; 43 - this->renderer = renderer; 44 - } 45 - 46 - template <typename Renderable> 47 - void EpdFontRenderer<Renderable>::renderString(const char* string, int* x, int* y, const uint16_t color) { 42 + void EpdFontRenderer<Renderable>::renderString(const char* string, int* x, int* y, const uint16_t color, 43 + const EpdFontStyle style) { 48 44 // cannot draw a NULL / empty string 49 45 if (string == nullptr || *string == '\0') { 50 46 return; 51 47 } 52 48 53 49 // no printable characters 54 - if (!font->hasPrintableChars(string)) { 50 + if (!fontFamily->hasPrintableChars(string, style)) { 55 51 return; 56 52 } 57 53 58 54 uint32_t cp; 59 55 while ((cp = utf8NextCodepoint(reinterpret_cast<const uint8_t**>(&string)))) { 60 - renderChar(cp, x, y, color); 56 + renderChar(cp, x, y, color, style); 61 57 } 62 58 63 - *y += font->data->advanceY; 59 + *y += fontFamily->getData(style)->advanceY; 64 60 } 65 61 66 62 template <typename Renderable> 67 - void EpdFontRenderer<Renderable>::renderChar(const uint32_t cp, int* x, const int* y, uint16_t color) { 68 - const EpdGlyph* glyph = font->getGlyph(cp); 63 + void EpdFontRenderer<Renderable>::renderChar(const uint32_t cp, int* x, const int* y, uint16_t color, 64 + const EpdFontStyle style) { 65 + const EpdGlyph* glyph = fontFamily->getGlyph(cp, style); 69 66 if (!glyph) { 70 67 // TODO: Replace with fallback glyph property? 71 - glyph = font->getGlyph('?'); 68 + glyph = fontFamily->getGlyph('?', style); 72 69 } 73 70 74 71 // no glyph? ··· 86 83 const unsigned long bitmapSize = byteWidth * height; 87 84 const uint8_t* bitmap = nullptr; 88 85 89 - if (font->data->compressed) { 86 + if (fontFamily->getData(style)->compressed) { 90 87 auto* tmpBitmap = static_cast<uint8_t*>(malloc(bitmapSize)); 91 88 if (tmpBitmap == nullptr && bitmapSize) { 92 89 Serial.println("Failed to allocate memory for decompression buffer"); 93 90 return; 94 91 } 95 92 96 - uncompress(tmpBitmap, bitmapSize, &font->data->bitmap[offset], glyph->compressedSize); 93 + uncompress(tmpBitmap, bitmapSize, &fontFamily->getData(style)->bitmap[offset], glyph->compressedSize); 97 94 bitmap = tmpBitmap; 98 95 } else { 99 - bitmap = &font->data->bitmap[offset]; 96 + bitmap = &fontFamily->getData(style)->bitmap[offset]; 100 97 } 101 98 102 99 if (bitmap != nullptr) { ··· 123 120 } 124 121 } 125 122 126 - if (font->data->compressed) { 123 + if (fontFamily->getData(style)->compressed) { 127 124 free(const_cast<uint8_t*>(bitmap)); 128 125 } 129 126 }
+41 -55
lib/EpdRenderer/EpdRenderer.cpp
··· 7 7 #include "builtinFonts/bookerly_italic.h" 8 8 9 9 EpdRenderer::EpdRenderer(XteinkDisplay* display) { 10 + const auto bookerlyFontFamily = new EpdFontFamily(new EpdFont(&bookerly), new EpdFont(&bookerly_bold), 11 + new EpdFont(&bookerly_italic), new EpdFont(&bookerly_bold_italic)); 12 + const auto babyblueFontFamily = new EpdFontFamily(new EpdFont(&babyblue)); 13 + 10 14 this->display = display; 11 - this->regularFont = new EpdFontRenderer<XteinkDisplay>(new EpdFont(&bookerly), display); 12 - this->boldFont = new EpdFontRenderer<XteinkDisplay>(new EpdFont(&bookerly_bold), display); 13 - this->italicFont = new EpdFontRenderer<XteinkDisplay>(new EpdFont(&bookerly_italic), display); 14 - this->bold_italicFont = new EpdFontRenderer<XteinkDisplay>(new EpdFont(&bookerly_bold_italic), display); 15 - this->smallFont = new EpdFontRenderer<XteinkDisplay>(new EpdFont(&babyblue), display); 15 + this->regularFontRenderer = new EpdFontRenderer<XteinkDisplay>(bookerlyFontFamily, display); 16 + this->smallFontRenderer = new EpdFontRenderer<XteinkDisplay>(babyblueFontFamily, display); 16 17 17 18 this->marginTop = 11; 18 19 this->marginBottom = 30; ··· 21 22 this->lineCompression = 0.95f; 22 23 } 23 24 24 - EpdFontRenderer<XteinkDisplay>* EpdRenderer::getFontRenderer(const bool bold, const bool italic) const { 25 - if (bold && italic) { 26 - return bold_italicFont; 27 - } 28 - if (bold) { 29 - return boldFont; 30 - } 31 - if (italic) { 32 - return italicFont; 33 - } 34 - return regularFont; 35 - } 36 - 37 - int EpdRenderer::getTextWidth(const char* text, const bool bold, const bool italic) const { 25 + int EpdRenderer::getTextWidth(const char* text, const EpdFontStyle style) const { 38 26 int w = 0, h = 0; 39 27 40 - getFontRenderer(bold, italic)->font->getTextDimensions(text, &w, &h); 28 + regularFontRenderer->fontFamily->getTextDimensions(text, &w, &h, style); 41 29 42 30 return w; 43 31 } 44 32 45 - int EpdRenderer::getSmallTextWidth(const char* text) const { 33 + int EpdRenderer::getSmallTextWidth(const char* text, const EpdFontStyle style) const { 46 34 int w = 0, h = 0; 47 35 48 - smallFont->font->getTextDimensions(text, &w, &h); 36 + smallFontRenderer->fontFamily->getTextDimensions(text, &w, &h, style); 49 37 50 38 return w; 51 39 } 52 40 53 - void EpdRenderer::drawText(const int x, const int y, const char* text, const bool bold, const bool italic, 54 - const uint16_t color) const { 41 + void EpdRenderer::drawText(const int x, const int y, const char* text, const uint16_t color, 42 + const EpdFontStyle style) const { 55 43 int ypos = y + getLineHeight() + marginTop; 56 44 int xpos = x + marginLeft; 57 - getFontRenderer(bold, italic)->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 45 + regularFontRenderer->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE, style); 58 46 } 59 47 60 - void EpdRenderer::drawSmallText(const int x, const int y, const char* text, const uint16_t color) const { 61 - int ypos = y + smallFont->font->data->advanceY + marginTop; 48 + void EpdRenderer::drawSmallText(const int x, const int y, const char* text, const uint16_t color, 49 + const EpdFontStyle style) const { 50 + int ypos = y + smallFontRenderer->fontFamily->getData(style)->advanceY + marginTop; 62 51 int xpos = x + marginLeft; 63 - smallFont->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 52 + smallFontRenderer->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 64 53 } 65 54 66 55 void EpdRenderer::drawTextBox(const int x, const int y, const std::string& text, const int width, const int height, 67 - const bool bold, const bool italic) const { 56 + const EpdFontStyle style) const { 68 57 const size_t length = text.length(); 69 58 // fit the text into the box 70 59 int start = 0; ··· 72 61 int ypos = 0; 73 62 while (true) { 74 63 if (end >= length) { 75 - drawText(x, y + ypos, text.substr(start, length - start).c_str(), bold, italic); 64 + drawText(x, y + ypos, text.substr(start, length - start).c_str(), 1, style); 76 65 break; 77 66 } 78 67 ··· 81 70 } 82 71 83 72 if (text[end - 1] == '\n') { 84 - drawText(x, y + ypos, text.substr(start, end - start).c_str(), bold, italic); 73 + drawText(x, y + ypos, text.substr(start, end - start).c_str(), 1, style); 85 74 ypos += getLineHeight(); 86 75 start = end; 87 76 end = start + 1; 88 77 continue; 89 78 } 90 79 91 - if (getTextWidth(text.substr(start, end - start).c_str(), bold, italic) > width) { 92 - drawText(x, y + ypos, text.substr(start, end - start - 1).c_str(), bold, italic); 80 + if (getTextWidth(text.substr(start, end - start).c_str(), style) > width) { 81 + drawText(x, y + ypos, text.substr(start, end - start - 1).c_str(), 1, style); 93 82 ypos += getLineHeight(); 94 83 start = end - 1; 95 84 continue; ··· 108 97 display->drawRect(x + marginLeft, y + marginTop, width, height, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 109 98 } 110 99 111 - void EpdRenderer::fillRect(const int x, const int y, const int width, const int height, 112 - const uint16_t color = 0) const { 100 + void EpdRenderer::fillRect(const int x, const int y, const int width, const int height, const uint16_t color) const { 113 101 display->fillRect(x + marginLeft, y + marginTop, width, height, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 114 102 } 115 103 104 + void EpdRenderer::drawCircle(const int x, const int y, const int radius, const uint16_t color) const { 105 + display->drawCircle(x + marginLeft, y + marginTop, radius, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 106 + } 107 + 108 + void EpdRenderer::fillCircle(const int x, const int y, const int radius, const uint16_t color) const { 109 + display->fillCircle(x + marginLeft, y + marginTop, radius, color > 0 ? GxEPD_BLACK : GxEPD_WHITE); 110 + } 111 + 112 + void EpdRenderer::drawImage(const uint8_t bitmap[], const int x, const int y, const int width, const int height, 113 + const bool invert) const { 114 + display->drawImage(bitmap, x + marginLeft, y + marginTop, width, height, invert); 115 + } 116 + 116 117 void EpdRenderer::clearScreen(const bool black) const { 117 118 Serial.println("Clearing screen"); 118 119 display->fillScreen(black ? GxEPD_BLACK : GxEPD_WHITE); ··· 121 122 void EpdRenderer::flushDisplay(const bool partialUpdate) const { display->display(partialUpdate); } 122 123 123 124 void EpdRenderer::flushArea(const int x, const int y, const int width, const int height) const { 124 - display->displayWindow(x, y, width, height); 125 + display->displayWindow(x + marginLeft, y + marginTop, width, height); 125 126 } 126 127 127 128 int EpdRenderer::getPageWidth() const { return display->width() - marginLeft - marginRight; } 128 129 129 130 int EpdRenderer::getPageHeight() const { return display->height() - marginTop - marginBottom; } 130 131 131 - int EpdRenderer::getSpaceWidth() const { return regularFont->font->getGlyph(' ')->advanceX; } 132 - 133 - int EpdRenderer::getLineHeight() const { return regularFont->font->data->advanceY * lineCompression; } 134 - 135 - // deep sleep helper - persist any state to disk that may be needed on wake 136 - bool EpdRenderer::dehydrate() { 137 - // TODO: Implement 138 - return false; 139 - }; 140 - 141 - // deep sleep helper - retrieve any state from disk after wake 142 - bool EpdRenderer::hydrate() { 143 - // TODO: Implement 144 - return false; 145 - }; 132 + int EpdRenderer::getSpaceWidth() const { return regularFontRenderer->fontFamily->getGlyph(' ', REGULAR)->advanceX; } 146 133 147 - // really really clear the screen 148 - void EpdRenderer::reset() { 149 - // TODO: Implement 150 - }; 134 + int EpdRenderer::getLineHeight() const { 135 + return regularFontRenderer->fontFamily->getData(REGULAR)->advanceY * lineCompression; 136 + }
+13 -23
lib/EpdRenderer/EpdRenderer.h
··· 8 8 9 9 class EpdRenderer { 10 10 XteinkDisplay* display; 11 - EpdFontRenderer<XteinkDisplay>* regularFont; 12 - EpdFontRenderer<XteinkDisplay>* boldFont; 13 - EpdFontRenderer<XteinkDisplay>* italicFont; 14 - EpdFontRenderer<XteinkDisplay>* bold_italicFont; 15 - EpdFontRenderer<XteinkDisplay>* smallFont; 11 + EpdFontRenderer<XteinkDisplay>* regularFontRenderer; 12 + EpdFontRenderer<XteinkDisplay>* smallFontRenderer; 16 13 int marginTop; 17 14 int marginBottom; 18 15 int marginLeft; 19 16 int marginRight; 20 17 float lineCompression; 21 - EpdFontRenderer<XteinkDisplay>* getFontRenderer(bool bold, bool italic) const; 22 18 23 19 public: 24 20 explicit EpdRenderer(XteinkDisplay* display); 25 21 ~EpdRenderer() = default; 26 - int getTextWidth(const char* text, bool bold = false, bool italic = false) const; 27 - int getSmallTextWidth(const char* text) const; 28 - void drawText(int x, int y, const char* text, bool bold = false, bool italic = false, uint16_t color = 1) const; 29 - void drawSmallText(int x, int y, const char* text, uint16_t color = 1) const; 30 - void drawTextBox(int x, int y, const std::string& text, int width, int height, bool bold = false, 31 - bool italic = false) const; 32 - void drawLine(int x1, int y1, int x2, int y2, uint16_t color) const; 33 - void drawRect(int x, int y, int width, int height, uint16_t color) const; 34 - void fillRect(int x, int y, int width, int height, uint16_t color) const; 22 + int getTextWidth(const char* text, EpdFontStyle style = REGULAR) const; 23 + int getSmallTextWidth(const char* text, EpdFontStyle style = REGULAR) const; 24 + void drawText(int x, int y, const char* text, uint16_t color = 1, EpdFontStyle style = REGULAR) const; 25 + void drawSmallText(int x, int y, const char* text, uint16_t color = 1, EpdFontStyle style = REGULAR) const; 26 + void drawTextBox(int x, int y, const std::string& text, int width, int height, EpdFontStyle style = REGULAR) const; 27 + void drawLine(int x1, int y1, int x2, int y2, uint16_t color = 1) const; 28 + void drawRect(int x, int y, int width, int height, uint16_t color = 1) const; 29 + void fillRect(int x, int y, int width, int height, uint16_t color = 1) const; 30 + void drawCircle(int x, int y, int radius, uint16_t color = 1) const; 31 + void fillCircle(int x, int y, int radius, uint16_t color = 1) const; 32 + void drawImage(const uint8_t bitmap[], int x, int y, int width, int height, bool invert = false) const; 35 33 void clearScreen(bool black = false) const; 36 34 void flushDisplay(bool partialUpdate = true) const; 37 35 void flushArea(int x, int y, int width, int height) const; ··· 45 43 void setMarginBottom(const int newMarginBottom) { this->marginBottom = newMarginBottom; } 46 44 void setMarginLeft(const int newMarginLeft) { this->marginLeft = newMarginLeft; } 47 45 void setMarginRight(const int newMarginRight) { this->marginRight = newMarginRight; } 48 - // deep sleep helper - persist any state to disk that may be needed on wake 49 - bool dehydrate(); 50 - // deep sleep helper - retrieve any state from disk after wake 51 - bool hydrate(); 52 - // really really clear the screen 53 - void reset(); 54 - 55 - uint8_t temperature = 20; 56 46 };
+4 -4
lib/Epub/Epub/Section.cpp
··· 107 107 delete p; 108 108 } else if (pageCount == 0) { 109 109 Serial.println("No pages to render"); 110 - const int width = renderer->getTextWidth("Empty chapter", true); 111 - renderer->drawText((renderer->getPageWidth() - width) / 2, 300, "Empty chapter", true); 110 + const int width = renderer->getTextWidth("Empty chapter", BOLD); 111 + renderer->drawText((renderer->getPageWidth() - width) / 2, 300, "Empty chapter", 1, BOLD); 112 112 } else { 113 113 Serial.printf("Page out of bounds: %d (max %d)\n", currentPage, pageCount); 114 - const int width = renderer->getTextWidth("Out of bounds", true); 115 - renderer->drawText((renderer->getPageWidth() - width) / 2, 300, "Out of bounds", true); 114 + const int width = renderer->getTextWidth("Out of bounds", BOLD); 115 + renderer->drawText((renderer->getPageWidth() - width) / 2, 300, "Out of bounds", 1, BOLD); 116 116 } 117 117 }
+23 -2
lib/Epub/Epub/blocks/TextBlock.cpp
··· 56 56 uint16_t wordWidths[totalWordCount]; 57 57 for (int i = 0; i < words.size(); i++) { 58 58 // measure the word 59 - const int width = renderer->getTextWidth(words[i].c_str(), wordStyles[i] & BOLD_SPAN, wordStyles[i] & ITALIC_SPAN); 59 + EpdFontStyle fontStyle = REGULAR; 60 + if (wordStyles[i] & BOLD_SPAN) { 61 + if (wordStyles[i] & ITALIC_SPAN) { 62 + fontStyle = BOLD_ITALIC; 63 + } else { 64 + fontStyle = BOLD; 65 + } 66 + } else if (wordStyles[i] & ITALIC_SPAN) { 67 + fontStyle = ITALIC; 68 + } 69 + const int width = renderer->getTextWidth(words[i].c_str(), fontStyle); 60 70 wordWidths[i] = width; 61 71 } 62 72 ··· 182 192 // get the style 183 193 const uint8_t wordStyle = wordStyles[i]; 184 194 // render the word 185 - renderer->drawText(x + wordXpos[i], y, words[i].c_str(), wordStyle & BOLD_SPAN, wordStyle & ITALIC_SPAN); 195 + EpdFontStyle fontStyle = REGULAR; 196 + if (wordStyles[i] & BOLD_SPAN) { 197 + if (wordStyles[i] & ITALIC_SPAN) { 198 + fontStyle = BOLD_ITALIC; 199 + } else { 200 + fontStyle = BOLD; 201 + } 202 + 203 + } else if (wordStyles[i] & ITALIC_SPAN) { 204 + fontStyle = ITALIC; 205 + } 206 + renderer->drawText(x + wordXpos[i], y, words[i].c_str(), 1, fontStyle); 186 207 } 187 208 } 188 209
+2 -2
src/main.cpp
··· 89 89 90 90 // Enter deep sleep mode 91 91 void enterDeepSleep() { 92 - enterNewScreen(new FullScreenMessageScreen(renderer, "Sleeping", true, false, true)); 92 + enterNewScreen(new FullScreenMessageScreen(renderer, "Sleeping", BOLD, true)); 93 93 94 94 Serial.println("Power button released after a long press. Entering deep sleep."); 95 95 delay(1000); // Allow Serial buffer to empty and display to update ··· 137 137 display.setTextColor(GxEPD_BLACK); 138 138 Serial.println("Display initialized"); 139 139 140 - enterNewScreen(new FullScreenMessageScreen(renderer, "Booting...", true)); 140 + enterNewScreen(new FullScreenMessageScreen(renderer, "Booting...", BOLD)); 141 141 142 142 // SD Card Initialization 143 143 SD.begin(SD_SPI_CS, SPI, SPI_FQ);
+10 -10
src/screens/EpubReaderScreen.cpp
··· 134 134 const int h = renderer->getLineHeight() + margin * 2; 135 135 renderer->fillRect(x, y, w, h, 0); 136 136 renderer->drawText(x + margin, y + margin, "Indexing..."); 137 - renderer->drawRect(x + 5, y + 5, w - 10, h - 10, 1); 138 - renderer->flushArea(x - 20, y - 20, w + 40, h + 40); 137 + renderer->drawRect(x + 5, y + 5, w - 10, h - 10); 138 + renderer->flushArea(x, y, w, h); 139 139 } 140 140 141 141 section->setupCacheDir(); ··· 199 199 constexpr int y = 772; 200 200 201 201 // Top line 202 - renderer->drawLine(x, y, x + batteryWidth - 4, y, 1); 202 + renderer->drawLine(x, y, x + batteryWidth - 4, y); 203 203 // Bottom line 204 - renderer->drawLine(x, y + batteryHeight - 1, x + batteryWidth - 4, y + batteryHeight - 1, 1); 204 + renderer->drawLine(x, y + batteryHeight - 1, x + batteryWidth - 4, y + batteryHeight - 1); 205 205 // Left line 206 - renderer->drawLine(x, y, x, y + batteryHeight - 1, 1); 206 + renderer->drawLine(x, y, x, y + batteryHeight - 1); 207 207 // Battery end 208 - renderer->drawLine(x + batteryWidth - 4, y, x + batteryWidth - 4, y + batteryHeight - 1, 1); 209 - renderer->drawLine(x + batteryWidth - 3, y + 2, x + batteryWidth - 3, y + batteryHeight - 3, 1); 210 - renderer->drawLine(x + batteryWidth - 2, y + 2, x + batteryWidth - 2, y + batteryHeight - 3, 1); 211 - renderer->drawLine(x + batteryWidth - 1, y + 2, x + batteryWidth - 1, y + batteryHeight - 3, 1); 208 + renderer->drawLine(x + batteryWidth - 4, y, x + batteryWidth - 4, y + batteryHeight - 1); 209 + renderer->drawLine(x + batteryWidth - 3, y + 2, x + batteryWidth - 3, y + batteryHeight - 3); 210 + renderer->drawLine(x + batteryWidth - 2, y + 2, x + batteryWidth - 2, y + batteryHeight - 3); 211 + renderer->drawLine(x + batteryWidth - 1, y + 2, x + batteryWidth - 1, y + batteryHeight - 3); 212 212 213 213 // The +1 is to round up, so that we always fill at least one pixel 214 214 int filledWidth = percentage * (batteryWidth - 5) / 100 + 1; 215 215 if (filledWidth > batteryWidth - 5) { 216 216 filledWidth = batteryWidth - 5; // Ensure we don't overflow 217 217 } 218 - renderer->fillRect(x + 1, y + 1, filledWidth, batteryHeight - 2, 1); 218 + renderer->fillRect(x + 1, y + 1, filledWidth, batteryHeight - 2); 219 219 220 220 // Page width minus existing content with 30px padding on each side 221 221 const int leftMargin = 20 + percentageTextWidth + 30;
+3 -3
src/screens/FileSelectionScreen.cpp
··· 91 91 renderer->clearScreen(); 92 92 93 93 const auto pageWidth = renderer->getPageWidth(); 94 - const auto titleWidth = renderer->getTextWidth("CrossPoint Reader", true); 95 - renderer->drawText((pageWidth - titleWidth) / 2, 0, "CrossPoint Reader", true); 94 + const auto titleWidth = renderer->getTextWidth("CrossPoint Reader", BOLD); 95 + renderer->drawText((pageWidth - titleWidth) / 2, 0, "CrossPoint Reader", 1, BOLD); 96 96 97 97 if (files.empty()) { 98 98 renderer->drawSmallText(50, 50, "No EPUBs found"); 99 99 } else { 100 100 // Draw selection 101 - renderer->fillRect(0, 50 + selectorIndex * 20 + 2, pageWidth - 1, 20, 1); 101 + renderer->fillRect(0, 50 + selectorIndex * 20 + 2, pageWidth - 1, 20); 102 102 103 103 for (size_t i = 0; i < files.size(); i++) { 104 104 const auto file = files[i];
+1 -1
src/screens/FileSelectionScreen.h
··· 21 21 void render() const; 22 22 void loadFiles(); 23 23 24 - public: 24 + public: 25 25 explicit FileSelectionScreen(EpdRenderer* renderer, const std::function<void(const std::string&)>& onSelect) 26 26 : Screen(renderer), onSelect(onSelect) {} 27 27 void onEnter() override;
+2 -2
src/screens/FullScreenMessageScreen.cpp
··· 3 3 #include <EpdRenderer.h> 4 4 5 5 void FullScreenMessageScreen::onEnter() { 6 - const auto width = renderer->getTextWidth(text.c_str(), bold, italic); 6 + const auto width = renderer->getTextWidth(text.c_str(), style); 7 7 const auto height = renderer->getLineHeight(); 8 8 const auto left = (renderer->getPageWidth() - width) / 2; 9 9 const auto top = (renderer->getPageHeight() - height) / 2; 10 10 11 11 renderer->clearScreen(invert); 12 - renderer->drawText(left, top, text.c_str(), bold, italic, invert ? 0 : 1); 12 + renderer->drawText(left, top, text.c_str(), invert ? 0 : 1, style); 13 13 // If inverted, do a full screen update to ensure no ghosting 14 14 renderer->flushDisplay(!invert); 15 15 }
+5 -5
src/screens/FullScreenMessageScreen.h
··· 2 2 #include <string> 3 3 #include <utility> 4 4 5 + #include "EpdFontFamily.h" 5 6 #include "Screen.h" 6 7 7 8 class FullScreenMessageScreen final : public Screen { 8 9 std::string text; 9 - bool bold; 10 - bool italic; 10 + EpdFontStyle style; 11 11 bool invert; 12 12 13 13 public: 14 - explicit FullScreenMessageScreen(EpdRenderer* renderer, std::string text, const bool bold = false, 15 - const bool italic = false, const bool invert = false) 16 - : Screen(renderer), text(std::move(text)), bold(bold), italic(italic), invert(invert) {} 14 + explicit FullScreenMessageScreen(EpdRenderer* renderer, std::string text, const EpdFontStyle style = REGULAR, 15 + const bool invert = false) 16 + : Screen(renderer), text(std::move(text)), style(style), invert(invert) {} 17 17 void onEnter() override; 18 18 };