| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
 -    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
 - 
 -    End User License Agreement: www.juce.com/juce-6-licence
 -    Privacy Policy: www.juce.com/juce-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - PositionedGlyph::PositionedGlyph() noexcept
 -     : character (0), glyph (0), x (0), y (0), w (0), whitespace (false)
 - {
 - }
 - 
 - PositionedGlyph::PositionedGlyph (const Font& font_, juce_wchar character_, int glyphNumber,
 -                                   float anchorX, float baselineY, float width, bool whitespace_)
 -     : font (font_), character (character_), glyph (glyphNumber),
 -       x (anchorX), y (baselineY), w (width), whitespace (whitespace_)
 - {
 - }
 - 
 - PositionedGlyph::~PositionedGlyph() {}
 - 
 - static void drawGlyphWithFont (Graphics& g, int glyph, const Font& font, AffineTransform t)
 - {
 -     auto& context = g.getInternalContext();
 -     context.setFont (font);
 -     context.drawGlyph (glyph, t);
 - }
 - 
 - void PositionedGlyph::draw (Graphics& g) const
 - {
 -     if (! isWhitespace())
 -         drawGlyphWithFont (g, glyph, font, AffineTransform::translation (x, y));
 - }
 - 
 - void PositionedGlyph::draw (Graphics& g, AffineTransform transform) const
 - {
 -     if (! isWhitespace())
 -         drawGlyphWithFont (g, glyph, font, AffineTransform::translation (x, y).followedBy (transform));
 - }
 - 
 - void PositionedGlyph::createPath (Path& path) const
 - {
 -     if (! isWhitespace())
 -     {
 -         if (auto* t = font.getTypeface())
 -         {
 -             Path p;
 -             t->getOutlineForGlyph (glyph, p);
 - 
 -             path.addPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight())
 -                                              .translated (x, y));
 -         }
 -     }
 - }
 - 
 - bool PositionedGlyph::hitTest (float px, float py) const
 - {
 -     if (getBounds().contains (px, py) && ! isWhitespace())
 -     {
 -         if (auto* t = font.getTypeface())
 -         {
 -             Path p;
 -             t->getOutlineForGlyph (glyph, p);
 - 
 -             AffineTransform::translation (-x, -y)
 -                             .scaled (1.0f / (font.getHeight() * font.getHorizontalScale()), 1.0f / font.getHeight())
 -                             .transformPoint (px, py);
 - 
 -             return p.contains (px, py);
 -         }
 -     }
 - 
 -     return false;
 - }
 - 
 - void PositionedGlyph::moveBy (float deltaX, float deltaY)
 - {
 -     x += deltaX;
 -     y += deltaY;
 - }
 - 
 - 
 - //==============================================================================
 - GlyphArrangement::GlyphArrangement()
 - {
 -     glyphs.ensureStorageAllocated (128);
 - }
 - 
 - //==============================================================================
 - void GlyphArrangement::clear()
 - {
 -     glyphs.clear();
 - }
 - 
 - PositionedGlyph& GlyphArrangement::getGlyph (int index) noexcept
 - {
 -     return glyphs.getReference (index);
 - }
 - 
 - //==============================================================================
 - void GlyphArrangement::addGlyphArrangement (const GlyphArrangement& other)
 - {
 -     glyphs.addArray (other.glyphs);
 - }
 - 
 - void GlyphArrangement::addGlyph (const PositionedGlyph& glyph)
 - {
 -     glyphs.add (glyph);
 - }
 - 
 - void GlyphArrangement::removeRangeOfGlyphs (int startIndex, int num)
 - {
 -     glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : num);
 - }
 - 
 - //==============================================================================
 - void GlyphArrangement::addLineOfText (const Font& font, const String& text, float xOffset, float yOffset)
 - {
 -     addCurtailedLineOfText (font, text, xOffset, yOffset, 1.0e10f, false);
 - }
 - 
 - void GlyphArrangement::addCurtailedLineOfText (const Font& font, const String& text,
 -                                                float xOffset, float yOffset,
 -                                                float maxWidthPixels, bool useEllipsis)
 - {
 -     if (text.isNotEmpty())
 -     {
 -         Array<int> newGlyphs;
 -         Array<float> xOffsets;
 -         font.getGlyphPositions (text, newGlyphs, xOffsets);
 -         auto textLen = newGlyphs.size();
 -         glyphs.ensureStorageAllocated (glyphs.size() + textLen);
 - 
 -         auto t = text.getCharPointer();
 - 
 -         for (int i = 0; i < textLen; ++i)
 -         {
 -             auto nextX = xOffsets.getUnchecked (i + 1);
 - 
 -             if (nextX > maxWidthPixels + 1.0f)
 -             {
 -                 // curtail the string if it's too wide..
 -                 if (useEllipsis && textLen > 3 && glyphs.size() >= 3)
 -                     insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size());
 - 
 -                 break;
 -             }
 - 
 -             auto thisX = xOffsets.getUnchecked (i);
 -             bool isWhitespace = t.isWhitespace();
 - 
 -             glyphs.add (PositionedGlyph (font, t.getAndAdvance(),
 -                                          newGlyphs.getUnchecked(i),
 -                                          xOffset + thisX, yOffset,
 -                                          nextX - thisX, isWhitespace));
 -         }
 -     }
 - }
 - 
 - int GlyphArrangement::insertEllipsis (const Font& font, float maxXPos, int startIndex, int endIndex)
 - {
 -     int numDeleted = 0;
 - 
 -     if (! glyphs.isEmpty())
 -     {
 -         Array<int> dotGlyphs;
 -         Array<float> dotXs;
 -         font.getGlyphPositions ("..", dotGlyphs, dotXs);
 - 
 -         auto dx = dotXs[1];
 -         float xOffset = 0.0f, yOffset = 0.0f;
 - 
 -         while (endIndex > startIndex)
 -         {
 -             auto& pg = glyphs.getReference (--endIndex);
 -             xOffset = pg.x;
 -             yOffset = pg.y;
 - 
 -             glyphs.remove (endIndex);
 -             ++numDeleted;
 - 
 -             if (xOffset + dx * 3 <= maxXPos)
 -                 break;
 -         }
 - 
 -         for (int i = 3; --i >= 0;)
 -         {
 -             glyphs.insert (endIndex++, PositionedGlyph (font, '.', dotGlyphs.getFirst(),
 -                                                         xOffset, yOffset, dx, false));
 -             --numDeleted;
 -             xOffset += dx;
 - 
 -             if (xOffset > maxXPos)
 -                 break;
 -         }
 -     }
 - 
 -     return numDeleted;
 - }
 - 
 - void GlyphArrangement::addJustifiedText (const Font& font, const String& text,
 -                                          float x, float y, float maxLineWidth,
 -                                          Justification horizontalLayout,
 -                                          float leading)
 - {
 -     auto lineStartIndex = glyphs.size();
 -     addLineOfText (font, text, x, y);
 - 
 -     auto originalY = y;
 - 
 -     while (lineStartIndex < glyphs.size())
 -     {
 -         int i = lineStartIndex;
 - 
 -         if (glyphs.getReference(i).getCharacter() != '\n'
 -               && glyphs.getReference(i).getCharacter() != '\r')
 -             ++i;
 - 
 -         auto lineMaxX = glyphs.getReference (lineStartIndex).getLeft() + maxLineWidth;
 -         int lastWordBreakIndex = -1;
 - 
 -         while (i < glyphs.size())
 -         {
 -             auto& pg = glyphs.getReference (i);
 -             auto c = pg.getCharacter();
 - 
 -             if (c == '\r' || c == '\n')
 -             {
 -                 ++i;
 - 
 -                 if (c == '\r' && i < glyphs.size()
 -                      && glyphs.getReference(i).getCharacter() == '\n')
 -                     ++i;
 - 
 -                 break;
 -             }
 - 
 -             if (pg.isWhitespace())
 -             {
 -                 lastWordBreakIndex = i + 1;
 -             }
 -             else if (pg.getRight() - 0.0001f >= lineMaxX)
 -             {
 -                 if (lastWordBreakIndex >= 0)
 -                     i = lastWordBreakIndex;
 - 
 -                 break;
 -             }
 - 
 -             ++i;
 -         }
 - 
 -         auto currentLineStartX = glyphs.getReference (lineStartIndex).getLeft();
 -         auto currentLineEndX = currentLineStartX;
 - 
 -         for (int j = i; --j >= lineStartIndex;)
 -         {
 -             if (! glyphs.getReference (j).isWhitespace())
 -             {
 -                 currentLineEndX = glyphs.getReference (j).getRight();
 -                 break;
 -             }
 -         }
 - 
 -         float deltaX = 0.0f;
 - 
 -         if (horizontalLayout.testFlags (Justification::horizontallyJustified))
 -             spreadOutLine (lineStartIndex, i - lineStartIndex, maxLineWidth);
 -         else if (horizontalLayout.testFlags (Justification::horizontallyCentred))
 -             deltaX = (maxLineWidth - (currentLineEndX - currentLineStartX)) * 0.5f;
 -         else if (horizontalLayout.testFlags (Justification::right))
 -             deltaX = maxLineWidth - (currentLineEndX - currentLineStartX);
 - 
 -         moveRangeOfGlyphs (lineStartIndex, i - lineStartIndex,
 -                            x + deltaX - currentLineStartX, y - originalY);
 - 
 -         lineStartIndex = i;
 - 
 -         y += font.getHeight() + leading;
 -     }
 - }
 - 
 - void GlyphArrangement::addFittedText (const Font& f, const String& text,
 -                                       float x, float y, float width, float height,
 -                                       Justification layout, int maximumLines,
 -                                       float minimumHorizontalScale)
 - {
 -     if (minimumHorizontalScale == 0.0f)
 -         minimumHorizontalScale = Font::getDefaultMinimumHorizontalScaleFactor();
 - 
 -     // doesn't make much sense if this is outside a sensible range of 0.5 to 1.0
 -     jassert (minimumHorizontalScale > 0 && minimumHorizontalScale <= 1.0f);
 - 
 -     if (text.containsAnyOf ("\r\n"))
 -     {
 -         addLinesWithLineBreaks (text, f, x, y, width, height, layout);
 -     }
 -     else
 -     {
 -         auto startIndex = glyphs.size();
 -         auto trimmed = text.trim();
 -         addLineOfText (f, trimmed, x, y);
 -         auto numGlyphs = glyphs.size() - startIndex;
 - 
 -         if (numGlyphs > 0)
 -         {
 -             auto lineWidth = glyphs.getReference (glyphs.size() - 1).getRight()
 -                                 - glyphs.getReference (startIndex).getLeft();
 - 
 -             if (lineWidth > 0)
 -             {
 -                 if (lineWidth * minimumHorizontalScale < width)
 -                 {
 -                     if (lineWidth > width)
 -                         stretchRangeOfGlyphs (startIndex, numGlyphs, width / lineWidth);
 - 
 -                     justifyGlyphs (startIndex, numGlyphs, x, y, width, height, layout);
 -                 }
 -                 else if (maximumLines <= 1)
 -                 {
 -                     fitLineIntoSpace (startIndex, numGlyphs, x, y, width, height,
 -                                       f, layout, minimumHorizontalScale);
 -                 }
 -                 else
 -                 {
 -                     splitLines (trimmed, f, startIndex, x, y, width, height,
 -                                 maximumLines, lineWidth, layout, minimumHorizontalScale);
 -                 }
 -             }
 -         }
 -     }
 - }
 - 
 - //==============================================================================
 - void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, const float dx, const float dy)
 - {
 -     jassert (startIndex >= 0);
 - 
 -     if (dx != 0.0f || dy != 0.0f)
 -     {
 -         if (num < 0 || startIndex + num > glyphs.size())
 -             num = glyphs.size() - startIndex;
 - 
 -         while (--num >= 0)
 -             glyphs.getReference (startIndex++).moveBy (dx, dy);
 -     }
 - }
 - 
 - void GlyphArrangement::addLinesWithLineBreaks (const String& text, const Font& f,
 -                                                float x, float y, float width, float height, Justification layout)
 - {
 -     GlyphArrangement ga;
 -     ga.addJustifiedText (f, text, x, y, width, layout);
 - 
 -     auto bb = ga.getBoundingBox (0, -1, false);
 -     auto dy = y - bb.getY();
 - 
 -     if (layout.testFlags (Justification::verticallyCentred))   dy += (height - bb.getHeight()) * 0.5f;
 -     else if (layout.testFlags (Justification::bottom))         dy += (height - bb.getHeight());
 - 
 -     ga.moveRangeOfGlyphs (0, -1, 0.0f, dy);
 - 
 -     glyphs.addArray (ga.glyphs);
 - }
 - 
 - int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font,
 -                                         Justification justification, float minimumHorizontalScale)
 - {
 -     int numDeleted = 0;
 -     auto lineStartX = glyphs.getReference (start).getLeft();
 -     auto lineWidth  = glyphs.getReference (start + numGlyphs - 1).getRight() - lineStartX;
 - 
 -     if (lineWidth > w)
 -     {
 -         if (minimumHorizontalScale < 1.0f)
 -         {
 -             stretchRangeOfGlyphs (start, numGlyphs, jmax (minimumHorizontalScale, w / lineWidth));
 -             lineWidth = glyphs.getReference (start + numGlyphs - 1).getRight() - lineStartX - 0.5f;
 -         }
 - 
 -         if (lineWidth > w)
 -         {
 -             numDeleted = insertEllipsis (font, lineStartX + w, start, start + numGlyphs);
 -             numGlyphs -= numDeleted;
 -         }
 -     }
 - 
 -     justifyGlyphs (start, numGlyphs, x, y, w, h, justification);
 -     return numDeleted;
 - }
 - 
 - void GlyphArrangement::stretchRangeOfGlyphs (int startIndex, int num, float horizontalScaleFactor)
 - {
 -     jassert (startIndex >= 0);
 - 
 -     if (num < 0 || startIndex + num > glyphs.size())
 -         num = glyphs.size() - startIndex;
 - 
 -     if (num > 0)
 -     {
 -         auto xAnchor = glyphs.getReference (startIndex).getLeft();
 - 
 -         while (--num >= 0)
 -         {
 -             auto& pg = glyphs.getReference (startIndex++);
 - 
 -             pg.x = xAnchor + (pg.x - xAnchor) * horizontalScaleFactor;
 -             pg.font.setHorizontalScale (pg.font.getHorizontalScale() * horizontalScaleFactor);
 -             pg.w *= horizontalScaleFactor;
 -         }
 -     }
 - }
 - 
 - Rectangle<float> GlyphArrangement::getBoundingBox (int startIndex, int num, bool includeWhitespace) const
 - {
 -     jassert (startIndex >= 0);
 - 
 -     if (num < 0 || startIndex + num > glyphs.size())
 -         num = glyphs.size() - startIndex;
 - 
 -     Rectangle<float> result;
 - 
 -     while (--num >= 0)
 -     {
 -         auto& pg = glyphs.getReference (startIndex++);
 - 
 -         if (includeWhitespace || ! pg.isWhitespace())
 -             result = result.getUnion (pg.getBounds());
 -     }
 - 
 -     return result;
 - }
 - 
 - void GlyphArrangement::justifyGlyphs (int startIndex, int num,
 -                                       float x, float y, float width, float height,
 -                                       Justification justification)
 - {
 -     jassert (num >= 0 && startIndex >= 0);
 - 
 -     if (glyphs.size() > 0 && num > 0)
 -     {
 -         auto bb = getBoundingBox (startIndex, num, ! justification.testFlags (Justification::horizontallyJustified
 -                                                                                | Justification::horizontallyCentred));
 -         float deltaX = x, deltaY = y;
 - 
 -         if (justification.testFlags (Justification::horizontallyJustified))     deltaX -= bb.getX();
 -         else if (justification.testFlags (Justification::horizontallyCentred))  deltaX += (width - bb.getWidth()) * 0.5f - bb.getX();
 -         else if (justification.testFlags (Justification::right))                deltaX += width - bb.getRight();
 -         else                                                                    deltaX -= bb.getX();
 - 
 -         if (justification.testFlags (Justification::top))                       deltaY -= bb.getY();
 -         else if (justification.testFlags (Justification::bottom))               deltaY += height - bb.getBottom();
 -         else                                                                    deltaY += (height - bb.getHeight()) * 0.5f - bb.getY();
 - 
 -         moveRangeOfGlyphs (startIndex, num, deltaX, deltaY);
 - 
 -         if (justification.testFlags (Justification::horizontallyJustified))
 -         {
 -             int lineStart = 0;
 -             auto baseY = glyphs.getReference (startIndex).getBaselineY();
 - 
 -             int i;
 -             for (i = 0; i < num; ++i)
 -             {
 -                 auto glyphY = glyphs.getReference (startIndex + i).getBaselineY();
 - 
 -                 if (glyphY != baseY)
 -                 {
 -                     spreadOutLine (startIndex + lineStart, i - lineStart, width);
 - 
 -                     lineStart = i;
 -                     baseY = glyphY;
 -                 }
 -             }
 - 
 -             if (i > lineStart)
 -                 spreadOutLine (startIndex + lineStart, i - lineStart, width);
 -         }
 -     }
 - }
 - 
 - void GlyphArrangement::spreadOutLine (int start, int num, float targetWidth)
 - {
 -     if (start + num < glyphs.size()
 -          && glyphs.getReference (start + num - 1).getCharacter() != '\r'
 -          && glyphs.getReference (start + num - 1).getCharacter() != '\n')
 -     {
 -         int numSpaces = 0;
 -         int spacesAtEnd = 0;
 - 
 -         for (int i = 0; i < num; ++i)
 -         {
 -             if (glyphs.getReference (start + i).isWhitespace())
 -             {
 -                 ++spacesAtEnd;
 -                 ++numSpaces;
 -             }
 -             else
 -             {
 -                 spacesAtEnd = 0;
 -             }
 -         }
 - 
 -         numSpaces -= spacesAtEnd;
 - 
 -         if (numSpaces > 0)
 -         {
 -             auto startX = glyphs.getReference (start).getLeft();
 -             auto endX   = glyphs.getReference (start + num - 1 - spacesAtEnd).getRight();
 - 
 -             auto extraPaddingBetweenWords = (targetWidth - (endX - startX)) / (float) numSpaces;
 -             float deltaX = 0.0f;
 - 
 -             for (int i = 0; i < num; ++i)
 -             {
 -                 glyphs.getReference (start + i).moveBy (deltaX, 0.0f);
 - 
 -                 if (glyphs.getReference (start + i).isWhitespace())
 -                     deltaX += extraPaddingBetweenWords;
 -             }
 -         }
 -     }
 - }
 - 
 - static bool isBreakableGlyph (const PositionedGlyph& g) noexcept
 - {
 -     return g.isWhitespace() || g.getCharacter() == '-';
 - }
 - 
 - void GlyphArrangement::splitLines (const String& text, Font font, int startIndex,
 -                                    float x, float y, float width, float height, int maximumLines,
 -                                    float lineWidth, Justification layout, float minimumHorizontalScale)
 - {
 -     auto length = text.length();
 -     auto originalStartIndex = startIndex;
 -     int numLines = 1;
 - 
 -     if (length <= 12 && ! text.containsAnyOf (" -\t\r\n"))
 -         maximumLines = 1;
 - 
 -     maximumLines = jmin (maximumLines, length);
 - 
 -     while (numLines < maximumLines)
 -     {
 -         ++numLines;
 -         auto newFontHeight = height / (float) numLines;
 - 
 -         if (newFontHeight < font.getHeight())
 -         {
 -             font.setHeight (jmax (8.0f, newFontHeight));
 - 
 -             removeRangeOfGlyphs (startIndex, -1);
 -             addLineOfText (font, text, x, y);
 - 
 -             lineWidth = glyphs.getReference (glyphs.size() - 1).getRight()
 -                             - glyphs.getReference (startIndex).getLeft();
 -         }
 - 
 -         // Try to estimate the point at which there are enough lines to fit the text,
 -         // allowing for unevenness in the lengths due to differently sized words.
 -         const float lineLengthUnevennessAllowance = 80.0f;
 - 
 -         if ((float) numLines > (lineWidth + lineLengthUnevennessAllowance) / width || newFontHeight < 8.0f)
 -             break;
 -     }
 - 
 -     if (numLines < 1)
 -         numLines = 1;
 - 
 -     int lineIndex = 0;
 -     auto lineY = y;
 -     auto widthPerLine = jmin (width / minimumHorizontalScale,
 -                               lineWidth / (float) numLines);
 - 
 -     while (lineY < y + height)
 -     {
 -         auto endIndex = startIndex;
 -         auto lineStartX = glyphs.getReference (startIndex).getLeft();
 -         auto lineBottomY = lineY + font.getHeight();
 - 
 -         if (lineIndex++ >= numLines - 1
 -              || lineBottomY >= y + height)
 -         {
 -             widthPerLine = width;
 -             endIndex = glyphs.size();
 -         }
 -         else
 -         {
 -             while (endIndex < glyphs.size())
 -             {
 -                 if (glyphs.getReference (endIndex).getRight() - lineStartX > widthPerLine)
 -                 {
 -                     // got to a point where the line's too long, so skip forward to find a
 -                     // good place to break it..
 -                     auto searchStartIndex = endIndex;
 - 
 -                     while (endIndex < glyphs.size())
 -                     {
 -                         auto& g = glyphs.getReference (endIndex);
 - 
 -                         if ((g.getRight() - lineStartX) * minimumHorizontalScale < width)
 -                         {
 -                             if (isBreakableGlyph (g))
 -                             {
 -                                 ++endIndex;
 -                                 break;
 -                             }
 -                         }
 -                         else
 -                         {
 -                             // can't find a suitable break, so try looking backwards..
 -                             endIndex = searchStartIndex;
 - 
 -                             for (int back = 1; back < jmin (7, endIndex - startIndex - 1); ++back)
 -                             {
 -                                 if (isBreakableGlyph (glyphs.getReference (endIndex - back)))
 -                                 {
 -                                     endIndex -= back - 1;
 -                                     break;
 -                                 }
 -                             }
 - 
 -                             break;
 -                         }
 - 
 -                         ++endIndex;
 -                     }
 - 
 -                     break;
 -                 }
 - 
 -                 ++endIndex;
 -             }
 - 
 -             auto wsStart = endIndex;
 -             auto wsEnd   = endIndex;
 - 
 -             while (wsStart > 0 && glyphs.getReference (wsStart - 1).isWhitespace())
 -                 --wsStart;
 - 
 -             while (wsEnd < glyphs.size() && glyphs.getReference (wsEnd).isWhitespace())
 -                 ++wsEnd;
 - 
 -             removeRangeOfGlyphs (wsStart, wsEnd - wsStart);
 -             endIndex = jmax (wsStart, startIndex + 1);
 -         }
 - 
 -         endIndex -= fitLineIntoSpace (startIndex, endIndex - startIndex,
 -                                       x, lineY, width, font.getHeight(), font,
 -                                       layout.getOnlyHorizontalFlags() | Justification::verticallyCentred,
 -                                       minimumHorizontalScale);
 - 
 -         startIndex = endIndex;
 -         lineY = lineBottomY;
 - 
 -         if (startIndex >= glyphs.size())
 -             break;
 -     }
 - 
 -     justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex,
 -                    x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified);
 - }
 - 
 - //==============================================================================
 - void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const PositionedGlyph& pg,
 -                                            int i, AffineTransform transform) const
 - {
 -     auto lineThickness = (pg.font.getDescent()) * 0.3f;
 -     auto nextX = pg.x + pg.w;
 - 
 -     if (i < glyphs.size() - 1 && glyphs.getReference (i + 1).y == pg.y)
 -         nextX = glyphs.getReference (i + 1).x;
 - 
 -     Path p;
 -     p.addRectangle (pg.x, pg.y + lineThickness * 2.0f, nextX - pg.x, lineThickness);
 -     g.fillPath (p, transform);
 - }
 - 
 - void GlyphArrangement::draw (const Graphics& g) const
 - {
 -     draw (g, {});
 - }
 - 
 - void GlyphArrangement::draw (const Graphics& g, AffineTransform transform) const
 - {
 -     auto& context = g.getInternalContext();
 -     auto lastFont = context.getFont();
 -     bool needToRestore = false;
 - 
 -     for (int i = 0; i < glyphs.size(); ++i)
 -     {
 -         auto& pg = glyphs.getReference (i);
 - 
 -         if (pg.font.isUnderlined())
 -             drawGlyphUnderline (g, pg, i, transform);
 - 
 -         if (! pg.isWhitespace())
 -         {
 -             if (lastFont != pg.font)
 -             {
 -                 lastFont = pg.font;
 - 
 -                 if (! needToRestore)
 -                 {
 -                     needToRestore = true;
 -                     context.saveState();
 -                 }
 - 
 -                 context.setFont (lastFont);
 -             }
 - 
 -             context.drawGlyph (pg.glyph, AffineTransform::translation (pg.x, pg.y)
 -                                                          .followedBy (transform));
 -         }
 -     }
 - 
 -     if (needToRestore)
 -         context.restoreState();
 - }
 - 
 - void GlyphArrangement::createPath (Path& path) const
 - {
 -     for (auto& g : glyphs)
 -         g.createPath (path);
 - }
 - 
 - int GlyphArrangement::findGlyphIndexAt (float x, float y) const
 - {
 -     for (int i = 0; i < glyphs.size(); ++i)
 -         if (glyphs.getReference (i).hitTest (x, y))
 -             return i;
 - 
 -     return -1;
 - }
 - 
 - } // namespace juce
 
 
  |