TextHeightBehavior implemented

Bug: skia:10201
Change-Id: I5398836d2068164282bab77fe8448654a72050d7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/286456
Commit-Queue: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
Julia Lavrova 2020-04-30 11:31:25 -04:00 committed by Skia Commit-Bot
parent 1ff415d5a1
commit 9588a643d9
7 changed files with 63 additions and 0 deletions

View File

@ -126,6 +126,13 @@ enum class TextBaseline {
kIdeographic,
};
enum TextHeightBehavior {
kAll = 0x0,
kDisableFirstAscent = 0x1,
kDisableLastDescent = 0x2,
kDisableAll = 0x1 | 0x2,
};
} // namespace textlayout
} // namespace skia

View File

@ -91,6 +91,10 @@ struct ParagraphStyle {
SkScalar getHeight() const { return fHeight; }
void setHeight(SkScalar height) { fHeight = height; }
TextHeightBehavior getTextHeightBehavior() const { return fTextHeightBehavior; }
void setTextHeightBehavior(TextHeightBehavior v) { fTextHeightBehavior = v; }
bool unlimited_lines() const {
return fLinesLimit == std::numeric_limits<size_t>::max();
}
@ -107,6 +111,7 @@ private:
size_t fLinesLimit;
SkString fEllipsis;
SkScalar fHeight;
TextHeightBehavior fTextHeightBehavior;
bool fHintingIsOn;
};
} // namespace textlayout

View File

@ -430,6 +430,7 @@ void ParagraphImpl::breakShapedTextIntoLines(SkScalar maxWidth) {
fLongestLine = std::max(fLongestLine, nearlyZero(advance.fX) ? widthWithSpaces : advance.fX);
});
fHeight = textWrapper.height();
fWidth = maxWidth;
fMaxIntrinsicWidth = textWrapper.maxIntrinsicWidth();
@ -437,6 +438,26 @@ void ParagraphImpl::breakShapedTextIntoLines(SkScalar maxWidth) {
fAlphabeticBaseline = fLines.empty() ? fEmptyMetrics.alphabeticBaseline() : fLines.front().alphabeticBaseline();
fIdeographicBaseline = fLines.empty() ? fEmptyMetrics.ideographicBaseline() : fLines.front().ideographicBaseline();
fExceededMaxLines = textWrapper.exceededMaxLines();
// Correct the first and the last line ascents/descents if required
if ((fParagraphStyle.getTextHeightBehavior() & TextHeightBehavior::kDisableFirstAscent) != 0) {
auto& firstLine = fLines.front();
auto delta = firstLine.metricsWithoutMultiplier(TextHeightBehavior::kDisableFirstAscent);
if (!SkScalarNearlyZero(delta)) {
fHeight += delta;
// Shift all the lines up
for (auto& line : fLines) {
line.shiftVertically(delta);
}
}
}
if ((fParagraphStyle.getTextHeightBehavior() & TextHeightBehavior::kDisableLastDescent) != 0) {
auto& lastLine = fLines.back();
auto delta = lastLine.metricsWithoutMultiplier(TextHeightBehavior::kDisableLastDescent);
// It's the last line. There is nothing below to shift
fHeight += delta;
}
}
void ParagraphImpl::formatLines(SkScalar maxWidth) {

View File

@ -21,6 +21,7 @@ ParagraphStyle::ParagraphStyle() {
fTextDirection = TextDirection::kLtr;
fLinesLimit = std::numeric_limits<size_t>::max();
fHeight = 1;
fTextHeightBehavior = TextHeightBehavior::kAll;
fHintingIsOn = true;
}

View File

@ -81,6 +81,8 @@ public:
}
SkVector offset() const { return fOffset; }
SkScalar ascent() const { return fFontMetrics.fAscent; }
SkScalar descent() const { return fFontMetrics.fDescent; }
SkScalar leading() const { return fFontMetrics.fLeading; }
SkScalar correctAscent() const {
if (fHeightMultiplier == 0) {
@ -417,6 +419,7 @@ public:
SkScalar descent() const { return fDescent; }
SkScalar leading() const { return fLeading; }
void setForceStrut(bool value) { fForceStrut = value; }
bool getForceStrut() const { return fForceStrut; }
private:

View File

@ -305,6 +305,29 @@ SkRect TextLine::extendHeight(const ClipContext& context) const {
return result;
}
SkScalar TextLine::metricsWithoutMultiplier(TextHeightBehavior correction) {
if (this->fSizes.getForceStrut()) {
return 0;
}
InternalLineMetrics result;
this->iterateThroughVisualRuns(true,
[&result](const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width) {
InternalLineMetrics runMetrics(run->ascent(), run->descent(), run->leading());
result.add(runMetrics);
return true;
});
SkScalar delta = 0;
if (correction == TextHeightBehavior::kDisableFirstAscent) {
delta += (this->fSizes.ascent() - result.ascent());
} else if (correction == TextHeightBehavior::kDisableLastDescent) {
delta -= (this->fSizes.descent() - result.descent());
}
fAdvance.fY += delta;
return delta;
}
void TextLine::paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const {
if (context.run->placeholderStyle() != nullptr) {

View File

@ -103,6 +103,9 @@ public:
SkRect extendHeight(const ClipContext& context) const;
SkScalar metricsWithoutMultiplier(TextHeightBehavior correction);
void shiftVertically(SkScalar shift) { fOffset.fY += shift; }
private:
Run* shapeEllipsis(const SkString& ellipsis, Run* run);