|
|
|
@@ -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)
|
|
|
|
{
|
|
|
|
|