提交 6d20d3c9 编写于 作者: G Gary Qian

Implement GetGlyphPositionAtCoordinate().

Change-Id: I78528de9d4fa1611ceb857790a3b3945c0988c9c
上级 20463c22
......@@ -169,6 +169,13 @@ void Paragraph::Layout(double width, bool force) {
// Reset member variables so Layout still works when called more than once
max_intrinsic_width_ = 0.0f;
lines_ = 0;
line_widths_ = std::vector<double>();
line_heights_ = std::vector<double>();
line_heights_.push_back(0);
glyph_position_x_ = std::vector<std::vector<double>>();
glyph_position_x_.push_back(std::vector<double>());
std::vector<double> glyph_single_line_position_x;
glyph_single_line_position_x.push_back(0);
SkScalar x = 0.0f;
SkScalar y = 0.0f;
......@@ -210,6 +217,32 @@ void Paragraph::Layout(double width, bool force) {
}
}
}
// Correct positions stored in the member vars.
for (size_t y_index = 0; y_index < lines_; ++y_index) {
switch (paragraph_style_.text_align) {
case TextAlign::left:
break;
case TextAlign::right: {
for (size_t i = 0; i < glyph_position_x_[y_index].size(); ++i) {
glyph_position_x_[y_index][i] +=
width_ - breaker_.getWidths()[y_index];
}
break;
}
case TextAlign::center: {
for (size_t i = 0; i < glyph_position_x_[y_index].size(); ++i) {
glyph_position_x_[y_index][i] +=
(width_ - breaker_.getWidths()[y_index]) / 2;
}
break;
}
case TextAlign::justify: {
// TODO(garyq): Track position changes due to justify in justify
// method.
break;
}
}
}
x_queue.clear();
};
for (size_t run_index = 0; run_index < runs_.size(); ++run_index) {
......@@ -261,6 +294,7 @@ void Paragraph::Layout(double width, bool force) {
letter_spacing_offset += run.style.letter_spacing;
// TODO(garyq): Implement RTL.
// Each Glyph/Letter.
bool whitespace_ended = true;
for (size_t blob_index = 0; blob_index < blob_length - trailing_length;
......@@ -283,6 +317,8 @@ void Paragraph::Layout(double width, bool force) {
buffers.back()->pos[pos_index] =
layout.getX(glyph_index) + letter_spacing_offset;
glyph_single_line_position_x.push_back(
buffers.back()->pos[pos_index]);
buffers.back()->pos[pos_index + 1] = layout.getY(glyph_index);
letter_spacing_offset += run.style.letter_spacing;
......@@ -337,6 +373,11 @@ void Paragraph::Layout(double width, bool force) {
if (layout_end == next_break) {
y += max_line_spacing + prev_max_descent;
line_heights_.push_back(
(line_heights_.empty() ? 0 : line_heights_.back()) +
max_line_spacing + max_descent);
glyph_single_line_position_x.push_back(FLT_MAX);
glyph_position_x_.push_back(glyph_single_line_position_x);
prev_max_descent = max_descent;
line_widths_.push_back(line_width);
postprocess_line();
......@@ -350,6 +391,8 @@ void Paragraph::Layout(double width, bool force) {
character_index = layout_end;
break_index += 1;
lines_++;
glyph_single_line_position_x = std::vector<double>();
glyph_single_line_position_x.push_back(0);
} else {
x += layout.getAdvance();
}
......@@ -358,11 +401,14 @@ void Paragraph::Layout(double width, bool force) {
}
}
y += max_line_spacing;
height_ = y + max_descent;
postprocess_line();
if (line_width != 0)
line_widths_.push_back(line_width);
height_ = y + max_descent;
line_heights_.push_back(FLT_MAX);
glyph_single_line_position_x.push_back(FLT_MAX);
glyph_position_x_.push_back(glyph_single_line_position_x);
}
// Amends the buffers to incorporate justification.
......@@ -565,6 +611,41 @@ void Paragraph::PaintWavyDecoration(SkCanvas* canvas,
}
}
std::vector<SkRect> Paragraph::GetRectsForRange(size_t start,
size_t end) const {
return std::vector<SkRect>();
}
size_t Paragraph::GetGlyphPositionAtCoordinate(double dx, double dy) const {
size_t offset = 0;
size_t y_index = 1;
size_t prev_count = 0;
for (y_index = 1; y_index < line_heights_.size(); ++y_index) {
if (dy < line_heights_[y_index]) {
offset += prev_count;
break;
} else {
offset += prev_count;
prev_count = glyph_position_x_[y_index].size() - 2;
}
}
prev_count = 0;
for (size_t x_index = 1; x_index < glyph_position_x_[y_index].size();
++x_index) {
if (dx < glyph_position_x_[y_index][x_index]) {
break;
} else {
offset += prev_count;
prev_count = 1;
}
}
return offset;
}
SkIPoint Paragraph::GetWordBoundary(size_t offset) const {
return SkIPoint::Make(0, 0);
}
int Paragraph::GetLineCount() const {
return lines_;
}
......
......@@ -27,6 +27,8 @@
#include "lib/txt/src/styled_runs.h"
#include "minikin/LineBreaker.h"
#include "third_party/gtest/include/gtest/gtest_prod.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkTextBlob.h"
class SkCanvas;
......@@ -55,6 +57,12 @@ class Paragraph {
double GetMinIntrinsicWidth() const;
std::vector<SkRect> GetRectsForRange(size_t start, size_t end) const;
size_t GetGlyphPositionAtCoordinate(double dx, double dy) const;
SkIPoint GetWordBoundary(size_t offset) const;
int GetLineCount() const;
bool DidExceedMaxLines() const;
......@@ -80,9 +88,13 @@ class Paragraph {
minikin::LineBreaker breaker_;
std::vector<PaintRecord> records_;
std::vector<double> line_widths_;
// TODO(garyq): Can we access this info without redundantly storing it here?
std::vector<double> line_heights_;
std::vector<std::vector<double>> glyph_position_x_;
ParagraphStyle paragraph_style_;
FontCollection* font_collection_;
// TODO(garyq): Height of the paragraph after Layout().
SkScalar height_ = 0.0f;
double width_ = 0.0f;
size_t lines_ = 0;
......
......@@ -340,6 +340,13 @@ TEST_F(RenderTest, LeftAlignParagraph) {
ASSERT_EQ(paragraph_style.text_align,
paragraph->GetParagraphStyle().text_align);
// Tests for GetGlyphPositionAtCoordinate()
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0, 0), 0ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 1), 0ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 30), 74ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 60), 142ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(2000, 30), 141ull);
ASSERT_TRUE(Snapshot());
}
......@@ -846,4 +853,54 @@ TEST_F(RenderTest, DISABLED_ArabicParagraph) {
ASSERT_TRUE(Snapshot());
}
TEST_F(RenderTest, GetGlyphPositionAtCoordinateParagraph) {
const char* text =
"12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
"67890";
auto icu_text = icu::UnicodeString::fromUTF8(text);
std::u16string u16_text(icu_text.getBuffer(),
icu_text.getBuffer() + icu_text.length());
txt::ParagraphStyle paragraph_style;
paragraph_style.max_lines = 10;
paragraph_style.text_align = TextAlign::left;
auto font_collection = FontCollection::GetFontCollection(txt::GetFontDir());
txt::ParagraphBuilder builder(paragraph_style, &font_collection);
txt::TextStyle text_style;
text_style.font_size = 50;
text_style.letter_spacing = 1;
text_style.word_spacing = 5;
text_style.color = SK_ColorBLACK;
text_style.height = 1.5;
builder.PushStyle(text_style);
builder.AddText(u16_text);
builder.Pop();
auto paragraph = builder.Build();
paragraph->Layout(GetTestCanvasWidth() - 500);
paragraph->Paint(GetCanvas(), 0, 0);
// Tests for GetGlyphPositionAtCoordinate()
// NOTE: resulting values can be a few off from their respective positions in
// the original text because the final trailing whitespaces are sometimes not
// drawn and therefore are not active glyphs.
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0, 0), 0ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(3, 3), 0ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(35, 1), 1ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(100000, 20), 16ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(100000, 80), 33ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 80), 17ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 160), 34ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(10000, 160), 50ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(70, 160), 36ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 270), 51ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(35, 80), 18ull);
ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(10000, 10000), 68ull);
ASSERT_TRUE(Snapshot());
}
} // namespace txt
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册