180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkPathMeasure_DEFINED
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPathMeasure_DEFINED
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkPathMeasure : SkNoncopyable {
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPathMeasure();
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Initialize the pathmeasure with the specified path. The path must remain valid
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for the lifetime of the measure object, or until setPath() is called with
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a different path (or null), since the measure object keeps a pointer to the
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        path object (does not copy its data).
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPathMeasure(const SkPath& path, bool forceClosed);
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkPathMeasure();
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Reset the pathmeasure with the specified path. The path must remain valid
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for the lifetime of the measure object, or until setPath() is called with
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a different path (or null), since the measure object keeps a pointer to the
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        path object (does not copy its data).
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void setPath(const SkPath*, bool forceClosed);
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Return the total length of the current contour, or 0 if no path
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        is associated (e.g. resetPath(null))
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar getLength();
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Pins distance to 0 <= distance <= getLength(), and then computes
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        the corresponding position and tangent.
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Returns false if there is no path, or a zero-length path was specified, in which case
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        position and tangent are unchanged.
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         SkVector* tangent);
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    enum MatrixFlags {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kGetPosition_MatrixFlag     = 0x01,
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kGetTangent_MatrixFlag      = 0x02,
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Pins distance to 0 <= distance <= getLength(), and then computes
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        the corresponding matrix (by calling getPosTan).
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Returns false if there is no path, or a zero-length path was specified, in which case
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix is unchanged.
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  MatrixFlags flags = kGetPosAndTan_MatrixFlag);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Given a start and stop distance, return in dst the intervening segment(s).
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        If the segment is zero-length, return false, else return true.
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        then return false (and leave dst untouched).
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Begin the segment with a moveTo if startWithMoveTo is true
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Return true if the current contour is closed()
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isClosed();
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Move to the next contour in the path. Return true if one exists, or false if
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        we're done with the path.
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool nextContour();
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void    dump();
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath::Iter    fIter;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkPath*   fPath;
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar        fLength;            // relative to the current contour
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int             fFirstPtIndex;      // relative to the current contour
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool            fIsClosed;          // relative to the current contour
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool            fForceClosed;
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Segment {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar    fDistance;  // total distance up to this point
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned    fPtIndex : 15; // index into the fPts array
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned    fTValue : 15;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned    fType : 2;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar getScalarT() const;
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<Segment>  fSegments;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<SkPoint>  fPts; // Points used to define the segments
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const Segment* NextSegment(const Segment*);
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void     buildSegments();
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                int mint, int maxt, int ptIndex);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                int mint, int maxt, int ptIndex);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
112