diff --git a/modules/juce_graphics/fonts/juce_TextLayout.cpp b/modules/juce_graphics/fonts/juce_TextLayout.cpp index 1a713db557..c062bcebb8 100644 --- a/modules/juce_graphics/fonts/juce_TextLayout.cpp +++ b/modules/juce_graphics/fonts/juce_TextLayout.cpp @@ -27,7 +27,7 @@ namespace juce { -TextLayout::Glyph::Glyph (const int glyph, Point anch, float w) noexcept +TextLayout::Glyph::Glyph (int glyph, Point anch, float w) noexcept : glyphCode (glyph), anchor (anch), width (w) { } @@ -69,6 +69,29 @@ TextLayout::Run::Run (const Run& other) TextLayout::Run::~Run() noexcept {} +Range TextLayout::Run::getRunBoundsX() const noexcept +{ + Range range; + bool isFirst = true; + + for (auto& glyph : glyphs) + { + Range r (glyph.anchor.x, glyph.anchor.x + glyph.width); + + if (isFirst) + { + isFirst = false; + range = r; + } + else + { + range = range.getUnionWith (r); + } + } + + return range; +} + //============================================================================== TextLayout::Line::Line() noexcept : ascent (0.0f), descent (0.0f), leading (0.0f) @@ -101,19 +124,16 @@ Range TextLayout::Line::getLineBoundsX() const noexcept for (auto* run : runs) { - for (auto& glyph : run->glyphs) - { - Range runRange (glyph.anchor.x, glyph.anchor.x + glyph.width); + auto runRange = run->getRunBoundsX(); - if (isFirst) - { - isFirst = false; - range = runRange; - } - else - { - range = range.getUnionWith (runRange); - } + if (isFirst) + { + isFirst = false; + range = runRange; + } + else + { + range = range.getUnionWith (runRange); } } @@ -177,7 +197,7 @@ TextLayout::~TextLayout() { } -TextLayout::Line& TextLayout::getLine (const int index) const +TextLayout::Line& TextLayout::getLine (int index) const noexcept { return *lines.getUnchecked (index); } @@ -194,12 +214,23 @@ void TextLayout::addLine (Line* line) void TextLayout::draw (Graphics& g, Rectangle area) const { - auto origin = justification.appliedToRectangle (Rectangle (width, getHeight()), area).getPosition(); + auto origin = justification.appliedToRectangle ({ width, getHeight() }, area).getPosition(); - auto& context = g.getInternalContext(); + auto& context = g.getInternalContext(); + auto clip = context.getClipBounds(); + auto clipTop = (float) clip.getY(); + auto clipBottom = (float) clip.getBottom(); for (auto* line : lines) { + auto lineRangeY = line->getLineBoundsY(); + + if (lineRangeY.getEnd() < clipTop) + continue; + + if (lineRangeY.getStart() > clipBottom) + break; + auto lineOrigin = origin + line->lineOrigin; for (auto* run : line->runs) @@ -213,16 +244,7 @@ void TextLayout::draw (Graphics& g, Rectangle area) const if (run->font.isUnderlined()) { - Range runExtent; - - for (auto& glyph : run->glyphs) - { - Range glyphRange (glyph.anchor.x, glyph.anchor.x + glyph.width); - - runExtent = runExtent.isEmpty() ? glyphRange - : runExtent.getUnionWith (glyphRange); - } - + auto runExtent = run->getRunBoundsX(); auto lineThickness = run->font.getDescent() * 0.3f; context.fillRect ({ runExtent.getStart() + lineOrigin.x, lineOrigin.y + lineThickness * 2.0f, @@ -385,7 +407,7 @@ namespace TextLayoutHelpers currentRun = new TextLayout::Run(); addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition); - currentLine->stringRange = Range (lineStartPosition, charPosition); + currentLine->stringRange = { lineStartPosition, charPosition }; if (! needToSetLineOrigin) layout.addLine (currentLine.release()); @@ -398,7 +420,7 @@ namespace TextLayoutHelpers else { addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition); - currentLine->stringRange = Range (lineStartPosition, charPosition); + currentLine->stringRange = { lineStartPosition, charPosition }; if (! needToSetLineOrigin) layout.addLine (currentLine.release()); @@ -426,7 +448,7 @@ namespace TextLayoutHelpers private: static void addRun (TextLayout::Line& glyphLine, TextLayout::Run* glyphRun, - const Token& t, const int start, const int end) + const Token& t, int start, int end) { glyphRun->stringRange = { start, end }; glyphRun->font = t.font; @@ -436,7 +458,7 @@ namespace TextLayoutHelpers glyphLine.runs.add (glyphRun); } - static int getCharacterType (const juce_wchar c) noexcept + static int getCharacterType (juce_wchar c) noexcept { if (c == '\r' || c == '\n') return 0; @@ -482,7 +504,7 @@ namespace TextLayoutHelpers tokens.add (new Token (currentString, font, colour, lastCharType == 2)); } - void layoutRuns (const float maxWidth, const float extraLineSpacing, const AttributedString::WordWrap wordWrap) + void layoutRuns (float maxWidth, float extraLineSpacing, AttributedString::WordWrap wordWrap) { float x = 0, y = 0, h = 0; int i; @@ -500,7 +522,7 @@ namespace TextLayoutHelpers if (nextTok == nullptr) break; - const bool tokenTooLarge = (x + nextTok->area.getWidth() > maxWidth); + bool tokenTooLarge = (x + nextTok->area.getWidth() > maxWidth); if (t.isNewLine || ((! nextTok->isWhitespace) && (tokenTooLarge && wordWrap != AttributedString::none))) { @@ -516,7 +538,7 @@ namespace TextLayoutHelpers ++totalLines; } - void setLastLineHeight (int i, const float height) noexcept + void setLastLineHeight (int i, float height) noexcept { while (--i >= 0) { diff --git a/modules/juce_graphics/fonts/juce_TextLayout.h b/modules/juce_graphics/fonts/juce_TextLayout.h index ae0254c543..4b11eee20d 100644 --- a/modules/juce_graphics/fonts/juce_TextLayout.h +++ b/modules/juce_graphics/fonts/juce_TextLayout.h @@ -119,6 +119,9 @@ public: Run (Range stringRange, int numGlyphsToPreallocate); ~Run() noexcept; + /** Returns the X position range which contains all the glyphs in this run. */ + Range getRunBoundsX() const noexcept; + Font font; /**< The run's font. */ Colour colour; /**< The run's colour. */ Array glyphs; /**< The glyphs in this run. */ @@ -171,7 +174,7 @@ public: int getNumLines() const noexcept { return lines.size(); } /** Returns one of the lines. */ - Line& getLine (int index) const; + Line& getLine (int index) const noexcept; /** Adds a line to the layout. The layout will take ownership of this line object and will delete it when it is no longer needed. */