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 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) : glyphCode (glyph), anchor (anch), width (w)
{ {
} }
@@ -69,6 +69,29 @@ TextLayout::Run::Run (const Run& other)
TextLayout::Run::~Run() noexcept {} 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 TextLayout::Line::Line() noexcept
: ascent (0.0f), descent (0.0f), leading (0.0f) : 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* 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); return *lines.getUnchecked (index);
} }
@@ -194,12 +214,23 @@ void TextLayout::addLine (Line* line)
void TextLayout::draw (Graphics& g, Rectangle<float> area) const 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) for (auto* line : lines)
{ {
auto lineRangeY = line->getLineBoundsY();
if (lineRangeY.getEnd() < clipTop)
continue;
if (lineRangeY.getStart() > clipBottom)
break;
auto lineOrigin = origin + line->lineOrigin; auto lineOrigin = origin + line->lineOrigin;
for (auto* run : line->runs) for (auto* run : line->runs)
@@ -213,16 +244,7 @@ void TextLayout::draw (Graphics& g, Rectangle<float> area) const
if (run->font.isUnderlined()) 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; auto lineThickness = run->font.getDescent() * 0.3f;
context.fillRect ({ runExtent.getStart() + lineOrigin.x, lineOrigin.y + lineThickness * 2.0f, context.fillRect ({ runExtent.getStart() + lineOrigin.x, lineOrigin.y + lineThickness * 2.0f,
@@ -385,7 +407,7 @@ namespace TextLayoutHelpers
currentRun = new TextLayout::Run(); currentRun = new TextLayout::Run();
addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition); addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
currentLine->stringRange = Range<int> (lineStartPosition, charPosition);
currentLine->stringRange = { lineStartPosition, charPosition };
if (! needToSetLineOrigin) if (! needToSetLineOrigin)
layout.addLine (currentLine.release()); layout.addLine (currentLine.release());
@@ -398,7 +420,7 @@ namespace TextLayoutHelpers
else else
{ {
addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition); addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
currentLine->stringRange = Range<int> (lineStartPosition, charPosition);
currentLine->stringRange = { lineStartPosition, charPosition };
if (! needToSetLineOrigin) if (! needToSetLineOrigin)
layout.addLine (currentLine.release()); layout.addLine (currentLine.release());
@@ -426,7 +448,7 @@ namespace TextLayoutHelpers
private: private:
static void addRun (TextLayout::Line& glyphLine, TextLayout::Run* glyphRun, 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->stringRange = { start, end };
glyphRun->font = t.font; glyphRun->font = t.font;
@@ -436,7 +458,7 @@ namespace TextLayoutHelpers
glyphLine.runs.add (glyphRun); glyphLine.runs.add (glyphRun);
} }
static int getCharacterType (const juce_wchar c) noexcept
static int getCharacterType (juce_wchar c) noexcept
{ {
if (c == '\r' || c == '\n') if (c == '\r' || c == '\n')
return 0; return 0;
@@ -482,7 +504,7 @@ namespace TextLayoutHelpers
tokens.add (new Token (currentString, font, colour, lastCharType == 2)); 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; float x = 0, y = 0, h = 0;
int i; int i;
@@ -500,7 +522,7 @@ namespace TextLayoutHelpers
if (nextTok == nullptr) if (nextTok == nullptr)
break; 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))) if (t.isNewLine || ((! nextTok->isWhitespace) && (tokenTooLarge && wordWrap != AttributedString::none)))
{ {
@@ -516,7 +538,7 @@ namespace TextLayoutHelpers
++totalLines; ++totalLines;
} }
void setLastLineHeight (int i, const float height) noexcept
void setLastLineHeight (int i, float height) noexcept
{ {
while (--i >= 0) 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 (Range<int> stringRange, int numGlyphsToPreallocate);
~Run() noexcept; ~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. */ Font font; /**< The run's font. */
Colour colour; /**< The run's colour. */ Colour colour; /**< The run's colour. */
Array<Glyph> glyphs; /**< The glyphs in this run. */ Array<Glyph> glyphs; /**< The glyphs in this run. */
@@ -171,7 +174,7 @@ public:
int getNumLines() const noexcept { return lines.size(); } int getNumLines() const noexcept { return lines.size(); }
/** Returns one of the lines. */ /** 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 /** 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. */ and will delete it when it is no longer needed. */


Loading…
Cancel
Save