diff --git a/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp b/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp index f481573817..5f88d0c0a1 100644 --- a/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp +++ b/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp @@ -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 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 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 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 diff --git a/modules/juce_graphics/fonts/juce_TextLayout.cpp b/modules/juce_graphics/fonts/juce_TextLayout.cpp index 550b02ff9a..3d1c3cb890 100644 --- a/modules/juce_graphics/fonts/juce_TextLayout.cpp +++ b/modules/juce_graphics/fonts/juce_TextLayout.cpp @@ -48,7 +48,7 @@ TextLayout::Run::Run() noexcept { } -TextLayout::Run::Run (Range range, const int numGlyphsToPreallocate) +TextLayout::Run::Run (Range range, int numGlyphsToPreallocate) : colour (0xff000000), stringRange (range) { glyphs.ensureStorageAllocated (numGlyphsToPreallocate); @@ -94,31 +94,20 @@ Range TextLayout::Line::getLineBoundsX() const noexcept Range 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 runRange (glyph.anchor.x, glyph.anchor.x + glyph.width); if (isFirst) { isFirst = false; - range = Range (minX, maxX); + range = runRange; } else { - range = range.getUnionWith (Range (minX, maxX)); + range = range.getUnionWith (runRange); } } } @@ -134,10 +123,10 @@ Range TextLayout::Line::getLineBoundsY() const noexcept Rectangle TextLayout::Line::getLineBounds() const noexcept { - const Range x (getLineBoundsX()), - y (getLineBoundsY()); + auto x = getLineBoundsX(); + auto y = getLineBoundsY(); - return Rectangle (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& area) const +void TextLayout::draw (Graphics& g, Rectangle area) const { - const Point origin (justification.appliedToRectangle (Rectangle (width, getHeight()), area).getPosition()); + auto origin = justification.appliedToRectangle (Rectangle (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 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 runExtent; + + for (auto& glyph : run->glyphs) + { + Range 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 newGlyphs; Array 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 (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 (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 (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 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 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(); diff --git a/modules/juce_graphics/fonts/juce_TextLayout.h b/modules/juce_graphics/fonts/juce_TextLayout.h index 24d2949d6d..b5a308a252 100644 --- a/modules/juce_graphics/fonts/juce_TextLayout.h +++ b/modules/juce_graphics/fonts/juce_TextLayout.h @@ -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& area) const; + void draw (Graphics&, Rectangle area) const; //============================================================================== /** A positioned glyph. */