Browse Source

Optimisation for drawing of large TextLayouts that go beyond the top and bottom of the graphics clip region

tags/2021-05-28
jules 8 years ago
parent
commit
0933ce4be8
2 changed files with 59 additions and 34 deletions
  1. +55
    -33
      modules/juce_graphics/fonts/juce_TextLayout.cpp
  2. +4
    -1
      modules/juce_graphics/fonts/juce_TextLayout.h

+ 55
- 33
modules/juce_graphics/fonts/juce_TextLayout.cpp View File

@@ -27,7 +27,7 @@
namespace juce
{
TextLayout::Glyph::Glyph (const int glyph, Point<float> anch, float w) noexcept
TextLayout::Glyph::Glyph (int glyph, Point<float> 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<float> TextLayout::Run::getRunBoundsX() const noexcept
{
Range<float> range;
bool isFirst = true;
for (auto& glyph : glyphs)
{
Range<float> 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<float> TextLayout::Line::getLineBoundsX() const noexcept
for (auto* run : runs)
{
for (auto& glyph : run->glyphs)
{
Range<float> 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<float> area) const
{
auto origin = justification.appliedToRectangle (Rectangle<float> (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<float> area) const
if (run->font.isUnderlined())
{
Range<float> runExtent;
for (auto& glyph : run->glyphs)
{
Range<float> 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<int> (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<int> (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)
{


+ 4
- 1
modules/juce_graphics/fonts/juce_TextLayout.h View File

@@ -119,6 +119,9 @@ public:
Run (Range<int> stringRange, int numGlyphsToPreallocate);
~Run() noexcept;
/** Returns the X position range which contains all the glyphs in this run. */
Range<float> getRunBoundsX() const noexcept;
Font font; /**< The run's font. */
Colour colour; /**< The run's colour. */
Array<Glyph> 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. */


Loading…
Cancel
Save