Add support for Decoration Styles, remove usage of separate decoration records.
Change-Id: I8fe929b0814b22e37e1517a7ddafb70a1c6b3d37
This commit is contained in:
@@ -22,16 +22,19 @@ namespace txt {
|
||||
PaintRecord::~PaintRecord() = default;
|
||||
|
||||
PaintRecord::PaintRecord(SkColor color,
|
||||
TextStyle style,
|
||||
SkPoint offset,
|
||||
sk_sp<SkTextBlob> 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_;
|
||||
|
||||
@@ -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<SkTextBlob> 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<SkTextBlob> text_;
|
||||
SkPaint::FontMetrics metrics_;
|
||||
|
||||
@@ -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<TextDecoration, SkColor, TextDecorationStyle, FontWeight>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,9 +75,6 @@ class Paragraph {
|
||||
StyledRuns runs_;
|
||||
minikin::LineBreaker breaker_;
|
||||
std::vector<PaintRecord> records_;
|
||||
std::vector<
|
||||
std::tuple<TextDecoration, SkColor, TextDecorationStyle, FontWeight>>
|
||||
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<TextDecoration, SkColor, TextDecorationStyle, FontWeight>
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user