diff options
author | Michael Lutz <michi@icosahedron.de> | 2019-04-02 21:30:53 +0200 |
---|---|---|
committer | Michael Lutz <michi@icosahedron.de> | 2019-04-09 22:45:15 +0200 |
commit | 329bb526134aca214a914f25006c805de78ec851 (patch) | |
tree | 00763488d458fee57ce8ba94e32ae53899367d21 | |
parent | 9325d63d8e55758a953f535c5f90534ab9bc01e3 (diff) | |
download | openttd-329bb526134aca214a914f25006c805de78ec851.tar.xz |
Codechange: Store text layout runs directly as values in a std::vector instead of heap allocated.
This reduces memory allocations and heap fragmentation.
-rw-r--r-- | src/gfx.cpp | 16 | ||||
-rw-r--r-- | src/gfx_layout.cpp | 59 | ||||
-rw-r--r-- | src/gfx_layout.h | 2 | ||||
-rw-r--r-- | src/os/macosx/string_osx.cpp | 7 | ||||
-rw-r--r-- | src/os/windows/string_uniscribe.cpp | 23 |
5 files changed, 65 insertions, 42 deletions
diff --git a/src/gfx.cpp b/src/gfx.cpp index f1b91c16e..7c90285ba 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -376,7 +376,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, * another size would be chosen it won't have truncated too little for * the truncation dots. */ - FontCache *fc = ((const Font*)line->GetVisualRun(0)->GetFont())->fc; + FontCache *fc = ((const Font*)line->GetVisualRun(0).GetFont())->fc; GlyphID dot_glyph = fc->MapCharToGlyph('.'); dot_width = fc->GetGlyphWidth(dot_glyph); dot_sprite = fc->GetGlyph(dot_glyph); @@ -422,8 +422,8 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, TextColour colour = TC_BLACK; bool draw_shadow = false; for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index); - const Font *f = (const Font*)run->GetFont(); + const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); + const Font *f = (const Font*)run.GetFont(); FontCache *fc = f->fc; colour = f->colour; @@ -435,15 +435,15 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, draw_shadow = fc->GetDrawGlyphShadow() && (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK; - for (int i = 0; i < run->GetGlyphCount(); i++) { - GlyphID glyph = run->GetGlyphs()[i]; + for (int i = 0; i < run.GetGlyphCount(); i++) { + GlyphID glyph = run.GetGlyphs()[i]; /* Not a valid glyph (empty) */ if (glyph == 0xFFFF) continue; - int begin_x = (int)run->GetPositions()[i * 2] + left - offset_x; - int end_x = (int)run->GetPositions()[i * 2 + 2] + left - offset_x - 1; - int top = (int)run->GetPositions()[i * 2 + 1] + y; + int begin_x = (int)run.GetPositions()[i * 2] + left - offset_x; + int end_x = (int)run.GetPositions()[i * 2 + 2] + left - offset_x - 1; + int top = (int)run.GetPositions()[i * 2 + 1] + y; /* Truncated away. */ if (truncation && (begin_x < min_x || end_x > max_x)) continue; diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index b46ac20d5..f0dee2f53 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -143,14 +143,14 @@ public: }; /** A single line worth of VisualRuns. */ - class ICULine : public AutoDeleteSmallVector<ICUVisualRun *>, public ParagraphLayouter::Line { + class ICULine : public std::vector<ICUVisualRun>, public ParagraphLayouter::Line { icu::ParagraphLayout::Line *l; ///< The actual ICU line. public: ICULine(icu::ParagraphLayout::Line *l) : l(l) { for (int i = 0; i < l->countRuns(); i++) { - this->push_back(new ICUVisualRun(l->getVisualRun(i))); + this->emplace_back(l->getVisualRun(i)); } } ~ICULine() override { delete l; } @@ -158,7 +158,7 @@ public: int GetLeading() const override { return l->getLeading(); } int GetWidth() const override { return l->getWidth(); } int CountRuns() const override { return l->countRuns(); } - const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override { return this->at(run); } + const ParagraphLayouter::VisualRun &GetVisualRun(int run) const override { return this->at(run); } int GetInternalCharLength(WChar c) const override { @@ -259,6 +259,7 @@ public: public: FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x); + FallbackVisualRun(FallbackVisualRun &&other) noexcept; ~FallbackVisualRun() override; const Font *GetFont() const override; int GetGlyphCount() const override; @@ -269,12 +270,12 @@ public: }; /** A single line worth of VisualRuns. */ - class FallbackLine : public AutoDeleteSmallVector<FallbackVisualRun *>, public ParagraphLayouter::Line { + class FallbackLine : public std::vector<FallbackVisualRun>, public ParagraphLayouter::Line { public: int GetLeading() const override; int GetWidth() const override; int CountRuns() const override; - const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override; + const ParagraphLayouter::VisualRun &GetVisualRun(int run) const override; int GetInternalCharLength(WChar c) const override { return 1; } }; @@ -350,6 +351,18 @@ FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const } } +/** Move constructor for visual runs.*/ +FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(FallbackVisualRun &&other) noexcept : font(other.font), glyph_count(other.glyph_count) +{ + this->positions = other.positions; + this->glyph_to_char = other.glyph_to_char; + this->glyphs = other.glyphs; + + other.positions = NULL; + other.glyph_to_char = NULL; + other.glyphs = NULL; +} + /** Free all data. */ FallbackParagraphLayout::FallbackVisualRun::~FallbackVisualRun() { @@ -419,8 +432,8 @@ int FallbackParagraphLayout::FallbackVisualRun::GetLeading() const int FallbackParagraphLayout::FallbackLine::GetLeading() const { int leading = 0; - for (const FallbackVisualRun * const &run : *this) { - leading = max(leading, run->GetLeading()); + for (const auto &run : *this) { + leading = max(leading, run.GetLeading()); } return leading; @@ -439,8 +452,8 @@ int FallbackParagraphLayout::FallbackLine::GetWidth() const * Since there is no left-to-right support, taking this value of * the last run gives us the end of the line and thus the width. */ - const ParagraphLayouter::VisualRun *run = this->GetVisualRun(this->CountRuns() - 1); - return (int)run->GetPositions()[run->GetGlyphCount() * 2]; + const auto &run = this->GetVisualRun(this->CountRuns() - 1); + return (int)run.GetPositions()[run.GetGlyphCount() * 2]; } /** @@ -456,7 +469,7 @@ int FallbackParagraphLayout::FallbackLine::CountRuns() const * Get a specific visual run. * @return The visual run. */ -const ParagraphLayouter::VisualRun *FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const +const ParagraphLayouter::VisualRun &FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const { return this->at(run); } @@ -498,7 +511,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) if (*this->buffer == '\0') { /* Only a newline. */ this->buffer = NULL; - l->push_back(new FallbackVisualRun(this->runs.front().second, this->buffer, 0, 0)); + l->emplace_back(this->runs.front().second, this->buffer, 0, 0); return l; } @@ -527,7 +540,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) if (this->buffer == next_run) { int w = l->GetWidth(); - l->push_back(new FallbackVisualRun(iter->second, begin, this->buffer - begin, w)); + l->emplace_back(iter->second, begin, this->buffer - begin, w); iter++; assert(iter != this->runs.End()); @@ -574,7 +587,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) if (l->size() == 0 || last_char - begin != 0) { int w = l->GetWidth(); - l->push_back(new FallbackVisualRun(iter->second, begin, last_char - begin, w)); + l->emplace_back(iter->second, begin, last_char - begin, w); } return l; } @@ -772,12 +785,12 @@ Point Layouter::GetCharPosition(const char *ch) const /* Scan all runs until we've found our code point index. */ for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index); + const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); - for (int i = 0; i < run->GetGlyphCount(); i++) { + for (int i = 0; i < run.GetGlyphCount(); i++) { /* Matching glyph? Return position. */ - if ((size_t)run->GetGlyphToCharMap()[i] == index) { - Point p = { (int)run->GetPositions()[i * 2], (int)run->GetPositions()[i * 2 + 1] }; + if ((size_t)run.GetGlyphToCharMap()[i] == index) { + Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] }; return p; } } @@ -798,18 +811,18 @@ const char *Layouter::GetCharAtPosition(int x) const const ParagraphLayouter::Line *line = this->front(); for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index); + const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); - for (int i = 0; i < run->GetGlyphCount(); i++) { + for (int i = 0; i < run.GetGlyphCount(); i++) { /* Not a valid glyph (empty). */ - if (run->GetGlyphs()[i] == 0xFFFF) continue; + if (run.GetGlyphs()[i] == 0xFFFF) continue; - int begin_x = (int)run->GetPositions()[i * 2]; - int end_x = (int)run->GetPositions()[i * 2 + 2]; + int begin_x = (int)run.GetPositions()[i * 2]; + int end_x = (int)run.GetPositions()[i * 2 + 2]; if (IsInsideMM(x, begin_x, end_x)) { /* Found our glyph, now convert to UTF-8 string index. */ - size_t index = run->GetGlyphToCharMap()[i]; + size_t index = run.GetGlyphToCharMap()[i]; size_t cur_idx = 0; for (const char *str = this->string; *str != '\0'; ) { diff --git a/src/gfx_layout.h b/src/gfx_layout.h index 93cc6fb2d..8a642c795 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -137,7 +137,7 @@ public: virtual int GetLeading() const = 0; virtual int GetWidth() const = 0; virtual int CountRuns() const = 0; - virtual const VisualRun *GetVisualRun(int run) const = 0; + virtual const VisualRun &GetVisualRun(int run) const = 0; virtual int GetInternalCharLength(WChar c) const = 0; }; diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index f26421e36..55eac42f9 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -53,6 +53,7 @@ public: public: CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff); + CoreTextVisualRun(CoreTextVisualRun &&other) = default; const GlyphID *GetGlyphs() const override { return &this->glyphs[0]; } const float *GetPositions() const override { return &this->positions[0]; } @@ -65,7 +66,7 @@ public: }; /** A single line worth of VisualRuns. */ - class CoreTextLine : public AutoDeleteSmallVector<CoreTextVisualRun *>, public ParagraphLayouter::Line { + class CoreTextLine : public std::vector<CoreTextVisualRun>, public ParagraphLayouter::Line { public: CoreTextLine(CTLineRef line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff) { @@ -78,7 +79,7 @@ public: auto map = fontMapping.begin(); while (map < fontMapping.end() - 1 && map->first <= chars.location) map++; - this->push_back(new CoreTextVisualRun(run, map->second, buff)); + this->emplace_back(run, map->second, buff); } CFRelease(line); } @@ -86,7 +87,7 @@ public: int GetLeading() const override; int GetWidth() const override; int CountRuns() const override { return this->size(); } - const VisualRun *GetVisualRun(int run) const override { return this->at(run); } + const VisualRun &GetVisualRun(int run) const override { return this->at(run); } int GetInternalCharLength(WChar c) const override { diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index a5d03b948..f47d9236a 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -90,6 +90,7 @@ public: public: UniscribeVisualRun(const UniscribeRun &range, int x); + UniscribeVisualRun(UniscribeVisualRun &&other) noexcept; ~UniscribeVisualRun() override { free(this->glyph_to_char); @@ -106,12 +107,12 @@ public: }; /** A single line worth of VisualRuns. */ - class UniscribeLine : public AutoDeleteSmallVector<UniscribeVisualRun *>, public ParagraphLayouter::Line { + class UniscribeLine : public std::vector<UniscribeVisualRun>, public ParagraphLayouter::Line { public: int GetLeading() const override; int GetWidth() const override; int CountRuns() const override { return (uint)this->size(); } - const VisualRun *GetVisualRun(int run) const override { return this->at(run); } + const VisualRun &GetVisualRun(int run) const override { return this->at(run); } int GetInternalCharLength(WChar c) const override { @@ -424,7 +425,7 @@ static std::vector<SCRIPT_ITEM> UniscribeItemizeString(UniscribeParagraphLayoutF if (!UniscribeShapeRun(this->text_buffer, run)) return NULL; } - line->push_back(new UniscribeVisualRun(run, cur_pos)); + line->emplace_back(run, cur_pos); cur_pos += run.total_advance; } @@ -448,8 +449,8 @@ static std::vector<SCRIPT_ITEM> UniscribeItemizeString(UniscribeParagraphLayoutF int UniscribeParagraphLayout::UniscribeLine::GetLeading() const { int leading = 0; - for (const UniscribeVisualRun *run : *this) { - leading = max(leading, run->GetLeading()); + for (const auto &run : *this) { + leading = max(leading, run.GetLeading()); } return leading; @@ -462,8 +463,8 @@ int UniscribeParagraphLayout::UniscribeLine::GetLeading() const int UniscribeParagraphLayout::UniscribeLine::GetWidth() const { int length = 0; - for (const UniscribeVisualRun *run : *this) { - length += run->GetAdvance(); + for (const auto &run : *this) { + length += run.GetAdvance(); } return length; @@ -484,6 +485,14 @@ UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const Uniscribe this->positions[this->num_glyphs * 2] = advance + x; } +UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(UniscribeVisualRun&& other) noexcept + : glyphs(std::move(other.glyphs)), positions(std::move(other.positions)), char_to_glyph(std::move(other.char_to_glyph)), + start_pos(other.start_pos), total_advance(other.total_advance), num_glyphs(other.num_glyphs), font(other.font) +{ + this->glyph_to_char = other.glyph_to_char; + other.glyph_to_char = NULL; +} + const int *UniscribeParagraphLayout::UniscribeVisualRun::GetGlyphToCharMap() const { if (this->glyph_to_char == NULL) { |