From ae575a7a5be70f0cc90c28219c103147073b0d19 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Jan 2024 21:06:43 +0000 Subject: [PATCH] Codechange: Store text run positions in vector of points. This simplifies the interlaced vector of x/y positions. --- src/core/geometry_type.hpp | 3 +++ src/gfx.cpp | 6 +++--- src/gfx_layout.cpp | 7 +++---- src/gfx_layout.h | 2 +- src/gfx_layout_fallback.cpp | 20 ++++++++++-------- src/gfx_layout_icu.cpp | 32 ++++++++++------------------- src/os/macosx/string_osx.cpp | 15 +++++++------- src/os/windows/string_uniscribe.cpp | 14 ++++++------- 8 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/core/geometry_type.hpp b/src/core/geometry_type.hpp index 98995f4797..c19932a160 100644 --- a/src/core/geometry_type.hpp +++ b/src/core/geometry_type.hpp @@ -21,6 +21,9 @@ struct Point { int x; int y; + + constexpr Point() : x(0), y(0) {} + constexpr Point(int x, int y) : x(x), y(y) {} }; /** Dimensions (a width and height) of a rectangle in 2D */ diff --git a/src/gfx.cpp b/src/gfx.cpp index 3953e7497e..1cf74769e6 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -599,9 +599,9 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, /* Not a valid glyph (empty) */ if (glyph == 0xFFFF) continue; - int begin_x = (int)positions[i * 2] + left - offset_x; - int end_x = (int)positions[i * 2 + 2] + left - offset_x - 1; - int top = (int)positions[i * 2 + 1] + y; + int begin_x = positions[i].x + left - offset_x; + int end_x = positions[i + 1].x + left - offset_x - 1; + int top = positions[i].y + 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 13ca5902d9..1ebe5dc251 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -260,8 +260,7 @@ Point Layouter::GetCharPosition(std::string_view::const_iterator ch) const for (int i = 0; i < run.GetGlyphCount(); i++) { /* Matching glyph? Return position. */ if ((size_t)charmap[i] == index) { - Point p = { (int)positions[i * 2], (int)positions[i * 2 + 1] }; - return p; + return positions[i]; } } } @@ -291,8 +290,8 @@ ptrdiff_t Layouter::GetCharAtPosition(int x, size_t line_index) const /* Not a valid glyph (empty). */ if (glyphs[i] == 0xFFFF) continue; - int begin_x = (int)positions[i * 2]; - int end_x = (int)positions[i * 2 + 2]; + int begin_x = positions[i].x; + int end_x = positions[i + 1].x; if (IsInsideMM(x, begin_x, end_x)) { /* Found our glyph, now convert to UTF-8 string index. */ diff --git a/src/gfx_layout.h b/src/gfx_layout.h index 136e345b4c..fc0340b179 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -97,7 +97,7 @@ public: virtual const Font *GetFont() const = 0; virtual int GetGlyphCount() const = 0; virtual const std::vector &GetGlyphs() const = 0; - virtual const std::vector &GetPositions() const = 0; + virtual const std::vector &GetPositions() const = 0; virtual int GetLeading() const = 0; virtual const std::vector &GetGlyphToCharMap() const = 0; }; diff --git a/src/gfx_layout_fallback.cpp b/src/gfx_layout_fallback.cpp index 04f1335a95..745a834c1f 100644 --- a/src/gfx_layout_fallback.cpp +++ b/src/gfx_layout_fallback.cpp @@ -40,7 +40,7 @@ public: /** Visual run contains data about the bit of text with the same font. */ class FallbackVisualRun : public ParagraphLayouter::VisualRun { std::vector glyphs; ///< The glyphs we're drawing. - std::vector positions; ///< The positions of the glyphs. + std::vector positions; ///< The positions of the glyphs. std::vector glyph_to_char; ///< The char index of the glyphs. Font *font; ///< The font used to layout these. @@ -50,7 +50,7 @@ public: const Font *GetFont() const override { return this->font; } int GetGlyphCount() const override { return static_cast(this->glyphs.size()); } const std::vector &GetGlyphs() const override { return this->glyphs; } - const std::vector &GetPositions() const override { return this->positions; } + const std::vector &GetPositions() const override { return this->positions; } int GetLeading() const override { return this->GetFont()->fc->GetHeight(); } const std::vector &GetGlyphToCharMap() const override { return this->glyph_to_char; } }; @@ -118,21 +118,23 @@ FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const this->glyph_to_char.reserve(char_count); /* Positions contains the location of the begin of each of the glyphs, and the end of the last one. */ - this->positions.resize(char_count * 2 + 2); - this->positions[0] = x; + this->positions.reserve(char_count + 1); + int advance = x; for (int i = 0; i < char_count; i++) { const GlyphID &glyph_id = this->glyphs.emplace_back(font->fc->MapCharToGlyph(chars[i])); if (isbuiltin) { - this->positions[2 * i + 1] = font->fc->GetAscender(); // Apply sprite font's ascender. + this->positions.emplace_back(advance, font->fc->GetAscender()); // Apply sprite font's ascender. } else if (chars[i] >= SCC_SPRITE_START && chars[i] <= SCC_SPRITE_END) { - this->positions[2 * i + 1] = (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2; // Align sprite font to centre + this->positions.emplace_back(advance, (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2); // Align sprite font to centre } else { - this->positions[2 * i + 1] = 0; // No ascender adjustment. + this->positions.emplace_back(advance, 0); // No ascender adjustment. } - this->positions[2 * i + 2] = this->positions[2 * i] + font->fc->GetGlyphWidth(glyph_id); + advance += font->fc->GetGlyphWidth(glyph_id); this->glyph_to_char.push_back(char_offset + i); } + /* End-of-run position. */ + this->positions.emplace_back(advance, 0); } /** @@ -163,7 +165,7 @@ int FallbackParagraphLayout::FallbackLine::GetWidth() const * the last run gives us the end of the line and thus the width. */ const auto &run = this->GetVisualRun(this->CountRuns() - 1); - return (int)run.GetPositions()[run.GetGlyphCount() * 2]; + return run.GetPositions().back().x; } /** diff --git a/src/gfx_layout_icu.cpp b/src/gfx_layout_icu.cpp index 64c8e6752b..d93a9eb771 100644 --- a/src/gfx_layout_icu.cpp +++ b/src/gfx_layout_icu.cpp @@ -45,7 +45,7 @@ public: std::vector glyphs; ///< The glyphs of the run. Valid after Shape() is called. std::vector advance; ///< The advance (width) of the glyphs. Valid after Shape() is called. std::vector glyph_to_char; ///< The mapping from glyphs to characters. Valid after Shape() is called. - std::vector positions; ///< The positions of the glyphs. Valid after Shape() is called. + std::vector positions; ///< The positions of the glyphs. Valid after Shape() is called. int total_advance = 0; ///< The total advance of the run. Valid after Shape() is called. ICURun(int start, int length, UBiDiLevel level, UScriptCode script = USCRIPT_UNKNOWN, Font *font = nullptr) : start(start), length(length), level(level), script(script), font(font) {} @@ -62,7 +62,7 @@ public: class ICUVisualRun : public ParagraphLayouter::VisualRun { private: std::vector glyphs; - std::vector positions; + std::vector positions; std::vector glyph_to_char; int total_advance; @@ -72,7 +72,7 @@ public: ICUVisualRun(const ICURun &run, int x); const std::vector &GetGlyphs() const override { return this->glyphs; } - const std::vector &GetPositions() const override { return this->positions; } + const std::vector &GetPositions() const override { return this->positions; } const std::vector &GetGlyphToCharMap() const override { return this->glyph_to_char; } const Font *GetFont() const override { return this->font; } @@ -135,16 +135,9 @@ ICUParagraphLayout::ICUVisualRun::ICUVisualRun(const ICURun &run, int x) : assert(!run.positions.empty()); this->positions.reserve(run.positions.size()); - /* "positions" is an array of x/y. So we need to alternate. */ - bool is_x = true; - for (auto &position : run.positions) { - if (is_x) { - this->positions.push_back(position + x); - } else { - this->positions.push_back(position); - } - - is_x = !is_x; + /* Copy positions, moving x coordinate by x offset. */ + for (const Point &pt : run.positions) { + this->positions.emplace_back(pt.x + x, pt.y); } } @@ -186,7 +179,7 @@ void ICURun::Shape(UChar *buff, size_t buff_length) /* Reserve space, as we already know the size. */ this->glyphs.reserve(glyph_count); this->glyph_to_char.reserve(glyph_count); - this->positions.reserve(glyph_count * 2 + 2); + this->positions.reserve(glyph_count + 1); this->advance.reserve(glyph_count); /* Prepare the glyphs/position. ICUVisualRun will give the position an offset if needed. */ @@ -198,13 +191,11 @@ void ICURun::Shape(UChar *buff, size_t buff_length) auto glyph = this->font->fc->MapCharToGlyph(buff[glyph_info[i].cluster]); this->glyphs.push_back(glyph); - this->positions.push_back(advance); - this->positions.push_back((this->font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->font->fc->GetSize()))) / 2); // Align sprite font to centre + this->positions.emplace_back(advance, (this->font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->font->fc->GetSize()))) / 2); // Align sprite font to centre x_advance = this->font->fc->GetGlyphWidth(glyph); } else { this->glyphs.push_back(glyph_info[i].codepoint); - this->positions.push_back(glyph_pos[i].x_offset / FONT_SCALE + advance); - this->positions.push_back(glyph_pos[i].y_offset / FONT_SCALE); + this->positions.emplace_back(glyph_pos[i].x_offset / FONT_SCALE + advance, glyph_pos[i].y_offset / FONT_SCALE); x_advance = glyph_pos[i].x_advance / FONT_SCALE; } @@ -213,9 +204,8 @@ void ICURun::Shape(UChar *buff, size_t buff_length) advance += x_advance; } - /* Position has one more element to close off the array. */ - this->positions.push_back(advance); - this->positions.push_back(0); + /* End-of-run position. */ + this->positions.emplace_back(advance, 0); /* Track the total advancement we made. */ this->total_advance = advance; diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index 6e52c74b69..539d478a4e 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -71,7 +71,7 @@ public: class CoreTextVisualRun : public ParagraphLayouter::VisualRun { private: std::vector glyphs; - std::vector positions; + std::vector positions; std::vector glyph_to_char; int total_advance = 0; @@ -82,7 +82,7 @@ public: CoreTextVisualRun(CoreTextVisualRun &&other) = default; const std::vector &GetGlyphs() const override { return this->glyphs; } - const std::vector &GetPositions() const override { return this->positions; } + const std::vector &GetPositions() const override { return this->positions; } const std::vector &GetGlyphToCharMap() const override { return this->glyph_to_char; } const Font *GetFont() const override { return this->font; } @@ -240,7 +240,7 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font CGPoint pts[this->glyphs.size()]; CTRunGetPositions(run, CFRangeMake(0, 0), pts); - this->positions.resize(this->glyphs.size() * 2 + 2); + this->positions.reserve(this->glyphs.size() + 1); /* Convert glyph array to our data type. At the same time, substitute * the proper glyphs for our private sprite glyphs. */ @@ -250,16 +250,15 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && (gl[i] == 0 || gl[i] == 3)) { /* A glyph of 0 indidicates not found, while apparently 3 is what char 0xFFFC maps to. */ this->glyphs[i] = font->fc->MapCharToGlyph(buff[this->glyph_to_char[i]]); - this->positions[i * 2 + 0] = pts[i].x; - this->positions[i * 2 + 1] = (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2; // Align sprite font to centre + this->positions.emplace_back(pts[i].x, (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2); // Align sprite font to centre } else { this->glyphs[i] = gl[i]; - this->positions[i * 2 + 0] = pts[i].x; - this->positions[i * 2 + 1] = pts[i].y; + this->positions.emplace_back(pts[i].x, pts[i].y); } } this->total_advance = (int)std::ceil(CTRunGetTypographicBounds(run, CFRangeMake(0, 0), nullptr, nullptr, nullptr)); - this->positions[this->glyphs.size() * 2] = this->positions[0] + this->total_advance; + /* End-of-run position. */ + this->positions.emplace_back(this->positions.front().x + this->total_advance, 0); } /** diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index fd6881b533..5e2b4019d5 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -74,7 +74,7 @@ public: class UniscribeVisualRun : public ParagraphLayouter::VisualRun { private: std::vector glyphs; - std::vector positions; + std::vector positions; std::vector char_to_glyph; int start_pos; @@ -89,7 +89,7 @@ public: UniscribeVisualRun(UniscribeVisualRun &&other) noexcept; const std::vector &GetGlyphs() const override { return this->glyphs; } - const std::vector &GetPositions() const override { return this->positions; } + const std::vector &GetPositions() const override { return this->positions; } const std::vector &GetGlyphToCharMap() const override; const Font *GetFont() const override { return this->font; } @@ -474,16 +474,16 @@ int UniscribeParagraphLayout::UniscribeLine::GetWidth() const UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const UniscribeRun &range, int x) : glyphs(range.ft_glyphs), char_to_glyph(range.char_to_glyph), start_pos(range.pos), total_advance(range.total_advance), font(range.font) { this->num_glyphs = (int)glyphs.size(); - this->positions.resize(this->num_glyphs * 2 + 2); + this->positions.reserve(this->num_glyphs + 1); - int advance = 0; + int advance = x; for (int i = 0; i < this->num_glyphs; i++) { - this->positions[i * 2 + 0] = range.offsets[i].du + advance + x; - this->positions[i * 2 + 1] = range.offsets[i].dv; + this->positions.emplace_back(range.offsets[i].du + advance, range.offsets[i].dv); advance += range.advances[i]; } - this->positions[this->num_glyphs * 2] = advance + x; + /* End-of-run position. */ + this->positions.emplace_back(advance, 0); } UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(UniscribeVisualRun&& other) noexcept