1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

TextEditor: Fix setLineSpacing

Applies the previously missed line spacing value of the TextEditor.

The changes in JustifiedText fix calculating the vertical position of
the first line for the case where ShapedTextOptions has the following
settings:

isBaselineAtZero() == false,
getHeight().has_value() == false
getLeading() > 1.0f

This case however is only triggered by the TextEditor, as with all
functions in GlyphArrangement at least one setting is different.
This commit is contained in:
attila 2025-04-22 15:39:58 +02:00 committed by Attila Szarvas
parent e23969f3ce
commit d2d5e9bdd2
3 changed files with 19 additions and 15 deletions

View file

@ -200,12 +200,12 @@ struct LineInfo
static float getCrossAxisStartingAnchor (Justification justification, static float getCrossAxisStartingAnchor (Justification justification,
Span<const LineInfo> lineInfos, Span<const LineInfo> lineInfos,
std::optional<float> height, std::optional<float> height,
float leadingInHeight) float leading)
{ {
if (lineInfos.empty()) if (lineInfos.empty())
return 0.0f; return 0.0f;
const auto minimumTop = lineInfos.front().maxAscent + lineInfos.front().lineHeight * leadingInHeight; const auto minimumTop = lineInfos.front().maxAscent * leading;
if (! height.has_value()) if (! height.has_value())
return minimumTop; return minimumTop;
@ -213,15 +213,14 @@ static float getCrossAxisStartingAnchor (Justification justification,
const auto textHeight = std::accumulate (lineInfos.begin(), const auto textHeight = std::accumulate (lineInfos.begin(),
lineInfos.end(), lineInfos.end(),
0.0f, 0.0f,
[] (auto acc, const auto info) { return acc + info.lineHeight; }); [leading] (auto acc, const auto info) { return acc + info.lineHeight * leading; });
if (justification.testFlags (Justification::verticallyCentred)) if (justification.testFlags (Justification::verticallyCentred))
return (*height - textHeight) / 2.0f + lineInfos.front().maxAscent; return (*height - textHeight) / 2.0f + lineInfos.front().maxAscent;
if (justification.testFlags (Justification::bottom)) if (justification.testFlags (Justification::bottom))
{ {
const auto bottomLeading = 0.5f * lineInfos.back().lineHeight * leadingInHeight; return *height - textHeight + lineInfos.front().maxAscent * leading;
return *height - textHeight - bottomLeading + lineInfos.front().maxAscent;
} }
return minimumTop; return minimumTop;
@ -230,8 +229,6 @@ static float getCrossAxisStartingAnchor (Justification justification,
JustifiedText::JustifiedText (const SimpleShapedText* t, const ShapedTextOptions& options) JustifiedText::JustifiedText (const SimpleShapedText* t, const ShapedTextOptions& options)
: shapedText (*t) : shapedText (*t)
{ {
const auto leading = options.getLeading() - 1.0f;
std::vector<LineInfo> lineInfos; std::vector<LineInfo> lineInfos;
for (const auto [range, lineNumber] : shapedText.getLineNumbersForGlyphRanges()) for (const auto [range, lineNumber] : shapedText.getLineNumbersForGlyphRanges())
@ -285,7 +282,7 @@ JustifiedText::JustifiedText (const SimpleShapedText* t, const ShapedTextOptions
: getCrossAxisStartingAnchor (options.getJustification(), : getCrossAxisStartingAnchor (options.getJustification(),
lineInfos, lineInfos,
options.getHeight(), options.getHeight(),
leading); options.getLeading());
detail::Ranges::Operations ops; detail::Ranges::Operations ops;
@ -297,16 +294,16 @@ JustifiedText::JustifiedText (const SimpleShapedText* t, const ShapedTextOptions
const auto range = lineNumber.range; const auto range = lineNumber.range;
const auto maxDescent = lineInfo.lineHeight - lineInfo.maxAscent; const auto maxDescent = lineInfo.lineHeight - lineInfo.maxAscent;
const auto nextLineTop = baseline + (1.0f + leading) * maxDescent + options.getAdditiveLineSpacing(); const auto nextLineTop = baseline + options.getLeading() * maxDescent + options.getAdditiveLineSpacing();
if (! top.has_value()) if (! top.has_value())
top = baseline - (1.0f + leading) * lineInfo.maxAscent; top = baseline - options.getLeading() * lineInfo.maxAscent;
lineMetricsForGlyphRange.set (range, lineMetricsForGlyphRange.set (range,
{ lineNumber.value, { lineNumber.value,
{ lineInfo.mainAxisLineAlignment.anchor, baseline }, { lineInfo.mainAxisLineAlignment.anchor, baseline },
lineInfo.maxAscent, lineInfo.maxAscent * options.getLeading(),
lineInfo.lineHeight - lineInfo.maxAscent, (lineInfo.lineHeight - lineInfo.maxAscent) * options.getLeading(),
lineInfo.mainAxisLineAlignment.effectiveLineLength lineInfo.mainAxisLineAlignment.effectiveLineLength
+ lineInfo.mainAxisLineAlignment.extraWhitespaceAdvance, + lineInfo.mainAxisLineAlignment.extraWhitespaceAdvance,
*top, *top,
@ -324,7 +321,7 @@ JustifiedText::JustifiedText (const SimpleShapedText* t, const ShapedTextOptions
ops.clear(); ops.clear();
const auto nextLineMaxAscent = lineIndex < (int) lineInfos.size() - 1 ? lineInfos[(size_t) lineIndex + 1].maxAscent : 0.0f; const auto nextLineMaxAscent = lineIndex < (int) lineInfos.size() - 1 ? lineInfos[(size_t) lineIndex + 1].maxAscent : 0.0f;
baseline = nextLineTop + (1.0f + leading) * nextLineMaxAscent; baseline = nextLineTop + options.getLeading() * nextLineMaxAscent;
top = nextLineTop; top = nextLineTop;
} }

View file

@ -377,6 +377,12 @@ void TextEditor::setJustification (Justification j)
} }
} }
void TextEditor::setLineSpacing (float newLineSpacing) noexcept
{
lineSpacing = jmax (1.0f, newLineSpacing);
updateBaseShapedTextOptions();
}
//============================================================================== //==============================================================================
void TextEditor::setFont (const Font& newFont) void TextEditor::setFont (const Font& newFont)
{ {
@ -924,7 +930,8 @@ TextEditor::CaretEdge TextEditor::getTextSelectionEdge (int index, Edge edge) co
void TextEditor::updateBaseShapedTextOptions() void TextEditor::updateBaseShapedTextOptions()
{ {
auto options = detail::ShapedText::Options{}.withTrailingWhitespacesShouldFit (true) auto options = detail::ShapedText::Options{}.withTrailingWhitespacesShouldFit (true)
.withJustification (getJustificationType().getOnlyHorizontalFlags()); .withJustification (getJustificationType().getOnlyHorizontalFlags())
.withLeading (lineSpacing);
if (wordWrap) if (wordWrap)
options = options.withMaxWidth ((float) getMaximumTextWidth()); options = options.withMaxWidth ((float) getMaximumTextWidth());

View file

@ -551,7 +551,7 @@ public:
The default (and minimum) value is 1.0 and values > 1.0 will increase the line spacing as a The default (and minimum) value is 1.0 and values > 1.0 will increase the line spacing as a
multiple of the line height e.g. for double-spacing call this method with an argument of 2.0. multiple of the line height e.g. for double-spacing call this method with an argument of 2.0.
*/ */
void setLineSpacing (float newLineSpacing) noexcept { lineSpacing = jmax (1.0f, newLineSpacing); } void setLineSpacing (float newLineSpacing) noexcept;
/** Returns the current line spacing of the TextEditor. */ /** Returns the current line spacing of the TextEditor. */
float getLineSpacing() const noexcept { return lineSpacing; } float getLineSpacing() const noexcept { return lineSpacing; }