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