Round unresolved font blocks to grapheme edges
I had to stage the change with SK_PARAGRAPH_GRAPHEME_EDGES because of some google3 tests. Bug: skia:11196 Change-Id: Ic45e43e6c69f649c6bc0fedcc6f303891139b85e Reviewed-on: https://skia-review.googlesource.com/c/skia/+/359566 Commit-Queue: Julia Lavrova <jlavrova@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
d6b26e5f06
commit
d20a1097e8
@ -3268,6 +3268,116 @@ private:
|
||||
using INHERITED = Sample;
|
||||
};
|
||||
|
||||
class ParagraphView54 : public ParagraphView_Base {
|
||||
protected:
|
||||
SkString name() override { return SkString("Paragraph54"); }
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
//std::string text("يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
|
||||
//auto text = "ד👨👩👧👦😀";
|
||||
auto text = "👨👩👧👦😀";
|
||||
|
||||
//auto fontCollection = sk_make_sp<FontCollection>();
|
||||
auto fontCollection = getFontCollection();
|
||||
fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
|
||||
fontCollection->enableFontFallback();
|
||||
//fontCollection->disableFontFallback();
|
||||
|
||||
ParagraphStyle paragraph_style;
|
||||
//paragraph_style.setTextDirection(TextDirection::kRtl);
|
||||
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
TextStyle text_style;
|
||||
text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
|
||||
text_style.setFontSize(36);
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(/*360*/width());
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
using INHERITED = Sample;
|
||||
};
|
||||
|
||||
class ParagraphView55 : public ParagraphView_Base {
|
||||
protected:
|
||||
SkString name() override { return SkString("Paragraph55"); }
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
std::string text("يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
|
||||
|
||||
//auto fontCollection = sk_make_sp<FontCollection>();
|
||||
//fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
|
||||
//fontCollection->enableFontFallback();
|
||||
auto fontCollection = getFontCollection();
|
||||
fontCollection->disableFontFallback();
|
||||
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.setTextDirection(TextDirection::kRtl);
|
||||
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
TextStyle text_style;
|
||||
text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
|
||||
text_style.setFontSize(64);
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text.substr(0, 10).data());
|
||||
text_style.setColor(SK_ColorRED);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text.substr(10, 20).data());
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text.substr(30, 50).data());
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(/*360*/width());
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
using INHERITED = Sample;
|
||||
};
|
||||
|
||||
class ParagraphView56 : public ParagraphView_Base {
|
||||
protected:
|
||||
SkString name() override { return SkString("Paragraph56"); }
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
auto text = "BAM BAM BAM by Jade Baraldo\n"
|
||||
"Now on Top 100 Music Videos United States";
|
||||
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
|
||||
fontCollection->addFontFromFile("music/Roboto-Regular.ttf", "roboto");
|
||||
fontCollection->addFontFromFile("music/NotoSansCJK-Regular.ttc", "noto");
|
||||
fontCollection->addFontFromFile("music/NotoColorEmoji.ttf", "emoji");
|
||||
|
||||
ParagraphStyle paragraph_style;
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
TextStyle text_style;
|
||||
//text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
|
||||
text_style.setFontFamilies({SkString("roboto"),
|
||||
SkString("noto"),
|
||||
SkString("emoji")});
|
||||
text_style.setFontSize(20);
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(width());
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
using INHERITED = Sample;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -3322,3 +3432,6 @@ DEF_SAMPLE(return new ParagraphView50();)
|
||||
DEF_SAMPLE(return new ParagraphView51();)
|
||||
DEF_SAMPLE(return new ParagraphView52();)
|
||||
DEF_SAMPLE(return new ParagraphView53();)
|
||||
DEF_SAMPLE(return new ParagraphView54();)
|
||||
DEF_SAMPLE(return new ParagraphView55();)
|
||||
DEF_SAMPLE(return new ParagraphView56();)
|
||||
|
@ -19,7 +19,12 @@ void OneLineShaper::commitRunBuffer(const RunInfo&) {
|
||||
fCurrentRun->commit();
|
||||
|
||||
auto oldUnresolvedCount = fUnresolvedBlocks.size();
|
||||
|
||||
/*
|
||||
SkDebugf("Run [%d:%d)\n", fCurrentRun->fTextRange.start, fCurrentRun->fTextRange.end);
|
||||
for (size_t i = 0; i < fCurrentRun->size(); ++i) {
|
||||
SkDebugf("[%d] %d %d %f\n", i, fCurrentRun->fGlyphs[i], fCurrentRun->fClusterIndexes[i], fCurrentRun->fPositions[i].fX);
|
||||
}
|
||||
*/
|
||||
// Find all unresolved blocks
|
||||
sortOutGlyphs([&](GlyphRange block){
|
||||
if (block.width() == 0) {
|
||||
@ -291,6 +296,60 @@ void OneLineShaper::addUnresolvedWithRun(GlyphRange glyphRange) {
|
||||
|
||||
// Glue whitespaces to the next/prev unresolved blocks
|
||||
// (so we don't have chinese text with english whitespaces broken into millions of tiny runs)
|
||||
#ifndef SK_PARAGRAPH_GRAPHEME_EDGES
|
||||
void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock) {
|
||||
|
||||
size_t unresolvedGlyphs = 0;
|
||||
|
||||
GlyphRange block = EMPTY_RANGE;
|
||||
bool graphemeResolved = false;
|
||||
TextIndex graphemeStart = EMPTY_INDEX;
|
||||
for (size_t i = 0; i < fCurrentRun->size(); ++i) {
|
||||
|
||||
ClusterIndex ci = clusterIndex(i);
|
||||
// Removing all pretty optimizations for whitespaces
|
||||
// because they get in a way of grapheme rounding
|
||||
// Inspect the glyph
|
||||
auto glyph = fCurrentRun->fGlyphs[i];
|
||||
|
||||
GraphemeIndex gi = fParagraph->findPreviousGraphemeBoundary(ci);
|
||||
if ((fCurrentRun->leftToRight() ? gi > graphemeStart : gi < graphemeStart) || graphemeStart == EMPTY_INDEX) {
|
||||
// We only count glyph resolved if all the glyphs in its grapheme are resolved
|
||||
graphemeResolved = glyph != 0;
|
||||
graphemeStart = gi;
|
||||
} else if (glyph == 0) {
|
||||
// Found unresolved glyph - the entire grapheme is unresolved now
|
||||
graphemeResolved = false;
|
||||
}
|
||||
|
||||
if (!graphemeResolved) { // Unresolved glyph and not control codepoint
|
||||
++unresolvedGlyphs;
|
||||
if (block.start == EMPTY_INDEX) {
|
||||
// Start new unresolved block
|
||||
block.start = i;
|
||||
block.end = EMPTY_INDEX;
|
||||
} else {
|
||||
// Keep skipping unresolved block
|
||||
}
|
||||
} else { // Resolved glyph or control codepoint
|
||||
if (block.start == EMPTY_INDEX) {
|
||||
// Keep skipping resolved code points
|
||||
} else {
|
||||
// This is the end of unresolved block
|
||||
block.end = i;
|
||||
sortOutUnresolvedBLock(block);
|
||||
block = EMPTY_RANGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// One last block could have been left
|
||||
if (block.start != EMPTY_INDEX) {
|
||||
block.end = fCurrentRun->size();
|
||||
sortOutUnresolvedBLock(block);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock) {
|
||||
|
||||
auto text = fCurrentRun->fOwner->text();
|
||||
@ -353,6 +412,7 @@ void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnres
|
||||
sortOutUnresolvedBLock(block);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OneLineShaper::iterateThroughFontStyles(TextRange textRange,
|
||||
SkSpan<Block> styleSpan,
|
||||
|
@ -45,7 +45,6 @@
|
||||
|
||||
struct GrContextOptions;
|
||||
|
||||
|
||||
#define VeryLongCanvasWidth 1000000
|
||||
#define TestCanvasWidth 1000
|
||||
#define TestCanvasHeight 600
|
||||
@ -1239,11 +1238,7 @@ DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
|
||||
paragraph->layout(550);
|
||||
|
||||
auto impl = static_cast<ParagraphImpl*>(paragraph.get());
|
||||
#ifdef SK_PARAGRAPH_LIBTXT_SPACES_RESOLUTION
|
||||
REPORTER_ASSERT(reporter, impl->runs().size() == 5);
|
||||
#else
|
||||
REPORTER_ASSERT(reporter, impl->runs().size() == 4);
|
||||
#endif
|
||||
REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
|
||||
REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
|
||||
|
||||
@ -3990,13 +3985,8 @@ DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
|
||||
paragraph->layout(TestCanvasWidth);
|
||||
paragraph->paint(canvas.get(), 10.0, 15.0);
|
||||
|
||||
#ifdef SK_PARAGRAPH_LIBTXT_SPACES_RESOLUTION
|
||||
size_t spaceRun = 1;
|
||||
REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1 ("字典" - excluding the last space)
|
||||
#else
|
||||
size_t spaceRun = 0;
|
||||
REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 3); // From the text1 ("字典 " - including the last space)
|
||||
#endif
|
||||
|
||||
auto impl = static_cast<ParagraphImpl*>(paragraph.get());
|
||||
|
||||
@ -4009,9 +3999,7 @@ DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
|
||||
// [Apple + Han] 5, 6
|
||||
auto robotoAdvance = impl->runs()[0].advance().fX +
|
||||
impl->runs()[1].advance().fX;
|
||||
#ifdef SK_PARAGRAPH_LIBTXT_SPACES_RESOLUTION
|
||||
robotoAdvance += impl->runs()[2].advance().fX;
|
||||
#endif
|
||||
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[2 + spaceRun].advance().fX, 139.125f, EPSILON100));
|
||||
@ -5503,11 +5491,7 @@ DEF_TEST(SkParagraph_FontResolutionInRTL, reporter) {
|
||||
paragraph->paint(canvas.get(), 0, 0);
|
||||
|
||||
auto impl = static_cast<ParagraphImpl*>(paragraph.get());
|
||||
#ifdef SK_PARAGRAPH_LIBTXT_SPACES_RESOLUTION
|
||||
REPORTER_ASSERT(reporter, impl->runs().size() == (10 + 11));
|
||||
#else
|
||||
REPORTER_ASSERT(reporter, impl->runs().size() == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
DEF_TEST(SkParagraph_FontResolutionInLTR, reporter) {
|
||||
@ -5534,20 +5518,12 @@ DEF_TEST(SkParagraph_FontResolutionInLTR, reporter) {
|
||||
paragraph->paint(canvas.get(), 0, 0);
|
||||
|
||||
auto impl = static_cast<ParagraphImpl*>(paragraph.get());
|
||||
#ifdef SK_PARAGRAPH_LIBTXT_SPACES_RESOLUTION
|
||||
REPORTER_ASSERT(reporter, impl->runs().size() == 5);
|
||||
REPORTER_ASSERT(reporter, impl->runs()[0].textRange().width() == 4); // "abc "
|
||||
REPORTER_ASSERT(reporter, impl->runs()[1].textRange().width() == 2); // "{unresolved}"
|
||||
REPORTER_ASSERT(reporter, impl->runs()[2].textRange().width() == 1); // " "
|
||||
REPORTER_ASSERT(reporter, impl->runs()[3].textRange().width() == 2); // "{unresolved}"
|
||||
REPORTER_ASSERT(reporter, impl->runs()[4].textRange().width() == 4); // " def"
|
||||
#else
|
||||
REPORTER_ASSERT(reporter, impl->runs().size() == 3);
|
||||
REPORTER_ASSERT(reporter, impl->runs()[0].textRange().width() == 4); // "abc "
|
||||
REPORTER_ASSERT(reporter, impl->runs()[1].textRange().width() == 5); // "{unresolved} {unresolved}"
|
||||
REPORTER_ASSERT(reporter, impl->runs()[2].textRange().width() == 4); // " def"
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
DEF_TEST(SkParagraph_Intrinsic, reporter) {
|
||||
@ -5818,3 +5794,5 @@ DEF_TEST(SkParagraph_PlaceholderWidth, reporter) {
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(len1, 300.0f));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(len2, 250.0f));
|
||||
}
|
||||
|
||||
// "\u05D3\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}\uD83D\uDE00"
|
||||
|
@ -723,6 +723,7 @@ def base_defines(os_conditions):
|
||||
# Google3 probably doesn't want this feature yet
|
||||
"SK_DISABLE_REDUCE_OPLIST_SPLITTING",
|
||||
# Staging flags for API changes
|
||||
"SK_PARAGRAPH_GRAPHEME_EDGES",
|
||||
# Should remove after we update golden images
|
||||
"SK_WEBP_ENCODER_USE_DEFAULT_METHOD",
|
||||
# Experiment to diagnose image diffs in Google3
|
||||
|
Loading…
Reference in New Issue
Block a user