SkPathEffect.h revision 548a1f321011292359ef163f78c8a1d4871b3b7f
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkPathEffect_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPathEffect_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFlattenable.h"
14629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com#include "SkPath.h"
15629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com#include "SkPoint.h"
16629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com#include "SkRect.h"
175f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h"
18629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com#include "SkTDArray.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkPath;
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkPathEffect
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect is the base class for objects in the SkPaint that affect
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    the geometry of a drawing primitive before it is transformed by the
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    canvas' matrix and drawn.
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Dashing is implemented as a subclass of SkPathEffect.
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
307ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgclass SK_API SkPathEffect : public SkFlattenable {
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
320456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com    SK_DECLARE_INST_COUNT(SkPathEffect)
330456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect() {}
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    /**
37fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  Given a src path (input) and a stroke-rec (input and output), apply
38fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  this effect to the src path, returning the new path in dst, and return
39fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  true. If this effect cannot be applied, return false and ignore dst
40fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  and stroke-rec.
41fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *
42fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  The stroke-rec specifies the initial request for stroking (if any).
43fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  The effect can treat this as input only, or it can choose to change
44fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  the rec as well. For example, the effect can decide to change the
45fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  stroke's width or join, or the effect can change the rec from stroke
46fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  to fill (or fill to stroke) in addition to returning a new (dst) path.
47fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *
48fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  If this method returns true, the caller will apply (as needed) the
49fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     *  resulting stroke-rec to dst and then draw.
50fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com     */
51548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com    virtual bool filterPath(SkPath* dst, const SkPath& src,
52548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com                            SkStrokeRec*) const = 0;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    /**
55e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com     *  Compute a conservative bounds for its effect, given the src bounds.
56e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com     *  The baseline implementation just assigns src to dst.
57e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com     */
58548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com    virtual void computeFastBounds(SkRect* dst, const SkRect& src) const;
59e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
60629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com    /** \class PointData
61629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com
62629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        PointData aggregates all the information needed to draw the point
63687c57c7d5a17549f63e0b15208db18b220e2a91skia.committer@gmail.com        primitives returned by an 'asPoints' call.
64629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com    */
65629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com    class PointData {
66629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com    public:
67629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        PointData()
68935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com            : fFlags(0)
69935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com            , fPoints(NULL)
70935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com            , fNumPoints(0) {
71629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com            fSize.set(SK_Scalar1, SK_Scalar1);
72687c57c7d5a17549f63e0b15208db18b220e2a91skia.committer@gmail.com            // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets
73629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com            // the kUseClip flag
74629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        };
75935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com        ~PointData() {
76935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com            delete [] fPoints;
77935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com        }
78629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com
79629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        // TODO: consider using passed-in flags to limit the work asPoints does.
80629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        // For example, a kNoPath flag could indicate don't bother generating
81629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        // stamped solutions.
82629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com
83629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        // Currently none of these flags are supported.
84629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        enum PointFlags {
85629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com            kCircles_PointFlag            = 0x01,   // draw points as circles (instead of rects)
86629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com            kUsePath_PointFlag            = 0x02,   // draw points as stamps of the returned path
87629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com            kUseClip_PointFlag            = 0x04,   // apply 'fClipRect' before drawing the points
88629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        };
89629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com
90629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        uint32_t           fFlags;      // flags that impact the drawing of the points
91935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com        SkPoint*           fPoints;     // the center point of each generated point
92935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com        int                fNumPoints;  // number of points in fPoints
93629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        SkVector           fSize;       // the size to draw the points
94629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        SkRect             fClipRect;   // clip required to draw the points (if kUseClip is set)
95629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com        SkPath             fPath;       // 'stamp' to be used at each point (if kUsePath is set)
966d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com
976d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com        SkPath             fFirst;      // If not empty, contains geometry for first point
986d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com        SkPath             fLast;       // If not empty, contains geometry for last point
99629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com    };
100629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com
101629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com    /**
102629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com     *  Does applying this path effect to 'src' yield a set of points? If so,
103629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com     *  optionally return the points in 'results'.
104629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com     */
105687c57c7d5a17549f63e0b15208db18b220e2a91skia.committer@gmail.com    virtual bool asPoints(PointData* results, const SkPath& src,
106629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com                          const SkStrokeRec&, const SkMatrix&) const;
107629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com
108ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.comprotected:
109ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
110ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // illegal
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect(const SkPathEffect&);
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect& operator=(const SkPathEffect&);
115ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com
116ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    typedef SkFlattenable INHERITED;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkPairPathEffect
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Common baseclass for Compose and Sum. This subclass manages two pathEffects,
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    including flattening them. It does nothing in filterPath, and is only useful
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for managing the lifetimes of its two arguments.
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkPairPathEffect : public SkPathEffect {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual ~SkPairPathEffect();
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPairPathEffect(SkFlattenableReadBuffer&);
13254924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
13354924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // these are visible to our subclasses
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect* fPE0, *fPE1;
136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkPathEffect INHERITED;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkComposePathEffect
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    This subclass of SkPathEffect composes its two arguments, to create
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a compound pathEffect.
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkComposePathEffect : public SkPairPathEffect {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Construct a pathEffect whose effect is to apply first the inner pathEffect
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and the the outer pathEffect (e.g. outer(inner(path)))
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The reference counts for outer and inner are both incremented in the constructor,
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and decremented in the destructor.
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner)
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(outer, inner) {}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
156548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com    virtual bool filterPath(SkPath* dst, const SkPath& src,
157548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com                            SkStrokeRec*) const SK_OVERRIDE;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16154924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comprotected:
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16454924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comprivate:
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // illegal
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkComposePathEffect(const SkComposePathEffect&);
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkComposePathEffect& operator=(const SkComposePathEffect&);
168fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkPairPathEffect INHERITED;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkSumPathEffect
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    This subclass of SkPathEffect applies two pathEffects, one after the other.
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Its filterPath() returns true if either of the effects succeeded.
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSumPathEffect : public SkPairPathEffect {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Construct a pathEffect whose effect is to apply two effects, in sequence.
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (e.g. first(path) + second(path))
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The reference counts for first and second are both incremented in the constructor,
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and decremented in the destructor.
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSumPathEffect(SkPathEffect* first, SkPathEffect* second)
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(first, second) {}
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
187548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com    virtual bool filterPath(SkPath* dst, const SkPath& src,
188548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com                            SkStrokeRec*) const SK_OVERRIDE;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
190ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19254924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comprotected:
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19554924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comprivate:
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // illegal
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSumPathEffect(const SkSumPathEffect&);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSumPathEffect& operator=(const SkSumPathEffect&);
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkPairPathEffect INHERITED;
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
205