SkPathEffect.h revision 6d87557278052c131957e5d6e093d3a675162d22
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 SkPathEffect_DEFINED 11#define SkPathEffect_DEFINED 12 13#include "SkFlattenable.h" 14#include "SkPaint.h" 15#include "SkPath.h" 16#include "SkPoint.h" 17#include "SkRect.h" 18#include "SkTDArray.h" 19 20class SkPath; 21 22class SkStrokeRec { 23public: 24 enum InitStyle { 25 kHairline_InitStyle, 26 kFill_InitStyle 27 }; 28 SkStrokeRec(InitStyle style); 29 30 SkStrokeRec(const SkStrokeRec&); 31 explicit SkStrokeRec(const SkPaint&); 32 33 enum Style { 34 kHairline_Style, 35 kFill_Style, 36 kStroke_Style, 37 kStrokeAndFill_Style 38 }; 39 40 Style getStyle() const; 41 SkScalar getWidth() const { return fWidth; } 42 SkScalar getMiter() const { return fMiterLimit; } 43 SkPaint::Cap getCap() const { return fCap; } 44 SkPaint::Join getJoin() const { return fJoin; } 45 46 bool isHairlineStyle() const { 47 return kHairline_Style == this->getStyle(); 48 } 49 50 bool isFillStyle() const { 51 return kFill_Style == this->getStyle(); 52 } 53 54 void setFillStyle(); 55 void setHairlineStyle(); 56 /** 57 * Specify the strokewidth, and optionally if you want stroke + fill. 58 * Note, if width==0, then this request is taken to mean: 59 * strokeAndFill==true -> new style will be Fill 60 * strokeAndFill==false -> new style will be Hairline 61 */ 62 void setStrokeStyle(SkScalar width, bool strokeAndFill = false); 63 64 void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) { 65 fCap = cap; 66 fJoin = join; 67 fMiterLimit = miterLimit; 68 } 69 70 /** 71 * Returns true if this specifes any thick stroking, i.e. applyToPath() 72 * will return true. 73 */ 74 bool needToApply() const { 75 Style style = this->getStyle(); 76 return (kStroke_Style == style) || (kStrokeAndFill_Style == style); 77 } 78 79 /** 80 * Apply these stroke parameters to the src path, returning the result 81 * in dst. 82 * 83 * If there was no change (i.e. style == hairline or fill) this returns 84 * false and dst is unchanged. Otherwise returns true and the result is 85 * stored in dst. 86 * 87 * src and dst may be the same path. 88 */ 89 bool applyToPath(SkPath* dst, const SkPath& src) const; 90 91private: 92 SkScalar fWidth; 93 SkScalar fMiterLimit; 94 SkPaint::Cap fCap; 95 SkPaint::Join fJoin; 96 bool fStrokeAndFill; 97}; 98 99/** \class SkPathEffect 100 101 SkPathEffect is the base class for objects in the SkPaint that affect 102 the geometry of a drawing primitive before it is transformed by the 103 canvas' matrix and drawn. 104 105 Dashing is implemented as a subclass of SkPathEffect. 106*/ 107class SK_API SkPathEffect : public SkFlattenable { 108public: 109 SK_DECLARE_INST_COUNT(SkPathEffect) 110 111 SkPathEffect() {} 112 113 /** 114 * Given a src path (input) and a stroke-rec (input and output), apply 115 * this effect to the src path, returning the new path in dst, and return 116 * true. If this effect cannot be applied, return false and ignore dst 117 * and stroke-rec. 118 * 119 * The stroke-rec specifies the initial request for stroking (if any). 120 * The effect can treat this as input only, or it can choose to change 121 * the rec as well. For example, the effect can decide to change the 122 * stroke's width or join, or the effect can change the rec from stroke 123 * to fill (or fill to stroke) in addition to returning a new (dst) path. 124 * 125 * If this method returns true, the caller will apply (as needed) the 126 * resulting stroke-rec to dst and then draw. 127 */ 128 virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) = 0; 129 130 /** 131 * Compute a conservative bounds for its effect, given the src bounds. 132 * The baseline implementation just assigns src to dst. 133 */ 134 virtual void computeFastBounds(SkRect* dst, const SkRect& src); 135 136 /** \class PointData 137 138 PointData aggregates all the information needed to draw the point 139 primitives returned by an 'asPoints' call. 140 */ 141 class PointData { 142 public: 143 PointData() 144 : fFlags(0) 145 , fPoints(NULL) 146 , fNumPoints(0) { 147 fSize.set(SK_Scalar1, SK_Scalar1); 148 // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets 149 // the kUseClip flag 150 }; 151 ~PointData() { 152 delete [] fPoints; 153 } 154 155 // TODO: consider using passed-in flags to limit the work asPoints does. 156 // For example, a kNoPath flag could indicate don't bother generating 157 // stamped solutions. 158 159 // Currently none of these flags are supported. 160 enum PointFlags { 161 kCircles_PointFlag = 0x01, // draw points as circles (instead of rects) 162 kUsePath_PointFlag = 0x02, // draw points as stamps of the returned path 163 kUseClip_PointFlag = 0x04, // apply 'fClipRect' before drawing the points 164 }; 165 166 uint32_t fFlags; // flags that impact the drawing of the points 167 SkPoint* fPoints; // the center point of each generated point 168 int fNumPoints; // number of points in fPoints 169 SkVector fSize; // the size to draw the points 170 SkRect fClipRect; // clip required to draw the points (if kUseClip is set) 171 SkPath fPath; // 'stamp' to be used at each point (if kUsePath is set) 172 173 SkPath fFirst; // If not empty, contains geometry for first point 174 SkPath fLast; // If not empty, contains geometry for last point 175 }; 176 177 /** 178 * Does applying this path effect to 'src' yield a set of points? If so, 179 * optionally return the points in 'results'. 180 */ 181 virtual bool asPoints(PointData* results, const SkPath& src, 182 const SkStrokeRec&, const SkMatrix&) const; 183 184protected: 185 SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 186 187private: 188 // illegal 189 SkPathEffect(const SkPathEffect&); 190 SkPathEffect& operator=(const SkPathEffect&); 191 192 typedef SkFlattenable INHERITED; 193}; 194 195/** \class SkPairPathEffect 196 197 Common baseclass for Compose and Sum. This subclass manages two pathEffects, 198 including flattening them. It does nothing in filterPath, and is only useful 199 for managing the lifetimes of its two arguments. 200*/ 201class SkPairPathEffect : public SkPathEffect { 202public: 203 SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1); 204 virtual ~SkPairPathEffect(); 205 206protected: 207 SkPairPathEffect(SkFlattenableReadBuffer&); 208 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; 209 210 // these are visible to our subclasses 211 SkPathEffect* fPE0, *fPE1; 212 213private: 214 typedef SkPathEffect INHERITED; 215}; 216 217/** \class SkComposePathEffect 218 219 This subclass of SkPathEffect composes its two arguments, to create 220 a compound pathEffect. 221*/ 222class SkComposePathEffect : public SkPairPathEffect { 223public: 224 /** Construct a pathEffect whose effect is to apply first the inner pathEffect 225 and the the outer pathEffect (e.g. outer(inner(path))) 226 The reference counts for outer and inner are both incremented in the constructor, 227 and decremented in the destructor. 228 */ 229 SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner) 230 : INHERITED(outer, inner) {} 231 232 virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE; 233 234 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect) 235 236protected: 237 SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 238 239private: 240 // illegal 241 SkComposePathEffect(const SkComposePathEffect&); 242 SkComposePathEffect& operator=(const SkComposePathEffect&); 243 244 typedef SkPairPathEffect INHERITED; 245}; 246 247/** \class SkSumPathEffect 248 249 This subclass of SkPathEffect applies two pathEffects, one after the other. 250 Its filterPath() returns true if either of the effects succeeded. 251*/ 252class SkSumPathEffect : public SkPairPathEffect { 253public: 254 /** Construct a pathEffect whose effect is to apply two effects, in sequence. 255 (e.g. first(path) + second(path)) 256 The reference counts for first and second are both incremented in the constructor, 257 and decremented in the destructor. 258 */ 259 SkSumPathEffect(SkPathEffect* first, SkPathEffect* second) 260 : INHERITED(first, second) {} 261 262 virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE; 263 264 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect) 265 266protected: 267 SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 268 269private: 270 // illegal 271 SkSumPathEffect(const SkSumPathEffect&); 272 SkSumPathEffect& operator=(const SkSumPathEffect&); 273 274 typedef SkPairPathEffect INHERITED; 275}; 276 277#endif 278 279