Cache should work with INF values
Change-Id: I1ae8d95bb85d28fdce9e0cf270583f0224e4dfed
Bug: skia:9874
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268938
Commit-Queue: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/skparagraph/include/ParagraphStyle.h b/modules/skparagraph/include/ParagraphStyle.h
index 528c30b..542a8fa 100644
--- a/modules/skparagraph/include/ParagraphStyle.h
+++ b/modules/skparagraph/include/ParagraphStyle.h
@@ -37,6 +37,17 @@
bool getHeightOverride() const { return fHeightOverride; }
void setHeightOverride(bool v) { fHeightOverride = v; }
+ bool operator==(const StrutStyle& rhs) const {
+ return this->fEnabled == rhs.fEnabled &&
+ this->fHeightOverride == rhs.fHeightOverride &&
+ this->fForceHeight == rhs.fForceHeight &&
+ nearlyEqual(this->fLeading, rhs.fLeading) &&
+ nearlyEqual(this->fHeight, rhs.fHeight) &&
+ nearlyEqual(this->fFontSize, rhs.fFontSize) &&
+ this->fFontStyle == rhs.fFontStyle &&
+ this->fFontFamilies == rhs.fFontFamilies;
+ }
+
private:
std::vector<SkString> fFontFamilies;
diff --git a/modules/skparagraph/include/TextStyle.h b/modules/skparagraph/include/TextStyle.h
index 454dc38..08509d7 100644
--- a/modules/skparagraph/include/TextStyle.h
+++ b/modules/skparagraph/include/TextStyle.h
@@ -18,6 +18,21 @@
namespace skia {
namespace textlayout {
+static inline bool nearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero) {
+ if (SkScalarIsFinite(x)) {
+ return SkScalarNearlyZero(x, tolerance);
+ }
+ return false;
+}
+
+static inline bool nearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance = SK_ScalarNearlyZero) {
+ if (SkScalarIsFinite(x) && SkScalarIsFinite(x)) {
+ return SkScalarNearlyEqual(x, y, tolerance);
+ }
+ // Inf == Inf, anything else is false
+ return x == y;
+}
+
// Multiple decorations can be applied at once. Ex: Underline and overline is
// (0x1 | 0x2)
enum TextDecoration {
@@ -100,7 +115,13 @@
};
struct PlaceholderStyle {
- PlaceholderStyle() { }
+ PlaceholderStyle()
+ : fWidth(0)
+ , fHeight(0)
+ , fAlignment(PlaceholderAlignment::kBaseline)
+ , fBaseline(TextBaseline::kAlphabetic)
+ , fBaselineOffset(0) {}
+
PlaceholderStyle(SkScalar width, SkScalar height, PlaceholderAlignment alignment,
TextBaseline baseline, SkScalar offset)
: fWidth(width)
@@ -111,13 +132,10 @@
bool equals(const PlaceholderStyle& other) const;
- SkScalar fWidth = 0;
- SkScalar fHeight = 0;
-
+ SkScalar fWidth;
+ SkScalar fHeight;
PlaceholderAlignment fAlignment;
-
TextBaseline fBaseline;
-
// Distance from the top edge of the rect to the baseline position. This
// baseline will be aligned against the alphabetic baseline of the surrounding
// text.
@@ -126,7 +144,7 @@
// small or negative values will cause the rect to be positioned underneath
// the line. When baseline == height, the bottom edge of the rect will rest on
// the alphabetic baseline.
- SkScalar fBaselineOffset = 0;
+ SkScalar fBaselineOffset;
};
class TextStyle {
diff --git a/modules/skparagraph/src/OneLineShaper.cpp b/modules/skparagraph/src/OneLineShaper.cpp
index 22b7c72..b28a80a 100644
--- a/modules/skparagraph/src/OneLineShaper.cpp
+++ b/modules/skparagraph/src/OneLineShaper.cpp
@@ -483,7 +483,7 @@
run.fPositions[0] = { advanceX, 0 };
run.fOffsets[0] = {0, 0};
run.fClusterIndexes[0] = 0;
- run.fPlaceholder = &placeholder.fStyle;
+ run.fPlaceholderIndex = &placeholder - fParagraph->fPlaceholders.begin();
advanceX += placeholder.fStyle.fWidth;
}
return true;
diff --git a/modules/skparagraph/src/ParagraphCache.cpp b/modules/skparagraph/src/ParagraphCache.cpp
index 522ef7d..f98c496 100644
--- a/modules/skparagraph/src/ParagraphCache.cpp
+++ b/modules/skparagraph/src/ParagraphCache.cpp
@@ -8,8 +8,12 @@
namespace {
SkScalar relax(SkScalar a) {
// This rounding is done to match Flutter tests. Must be removed..
- auto threshold = SkIntToScalar(1 << 12);
- return SkScalarRoundToScalar(a * threshold)/threshold;
+ if (SkScalarIsFinite(a)) {
+ auto threshold = SkIntToScalar(1 << 12);
+ return SkScalarRoundToScalar(a * threshold)/threshold;
+ } else {
+ return a;
+ }
}
}
@@ -31,19 +35,15 @@
public:
ParagraphCacheValue(const ParagraphImpl* paragraph)
: fKey(ParagraphCacheKey(paragraph))
- , fInternalState(paragraph->fState)
, fRuns(paragraph->fRuns)
- , fClusters(paragraph->fClusters)
- , fUnresolvedGlyphs(paragraph->fUnresolvedGlyphs){ }
+ , fClusters(paragraph->fClusters) { }
// Input == key
ParagraphCacheKey fKey;
- // Shaped results:
- InternalState fInternalState;
+ // Shaped results
SkTArray<Run, false> fRuns;
SkTArray<Cluster, true> fClusters;
- size_t fUnresolvedGlyphs;
};
uint32_t ParagraphCache::KeyHash::mix(uint32_t hash, uint32_t data) const {
@@ -56,21 +56,20 @@
uint32_t ParagraphCache::KeyHash::operator()(const ParagraphCacheKey& key) const {
uint32_t hash = 0;
for (auto& ph : key.fPlaceholders) {
- if (&ph == &key.fPlaceholders.back()) {
- // Skip the last "dummy" placeholder
- break;
+ if (ph.fRange.width() == 0) {
+ continue;
}
hash = mix(hash, SkGoodHash()(ph.fRange.start));
hash = mix(hash, SkGoodHash()(ph.fRange.end));
- hash = mix(hash, SkGoodHash()(relax(ph.fStyle.fBaselineOffset)));
- hash = mix(hash, SkGoodHash()(ph.fStyle.fBaseline));
+ hash = mix(hash, SkGoodHash()(relax(ph.fStyle.fHeight)));
+ hash = mix(hash, SkGoodHash()(relax(ph.fStyle.fWidth)));
hash = mix(hash, SkGoodHash()(ph.fStyle.fAlignment));
+ hash = mix(hash, SkGoodHash()(ph.fStyle.fBaseline));
if (ph.fStyle.fAlignment == PlaceholderAlignment::kBaseline) {
hash = mix(hash, SkGoodHash()(relax(ph.fStyle.fBaselineOffset)));
}
- hash = mix(hash, SkGoodHash()(relax(ph.fStyle.fHeight)));
- hash = mix(hash, SkGoodHash()(relax(ph.fStyle.fWidth)));
}
+
for (auto& ts : key.fTextStyles) {
if (ts.fStyle.isPlaceholder()) {
continue;
@@ -79,22 +78,34 @@
hash = mix(hash, SkGoodHash()(relax(ts.fStyle.getWordSpacing())));
hash = mix(hash, SkGoodHash()(ts.fStyle.getLocale()));
hash = mix(hash, SkGoodHash()(relax(ts.fStyle.getHeight())));
- hash = mix(hash, SkGoodHash()(ts.fRange));
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()(ff.fValue));
+ hash = mix(hash, SkGoodHash()(ff.fName));
}
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()(ts.fRange));
}
hash = mix(hash, SkGoodHash()(relax(key.fParagraphStyle.getHeight())));
hash = mix(hash, SkGoodHash()(key.fParagraphStyle.getTextDirection()));
+ auto& strutStyle = key.fParagraphStyle.getStrutStyle();
+ if (strutStyle.getStrutEnabled()) {
+ hash = mix(hash, SkGoodHash()(relax(strutStyle.getHeight())));
+ hash = mix(hash, SkGoodHash()(relax(strutStyle.getLeading())));
+ hash = mix(hash, SkGoodHash()(relax(strutStyle.getFontSize())));
+ hash = mix(hash, SkGoodHash()(strutStyle.getHeightOverride()));
+ hash = mix(hash, SkGoodHash()(strutStyle.getFontStyle()));
+ hash = mix(hash, SkGoodHash()(strutStyle.getForceStrutHeight()));
+ for (auto& ff : strutStyle.getFontFamilies()) {
+ hash = mix(hash, SkGoodHash()(ff));
+ }
+ }
+
hash = mix(hash, SkGoodHash()(key.fText));
return hash;
}
@@ -114,13 +125,17 @@
}
// There is no need to compare default paragraph styles - they are included into fTextStyles
- if (!SkScalarNearlyEqual(a.fParagraphStyle.getHeight(), b.fParagraphStyle.getHeight())) {
+ if (!nearlyEqual(a.fParagraphStyle.getHeight(), b.fParagraphStyle.getHeight())) {
return false;
}
if (a.fParagraphStyle.getTextDirection() != b.fParagraphStyle.getTextDirection()) {
return false;
}
+ if (!(a.fParagraphStyle.getStrutStyle() == b.fParagraphStyle.getStrutStyle())) {
+ return false;
+ }
+
for (size_t i = 0; i < a.fTextStyles.size(); ++i) {
auto& tsa = a.fTextStyles[i];
auto& tsb = b.fTextStyles[i];
@@ -137,9 +152,12 @@
return false;
}
}
- for (size_t i = 0; i < a.fPlaceholders.size() - 1; ++i) {
+ for (size_t i = 0; i < a.fPlaceholders.size(); ++i) {
auto& tsa = a.fPlaceholders[i];
auto& tsb = b.fPlaceholders[i];
+ if (tsa.fRange.width() == 0 && tsb.fRange.width() == 0) {
+ continue;
+ }
if (!(tsa.fStyle.equals(tsb.fStyle))) {
return false;
}
@@ -175,7 +193,6 @@
void ParagraphCache::updateFrom(const ParagraphImpl* paragraph, Entry* entry) {
- entry->fValue->fInternalState = paragraph->state();
for (size_t i = 0; i < paragraph->fRuns.size(); ++i) {
auto& run = paragraph->fRuns[i];
if (run.fSpaced) {
@@ -185,6 +202,7 @@
}
void ParagraphCache::updateTo(ParagraphImpl* paragraph, const Entry* entry) {
+
paragraph->fRuns.reset();
paragraph->fRuns = entry->fValue->fRuns;
for (auto& run : paragraph->fRuns) {
@@ -197,8 +215,7 @@
cluster.setMaster(paragraph);
}
- paragraph->fState = entry->fValue->fInternalState;
- paragraph->fUnresolvedGlyphs = entry->fValue->fUnresolvedGlyphs;
+ paragraph->fState = kMarked;
}
void ParagraphCache::printStatistics() {
diff --git a/modules/skparagraph/src/ParagraphImpl.cpp b/modules/skparagraph/src/ParagraphImpl.cpp
index 5d6459b..66a20de 100644
--- a/modules/skparagraph/src/ParagraphImpl.cpp
+++ b/modules/skparagraph/src/ParagraphImpl.cpp
@@ -414,7 +414,7 @@
}
}
- fLongestLine = SkTMax(fLongestLine, SkScalarNearlyZero(advance.fX) ? widthWithSpaces : advance.fX);
+ fLongestLine = SkTMax(fLongestLine, nearlyZero(advance.fX) ? widthWithSpaces : advance.fX);
});
fHeight = textWrapper.height();
fWidth = maxWidth;
@@ -427,9 +427,17 @@
void ParagraphImpl::formatLines(SkScalar maxWidth) {
auto effectiveAlign = fParagraphStyle.effective_align();
+
+ if (!SkScalarIsFinite(maxWidth) && effectiveAlign != TextAlign::kLeft) {
+ // Special case: clean all text in case of maxWidth == INF & align != left
+ // We had to go through shaping though because we need all the measurement numbers
+ fLines.reset();
+ return;
+ }
if (effectiveAlign == TextAlign::kJustify) {
this->resetRunShifts();
}
+
for (auto& line : fLines) {
if (&line == &fLines.back() && effectiveAlign == TextAlign::kJustify) {
effectiveAlign = line.assumedTextAlign();
@@ -768,16 +776,16 @@
bool mergedBoxes = false;
if (!results.empty() &&
lastRun != nullptr &&
- lastRun->placeholder() == nullptr &&
- context.run->placeholder() == nullptr &&
- SkScalarNearlyEqual(lastRun->lineHeight(), context.run->lineHeight()) &&
+ lastRun->placeholderStyle() == nullptr &&
+ context.run->placeholderStyle() == nullptr &&
+ nearlyEqual(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)))
+ if (nearlyEqual(lastBox.rect.fTop, clip.fTop) &&
+ nearlyEqual(lastBox.rect.fBottom, clip.fBottom) &&
+ (nearlyEqual(lastBox.rect.fLeft, clip.fRight) ||
+ nearlyEqual(lastBox.rect.fRight, clip.fLeft)))
{
lastBox.rect.fLeft = SkTMin(lastBox.rect.fLeft, clip.fLeft);
lastBox.rect.fRight = SkTMax(lastBox.rect.fRight, clip.fRight);
@@ -792,7 +800,7 @@
results.emplace_back(
clip, context.run->leftToRight() ? TextDirection::kLtr : TextDirection::kRtl);
}
- if (!SkScalarNearlyZero(trailingSpaces.width()) && !merge(trailingSpaces)) {
+ if (!nearlyZero(trailingSpaces.width()) && !merge(trailingSpaces)) {
results.emplace_back(trailingSpaces, paragraphTextDirection);
}
@@ -843,7 +851,7 @@
auto context =
line.measureTextInsideOneRun(textRange, run, runOffset, 0, true, false);
*width = context.clip.width();
- if (run->placeholder() == nullptr) {
+ if (run->placeholderStyle() == nullptr) {
return true;
}
if (run->textRange().width() == 0) {
@@ -1120,7 +1128,9 @@
fEmptyMetrics.leading() * multiplier);
}
- fStrutMetrics.updateLineMetrics(fEmptyMetrics);
+ if (fParagraphStyle.getStrutStyle().getStrutEnabled()) {
+ 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 fd39e10..2f4d2cd 100644
--- a/modules/skparagraph/src/ParagraphImpl.h
+++ b/modules/skparagraph/src/ParagraphImpl.h
@@ -135,6 +135,9 @@
SkSpan<Block> styles() {
return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
}
+ SkSpan<Placeholder> placeholders() {
+ return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
+ }
SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
diff --git a/modules/skparagraph/src/Run.cpp b/modules/skparagraph/src/Run.cpp
index 8d9ad08..bc1618e 100644
--- a/modules/skparagraph/src/Run.cpp
+++ b/modules/skparagraph/src/Run.cpp
@@ -47,7 +47,7 @@
fOffsets[info.glyphCount] = { 0, 0};
fClusterIndexes[info.glyphCount] = this->leftToRight() ? info.utf8Range.end() : info.utf8Range.begin();
fEllipsis = false;
- fPlaceholder = nullptr;
+ fPlaceholderIndex = std::numeric_limits<size_t>::max();
}
SkShaper::RunHandler::Buffer Run::newRunBuffer() {
@@ -238,9 +238,11 @@
void Run::updateMetrics(InternalLineMetrics* endlineMetrics) {
+ SkASSERT(isPlaceholder());
+ auto placeholderStyle = this->placeholderStyle();
// Difference between the placeholder baseline and the line bottom
SkScalar baselineAdjustment = 0;
- switch (fPlaceholder->fBaseline) {
+ switch (placeholderStyle->fBaseline) {
case TextBaseline::kAlphabetic:
break;
@@ -249,11 +251,11 @@
break;
}
- auto height = fPlaceholder->fHeight;
- auto offset = fPlaceholder->fBaselineOffset;
+ auto height = placeholderStyle->fHeight;
+ auto offset = placeholderStyle->fBaselineOffset;
fFontMetrics.fLeading = 0;
- switch (fPlaceholder->fAlignment) {
+ switch (placeholderStyle->fAlignment) {
case PlaceholderAlignment::kBaseline:
fFontMetrics.fAscent = baselineAdjustment - offset;
fFontMetrics.fDescent = baselineAdjustment + height - offset;
@@ -339,6 +341,14 @@
return posX(pos) + fShifts[pos] + fMaster->posShift(fIndex, pos);
}
+PlaceholderStyle* Run::placeholderStyle() const {
+ if (isPlaceholder()) {
+ return &fMaster->placeholders()[fPlaceholderIndex].fStyle;
+ } else {
+ return nullptr;
+ }
+}
+
Run* Cluster::run() const {
if (fRunIndex >= fMaster->runs().size()) {
return nullptr;
diff --git a/modules/skparagraph/src/Run.h b/modules/skparagraph/src/Run.h
index 498e74d..3cc5d38 100644
--- a/modules/skparagraph/src/Run.h
+++ b/modules/skparagraph/src/Run.h
@@ -104,8 +104,8 @@
bool leftToRight() const { return fBidiLevel % 2 == 0; }
size_t index() const { return fIndex; }
SkScalar lineHeight() const { return fHeightMultiplier; }
- PlaceholderStyle* placeholder() const { return fPlaceholder; }
- bool isPlaceholder() const { return fPlaceholder != nullptr; }
+ PlaceholderStyle* placeholderStyle() const;
+ bool isPlaceholder() const { return fPlaceholderIndex != std::numeric_limits<size_t>::max(); }
size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; }
SkScalar positionX(size_t pos) const;
@@ -177,7 +177,7 @@
SkFont fFont;
SkFontMetrics fFontMetrics;
SkScalar fHeightMultiplier;
- PlaceholderStyle* fPlaceholder;
+ size_t fPlaceholderIndex;
bool fEllipsis;
size_t fIndex;
uint8_t fBidiLevel;
diff --git a/modules/skparagraph/src/TextLine.cpp b/modules/skparagraph/src/TextLine.cpp
index 39e8651..25af76d 100644
--- a/modules/skparagraph/src/TextLine.cpp
+++ b/modules/skparagraph/src/TextLine.cpp
@@ -34,7 +34,7 @@
// It has to be relative to be useful
auto base = SkTMax(SkScalarAbs(a), SkScalarAbs(b));
auto diff = SkScalarAbs(a - b);
- if (SkScalarNearlyZero(base) || diff / base < 0.001f) {
+ if (nearlyZero(base) || diff / base < 0.001f) {
return 0;
}
@@ -223,7 +223,7 @@
this->iterateThroughVisualRuns(false,
[textCanvas, this]
(const Run* run, SkScalar runOffsetInLine, TextRange textRange, SkScalar* runWidthInLine) {
- if (run->placeholder() != nullptr) {
+ if (run->placeholderStyle() != nullptr) {
*runWidthInLine = run->advance().fX;
return true;
}
@@ -300,7 +300,7 @@
void TextLine::paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const {
- if (context.run->placeholder() != nullptr) {
+ if (context.run->placeholderStyle() != nullptr) {
return;
}
@@ -578,7 +578,7 @@
return true;
});
- SkAssertResult(SkScalarNearlyEqual(shift, maxWidth - textLen));
+ SkAssertResult(nearlyEqual(shift, maxWidth - textLen));
SkASSERT(whitespacePatches == 0);
this->fWidthWithSpaces += ghostShift;
@@ -644,7 +644,7 @@
void commitRunBuffer(const RunInfo& info) override {
fRun->fAdvance.fX = info.fAdvance.fX;
fRun->fAdvance.fY = fRun->advance().fY;
- fRun->fPlaceholder = nullptr;
+ fRun->fPlaceholderIndex = std::numeric_limits<size_t>::max();
fRun->fEllipsis = true;
}
@@ -673,7 +673,7 @@
bool limitToClusters) const {
ClipContext result = { run, 0, run->size(), 0, SkRect::MakeEmpty(), false };
- if (run->placeholder() != nullptr || run->fEllipsis) {
+ if (run->placeholderStyle() != nullptr || run->fEllipsis) {
// Both ellipsis and placeholders can only be measured as one glyph
SkASSERT(textRange == run->textRange());
result.fTextShift = runOffsetInLine;
@@ -931,7 +931,7 @@
this->iterateThroughVisualRuns(false,
[this, &result]
(const Run* run, SkScalar runOffsetInLine, TextRange textRange, SkScalar* runWidthInLine) {
- if (run->placeholder() != nullptr) {
+ if (run->placeholderStyle() != nullptr) {
*runWidthInLine = run->advance().fX;
return true;
}
diff --git a/modules/skparagraph/src/TextStyle.cpp b/modules/skparagraph/src/TextStyle.cpp
index e3d645c..d4ce181 100644
--- a/modules/skparagraph/src/TextStyle.cpp
+++ b/modules/skparagraph/src/TextStyle.cpp
@@ -108,10 +108,10 @@
fFontStyle == that.fFontStyle &&
fFontFamilies == that.fFontFamilies &&
fFontFeatures == that.fFontFeatures &&
- SkScalarNearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
- SkScalarNearlyEqual(fWordSpacing, that.fWordSpacing) &&
- SkScalarNearlyEqual(fHeight, that.fHeight) &&
- SkScalarNearlyEqual(fFontSize, that.fFontSize) &&
+ nearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
+ nearlyEqual(fWordSpacing, that.fWordSpacing) &&
+ nearlyEqual(fHeight, that.fHeight) &&
+ nearlyEqual(fFontSize, that.fFontSize) &&
fLocale == that.fLocale;
}
@@ -180,12 +180,12 @@
}
bool PlaceholderStyle::equals(const PlaceholderStyle& other) const {
- return SkScalarNearlyEqual(fWidth, other.fWidth) &&
- SkScalarNearlyEqual(fHeight, other.fHeight) &&
+ return nearlyEqual(fWidth, other.fWidth) &&
+ nearlyEqual(fHeight, other.fHeight) &&
fAlignment == other.fAlignment &&
fBaseline == other.fBaseline &&
(fAlignment != PlaceholderAlignment::kBaseline ||
- SkScalarNearlyEqual(fBaselineOffset, other.fBaselineOffset));
+ nearlyEqual(fBaselineOffset, other.fBaselineOffset));
}
} // namespace textlayout
diff --git a/modules/skparagraph/src/TextWrapper.cpp b/modules/skparagraph/src/TextWrapper.cpp
index c2891a6..8d3f163 100644
--- a/modules/skparagraph/src/TextWrapper.cpp
+++ b/modules/skparagraph/src/TextWrapper.cpp
@@ -220,7 +220,7 @@
continue;
}
lastRun = cluster->run();
- if (lastRun->placeholder() != nullptr) {
+ if (lastRun->placeholderStyle() != nullptr) {
SkASSERT(lastRun->size() == 1);
// Update the placeholder metrics so we can get the placeholder positions later
// and the line metrics (to make sure the placeholder fits)
diff --git a/modules/skparagraph/src/TextWrapper.h b/modules/skparagraph/src/TextWrapper.h
index 0db41cc..ab24648 100644
--- a/modules/skparagraph/src/TextWrapper.h
+++ b/modules/skparagraph/src/TextWrapper.h
@@ -112,7 +112,7 @@
if (fEnd.cluster() != nullptr &&
fEnd.cluster()->master() != nullptr &&
fEnd.cluster()->run() != nullptr &&
- fEnd.cluster()->run()->placeholder() == nullptr &&
+ fEnd.cluster()->run()->placeholderStyle() == nullptr &&
fWidth > 0) {
fWidth -= (fEnd.cluster()->width() - fEnd.cluster()->trimmedWidth(fEnd.position()));
}
diff --git a/samplecode/SampleParagraph.cpp b/samplecode/SampleParagraph.cpp
index 8141c14..9bccc41 100644
--- a/samplecode/SampleParagraph.cpp
+++ b/samplecode/SampleParagraph.cpp
@@ -1869,27 +1869,61 @@
void onDrawContent(SkCanvas* canvas) override {
canvas->drawColor(SK_ColorWHITE);
-
- const char* text = "Overflowing endorsement that has a large lengthy text and is a lot longer than expected";
+/*
+ * Shell: ParagraphStyle: 1.000000 1
+Shell: Strut enabled: 0 1.000000 14.000000 400 5 0
+Shell: Font Families: 0
+Shell: DefaultTextStyle: 16.000000 500 5 0
+Shell: Font Families: 1 Roboto
+Shell: Font Features: 0
+Shell: TextStyle#0: [0:22) 16.000000 500 5 0
+Shell: Font Families: 1 Roboto
+Shell: Font Features: 0
+Shell: TextStyle#1: [25:49) 16.000000 500 5 0
+Shell: Font Families: 1 Roboto
+Shell: Font Features: 0
+Shell: Placeholder#0: [22:25) 32.000000 32.000000 32.000000 0 5
+Shell: Placeholder#1: [49:52) 19.000000 41.000000 19.000000 0 4
+Shell: Placeholder#2: [52:52) 0.000000 0.000000 0.000000 0 5
+Shell: layout('Go to device settings  and set up a passcode. ', 280.000000): 280.000000 * 38.000000
+ */
+ auto fontCollection = getFontCollection();
+ //fontCollection->getParagraphCache()->turnOn(false);
+ const char* text1 = "Go to device settings ";
+ const char* text2 = "and set up a passcode.";
ParagraphStyle paragraph_style;
- paragraph_style.setEllipsis(u"\u2026");
- paragraph_style.setMaxLines(std::numeric_limits<size_t>::max());
- ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
+ StrutStyle strut_style;
+ strut_style.setStrutEnabled(false);
+ strut_style.setFontSize(14);
+ strut_style.setForceStrutHeight(false);
+ strut_style.setHeight(14);
+ paragraph_style.setStrutStyle(strut_style);
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(594.0f);
- paragraph->paint(canvas, 0, 0);
- canvas->translate(0, 200);
- paragraph->layout(std::numeric_limits<SkScalar>::max());
- paragraph->paint(canvas, 0, 0);
- canvas->translate(0, 200);
- paragraph->layout(787.0f);
- paragraph->paint(canvas, 0, 0);
+ text_style.setFontFamilies({SkString("Roboto")});
+ text_style.setFontSize(16);
+ PlaceholderStyle placeholder_style;
+ {
+ ParagraphBuilderImpl builder(paragraph_style, fontCollection);
+ builder.pushStyle(text_style);
+ builder.addText(text1);
+ placeholder_style.fHeight = 32;
+ placeholder_style.fWidth = 32;
+ placeholder_style.fBaselineOffset = 32;
+ placeholder_style.fBaseline = TextBaseline::kAlphabetic;
+ placeholder_style.fAlignment = PlaceholderAlignment::kMiddle;
+ builder.addPlaceholder(placeholder_style);
+ builder.addText(text2);
+ placeholder_style.fHeight = 19;
+ placeholder_style.fWidth = 41;
+ placeholder_style.fBaselineOffset = 19;
+ placeholder_style.fBaseline = TextBaseline::kAlphabetic;
+ placeholder_style.fAlignment = PlaceholderAlignment::kTop;
+ builder.addPlaceholder(placeholder_style);
+ auto paragraph = builder.Build();
+ paragraph->layout(280);
+ paragraph->paint(canvas, 0, 0);
+ }
}
private:
@@ -2089,5 +2123,5 @@
DEF_SAMPLE(return new ParagraphView23();)
DEF_SAMPLE(return new ParagraphView24();)
DEF_SAMPLE(return new ParagraphView25();)
-DEF_SAMPLE(return new ParagraphView26();)
-DEF_SAMPLE(return new ParagraphView27();)
+//DEF_SAMPLE(return new ParagraphView26();)
+//DEF_SAMPLE(return new ParagraphView27();)
diff --git a/tests/SkParagraphTest.cpp b/tests/SkParagraphTest.cpp
index 9378773..1c9a38f 100644
--- a/tests/SkParagraphTest.cpp
+++ b/tests/SkParagraphTest.cpp
@@ -5223,3 +5223,55 @@
//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
};
+
+DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
+ sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
+ if (!fontCollection->fontsFound()) return;
+ fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
+ TestCanvas canvas("SkParagraph_FormattingInfinity.png");
+
+ const char* text = "Some text\nAnother line";
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorBLACK);
+
+ TextStyle textStyle;
+ textStyle.setForegroundColor(paint);
+ textStyle.setFontFamilies({ SkString("Roboto") });
+ ParagraphStyle paragraphStyle;
+ paragraphStyle.setTextStyle(textStyle);
+
+ auto draw = [&](const char* prefix, TextAlign textAlign) {
+ paragraphStyle.setTextAlign(textAlign);
+ ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
+ builder.addText(text);
+ auto paragraph = builder.Build();
+ paragraph->layout(SK_ScalarInfinity);
+ paragraph->paint(canvas.get(), 0, 0);
+ canvas.get()->translate(0, 100);
+ };
+
+ draw("left", TextAlign::kLeft);
+ draw("right", TextAlign::kRight);
+ draw("center", TextAlign::kCenter);
+ draw("justify", TextAlign::kJustify);
+};
+
+DEF_TEST(SkParagraph_Infinity, reporter) {
+ SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
+ SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
+ SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
+
+ SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
+ SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
+ SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
+
+ SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
+ SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
+ SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
+
+ SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
+ SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
+ SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
+};