1 2 /* 3 * Copyright 2011 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #ifndef SkDrawLooper_DEFINED 11 #define SkDrawLooper_DEFINED 12 13 #include "include/core/SkBlurTypes.h" 14 #include "include/core/SkColor.h" 15 #include "include/core/SkFlattenable.h" 16 #include "include/core/SkPoint.h" 17 #include <functional> // std::function 18 19 class SkArenaAlloc; 20 class SkCanvas; 21 class SkPaint; 22 struct SkRect; 23 class SkString; 24 25 /** \class SkDrawLooper 26 Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are, 27 and something is drawn to a canvas with that paint, the looper subclass will 28 be called, allowing it to modify the canvas and/or paint for that draw call. 29 More than that, via the next() method, the looper can modify the draw to be 30 invoked multiple times (hence the name loop-er), allow it to perform effects 31 like shadows or frame/fills, that require more than one pass. 32 */ 33 class SK_API SkDrawLooper : public SkFlattenable { 34 public: 35 /** 36 * Holds state during a draw. Users call next() until it returns false. 37 * 38 * Subclasses of SkDrawLooper should create a subclass of this object to 39 * hold state specific to their subclass. 40 */ 41 class SK_API Context { 42 public: Context()43 Context() {} ~Context()44 virtual ~Context() {} 45 46 struct Info { 47 SkVector fTranslate; 48 bool fApplyPostCTM; 49 50 void applyToCTM(SkMatrix* ctm) const; 51 void applyToCanvas(SkCanvas*) const; 52 }; 53 54 /** 55 * Called in a loop on objects returned by SkDrawLooper::createContext(). 56 * Each time true is returned, the object is drawn (possibly with a modified 57 * canvas and/or paint). When false is finally returned, drawing for the object 58 * stops. 59 * 60 * On each call, the paint will be in its original state, but the 61 * canvas will be as it was following the previous call to next() or 62 * createContext(). 63 * 64 * The implementation must ensure that, when next() finally returns 65 * false, the canvas has been restored to the state it was 66 * initially, before createContext() was first called. 67 */ 68 virtual bool next(Info*, SkPaint*) = 0; 69 70 private: 71 Context(const Context&) = delete; 72 Context& operator=(const Context&) = delete; 73 }; 74 75 /** 76 * Called right before something is being drawn. Returns a Context 77 * whose next() method should be called until it returns false. 78 */ 79 virtual Context* makeContext(SkArenaAlloc*) const = 0; 80 81 /** 82 * The fast bounds functions are used to enable the paint to be culled early 83 * in the drawing pipeline. If a subclass can support this feature it must 84 * return true for the canComputeFastBounds() function. If that function 85 * returns false then computeFastBounds behavior is undefined otherwise it 86 * is expected to have the following behavior. Given the parent paint and 87 * the parent's bounding rect the subclass must fill in and return the 88 * storage rect, where the storage rect is with the union of the src rect 89 * and the looper's bounding rect. 90 */ 91 bool canComputeFastBounds(const SkPaint& paint) const; 92 void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const; 93 94 struct BlurShadowRec { 95 SkScalar fSigma; 96 SkVector fOffset; 97 SkColor fColor; 98 SkBlurStyle fStyle; 99 }; 100 /** 101 * If this looper can be interpreted as having two layers, such that 102 * 1. The first layer (bottom most) just has a blur and translate 103 * 2. The second layer has no modifications to either paint or canvas 104 * 3. No other layers. 105 * then return true, and if not null, fill out the BlurShadowRec). 106 * 107 * If any of the above are not met, return false and ignore the BlurShadowRec parameter. 108 */ 109 virtual bool asABlurShadow(BlurShadowRec*) const; 110 GetFlattenableType()111 static SkFlattenable::Type GetFlattenableType() { 112 return kSkDrawLooper_Type; 113 } 114 getFlattenableType()115 SkFlattenable::Type getFlattenableType() const override { 116 return kSkDrawLooper_Type; 117 } 118 119 static sk_sp<SkDrawLooper> Deserialize(const void* data, size_t size, 120 const SkDeserialProcs* procs = nullptr) { 121 return sk_sp<SkDrawLooper>(static_cast<SkDrawLooper*>( 122 SkFlattenable::Deserialize( 123 kSkDrawLooper_Type, data, size, procs).release())); 124 } 125 126 void apply(SkCanvas* canvas, const SkPaint& paint, 127 std::function<void(SkCanvas*, const SkPaint&)>); 128 129 protected: SkDrawLooper()130 SkDrawLooper() {} 131 132 private: 133 typedef SkFlattenable INHERITED; 134 }; 135 136 #endif 137