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