1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
9cb93a386Sopenharmony_ci#include "include/core/SkPathEffect.h"
10cb93a386Sopenharmony_ci#include "src/core/SkPathEffectBase.h"
11cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
12cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_cibool SkPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
17cb93a386Sopenharmony_ci                              const SkRect* bounds) const {
18cb93a386Sopenharmony_ci    return this->filterPath(dst, src, rec, bounds, SkMatrix::I());
19cb93a386Sopenharmony_ci}
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cibool SkPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
22cb93a386Sopenharmony_ci                              const SkRect* bounds, const SkMatrix& ctm) const {
23cb93a386Sopenharmony_ci    SkPath tmp, *tmpDst = dst;
24cb93a386Sopenharmony_ci    if (dst == &src) {
25cb93a386Sopenharmony_ci        tmpDst = &tmp;
26cb93a386Sopenharmony_ci    }
27cb93a386Sopenharmony_ci    if (as_PEB(this)->onFilterPath(tmpDst, src, rec, bounds, ctm)) {
28cb93a386Sopenharmony_ci        if (dst == &src) {
29cb93a386Sopenharmony_ci            *dst = tmp;
30cb93a386Sopenharmony_ci        }
31cb93a386Sopenharmony_ci        return true;
32cb93a386Sopenharmony_ci    }
33cb93a386Sopenharmony_ci    return false;
34cb93a386Sopenharmony_ci}
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_cibool SkPathEffectBase::asPoints(PointData* results, const SkPath& src,
37cb93a386Sopenharmony_ci                    const SkStrokeRec& rec, const SkMatrix& mx, const SkRect* rect) const {
38cb93a386Sopenharmony_ci    return this->onAsPoints(results, src, rec, mx, rect);
39cb93a386Sopenharmony_ci}
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ciSkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const {
42cb93a386Sopenharmony_ci    return as_PEB(this)->onAsADash(info);
43cb93a386Sopenharmony_ci}
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_cibool SkPathEffect::needsCTM() const {
46cb93a386Sopenharmony_ci    return as_PEB(this)->onNeedsCTM();
47cb93a386Sopenharmony_ci}
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci/** \class SkPairPathEffect
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci Common baseclass for Compose and Sum. This subclass manages two pathEffects,
54cb93a386Sopenharmony_ci including flattening them. It does nothing in filterPath, and is only useful
55cb93a386Sopenharmony_ci for managing the lifetimes of its two arguments.
56cb93a386Sopenharmony_ci */
57cb93a386Sopenharmony_ciclass SkPairPathEffect : public SkPathEffectBase {
58cb93a386Sopenharmony_ciprotected:
59cb93a386Sopenharmony_ci    SkPairPathEffect(sk_sp<SkPathEffect> pe0, sk_sp<SkPathEffect> pe1)
60cb93a386Sopenharmony_ci        : fPE0(std::move(pe0)), fPE1(std::move(pe1))
61cb93a386Sopenharmony_ci    {
62cb93a386Sopenharmony_ci        SkASSERT(fPE0.get());
63cb93a386Sopenharmony_ci        SkASSERT(fPE1.get());
64cb93a386Sopenharmony_ci    }
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    void flatten(SkWriteBuffer& buffer) const override {
67cb93a386Sopenharmony_ci        buffer.writeFlattenable(fPE0.get());
68cb93a386Sopenharmony_ci        buffer.writeFlattenable(fPE1.get());
69cb93a386Sopenharmony_ci    }
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci    // these are visible to our subclasses
72cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPE0;
73cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPE1;
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ciprivate:
76cb93a386Sopenharmony_ci    using INHERITED = SkPathEffectBase;
77cb93a386Sopenharmony_ci};
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ciclass SkComposePathEffect : public SkPairPathEffect {
82cb93a386Sopenharmony_cipublic:
83cb93a386Sopenharmony_ci    /** Construct a pathEffect whose effect is to apply first the inner pathEffect
84cb93a386Sopenharmony_ci     and the the outer pathEffect (e.g. outer(inner(path)))
85cb93a386Sopenharmony_ci     The reference counts for outer and inner are both incremented in the constructor,
86cb93a386Sopenharmony_ci     and decremented in the destructor.
87cb93a386Sopenharmony_ci     */
88cb93a386Sopenharmony_ci    static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner) {
89cb93a386Sopenharmony_ci        if (!outer) {
90cb93a386Sopenharmony_ci            return inner;
91cb93a386Sopenharmony_ci        }
92cb93a386Sopenharmony_ci        if (!inner) {
93cb93a386Sopenharmony_ci            return outer;
94cb93a386Sopenharmony_ci        }
95cb93a386Sopenharmony_ci        return sk_sp<SkPathEffect>(new SkComposePathEffect(outer, inner));
96cb93a386Sopenharmony_ci    }
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    SkComposePathEffect(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner)
99cb93a386Sopenharmony_ci        : INHERITED(outer, inner) {}
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
102cb93a386Sopenharmony_ci                       const SkRect* cullRect, const SkMatrix& ctm) const override {
103cb93a386Sopenharmony_ci        SkPath          tmp;
104cb93a386Sopenharmony_ci        const SkPath*   ptr = &src;
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci        if (fPE1->filterPath(&tmp, src, rec, cullRect, ctm)) {
107cb93a386Sopenharmony_ci            ptr = &tmp;
108cb93a386Sopenharmony_ci        }
109cb93a386Sopenharmony_ci        return fPE0->filterPath(dst, *ptr, rec, cullRect, ctm);
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    SK_FLATTENABLE_HOOKS(SkComposePathEffect)
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    bool computeFastBounds(SkRect* bounds) const override {
115cb93a386Sopenharmony_ci        // inner (fPE1) is computed first, automatically updating bounds before computing outer.
116cb93a386Sopenharmony_ci        return as_PEB(fPE1)->computeFastBounds(bounds) &&
117cb93a386Sopenharmony_ci               as_PEB(fPE0)->computeFastBounds(bounds);
118cb93a386Sopenharmony_ci    }
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ciprivate:
121cb93a386Sopenharmony_ci    // illegal
122cb93a386Sopenharmony_ci    SkComposePathEffect(const SkComposePathEffect&);
123cb93a386Sopenharmony_ci    SkComposePathEffect& operator=(const SkComposePathEffect&);
124cb93a386Sopenharmony_ci    friend class SkPathEffect;
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    using INHERITED = SkPairPathEffect;
127cb93a386Sopenharmony_ci};
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkComposePathEffect::CreateProc(SkReadBuffer& buffer) {
130cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
131cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
132cb93a386Sopenharmony_ci    return SkComposePathEffect::Make(std::move(pe0), std::move(pe1));
133cb93a386Sopenharmony_ci}
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci/** \class SkSumPathEffect
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci This subclass of SkPathEffect applies two pathEffects, one after the other.
140cb93a386Sopenharmony_ci Its filterPath() returns true if either of the effects succeeded.
141cb93a386Sopenharmony_ci */
142cb93a386Sopenharmony_ciclass SkSumPathEffect : public SkPairPathEffect {
143cb93a386Sopenharmony_cipublic:
144cb93a386Sopenharmony_ci    /** Construct a pathEffect whose effect is to apply two effects, in sequence.
145cb93a386Sopenharmony_ci     (e.g. first(path) + second(path))
146cb93a386Sopenharmony_ci     The reference counts for first and second are both incremented in the constructor,
147cb93a386Sopenharmony_ci     and decremented in the destructor.
148cb93a386Sopenharmony_ci     */
149cb93a386Sopenharmony_ci    static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
150cb93a386Sopenharmony_ci        if (!first) {
151cb93a386Sopenharmony_ci            return second;
152cb93a386Sopenharmony_ci        }
153cb93a386Sopenharmony_ci        if (!second) {
154cb93a386Sopenharmony_ci            return first;
155cb93a386Sopenharmony_ci        }
156cb93a386Sopenharmony_ci        return sk_sp<SkPathEffect>(new SkSumPathEffect(first, second));
157cb93a386Sopenharmony_ci    }
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    SkSumPathEffect(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second)
160cb93a386Sopenharmony_ci        : INHERITED(first, second) {}
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci    bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
163cb93a386Sopenharmony_ci                      const SkRect* cullRect, const SkMatrix& ctm) const override {
164cb93a386Sopenharmony_ci        // always call both, even if the first one succeeds
165cb93a386Sopenharmony_ci        bool filteredFirst = fPE0->filterPath(dst, src, rec, cullRect, ctm);
166cb93a386Sopenharmony_ci        bool filteredSecond = fPE1->filterPath(dst, src, rec, cullRect, ctm);
167cb93a386Sopenharmony_ci        return filteredFirst || filteredSecond;
168cb93a386Sopenharmony_ci    }
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci    SK_FLATTENABLE_HOOKS(SkSumPathEffect)
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    bool computeFastBounds(SkRect* bounds) const override {
173cb93a386Sopenharmony_ci        // Unlike Compose(), PE0 modifies the path first for Sum
174cb93a386Sopenharmony_ci        return as_PEB(fPE0)->computeFastBounds(bounds) &&
175cb93a386Sopenharmony_ci               as_PEB(fPE1)->computeFastBounds(bounds);
176cb93a386Sopenharmony_ci    }
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ciprivate:
179cb93a386Sopenharmony_ci    // illegal
180cb93a386Sopenharmony_ci    SkSumPathEffect(const SkSumPathEffect&);
181cb93a386Sopenharmony_ci    SkSumPathEffect& operator=(const SkSumPathEffect&);
182cb93a386Sopenharmony_ci    friend class SkPathEffect;
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci    using INHERITED = SkPairPathEffect;
185cb93a386Sopenharmony_ci};
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkSumPathEffect::CreateProc(SkReadBuffer& buffer) {
188cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
189cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
190cb93a386Sopenharmony_ci    return SkSumPathEffect::Make(pe0, pe1);
191cb93a386Sopenharmony_ci}
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkPathEffect::MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
196cb93a386Sopenharmony_ci    return SkSumPathEffect::Make(std::move(first), std::move(second));
197cb93a386Sopenharmony_ci}
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkPathEffect::MakeCompose(sk_sp<SkPathEffect> outer,
200cb93a386Sopenharmony_ci                                              sk_sp<SkPathEffect> inner) {
201cb93a386Sopenharmony_ci    return SkComposePathEffect::Make(std::move(outer), std::move(inner));
202cb93a386Sopenharmony_ci}
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_civoid SkPathEffectBase::RegisterFlattenables() {
205cb93a386Sopenharmony_ci    SK_REGISTER_FLATTENABLE(SkComposePathEffect);
206cb93a386Sopenharmony_ci    SK_REGISTER_FLATTENABLE(SkSumPathEffect);
207cb93a386Sopenharmony_ci}
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkPathEffect::Deserialize(const void* data, size_t size,
210cb93a386Sopenharmony_ci                                              const SkDeserialProcs* procs) {
211cb93a386Sopenharmony_ci    return sk_sp<SkPathEffect>(static_cast<SkPathEffect*>(
212cb93a386Sopenharmony_ci                               SkFlattenable::Deserialize(
213cb93a386Sopenharmony_ci                               kSkPathEffect_Type, data, size, procs).release()));
214cb93a386Sopenharmony_ci}
215