1 2 /* 3 * Copyright 2006 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 SkMaskFilter_DEFINED 11 #define SkMaskFilter_DEFINED 12 13 #include "SkFlattenable.h" 14 #include "SkMask.h" 15 #include "SkPaint.h" 16 17 class SkBlitter; 18 class SkBounder; 19 class SkMatrix; 20 class SkPath; 21 class SkRasterClip; 22 23 /** \class SkMaskFilter 24 25 SkMaskFilter is the base class for object that perform transformations on 26 an alpha-channel mask before drawing it. A subclass of SkMaskFilter may be 27 installed into a SkPaint. Once there, each time a primitive is drawn, it 28 is first scan converted into a SkMask::kA8_Format mask, and handed to the 29 filter, calling its filterMask() method. If this returns true, then the 30 new mask is used to render into the device. 31 32 Blur and emboss are implemented as subclasses of SkMaskFilter. 33 */ 34 class SK_API SkMaskFilter : public SkFlattenable { 35 public: 36 SK_DECLARE_INST_COUNT(SkMaskFilter) 37 38 SkMaskFilter() {} 39 40 /** Returns the format of the resulting mask that this subclass will return 41 when its filterMask() method is called. 42 */ 43 virtual SkMask::Format getFormat() const = 0; 44 45 /** Create a new mask by filter the src mask. 46 If src.fImage == null, then do not allocate or create the dst image 47 but do fill out the other fields in dstMask. 48 If you do allocate a dst image, use SkMask::AllocImage() 49 If this returns false, dst mask is ignored. 50 @param dst the result of the filter. If src.fImage == null, dst should not allocate its image 51 @param src the original image to be filtered. 52 @param matrix the CTM 53 @param margin if not null, return the buffer dx/dy need when calculating the effect. Used when 54 drawing a clipped object to know how much larger to allocate the src before 55 applying the filter. If returning false, ignore this parameter. 56 @return true if the dst mask was correctly created. 57 */ 58 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, 59 SkIPoint* margin) const; 60 61 enum BlurType { 62 kNone_BlurType, //!< this maskfilter is not a blur 63 kNormal_BlurType, //!< fuzzy inside and outside 64 kSolid_BlurType, //!< solid inside, fuzzy outside 65 kOuter_BlurType, //!< nothing inside, fuzzy outside 66 kInner_BlurType //!< fuzzy inside, nothing outside 67 }; 68 69 struct BlurInfo { 70 SkScalar fRadius; 71 bool fIgnoreTransform; 72 bool fHighQuality; 73 }; 74 75 /** 76 * Optional method for maskfilters that can be described as a blur. If so, 77 * they return the corresponding BlurType and set the fields in BlurInfo 78 * (if not null). If they cannot be described as a blur, they return 79 * kNone_BlurType and ignore the info parameter. 80 */ 81 virtual BlurType asABlur(BlurInfo*) const; 82 83 /** 84 * The fast bounds function is used to enable the paint to be culled early 85 * in the drawing pipeline. This function accepts the current bounds of the 86 * paint as its src param and the filter adjust those bounds using its 87 * current mask and returns the result using the dest param. Callers are 88 * allowed to provide the same struct for both src and dest so each 89 * implementation must accomodate that behavior. 90 * 91 * The default impl calls filterMask with the src mask having no image, 92 * but subclasses may override this if they can compute the rect faster. 93 */ 94 virtual void computeFastBounds(const SkRect& src, SkRect* dest) const; 95 96 protected: 97 // empty for now, but lets get our subclass to remember to init us for the future 98 SkMaskFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 99 100 enum FilterReturn { 101 kFalse_FilterReturn, 102 kTrue_FilterReturn, 103 kUnimplemented_FilterReturn 104 }; 105 106 struct NinePatch { 107 SkMask fMask; // fBounds must have [0,0] in its top-left 108 SkIRect fOuterRect; // width/height must be >= fMask.fBounds' 109 SkIPoint fCenter; // identifies center row/col for stretching 110 }; 111 112 /** 113 * Override if your subclass can filter a rect, and return the answer as 114 * a ninepatch mask to be stretched over the returned outerRect. On success 115 * return kTrue_FilterReturn. On failure (e.g. out of memory) return 116 * kFalse_FilterReturn. If the normal filterMask() entry-point should be 117 * called (the default) return kUnimplemented_FilterReturn. 118 * 119 * By convention, the caller will take the center rol/col from the returned 120 * mask as the slice it can replicate horizontally and vertically as we 121 * stretch the mask to fit inside outerRect. It is an error for outerRect 122 * to be smaller than the mask's bounds. This would imply that the width 123 * and height of the mask should be odd. This is not required, just that 124 * the caller will call mask.fBounds.centerX() and centerY() to find the 125 * strips that will be replicated. 126 */ 127 virtual FilterReturn filterRectsToNine(const SkRect[], int count, 128 const SkMatrix&, 129 const SkIRect& clipBounds, 130 NinePatch*) const; 131 132 private: 133 friend class SkDraw; 134 135 /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask 136 and then call filterMask(). If this returns true, the specified blitter will be called 137 to render that mask. Returns false if filterMask() returned false. 138 This method is not exported to java. 139 */ 140 bool filterPath(const SkPath& devPath, const SkMatrix& devMatrix, 141 const SkRasterClip&, SkBounder*, SkBlitter* blitter, 142 SkPaint::Style style) const; 143 144 typedef SkFlattenable INHERITED; 145 }; 146 147 #endif 148