diff --git a/modules/juce_graphics/fonts/juce_SimpleShapedText.cpp b/modules/juce_graphics/fonts/juce_SimpleShapedText.cpp index b73e22b894..02d9612f60 100644 --- a/modules/juce_graphics/fonts/juce_SimpleShapedText.cpp +++ b/modules/juce_graphics/fonts/juce_SimpleShapedText.cpp @@ -1398,7 +1398,10 @@ void SimpleShapedText::shape (const String& data, const auto end = (int64) glyphsInVisualOrder.size(); - glyphLookup.set (s.textRange, { { start, end }, ltr }); + for (auto i = start; i < end; ++i) + glyphsInVisualOrder[(size_t) i].cluster += lineRange.getStart(); + + glyphLookup.set (s.textRange + lineRange.getStart(), { { start, end }, ltr }); resolvedFonts.set ({ start, end }, s.font); } @@ -1471,4 +1474,63 @@ Range SimpleShapedText::getTextRange (int64 glyphIndex) const return Range::withStartAndLength (cluster, std::max ((int64) 1, nextAdjacentCluster - cluster)); } +#if JUCE_UNIT_TESTS + +struct SimpleShapedTextTests : public UnitTest +{ + SimpleShapedTextTests() + : UnitTest ("SimpleShapedText", UnitTestCategories::text) + { + } + + static constexpr const char* testStrings[] + { + "Some trivial text", + "Text with \r\n\r\n line feed and new line characters", + "\nPrepending new line character", + "\n\nMultiple prepending new line characters", + "\n\nMultiple prepending and trailing line feed or new line characters\n\r\n", + "Try right-clicking on a slider for an options menu. \n\nAlso, holding down CTRL while dragging will turn on a slider's velocity-sensitive mode", + }; + + void runTest (const char* text, float maxWidth) + { + String testString { text }; + + SimpleShapedText st { &testString, ShapedTextOptions{}.withMaxWidth (maxWidth) }; + + auto success = true; + + for (int64 glyphIndex = 0; glyphIndex < st.getNumGlyphs(); ++glyphIndex) + { + const auto textRange = st.getTextRange (glyphIndex); + + // This assumption holds for LTR text if no ligatures are used + success &= textRange.getStart() == glyphIndex && textRange.getLength() == 1; + } + + expect (success, String { "Failed for test string: " } + testString.replace ("\r", "") + .replace ("\n", "")); + } + + void runTest() override + { + beginTest ("getTextRange: LTR Latin text without ligatures - no soft breaks"); + { + for (auto* testString : testStrings) + runTest (testString, 100'000.0f); + } + + beginTest ("getTextRange: LTR Latin text without ligatures - with soft breaks"); + { + for (auto* testString : testStrings) + runTest (testString, 60.0f); + } + } +}; + +static SimpleShapedTextTests simpleShapedTextTests; + +#endif + } // namespace juce