1 /*
2 * Copyright 2017 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 "SkSGTrimEffect.h"
9
10 #include "SkCanvas.h"
11 #include "SkDashPathEffect.h"
12 #include "SkPathMeasure.h"
13
14 namespace sksg {
15
TrimEffect(sk_sp<GeometryNode> child)16 TrimEffect::TrimEffect(sk_sp<GeometryNode> child)
17 : fChild(std::move(child)) {
18 this->observeInval(fChild);
19 }
20
~TrimEffect()21 TrimEffect::~TrimEffect() {
22 this->unobserveInval(fChild);
23 }
24
onClip(SkCanvas * canvas,bool antiAlias) const25 void TrimEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
26 canvas->clipPath(fChild->asPath(), SkClipOp::kIntersect, antiAlias);
27 }
28
29 // TODO
30 // This is a quick hack to get something on the screen. What we really want here is to apply
31 // the geometry transformation and cache the result on revalidation. Or an SkTrimPathEffect.
onDraw(SkCanvas * canvas,const SkPaint & paint) const32 void TrimEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
33 SkASSERT(!paint.getPathEffect());
34
35 const auto path = fChild->asPath();
36 SkScalar pathLen = 0;
37 SkPathMeasure measure(path, false);
38 do {
39 pathLen += measure.getLength();
40 } while (measure.nextContour());
41
42 const auto start = pathLen * fStart,
43 end = pathLen * fEnd,
44 offset = pathLen * fOffset,
45 len = end - start;
46
47 if (len <= 0) {
48 return;
49 }
50
51 const SkScalar dashes[] = { len, pathLen - len };
52 SkPaint dashedPaint(paint);
53 dashedPaint.setPathEffect(SkDashPathEffect::Make(dashes,
54 SK_ARRAY_COUNT(dashes),
55 -start - offset));
56
57 canvas->drawPath(path, dashedPaint);
58 }
59
onAsPath() const60 SkPath TrimEffect::onAsPath() const {
61 return fChild->asPath();
62 }
63
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)64 SkRect TrimEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
65 SkASSERT(this->hasInval());
66 return fChild->revalidate(ic, ctm);
67 }
68
69 } // namespace sksg
70