From ef840b74728a0cd055d33387fba06871284c43da Mon Sep 17 00:00:00 2001 From: attila Date: Tue, 28 Jan 2025 17:58:24 +0100 Subject: [PATCH] Use detail::RangedValues on ShapedText related interfaces Previously using the FontForRange type was motivated by hiding the RangedValues type in case we wanted to expose the ShapedText API. This introduced unnecessary conversions between FontForRange and RangedValues. --- .../detail/juce_SimpleShapedText.cpp | 35 ++++++++----------- .../detail/juce_SimpleShapedText.h | 21 ++++++----- .../juce_graphics/fonts/juce_TextLayout.cpp | 19 +--------- 3 files changed, 28 insertions(+), 47 deletions(-) diff --git a/modules/juce_graphics/detail/juce_SimpleShapedText.cpp b/modules/juce_graphics/detail/juce_SimpleShapedText.cpp index cdc626ac31..2b115a4d2f 100644 --- a/modules/juce_graphics/detail/juce_SimpleShapedText.cpp +++ b/modules/juce_graphics/detail/juce_SimpleShapedText.cpp @@ -494,19 +494,19 @@ static auto makeSpan (T& array) return Span { array.getRawDataPointer(), (size_t) array.size() }; } -static std::vector findSuitableFontsForText (const Font& font, - const String& text, - const String& language = {}) +static detail::RangedValues findSuitableFontsForText (const Font& font, + const String& text, + const String& language = {}) { detail::RangedValues> fonts; fonts.set ({ 0, (int64) text.length() }, font); const auto getResult = [&] { - std::vector result; + detail::RangedValues result; for (const auto [r, v] : fonts) - result.emplace_back (r, v.value_or (font)); + result.set (r, v.value_or (font)); return result; }; @@ -540,7 +540,7 @@ static std::vector findSuitableFontsForText (const Font& font, // can't find any more suitable fonts or all codepoints have one for (auto numMissingGlyphs = markMissingGlyphs(); numMissingGlyphs > 0;) { - std::vector changes; + std::vector, Font>> changes; for (const auto [r, f] : fonts) { @@ -575,10 +575,8 @@ static RangedValues resolveFontsWithFallback (const String& string, const auto rf = findSuitableFontsForText (f, string.substring ((int) r.getStart(), (int) std::min (r.getEnd(), (int64) string.length()))); - for (auto& item : rf) - item.first += r.getStart(); - - resolved.setForEach (rf.begin(), rf.end()); + for (const auto [subRange, font] : rf) + resolved.set (subRange + r.getStart(), font); } return resolved; @@ -785,16 +783,11 @@ private: }; template -static auto createRangedValues (const std::vector, T>>& pairs, int64 offset = 0) +static auto rangedValuesWithOffset (detail::RangedValues rv, int64 offset = 0) { - detail::RangedValues result; - - for (const auto& [range, value] : pairs) - result.insert (range.movedToStartAt (range.getStart() - offset), value); - - result.eraseUpTo (0); - - return result; + rv.shift (std::numeric_limits::min(), -offset); + rv.eraseUpTo (0); + return rv; } struct Shaper @@ -819,8 +812,8 @@ struct Shaper const auto bidiLevels = bidiParagraph.getResolvedLevels(); const auto fonts = resolveFontsWithFallback (string, - createRangedValues (options.getFontsForRange(), - shapingRange.getStart())); + rangedValuesWithOffset (options.getFontsForRange(), + shapingRange.getStart())); for (Unicode::LineBreakIterator lineIter { makeSpan (analysis) }; auto lineRun = lineIter.next();) { diff --git a/modules/juce_graphics/detail/juce_SimpleShapedText.h b/modules/juce_graphics/detail/juce_SimpleShapedText.h index b2c59446a6..5c0b7efd33 100644 --- a/modules/juce_graphics/detail/juce_SimpleShapedText.h +++ b/modules/juce_graphics/detail/juce_SimpleShapedText.h @@ -35,8 +35,6 @@ namespace juce::detail { -using FontForRange = std::pair, Font>; - /** Types of text direction. This may also be applied to characters. */ enum class TextDirection { @@ -64,12 +62,13 @@ public: [[nodiscard]] ShapedTextOptions withFont (Font x) const { - return withMember (*this, &ShapedTextOptions::fontsForRange, - std::vector { { { 0, std::numeric_limits::max() }, - x } }); + RangedValues fonts; + fonts.set ({ 0, std::numeric_limits::max() }, x); + + return withMember (*this, &ShapedTextOptions::fontsForRange, std::move (fonts)); } - [[nodiscard]] ShapedTextOptions withFontsForRange (const std::vector& x) const + [[nodiscard]] ShapedTextOptions withFonts (const detail::RangedValues& x) const { return withMember (*this, &ShapedTextOptions::fontsForRange, x); } @@ -151,8 +150,14 @@ private: std::optional readingDir; std::optional maxWidth; std::optional height; - std::vector fontsForRange { { { 0, std::numeric_limits::max() }, - FontOptions { 15.0f } } }; + + detail::RangedValues fontsForRange = std::invoke ([&] + { + detail::RangedValues result; + result.set ({ 0, std::numeric_limits::max() }, FontOptions { 15.0f }); + return result; + }); + String language = SystemStats::getDisplayLanguage(); float firstLineIndent = 0.0f; float leading = 1.0f; diff --git a/modules/juce_graphics/fonts/juce_TextLayout.cpp b/modules/juce_graphics/fonts/juce_TextLayout.cpp index 2c6dd56422..58bf43d440 100644 --- a/modules/juce_graphics/fonts/juce_TextLayout.cpp +++ b/modules/juce_graphics/fonts/juce_TextLayout.cpp @@ -325,23 +325,6 @@ static auto castTo (const Range& r) return Range (static_cast (r.getStart()), static_cast (r.getEnd())); } -static auto getFontsForRange (const detail::RangedValues& fonts) -{ - using namespace detail; - - std::vector result; - result.reserve (fonts.size()); - - std::transform (fonts.begin(), - fonts.end(), - std::back_inserter (result), - [] (auto entry) { - return FontForRange { entry.range, entry.value }; - }); - - return result; -} - static Range getInputRange (const detail::ShapedText& st, Range glyphRange) { if (glyphRange.isEmpty()) @@ -425,7 +408,7 @@ void TextLayout::createStandardLayout (const AttributedString& text) colours.set (range, attribute.colour); } - auto shapedTextOptions = ShapedTextOptions{}.withFontsForRange (getFontsForRange (fonts)) + auto shapedTextOptions = ShapedTextOptions{}.withFonts (fonts) .withLanguage (SystemStats::getUserLanguage()) .withTrailingWhitespacesShouldFit (false) .withJustification (justification)