getRectsForRange results must be adjusted to glyphs.

Bug: skia:9957
Change-Id: I7c8537e8217288bf5d9d38950377cdacae705816
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274746
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
Julia Lavrova 2020-03-03 11:43:40 -05:00 committed by Skia Commit-Bot
parent 4fb529595e
commit 2813d454f3
3 changed files with 96 additions and 61 deletions

View File

@ -617,37 +617,14 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
return results;
}
// Snap text edges to the code points/grapheme edges
// Get the text that will be adjusted to cluster edges
TextRange text(fText.size(), fText.size());
if (start < fCodePoints.size()) {
auto startGrapheme = fGraphemes16[fCodePoints[start].fGrapheme];
auto lastGrapheme = fCodePoints[start].fGrapheme == fGraphemes16.size() - 1;
if (start > startGrapheme.fCodepointRange.start) {
if (end == startGrapheme.fCodepointRange.end &&
start == startGrapheme.fCodepointRange.end - 1) {
// This is a fix to make test GetRectsForRangeIncludeCombiningCharacter work
// Must be removed...
text.start = startGrapheme.fTextRange.start;
} else {
text.start = lastGrapheme && end >= fCodePoints.size()
? fCodePoints.back().fTextIndex
: startGrapheme.fTextRange.end;
}
} else {
text.start = startGrapheme.fTextRange.start;
}
text.start = fCodePoints[start].fTextIndex;
}
if (end < fCodePoints.size()) {
auto codepoint = fCodePoints[end];
auto endGrapheme = fGraphemes16[fCodePoints[end].fGrapheme];
if (text.start == endGrapheme.fTextRange.start &&
end + codepoint.fIndex == fCodePoints.size()) {
text.end = endGrapheme.fTextRange.end;
} else {
text.end = endGrapheme.fTextRange.start;
}
text.end = fCodePoints[end].fTextIndex;
}
auto firstBoxOnTheLine = results.size();
@ -815,6 +792,16 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
r.rect.fBottom = littleRound(r.rect.fBottom);
}
}
/*
SkDebugf("getRectsForRange(%d, %d)\n", start, end);
for (auto& r : results) {
r.rect.fLeft = littleRound(r.rect.fLeft);
r.rect.fRight = littleRound(r.rect.fRight);
r.rect.fTop = littleRound(r.rect.fTop);
r.rect.fBottom = littleRound(r.rect.fBottom);
SkDebugf("[%f:%f * %f:%f]\n", r.rect.fLeft, r.rect.fRight, r.rect.fTop, r.rect.fBottom);
}
*/
return results;
}

View File

