Correct line metric style for the first/last lines
Bug: skia:13767
Change-Id: Ib94df2bd1ceb981e442ce5ee2f568a51f2fbc000
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/587676
Commit-Queue: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/skparagraph/samples/SampleParagraph.cpp b/modules/skparagraph/samples/SampleParagraph.cpp
index 6e95088..d341d6b 100644
--- a/modules/skparagraph/samples/SampleParagraph.cpp
+++ b/modules/skparagraph/samples/SampleParagraph.cpp
@@ -3818,6 +3818,100 @@
using INHERITED = Sample;
};
+class ParagraphViewLast : public ParagraphView_Base {
+protected:
+ SkString name() override { return SkString("ParagraphViewLast"); }
+ void onDrawContent(SkCanvas* canvas) override {
+ canvas->drawColor(SK_ColorWHITE);
+ auto fontCollection = getFontCollection();
+ fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
+ fontCollection->enableFontFallback();
+ ParagraphStyle paragraph_style;
+ paragraph_style.setTextDirection(TextDirection::kLtr);
+ TextStyle text_style;
+ text_style.setColor(SK_ColorBLACK);
+ text_style.setFontFamilies({SkString("Roboto")});
+ text_style.setFontSize(14.0);
+ SkPaint paint;
+ paint.setColor(SK_ColorBLUE);
+ //text_style.setBackgroundColor(paint);
+ TextStyle text_style1;
+ text_style1.setColor(SK_ColorBLACK);
+ text_style1.setFontFamilies({SkString("Roboto")});
+ text_style1.setFontSize(30);
+ text_style1.setHeight(3.0);
+ text_style1.setHeightOverride(true);
+ //paint.setColor(SK_ColorRED);
+ text_style1.setDecorationStyle(TextDecorationStyle::kSolid);
+ text_style1.setDecorationColor(SK_ColorRED);
+ //text_style1.setBackgroundColor(paint);
+ StrutStyle strut_style;
+ strut_style.setFontSize(30);
+ strut_style.setHeight(3.0);
+ strut_style.setHeightOverride(true);
+ strut_style.setFontFamilies({SkString("Roboto")});
+
+ auto draw = [&](const char* text, bool test = false) {
+ if (test) {
+ paragraph_style.setTextHeightBehavior(TextHeightBehavior::kDisableAll);
+ strut_style.setStrutEnabled(true);
+ paragraph_style.setStrutStyle(strut_style);
+ } else {
+ paragraph_style.setTextHeightBehavior(TextHeightBehavior::kAll);
+ strut_style.setStrutEnabled(false);
+ paragraph_style.setStrutStyle(strut_style);
+ }
+ ParagraphBuilderImpl builder(paragraph_style, fontCollection);
+ if (test) {
+ if (text[0] == 'u') {
+ text_style1.setDecoration(TextDecoration::kUnderline);
+ } else if (text[0] == 'o') {
+ text_style1.setDecoration(TextDecoration::kOverline);
+ text_style1.setDecorationColor(SK_ColorGREEN);
+ } else if (text[0] == 's') {
+ text_style1.setDecoration(TextDecoration::kLineThrough);
+ } else {
+ text_style1.setDecoration(TextDecoration::kNoDecoration);
+ }
+ builder.pushStyle(text_style1);
+ } else {
+ builder.pushStyle(text_style);
+ }
+ builder.addText(text);
+ builder.pop();
+ auto paragraph = builder.Build();
+ paragraph->layout(width());
+ paragraph->paint(canvas, 0, 0);
+ if (test) {
+ /*
+ auto boxes = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight);
+ for (auto& box : boxes) {
+ SkPaint paint;
+ paint.setColor(SK_ColorGREEN);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(2);
+ canvas->drawRect(box.rect, paint);
+ }
+ */
+ }
+ canvas->translate(0, paragraph->getHeight());
+ };
+
+ draw("+++++++++++++++++++");
+ draw("AAA\nBBB\nCCC", true);
+ draw("===================");
+ draw("underline\nBBB\nCCC", true);
+ draw("===================");
+ draw("strike\nBBB\nCCC", true);
+ draw("===================");
+ draw("overline\nBBB\nCCC", true);
+ draw("===================");
+ }
+private:
+ using INHERITED = Sample;
+};
+
} // namespace
//////////////////////////////////////////////////////////////////////////////
@@ -3885,4 +3979,4 @@
DEF_SAMPLE(return new ParagraphView64();)
DEF_SAMPLE(return new ParagraphView65();)
DEF_SAMPLE(return new ParagraphView66();)
-
+DEF_SAMPLE(return new ParagraphViewLast();)
diff --git a/modules/skparagraph/src/Decorations.cpp b/modules/skparagraph/src/Decorations.cpp
index 9d4c2e5..f9e5fa9 100644
--- a/modules/skparagraph/src/Decorations.cpp
+++ b/modules/skparagraph/src/Decorations.cpp
@@ -33,7 +33,10 @@
continue;
}
- calculatePosition(decoration, context.run->correctAscent());
+ calculatePosition(decoration,
+ decoration == TextDecoration::kOverline
+ ? context.run->correctAscent() - context.run->ascent()
+ : context.run->correctAscent());
calculatePaint(textStyle);
@@ -165,7 +168,7 @@
fPosition -= ascent;
break;
case TextDecoration::kOverline:
- fPosition = 0;
+ fPosition = - ascent;
break;
case TextDecoration::kLineThrough: {
fPosition = (fFontMetrics.fFlags & SkFontMetrics::FontMetricsFlags::kStrikeoutPositionIsValid_Flag)
diff --git a/modules/skparagraph/src/TextLine.cpp b/modules/skparagraph/src/TextLine.cpp
index 327112c..c2cdd28 100644
--- a/modules/skparagraph/src/TextLine.cpp
+++ b/modules/skparagraph/src/TextLine.cpp
@@ -458,7 +458,7 @@
SkAutoCanvasRestore acr(canvas, true);
canvas->translate(x + this->offset().fX, y + this->offset().fY + style.getBaselineShift());
Decorations decorations;
- SkScalar correctedBaseline = SkScalarFloorToScalar(this->baseline() + style.getBaselineShift() + 0.5);
+ SkScalar correctedBaseline = SkScalarFloorToScalar(-this->sizes().rawAscent() + style.getBaselineShift() + 0.5);
decorations.paint(canvas, style, context, correctedBaseline);
}
@@ -909,10 +909,21 @@
StyleType styleType,
const RunStyleVisitor& visitor) const {
+ auto correctContext = [&](TextRange textRange, SkScalar textOffsetInRun) -> ClipContext {
+ auto result = this->measureTextInsideOneRun(
+ textRange, run, runOffset, textOffsetInRun, false, true);
+ if (styleType == StyleType::kDecorations) {
+ result.clip.fTop = this->sizes().runTop(run, LineMetricStyle::CSS);
+ result.clip.fBottom =
+ result.clip.fTop +
+ run->calculateHeight(LineMetricStyle::CSS, LineMetricStyle::CSS);
+ }
+ return result;
+ };
+
if (run->fEllipsis) {
// Extra efforts to get the ellipsis text style
- ClipContext clipContext = this->measureTextInsideOneRun(run->textRange(), run, runOffset,
- 0, false, true);
+ ClipContext clipContext = correctContext(run->textRange(), 0.0f);
TextRange testRange(run->fClusterStart, run->fClusterStart + run->textRange().width());
for (BlockIndex index = fBlockRange.start; index < fBlockRange.end; ++index) {
auto block = fOwner->styles().begin() + index;
@@ -926,8 +937,7 @@
}
if (styleType == StyleType::kNone) {
- ClipContext clipContext = this->measureTextInsideOneRun(textRange, run, runOffset,
- 0, false, true);
+ ClipContext clipContext = correctContext(textRange, 0.0f);
if (clipContext.clip.height() > 0) {
visitor(textRange, TextStyle(), clipContext);
return clipContext.clip.width();
@@ -986,9 +996,7 @@
// We have the style and the text
auto runStyleTextRange = TextRange(start, start + size);
- // Measure the text
- ClipContext clipContext = this->measureTextInsideOneRun(runStyleTextRange, run, runOffset,
- textOffsetInRun, false, true);
+ ClipContext clipContext = correctContext(runStyleTextRange, textOffsetInRun);
textOffsetInRun += clipContext.clip.width();
if (clipContext.clip.height() == 0) {
continue;
@@ -1106,11 +1114,11 @@
return result;
}
-bool TextLine::isFirstLine() {
+bool TextLine::isFirstLine() const {
return this == &fOwner->lines().front();
}
-bool TextLine::isLastLine() {
+bool TextLine::isLastLine() const {
return this == &fOwner->lines().back();
}
diff --git a/modules/skparagraph/src/TextLine.h b/modules/skparagraph/src/TextLine.h
index c74fe46..3f15853 100644
--- a/modules/skparagraph/src/TextLine.h
+++ b/modules/skparagraph/src/TextLine.h
@@ -98,8 +98,8 @@
void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
- bool isFirstLine();
- bool isLastLine();
+ bool isFirstLine() const;
+ bool isLastLine() const;
void getRectsForRange(TextRange textRange, RectHeightStyle rectHeightStyle, RectWidthStyle rectWidthStyle, std::vector<TextBox>& boxes);
void getRectsForPlaceholders(std::vector<TextBox>& boxes);
PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx);
@@ -118,6 +118,9 @@
SkScalar metricsWithoutMultiplier(TextHeightBehavior correction);
void shiftVertically(SkScalar shift) { fOffset.fY += shift; }
+ void setAscentStyle(LineMetricStyle style) { fAscentStyle = style; }
+ void setDescentStyle(LineMetricStyle style) { fDescentStyle = style; }
+
bool endsWithHardLineBreak() const;
private:
diff --git a/modules/skparagraph/src/TextWrapper.cpp b/modules/skparagraph/src/TextWrapper.cpp
index a94ce21..d17eeeb 100644
--- a/modules/skparagraph/src/TextWrapper.cpp
+++ b/modules/skparagraph/src/TextWrapper.cpp
@@ -484,6 +484,17 @@
fHeight += fEndLine.metrics().height();
parent->lines().back().setMaxRunMetrics(maxRunMetrics);
}
+
+ if (parent->lines().empty()) {
+ return;
+ }
+ // Correct line metric styles for the first and for the last lines if needed
+ if (disableFirstAscent) {
+ parent->lines().front().setAscentStyle(LineMetricStyle::Typographic);
+ }
+ if (disableLastDescent) {
+ parent->lines().back().setDescentStyle(LineMetricStyle::Typographic);
+ }
}
} // namespace textlayout