From 6d0361ae0892952fad46bc1838cfed37f9533b49 Mon Sep 17 00:00:00 2001 From: Fabrice Weinberg <Fabrice@weinberg.me> Date: Sun, 10 Jan 2016 20:12:37 +0100 Subject: [PATCH] Improve drawStringMax performance --- SSD1306.cpp | 50 +++++++++++++++++++++++++++++++++----------------- SSD1306.h | 8 ++------ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/SSD1306.cpp b/SSD1306.cpp index 2d13709..1c23328 100644 --- a/SSD1306.cpp +++ b/SSD1306.cpp @@ -297,29 +297,45 @@ void SSD1306::drawString(int16_t xMove, int16_t yMove, String strUser) { free(text); } -void SSD1306::drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, String text) { - uint16_t startsAt = 0; - uint16_t endsAt = 0; - uint16_t lineNumber = 0; +void SSD1306::drawStringMaxWidth(int16_t xMove, int16_t yMove, uint16_t maxLineWidth, String strUser) { + uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); - String currentLine = ""; - uint16_t length = text.length(); + + char* text = utf8ascii(strUser); + + uint16_t length = strlen(text); + uint16_t lastDrawnPos = 0; + uint16_t lineNumber = 0; + uint16_t strWidth = 0; + + uint16_t preferredBreakpoint = 0; + uint16_t widthAtBreakpoint = 0; + for (uint16_t i = 0; i < length; i++) { - char currentChar = text.charAt(i); - if (currentChar == ' ' || currentChar == '-') { - String lineCandidate = text.substring(startsAt, i); - if (getStringWidth(lineCandidate.c_str()) <= maxLineWidth) { - endsAt = i; - } else { - drawString(x, y + lineNumber * lineHeight, text.substring(startsAt, endsAt)); - lineNumber++; - startsAt = endsAt + 1; - } + strWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[i] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); + + // Always try to break on a space or dash + if (text[i] == ' ' || text[i]== '-') { + preferredBreakpoint = i; + widthAtBreakpoint = strWidth; + } + + if (strWidth >= maxLineWidth) { + preferredBreakpoint = preferredBreakpoint ? preferredBreakpoint : i; + widthAtBreakpoint = preferredBreakpoint ? widthAtBreakpoint : strWidth; + + drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], preferredBreakpoint - lastDrawnPos, widthAtBreakpoint); + + lastDrawnPos = preferredBreakpoint + 1; strWidth = 0; preferredBreakpoint = 0; } + } + // Draw last part if needed + if (lastDrawnPos < length) { + drawStringInternal(xMove, yMove + lineNumber * lineHeight , &text[lastDrawnPos], length - lastDrawnPos, getStringWidth(&text[lastDrawnPos], length - lastDrawnPos)); } - drawString(x, y + lineNumber * lineHeight, text.substring(startsAt)); + free(text); } uint16_t SSD1306::getStringWidth(const char* text, uint16_t length) { diff --git a/SSD1306.h b/SSD1306.h index 1878f88..ee9a7b8 100644 --- a/SSD1306.h +++ b/SSD1306.h @@ -132,7 +132,7 @@ class SSD1306 { byte utf8ascii(byte ascii); char* utf8ascii(String s); - void drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData); + void drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline)); void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth); public: @@ -186,11 +186,7 @@ class SSD1306 { // Draws a String with a maximum width at the given location. // If the given String is wider than the specified width // The text will be wrapped to the next line at a space or dash - void drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, String text); - - // Returns the width of the const char* with the current - // font settings - uint16_t getStringWidth(const char* text); + void drawStringMaxWidth(int16_t x, int16_t y, uint16_t maxLineWidth, String text); // Specifies relative to which anchor point // the text is rendered. Available constants: -- GitLab