Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 "SkPathEffect.h"
      9 #include "SkPath.h"
     10 #include "SkReadBuffer.h"
     11 #include "SkWriteBuffer.h"
     12 
     13 ///////////////////////////////////////////////////////////////////////////////
     14 
     15 bool SkPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
     16                               const SkRect* bounds) const {
     17     SkPath tmp, *tmpDst = dst;
     18     if (dst == &src) {
     19         tmpDst = &tmp;
     20     }
     21     if (this->onFilterPath(tmpDst, src, rec, bounds)) {
     22         if (dst == &src) {
     23             *dst = tmp;
     24         }
     25         return true;
     26     }
     27     return false;
     28 }
     29 
     30 void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) const {
     31     *dst = this->onComputeFastBounds(src);
     32 }
     33 
     34 bool SkPathEffect::asPoints(PointData* results, const SkPath& src,
     35                     const SkStrokeRec& rec, const SkMatrix& mx, const SkRect* rect) const {
     36     return this->onAsPoints(results, src, rec, mx, rect);
     37 }
     38 
     39 SkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const {
     40     return this->onAsADash(info);
     41 }
     42 
     43 ///////////////////////////////////////////////////////////////////////////////
     44 
     45 /** \class SkPairPathEffect
     46 
     47  Common baseclass for Compose and Sum. This subclass manages two pathEffects,
     48  including flattening them. It does nothing in filterPath, and is only useful
     49  for managing the lifetimes of its two arguments.
     50  */
     51 class SkPairPathEffect : public SkPathEffect {
     52 protected:
     53     SkPairPathEffect(sk_sp<SkPathEffect> pe0, sk_sp<SkPathEffect> pe1)
     54         : fPE0(std::move(pe0)), fPE1(std::move(pe1))
     55     {
     56         SkASSERT(fPE0.get());
     57         SkASSERT(fPE1.get());
     58     }
     59 
     60     void flatten(SkWriteBuffer& buffer) const override {
     61         buffer.writeFlattenable(fPE0.get());
     62         buffer.writeFlattenable(fPE1.get());
     63     }
     64 
     65     // these are visible to our subclasses
     66     sk_sp<SkPathEffect> fPE0;
     67     sk_sp<SkPathEffect> fPE1;
     68 
     69 private:
     70     typedef SkPathEffect INHERITED;
     71 };
     72 
     73 ///////////////////////////////////////////////////////////////////////////////////////////////////
     74 
     75 /** \class SkComposePathEffect
     76 
     77  This subclass of SkPathEffect composes its two arguments, to create
     78  a compound pathEffect.
     79  */
     80 class SkComposePathEffect : public SkPairPathEffect {
     81 public:
     82     /** Construct a pathEffect whose effect is to apply first the inner pathEffect
     83      and the the outer pathEffect (e.g. outer(inner(path)))
     84      The reference counts for outer and inner are both incremented in the constructor,
     85      and decremented in the destructor.
     86      */
     87     static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner) {
     88         if (!outer) {
     89             return inner;
     90         }
     91         if (!inner) {
     92             return outer;
     93         }
     94         return sk_sp<SkPathEffect>(new SkComposePathEffect(outer, inner));
     95     }
     96 
     97 protected:
     98     SkComposePathEffect(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner)
     99         : INHERITED(outer, inner) {}
    100 
    101     bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
    102                       const SkRect* cullRect) const override {
    103         SkPath          tmp;
    104         const SkPath*   ptr = &src;
    105 
    106         if (fPE1->filterPath(&tmp, src, rec, cullRect)) {
    107             ptr = &tmp;
    108         }
    109         return fPE0->filterPath(dst, *ptr, rec, cullRect);
    110     }
    111 
    112 private:
    113     SK_FLATTENABLE_HOOKS(SkComposePathEffect)
    114 
    115     // illegal
    116     SkComposePathEffect(const SkComposePathEffect&);
    117     SkComposePathEffect& operator=(const SkComposePathEffect&);
    118     friend class SkPathEffect;
    119 
    120     typedef SkPairPathEffect INHERITED;
    121 };
    122 
    123 sk_sp<SkFlattenable> SkComposePathEffect::CreateProc(SkReadBuffer& buffer) {
    124     sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
    125     sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
    126     return SkComposePathEffect::Make(std::move(pe0), std::move(pe1));
    127 }
    128 
    129 ///////////////////////////////////////////////////////////////////////////////
    130 
    131 /** \class SkSumPathEffect
    132 
    133  This subclass of SkPathEffect applies two pathEffects, one after the other.
    134  Its filterPath() returns true if either of the effects succeeded.
    135  */
    136 class SkSumPathEffect : public SkPairPathEffect {
    137 public:
    138     /** Construct a pathEffect whose effect is to apply two effects, in sequence.
    139      (e.g. first(path) + second(path))
    140      The reference counts for first and second are both incremented in the constructor,
    141      and decremented in the destructor.
    142      */
    143     static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
    144         if (!first) {
    145             return second;
    146         }
    147         if (!second) {
    148             return first;
    149         }
    150         return sk_sp<SkPathEffect>(new SkSumPathEffect(first, second));
    151     }
    152 
    153     SK_FLATTENABLE_HOOKS(SkSumPathEffect)
    154 
    155 protected:
    156     SkSumPathEffect(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second)
    157         : INHERITED(first, second) {}
    158 
    159     bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
    160                       const SkRect* cullRect) const override {
    161         // use bit-or so that we always call both, even if the first one succeeds
    162         return fPE0->filterPath(dst, src, rec, cullRect) |
    163                fPE1->filterPath(dst, src, rec, cullRect);
    164     }
    165 
    166 private:
    167     // illegal
    168     SkSumPathEffect(const SkSumPathEffect&);
    169     SkSumPathEffect& operator=(const SkSumPathEffect&);
    170     friend class SkPathEffect;
    171 
    172     typedef SkPairPathEffect INHERITED;
    173 };
    174 
    175 sk_sp<SkFlattenable> SkSumPathEffect::CreateProc(SkReadBuffer& buffer) {
    176     sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
    177     sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
    178     return SkSumPathEffect::Make(pe0, pe1);
    179 }
    180 
    181 ///////////////////////////////////////////////////////////////////////////////////////////////////
    182 
    183 sk_sp<SkPathEffect> SkPathEffect::MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
    184     return SkSumPathEffect::Make(std::move(first), std::move(second));
    185 }
    186 
    187 sk_sp<SkPathEffect> SkPathEffect::MakeCompose(sk_sp<SkPathEffect> outer,
    188                                               sk_sp<SkPathEffect> inner) {
    189     return SkComposePathEffect::Make(std::move(outer), std::move(inner));
    190 }
    191 
    192 void SkPathEffect::RegisterFlattenables() {
    193     SK_REGISTER_FLATTENABLE(SkComposePathEffect);
    194     SK_REGISTER_FLATTENABLE(SkSumPathEffect);
    195 }
    196