Browse Source

Modernised some code in some text layout classes, and made TextLayout draw underlining where the font asks for it

tags/2021-05-28
jules 8 years ago
parent
commit
89ad7eb0a4
3 changed files with 79 additions and 80 deletions
  1. +15
    -16
      modules/juce_graphics/fonts/juce_GlyphArrangement.cpp
  2. +63
    -63
      modules/juce_graphics/fonts/juce_TextLayout.cpp
  3. +1
    -1
      modules/juce_graphics/fonts/juce_TextLayout.h

+ 15
- 16
modules/juce_graphics/fonts/juce_GlyphArrangement.cpp View File

@@ -96,7 +96,7 @@ void PositionedGlyph::createPath (Path& path) const
{
if (! isWhitespace())
{
if (Typeface* const t = font.getTypeface())
if (auto* t = font.getTypeface())
{
Path p;
t->getOutlineForGlyph (glyph, p);
@@ -111,7 +111,7 @@ bool PositionedGlyph::hitTest (float px, float py) const
{
if (getBounds().contains (px, py) && ! isWhitespace())
{
if (Typeface* const t = font.getTypeface())
if (auto* t = font.getTypeface())
{
Path p;
t->getOutlineForGlyph (glyph, p);
@@ -207,7 +207,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font,
const int textLen = newGlyphs.size();
glyphs.ensureStorageAllocated (glyphs.size() + textLen);
String::CharPointerType t (text.getCharPointer());
auto t = text.getCharPointer();
for (int i = 0; i < textLen; ++i)
{
@@ -249,7 +249,7 @@ int GlyphArrangement::insertEllipsis (const Font& font, const float maxXPos,
while (endIndex > startIndex)
{
const PositionedGlyph& pg = glyphs.getReference (--endIndex);
auto& pg = glyphs.getReference (--endIndex);
xOffset = pg.x;
yOffset = pg.y;
@@ -299,7 +299,7 @@ void GlyphArrangement::addJustifiedText (const Font& font,
while (i < glyphs.size())
{
const PositionedGlyph& pg = glyphs.getReference (i);
auto& pg = glyphs.getReference (i);
const juce_wchar c = pg.getCharacter();
if (c == '\r' || c == '\n')
@@ -433,7 +433,7 @@ void GlyphArrangement::addLinesWithLineBreaks (const String& text, const Font& f
GlyphArrangement ga;
ga.addJustifiedText (f, text, x, y, width, layout);
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
auto bb = ga.getBoundingBox (0, -1, false);
float dy = y - bb.getY();
@@ -485,7 +485,7 @@ void GlyphArrangement::stretchRangeOfGlyphs (int startIndex, int num,
while (--num >= 0)
{
PositionedGlyph& pg = glyphs.getReference (startIndex++);
auto& pg = glyphs.getReference (startIndex++);
pg.x = xAnchor + (pg.x - xAnchor) * horizontalScaleFactor;
pg.font.setHorizontalScale (pg.font.getHorizontalScale() * horizontalScaleFactor);
@@ -505,7 +505,7 @@ Rectangle<float> GlyphArrangement::getBoundingBox (int startIndex, int num, cons
while (--num >= 0)
{
const PositionedGlyph& pg = glyphs.getReference (startIndex++);
auto& pg = glyphs.getReference (startIndex++);
if (includeWhitespace || ! pg.isWhitespace())
result = result.getUnion (pg.getBounds());
@@ -522,8 +522,8 @@ void GlyphArrangement::justifyGlyphs (const int startIndex, const int num,
if (glyphs.size() > 0 && num > 0)
{
const Rectangle<float> bb (getBoundingBox (startIndex, num, ! justification.testFlags (Justification::horizontallyJustified
| Justification::horizontallyCentred)));
auto bb = getBoundingBox (startIndex, num, ! justification.testFlags (Justification::horizontallyJustified
| Justification::horizontallyCentred));
float deltaX = 0.0f, deltaY = 0.0f;
if (justification.testFlags (Justification::horizontallyJustified)) deltaX = x - bb.getX();
@@ -591,8 +591,7 @@ void GlyphArrangement::spreadOutLine (const int start, const int num, const floa
const float startX = glyphs.getReference (start).getLeft();
const float endX = glyphs.getReference (start + num - 1 - spacesAtEnd).getRight();
const float extraPaddingBetweenWords
= (targetWidth - (endX - startX)) / (float) numSpaces;
const float extraPaddingBetweenWords = (targetWidth - (endX - startX)) / (float) numSpaces;
float deltaX = 0.0f;
@@ -764,13 +763,13 @@ void GlyphArrangement::draw (const Graphics& g) const
void GlyphArrangement::draw (const Graphics& g, const AffineTransform& transform) const
{
LowLevelGraphicsContext& context = g.getInternalContext();
auto& context = g.getInternalContext();
Font lastFont (context.getFont());
bool needToRestore = false;
for (int i = 0; i < glyphs.size(); ++i)
{
const PositionedGlyph& pg = glyphs.getReference(i);
auto& pg = glyphs.getReference(i);
if (pg.font.isUnderlined())
drawGlyphUnderline (g, pg, i, transform);
@@ -800,8 +799,8 @@ void GlyphArrangement::draw (const Graphics& g, const AffineTransform& transform
void GlyphArrangement::createPath (Path& path) const
{
for (int i = 0; i < glyphs.size(); ++i)
glyphs.getReference (i).createPath (path);
for (auto& g : glyphs)
g.createPath (path);
}
int GlyphArrangement::findGlyphIndexAt (const float x, const float y) const


+ 63
- 63
modules/juce_graphics/fonts/juce_TextLayout.cpp View File

@@ -48,7 +48,7 @@ TextLayout::Run::Run() noexcept
{
}
TextLayout::Run::Run (Range<int> range, const int numGlyphsToPreallocate)
TextLayout::Run::Run (Range<int> range, int numGlyphsToPreallocate)
: colour (0xff000000), stringRange (range)
{
glyphs.ensureStorageAllocated (numGlyphsToPreallocate);
@@ -94,31 +94,20 @@ Range<float> TextLayout::Line::getLineBoundsX() const noexcept
Range<float> range;
bool isFirst = true;
for (int i = runs.size(); --i >= 0;)
for (auto* run : runs)
{
const Run& run = *runs.getUnchecked(i);
if (run.glyphs.size() > 0)
for (auto& glyph : run->glyphs)
{
float minX = run.glyphs.getReference(0).anchor.x;
float maxX = minX;
for (int j = run.glyphs.size(); --j >= 0;)
{
const Glyph& glyph = run.glyphs.getReference (j);
const float x = glyph.anchor.x;
minX = jmin (minX, x);
maxX = jmax (maxX, x + glyph.width);
}
Range<float> runRange (glyph.anchor.x, glyph.anchor.x + glyph.width);
if (isFirst)
{
isFirst = false;
range = Range<float> (minX, maxX);
range = runRange;
}
else
{
range = range.getUnionWith (Range<float> (minX, maxX));
range = range.getUnionWith (runRange);
}
}
}
@@ -134,10 +123,10 @@ Range<float> TextLayout::Line::getLineBoundsY() const noexcept
Rectangle<float> TextLayout::Line::getLineBounds() const noexcept
{
const Range<float> x (getLineBoundsX()),
y (getLineBoundsY());
auto x = getLineBoundsX();
auto y = getLineBoundsY();
return Rectangle<float> (x.getStart(), y.getStart(), x.getLength(), y.getLength());
return { x.getStart(), y.getStart(), x.getLength(), y.getLength() };
}
//==============================================================================
@@ -198,28 +187,40 @@ void TextLayout::addLine (Line* line)
lines.add (line);
}
void TextLayout::draw (Graphics& g, const Rectangle<float>& area) const
void TextLayout::draw (Graphics& g, Rectangle<float> area) const
{
const Point<float> origin (justification.appliedToRectangle (Rectangle<float> (width, getHeight()), area).getPosition());
auto origin = justification.appliedToRectangle (Rectangle<float> (width, getHeight()), area).getPosition();
LowLevelGraphicsContext& context = g.getInternalContext();
auto& context = g.getInternalContext();
for (int i = 0; i < lines.size(); ++i)
for (auto* line : lines)
{
const Line& line = getLine (i);
const Point<float> lineOrigin (origin + line.lineOrigin);
auto lineOrigin = origin + line->lineOrigin;
for (int j = 0; j < line.runs.size(); ++j)
for (auto* run : line->runs)
{
const Run& run = *line.runs.getUnchecked (j);
context.setFont (run.font);
context.setFill (run.colour);
context.setFont (run->font);
context.setFill (run->colour);
for (int k = 0; k < run.glyphs.size(); ++k)
{
const Glyph& glyph = run.glyphs.getReference (k);
for (auto& glyph : run->glyphs)
context.drawGlyph (glyph.glyphCode, AffineTransform::translation (lineOrigin.x + glyph.anchor.x,
lineOrigin.y + glyph.anchor.y));
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);
}
const float lineThickness = run->font.getDescent() * 0.3f;
context.fillRect ({ runExtent.getStart() + lineOrigin.x, lineOrigin.y + lineThickness * 2.0f,
runExtent.getLength(), lineThickness });
}
}
}
@@ -287,7 +288,7 @@ namespace TextLayoutHelpers
{
struct Token
{
Token (const String& t, const Font& f, Colour c, const bool whitespace)
Token (const String& t, const Font& f, Colour c, bool whitespace)
: text (t), font (f), colour (c),
area (font.getStringWidthFloat (t), f.getHeight()),
isWhitespace (whitespace),
@@ -308,7 +309,7 @@ namespace TextLayoutHelpers
struct TokenList
{
TokenList() noexcept : totalLines (0) {}
TokenList() noexcept {}
void createLayout (const AttributedString& text, TextLayout& layout)
{
@@ -328,7 +329,7 @@ namespace TextLayoutHelpers
for (int i = 0; i < tokens.size(); ++i)
{
const Token& t = *tokens.getUnchecked (i);
auto& t = *tokens.getUnchecked (i);
Array<int> newGlyphs;
Array<float> xOffsets;
@@ -364,19 +365,7 @@ namespace TextLayoutHelpers
if (t.isWhitespace || t.isNewLine)
++charPosition;
const Token* const nextToken = tokens [i + 1];
if (nextToken == nullptr) // this is the last token
{
addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
currentLine->stringRange = Range<int> (lineStartPosition, charPosition);
if (! needToSetLineOrigin)
layout.addLine (currentLine.release());
needToSetLineOrigin = true;
}
else
if (auto* nextToken = tokens [i + 1])
{
if (t.font != nextToken->font || t.colour != nextToken->colour)
{
@@ -400,6 +389,16 @@ namespace TextLayoutHelpers
needToSetLineOrigin = true;
}
}
else
{
addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
currentLine->stringRange = Range<int> (lineStartPosition, charPosition);
if (! needToSetLineOrigin)
layout.addLine (currentLine.release());
needToSetLineOrigin = true;
}
}
if ((text.getJustification().getFlags() & (Justification::right | Justification::horizontallyCentred)) != 0)
@@ -423,7 +422,7 @@ namespace TextLayoutHelpers
static void addRun (TextLayout::Line& glyphLine, TextLayout::Run* glyphRun,
const Token& t, const int start, const int end)
{
glyphRun->stringRange = Range<int> (start, end);
glyphRun->stringRange = { start, end };
glyphRun->font = t.font;
glyphRun->colour = t.colour;
glyphLine.ascent = jmax (glyphLine.ascent, t.font.getAscent());
@@ -441,7 +440,7 @@ namespace TextLayoutHelpers
void appendText (const String& stringText, const Font& font, Colour colour)
{
String::CharPointerType t (stringText.getCharPointer());
auto t = stringText.getCharPointer();
String currentString;
int lastCharType = 0;
@@ -483,13 +482,13 @@ namespace TextLayoutHelpers
for (i = 0; i < tokens.size(); ++i)
{
Token& t = *tokens.getUnchecked(i);
auto& t = *tokens.getUnchecked(i);
t.area.setPosition (x, y);
t.line = totalLines;
x += t.area.getWidth();
h = jmax (h, t.area.getHeight() + extraLineSpacing);
const Token* const nextTok = tokens[i + 1];
auto* nextTok = tokens[i + 1];
if (nextTok == nullptr)
break;
@@ -514,7 +513,7 @@ namespace TextLayoutHelpers
{
while (--i >= 0)
{
Token& tok = *tokens.getUnchecked (i);
auto& tok = *tokens.getUnchecked (i);
if (tok.line == totalLines)
tok.lineHeight = height;
@@ -530,7 +529,7 @@ namespace TextLayoutHelpers
for (int i = 0; i < numAttributes; ++i)
{
const AttributedString::Attribute& attr = text.getAttribute (i);
auto& attr = text.getAttribute (i);
appendText (text.getText().substring (attr.range.getStart(), attr.range.getEnd()),
attr.font, attr.colour);
@@ -539,7 +538,8 @@ namespace TextLayoutHelpers
static String getTrimmedEndIfNotAllWhitespace (const String& s)
{
String trimmed (s.trimEnd());
auto trimmed = s.trimEnd();
if (trimmed.isEmpty() && s.isNotEmpty())
trimmed = s.replaceCharacters ("\r\n\t", " ");
@@ -547,7 +547,7 @@ namespace TextLayoutHelpers
}
OwnedArray<Token> tokens;
int totalLines;
int totalLines = 0;
JUCE_DECLARE_NON_COPYABLE (TokenList)
};
@@ -562,15 +562,15 @@ void TextLayout::createStandardLayout (const AttributedString& text)
void TextLayout::recalculateSize()
{
if (lines.size() > 0)
if (! lines.isEmpty())
{
Rectangle<float> bounds (lines.getFirst()->getLineBounds());
auto bounds = lines.getFirst()->getLineBounds();
for (int i = lines.size(); --i > 0;)
bounds = bounds.getUnion (lines.getUnchecked(i)->getLineBounds());
for (auto* line : lines)
bounds = bounds.getUnion (line->getLineBounds());
for (int i = lines.size(); --i >= 0;)
lines.getUnchecked(i)->lineOrigin.x -= bounds.getX();
for (auto* line : lines)
line->lineOrigin.x -= bounds.getX();
width = bounds.getWidth();
height = bounds.getHeight();


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

@@ -81,7 +81,7 @@ public:
The position of the text within the rectangle is controlled by the justification
flags set in the original AttributedString that was used to create this layout.
*/
void draw (Graphics&, const Rectangle<float>& area) const;
void draw (Graphics&, Rectangle<float> area) const;
//==============================================================================
/** A positioned glyph. */


Loading…
Cancel
Save