SkPathEffect.h revision 687c57c7d5a17549f63e0b15208db18b220e2a91
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 fSize.set(SK_Scalar1, SK_Scalar1); 146 // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets 147 // the kUseClip flag 148 }; 149 ~PointData() {}; 150 151 // TODO: consider using passed-in flags to limit the work asPoints does. 152 // For example, a kNoPath flag could indicate don't bother generating 153 // stamped solutions. 154 155 // Currently none of these flags are supported. 156 enum PointFlags { 157 kCircles_PointFlag = 0x01, // draw points as circles (instead of rects) 158 kUsePath_PointFlag = 0x02, // draw points as stamps of the returned path 159 kUseClip_PointFlag = 0x04, // apply 'fClipRect' before drawing the points 160 }; 161 162 uint32_t fFlags; // flags that impact the drawing of the points 163 // TODO: consider replacing the TDArray with either SkData or a ptr/len field 164 SkTDArray<SkPoint> fPoints; // the center point of each generated point 165 SkVector fSize; // the size to draw the points 166 SkRect fClipRect; // clip required to draw the points (if kUseClip is set) 167 SkPath fPath; // 'stamp' to be used at each point (if kUsePath is set) 168 }; 169 170 /** 171 * Does applying this path effect to 'src' yield a set of points? If so, 172 * optionally return the points in 'results'. 173 */ 174 virtual bool asPoints(PointData* results, const SkPath& src, 175 const SkStrokeRec&, const SkMatrix&) const; 176 177protected: 178 SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 179 180private: 181 // illegal 182 SkPathEffect(const SkPathEffect&); 183 SkPathEffect& operator=(const SkPathEffect&); 184 185 typedef SkFlattenable INHERITED; 186}; 187 188/** \class SkPairPathEffect 189 190 Common baseclass for Compose and Sum. This subclass manages two pathEffects, 191 including flattening them. It does nothing in filterPath, and is only useful 192 for managing the lifetimes of its two arguments. 193*/ 194class SkPairPathEffect : public SkPathEffect { 195public: 196 SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1); 197 virtual ~SkPairPathEffect(); 198 199protected: 200 SkPairPathEffect(SkFlattenableReadBuffer&); 201 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; 202 203 // these are visible to our subclasses 204 SkPathEffect* fPE0, *fPE1; 205 206private: 207 typedef SkPathEffect INHERITED; 208}; 209 210/** \class SkComposePathEffect 211 212 This subclass of SkPathEffect composes its two arguments, to create 213 a compound pathEffect. 214*/ 215class SkComposePathEffect : public SkPairPathEffect { 216public: 217 /** Construct a pathEffect whose effect is to apply first the inner pathEffect 218 and the the outer pathEffect (e.g. outer(inner(path))) 219 The reference counts for outer and inner are both incremented in the constructor, 220 and decremented in the destructor. 221 */ 222 SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner) 223 : INHERITED(outer, inner) {} 224 225 virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE; 226 227 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect) 228 229protected: 230 SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 231 232private: 233 // illegal 234 SkComposePathEffect(const SkComposePathEffect&); 235 SkComposePathEffect& operator=(const SkComposePathEffect&); 236 237 typedef SkPairPathEffect INHERITED; 238}; 239 240/** \class SkSumPathEffect 241 242 This subclass of SkPathEffect applies two pathEffects, one after the other. 243 Its filterPath() returns true if either of the effects succeeded. 244*/ 245class SkSumPathEffect : public SkPairPathEffect { 246public: 247 /** Construct a pathEffect whose effect is to apply two effects, in sequence. 248 (e.g. first(path) + second(path)) 249 The reference counts for first and second are both incremented in the constructor, 250 and decremented in the destructor. 251 */ 252 SkSumPathEffect(SkPathEffect* first, SkPathEffect* second) 253 : INHERITED(first, second) {} 254 255 virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE; 256 257 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect) 258 259protected: 260 SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 261 262private: 263 // illegal 264 SkSumPathEffect(const SkSumPathEffect&); 265 SkSumPathEffect& operator=(const SkSumPathEffect&); 266 267 typedef SkPairPathEffect INHERITED; 268}; 269 270#endif 271 272