From 6639a550f1d25cd4afa8925d28fd3e8a2d35078d Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 25 May 2019 18:37:36 +0200 Subject: [PATCH] Improve WordWrapper: - When wrapping before word, left trim whitespaces to prevent newlines from starting indented - Change lastLineStart_ to size_t to cut down on nasty typecasts - Replace operator += with explicit call to append to make intent more clear and reduce memory allocations --- ext/native/util/text/wrap_text.cpp | 25 +++++++++++++++++++------ ext/native/util/text/wrap_text.h | 4 ++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/ext/native/util/text/wrap_text.cpp b/ext/native/util/text/wrap_text.cpp index ca95b23fbf..edf3354673 100644 --- a/ext/native/util/text/wrap_text.cpp +++ b/ext/native/util/text/wrap_text.cpp @@ -74,7 +74,7 @@ std::string WordWrapper::Wrapped() { return out_; } -void WordWrapper::WrapBeforeWord() { +bool WordWrapper::WrapBeforeWord() { if (x_ + wordWidth_ > maxW_ && out_.size() > 0) { if (IsShy(out_[out_.size() - 1])) { // Soft hyphen, replace it with a real hyphen since we wrapped at it. @@ -82,24 +82,37 @@ void WordWrapper::WrapBeforeWord() { out_[out_.size() - 1] = '-'; } out_ += "\n"; - lastLineStart_ = (int)out_.size(); + lastLineStart_ = out_.size(); x_ = 0.0f; forceEarlyWrap_ = false; + return true; } + return false; } void WordWrapper::AppendWord(int endIndex, bool addNewline) { - WrapBeforeWord(); + int nextWordIndex = lastIndex_; + if (WrapBeforeWord()) { + // Advance to the first non-whitespace UTF-8 character in the following word (if any) to prevent starting the new line with a whitespace + UTF8 utf8Word(str_, nextWordIndex); + while (nextWordIndex < endIndex) { + const uint32_t c = utf8Word.next(); + if (!IsSpace(c)) { + break; + } + nextWordIndex = utf8Word.byteIndex(); + } + } // This will include the newline. - out_ += std::string(str_ + lastIndex_, endIndex - lastIndex_); + out_.append(str_ + nextWordIndex, str_ + endIndex); if (addNewline) { out_ += "\n"; - lastLineStart_ = (int)out_.size(); + lastLineStart_ = out_.size(); } else { // We may have appended a newline - check. size_t pos = out_.substr(lastLineStart_).find_last_of("\n"); if (pos != out_.npos) { - lastLineStart_ += (int)pos; + lastLineStart_ += pos; } } lastIndex_ = endIndex; diff --git a/ext/native/util/text/wrap_text.h b/ext/native/util/text/wrap_text.h index ed2bc06d00..7418a8022e 100644 --- a/ext/native/util/text/wrap_text.h +++ b/ext/native/util/text/wrap_text.h @@ -13,7 +13,7 @@ public: protected: virtual float MeasureWidth(const char *str, size_t bytes) = 0; void Wrap(); - void WrapBeforeWord(); + bool WrapBeforeWord(); void AppendWord(int endIndex, bool addNewline); static bool IsCJK(uint32_t c); @@ -27,7 +27,7 @@ protected: // Index of last output / start of current word. int lastIndex_ = 0; // Index of last line start. - int lastLineStart_ = 0; + size_t lastLineStart_ = 0; // Position the current word starts at. float x_ = 0.0f; // Most recent width of word since last index.