diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index 8642e6b416..2be45e046d 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -174,11 +174,21 @@ Layouter::Layouter(std::string_view str, int maxw, FontSize fontsize) : string(s } } - /* Move all lines into a local cache so we can reuse them later on more easily. */ - for (;;) { - auto l = line.layout->NextLine(maxw); - if (l == nullptr) break; - this->push_back(std::move(l)); + if (line.cached_width != maxw) { + /* First run or width has changed, so we need to go through the layouter. Lines are moved into a cache to + * be reused if the width is not changed. */ + line.cached_layout.clear(); + line.cached_width = maxw; + for (;;) { + auto l = line.layout->NextLine(maxw); + if (l == nullptr) break; + line.cached_layout.push_back(std::move(l)); + } + } + + /* Retrieve layout from the cache. */ + for (const auto &l : line.cached_layout) { + this->push_back(l.get()); } /* Break out if this was the last line. */ diff --git a/src/gfx_layout.h b/src/gfx_layout.h index ecf5d5fb65..1b0dc6705f 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -135,7 +135,7 @@ public: * * It also accounts for the memory allocations and frees. */ -class Layouter : public std::vector> { +class Layouter : public std::vector { std::string_view string; ///< Pointer to the original string. /** Key into the linecache */ @@ -174,6 +174,9 @@ public: FontState state_after; ///< Font state after the line. std::unique_ptr layout = nullptr; ///< Layout of the line. + + std::vector> cached_layout{}; ///< Cached results of line layouting. + int cached_width = 0; ///< Width used for the cached layout. }; private: typedef std::map LineCache;