From b4c8d2c134234afc0eeb2f5b4975ac83b456efbc Mon Sep 17 00:00:00 2001 From: Gary Qian Date: Tue, 20 Jun 2017 18:28:09 -0700 Subject: [PATCH] Add support for Decoration Styles, remove usage of separate decoration records. Change-Id: I8fe929b0814b22e37e1517a7ddafb70a1c6b3d37 --- engine/src/flutter/src/paint_record.cc | 4 + engine/src/flutter/src/paint_record.h | 5 ++ engine/src/flutter/src/paragraph.cc | 103 ++++++++++++++++------- engine/src/flutter/src/paragraph.h | 17 ++-- engine/src/flutter/src/text_decoration.h | 10 +-- 5 files changed, 89 insertions(+), 50 deletions(-) diff --git a/engine/src/flutter/src/paint_record.cc b/engine/src/flutter/src/paint_record.cc index 8740ee8ea4..f8d13dbc25 100644 --- a/engine/src/flutter/src/paint_record.cc +++ b/engine/src/flutter/src/paint_record.cc @@ -22,16 +22,19 @@ namespace txt { PaintRecord::~PaintRecord() = default; PaintRecord::PaintRecord(SkColor color, + TextStyle style, SkPoint offset, sk_sp text, SkPaint::FontMetrics metrics) : color_(color), + style_(style), offset_(offset), text_(std::move(text)), metrics_(metrics) {} PaintRecord::PaintRecord(PaintRecord&& other) { color_ = other.color_; + style_ = other.style_; offset_ = other.offset_; text_ = std::move(other.text_); metrics_ = other.metrics_; @@ -39,6 +42,7 @@ PaintRecord::PaintRecord(PaintRecord&& other) { PaintRecord& PaintRecord::operator=(PaintRecord&& other) { color_ = other.color_; + style_ = other.style_; offset_ = other.offset_; text_ = std::move(other.text_); metrics_ = other.metrics_; diff --git a/engine/src/flutter/src/paint_record.h b/engine/src/flutter/src/paint_record.h index f758b68729..d0c18fc05d 100644 --- a/engine/src/flutter/src/paint_record.h +++ b/engine/src/flutter/src/paint_record.h @@ -19,6 +19,7 @@ #include "lib/ftl/logging.h" #include "lib/ftl/macros.h" +#include "lib/txt/src/text_style.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkTextBlob.h" @@ -31,6 +32,7 @@ class PaintRecord { ~PaintRecord(); PaintRecord(SkColor color, + TextStyle style, SkPoint offset, sk_sp text, SkPaint::FontMetrics metrics); @@ -47,8 +49,11 @@ class PaintRecord { const SkPaint::FontMetrics& metrics() const { return metrics_; } + const TextStyle& style() const { return style_; } + private: SkColor color_; + TextStyle style_; SkPoint offset_; sk_sp text_; SkPaint::FontMetrics metrics_; diff --git a/engine/src/flutter/src/paragraph.cc b/engine/src/flutter/src/paragraph.cc index 220e7c260a..48fcc8a56f 100644 --- a/engine/src/flutter/src/paragraph.cc +++ b/engine/src/flutter/src/paragraph.cc @@ -31,6 +31,8 @@ #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/effects/SkDashPathEffect.h" +#include "third_party/skia/include/effects/SkDiscretePathEffect.h" namespace txt { namespace { @@ -230,11 +232,9 @@ void Paragraph::Layout(double width, // run. SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); - records_.push_back(PaintRecord{run.style.color, SkPoint::Make(x, y_), - builder.make(), metrics}); - decorations_.push_back( - std::make_tuple(run.style.decoration, run.style.decoration_color, - run.style.decoration_style, run.style.font_weight)); + records_.push_back(PaintRecord{run.style.color, run.style, + SkPoint::Make(x, y_), builder.make(), + metrics}); if (max_line_spacing < -metrics.fAscent * run.style.height) max_line_spacing = -metrics.fAscent * run.style.height; @@ -290,48 +290,87 @@ void Paragraph::SetParagraphStyle(const ParagraphStyle& style) { } void Paragraph::Paint(SkCanvas* canvas, double x, double y) { - int i = 0; for (const auto& record : records_) { SkPaint paint; paint.setColor(record.color()); const SkPoint& offset = record.offset(); canvas->drawTextBlob(record.text(), x + offset.x(), y + offset.y(), paint); - PaintDecorations(canvas, x + offset.x(), y + offset.y(), decorations_[i], + PaintDecorations(canvas, x + offset.x(), y + offset.y(), record.style(), record.metrics(), record.text()); - i++; } } -void Paragraph::PaintDecorations( - SkCanvas* canvas, - double x, - double y, - std::tuple - decoration, - SkPaint::FontMetrics metrics, - SkTextBlob* blob) { - if (std::get<0>(decoration) != TextDecoration::kNone) { +void Paragraph::PaintDecorations(SkCanvas* canvas, + double x, + double y, + TextStyle style, + SkPaint::FontMetrics metrics, + SkTextBlob* blob) { + if (style.decoration != TextDecoration::kNone) { SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(std::get<1>(decoration)); + paint.setColor(style.decoration_color); paint.setAntiAlias(true); + // This is set to 2 for the double line style + int decoration_count = 1; + + switch (style.decoration_style) { + case TextDecorationStyle::kSolid: + break; + case TextDecorationStyle::kDouble: { + decoration_count = 2; + break; + } + case TextDecorationStyle::kDotted: { + const SkScalar intervals[] = {3.0f, 5.0f, 3.0f, 5.0f}; + size_t count = sizeof(intervals) / sizeof(intervals[0]); + paint.setPathEffect(SkPathEffect::MakeCompose( + SkDashPathEffect::Make(intervals, count, 0.0f), + SkDiscretePathEffect::Make(0, 0))); + break; + } + case TextDecorationStyle::kDashed: { + const SkScalar intervals[] = {10.0f, 5.0f, 10.0f, 5.0f}; + size_t count = sizeof(intervals) / sizeof(intervals[0]); + paint.setPathEffect(SkPathEffect::MakeCompose( + SkDashPathEffect::Make(intervals, count, 0.0f), + SkDiscretePathEffect::Make(0, 0))); + break; + } + case TextDecorationStyle::kWavy: { + // TODO(garyq): Wave currently does a random wave instead of an ordered + // wave. + const SkScalar intervals[] = {1}; + size_t count = sizeof(intervals) / sizeof(intervals[0]); + paint.setPathEffect(SkPathEffect::MakeCompose( + SkDashPathEffect::Make(intervals, count, 0.0f), + SkDiscretePathEffect::Make(metrics.fAvgCharWidth / 10.0f, + metrics.fAvgCharWidth / 10.0f))); + break; + } + } + double width = blob->bounds().fRight + blob->bounds().fLeft; - if (std::get<0>(decoration) & 0x1) { - paint.setStrokeWidth(metrics.fUnderlineThickness); - canvas->drawLine(x, y + metrics.fUnderlineThickness, x + width, - y + metrics.fUnderlineThickness, paint); - } - if (std::get<0>(decoration) & 0x2) { - paint.setStrokeWidth(metrics.fUnderlineThickness); - canvas->drawLine(x, y + metrics.fAscent, x + width, y + metrics.fAscent, - paint); - } - if (std::get<0>(decoration) & 0x4) { - paint.setStrokeWidth(metrics.fUnderlineThickness); - canvas->drawLine(x, y - metrics.fCapHeight / 2.5, x + width, - y - metrics.fCapHeight / 2.5, paint); + for (int i = 0; i < decoration_count; i++) { + double y_offset = i * metrics.fUnderlineThickness * 3.0f; + if (style.decoration & 0x1) { + paint.setStrokeWidth(metrics.fUnderlineThickness); + canvas->drawLine(x, y + metrics.fUnderlineThickness + y_offset, + x + width, y + metrics.fUnderlineThickness + y_offset, + paint); + } + if (style.decoration & 0x2) { + paint.setStrokeWidth(metrics.fUnderlineThickness); + canvas->drawLine(x, y + metrics.fAscent + y_offset, x + width, + y + metrics.fAscent + y_offset, paint); + } + if (style.decoration & 0x4) { + paint.setStrokeWidth(metrics.fUnderlineThickness); + canvas->drawLine(x, y - metrics.fXHeight / 2 + y_offset, x + width, + y - metrics.fXHeight / 2 + y_offset, paint); + } } } } diff --git a/engine/src/flutter/src/paragraph.h b/engine/src/flutter/src/paragraph.h index 5a1e861afd..1d6ccd402d 100644 --- a/engine/src/flutter/src/paragraph.h +++ b/engine/src/flutter/src/paragraph.h @@ -75,9 +75,6 @@ class Paragraph { StyledRuns runs_; minikin::LineBreaker breaker_; std::vector records_; - std::vector< - std::tuple> - decorations_; ParagraphStyle paragraph_style_; SkScalar y_ = 0.0f; // Height of the paragraph after Layout(). double width_ = 0.0f; @@ -91,14 +88,12 @@ class Paragraph { void AddRunsToLineBreaker(const std::string& rootdir = ""); - void PaintDecorations( - SkCanvas* canvas, - double x, - double y, - std::tuple - decoration, - SkPaint::FontMetrics metrics, - SkTextBlob* blob); + void PaintDecorations(SkCanvas* canvas, + double x, + double y, + TextStyle style, + SkPaint::FontMetrics metrics, + SkTextBlob* blob); FTL_DISALLOW_COPY_AND_ASSIGN(Paragraph); }; diff --git a/engine/src/flutter/src/text_decoration.h b/engine/src/flutter/src/text_decoration.h index 8e7b1654a4..055cf4b579 100644 --- a/engine/src/flutter/src/text_decoration.h +++ b/engine/src/flutter/src/text_decoration.h @@ -19,6 +19,8 @@ namespace txt { +// Multiple decorations can be applied at once. Ex: Underline and overline is +// (0x1 | 0x2) enum TextDecoration { kNone = 0x0, kUnderline = 0x1, @@ -26,13 +28,7 @@ enum TextDecoration { kLineThrough = 0x4, }; -enum TextDecorationStyle { - kSolid, - kDouble, // "double" is reserved. - kDotted, - kDashed, - kWavy -}; +enum TextDecorationStyle { kSolid, kDouble, kDotted, kDashed, kWavy }; } // namespace txt