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:
parent
6fc1f025f8
commit
0f629d7f48
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user