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 void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) const {
     16     *dst = src;
     17 }
     18 
     19 bool SkPathEffect::asPoints(PointData* results, const SkPath& src,
     20                     const SkStrokeRec&, const SkMatrix&, const SkRect*) const {
     21     return false;
     22 }
     23 
     24 SkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const {
     25     return kNone_DashType;
     26 }
     27 
     28 ///////////////////////////////////////////////////////////////////////////////
     29 
     30 /** \class SkPairPathEffect
     31 
     32  Common baseclass for Compose and Sum. This subclass manages two pathEffects,
     33  including flattening them. It does nothing in filterPath, and is only useful
     34  for managing the lifetimes of its two arguments.
     35  */
     36 class SkPairPathEffect : public SkPathEffect {
     37 protected:
     38     SkPairPathEffect(sk_sp<SkPathEffect> pe0, sk_sp<SkPathEffect> pe1)
     39         : fPE0(std::move(pe0)), fPE1(std::move(pe1))
     40     {
     41         SkASSERT(fPE0.get());
     42         SkASSERT(fPE1.get());
     43     }
     44 
     45     void flatten(SkWriteBuffer& buffer) const override {
     46         buffer.writeFlattenable(fPE0.get());
     47         buffer.writeFlattenable(fPE1.get());
     48     }
     49 
     50     // these are visible to our subclasses
     51     sk_sp<SkPathEffect> fPE0;
     52     sk_sp<SkPathEffect> fPE1;
     53 
     54     SK_TO_STRING_OVERRIDE()
     55 
     56 private:
     57     typedef SkPathEffect INHERITED;
     58 };
     59 
     60 #ifndef SK_IGNORE_TO_STRING
     61 void SkPairPathEffect::toString(SkString* str) const {
     62     str->appendf("first: ");
     63     if (fPE0) {
     64         fPE0->toString(str);
     65     }
     66     str->appendf(" second: ");
     67     if (fPE1) {
     68         fPE1->toString(str);
     69     }
     70 }
     71 #endif
     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     bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
     98                     const SkRect* cullRect) const override {
     99         SkPath          tmp;
    100         const SkPath*   ptr = &src;
    101 
    102         if (fPE1->filterPath(&tmp, src, rec, cullRect)) {
    103             ptr = &tmp;
    104         }
    105         return fPE0->filterPath(dst, *ptr, rec, cullRect);
    106     }
    107 
    108 
    109     SK_TO_STRING_OVERRIDE()
    110     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
    111 
    112 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    113     bool exposedInAndroidJavaAPI() const override { return true; }
    114 #endif
    115 
    116 protected:
    117     SkComposePathEffect(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner)
    118         : INHERITED(outer, inner) {}
    119 
    120 private:
    121     // illegal
    122     SkComposePathEffect(const SkComposePathEffect&);
    123     SkComposePathEffect& operator=(const SkComposePathEffect&);
    124     friend class SkPathEffect;
    125 
    126     typedef SkPairPathEffect INHERITED;
    127 };
    128 
    129 sk_sp<SkFlattenable> SkComposePathEffect::CreateProc(SkReadBuffer& buffer) {
    130     sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
    131     sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
    132     return SkComposePathEffect::Make(std::move(pe0), std::move(pe1));
    133 }
    134 
    135 #ifndef SK_IGNORE_TO_STRING
    136 void SkComposePathEffect::toString(SkString* str) const {
    137     str->appendf("SkComposePathEffect: (");
    138     this->INHERITED::toString(str);
    139     str->appendf(")");
    140 }
    141 #endif
    142 
    143 ///////////////////////////////////////////////////////////////////////////////
    144 
    145 /** \class SkSumPathEffect
    146 
    147  This subclass of SkPathEffect applies two pathEffects, one after the other.
    148  Its filterPath() returns true if either of the effects succeeded.
    149  */
    150 class SkSumPathEffect : public SkPairPathEffect {
    151 public:
    152     /** Construct a pathEffect whose effect is to apply two effects, in sequence.
    153      (e.g. first(path) + second(path))
    154      The reference counts for first and second are both incremented in the constructor,
    155      and decremented in the destructor.
    156      */
    157     static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
    158         if (!first) {
    159             return second;
    160         }
    161         if (!second) {
    162             return first;
    163         }
    164         return sk_sp<SkPathEffect>(new SkSumPathEffect(first, second));
    165     }
    166 
    167     bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
    168                     const SkRect* cullRect) const override {
    169         // use bit-or so that we always call both, even if the first one succeeds
    170         return fPE0->filterPath(dst, src, rec, cullRect) |
    171                fPE1->filterPath(dst, src, rec, cullRect);
    172     }
    173 
    174 
    175     SK_TO_STRING_OVERRIDE()
    176     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
    177 
    178 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    179     bool exposedInAndroidJavaAPI() const override { return true; }
    180 #endif
    181 
    182 protected:
    183     SkSumPathEffect(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second)
    184     : INHERITED(first, second) {}
    185 
    186 private:
    187     // illegal
    188     SkSumPathEffect(const SkSumPathEffect&);
    189     SkSumPathEffect& operator=(const SkSumPathEffect&);
    190     friend class SkPathEffect;
    191 
    192     typedef SkPairPathEffect INHERITED;
    193 };
    194 
    195 sk_sp<SkFlattenable> SkSumPathEffect::CreateProc(SkReadBuffer& buffer) {
    196     sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
    197     sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
    198     return SkSumPathEffect::Make(pe0, pe1);
    199 }
    200 
    201 #ifndef SK_IGNORE_TO_STRING
    202 void SkSumPathEffect::toString(SkString* str) const {
    203     str->appendf("SkSumPathEffect: (");
    204     this->INHERITED::toString(str);
    205     str->appendf(")");
    206 }
    207 #endif
    208 
    209 ///////////////////////////////////////////////////////////////////////////////////////////////////
    210 
    211 sk_sp<SkPathEffect> SkPathEffect::MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
    212     return SkSumPathEffect::Make(std::move(first), std::move(second));
    213 }
    214 
    215 sk_sp<SkPathEffect> SkPathEffect::MakeCompose(sk_sp<SkPathEffect> outer,
    216                                               sk_sp<SkPathEffect> inner) {
    217     return SkComposePathEffect::Make(std::move(outer), std::move(inner));
    218 }
    219 
    220 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkPathEffect)
    221     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposePathEffect)
    222     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
    223 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
    224