blob: 935c9174858d181149027638a398fd4255f090ce [file] [log] [blame]
Florin Malita52a43792020-07-03 12:06:41 -04001/*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "modules/sksg/include/SkSGGeometryEffect.h"
9
10#include "include/core/SkCanvas.h"
11#include "include/core/SkStrokeRec.h"
12#include "include/effects/SkCornerPathEffect.h"
13#include "include/effects/SkDashPathEffect.h"
14#include "include/effects/SkTrimPathEffect.h"
15#include "modules/sksg/src/SkSGTransformPriv.h"
16
17namespace sksg {
18
19GeometryEffect::GeometryEffect(sk_sp<GeometryNode> child)
20 : fChild(std::move(child)) {
21 SkASSERT(fChild);
22
23 this->observeInval(fChild);
24}
25
26GeometryEffect::~GeometryEffect() {
27 this->unobserveInval(fChild);
28}
29
30void GeometryEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
31 canvas->clipPath(fPath, SkClipOp::kIntersect, antiAlias);
32}
33
34void GeometryEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
35 canvas->drawPath(fPath, paint);
36}
37
38bool GeometryEffect::onContains(const SkPoint& p) const {
39 return fPath.contains(p.x(), p.y());
40}
41
42SkPath GeometryEffect::onAsPath() const {
43 return fPath;
44}
45
46SkRect GeometryEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
47 SkASSERT(this->hasInval());
48
49 fChild->revalidate(ic, ctm);
50
51 fPath = this->onRevalidateEffect(fChild);
52 fPath.shrinkToFit();
53
54 return fPath.computeTightBounds();
55}
56
57SkPath TrimEffect::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
58 SkPath path = child->asPath();
59
60 if (const auto trim = SkTrimPathEffect::Make(fStart, fStop, fMode)) {
61 SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
62 SkAssertResult(trim->filterPath(&path, path, &rec, nullptr));
63 }
64
65 return path;
66}
67
68GeometryTransform::GeometryTransform(sk_sp<GeometryNode> child, sk_sp<Transform> transform)
69 : INHERITED(std::move(child))
70 , fTransform(std::move(transform)) {
71 SkASSERT(fTransform);
72 this->observeInval(fTransform);
73}
74
75GeometryTransform::~GeometryTransform() {
76 this->unobserveInval(fTransform);
77}
78
79SkPath GeometryTransform::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
80 fTransform->revalidate(nullptr, SkMatrix::I());
81 const auto m = TransformPriv::As<SkMatrix>(fTransform);
82
83 SkPath path = child->asPath();
84 path.transform(m);
85
86 return path;
87}
88
89namespace {
90
91sk_sp<SkPathEffect> make_dash(const std::vector<float> intervals, float phase) {
92 if (intervals.empty()) {
93 return nullptr;
94 }
95
96 const auto* intervals_ptr = intervals.data();
97 auto intervals_count = intervals.size();
98
99 SkSTArray<32, float, true> storage;
100 if (intervals_count & 1) {
101 intervals_count *= 2;
102 storage.resize(intervals_count);
103 intervals_ptr = storage.data();
104
105 std::copy(intervals.begin(), intervals.end(), storage.begin());
106 std::copy(intervals.begin(), intervals.end(), storage.begin() + intervals.size());
107 }
108
109 return SkDashPathEffect::Make(intervals_ptr, SkToInt(intervals_count), phase);
110}
111
112} // namespace
113
114SkPath DashEffect::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
115 SkPath path = child->asPath();
116
117 if (const auto dash_patheffect = make_dash(fIntervals, fPhase)) {
118 SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
119 dash_patheffect->filterPath(&path, path, &rec, nullptr);
120 }
121
122 return path;
123}
124
125SkPath RoundEffect::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
126 SkPath path = child->asPath();
127
128 if (const auto round = SkCornerPathEffect::Make(fRadius)) {
129 SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
130 SkAssertResult(round->filterPath(&path, path, &rec, nullptr));
131 }
132
133 return path;
134}
135
136} // namesapce sksg