void GlyphArrangement::justifyGlyphs (const int startIndex, const int num, const float x, const float y, const float width, const float height, const Justification& justification) { jassert (num >= 0 && startIndex >= 0); if (glyphs.size() > 0 && num > 0) { const Rectangle<float> bb (getBoundingBox (startIndex, num, ! justification.testFlags (Justification::horizontallyJustified | Justification::horizontallyCentred))); float deltaX = 0.0f; if (justification.testFlags (Justification::horizontallyJustified)) deltaX = x - bb.getX(); else if (justification.testFlags (Justification::horizontallyCentred)) deltaX = x + (width - bb.getWidth()) * 0.5f - bb.getX(); else if (justification.testFlags (Justification::right)) deltaX = (x + width) - bb.getRight(); else deltaX = x - bb.getX(); float deltaY = 0.0f; if (justification.testFlags (Justification::top)) deltaY = y - bb.getY(); else if (justification.testFlags (Justification::bottom)) deltaY = (y + height) - bb.getBottom(); else deltaY = y + (height - bb.getHeight()) * 0.5f - bb.getY(); moveRangeOfGlyphs (startIndex, num, deltaX, deltaY); if (justification.testFlags (Justification::horizontallyJustified)) { int lineStart = 0; float baseY = glyphs.getUnchecked (startIndex)->getBaselineY(); int i; for (i = 0; i < num; ++i) { const float glyphY = glyphs.getUnchecked (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::addJustifiedText (const Font& font, const String& text, float x, float y, const float maxLineWidth, Justification horizontalLayout) { int lineStartIndex = glyphs.size(); addLineOfText (font, text, x, y); const float originalY = y; while (lineStartIndex < glyphs.size()) { int i = lineStartIndex; if (glyphs.getReference(i).getCharacter() != '\n' && glyphs.getReference(i).getCharacter() != '\r') ++i; const float lineMaxX = glyphs.getReference (lineStartIndex).getLeft() + maxLineWidth; int lastWordBreakIndex = -1; while (i < glyphs.size()) { const PositionedGlyph& pg = glyphs.getReference (i); const juce_wchar 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; } const float currentLineStartX = glyphs.getReference (lineStartIndex).getLeft(); float 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(); } }