michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #ifndef SkPathEffect_DEFINED michael@0: #define SkPathEffect_DEFINED michael@0: michael@0: #include "SkFlattenable.h" michael@0: #include "SkPath.h" michael@0: #include "SkPoint.h" michael@0: #include "SkRect.h" michael@0: #include "SkStrokeRec.h" michael@0: #include "SkTDArray.h" michael@0: michael@0: class SkPath; michael@0: michael@0: /** \class SkPathEffect michael@0: michael@0: SkPathEffect is the base class for objects in the SkPaint that affect michael@0: the geometry of a drawing primitive before it is transformed by the michael@0: canvas' matrix and drawn. michael@0: michael@0: Dashing is implemented as a subclass of SkPathEffect. michael@0: */ michael@0: class SK_API SkPathEffect : public SkFlattenable { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkPathEffect) michael@0: michael@0: /** michael@0: * Given a src path (input) and a stroke-rec (input and output), apply michael@0: * this effect to the src path, returning the new path in dst, and return michael@0: * true. If this effect cannot be applied, return false and ignore dst michael@0: * and stroke-rec. michael@0: * michael@0: * The stroke-rec specifies the initial request for stroking (if any). michael@0: * The effect can treat this as input only, or it can choose to change michael@0: * the rec as well. For example, the effect can decide to change the michael@0: * stroke's width or join, or the effect can change the rec from stroke michael@0: * to fill (or fill to stroke) in addition to returning a new (dst) path. michael@0: * michael@0: * If this method returns true, the caller will apply (as needed) the michael@0: * resulting stroke-rec to dst and then draw. michael@0: */ michael@0: virtual bool filterPath(SkPath* dst, const SkPath& src, michael@0: SkStrokeRec*, const SkRect* cullR) const = 0; michael@0: michael@0: /** michael@0: * Compute a conservative bounds for its effect, given the src bounds. michael@0: * The baseline implementation just assigns src to dst. michael@0: */ michael@0: virtual void computeFastBounds(SkRect* dst, const SkRect& src) const; michael@0: michael@0: /** \class PointData michael@0: michael@0: PointData aggregates all the information needed to draw the point michael@0: primitives returned by an 'asPoints' call. michael@0: */ michael@0: class PointData { michael@0: public: michael@0: PointData() michael@0: : fFlags(0) michael@0: , fPoints(NULL) michael@0: , fNumPoints(0) { michael@0: fSize.set(SK_Scalar1, SK_Scalar1); michael@0: // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets michael@0: // the kUseClip flag michael@0: }; michael@0: ~PointData() { michael@0: delete [] fPoints; michael@0: } michael@0: michael@0: // TODO: consider using passed-in flags to limit the work asPoints does. michael@0: // For example, a kNoPath flag could indicate don't bother generating michael@0: // stamped solutions. michael@0: michael@0: // Currently none of these flags are supported. michael@0: enum PointFlags { michael@0: kCircles_PointFlag = 0x01, // draw points as circles (instead of rects) michael@0: kUsePath_PointFlag = 0x02, // draw points as stamps of the returned path michael@0: kUseClip_PointFlag = 0x04, // apply 'fClipRect' before drawing the points michael@0: }; michael@0: michael@0: uint32_t fFlags; // flags that impact the drawing of the points michael@0: SkPoint* fPoints; // the center point of each generated point michael@0: int fNumPoints; // number of points in fPoints michael@0: SkVector fSize; // the size to draw the points michael@0: SkRect fClipRect; // clip required to draw the points (if kUseClip is set) michael@0: SkPath fPath; // 'stamp' to be used at each point (if kUsePath is set) michael@0: michael@0: SkPath fFirst; // If not empty, contains geometry for first point michael@0: SkPath fLast; // If not empty, contains geometry for last point michael@0: }; michael@0: michael@0: /** michael@0: * Does applying this path effect to 'src' yield a set of points? If so, michael@0: * optionally return the points in 'results'. michael@0: */ michael@0: virtual bool asPoints(PointData* results, const SkPath& src, michael@0: const SkStrokeRec&, const SkMatrix&, michael@0: const SkRect* cullR) const; michael@0: michael@0: SK_DEFINE_FLATTENABLE_TYPE(SkPathEffect) michael@0: michael@0: protected: michael@0: SkPathEffect() {} michael@0: SkPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} michael@0: michael@0: private: michael@0: // illegal michael@0: SkPathEffect(const SkPathEffect&); michael@0: SkPathEffect& operator=(const SkPathEffect&); michael@0: michael@0: typedef SkFlattenable INHERITED; michael@0: }; michael@0: michael@0: /** \class SkPairPathEffect michael@0: michael@0: Common baseclass for Compose and Sum. This subclass manages two pathEffects, michael@0: including flattening them. It does nothing in filterPath, and is only useful michael@0: for managing the lifetimes of its two arguments. michael@0: */ michael@0: class SkPairPathEffect : public SkPathEffect { michael@0: public: michael@0: virtual ~SkPairPathEffect(); michael@0: michael@0: protected: michael@0: SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1); michael@0: SkPairPathEffect(SkReadBuffer&); michael@0: virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; michael@0: michael@0: // these are visible to our subclasses michael@0: SkPathEffect* fPE0, *fPE1; michael@0: michael@0: private: michael@0: typedef SkPathEffect INHERITED; michael@0: }; michael@0: michael@0: /** \class SkComposePathEffect michael@0: michael@0: This subclass of SkPathEffect composes its two arguments, to create michael@0: a compound pathEffect. michael@0: */ michael@0: class SkComposePathEffect : public SkPairPathEffect { michael@0: public: michael@0: /** Construct a pathEffect whose effect is to apply first the inner pathEffect michael@0: and the the outer pathEffect (e.g. outer(inner(path))) michael@0: The reference counts for outer and inner are both incremented in the constructor, michael@0: and decremented in the destructor. michael@0: */ michael@0: static SkComposePathEffect* Create(SkPathEffect* outer, SkPathEffect* inner) { michael@0: return SkNEW_ARGS(SkComposePathEffect, (outer, inner)); michael@0: } michael@0: michael@0: virtual bool filterPath(SkPath* dst, const SkPath& src, michael@0: SkStrokeRec*, const SkRect*) const SK_OVERRIDE; michael@0: michael@0: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect) michael@0: michael@0: protected: michael@0: SkComposePathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} michael@0: michael@0: #ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS michael@0: public: michael@0: #endif michael@0: SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner) michael@0: : INHERITED(outer, inner) {} michael@0: michael@0: private: michael@0: // illegal michael@0: SkComposePathEffect(const SkComposePathEffect&); michael@0: SkComposePathEffect& operator=(const SkComposePathEffect&); michael@0: michael@0: typedef SkPairPathEffect INHERITED; michael@0: }; michael@0: michael@0: /** \class SkSumPathEffect michael@0: michael@0: This subclass of SkPathEffect applies two pathEffects, one after the other. michael@0: Its filterPath() returns true if either of the effects succeeded. michael@0: */ michael@0: class SkSumPathEffect : public SkPairPathEffect { michael@0: public: michael@0: /** Construct a pathEffect whose effect is to apply two effects, in sequence. michael@0: (e.g. first(path) + second(path)) michael@0: The reference counts for first and second are both incremented in the constructor, michael@0: and decremented in the destructor. michael@0: */ michael@0: static SkSumPathEffect* Create(SkPathEffect* first, SkPathEffect* second) { michael@0: return SkNEW_ARGS(SkSumPathEffect, (first, second)); michael@0: } michael@0: michael@0: virtual bool filterPath(SkPath* dst, const SkPath& src, michael@0: SkStrokeRec*, const SkRect*) const SK_OVERRIDE; michael@0: michael@0: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect) michael@0: michael@0: protected: michael@0: SkSumPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} michael@0: michael@0: #ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS michael@0: public: michael@0: #endif michael@0: SkSumPathEffect(SkPathEffect* first, SkPathEffect* second) michael@0: : INHERITED(first, second) {} michael@0: michael@0: private: michael@0: // illegal michael@0: SkSumPathEffect(const SkSumPathEffect&); michael@0: SkSumPathEffect& operator=(const SkSumPathEffect&); michael@0: michael@0: typedef SkPairPathEffect INHERITED; michael@0: }; michael@0: michael@0: #endif