RTL fixes + few small bugs
1. Removed unnecessary iterators (use SkShaper iterators instead) 2. More careful hash function and comparison (ParagraphStyle) 3. computeEmptyMetrics should go after resolveStrut 4. longestLine for line with spaces only should not be 0 5. LTR/RTL * left/right align * latin/arabic * leading/trailing spaces positioning 6. Height for MaxHeight rect (to follow Gary's change) Change-Id: I3507ff9fb93148e5ef882a2f514078fcea9cfef3 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268301 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
parent
c61d7e3d6e
commit
d3a32c5425
@ -15,27 +15,6 @@
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
class SingleFontIterator final : public SkShaper::FontRunIterator {
|
||||
public:
|
||||
SingleFontIterator(SkSpan<const char> utf8, const SkFont& font)
|
||||
: fText(utf8), fCurrentChar(utf8.begin()), fFont(font) { }
|
||||
|
||||
void consume() override {
|
||||
SkASSERT(fCurrentChar < fText.end());
|
||||
fCurrentChar = fText.end();
|
||||
}
|
||||
|
||||
size_t endOfCurrentRun() const override { return fCurrentChar - fText.begin(); }
|
||||
bool atEnd() const override { return fCurrentChar == fText.end(); }
|
||||
const SkFont& currentFont() const override { return fFont; }
|
||||
|
||||
private:
|
||||
|
||||
SkSpan<const char> fText;
|
||||
const char* fCurrentChar;
|
||||
SkFont fFont;
|
||||
};
|
||||
|
||||
class LangIterator final : public SkShaper::LanguageRunIterator {
|
||||
public:
|
||||
LangIterator(SkSpan<const char> utf8, SkSpan<Block> styles, const TextStyle& defaultStyle)
|
||||
|
@ -497,7 +497,7 @@ bool OneLineShaper::shape() {
|
||||
|
||||
auto result = iterateThroughShapingRegions(
|
||||
[this, limitlessWidth]
|
||||
(TextRange textRange, SkSpan<Block> styleSpan, SkScalar& advanceX, TextIndex textStart, uint8_t textDirection) {
|
||||
(TextRange textRange, SkSpan<Block> styleSpan, SkScalar& advanceX, TextIndex textStart, uint8_t defaultBidiLevel) {
|
||||
|
||||
// Set up the shaper and shape the next
|
||||
auto shaper = SkShaper::MakeShapeDontWrapOrReorder();
|
||||
@ -507,7 +507,7 @@ bool OneLineShaper::shape() {
|
||||
}
|
||||
|
||||
iterateThroughFontStyles(textRange, styleSpan,
|
||||
[this, &shaper, textDirection, limitlessWidth, &advanceX]
|
||||
[this, &shaper, defaultBidiLevel, limitlessWidth, &advanceX]
|
||||
(Block block, SkTArray<SkShaper::Feature> features) {
|
||||
auto blockSpan = SkSpan<Block>(&block, 1);
|
||||
|
||||
@ -531,20 +531,15 @@ bool OneLineShaper::shape() {
|
||||
auto unresolvedRange = fUnresolvedBlocks.front().fText;
|
||||
auto unresolvedText = fParagraph->text(unresolvedRange);
|
||||
|
||||
SingleFontIterator fontIter(unresolvedText, font);
|
||||
LangIterator lang(unresolvedText, blockSpan,
|
||||
SkShaper::TrivialFontRunIterator fontIter(font, unresolvedText.size());
|
||||
LangIterator langIter(unresolvedText, blockSpan,
|
||||
fParagraph->paragraphStyle().getTextStyle());
|
||||
auto script = SkShaper::MakeHbIcuScriptRunIterator(unresolvedText.begin(),
|
||||
unresolvedText.size());
|
||||
auto bidi = SkShaper::MakeIcuBiDiRunIterator(
|
||||
unresolvedText.begin(), unresolvedText.size(), textDirection);
|
||||
if (bidi == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkShaper::TrivialBiDiRunIterator bidiIter(defaultBidiLevel, unresolvedText.size());
|
||||
auto scriptIter = SkShaper::MakeHbIcuScriptRunIterator
|
||||
(unresolvedText.begin(), unresolvedText.size());
|
||||
fCurrentText = unresolvedRange;
|
||||
shaper->shape(unresolvedText.begin(), unresolvedText.size(),
|
||||
fontIter, *bidi,*script, lang,
|
||||
fontIter, bidiIter,*scriptIter, langIter,
|
||||
features.data(), features.size(),
|
||||
limitlessWidth, this);
|
||||
|
||||
|
@ -83,11 +83,18 @@ uint32_t ParagraphCache::KeyHash::operator()(const ParagraphCacheKey& key) const
|
||||
for (auto& ff : ts.fStyle.getFontFamilies()) {
|
||||
hash = mix(hash, SkGoodHash()(ff));
|
||||
}
|
||||
for (auto& ff : ts.fStyle.getFontFeatures()) {
|
||||
hash = mix(hash, SkGoodHash()(ff));
|
||||
}
|
||||
hash = mix(hash, SkGoodHash()(ts.fStyle.getFontStyle()));
|
||||
hash = mix(hash, SkGoodHash()(relax(ts.fStyle.getFontSize())));
|
||||
hash = mix(hash, SkGoodHash()(ts.fRange.start));
|
||||
hash = mix(hash, SkGoodHash()(ts.fRange.end));
|
||||
}
|
||||
|
||||
hash = mix(hash, SkGoodHash()(relax(key.fParagraphStyle.getHeight())));
|
||||
hash = mix(hash, SkGoodHash()(key.fParagraphStyle.getTextDirection()));
|
||||
|
||||
hash = mix(hash, SkGoodHash()(key.fText));
|
||||
return hash;
|
||||
}
|
||||
@ -107,7 +114,10 @@ bool operator==(const ParagraphCacheKey& a, const ParagraphCacheKey& b) {
|
||||
}
|
||||
|
||||
// There is no need to compare default paragraph styles - they are included into fTextStyles
|
||||
if (a.fParagraphStyle.getHeight() != b.fParagraphStyle.getHeight()) {
|
||||
if (!SkScalarNearlyEqual(a.fParagraphStyle.getHeight(), b.fParagraphStyle.getHeight())) {
|
||||
return false;
|
||||
}
|
||||
if (a.fParagraphStyle.getTextDirection() != b.fParagraphStyle.getTextDirection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -139,12 +139,13 @@ void ParagraphImpl::layout(SkScalar rawWidth) {
|
||||
fClusters.reset();
|
||||
fGraphemes.reset();
|
||||
this->markGraphemes();
|
||||
this->computeEmptyMetrics();
|
||||
|
||||
if (!this->shapeTextIntoEndlessLine()) {
|
||||
|
||||
this->resetContext();
|
||||
// TODO: merge the two next calls - they always come together
|
||||
this->resolveStrut();
|
||||
this->computeEmptyMetrics();
|
||||
this->fLines.reset();
|
||||
|
||||
// Set the important values that are not zero
|
||||
@ -190,6 +191,7 @@ void ParagraphImpl::layout(SkScalar rawWidth) {
|
||||
if (fState < kLineBroken) {
|
||||
this->resetContext();
|
||||
this->resolveStrut();
|
||||
this->computeEmptyMetrics();
|
||||
this->fLines.reset();
|
||||
this->breakShapedTextIntoLines(floorWidth);
|
||||
fState = kLineBroken;
|
||||
@ -412,7 +414,7 @@ void ParagraphImpl::breakShapedTextIntoLines(SkScalar maxWidth) {
|
||||
}
|
||||
}
|
||||
|
||||
fLongestLine = SkTMax(fLongestLine, advance.fX);
|
||||
fLongestLine = SkTMax(fLongestLine, SkScalarNearlyZero(advance.fX) ? widthWithSpaces : advance.fX);
|
||||
});
|
||||
fHeight = textWrapper.height();
|
||||
fWidth = maxWidth;
|
||||
@ -654,7 +656,6 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
|
||||
// Found a line that intersects with the text
|
||||
auto firstBoxOnTheLine = results.size();
|
||||
auto paragraphTextDirection = paragraphStyle().getTextDirection();
|
||||
auto lineTextAlign = line.assumedTextAlign();
|
||||
const Run* lastRun = nullptr;
|
||||
line.iterateThroughVisualRuns(true,
|
||||
[&](const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width) {
|
||||
@ -683,35 +684,17 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
|
||||
|
||||
auto runInLineWidth = line.measureTextInsideOneRun(textRange, run, runOffset, 0, true, false).clip.width();
|
||||
runOffset += *width;
|
||||
*width = runInLineWidth;
|
||||
|
||||
// Found a run that intersects with the text
|
||||
auto context = line.measureTextInsideOneRun(intersect, run, runOffset, 0, true, true);
|
||||
|
||||
//*width += context.clip.width();
|
||||
*width = runInLineWidth;
|
||||
|
||||
SkRect clip = context.clip;
|
||||
SkRect trailingSpaces = SkRect::MakeEmpty();
|
||||
SkScalar ghostSpacesRight = context.run->leftToRight() ? clip.right() - line.width() : 0;
|
||||
SkScalar ghostSpacesLeft = !context.run->leftToRight() ? clip.right() - line.width() : 0;
|
||||
|
||||
if (ghostSpacesRight + ghostSpacesLeft > 0) {
|
||||
if (lineTextAlign == TextAlign::kLeft && ghostSpacesLeft > 0) {
|
||||
clip.offset(-ghostSpacesLeft, 0);
|
||||
} else if (lineTextAlign == TextAlign::kRight && ghostSpacesLeft > 0) {
|
||||
clip.offset(-ghostSpacesLeft, 0);
|
||||
} else if (lineTextAlign == TextAlign::kCenter) {
|
||||
// TODO: What do we do for centering?
|
||||
}
|
||||
}
|
||||
|
||||
if (rectHeightStyle == RectHeightStyle::kMax) {
|
||||
// TODO: Change it once flutter rolls into google3
|
||||
// (probably will break things if changed before)
|
||||
clip.fBottom = line.height();
|
||||
clip.fTop = line.sizes().baseline() -
|
||||
line.getMaxRunMetrics().baseline() +
|
||||
line.getMaxRunMetrics().delta();
|
||||
clip.fTop = line.sizes().delta();
|
||||
|
||||
} else if (rectHeightStyle == RectHeightStyle::kIncludeLineSpacingTop) {
|
||||
if (&line != &fLines.front()) {
|
||||
@ -734,37 +717,82 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
|
||||
} else if (rectHeightStyle == RectHeightStyle::kStrut) {
|
||||
auto strutStyle = this->paragraphStyle().getStrutStyle();
|
||||
if (strutStyle.getStrutEnabled() && strutStyle.getFontSize() > 0) {
|
||||
auto top = line.baseline() ; //+ line.sizes().runTop(run);
|
||||
auto top = line.baseline();
|
||||
clip.fTop = top + fStrutMetrics.ascent();
|
||||
clip.fBottom = top + fStrutMetrics.descent();
|
||||
}
|
||||
}
|
||||
clip.offset(line.offset());
|
||||
|
||||
// Check if we can merge two boxes
|
||||
bool mergedBoxes = false;
|
||||
if (!results.empty() &&
|
||||
lastRun != nullptr && lastRun->placeholder() == nullptr && context.run->placeholder() == nullptr &&
|
||||
lastRun->lineHeight() == context.run->lineHeight() &&
|
||||
lastRun->font() == context.run->font()) {
|
||||
auto& lastBox = results.back();
|
||||
if (SkScalarNearlyEqual(lastBox.rect.fTop, clip.fTop) &&
|
||||
SkScalarNearlyEqual(lastBox.rect.fBottom, clip.fBottom) &&
|
||||
(SkScalarNearlyEqual(lastBox.rect.fLeft, clip.fRight) ||
|
||||
SkScalarNearlyEqual(lastBox.rect.fRight, clip.fLeft))) {
|
||||
lastBox.rect.fLeft = SkTMin(lastBox.rect.fLeft, clip.fLeft);
|
||||
lastBox.rect.fRight = SkTMax(lastBox.rect.fRight, clip.fRight);
|
||||
mergedBoxes = true;
|
||||
// Separate trailing spaces and move them in the default order of the paragraph
|
||||
// in case the run order and the paragraph order don't match
|
||||
SkRect trailingSpaces = SkRect::MakeEmpty();
|
||||
if (line.trimmedText().end < line.textWithSpaces().end && // Line has trailing spaces
|
||||
line.textWithSpaces().end == intersect.end && // Range is at the end of the line
|
||||
line.trimmedText().end > intersect.start) // Range has more than just spaces
|
||||
{
|
||||
auto delta = line.spacesWidth();
|
||||
trailingSpaces = SkRect::MakeXYWH(0, 0, 0, 0);
|
||||
// There are trailing spaces in this run
|
||||
if (this->paragraphStyle().getTextAlign() == TextAlign::kJustify &&
|
||||
&line != &fLines.back())
|
||||
{
|
||||
// TODO: this is just a patch. Make it right later (when it's clear what and how)
|
||||
clip.fLeft = 0;
|
||||
clip.fRight = line.width();
|
||||
} else if (this->fParagraphStyle.getTextDirection() == TextDirection::kRtl &&
|
||||
!run->leftToRight())
|
||||
{
|
||||
// Split
|
||||
trailingSpaces = clip;
|
||||
trailingSpaces.fLeft = - delta;
|
||||
trailingSpaces.fRight = 0;
|
||||
clip.fLeft += delta;
|
||||
} else if (this->fParagraphStyle.getTextDirection() == TextDirection::kLtr &&
|
||||
run->leftToRight())
|
||||
{
|
||||
// Split
|
||||
trailingSpaces = clip;
|
||||
trailingSpaces.fLeft = line.width();
|
||||
trailingSpaces.fRight = trailingSpaces.fLeft + delta;
|
||||
clip.fRight -= delta;
|
||||
}
|
||||
}
|
||||
lastRun = context.run;
|
||||
|
||||
if (!mergedBoxes) {
|
||||
clip.offset(line.offset());
|
||||
if (trailingSpaces.width() > 0) {
|
||||
trailingSpaces.offset(line.offset());
|
||||
}
|
||||
|
||||
// Check if we can merge two boxes instead of adding a new one
|
||||
auto merge = [&lastRun, &context, &results](SkRect clip) {
|
||||
bool mergedBoxes = false;
|
||||
if (!results.empty() &&
|
||||
lastRun != nullptr &&
|
||||
lastRun->placeholder() == nullptr &&
|
||||
context.run->placeholder() == nullptr &&
|
||||
SkScalarNearlyEqual(lastRun->lineHeight(), context.run->lineHeight()) &&
|
||||
lastRun->font() == context.run->font())
|
||||
{
|
||||
auto& lastBox = results.back();
|
||||
if (SkScalarNearlyEqual(lastBox.rect.fTop, clip.fTop) &&
|
||||
SkScalarNearlyEqual(lastBox.rect.fBottom, clip.fBottom) &&
|
||||
(SkScalarNearlyEqual(lastBox.rect.fLeft, clip.fRight) ||
|
||||
SkScalarNearlyEqual(lastBox.rect.fRight, clip.fLeft)))
|
||||
{
|
||||
lastBox.rect.fLeft = SkTMin(lastBox.rect.fLeft, clip.fLeft);
|
||||
lastBox.rect.fRight = SkTMax(lastBox.rect.fRight, clip.fRight);
|
||||
mergedBoxes = true;
|
||||
}
|
||||
}
|
||||
lastRun = context.run;
|
||||
return mergedBoxes;
|
||||
};
|
||||
|
||||
if (!merge(clip)) {
|
||||
results.emplace_back(
|
||||
clip, context.run->leftToRight() ? TextDirection::kLtr : TextDirection::kRtl);
|
||||
}
|
||||
|
||||
if (trailingSpaces.width() > 0) {
|
||||
if (!SkScalarNearlyZero(trailingSpaces.width()) && !merge(trailingSpaces)) {
|
||||
results.emplace_back(trailingSpaces, paragraphTextDirection);
|
||||
}
|
||||
|
||||
@ -862,13 +890,13 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
|
||||
|
||||
auto offsetX = line.offset().fX;
|
||||
auto context = line.measureTextInsideOneRun(textRange, run, 0, 0, true, false);
|
||||
if (dx < context.clip.fLeft ) {
|
||||
if (dx < context.clip.fLeft + offsetX) {
|
||||
// All the other runs are placed right of this one
|
||||
result = { SkToS32(context.run->fClusterIndexes[context.pos]), kDownstream };
|
||||
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;
|
||||
@ -887,12 +915,18 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
|
||||
size_t found = context.pos;
|
||||
for (size_t i = context.pos; i < context.pos + context.size; ++i) {
|
||||
// TODO: this rounding is done to match Flutter tests. Must be removed..
|
||||
auto end = littleRound(context.run->positionX(i) + context.fTextShift + offsetX);
|
||||
if (end > dx) {
|
||||
auto index = context.run->leftToRight() ? i : context.size - i;
|
||||
auto end = littleRound(context.run->positionX(index) + context.fTextShift + offsetX);
|
||||
if ((context.run->leftToRight() ? end > dx : dx > end)) {
|
||||
break;
|
||||
}
|
||||
found = i;
|
||||
found = index;
|
||||
}
|
||||
|
||||
if (!context.run->leftToRight()) {
|
||||
--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];
|
||||
@ -1054,6 +1088,7 @@ void ParagraphImpl::setState(InternalState state) {
|
||||
case kLineBroken:
|
||||
this->resetContext();
|
||||
this->resolveStrut();
|
||||
this->computeEmptyMetrics();
|
||||
this->fRunShifts.reset();
|
||||
fLines.reset();
|
||||
case kFormatted:
|
||||
|
@ -266,12 +266,9 @@ TextAlign TextLine::assumedTextAlign() const {
|
||||
return this->fMaster->paragraphStyle().effective_align();
|
||||
}
|
||||
|
||||
if (fClusterRange.empty()) {
|
||||
return TextAlign::kLeft;
|
||||
} else {
|
||||
auto run = this->fMaster->cluster(fClusterRange.end - 1).run();
|
||||
return run->leftToRight() ? TextAlign::kLeft : TextAlign::kRight;
|
||||
}
|
||||
return this->fMaster->paragraphStyle().getTextDirection() == TextDirection::kLtr
|
||||
? TextAlign::kLeft
|
||||
: TextAlign::kRight;
|
||||
}
|
||||
|
||||
void TextLine::scanStyles(StyleType styleType, const RunStyleVisitor& visitor) {
|
||||
@ -855,6 +852,7 @@ void TextLine::iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisi
|
||||
// Walk through all the runs that intersect with the line in visual order
|
||||
SkScalar width = 0;
|
||||
SkScalar runOffset = 0;
|
||||
SkScalar totalWidth = 0;
|
||||
auto textRange = includingGhostSpaces ? this->textWithSpaces() : this->trimmedText();
|
||||
for (auto& runIndex : fRunsInVisualOrder) {
|
||||
|
||||
@ -864,23 +862,37 @@ void TextLine::iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisi
|
||||
// TODO: deal with empty runs in a better way
|
||||
continue;
|
||||
}
|
||||
if (!run->leftToRight() && runOffset == 0 && includingGhostSpaces) {
|
||||
// runOffset does not take in account a possibility
|
||||
// that RTL run could start before the line (trailing spaces)
|
||||
// so we need to do runOffset -= "trailing whitespaces length"
|
||||
TextRange whitespaces = intersected(
|
||||
TextRange(fTextRange.end, fTextWithWhitespacesRange.end), run->fTextRange);
|
||||
if (whitespaces.width() > 0) {
|
||||
auto whitespacesLen = measureTextInsideOneRun(whitespaces, run, runOffset, 0, true, false).clip.width();
|
||||
runOffset -= whitespacesLen;
|
||||
}
|
||||
}
|
||||
runOffset += width;
|
||||
totalWidth += width;
|
||||
if (!visitor(run, runOffset, lineIntersection, &width)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
runOffset += width;
|
||||
totalWidth += width;
|
||||
|
||||
if (this->ellipsis() != nullptr) {
|
||||
if (visitor(ellipsis(), runOffset, ellipsis()->textRange(), &width)) {
|
||||
runOffset += width;
|
||||
totalWidth += width;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a very important assert!
|
||||
// It asserts that 2 different ways of calculation come with the same results
|
||||
if (!includingGhostSpaces && compareRound(runOffset, this->width()) != 0) {
|
||||
SkDebugf("ASSERT: %f != %f\n", runOffset, this->width());
|
||||
if (!includingGhostSpaces && compareRound(totalWidth, this->width()) != 0) {
|
||||
SkDebugf("ASSERT: %f != %f\n", totalWidth, this->width());
|
||||
SkASSERT(false);
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
InternalLineMetrics sizes() const { return fSizes; }
|
||||
bool empty() const { return fTextRange.empty(); }
|
||||
|
||||
SkScalar spacesWidth() { return fWidthWithSpaces - width(); }
|
||||
SkScalar height() const { return fAdvance.fY; }
|
||||
SkScalar width() const {
|
||||
return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
|
||||
|
@ -107,6 +107,7 @@ bool TextStyle::equalsByFonts(const TextStyle& that) const {
|
||||
return !fIsPlaceholder && !that.fIsPlaceholder &&
|
||||
fFontStyle == that.fFontStyle &&
|
||||
fFontFamilies == that.fFontFamilies &&
|
||||
fFontFeatures == that.fFontFeatures &&
|
||||
SkScalarNearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
|
||||
SkScalarNearlyEqual(fWordSpacing, that.fWordSpacing) &&
|
||||
SkScalarNearlyEqual(fHeight, that.fHeight) &&
|
||||
|
@ -103,19 +103,10 @@ void TextWrapper::trimEndSpaces(TextAlign align) {
|
||||
// Remember the breaking position
|
||||
fEndLine.saveBreak();
|
||||
// Skip all space cluster at the end
|
||||
//bool left = align == TextAlign::kStart || align == TextAlign::kLeft;
|
||||
bool right = align == TextAlign::kRight || align == TextAlign::kEnd;
|
||||
for (auto cluster = fEndLine.endCluster();
|
||||
cluster >= fEndLine.startCluster() && cluster->isWhitespaces();
|
||||
--cluster) {
|
||||
if ((cluster->run()->leftToRight()) ||
|
||||
(right && !cluster->run()->leftToRight()) ||
|
||||
align == TextAlign::kJustify || align == TextAlign::kCenter) {
|
||||
fEndLine.trim(cluster);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
fEndLine.trim(cluster);
|
||||
}
|
||||
fEndLine.trim();
|
||||
}
|
||||
|
@ -1901,26 +1901,59 @@ protected:
|
||||
SkString name() override { return SkString("Paragraph26"); }
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
auto fontCollection = sk_make_sp<FontCollection>();
|
||||
fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
|
||||
fontCollection->enableFontFallback();
|
||||
fontCollection->getParagraphCache()->turnOn(false);
|
||||
|
||||
//const char* text = "ERROR\nSECOND ERROR";
|
||||
const char* text = "ERROR\nSECOND ERROR\nTHIRD ERRORRRRRRRRR\nFOURTH ERROR";
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.setEllipsis(u"\u2026");
|
||||
paragraph_style.setMaxLines(std::numeric_limits<size_t>::max());
|
||||
ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
|
||||
TextStyle text_style;
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
text_style.setFontFamilies({SkString("Google Sans")});
|
||||
text_style.setFontSize(20);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(std::numeric_limits<SkScalar>::max());
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
canvas->translate(0, 300);
|
||||
paragraph->layout(200);
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
canvas->clear(SK_ColorWHITE);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setColor(SK_ColorBLACK);
|
||||
|
||||
TextStyle textStyle;
|
||||
textStyle.setForegroundColor(paint);
|
||||
textStyle.setFontFamilies({SkString("Roboto")});
|
||||
textStyle.setFontSize(16);
|
||||
|
||||
ParagraphStyle paragraphStyle;
|
||||
paragraphStyle.setTextStyle(textStyle);
|
||||
paragraphStyle.setTextAlign(TextAlign::kLeft);
|
||||
{
|
||||
ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
|
||||
builder.addText("");
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(SK_ScalarInfinity);
|
||||
SkDebugf("layout: %f %f %f %f %f %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight(),
|
||||
paragraph->getMaxIntrinsicWidth(), paragraph->getMinIntrinsicWidth(),
|
||||
paragraph->getLongestLine(), paragraph->getAlphabeticBaseline(),
|
||||
paragraph->getIdeographicBaseline());
|
||||
|
||||
paragraph->layout(253);
|
||||
SkDebugf("layout: %f %f %f %f %f %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight(),
|
||||
paragraph->getMaxIntrinsicWidth(), paragraph->getMinIntrinsicWidth(),
|
||||
paragraph->getLongestLine(), paragraph->getAlphabeticBaseline(),
|
||||
paragraph->getIdeographicBaseline());
|
||||
}
|
||||
{
|
||||
ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
|
||||
builder.addText(" ");
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(SK_ScalarInfinity);
|
||||
SkDebugf("layout: %f %f %f %f %f %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight(),
|
||||
paragraph->getMaxIntrinsicWidth(), paragraph->getMinIntrinsicWidth(),
|
||||
paragraph->getLongestLine(), paragraph->getAlphabeticBaseline(),
|
||||
paragraph->getIdeographicBaseline());
|
||||
|
||||
paragraph->layout(253);
|
||||
SkDebugf("layout: %f %f %f %f %f %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight(),
|
||||
paragraph->getMaxIntrinsicWidth(), paragraph->getMinIntrinsicWidth(),
|
||||
paragraph->getLongestLine(), paragraph->getAlphabeticBaseline(),
|
||||
paragraph->getIdeographicBaseline());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1932,37 +1965,104 @@ protected:
|
||||
SkString name() override { return SkString("Paragraph27"); }
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
auto fontCollection = sk_make_sp<FontCollection>();
|
||||
fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
|
||||
fontCollection->enableFontFallback();
|
||||
fontCollection->getParagraphCache()->turnOn(false);
|
||||
|
||||
SkPaint red;
|
||||
red.setColor(SK_ColorRED);
|
||||
red.setStyle(SkPaint::kStroke_Style);
|
||||
red.setAntiAlias(true);
|
||||
red.setStrokeWidth(1);
|
||||
|
||||
SkPaint blue;
|
||||
blue.setColor(SK_ColorRED);
|
||||
blue.setStyle(SkPaint::kStroke_Style);
|
||||
blue.setAntiAlias(true);
|
||||
blue.setStrokeWidth(1);
|
||||
|
||||
SkPaint black;
|
||||
black.setColor(SK_ColorBLACK);
|
||||
black.setStyle(SkPaint::kStroke_Style);
|
||||
black.setAntiAlias(true);
|
||||
black.setStrokeWidth(1);
|
||||
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.setMaxLines(std::numeric_limits<size_t>::max());
|
||||
paragraph_style.setEllipsis(u"\u2026");
|
||||
paragraph_style.setTextAlign(TextAlign::kRight);
|
||||
TextStyle text_style;
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
text_style.setFontFamilies({SkString("Google Sans")});
|
||||
text_style.setFontSize(24);
|
||||
text_style.setFontFamilies({SkString("Roboto")});
|
||||
|
||||
auto draw = [&](const char* text, SkScalar height) {
|
||||
ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
|
||||
text_style.setHeightOverride(true);
|
||||
text_style.setHeight(height);
|
||||
// RTL + right align + arabic
|
||||
// RTL + right align + latin
|
||||
// LTR + right align + arabic
|
||||
// LTR + right align + latin
|
||||
// RTL + left align + arabic
|
||||
// RTL + left align + latin
|
||||
// arabic and latin should not differ at all
|
||||
// check: line breaking and trailing spaces
|
||||
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
auto h = 60;
|
||||
auto w = 300;
|
||||
|
||||
auto draw = [&](SkScalar width, SkScalar height, TextDirection td, TextAlign ta, const char* text) {
|
||||
SkString str;
|
||||
str.append(" ");
|
||||
str.append(text);
|
||||
str.append(" ");
|
||||
str.append(text);
|
||||
str.append(" ");
|
||||
|
||||
SkDebugf("draw '%s' dir:%s align:%s\n", str.c_str(),
|
||||
td == TextDirection::kLtr ? "left" : "right",
|
||||
ta == TextAlign::kLeft ? "left" : "right");
|
||||
paragraph_style.setTextDirection(td);
|
||||
paragraph_style.setTextAlign(ta);
|
||||
text_style.setFontSize(20);
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
builder.addText(str.c_str());
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(153.33f);
|
||||
|
||||
SkDebugf("'%s': %f\n", text, paragraph->getHeight());
|
||||
auto boxes1 = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
|
||||
auto boxes2 = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kMax, RectWidthStyle::kTight);
|
||||
if (boxes1.size() > 0 && boxes2.size() > 0) {
|
||||
SkDebugf("Heights: %f %f\\b", boxes1[0].rect.height() , boxes2[0].rect.height());
|
||||
}
|
||||
paragraph->layout(width);
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
canvas->translate(0, 200);
|
||||
auto impl = static_cast<ParagraphImpl*>(paragraph.get());
|
||||
for (auto& line : impl->lines()) {
|
||||
SkDebugf("line[%d]: %f + %f\n", &line - impl->lines().begin(), line.offset().fX, line.shift());
|
||||
line.iterateThroughVisualRuns(true,
|
||||
[&](const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width) {
|
||||
*width = line.measureTextInsideOneRun(textRange, run, runOffset, 0, true, false).clip.width();
|
||||
SkDebugf("%d[%d: %d) @%f + %f %s\n", run->index(),
|
||||
textRange.start, textRange.end, runOffset, *width, run->leftToRight() ? "left" : "right");
|
||||
return true;
|
||||
});
|
||||
}
|
||||
auto boxes = paragraph->getRectsForRange(0, 100, RectHeightStyle::kTight, RectWidthStyle::kTight);
|
||||
bool even = true;
|
||||
for (auto& box : boxes) {
|
||||
SkDebugf("[%f:%f,%f:%f] %s\n",
|
||||
box.rect.fLeft, box.rect.fRight, box.rect.fTop, box.rect.fBottom,
|
||||
box.direction == TextDirection::kLtr ? "left" : "right");
|
||||
canvas->drawRect(box.rect, even ? red : blue);
|
||||
even = !even;
|
||||
}
|
||||
canvas->translate(0, height);
|
||||
};
|
||||
|
||||
//draw("Artist Name with long text in active media bar to test word truncation", 1.333f);
|
||||
draw("provider with long text in active media bar to test word truncation inside the subtitle", 1);
|
||||
canvas->drawRect(SkRect::MakeXYWH(0, 0, w, h * 8), black);
|
||||
|
||||
draw(w, h, TextDirection::kRtl, TextAlign::kRight, "RTL+RIGHT#1234567890");
|
||||
draw(w, h, TextDirection::kRtl, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
|
||||
|
||||
draw(w, h, TextDirection::kLtr, TextAlign::kRight, "LTR+RIGHT#1234567890");
|
||||
draw(w, h, TextDirection::kLtr, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
|
||||
|
||||
draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "RTL+LEFT##1234567890");
|
||||
draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
|
||||
|
||||
draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "LTR+LEFT##1234567890");
|
||||
draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -159,7 +159,6 @@ private:
|
||||
|
||||
} // namespace
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -943,7 +942,6 @@ DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1106,7 +1104,6 @@ DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, index == 5);
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1146,7 +1143,6 @@ DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, index == 1);
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_BoldParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1193,7 +1189,6 @@ DEF_TEST(SkParagraph_BoldParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, index == 1);
|
||||
}
|
||||
|
||||
// Checked: NO DIFF (line height rounding error)
|
||||
DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1249,7 +1244,6 @@ DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
|
||||
}
|
||||
|
||||
// Checked: DIFF+
|
||||
DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1331,10 +1325,9 @@ DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
|
||||
REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
|
||||
REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
|
||||
REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);//
|
||||
REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1422,7 +1415,6 @@ DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
|
||||
paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1510,7 +1502,6 @@ DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
|
||||
paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1612,6 +1603,7 @@ DEF_TEST(SkParagraph_JustifyRTL, reporter) {
|
||||
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);
|
||||
|
||||
@ -1650,7 +1642,7 @@ DEF_TEST(SkParagraph_JustifyRTL, reporter) {
|
||||
RectWidthStyle rect_width_style = RectWidthStyle::kTight;
|
||||
auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 5);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 3);
|
||||
|
||||
boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
|
||||
canvas.drawRects(SK_ColorBLUE, boxes);
|
||||
@ -1780,7 +1772,6 @@ DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
|
||||
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>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1904,7 +1895,6 @@ DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
|
||||
SkDebugf("TODO: Add test for wavy decorations\n");
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -1969,7 +1959,6 @@ DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
|
||||
});
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -2018,7 +2007,7 @@ DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
|
||||
}
|
||||
|
||||
// Checked: NO DIFF (disabled)
|
||||
// Checked: disabled for TxtLib
|
||||
DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -2210,7 +2199,6 @@ DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -2275,7 +2263,6 @@ DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
|
||||
REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -2372,7 +2359,6 @@ DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
|
||||
}
|
||||
}
|
||||
|
||||
// Checked: NO DIFF
|
||||
DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
|
||||
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
|
||||
if (!fontCollection->fontsFound()) return;
|
||||
@ -4067,7 +4053,7 @@ DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
|
||||
}
|
||||
@ -4085,7 +4071,7 @@ DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
|
||||
}
|
||||
@ -4094,7 +4080,7 @@ DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 224.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
|
||||
}
|
||||
@ -4103,7 +4089,7 @@ DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 319.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
|
||||
}
|
||||
@ -4174,7 +4160,7 @@ DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
|
||||
}
|
||||
@ -4192,7 +4178,7 @@ DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
|
||||
}
|
||||
@ -4201,7 +4187,7 @@ DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 184, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
|
||||
}
|
||||
@ -4210,7 +4196,7 @@ DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 264, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
|
||||
}
|
||||
@ -4282,7 +4268,7 @@ DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
|
||||
}
|
||||
@ -4300,7 +4286,7 @@ DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
|
||||
}
|
||||
@ -4309,7 +4295,7 @@ DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 128, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
|
||||
}
|
||||
@ -4318,7 +4304,7 @@ DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes);
|
||||
REPORTER_ASSERT(reporter, boxes.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 188, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
|
||||
}
|
||||
@ -4386,7 +4372,7 @@ DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes3);
|
||||
REPORTER_ASSERT(reporter, boxes3.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 22.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
|
||||
|
||||
@ -4402,7 +4388,7 @@ DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes5);
|
||||
REPORTER_ASSERT(reporter, boxes5.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 22.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
|
||||
|
||||
@ -4410,7 +4396,7 @@ DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes6);
|
||||
REPORTER_ASSERT(reporter, boxes6.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 182.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
|
||||
|
||||
@ -4418,7 +4404,7 @@ DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
|
||||
canvas.drawRects(SK_ColorRED, boxes7);
|
||||
REPORTER_ASSERT(reporter, boxes7.size() == 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 262.5f, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
|
||||
}
|
||||
@ -4499,7 +4485,7 @@ DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
|
||||
TextStyle text_style;
|
||||
text_style.setFontStyle(SkFontStyle::Italic());
|
||||
text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
|
||||
text_style.setFontFamilies({SkString("Roboto")});
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user