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:
parent
4fb529595e
commit
2813d454f3
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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->layout(width());//758
|
||||
|
||||
//auto res1 = paragraph->getGlyphPositionAtCoordinate(line.width() + line.spacesWidth() / 2, line.offset().fY + 10);
|
||||
//auto res2 = paragraph->getWordBoundary(res1.position);
|
||||
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(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);
|
||||
for (size_t i = 0; i < 402; ++i) {
|
||||
//auto res1 = paragraph->getGlyphPositionAtCoordinate(fPoint.fX, fPoint.fY);
|
||||
//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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
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);
|
||||
}
|
||||
canvas->drawRect(r.rect, paint);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
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();)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user