RTL Paragraph + all it causes
Change-Id: Ia8711bf8a002af7ca9ae603cdd9a109c8af86360 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/264640 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
parent
23f29761a6
commit
9bd8351ef3
@ -333,7 +333,6 @@ void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnres
|
||||
block.end = fCurrentRun->size();
|
||||
sortOutUnresolvedBLock(block);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OneLineShaper::iterateThroughFontStyles(SkSpan<Block> styleSpan,
|
||||
@ -466,7 +465,7 @@ bool OneLineShaper::shape() {
|
||||
|
||||
// The text can be broken into many shaping sequences
|
||||
// (by place holders, possibly, by hard line breaks or tabs, too)
|
||||
uint8_t textDirection = fParagraph->fParagraphStyle.getTextDirection() == TextDirection::kLtr ? 2 : 1;
|
||||
uint8_t textDirection = fParagraph->fParagraphStyle.getTextDirection() == TextDirection::kLtr ? 2 : 0xff;
|
||||
auto limitlessWidth = std::numeric_limits<SkScalar>::max();
|
||||
|
||||
auto result = iterateThroughShapingRegions(
|
||||
|
@ -89,10 +89,11 @@ bool operator==(const ParagraphCacheKey& a, const ParagraphCacheKey& b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.fParagraphStyle.getMaxLines() != b.fParagraphStyle.getMaxLines()) {
|
||||
if (!(a.fParagraphStyle == b.fParagraphStyle)) {
|
||||
// This is too strong, but at least we will not lose lines
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < a.fTextStyles.size(); ++i) {
|
||||
auto& tsa = a.fTextStyles[i];
|
||||
auto& tsb = b.fTextStyles[i];
|
||||
|
@ -192,6 +192,8 @@ void ParagraphImpl::layout(SkScalar rawWidth) {
|
||||
if (fState < kFormatted) {
|
||||
// Build the picture lazily not until we actually have to paint (or never)
|
||||
this->formatLines(fWidth);
|
||||
// We have to calculate the paragraph boundaries only after we format the lines
|
||||
this->calculateBoundaries();
|
||||
fState = kFormatted;
|
||||
}
|
||||
|
||||
@ -492,34 +494,10 @@ BlockRange ParagraphImpl::findAllBlocks(TextRange textRange) {
|
||||
return { begin, end + 1 };
|
||||
}
|
||||
|
||||
void ParagraphImpl::calculateBoundaries(ClusterRange clusters, SkVector offset, SkVector advance) {
|
||||
|
||||
auto boundaries = SkRect::MakeXYWH(0, 0, advance.fX, advance.fY);
|
||||
|
||||
if (!fRuns.empty()) {
|
||||
// TODO: Move it down to the TextWrapper to avoid extra calculations
|
||||
auto run = &fRuns[0];
|
||||
auto runShift = 0.0f;
|
||||
auto clusterShift = 0.0f;
|
||||
for (auto index = clusters.start; index < clusters.end; ++index) {
|
||||
auto& cluster = fClusters[index];
|
||||
if (cluster.runIndex() != run->index()) {
|
||||
run = &fRuns[cluster.runIndex()];
|
||||
runShift += clusterShift;
|
||||
clusterShift = 0;
|
||||
}
|
||||
clusterShift += cluster.width();
|
||||
for (auto i = cluster.startPos(); i < cluster.endPos(); ++i) {
|
||||
auto posX = run->posX(i);
|
||||
auto posY = run->posY(i);
|
||||
auto bounds = run->getBounds(i);
|
||||
bounds.offset(posX + runShift, posY);
|
||||
boundaries.joinPossiblyEmptyRect(bounds);
|
||||
}
|
||||
}
|
||||
void ParagraphImpl::calculateBoundaries() {
|
||||
for (auto& line : fLines) {
|
||||
fOrigin.joinPossiblyEmptyRect(line.calculateBoundaries());
|
||||
}
|
||||
boundaries.offset(offset);
|
||||
fOrigin.joinPossiblyEmptyRect(boundaries);
|
||||
}
|
||||
|
||||
TextLine& ParagraphImpl::addLine(SkVector offset,
|
||||
@ -532,11 +510,6 @@ TextLine& ParagraphImpl::addLine(SkVector offset,
|
||||
InternalLineMetrics sizes) {
|
||||
// Define a list of styles that covers the line
|
||||
auto blocks = findAllBlocks(text);
|
||||
|
||||
auto correctedOffset = offset;
|
||||
correctedOffset.offset(0, sizes.baseline());
|
||||
calculateBoundaries(clusters, correctedOffset, advance);
|
||||
|
||||
return fLines.emplace_back(this, offset, advance, blocks, text, textWithSpaces, clusters, clustersWithGhosts, widthWithSpaces, sizes);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ private:
|
||||
friend class TextWrapper;
|
||||
friend class OneLineShaper;
|
||||
|
||||
void calculateBoundaries(ClusterRange clusters, SkVector offset, SkVector advance);
|
||||
void calculateBoundaries();
|
||||
void extractStyles();
|
||||
|
||||
void markGraphemes16();
|
||||
|
@ -115,6 +115,36 @@ TextLine::TextLine(ParagraphImpl* master,
|
||||
}
|
||||
}
|
||||
|
||||
SkRect TextLine::calculateBoundaries() {
|
||||
|
||||
auto boundaries = SkRect::MakeEmpty();
|
||||
auto clusters = fMaster->clusters(fClusterRange);
|
||||
Run* run = nullptr;
|
||||
auto runShift = 0.0f;
|
||||
auto clusterShift = 0.0f;
|
||||
for (auto cluster = clusters.begin(); cluster != clusters.end(); ++cluster) {
|
||||
if (run == nullptr || cluster->runIndex() != run->index()) {
|
||||
run = &fMaster->run(cluster->runIndex());
|
||||
runShift += clusterShift;
|
||||
clusterShift = 0;
|
||||
}
|
||||
clusterShift += cluster->width();
|
||||
for (auto i = cluster->startPos(); i < cluster->endPos(); ++i) {
|
||||
auto posX = run->posX(i);
|
||||
auto posY = run->posY(i);
|
||||
auto bounds = run->getBounds(i);
|
||||
bounds.offset(posX + runShift, posY);
|
||||
boundaries.joinPossiblyEmptyRect(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
boundaries.offset(this->fOffset); // Line offset from the beginning of the para
|
||||
boundaries.offset(this->fShift, 0); // Shift produced by formatting
|
||||
boundaries.offset(0, this->baseline()); // Down by baseline
|
||||
|
||||
return boundaries;
|
||||
}
|
||||
|
||||
void TextLine::paint(SkCanvas* textCanvas) {
|
||||
if (this->empty()) {
|
||||
return;
|
||||
@ -239,13 +269,13 @@ void TextLine::paintText(SkCanvas* canvas, TextRange textRange, const TextStyle&
|
||||
|
||||
// TODO: This is the change for flutter, must be removed later
|
||||
SkScalar correctedBaseline = SkScalarFloorToScalar(this->baseline() + 0.5);
|
||||
|
||||
SkTextBlobBuilder builder;
|
||||
context.run->copyTo(builder, SkToU32(context.pos), context.size, SkVector::Make(0, correctedBaseline));
|
||||
canvas->save();
|
||||
if (context.clippingNeeded) {
|
||||
canvas->clipRect(context.clip);
|
||||
}
|
||||
|
||||
canvas->translate(context.fTextShift, 0);
|
||||
canvas->drawTextBlob(builder.make(), 0, 0, paint);
|
||||
canvas->restore();
|
||||
|
@ -93,6 +93,8 @@ public:
|
||||
|
||||
LineMetrics getMetrics() const;
|
||||
|
||||
SkRect calculateBoundaries();
|
||||
|
||||
private:
|
||||
|
||||
Run* shapeEllipsis(const SkString& ellipsis, Run* run);
|
||||
|
@ -1723,36 +1723,52 @@ class ParagraphView22 : public ParagraphView_Base {
|
||||
protected:
|
||||
SkString name() override { return SkString("Paragraph22"); }
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
|
||||
const char* text = "By continuing, you agree to the Google Payments . The  describes how your data is handled.";
|
||||
for (size_t i = 0; i < 10000; ++i) {
|
||||
ParagraphStyle paragraph_style;
|
||||
ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
|
||||
TextStyle text_style;
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
text_style.setFontFamilies({SkString("Roboto")});
|
||||
text_style.setFontSize(12);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(std::numeric_limits<SkScalar>::max());
|
||||
SkDebugf("layout: %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight());
|
||||
if (i % 3 != 1) {
|
||||
paragraph->layout(566);
|
||||
SkDebugf("layout: %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight());
|
||||
} else if (i % 3 == 2) {
|
||||
paragraph->layout(633);
|
||||
SkDebugf("layout: %f %f\n", paragraph->getMaxWidth(), paragraph->getHeight());
|
||||
bool onChar(SkUnichar uni) override {
|
||||
switch (uni) {
|
||||
case 'l':
|
||||
direction = true;
|
||||
return true;
|
||||
case 'r':
|
||||
direction = false;
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
//paragraph->paint(canvas, 0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.setTextDirection(direction ? TextDirection::kLtr : TextDirection::kRtl);
|
||||
auto collection = getFontCollection();
|
||||
ParagraphBuilderImpl builder(paragraph_style, collection);
|
||||
collection->getParagraphCache()->reset();
|
||||
collection->getParagraphCache()->turnOn(false);
|
||||
TextStyle text_style;
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
text_style.setFontFamilies({SkString("Roboto")});
|
||||
text_style.setFontSize(12);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText("I have got a ");
|
||||
text_style.setFontStyle(SkFontStyle::Bold());
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText("lovely bunch");
|
||||
text_style.setFontStyle(SkFontStyle::Normal());
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(" of coconuts.");
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(this->width());
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
collection->getParagraphCache()->turnOn(true);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef Sample INHERITED;
|
||||
bool direction;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DEF_SAMPLE(return new ParagraphView1();)
|
||||
|
Loading…
Reference in New Issue
Block a user