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>
This commit is contained in:
Julia Lavrova 2019-12-04 11:43:32 -05:00 committed by Skia Commit-Bot
parent 3f7c49c96d
commit 90bfd1c1c3
8 changed files with 206 additions and 81 deletions

View File

@ -243,15 +243,13 @@ struct Block {
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 @@ struct Placeholder {
, 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;

View File

@ -339,6 +339,7 @@ void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnres
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 @@ bool OneLineShaper::shape() {
}
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 @@ bool OneLineShaper::shape() {
}
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 @@ bool OneLineShaper::shape() {
return !fUnresolvedBlocks.empty();
});
this->finish(block.fRange, block.fStyle.getHeight(), advanceX);
this->finish(block.fRange, fHeight, advanceX);
});
return true;

View File

@ -887,7 +887,7 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
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 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
}
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 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
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::setState(InternalState state) {
}
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) {

View File

@ -199,6 +199,8 @@ public:
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 @@ private:
friend class OneLineShaper;
void calculateBoundaries(ClusterRange clusters, SkVector offset, SkVector advance);
BlockRange findAllBlocks(TextRange textRange);
void extractStyles();
void markGraphemes16();

View File

@ -84,8 +84,7 @@ bool TextStyle::equals(const TextStyle& other) const {
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 @@ bool TextStyle::matchOneAttribute(StyleType styleType, const TextStyle& other) c
// 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;

View File

@ -35,9 +35,7 @@ void TextWrapper::lookAhead(SkScalar maxWidth, Cluster* endOfClusters) {
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 @@ void TextWrapper::lookAhead(SkScalar maxWidth, Cluster* endOfClusters) {
}
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 @@ void TextWrapper::moveForward() {
} 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 @@ void TextWrapper::breakTextIntoLines(ParagraphImpl* parent,
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 @@ void TextWrapper::breakTextIntoLines(ParagraphImpl* parent,
}
// 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) {

View File

@ -1647,15 +1647,13 @@ protected:
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 @@ protected:
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);
}

View File

@ -197,7 +197,6 @@ DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
}
}
// 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 @@ DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
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 @@ DEF_TEST(SkParagraph_JustifyRTL, reporter) {
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_DecorationsParagraph, reporter) {
}
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 @@ DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
}
}
// 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 @@ DEF_TEST(SkParagraph_Ellipsis, reporter) {
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);
}