Positioning in chinese glyphs

+small fix for placeholder in getGlyphPositionAtCoordinate

Bug: skia:12322
Change-Id: I8f03c5c808db54fc9742e5817768db4a088bc5b5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/440458
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
Julia Lavrova 2021-08-18 10:03:47 -04:00 committed by SkCQ
parent 6fc1f025f8
commit 0f629d7f48
2 changed files with 30 additions and 26 deletions

View File

@ -602,6 +602,7 @@ TextLine::ClipContext TextLine::measureTextInsideOneRun(TextRange textRange,
run->calculateHeight(this->fAscentStyle,this->fDescentStyle));
return result;
} else if (run->isPlaceholder()) {
result.fTextShift = runOffsetInLine;
if (SkScalarIsFinite(run->fFontMetrics.fAscent)) {
result.clip = SkRect::MakeXYWH(runOffsetInLine,
sizes().runTop(run, this->fAscentStyle),
@ -1227,30 +1228,14 @@ PositionWithAffinity TextLine::getGlyphPositionAtCoordinate(SkScalar dx) {
// Find the grapheme range that contains the point
auto clusterIndex8 = context.run->globalClusterIndex(found);
auto clusterEnd8 = context.run->globalClusterIndex(found + 1);
TextIndex graphemeUtf8Start =
fOwner->findPreviousGraphemeBoundary(clusterIndex8);
TextIndex graphemeUtf8Width =
fOwner->findNextGraphemeBoundary(clusterEnd8) - graphemeUtf8Start;
size_t utf16Index = fOwner->getUTF16Index(clusterIndex8);
SkScalar center = glyphemePosLeft + glyphemePosWidth / 2;
bool insideGlypheme = false;
if (graphemeUtf8Width > 1) {
// TODO: the average width of a code unit (especially UTF-8) is meaningless.
// Probably want the average width of a grapheme or codepoint?
SkScalar averageUtf8Width = glyphemePosWidth / graphemeUtf8Width;
SkScalar delta = dx - glyphemePosLeft;
int insideUtf8Offset = SkScalarNearlyZero(averageUtf8Width)
? 0
: SkScalarFloorToInt(delta / averageUtf8Width);
insideGlypheme = averageUtf8Width < delta && delta < glyphemePosWidth - averageUtf8Width;
center = glyphemePosLeft + averageUtf8Width * insideUtf8Offset + averageUtf8Width / 2;
// Keep UTF16 index as is
}
if ((dx < center) == context.run->leftToRight() || insideGlypheme) {
if ((dx < center) == context.run->leftToRight()) {
size_t utf16Index = fOwner->getUTF16Index(clusterIndex8);
result = { SkToS32(utf16Index), kDownstream };
} else {
result = { SkToS32(utf16Index + 1), kUpstream };
size_t utf16Index = fOwner->getUTF16Index(clusterEnd8);
result = { SkToS32(utf16Index), kUpstream };
}
return keepLooking = false;

View File

@ -6012,6 +6012,22 @@ DEF_TEST(SkParagraph_PositionInsideEmoji, reporter) {
paragraph->layout(TestCanvasWidth);
paragraph->paint(canvas.get(), 0, 0);
// UTF8 UTF16
// 4 [0:2)
// 3 + 4 [2:5)
// 3 + 4 [5:8)
// 3 + 4 [8:11)
// 4 [11:13)
// 4 [13:15)
// 4 [15:17)
// 4 [17:19)
auto family = paragraph->getRectsForRange(0, 11, RectHeightStyle::kTight, RectWidthStyle::kTight); // 00.0000000 + 17.4699993
auto face01 = paragraph->getRectsForRange(11, 13, RectHeightStyle::kTight, RectWidthStyle::kTight); // 17.4699993 + 17.4699993
auto face02 = paragraph->getRectsForRange(13, 15, RectHeightStyle::kTight, RectWidthStyle::kTight); // 34.9399986 + 17.4699993
auto face03 = paragraph->getRectsForRange(15, 17, RectHeightStyle::kTight, RectWidthStyle::kTight); // 52.4099998 + 17.4699993
auto face04 = paragraph->getRectsForRange(17, 19, RectHeightStyle::kTight, RectWidthStyle::kTight); // 69.8799973 + 17.4699993
int32_t words[] = { 11, 13, 15, 17, 19, 21};
auto j = 0;
for (auto i : words) {
@ -6019,11 +6035,13 @@ DEF_TEST(SkParagraph_PositionInsideEmoji, reporter) {
if (rects.empty()) {
continue;
}
auto X = rects[0].rect.fRight;
auto Y = rects[0].rect.fTop;
auto res = paragraph->getGlyphPositionAtCoordinate(X, Y);
//SkDebugf("[%d:%d) @%f,%f: %d %s\n", j, i, X, Y, res.position, res.affinity == Affinity::kDownstream ? "D" : "U");
REPORTER_ASSERT(reporter, i == res.position);
auto X = rects[0].rect.centerX();
auto Y = rects[0].rect.centerY();
auto res1 = paragraph->getGlyphPositionAtCoordinate(X - 5, Y);
//SkDebugf("[%d:%d) @%f,%f: %d %s\n", j, i, X - 5, Y, res1.position, res1.affinity == Affinity::kDownstream ? "D" : "U");
auto res2 = paragraph->getGlyphPositionAtCoordinate(X + 5, Y);
//SkDebugf("[%d:%d) @%f,%f: %d %s\n\n", j, i, X + 5, Y, res2.position, res2.affinity == Affinity::kDownstream ? "D" : "U");
REPORTER_ASSERT(reporter, i == res2.position && res1.position == j);
j = i;
}
}
@ -6452,7 +6470,7 @@ DEF_TEST(SkParagraph_PlaceholderPosition, reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
if (!fontCollection->fontsFound()) return;
TestCanvas canvas("SkParagraph_PlaceholderPosition");
TestCanvas canvas("SkParagraph_PlaceholderPosition.png");
canvas.get()->translate(100, 100);
TextStyle text_style;
@ -6474,6 +6492,7 @@ DEF_TEST(SkParagraph_PlaceholderPosition, reporter) {
auto paragraph = builder.Build();
paragraph->layout(500);
paragraph->paint(canvas.get(), 0, 0);
auto result = paragraph->getGlyphPositionAtCoordinate(41.0f, 0.0f);
REPORTER_ASSERT(reporter, result.position == 4 && result.affinity == Affinity::kDownstream);