@ -2409,7 +2409,7 @@ protected:
fontCollection->enableFontFallback();
ParagraphStyle paragraph_style;
paragraph_style.setTextAlign(TextAlign::kJustify);
//paragraph_style.setTextAlign(TextAlign::kJustify);
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
TextStyle text_style;
text_style.setColor(SK_ColorBLACK);
@ -2418,26 +2418,27 @@ protected:
builder.pushStyle(text_style);
builder.addText(text);
auto paragraph = builder.Build();
paragraph->layout(width());
paragraph->paint(canvas, 0, 0);
for (size_t i = 0; i < 402; ++i) {
//auto res1 = paragraph->getGlyphPositionAtCoordinate(fPoint.fX, fPoint.fY);
paragraph->layout(width());//758
//auto res1 = paragraph->getGlyphPositionAtCoordinate(line.width() + line.spacesWidth() / 2, line.offset().fY + 10);
//auto res2 = paragraph->getWordBoundary(res1.position);
auto res3 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kTight, RectWidthStyle::kTight);
if (res3.empty()) {
SkDebugf("empty: %f %d %d\n", width(), i, i + 1);
}
}
/*
auto res1 = paragraph->getRectsForRange(360, 361, RectHeightStyle::kTight, RectWidthStyle::kTight);
auto res2 = paragraph->getRectsForRange(359, 360, RectHeightStyle::kTight, RectWidthStyle::kTight);
auto res3 = paragraph->getRectsForRange(358, 359, RectHeightStyle::kTight, RectWidthStyle::kTight);
auto draw = [&](std::vector<TextBox> res, SkColor color) {
SkPaint paint;
paint.setColor(SK_ColorLTGRAY);
for (auto& r : res3) {
if (SkScalarNearlyZero(r.rect.fLeft) && SkScalarNearlyZero(r.rect.fTop)) {
SkDebugf("0, 0: %f %d %d\n", width(), res2.start, res2.end);
}
paint.setColor(color);
for (auto& r : res) {
canvas->drawRect(r.rect, paint);
}
*/
};
draw(res1, SK_ColorRED);
draw(res2, SK_ColorGREEN);
draw(res3, SK_ColorBLUE);
paragraph->paint(canvas, 0, 0);
}
private:
@ -2445,8 +2446,56 @@ private:
SkPoint fPoint;
};
//////////////////////////////////////////////////////////////////////////////
class ParagraphView36 : public ParagraphView_Base {
protected:
SkString name() override { return SkString("Paragraph36"); }
void onDrawContent(SkCanvas* canvas) override {
canvas->drawColor(SK_ColorWHITE);
auto text = u"\U0001f469\u200D\U0001f469\u200D\U0001f466\U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467\U0001f1fa\U0001f1f8";
auto fontCollection = sk_make_sp<FontCollection>();
fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
fontCollection->enableFontFallback();
ParagraphStyle paragraph_style;
paragraph_style.setTextAlign(TextAlign::kJustify);
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
TextStyle text_style;
text_style.setColor(SK_ColorBLACK);
text_style.setFontFamilies({SkString("Ahem")});
text_style.setFontSize(36);
builder.pushStyle(text_style);
builder.addText(text);
auto paragraph = builder.Build();
paragraph->layout(width());
auto draw = [&](std::vector<TextBox> res, SkColor color) {
SkPaint paint;
paint.setColor(color);
for (auto& r : res) {
canvas->drawRect(r.rect, paint);
}
};
auto res1 = paragraph->getRectsForRange(0, 2, RectHeightStyle::kTight, RectWidthStyle::kTight);
auto res2 = paragraph->getRectsForRange(0, 4, RectHeightStyle::kTight, RectWidthStyle::kTight);
auto res3 = paragraph->getRectsForRange(0, 8, RectHeightStyle::kTight, RectWidthStyle::kTight);
draw(res1, SK_ColorRED);
draw(res2, SK_ColorGREEN);
draw(res3, SK_ColorBLUE);
paragraph->paint(canvas, 0, 0);
}
private:
typedef Sample INHERITED;
};
//"\U0001f469\u200D\U0001f469\u200D\U0001f466\U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467\U0001f1fa\U0001f1f8"
//////////////////////////////////////////////////////////////////////////////
DEF_SAMPLE(return new ParagraphView1();)
DEF_SAMPLE(return new ParagraphView2();)
DEF_SAMPLE(return new ParagraphView3();)
@ -2481,3 +2530,4 @@ DEF_SAMPLE(return new ParagraphView32();)
DEF_SAMPLE(return new ParagraphView33();)
DEF_SAMPLE(return new ParagraphView34();)
DEF_SAMPLE(return new ParagraphView35();)
DEF_SAMPLE(return new ParagraphView36();)

View File

@ -2790,8 +2790,9 @@ DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
}
}
// Checked: NO DIFF
DEF_TEST(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
// This is the test I cannot accommodate
// Any text range gets a smallest glyph rectangle
DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
if (!fontCollection->fontsFound()) return;
TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
@ -3576,7 +3577,7 @@ DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
canvas.drawRects(SK_ColorRED, result);
result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
REPORTER_ASSERT(reporter, result.size() == 0); // There is no single glyph
REPORTER_ASSERT(reporter, result.size() == 1);
canvas.drawRects(SK_ColorBLUE, result);
auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
@ -3734,18 +3735,15 @@ DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
for (size_t i = 0; i < 12; ++i) {
auto r =
paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
.front()
.rect;
auto r1 =
paragraph1
->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
.front()
.rect;
// Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
REPORTER_ASSERT(reporter, r.fLeft == r1.fLeft);
REPORTER_ASSERT(reporter, r.fRight == r1.fRight);
REPORTER_ASSERT(reporter, r1.size() == r2.size());
if (!r1.empty() && !r2.empty()) {
REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
}
}
}