15#include "include/core/SkMatrix.h"
16#include "third_party/skia/src/core/SkTextBlobPriv.h"
20namespace skt = skia::textlayout;
21using PaintID = skt::ParagraphPainter::PaintID;
28 return font_slant == SkFontStyle::Slant::kUpright_Slant
33class DisplayListParagraphPainter :
public skt::ParagraphPainter {
53 const std::vector<DlPaint>& dl_paints,
54 bool impeller_enabled)
56 dl_paints_(dl_paints),
57 impeller_enabled_(impeller_enabled) {}
59 void drawTextBlob(
const sk_sp<SkTextBlob>& blob,
62 const SkPaintOrID& paint)
override {
66 size_t paint_id = std::get<PaintID>(paint);
69#ifdef IMPELLER_SUPPORTS_RENDERING
70 if (impeller_enabled_) {
71 SkTextBlobRunIterator run(blob.get());
72 if (ShouldRenderAsPath(dl_paints_[paint_id])) {
73 SkPath
path = skia::textlayout::Paragraph::GetPath(blob.get());
77 builder_->DrawText(DlTextImpeller::Make(
79 x,
y, dl_paints_[paint_id]);
84 auto transformed =
path.makeTransform(SkMatrix::Translate(
85 x + blob->bounds().left(),
y + blob->bounds().top()));
86 builder_->DrawPath(
DlPath(transformed), dl_paints_[paint_id]);
91 x,
y, dl_paints_[paint_id]);
95 builder_->DrawText(DlTextSkia::Make(blob),
x,
y, dl_paints_[paint_id]);
98 void drawTextShadow(
const sk_sp<SkTextBlob>& blob,
102 SkScalar blur_sigma)
override {
108 if (blur_sigma > 0.0) {
112 std::shared_ptr<DlText>
text;
113#if IMPELLER_SUPPORTS_RENDERING
114 if (impeller_enabled_) {
118 text = DlTextSkia::Make(blob);
121 text = DlTextSkia::Make(blob);
123 builder_->DrawText(
text,
x,
y, paint);
126 void drawRect(
const SkRect& rect,
const SkPaintOrID& paint)
override {
127 size_t paint_id = std::get<PaintID>(paint);
129 builder_->DrawRect(
ToDlRect(rect), dl_paints_[paint_id]);
132 void drawFilledRect(
const SkRect& rect,
133 const DecorationStyle& decor_style)
override {
134 DlPaint paint = toDlPaint(decor_style, DlDrawStyle::kFill);
135 builder_->DrawRect(
ToDlRect(rect), paint);
138 void drawPath(
const SkPath&
path,
139 const DecorationStyle& decor_style)
override {
140 builder_->DrawPath(
DlPath(
path), toDlPaint(decor_style));
143 void drawLine(SkScalar x0,
147 const DecorationStyle& decor_style)
override {
148 auto dash_path_effect = decor_style.getDashPathEffect();
149 auto paint = toDlPaint(decor_style);
151 if (dash_path_effect) {
153 dash_path_effect->fOnLength,
154 dash_path_effect->fOffLength, paint);
160 void clipRect(
const SkRect& rect)
override {
161 builder_->ClipRect(
ToDlRect(rect), DlClipOp::kIntersect,
false);
164 void translate(SkScalar dx, SkScalar dy)
override {
165 builder_->Translate(dx, dy);
168 void save()
override { builder_->Save(); }
170 void restore()
override { builder_->Restore(); }
173 bool ShouldRenderAsPath(
const DlPaint& paint)
const {
189 DlPaint toDlPaint(
const DecorationStyle& decor_style,
200 const std::vector<DlPaint>& dl_paints_;
201 const bool impeller_enabled_;
207 std::vector<flutter::DlPaint>&& dl_paints,
208 bool impeller_enabled)
209 : paragraph_(
std::move(paragraph)),
210 dl_paints_(dl_paints),
211 impeller_enabled_(impeller_enabled) {}
214 return SkScalarToDouble(paragraph_->getMaxWidth());
218 return SkScalarToDouble(paragraph_->getHeight());
222 return SkScalarToDouble(paragraph_->getLongestLine());
226 if (!line_metrics_) {
227 std::vector<skt::LineMetrics> metrics;
228 paragraph_->getLineMetrics(metrics);
230 line_metrics_.emplace();
231 line_metrics_styles_.reserve(
232 std::accumulate(metrics.begin(), metrics.end(), 0,
233 [](
const int a,
const skt::LineMetrics& b) {
234 return a + b.fLineMetrics.size();
237 for (
const skt::LineMetrics& skm : metrics) {
240 skm.fStartIndex, skm.fEndIndex, skm.fEndExcludingWhitespaces,
241 skm.fEndIncludingNewline, skm.fHardBreak);
242 txtm.
ascent = skm.fAscent;
245 txtm.
height = skm.fHeight;
246 txtm.
width = skm.fWidth;
247 txtm.
left = skm.fLeft;
251 for (
const auto& sk_iter : skm.fLineMetrics) {
252 const skt::StyleMetrics& sk_style_metrics = sk_iter.second;
253 line_metrics_styles_.push_back(SkiaToTxt(*sk_style_metrics.text_style));
255 std::piecewise_construct, std::forward_as_tuple(sk_iter.first),
256 std::forward_as_tuple(&line_metrics_styles_.back(),
257 sk_style_metrics.font_metrics));
263 return line_metrics_.value();
267 skt::LineMetrics* lineMetrics)
const {
268 return paragraph_->getLineMetricsAt(lineNumber, lineMetrics);
272 return SkScalarToDouble(paragraph_->getMinIntrinsicWidth());
276 return SkScalarToDouble(paragraph_->getMaxIntrinsicWidth());
280 return SkScalarToDouble(paragraph_->getAlphabeticBaseline());
284 return SkScalarToDouble(paragraph_->getIdeographicBaseline());
288 return paragraph_->didExceedMaxLines();
292 line_metrics_.reset();
293 line_metrics_styles_.clear();
294 paragraph_->layout(
width);
298 DisplayListParagraphPainter painter(builder, dl_paints_, impeller_enabled_);
299 paragraph_->paint(&painter,
x,
y);
306 RectHeightStyle rect_height_style,
307 RectWidthStyle rect_width_style) {
308 std::vector<skt::TextBox> skia_boxes = paragraph_->getRectsForRange(
309 start,
end,
static_cast<skt::RectHeightStyle
>(rect_height_style),
310 static_cast<skt::RectWidthStyle
>(rect_width_style));
312 std::vector<Paragraph::TextBox> boxes;
313 boxes.reserve(skia_boxes.size());
314 for (
const skt::TextBox& skia_box : skia_boxes) {
315 boxes.emplace_back(skia_box.rect,
323 std::vector<skt::TextBox> skia_boxes = paragraph_->getRectsForPlaceholders();
325 std::vector<Paragraph::TextBox> boxes;
326 boxes.reserve(skia_boxes.size());
327 for (
const skt::TextBox& skia_box : skia_boxes) {
328 boxes.emplace_back(skia_box.rect,
338 skt::PositionWithAffinity skia_pos =
339 paragraph_->getGlyphPositionAtCoordinate(dx, dy);
341 return ParagraphSkia::PositionWithAffinity(
342 skia_pos.position,
static_cast<Affinity
>(skia_pos.affinity));
347 skia::textlayout::Paragraph::GlyphInfo* glyphInfo)
const {
348 return paragraph_->getGlyphInfoAtUTF16Offset(offset, glyphInfo);
354 skia::textlayout::Paragraph::GlyphInfo* glyphInfo)
const {
355 return paragraph_->getClosestUTF16GlyphInfoAt(dx, dy, glyphInfo);
359 skt::SkRange<size_t> range = paragraph_->getWordBoundary(offset);
364 return paragraph_->lineNumber();
368 return paragraph_->getLineNumberAtUTF16Offset(codeUnitIndex);
371TextStyle ParagraphSkia::SkiaToTxt(
const skt::TextStyle& skia) {
374 txt.color = skia.getColor();
376 txt.decoration_color = skia.getDecorationColor();
377 txt.decoration_style =
379 txt.decoration_thickness_multiplier =
380 SkScalarToDouble(skia.getDecorationThicknessMultiplier());
381 txt.font_weight = skia.getFontStyle().weight();
382 txt.font_style = GetTxtFontStyle(skia.getFontStyle().slant());
386 for (
const SkString& font_family : skia.getFontFamilies()) {
387 txt.font_families.emplace_back(font_family.c_str());
390 txt.font_size = SkScalarToDouble(skia.getFontSize());
391 txt.letter_spacing = SkScalarToDouble(skia.getLetterSpacing());
392 txt.word_spacing = SkScalarToDouble(skia.getWordSpacing());
393 txt.height = SkScalarToDouble(skia.getHeight());
395 txt.locale = skia.getLocale().c_str();
396 if (skia.hasBackground()) {
397 PaintID background_id = std::get<PaintID>(skia.getBackgroundPaintOrID());
398 txt.background = dl_paints_[background_id];
400 if (skia.hasForeground()) {
401 PaintID foreground_id = std::get<PaintID>(skia.getForegroundPaintOrID());
402 txt.foreground = dl_paints_[foreground_id];
405 txt.text_shadows.clear();
406 for (
const skt::TextShadow& skia_shadow : skia.getShadows()) {
408 shadow.
offset = skia_shadow.fOffset;
410 shadow.
color = skia_shadow.fColor;
411 txt.text_shadows.emplace_back(shadow);
DlPaint & setColor(DlColor color)
DlPaint & setAntiAlias(bool isAntiAlias)
DlPaint & setStrokeWidth(float width)
DlDrawStyle getDrawStyle() const
const std::shared_ptr< const DlColorSource > & getColorSource() const
float getStrokeWidth() const
DlPaint & setMaskFilter(std::nullptr_t filter)
DlPaint & setDrawStyle(DlDrawStyle style)
std::map< size_t, RunMetrics > run_metrics
double GetMaxIntrinsicWidth() override
bool DidExceedMaxLines() override
double GetHeight() override
ParagraphSkia(std::unique_ptr< skia::textlayout::Paragraph > paragraph, std::vector< flutter::DlPaint > &&dl_paints, bool impeller_enabled)
size_t GetNumberOfLines() const override
PositionWithAffinity GetGlyphPositionAtCoordinate(double dx, double dy) override
double GetAlphabeticBaseline() override
bool GetClosestGlyphInfoAtCoordinate(double dx, double dy, skia::textlayout::Paragraph::GlyphInfo *glyphInfo) const override
int GetLineNumberAt(size_t utf16Offset) const override
bool GetLineMetricsAt(int lineNumber, skia::textlayout::LineMetrics *lineMetrics) const override
double GetLongestLine() override
std::vector< LineMetrics > & GetLineMetrics() override
void Layout(double width) override
std::vector< TextBox > GetRectsForRange(size_t start, size_t end, RectHeightStyle rect_height_style, RectWidthStyle rect_width_style) override
std::vector< TextBox > GetRectsForPlaceholders() override
double GetMaxWidth() override
bool Paint(flutter::DisplayListBuilder *builder, double x, double y) override
bool GetGlyphInfoAt(unsigned offset, skia::textlayout::Paragraph::GlyphInfo *glyphInfo) const override
double GetMinIntrinsicWidth() override
Range< size_t > GetWordBoundary(size_t offset) override
double GetIdeographicBaseline() override
#define FML_DCHECK(condition)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
const DlRect & ToDlRect(const SkRect &rect)
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
skt::ParagraphPainter::PaintID PaintID