Small changes
Change-Id: Ic9c41a2dd11b4df8ab24037df0109e36536ec6c3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/257892
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
diff --git a/modules/skparagraph/include/TextStyle.h b/modules/skparagraph/include/TextStyle.h
index 85ab428..387bf82 100644
--- a/modules/skparagraph/include/TextStyle.h
+++ b/modules/skparagraph/include/TextStyle.h
@@ -243,15 +243,13 @@
Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {}
Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {}
- Block(const Block& other) {
- fRange = other.fRange;
- fStyle = other.fStyle;
- }
+ Block(const Block& other) : fRange(other.fRange), fStyle(other.fStyle) {}
void add(TextRange tail) {
SkASSERT(fRange.end == tail.start);
fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
}
+
TextRange fRange;
TextStyle fStyle;
};
@@ -273,13 +271,12 @@
, fBlocksBefore(blocksBefore)
, fTextBefore(textBefore) {}
- Placeholder(const Placeholder& other) {
- fRange = other.fRange;
- fStyle = other.fStyle;
- fTextStyle = other.fTextStyle;
- fBlocksBefore = other.fBlocksBefore;
- fTextBefore = other.fTextBefore;
- }
+ Placeholder(const Placeholder& other)
+ : fRange(other.fRange)
+ , fStyle(other.fStyle)
+ , fTextStyle(other.fTextStyle)
+ , fBlocksBefore(other.fBlocksBefore)
+ , fTextBefore(other.fTextBefore) {}
TextRange fRange;
PlaceholderStyle fStyle;
diff --git a/modules/skparagraph/src/OneLineShaper.cpp b/modules/skparagraph/src/OneLineShaper.cpp
index 2974e5e..f777ac8 100644
--- a/modules/skparagraph/src/OneLineShaper.cpp
+++ b/modules/skparagraph/src/OneLineShaper.cpp
@@ -339,6 +339,7 @@
void OneLineShaper::iterateThroughFontStyles(SkSpan<Block> styleSpan,
const ShapeSingleFontVisitor& visitor) {
Block combinedBlock;
+
for (auto& block : styleSpan) {
SkASSERT(combinedBlock.fRange.width() == 0 ||
combinedBlock.fRange.end == block.fRange.start);
@@ -460,11 +461,12 @@
}
iterateThroughFontStyles(styleSpan,
- [this, &shaper, textDirection, limitlessWidth, &advanceX](Block block) {
+ [this, &shaper, textDirection, limitlessWidth, &advanceX]
+ (Block block) {
auto blockSpan = SkSpan<Block>(&block, 1);
// Start from the beginning (hoping that it's a simple case one block - one run)
- fHeight = block.fStyle.getHeight();
+ fHeight = block.fStyle.getHeightOverride() ? block.fStyle.getHeight() : 0;
fAdvance = SkVector::Make(advanceX, 0);
fCurrentText = block.fRange;
fUnresolvedBlocks.emplace(RunBlock(block.fRange));
@@ -495,8 +497,9 @@
}
fCurrentText = unresolvedRange;
- shaper->shape(unresolvedText.begin(), unresolvedText.size(), fontIter, *bidi,
- *script, lang, limitlessWidth, this);
+ shaper->shape(unresolvedText.begin(), unresolvedText.size(),
+ fontIter, *bidi,*script, lang,
+ limitlessWidth, this);
// Take off the queue the block we tried to resolved -
// whatever happened, we have now smaller pieces of it to deal with
@@ -507,7 +510,7 @@
return !fUnresolvedBlocks.empty();
});
- this->finish(block.fRange, block.fStyle.getHeight(), advanceX);
+ this->finish(block.fRange, fHeight, advanceX);
});
return true;
diff --git a/modules/skparagraph/src/ParagraphImpl.cpp b/modules/skparagraph/src/ParagraphImpl.cpp
index 7d4f08b..f8f287f 100644
--- a/modules/skparagraph/src/ParagraphImpl.cpp
+++ b/modules/skparagraph/src/ParagraphImpl.cpp
@@ -887,7 +887,7 @@
return false;
}
- if (dx >= context.clip.fRight) {
+ if (dx >= context.clip.fRight + offsetX) {
// We have to keep looking but just in case keep the last one as the closes
// so far
auto index = context.pos + context.size;
@@ -912,7 +912,7 @@
}
found = i;
}
- auto glyphStart = context.run->positionX(found);
+ auto glyphStart = context.run->positionX(found) + context.fTextShift + offsetX;
auto glyphWidth = context.run->positionX(found + 1) - context.run->positionX(found);
auto clusterIndex8 = context.run->fClusterIndexes[found];
@@ -932,14 +932,11 @@
auto averageCodepoint = glyphWidth / graphemeSize;
auto codepointStart = glyphStart + averageCodepoint * (codepointIndex - codepoints.start);
auto codepointEnd = codepointStart + averageCodepoint;
- center = (codepointStart + codepointEnd) / 2 + context.fTextShift;
+ center = (codepointStart + codepointEnd) / 2;
} else {
SkASSERT(graphemeSize == 1);
- auto codepointStart = glyphStart;
- auto codepointEnd = codepointStart + glyphWidth;
- center = (codepointStart + codepointEnd) / 2 + context.fTextShift;
+ center = glyphStart + glyphWidth / 2;
}
-
if ((dx < center) == context.run->leftToRight()) {
result = { SkToS32(codepointIndex), kDownstream };
} else {
@@ -1092,15 +1089,25 @@
}
void ParagraphImpl::computeEmptyMetrics() {
- auto defaultTextStyle = paragraphStyle().getTextStyle();
+ auto defaultTextStyle = paragraphStyle().getTextStyle();
- auto typefaces = fontCollection()->findTypefaces(
+ auto typefaces = fontCollection()->findTypefaces(
defaultTextStyle.getFontFamilies(), defaultTextStyle.getFontStyle());
- auto typeface = typefaces.size() ? typefaces.front() : nullptr;
+ auto typeface = typefaces.size() ? typefaces.front() : nullptr;
- SkFont font(typeface, defaultTextStyle.getFontSize());
- fEmptyMetrics = InternalLineMetrics(font, paragraphStyle().getStrutStyle().getForceStrutHeight());
- fStrutMetrics.updateLineMetrics(fEmptyMetrics);
+ SkFont font(typeface, defaultTextStyle.getFontSize());
+
+ fEmptyMetrics = InternalLineMetrics(font, paragraphStyle().getStrutStyle().getForceStrutHeight());
+ if (!paragraphStyle().getStrutStyle().getForceStrutHeight() &&
+ defaultTextStyle.getHeightOverride()) {
+ auto multiplier =
+ defaultTextStyle.getHeight() * defaultTextStyle.getFontSize() / fEmptyMetrics.height();
+ fEmptyMetrics = InternalLineMetrics(fEmptyMetrics.ascent() * multiplier,
+ fEmptyMetrics.descent() * multiplier,
+ fEmptyMetrics.leading() * multiplier);
+ }
+
+ fStrutMetrics.updateLineMetrics(fEmptyMetrics);
}
void ParagraphImpl::updateText(size_t from, SkString text) {
diff --git a/modules/skparagraph/src/ParagraphImpl.h b/modules/skparagraph/src/ParagraphImpl.h
index 25f6f13..30508c9 100644
--- a/modules/skparagraph/src/ParagraphImpl.h
+++ b/modules/skparagraph/src/ParagraphImpl.h
@@ -199,6 +199,8 @@
InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
+ BlockRange findAllBlocks(TextRange textRange);
+
private:
friend class ParagraphBuilder;
friend class ParagraphCacheKey;
@@ -209,7 +211,6 @@
friend class OneLineShaper;
void calculateBoundaries(ClusterRange clusters, SkVector offset, SkVector advance);
- BlockRange findAllBlocks(TextRange textRange);
void extractStyles();
void markGraphemes16();
diff --git a/modules/skparagraph/src/TextStyle.cpp b/modules/skparagraph/src/TextStyle.cpp
index ce0cc40..4fc619a 100644
--- a/modules/skparagraph/src/TextStyle.cpp
+++ b/modules/skparagraph/src/TextStyle.cpp
@@ -84,8 +84,7 @@
if (fTextShadows.size() != other.fTextShadows.size()) {
return false;
}
-
- for (int32_t i = 0; i < (int32_t)fTextShadows.size(); ++i) {
+ for (size_t i = 0; i < fTextShadows.size(); ++i) {
if (fTextShadows[i] != other.fTextShadows[i]) {
return false;
}
@@ -134,7 +133,6 @@
// TODO: should not we take typefaces in account?
return fFontStyle == other.fFontStyle && fFontFamilies == other.fFontFamilies &&
fFontSize == other.fFontSize && fHeight == other.fHeight;
-
default:
SkASSERT(false);
return false;
diff --git a/modules/skparagraph/src/TextWrapper.cpp b/modules/skparagraph/src/TextWrapper.cpp
index 98fc5a4..4f69c46 100644
--- a/modules/skparagraph/src/TextWrapper.cpp
+++ b/modules/skparagraph/src/TextWrapper.cpp
@@ -35,9 +35,7 @@
break;
}
if (cluster->width() > maxWidth) {
- // Break the cluster into parts by glyph position
- auto delta = maxWidth - (fWords.width() + fClusters.width());
- fClip.extend(cluster, cluster->roundPos(delta));
+ fClusters.extend(cluster);
fTooLongCluster = true;
fTooLongWord = true;
break;
@@ -53,11 +51,9 @@
}
if (nextWordLength > maxWidth) {
// If the word is too long we can break it right now and hope it's enough
+ fMinIntrinsicWidth = SkTMax(fMinIntrinsicWidth, nextWordLength);
fTooLongWord = true;
}
-
- // TODO: this is the place when we use hyphenation
- fMinIntrinsicWidth = SkTMax(fMinIntrinsicWidth, fTooLongWord ? maxWidth : nextWordLength);
break;
}
@@ -83,8 +79,10 @@
} else if (fClusters.width() > 0) {
fEndLine.extend(fClusters);
fTooLongWord = false;
+ fTooLongCluster = false;
} else if (fClip.width() > 0 || (fTooLongWord && fTooLongCluster)) {
- fEndLine.extend(fClip);
+ // Flutter: forget the clipped cluster but keep the metrics
+ fEndLine.metrics().add(fClip.metrics());
fTooLongWord = false;
fTooLongCluster = false;
} else {
@@ -159,8 +157,8 @@
SkScalar maxWidth,
const AddLineToParagraph& addLine) {
fHeight = 0;
- fMinIntrinsicWidth = 0;
- fMaxIntrinsicWidth = 0;
+ fMinIntrinsicWidth = std::numeric_limits<SkScalar>::min();
+ fMaxIntrinsicWidth = std::numeric_limits<SkScalar>::min();
auto span = parent->clusters();
if (span.size() == 0) {
@@ -268,16 +266,35 @@
}
// We finished formatting the text but we need to scan the rest for some numbers
- auto cluster = fEndLine.endCluster();
- while (cluster != end) {
- fExceededMaxLines = true;
- if (cluster->isHardBreak()) {
- softLineMaxIntrinsicWidth = 0;
- } else {
- softLineMaxIntrinsicWidth += cluster->width();
- fMaxIntrinsicWidth = SkTMax(fMaxIntrinsicWidth, softLineMaxIntrinsicWidth);
+ if (fEndLine.breakCluster() != nullptr) {
+ auto lastWordLength = 0.0f;
+ auto cluster = fEndLine.breakCluster();
+ if (cluster != end) {
+ ++cluster;
}
- ++cluster;
+ while (cluster != end || cluster->endPos() < end->endPos()) {
+ fExceededMaxLines = true;
+ if (cluster->isHardBreak()) {
+ fMaxIntrinsicWidth = SkTMax(fMaxIntrinsicWidth, softLineMaxIntrinsicWidth);
+ softLineMaxIntrinsicWidth = 0;
+
+ fMinIntrinsicWidth = SkTMax(fMinIntrinsicWidth, lastWordLength);
+ lastWordLength = 0;
+ } else if (cluster->isWhitespaces()) {
+ SkASSERT(cluster->isWhitespaces());
+ softLineMaxIntrinsicWidth += cluster->width();
+ fMinIntrinsicWidth = SkTMax(fMinIntrinsicWidth, lastWordLength);
+ lastWordLength = 0;
+ } else {
+ softLineMaxIntrinsicWidth += cluster->width();
+ lastWordLength += cluster->width();
+ }
+ ++cluster;
+ }
+ fMinIntrinsicWidth = SkTMax(fMinIntrinsicWidth, lastWordLength);
+ fMaxIntrinsicWidth = SkTMax(fMaxIntrinsicWidth, softLineMaxIntrinsicWidth);
+ // In case we could not place a single cluster on the line
+ fHeight = SkTMax(fHeight, fEndLine.metrics().height());
}
if (fHardLineBreak) {
diff --git a/samplecode/SampleParagraph.cpp b/samplecode/SampleParagraph.cpp
index cc10e03..450f866 100644
--- a/samplecode/SampleParagraph.cpp
+++ b/samplecode/SampleParagraph.cpp
@@ -1647,15 +1647,13 @@
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
- const char* text = "World domination is such an ugly phrase - I prefer to call it world optimisation";
+ std::u16string text = u"\u0068\u0301\u0350\u0312\u0357\u030C\u0369\u0305\u036C\u0304\u0310\u033F\u0366\u0350\u0343\u0364\u0369\u0311\u0309\u030E\u0365\u031B\u0340\u0337\u0335\u035E\u0334\u0328\u0360\u0360\u0315\u035F\u0340\u0340\u0362\u0360\u0322\u031B\u031B\u0337\u0340\u031E\u031F\u032A\u0331\u0345\u032F\u0332\u032E\u0333\u0353\u0320\u0345\u031C\u031F\u033C\u0325\u0355\u032C\u0325\u033Aa\u0307\u0312\u034B\u0308\u0312\u0346\u0313\u0346\u0304\u0307\u0344\u0305\u0342\u0368\u0346\u036A\u035B\u030F\u0365\u0307\u0340\u0328\u0322\u0361\u0489\u034F\u0328\u0334\u035F\u0335\u0362\u0489\u0360\u0358\u035E\u0360\u035D\u0341\u0337\u0337\u032E\u0326\u032D\u0359\u0318\u033C\u032F\u0333\u035A\u034D\u0319\u031C\u0353\u033C\u0345\u0359\u0331\u033B\u0331\u033C";
ParagraphStyle paragraph_style;
- paragraph_style.setMaxLines(7);
- paragraph_style.setEllipsis(u"\u2026");
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
TextStyle text_style;
text_style.setColor(SK_ColorBLACK);
text_style.setFontFamilies({SkString("Roboto")});
- text_style.setFontSize(40);
+ text_style.setFontSize(20);
builder.pushStyle(text_style);
builder.addText(text);
auto paragraph = builder.Build();
@@ -1677,19 +1675,20 @@
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
- const char* text = "";
+ const char* text = "0";
ParagraphStyle paragraph_style;
paragraph_style.setMaxLines(std::numeric_limits<size_t>::max());
- //paragraph_style.setEllipsis(u"\u2026");
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
TextStyle text_style;
text_style.setColor(SK_ColorBLACK);
- text_style.setFontFamilies({SkString("Roboto")});
- text_style.setFontSize(40);
+ text_style.setFontFamilies({SkString("Google Sans Display")});
+ text_style.setFontSize(160);
+ //text_style.setHeightOverride(true);
+ //text_style.setHeight(1.75);
builder.pushStyle(text_style);
builder.addText(text);
auto paragraph = builder.Build();
- paragraph->layout(this->width());
+ paragraph->layout(94);
paragraph->paint(canvas, 0, 0);
}
diff --git a/tests/SkParagraphTest.cpp b/tests/SkParagraphTest.cpp
index 20f5824..ffce0de 100644
--- a/tests/SkParagraphTest.cpp
+++ b/tests/SkParagraphTest.cpp
@@ -197,7 +197,6 @@
}
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
@@ -297,7 +296,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
@@ -354,7 +352,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
@@ -411,7 +408,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
@@ -468,7 +464,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
@@ -523,7 +518,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
@@ -578,7 +572,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
@@ -633,7 +626,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
@@ -687,7 +679,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
@@ -823,7 +814,6 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
}
-// Checked: DIFF+ (half of the letter spacing before the text???)
DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
@@ -1671,6 +1661,124 @@
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
}
+DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
+ sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
+ if (!fontCollection->fontsFound()) return;
+ TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
+ const char* text =
+ "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
+ "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
+ "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
+
+ auto icu_text = icu::UnicodeString::fromUTF8(text);
+ std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
+ const size_t len = strlen(text);
+
+ ParagraphStyle paragraph_style;
+ paragraph_style.setMaxLines(14);
+ paragraph_style.setTextAlign(TextAlign::kJustify);
+ paragraph_style.setTextDirection(TextDirection::kRtl);
+ paragraph_style.turnHintingOff();
+ ParagraphBuilderImpl builder(paragraph_style, fontCollection);
+
+ TextStyle text_style;
+ text_style.setFontFamilies({SkString("Ahem")});
+ text_style.setFontSize(26);
+ text_style.setColor(SK_ColorBLACK);
+ builder.pushStyle(text_style);
+ builder.addText(text, len);
+ builder.pop();
+
+ auto paragraph = builder.Build();
+ paragraph->layout(TestCanvasWidth - 100);
+ paragraph->paint(canvas.get(), 0, 0);
+
+ auto impl = static_cast<ParagraphImpl*>(paragraph.get());
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(1);
+
+ // Tests for GetRectsForRange()
+ RectHeightStyle rect_height_style = RectHeightStyle::kMax;
+ RectWidthStyle rect_width_style = RectWidthStyle::kTight;
+ paint.setColor(SK_ColorRED);
+ auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
+ for (size_t i = 0; i < boxes.size(); ++i) {
+ canvas.get()->drawRect(boxes[i].rect, paint);
+ }
+ REPORTER_ASSERT(reporter, boxes.size() == 2ull);
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
+
+ paint.setColor(SK_ColorBLUE);
+ boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
+ for (size_t i = 0; i < boxes.size(); ++i) {
+ canvas.get()->drawRect(boxes[i].rect, paint);
+ }
+ REPORTER_ASSERT(reporter, boxes.size() == 1ull);
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
+
+ // All lines should be justified to the width of the
+ // paragraph.
+ for (auto& line : impl->lines()) {
+ REPORTER_ASSERT(reporter,
+ SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
+ }
+}
+
+DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
+ sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
+ if (!fontCollection->fontsFound()) return;
+ TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
+
+ const char* text = " leading space";
+
+ auto icu_text = icu::UnicodeString::fromUTF8(text);
+ std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
+ const size_t len = strlen(text);
+
+ ParagraphStyle paragraph_style;
+ paragraph_style.setMaxLines(14);
+ paragraph_style.setTextAlign(TextAlign::kJustify);
+ paragraph_style.setTextDirection(TextDirection::kRtl);
+ paragraph_style.turnHintingOff();
+ ParagraphBuilderImpl builder(paragraph_style, fontCollection);
+
+ TextStyle text_style;
+ text_style.setFontFamilies({SkString("Ahem")});
+ text_style.setFontSize(26);
+ text_style.setColor(SK_ColorBLACK);
+ builder.pushStyle(text_style);
+ builder.addText(text, len);
+ builder.pop();
+
+ auto paragraph = builder.Build();
+ paragraph->layout(TestCanvasWidth - 100);
+ paragraph->paint(canvas.get(), 0, 0);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(1);
+
+ // Tests for GetRectsForRange()
+ RectHeightStyle rect_height_style = RectHeightStyle::kMax;
+ RectWidthStyle rect_width_style = RectWidthStyle::kTight;
+ paint.setColor(SK_ColorRED);
+ auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
+ for (size_t i = 0; i < boxes.size(); ++i) {
+ canvas.get()->drawRect(boxes[i].rect, paint);
+ }
+ REPORTER_ASSERT(reporter, boxes.size() == 2ull);
+}
+
// Checked: NO DIFF (some minor decoration differences, probably)
DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
@@ -1792,7 +1900,7 @@
}
DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
- // SkDebugf("TODO: Fix decorations\n");
+ SkDebugf("TODO: Add test for wavy decorations\n");
}
// Checked: NO DIFF
@@ -4374,11 +4482,6 @@
}
}
-// TODO: Implement font features
-DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
- // SkDebugf("TODO: Font features\n");
-}
-
// Not in Minikin
DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
@@ -5040,14 +5143,14 @@
canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
- relayout(3, false, 50, 30, 50, 950, SK_ColorBLUE);
- relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 50, 950, SK_ColorGREEN);
+ relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
+ relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
- relayout(3, true, 50, 30, 50, 950, SK_ColorMAGENTA);
+ relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
- relayout(3, false, 50, 30, 50, 950, SK_ColorBLUE);
- relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 50, 950, SK_ColorGREEN);
+ relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
+ relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
}