code:
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPackBits_DEFINED
#define SkPackBits_DEFINED

#include "SkTypes.h"

class SkPackBits {
public:
    /** Given the number of 16bit values that will be passed to Pack16,
        returns the worst-case size needed for the dst[] buffer.
    */
    static size_t ComputeMaxSize16(int count);

    /** Given the number of 8bit values that will be passed to Pack8,
        returns the worst-case size needed for the dst[] buffer.
    */
    static size_t ComputeMaxSize8(int count);

    /** Write the src array into a packed format. The packing process may end
        up writing more bytes than it read, so dst[] must be large enough.
        @param src      Input array of 16bit values
        @param count    Number of entries in src[]
        @param dst      Buffer (allocated by caller) to write the packed data
                        into
        @return the number of bytes written to dst[]
    */
    static size_t Pack16(const uint16_t src[], int count, uint8_t dst[]);

    /** Write the src array into a packed format. The packing process may end
        up writing more bytes than it read, so dst[] must be large enough.
        @param src      Input array of 8bit values
        @param count    Number of entries in src[]
        @param dst      Buffer (allocated by caller) to write the packed data
                        into
        @return the number of bytes written to dst[]
    */
    static size_t Pack8(const uint8_t src[], int count, uint8_t dst[]);

    /** Unpack the data in src[], and expand it into dst[]. The src[] data was
        written by a previous call to Pack16.
        @param src  Input data to unpack, previously created by Pack16.
        @param srcSize  Number of bytes of src to unpack
        @param dst  Buffer (allocated by caller) to expand the src[] into.
        @return the number of dst elements (not bytes) written into dst.
    */
    static int Unpack16(const uint8_t src[], size_t srcSize, uint16_t dst[]);

    /** Unpack the data in src[], and expand it into dst[]. The src[] data was
        written by a previous call to Pack8.
        @param src      Input data to unpack, previously created by Pack8.
        @param srcSize  Number of bytes of src to unpack
        @param dst      Buffer (allocated by caller) to expand the src[] into.
        @return the number of bytes written into dst.
    */
    static int Unpack8(const uint8_t src[], size_t srcSize, uint8_t dst[]);

    /** Unpack the data from src[], skip the first dstSkip bytes, then write
        dstWrite bytes into dst[]. The src[] data was written by a previous
        call to Pack8. Return the number of bytes actually writtten into dst[]
        @param src      Input data to unpack, previously created by Pack8.
        @param dst      Buffer (allocated by caller) to expand the src[] into.
        @param dstSkip  Number of bytes of unpacked src to skip before writing
                        into dst
        @param dstWrite Number of bytes of unpacked src to write into dst (after
                        skipping dstSkip bytes)
    */
    static void Unpack8(uint8_t dst[], size_t dstSkip, size_t dstWrite,
                        const uint8_t src[]);
};

#endif


code:
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPageFlipper_DEFINED
#define SkPageFlipper_DEFINED

#include "SkRegion.h"

/** SkPageFlipper manages alternating inval/dirty regions for a rectangular area
    (like a bitmap). You call inval() to accumulate inval areas, and then when
    you're ready to "flip" pages (i.e. draw into the one you've been
    invalidating) you call update, which swaps the inval regions, and returns
    two things to you: 1) the final inval region to be drawn into, and 2) the
    region of pixels that should be copied from the "front" page onto the one
    you're about to draw into. This copyBits region will be disjoint from the
    inval region, so both need to be handled.
 */
class SkPageFlipper {
public:
    SkPageFlipper();
    SkPageFlipper(int width, int height);

    int width() const { return fWidth; }
    int height() const { return fHeight; }

    void resize(int width, int height);

    bool isDirty() const { return !fDirty1->isEmpty(); }
    const SkRegion& dirtyRgn() const { return *fDirty1; }

    void inval();
    void inval(const SkIRect&);
    void inval(const SkRegion&);
    void inval(const SkRect&, bool antialias);

    /** When you're ready to write to the back page, call update. The returned
        region is the invalidate are that needs to be drawn to. The copyBits
        region (provided by the caller) is the area that should be copied from
        the front page to the back page (will not intersect with the returned
        inval region.

        Once this is called, the two internal regions are swapped, so the *new*
        back inval region is ready to receive new inval calls.
     */
    const SkRegion& update(SkRegion* copyBits);

private:
    SkRegion*   fDirty0;
    SkRegion*   fDirty1;
    SkRegion    fDirty0Storage;
    SkRegion    fDirty1Storage;
    int         fWidth;
    int         fHeight;
};

#endif

license: mit


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPaint_DEFINED
#define SkPaint_DEFINED

#include "SkColor.h"
#include "SkMath.h"
#include "SkXfermode.h"

class SkAutoGlyphCache;
class SkColorFilter;
class SkDescriptor;
class SkFlattenableReadBuffer;
class SkFlattenableWriteBuffer;
struct SkGlyph;
struct SkRect;
class SkGlyphCache;
class SkMaskFilter;
class SkMatrix;
class SkPath;
class SkPathEffect;
class SkRasterizer;
class SkShader;
class SkDrawLooper;
class SkTypeface;

typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**,
                                           SkFixed x, SkFixed y);

typedef const SkGlyph& (*SkMeasureCacheProc)(SkGlyphCache*, const char**);

/** \class SkPaint

    The SkPaint class holds the style and color information about how to draw
    geometries, text and bitmaps.
*/
class SK_API SkPaint {
public:
    SkPaint();
    SkPaint(const SkPaint& paint);
    ~SkPaint();

    SkPaint& operator=(const SkPaint&);

    SK_API friend int operator==(const SkPaint& a, const SkPaint& b);
    friend int operator!=(const SkPaint& a, const SkPaint& b) {
        return !(a == b);
    }

    void flatten(SkFlattenableWriteBuffer&) const;
    void unflatten(SkFlattenableReadBuffer&);

    /** Restores the paint to its initial settings.
    */
    void reset();

    /** Specifies the level of hinting to be performed. These names are taken
        from the Gnome/Cairo names for the same. They are translated into
        Freetype concepts the same as in cairo-ft-font.c:
           kNo_Hinting     -> FT_LOAD_NO_HINTING
           kSlight_Hinting -> FT_LOAD_TARGET_LIGHT
           kNormal_Hinting -> <default, no option>
           kFull_Hinting   -> <same as kNormalHinting, unless we are rendering
                              subpixel glyphs, in which case TARGET_LCD or
                              TARGET_LCD_V is used>
    */
    enum Hinting {
        kNo_Hinting            = 0,
        kSlight_Hinting        = 1,
        kNormal_Hinting        = 2,     //!< this is the default
        kFull_Hinting          = 3,
    };

    Hinting getHinting() const {
        return static_cast<Hinting>(fHinting);
    }

    void setHinting(Hinting hintingLevel);

    /** Specifies the bit values that are stored in the paint's flags.
    */
    enum Flags {
        kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing
        kFilterBitmap_Flag    = 0x02,   //!< mask to enable bitmap filtering
        kDither_Flag          = 0x04,   //!< mask to enable dithering
        kUnderlineText_Flag   = 0x08,   //!< mask to enable underline text
        kStrikeThruText_Flag  = 0x10,   //!< mask to enable strike-thru text
        kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text
        kLinearText_Flag      = 0x40,   //!< mask to enable linear-text
        kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel text positioning
        kDevKernText_Flag     = 0x100,  //!< mask to enable device kerning text
        kLCDRenderText_Flag   = 0x200,  //!< mask to enable subpixel glyph renderering
        kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes
        kAutoHinting_Flag     = 0x800,  //!< mask to force Freetype's autohinter
        // when adding extra flags, note that the fFlags member is specified
        // with a bit-width and you'll have to expand it.

        kAllFlags = 0xFFF
    };

    /** Return the paint's flags. Use the Flag enum to test flag values.
        @return the paint's flags (see enums ending in _Flag for bit masks)
    */
    uint32_t getFlags() const { return fFlags; }

    /** Set the paint's flags. Use the Flag enum to specific flag values.
        @param flags    The new flag bits for the paint (see Flags enum)
    */
    void setFlags(uint32_t flags);

    /** Helper for getFlags(), returning true if kAntiAlias_Flag bit is set
        @return true if the antialias bit is set in the paint's flags.
        */
    bool isAntiAlias() const {
        return SkToBool(this->getFlags() & kAntiAlias_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kAntiAlias_Flag bit
        @param aa   true to enable antialiasing, false to disable it
        */
    void setAntiAlias(bool aa);

    /** Helper for getFlags(), returning true if kDither_Flag bit is set
        @return true if the dithering bit is set in the paint's flags.
        */
    bool isDither() const {
        return SkToBool(this->getFlags() & kDither_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kDither_Flag bit
        @param dither   true to enable dithering, false to disable it
        */
    void setDither(bool dither);

    /** Helper for getFlags(), returning true if kLinearText_Flag bit is set
        @return true if the lineartext bit is set in the paint's flags
    */
    bool isLinearText() const {
        return SkToBool(this->getFlags() & kLinearText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kLinearText_Flag bit
        @param linearText true to set the linearText bit in the paint's flags,
                          false to clear it.
    */
    void setLinearText(bool linearText);

    /** Helper for getFlags(), returning true if kSubpixelText_Flag bit is set
        @return true if the lineartext bit is set in the paint's flags
    */
    bool isSubpixelText() const {
        return SkToBool(this->getFlags() & kSubpixelText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kSubpixelText_Flag
       bit @param subpixelText true to set the subpixelText bit in the paint's flags,
                               false to clear it.
    */
    void setSubpixelText(bool subpixelText);

    bool isLCDRenderText() const {
        return SkToBool(this->getFlags() & kLCDRenderText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kLCDRenderText_Flag bit
        @param subpixelRender true to set the subpixelRenderText bit in the paint's flags,
                              false to clear it.
    */
    void setLCDRenderText(bool subpixelRender);

    bool isEmbeddedBitmapText() const {
        return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kEmbeddedBitmapText_Flag bit
        @param useEmbeddedBitmapText true to set the kEmbeddedBitmapText bit in the paint's flags,
                                     false to clear it.
    */
    void setEmbeddedBitmapText(bool useEmbeddedBitmapText);

    bool isAutohinted() const {
        return SkToBool(this->getFlags() & kAutoHinting_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kAutoHinting_Flag bit
        @param useAutohinter true to set the kEmbeddedBitmapText bit in the
                                  paint's flags,
                             false to clear it.
    */
    void setAutohinted(bool useAutohinter);

    /** Helper for getFlags(), returning true if kUnderlineText_Flag bit is set
        @return true if the underlineText bit is set in the paint's flags.
    */
    bool isUnderlineText() const {
        return SkToBool(this->getFlags() & kUnderlineText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kUnderlineText_Flag bit
        @param underlineText true to set the underlineText bit in the paint's
                             flags, false to clear it.
    */
    void setUnderlineText(bool underlineText);

    /** Helper for getFlags(), returns true if kStrikeThruText_Flag bit is set
        @return true if the strikeThruText bit is set in the paint's flags.
    */
    bool isStrikeThruText() const {
        return SkToBool(this->getFlags() & kStrikeThruText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kStrikeThruText_Flag bit
        @param strikeThruText   true to set the strikeThruText bit in the
                                paint's flags, false to clear it.
    */
    void setStrikeThruText(bool strikeThruText);

    /** Helper for getFlags(), returns true if kFakeBoldText_Flag bit is set
        @return true if the kFakeBoldText_Flag bit is set in the paint's flags.
    */
    bool isFakeBoldText() const {
        return SkToBool(this->getFlags() & kFakeBoldText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kFakeBoldText_Flag bit
        @param fakeBoldText true to set the kFakeBoldText_Flag bit in the paint's
                            flags, false to clear it.
    */
    void setFakeBoldText(bool fakeBoldText);

    /** Helper for getFlags(), returns true if kDevKernText_Flag bit is set
        @return true if the kernText bit is set in the paint's flags.
    */
    bool isDevKernText() const {
        return SkToBool(this->getFlags() & kDevKernText_Flag);
    }

    /** Helper for setFlags(), setting or clearing the kKernText_Flag bit
        @param kernText true to set the kKernText_Flag bit in the paint's
                            flags, false to clear it.
    */
    void setDevKernText(bool devKernText);

    bool isFilterBitmap() const {
        return SkToBool(this->getFlags() & kFilterBitmap_Flag);
    }

    void setFilterBitmap(bool filterBitmap);

    /** Styles apply to rect, oval, path, and text.
        Bitmaps are always drawn in "fill", and lines are always drawn in
        "stroke".

        Note: strokeandfill implicitly draws the result with
        SkPath::kWinding_FillType, so if the original path is even-odd, the
        results may not appear the same as if it was drawn twice, filled and
        then stroked.
    */
    enum Style {
        kFill_Style,            //!< fill the geometry
        kStroke_Style,          //!< stroke the geometry
        kStrokeAndFill_Style,   //!< fill and stroke the geometry

        kStyleCount,
    };

    /** Return the paint's style, used for controlling how primitives'
        geometries are interpreted (except for drawBitmap, which always assumes
        kFill_Style).
        @return the paint's Style
    */
    Style getStyle() const { return (Style)fStyle; }

    /** Set the paint's style, used for controlling how primitives'
        geometries are interpreted (except for drawBitmap, which always assumes
        Fill).
        @param style    The new style to set in the paint
    */
    void setStyle(Style style);

    /** Return the paint's color. Note that the color is a 32bit value
        containing alpha as well as r,g,b. This 32bit value is not
        premultiplied, meaning that its alpha can be any value, regardless of
        the values of r,g,b.
        @return the paint's color (and alpha).
    */
    SkColor getColor() const { return fColor; }

    /** Set the paint's color. Note that the color is a 32bit value containing
        alpha as well as r,g,b. This 32bit value is not premultiplied, meaning
        that its alpha can be any value, regardless of the values of r,g,b.
        @param color    The new color (including alpha) to set in the paint.
    */
    void setColor(SkColor color);

    /** Helper to getColor() that just returns the color's alpha value.
        @return the alpha component of the paint's color.
        */
    uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }

    /** Helper to setColor(), that only assigns the color's alpha value,
        leaving its r,g,b values unchanged.
        @param a    set the alpha component (0..255) of the paint's color.
    */
    void setAlpha(U8CPU a);

    /** Helper to setColor(), that takes a,r,g,b and constructs the color value
        using SkColorSetARGB()
        @param a    The new alpha component (0..255) of the paint's color.
        @param r    The new red component (0..255) of the paint's color.
        @param g    The new green component (0..255) of the paint's color.
        @param b    The new blue component (0..255) of the paint's color.
    */
    void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);

    /** Return the width for stroking.

        A value of 0 strokes in hairline mode.
        Hairlines always draw 1-pixel wide, regardless of the matrix.
        @return the paint's stroke width, used whenever the paint's style is
                Stroke or StrokeAndFill.
    */
    SkScalar getStrokeWidth() const { return fWidth; }

    /** Set the width for stroking.
        Pass 0 to stroke in hairline mode.
        Hairlines always draw 1-pixel wide, regardless of the matrix.
        @param width set the paint's stroke width, used whenever the paint's
                     style is Stroke or StrokeAndFill.
    */
    void setStrokeWidth(SkScalar width);

    /** Return the paint's stroke miter value. This is used to control the
        behavior of miter joins when the joins angle is sharp.
        @return the paint's miter limit, used whenever the paint's style is
                Stroke or StrokeAndFill.
    */
    SkScalar getStrokeMiter() const { return fMiterLimit; }

    /** Set the paint's stroke miter value. This is used to control the
        behavior of miter joins when the joins angle is sharp. This value must
        be >= 0.
        @param miter    set the miter limit on the paint, used whenever the
                        paint's style is Stroke or StrokeAndFill.
    */
    void setStrokeMiter(SkScalar miter);

    /** Cap enum specifies the settings for the paint's strokecap. This is the
        treatment that is applied to the beginning and end of each non-closed
        contour (e.g. lines).
    */
    enum Cap {
        kButt_Cap,      //!< begin/end contours with no extension
        kRound_Cap,     //!< begin/end contours with a semi-circle extension
        kSquare_Cap,    //!< begin/end contours with a half square extension

        kCapCount,
        kDefault_Cap = kButt_Cap
    };

    /** Join enum specifies the settings for the paint's strokejoin. This is
        the treatment that is applied to corners in paths and rectangles.
    */
    enum Join {
        kMiter_Join,    //!< connect path segments with a sharp join
        kRound_Join,    //!< connect path segments with a round join
        kBevel_Join,    //!< connect path segments with a flat bevel join

        kJoinCount,
        kDefault_Join = kMiter_Join
    };

    /** Return the paint's stroke cap type, controlling how the start and end
        of stroked lines and paths are treated.
        @return the line cap style for the paint, used whenever the paint's
                style is Stroke or StrokeAndFill.
    */
    Cap getStrokeCap() const { return (Cap)fCapType; }

    /** Set the paint's stroke cap type.
        @param cap  set the paint's line cap style, used whenever the paint's
                    style is Stroke or StrokeAndFill.
    */
    void setStrokeCap(Cap cap);

    /** Return the paint's stroke join type.
        @return the paint's line join style, used whenever the paint's style is
                Stroke or StrokeAndFill.
    */
    Join getStrokeJoin() const { return (Join)fJoinType; }

    /** Set the paint's stroke join type.
        @param join set the paint's line join style, used whenever the paint's
                    style is Stroke or StrokeAndFill.
    */
    void setStrokeJoin(Join join);

    /** Applies any/all effects (patheffect, stroking) to src, returning the
        result in dst. The result is that drawing src with this paint will be
        the same as drawing dst with a default paint (at least from the
        geometric perspective).
        @param src  input path
        @param dst  output path (may be the same as src)
        @return     true if the path should be filled, or false if it should be
                    drawn with a hairline (width == 0)
    */
    bool getFillPath(const SkPath& src, SkPath* dst) const;

    /** Returns true if the current paint settings allow for fast computation of
        bounds (i.e. there is nothing complex like a patheffect that would make
        the bounds computation expensive.
    */
    bool canComputeFastBounds() const {
        // use bit-or since no need for early exit
        return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
                reinterpret_cast<uintptr_t>(this->getLooper()) |
                reinterpret_cast<uintptr_t>(this->getRasterizer()) |
                reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
    }

    /** Only call this if canComputeFastBounds() returned true. This takes a
        raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
        effects in the paint (e.g. stroking). If needed, it uses the storage
        rect parameter. It returns the adjusted bounds that can then be used
        for quickReject tests.

        The returned rect will either be orig or storage, thus the caller
        should not rely on storage being set to the result, but should always
        use the retured value. It is legal for orig and storage to be the same
        rect.

        e.g.
        if (paint.canComputeFastBounds()) {
            SkRect r, storage;
            path.computeBounds(&r, SkPath::kFast_BoundsType);
            const SkRect& fastR = paint.computeFastBounds(r, &storage);
            if (canvas->quickReject(fastR, ...)) {
                // don't draw the path
            }
        }
    */
    const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
        return this->getStyle() == kFill_Style ? orig :
                    this->computeStrokeFastBounds(orig, storage);
    }

    /** Get the paint's shader object.

      The shader's reference count is not affected.
        @return the paint's shader (or NULL)
    */
    SkShader* getShader() const { return fShader; }

    /** Set or clear the shader object.

        Pass NULL to clear any previous shader.
        As a convenience, the parameter passed is also returned.
        If a previous shader exists, its reference count is decremented.
        If shader is not NULL, its reference count is incremented.
        @param shader   May be NULL. The shader to be installed in the paint
        @return         shader
    */
    SkShader* setShader(SkShader* shader);

    /** Get the paint's colorfilter. If there is a colorfilter, its reference
        count is not changed.
        @return the paint's colorfilter (or NULL)
    */
    SkColorFilter* getColorFilter() const { return fColorFilter; }

    /** Set or clear the paint's colorfilter, returning the parameter.

        If the paint already has a filter, its reference count is decremented.
        If filter is not NULL, its reference count is incremented.
        @param filter   May be NULL. The filter to be installed in the paint
        @return         filter
    */
    SkColorFilter* setColorFilter(SkColorFilter* filter);

    /** Get the paint's xfermode object.

      The xfermode's reference count is not affected.
        @return the paint's xfermode (or NULL)
    */
    SkXfermode* getXfermode() const { return fXfermode; }

    /** Set or clear the xfermode object.

        Pass NULL to clear any previous xfermode.
        As a convenience, the parameter passed is also returned.
        If a previous xfermode exists, its reference count is decremented.
        If xfermode is not NULL, its reference count is incremented.
        @param xfermode May be NULL. The new xfermode to be installed in the
                        paint
        @return         xfermode
    */
    SkXfermode* setXfermode(SkXfermode* xfermode);

    /** Create an xfermode based on the specified Mode, and assign it into the
        paint, returning the mode that was set. If the Mode is SrcOver, then
        the paint's xfermode is set to null.
     */
    SkXfermode* setXfermodeMode(SkXfermode::Mode);

    /** Get the paint's patheffect object.

      The patheffect reference count is not affected.
        @return the paint's patheffect (or NULL)
    */
    SkPathEffect* getPathEffect() const { return fPathEffect; }

    /** Set or clear the patheffect object.

        Pass NULL to clear any previous patheffect.
        As a convenience, the parameter passed is also returned.
        If a previous patheffect exists, its reference count is decremented.
        If patheffect is not NULL, its reference count is incremented.
        @param effect   May be NULL. The new patheffect to be installed in the
                        paint
        @return         effect
    */
    SkPathEffect* setPathEffect(SkPathEffect* effect);

    /** Get the paint's maskfilter object.

      The maskfilter reference count is not affected.
        @return the paint's maskfilter (or NULL)
    */
    SkMaskFilter* getMaskFilter() const { return fMaskFilter; }

    /** Set or clear the maskfilter object.

        Pass NULL to clear any previous maskfilter.
        As a convenience, the parameter passed is also returned.
        If a previous maskfilter exists, its reference count is decremented.
        If maskfilter is not NULL, its reference count is incremented.
        @param maskfilter   May be NULL. The new maskfilter to be installed in
                            the paint
        @return             maskfilter
    */
    SkMaskFilter* setMaskFilter(SkMaskFilter* maskfilter);

    // These attributes are for text/fonts

    /** Get the paint's typeface object.

        The typeface object identifies which font to use when drawing or
        measuring text. The typeface reference count is not affected.
        @return the paint's typeface (or NULL)
    */
    SkTypeface* getTypeface() const { return fTypeface; }

    /** Set or clear the typeface object.

        Pass NULL to clear any previous typeface.
        As a convenience, the parameter passed is also returned.
        If a previous typeface exists, its reference count is decremented.
        If typeface is not NULL, its reference count is incremented.
        @param typeface May be NULL. The new typeface to be installed in the
                        paint
        @return         typeface
    */
    SkTypeface* setTypeface(SkTypeface* typeface);

    /** Get the paint's rasterizer (or NULL).

        The raster controls how paths/text are turned into alpha masks.
        @return the paint's rasterizer (or NULL)
    */
    SkRasterizer* getRasterizer() const { return fRasterizer; }

    /** Set or clear the rasterizer object.

        Pass NULL to clear any previous rasterizer.
        As a convenience, the parameter passed is also returned.
        If a previous rasterizer exists in the paint, its reference count is
        decremented. If rasterizer is not NULL, its reference count is
        incremented.
        @param rasterizer May be NULL. The new rasterizer to be installed in
                          the paint.
        @return           rasterizer
    */
    SkRasterizer* setRasterizer(SkRasterizer* rasterizer);

    /**
     *  Return the paint's SkDrawLooper (if any). Does not affect the looper's
     *  reference count.
     */
    SkDrawLooper* getLooper() const { return fLooper; }

    /**
     *  Set or clear the looper object.
     *

     *  Pass NULL to clear any previous looper.
     *  As a convenience, the parameter passed is also returned.
     *  If a previous looper exists in the paint, its reference count is
     *  decremented. If looper is not NULL, its reference count is
     *  incremented.
     *  @param looper May be NULL. The new looper to be installed in the paint.
     *  @return looper
     */
    SkDrawLooper* setLooper(SkDrawLooper* looper);

    enum Align {
        kLeft_Align,
        kCenter_Align,
        kRight_Align,

        kAlignCount
    };

    /** Return the paint's Align value for drawing text.
        @return the paint's Align value for drawing text.
    */
    Align   getTextAlign() const { return (Align)fTextAlign; }

    /** Set the paint's text alignment.
        @param align set the paint's Align value for drawing text.
    */
    void    setTextAlign(Align align);

    /** Return the paint's text size.
        @return the paint's text size.
    */
    SkScalar getTextSize() const { return fTextSize; }

    /** Set the paint's text size. This value must be > 0
        @param textSize set the paint's text size.
    */
    void setTextSize(SkScalar textSize);

    /** Return the paint's horizontal scale factor for text. The default value
        is 1.0.
        @return the paint's scale factor in X for drawing/measuring text
    */
    SkScalar getTextScaleX() const { return fTextScaleX; }

    /** Set the paint's horizontal scale factor for text. The default value
        is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
        stretch the text narrower.
        @param scaleX   set the paint's scale factor in X for drawing/measuring
                        text.
    */
    void setTextScaleX(SkScalar scaleX);

    /** Return the paint's horizontal skew factor for text. The default value
        is 0.
        @return the paint's skew factor in X for drawing text.
    */
    SkScalar getTextSkewX() const { return fTextSkewX; }

    /** Set the paint's horizontal skew factor for text. The default value
        is 0. For approximating oblique text, use values around -0.25.
        @param skewX set the paint's skew factor in X for drawing text.
    */
    void setTextSkewX(SkScalar skewX);

    /** Describes how to interpret the text parameters that are passed to paint
        methods like measureText() and getTextWidths().
    */
    enum TextEncoding {
        kUTF8_TextEncoding,     //!< the text parameters are UTF8
        kUTF16_TextEncoding,    //!< the text parameters are UTF16
        kGlyphID_TextEncoding   //!< the text parameters are glyph indices
    };

    TextEncoding getTextEncoding() const { return (TextEncoding)fTextEncoding; }

    void setTextEncoding(TextEncoding encoding);

    struct FontMetrics {
        SkScalar    fTop;       //!< The greatest distance above the baseline for any glyph (will be <= 0)
        SkScalar    fAscent;    //!< The recommended distance above the baseline (will be <= 0)
        SkScalar    fDescent;   //!< The recommended distance below the baseline (will be >= 0)
        SkScalar    fBottom;    //!< The greatest distance below the baseline for any glyph (will be >= 0)
        SkScalar    fLeading;   //!< The recommended distance to add between lines of text (will be >= 0)
        SkScalar    fAvgCharWidth;  //!< the average charactor width (>= 0)
        SkScalar    fXMin;      //!< The minimum bounding box x value for all glyphs
        SkScalar    fXMax;      //!< The maximum bounding box x value for all glyphs
        SkScalar    fXHeight;   //!< the height of an 'x' in px, or 0 if no 'x' in face
    };

    /** Return the recommend spacing between lines (which will be
        fDescent - fAscent + fLeading).
        If metrics is not null, return in it the font metrics for the
        typeface/pointsize/etc. currently set in the paint.
        @param metrics      If not null, returns the font metrics for the
                            current typeface/pointsize/etc setting in this
                            paint.
        @param scale        If not 0, return width as if the canvas were scaled
                            by this value
        @param return the recommended spacing between lines
    */
    SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;

    /** Return the recommend line spacing. This will be
        fDescent - fAscent + fLeading
    */
    SkScalar getFontSpacing() const { return this->getFontMetrics(NULL, 0); }

    /** Convert the specified text into glyph IDs, returning the number of
        glyphs ID written. If glyphs is NULL, it is ignore and only the count
        is returned.
    */
    int textToGlyphs(const void* text, size_t byteLength,
                     uint16_t glyphs[]) const;

    /** Return true if all of the specified text has a corresponding non-zero
        glyph ID. If any of the code-points in the text are not supported in
        the typeface (i.e. the glyph ID would be zero), then return false.

        If the text encoding for the paint is kGlyph_TextEncoding, then this
        returns true if all of the specified glyph IDs are non-zero.
     */
    bool containsText(const void* text, size_t byteLength) const;

    /** Convert the glyph array into Unichars. Unconvertable glyphs are mapped
        to zero. Note: this does not look at the text-encoding setting in the
        paint, only at the typeface.
    */
    void glyphsToUnichars(const uint16_t glyphs[], int count,
                          SkUnichar text[]) const;

    /** Return the number of drawable units in the specified text buffer.
        This looks at the current TextEncoding field of the paint. If you also
        want to have the text converted into glyph IDs, call textToGlyphs
        instead.
    */
    int countText(const void* text, size_t byteLength) const {
        return this->textToGlyphs(text, byteLength, NULL);
    }

    /** Return the width of the text.
        @param text         The text to be measured
        @param length       Number of bytes of text to measure
        @param bounds       If not NULL, returns the bounds of the text,
                            relative to (0, 0).
        @param scale        If not 0, return width as if the canvas were scaled
                            by this value
        @return             The advance width of the text
    */
    SkScalar measureText(const void* text, size_t length,
                         SkRect* bounds, SkScalar scale = 0) const;

    /** Return the width of the text.
        @param text         Address of the text
        @param length       Number of bytes of text to measure
        @return The width of the text
    */
    SkScalar measureText(const void* text, size_t length) const {
        return this->measureText(text, length, NULL, 0);
    }

    /** Specify the direction the text buffer should be processed in breakText()
    */
    enum TextBufferDirection {
        /** When measuring text for breakText(), begin at the start of the text
            buffer and proceed forward through the data. This is the default.
        */
        kForward_TextBufferDirection,
        /** When measuring text for breakText(), begin at the end of the text
            buffer and proceed backwards through the data.
        */
        kBackward_TextBufferDirection
    };

    /** Return the width of the text.
        @param text     The text to be measured
        @param length   Number of bytes of text to measure
        @param maxWidth Maximum width. Only the subset of text whose accumulated
                        widths are <= maxWidth are measured.
        @param measuredWidth Optional. If non-null, this returns the actual
                        width of the measured text.
        @param tbd      Optional. The direction the text buffer should be
                        traversed during measuring.
        @return         The number of bytes of text that were measured. Will be
                        <= length.
    */
    size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
                      SkScalar* measuredWidth = NULL,
                      TextBufferDirection tbd = kForward_TextBufferDirection)
                      const;

    /** Return the advance widths for the characters in the string.
        @param text         the text
        @param byteLength   number of bytes to of text
        @param widths       If not null, returns the array of advance widths of
                            the glyphs. If not NULL, must be at least a large
                            as the number of unichars in the specified text.
        @param bounds       If not null, returns the bounds for each of
                            character, relative to (0, 0)
        @return the number of unichars in the specified text.
    */
    int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
                      SkRect bounds[] = NULL) const;

    /** Return the path (outline) for the specified text.
        Note: just like SkCanvas::drawText, this will respect the Align setting
              in the paint.
    */
    void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
                     SkPath* path) const;

#ifdef ANDROID
    const SkGlyph& getUnicharMetrics(SkUnichar);
    const void* findImage(const SkGlyph&);

    uint32_t getGenerationID() const;
#endif

private:
    SkTypeface*     fTypeface;
    SkScalar        fTextSize;
    SkScalar        fTextScaleX;
    SkScalar        fTextSkewX;

    SkPathEffect*   fPathEffect;
    SkShader*       fShader;
    SkXfermode*     fXfermode;
    SkMaskFilter*   fMaskFilter;
    SkColorFilter*  fColorFilter;
    SkRasterizer*   fRasterizer;
    SkDrawLooper*   fLooper;

    SkColor         fColor;
    SkScalar        fWidth;
    SkScalar        fMiterLimit;
    unsigned        fFlags : 12;
    unsigned        fTextAlign : 2;
    unsigned        fCapType : 2;
    unsigned        fJoinType : 2;
    unsigned        fStyle : 2;
    unsigned        fTextEncoding : 2;  // 3 values
    unsigned        fHinting : 2;
#ifdef ANDROID
    uint32_t        fGenerationID;
#endif

    SkDrawCacheProc    getDrawCacheProc() const;
    SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir,
                                           bool needFullMetrics) const;

    SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
                          int* count, SkRect* bounds) const;

    SkGlyphCache*   detachCache(const SkMatrix*) const;

    void descriptorProc(const SkMatrix* deviceMatrix,
                        void (*proc)(const SkDescriptor*, void*),
                        void* context, bool ignoreGamma = false) const;

    const SkRect& computeStrokeFastBounds(const SkRect& orig,
                                          SkRect* storage) const;

    enum {
        kCanonicalTextSizeForPaths = 64
    };
    friend class SkAutoGlyphCache;
    friend class SkCanvas;
    friend class SkDraw;
    friend class SkPDFDevice;
    friend class SkTextToPathIter;
};

///////////////////////////////////////////////////////////////////////////////

#include "SkPathEffect.h"

/** \class SkStrokePathEffect

    SkStrokePathEffect simulates stroking inside a patheffect, allowing the
    caller to have explicit control of when to stroke a path. Typically this is
    used if the caller wants to stroke before another patheffect is applied
    (using SkComposePathEffect or SkSumPathEffect).
*/
class SkStrokePathEffect : public SkPathEffect {
public:
    SkStrokePathEffect(const SkPaint&);
    SkStrokePathEffect(SkScalar width, SkPaint::Style, SkPaint::Join,
                       SkPaint::Cap, SkScalar miterLimit = -1);

    // overrides
    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);

    // overrides for SkFlattenable
    virtual void flatten(SkFlattenableWriteBuffer&);
    virtual Factory getFactory();

    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);

private:
    SkScalar    fWidth, fMiter;
    uint8_t     fStyle, fJoin, fCap;

    SkStrokePathEffect(SkFlattenableReadBuffer&);

    typedef SkPathEffect INHERITED;

    // illegal
    SkStrokePathEffect(const SkStrokePathEffect&);
    SkStrokePathEffect& operator=(const SkStrokePathEffect&);
};

#endif


code:
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPaintFlagsDrawFilter_DEFINED
#define SkPaintFlagsDrawFilter_DEFINED

#include "SkDrawFilter.h"

class SkPaintFlagsDrawFilter : public SkDrawFilter {
public:
    SkPaintFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags);

    // overrides
    virtual void filter(SkPaint*, Type);

private:
    uint32_t    fPrevFlags;     // local cache for filter/restore
    uint16_t    fClearFlags;    // user specified
    uint16_t    fSetFlags;      // user specified
};

#endif


code:
/* libs/graphics/animator/SkPaintParts.h
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef SkPaintParts_DEFINED
#define SkPaintParts_DEFINED

#include "SkDisplayable.h"
#include "SkMemberInfo.h"
#include "SkPaint.h"
#include "SkShader.h"
#include "SkTypeface.h"
#include "SkXfermode.h"

class SkDrawPaint;
class SkDrawMatrix;

class SkPaintPart : public SkDisplayable {
public:
    SkPaintPart();
    virtual bool add() = 0;
    virtual SkDisplayable* getParent() const;
    virtual bool setParent(SkDisplayable* parent);
#ifdef SK_DEBUG
    virtual bool isPaintPart() const { return true; }
#endif
protected:
    SkDrawPaint* fPaint;
};

class SkDrawMaskFilter : public SkPaintPart {
    DECLARE_EMPTY_MEMBER_INFO(MaskFilter);
    virtual SkMaskFilter* getMaskFilter();
protected:
    virtual bool add();
};

class SkDrawPathEffect : public SkPaintPart {
    DECLARE_EMPTY_MEMBER_INFO(PathEffect);
    virtual SkPathEffect* getPathEffect();
protected:
    virtual bool add();
};

class SkDrawShader : public SkPaintPart {
    DECLARE_DRAW_MEMBER_INFO(Shader);
    SkDrawShader();
    virtual SkShader* getShader();
protected:
    virtual bool add();
    void addPostlude(SkShader* shader);
    SkDrawMatrix* matrix;
    int /*SkShader::TileMode*/ tileMode;
};

class SkDrawTypeface  : public SkPaintPart {
    DECLARE_DRAW_MEMBER_INFO(Typeface);
    SkDrawTypeface();
#ifdef SK_DUMP_ENABLED
    virtual void dump(SkAnimateMaker *);
#endif
    SkTypeface* getTypeface() {
        return SkTypeface::CreateFromName(fontName.c_str(), style); }
protected:
    virtual bool add();
    SkString fontName;
    SkTypeface::Style style;
};

#endif // SkPaintParts_DEFINED


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkParse_DEFINED
#define SkParse_DEFINED

#include "SkColor.h"
#include "SkMath.h"

class SkParse {
public:
    static int Count(const char str[]); // number of scalars or int values
    static int Count(const char str[], char separator);
    static const char* FindColor(const char str[], SkColor* value);
    static const char* FindHex(const char str[], uint32_t* value);
    static const char* FindMSec(const char str[], SkMSec* value);
    static const char* FindNamedColor(const char str[], size_t len, SkColor* color);
    static const char* FindS32(const char str[], int32_t* value);
    static const char* FindScalar(const char str[], SkScalar* value);
    static const char* FindScalars(const char str[], SkScalar value[], int count);

    static bool FindBool(const char str[], bool* value);
    // return the index of str in list[], or -1 if not found
    static int  FindList(const char str[], const char list[]);
#ifdef SK_SUPPORT_UNITTEST
    static void TestColor();
    static void UnitTest();
#endif
};

#endif


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkParsePaint_DEFINED
#define SkParsePaint_DEFINED

#include "SkPaint.h"
#include "SkDOM.h"

/** "color"             color
    "opacity"           scalar  [0..1]
    "stroke-width"      scalar  (0...inf)
    "text-size"         scalar  (0..inf)
    "is-stroke"         bool
    "is-antialias"      bool
    "is-lineartext"     bool
*/
void SkPaint_Inflate(SkPaint*, const SkDOM&, const SkDOM::Node*);

#endif


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkParsePath_DEFINED
#define SkParsePath_DEFINED

#include "SkPath.h"

class SkString;

class SkParsePath {
public:
    static bool FromSVGString(const char str[], SkPath*);
    static void ToSVGString(const SkPath&, SkString*);
};

#endif


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPath_DEFINED
#define SkPath_DEFINED

#include "SkMatrix.h"
#include "SkTDArray.h"

#ifdef ANDROID
#define GEN_ID_INC              fGenerationID++
#define GEN_ID_PTR_INC(ptr)     ptr->fGenerationID++
#else
#define GEN_ID_INC
#define GEN_ID_PTR_INC(ptr)
#endif

class SkReader32;
class SkWriter32;
class SkAutoPathBoundsUpdate;
class SkString;

/** \class SkPath

    The SkPath class encapsulates compound (multiple contour) geometric paths
    consisting of straight line segments, quadratic curves, and cubic curves.
*/
class SK_API SkPath {
public:
    SkPath();
    SkPath(const SkPath&);
    ~SkPath();

    SkPath& operator=(const SkPath&);

    friend bool operator==(const SkPath&, const SkPath&);
    friend bool operator!=(const SkPath& a, const SkPath& b) {
        return !(a == b);
    }

    enum FillType {
        /** Specifies that "inside" is computed by a non-zero sum of signed
            edge crossings
        */
        kWinding_FillType,
        /** Specifies that "inside" is computed by an odd number of edge
            crossings
        */
        kEvenOdd_FillType,
        /** Same as Winding, but draws outside of the path, rather than inside
        */
        kInverseWinding_FillType,
        /** Same as EvenOdd, but draws outside of the path, rather than inside
         */
        kInverseEvenOdd_FillType
    };

    /** Return the path's fill type. This is used to define how "inside" is
        computed. The default value is kWinding_FillType.

        @return the path's fill type
    */
    FillType getFillType() const { return (FillType)fFillType; }

    /** Set the path's fill type. This is used to define how "inside" is
        computed. The default value is kWinding_FillType.

        @param ft The new fill type for this path
    */
    void setFillType(FillType ft) {
        fFillType = SkToU8(ft);
        GEN_ID_INC;
    }

    /** Returns true if the filltype is one of the Inverse variants */
    bool isInverseFillType() const { return (fFillType & 2) != 0; }

    /**
     *  Toggle between inverse and normal filltypes. This reverse the return
     *  value of isInverseFillType()
     */
    void toggleInverseFillType() {
        fFillType ^= 2;
        GEN_ID_INC;
     }

    enum Convexity {
        kUnknown_Convexity,
        kConvex_Convexity,
        kConcave_Convexity
    };

    /**
     *  Return the path's convexity, as stored in the path. If it is currently
     *  unknown, and the computeIfUnknown bool is true, then this will first
     *  call ComputeConvexity() and then return that (cached) value.
     */
    Convexity getConvexity() const {
        if (kUnknown_Convexity == fConvexity) {
            fConvexity = (uint8_t)ComputeConvexity(*this);
        }
        return (Convexity)fConvexity;
    }

    /**
     *  Return the currently cached value for convexity, even if that is set to
     *  kUnknown_Convexity. Note: getConvexity() will automatically call
     *  ComputeConvexity and cache its return value if the current setting is
     *  kUnknown.
     */
    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }

    /**
     *  Store a convexity setting in the path. There is no automatic check to
     *  see if this value actually agress with the return value from
     *  ComputeConvexity().
     *
     *  Note: even if this is set to a "known" value, if the path is later
     *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
     *  reset to kUnknown_Convexity.
     */
    void setConvexity(Convexity);

    /**
     *  Compute the convexity of the specified path. This does not look at the
     *  value stored in the path, but computes it directly from the path's data.
     *
     *  This never returns kUnknown_Convexity.
     *
     *  If there is more than one contour, this returns kConcave_Convexity.
     *  If the contour is degenerate (e.g. there are fewer than 3 non-degenerate
     *  segments), then this returns kConvex_Convexity.
     *  The contour is treated as if it were closed, even if there is no kClose
     *  verb.
     */
    static Convexity ComputeConvexity(const SkPath&);

    /**
     *  DEPRECATED: use getConvexity()
     *  Returns true if the path is flagged as being convex. This is not a
     *  confirmed by any analysis, it is just the value set earlier.
     */
    bool isConvex() const {
        return kConvex_Convexity == this->getConvexity();
    }

    /**
     *  DEPRECATED: use setConvexity()
     *  Set the isConvex flag to true or false. Convex paths may draw faster if
     *  this flag is set, though setting this to true on a path that is in fact
     *  not convex can give undefined results when drawn. Paths default to
     *  isConvex == false
     */
    void setIsConvex(bool isConvex) {
        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
    }

    /** Clear any lines and curves from the path, making it empty. This frees up
        internal storage associated with those segments.
        This does NOT change the fill-type setting nor isConvex
    */
    void reset();

    /** Similar to reset(), in that all lines and curves are removed from the
        path. However, any internal storage for those lines/curves is retained,
        making reuse of the path potentially faster.
        This does NOT change the fill-type setting nor isConvex
    */
    void rewind();

    /** Returns true if the path is empty (contains no lines or curves)

        @return true if the path is empty (contains no lines or curves)
    */
    bool isEmpty() const;

    /** Returns true if the path specifies a rectangle. If so, and if rect is
        not null, set rect to the bounds of the path. If the path does not
        specify a rectangle, return false and ignore rect.

        @param rect If not null, returns the bounds of the path if it specifies
                    a rectangle
        @return true if the path specifies a rectangle
    */
    bool isRect(SkRect* rect) const;

    /** Return the number of points in the path
     */
    int countPoints() const {
        return this->getPoints(NULL, 0);
    }

    /** Return the point at the specified index. If the index is out of range
         (i.e. is not 0 <= index < countPoints()) then the returned coordinates
         will be (0,0)
     */
    SkPoint getPoint(int index) const;

    /** Returns the number of points in the path. Up to max points are copied.

        @param points If not null, receives up to max points
        @param max The maximum number of points to copy into points
        @return the actual number of points in the path
    */
    int getPoints(SkPoint points[], int max) const;

    //! Swap contents of this and other. Guaranteed not to throw
    void swap(SkPath& other);

    /** Returns the bounds of the path's points. If the path contains 0 or 1
        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
        Note: this bounds may be larger than the actual shape, since curves
        do not extend as far as their control points.
    */
    const SkRect& getBounds() const {
        if (fBoundsIsDirty) {
            this->computeBounds();
        }
        return fBounds;
    }

    /** Calling this will, if the internal cache of the bounds is out of date,
        update it so that subsequent calls to getBounds will be instanteous.
        This also means that any copies or simple transformations of the path
        will inherit the cached bounds.
     */
    void updateBoundsCache() const {
        // for now, just calling getBounds() is sufficient
        this->getBounds();
    }

    //  Construction methods

    /** Hint to the path to prepare for adding more points. This can allow the
        path to more efficiently grow its storage.

        @param extraPtCount The number of extra points the path should
                            preallocate for.
    */
    void incReserve(unsigned extraPtCount);

    /** Set the beginning of the next contour to the point (x,y).

        @param x    The x-coordinate of the start of a new contour
        @param y    The y-coordinate of the start of a new contour
    */
    void moveTo(SkScalar x, SkScalar y);

    /** Set the beginning of the next contour to the point

        @param p    The start of a new contour
    */
    void moveTo(const SkPoint& p) {
        this->moveTo(p.fX, p.fY);
    }

    /** Set the beginning of the next contour relative to the last point on the
        previous contour. If there is no previous contour, this is treated the
        same as moveTo().

        @param dx   The amount to add to the x-coordinate of the end of the
                    previous contour, to specify the start of a new contour
        @param dy   The amount to add to the y-coordinate of the end of the
                    previous contour, to specify the start of a new contour
    */
    void rMoveTo(SkScalar dx, SkScalar dy);

    /** Add a line from the last point to the specified point (x,y). If no
        moveTo() call has been made for this contour, the first point is
        automatically set to (0,0).

        @param x    The x-coordinate of the end of a line
        @param y    The y-coordinate of the end of a line
    */
    void lineTo(SkScalar x, SkScalar y);

    /** Add a line from the last point to the specified point. If no moveTo()
        call has been made for this contour, the first point is automatically
        set to (0,0).

        @param p    The end of a line
    */
    void lineTo(const SkPoint& p) {
        this->lineTo(p.fX, p.fY);
    }

    /** Same as lineTo, but the coordinates are considered relative to the last
        point on this contour. If there is no previous point, then a moveTo(0,0)
        is inserted automatically.

        @param dx   The amount to add to the x-coordinate of the previous point
                    on this contour, to specify a line
        @param dy   The amount to add to the y-coordinate of the previous point
                    on this contour, to specify a line
    */
    void rLineTo(SkScalar dx, SkScalar dy);

    /** Add a quadratic bezier from the last point, approaching control point
        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
        this contour, the first point is automatically set to (0,0).

        @param x1   The x-coordinate of the control point on a quadratic curve
        @param y1   The y-coordinate of the control point on a quadratic curve
        @param x2   The x-coordinate of the end point on a quadratic curve
        @param y2   The y-coordinate of the end point on a quadratic curve
    */
    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);

    /** Add a quadratic bezier from the last point, approaching control point
        p1, and ending at p2. If no moveTo() call has been made for this
        contour, the first point is automatically set to (0,0).

        @param p1   The control point on a quadratic curve
        @param p2   The end point on a quadratic curve
    */
    void quadTo(const SkPoint& p1, const SkPoint& p2) {
        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
    }

    /** Same as quadTo, but the coordinates are considered relative to the last
        point on this contour. If there is no previous point, then a moveTo(0,0)
        is inserted automatically.

        @param dx1   The amount to add to the x-coordinate of the last point on
                this contour, to specify the control point of a quadratic curve
        @param dy1   The amount to add to the y-coordinate of the last point on
                this contour, to specify the control point of a quadratic curve
        @param dx2   The amount to add to the x-coordinate of the last point on
                     this contour, to specify the end point of a quadratic curve
        @param dy2   The amount to add to the y-coordinate of the last point on
                     this contour, to specify the end point of a quadratic curve
    */
    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);

    /** Add a cubic bezier from the last point, approaching control points
        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
        made for this contour, the first point is automatically set to (0,0).

        @param x1   The x-coordinate of the 1st control point on a cubic curve
        @param y1   The y-coordinate of the 1st control point on a cubic curve
        @param x2   The x-coordinate of the 2nd control point on a cubic curve
        @param y2   The y-coordinate of the 2nd control point on a cubic curve
        @param x3   The x-coordinate of the end point on a cubic curve
        @param y3   The y-coordinate of the end point on a cubic curve
    */
    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                 SkScalar x3, SkScalar y3);

    /** Add a cubic bezier from the last point, approaching control points p1
        and p2, and ending at p3. If no moveTo() call has been made for this
        contour, the first point is automatically set to (0,0).

        @param p1   The 1st control point on a cubic curve
        @param p2   The 2nd control point on a cubic curve
        @param p3   The end point on a cubic curve
    */
    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
    }

    /** Same as cubicTo, but the coordinates are considered relative to the
        current point on this contour. If there is no previous point, then a
        moveTo(0,0) is inserted automatically.

        @param dx1   The amount to add to the x-coordinate of the last point on
                this contour, to specify the 1st control point of a cubic curve
        @param dy1   The amount to add to the y-coordinate of the last point on
                this contour, to specify the 1st control point of a cubic curve
        @param dx2   The amount to add to the x-coordinate of the last point on
                this contour, to specify the 2nd control point of a cubic curve
        @param dy2   The amount to add to the y-coordinate of the last point on
                this contour, to specify the 2nd control point of a cubic curve
        @param dx3   The amount to add to the x-coordinate of the last point on
                     this contour, to specify the end point of a cubic curve
        @param dy3   The amount to add to the y-coordinate of the last point on
                     this contour, to specify the end point of a cubic curve
    */
    void    rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                     SkScalar x3, SkScalar y3);

    /** Append the specified arc to the path as a new contour. If the start of
        the path is different from the path's current last point, then an
        automatic lineTo() is added to connect the current contour to the start
        of the arc. However, if the path is empty, then we call moveTo() with
        the first point of the arc. The sweep angle is treated mod 360.

        @param oval The bounding oval defining the shape and size of the arc
        @param startAngle Starting angle (in degrees) where the arc begins
        @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
                          treated mod 360.
        @param forceMoveTo If true, always begin a new contour with the arc
    */
    void    arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
                  bool forceMoveTo);

    /** Append a line and arc to the current path. This is the same as the
        PostScript call "arct".
    */
    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
               SkScalar radius);

    /** Append a line and arc to the current path. This is the same as the
        PostScript call "arct".
    */
    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
    }

    /** Close the current contour. If the current point is not equal to the
        first point of the contour, a line segment is automatically added.
    */
    void close();

    enum Direction {
        /** clockwise direction for adding closed contours */
        kCW_Direction,
        /** counter-clockwise direction for adding closed contours */
        kCCW_Direction
    };

    /** Add a closed rectangle contour to the path
        @param rect The rectangle to add as a closed contour to the path
        @param dir  The direction to wind the rectangle's contour
    */
    void    addRect(const SkRect& rect, Direction dir = kCW_Direction);

    /** Add a closed rectangle contour to the path

        @param left     The left side of a rectangle to add as a closed contour
                        to the path
        @param top      The top of a rectangle to add as a closed contour to the
                        path
        @param right    The right side of a rectangle to add as a closed contour
                        to the path
        @param bottom   The bottom of a rectangle to add as a closed contour to
                        the path
        @param dir      The direction to wind the rectangle's contour
    */
    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
                 Direction dir = kCW_Direction);

    /** Add a closed oval contour to the path

        @param oval The bounding oval to add as a closed contour to the path
        @param dir  The direction to wind the oval's contour
    */
    void addOval(const SkRect& oval, Direction dir = kCW_Direction);

    /** Add a closed circle contour to the path

        @param x        The x-coordinate of the center of a circle to add as a
                        closed contour to the path
        @param y        The y-coordinate of the center of a circle to add as a
                        closed contour to the path
        @param radius   The radius of a circle to add as a closed contour to the
                        path
        @param dir      The direction to wind the circle's contour
    */
    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
                   Direction dir = kCW_Direction);

    /** Add the specified arc to the path as a new contour.

        @param oval The bounds of oval used to define the size of the arc
        @param startAngle Starting angle (in degrees) where the arc begins
        @param sweepAngle Sweep angle (in degrees) measured clockwise
    */
    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);

    /** Add a closed round-rectangle contour to the path
        @param rect The bounds of a round-rectangle to add as a closed contour
        @param rx   The x-radius of the rounded corners on the round-rectangle
        @param ry   The y-radius of the rounded corners on the round-rectangle
        @param dir  The direction to wind the round-rectangle's contour
    */
    void    addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
                         Direction dir = kCW_Direction);

    /** Add a closed round-rectangle contour to the path. Each corner receives
        two radius values [X, Y]. The corners are ordered top-left, top-right,
        bottom-right, bottom-left.
        @param rect The bounds of a round-rectangle to add as a closed contour
        @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
        @param dir  The direction to wind the round-rectangle's contour
        */
    void addRoundRect(const SkRect& rect, const SkScalar radii[],
                      Direction dir = kCW_Direction);

    /** Add a copy of src to the path, offset by (dx,dy)
        @param src  The path to add as a new contour
        @param dx   The amount to translate the path in X as it is added
        @param dx   The amount to translate the path in Y as it is added
    */
    void    addPath(const SkPath& src, SkScalar dx, SkScalar dy);

    /** Add a copy of src to the path
    */
    void addPath(const SkPath& src) {
        SkMatrix m;
        m.reset();
        this->addPath(src, m);
    }

    /** Add a copy of src to the path, transformed by matrix
        @param src  The path to add as a new contour
    */
    void addPath(const SkPath& src, const SkMatrix& matrix);

    /** Offset the path by (dx,dy), returning true on success

        @param dx   The amount in the X direction to offset the entire path
        @param dy   The amount in the Y direction to offset the entire path
        @param dst  The translated path is written here
    */
    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;

    /** Offset the path by (dx,dy), returning true on success

        @param dx   The amount in the X direction to offset the entire path
        @param dy   The amount in the Y direction to offset the entire path
    */
    void offset(SkScalar dx, SkScalar dy) {
        this->offset(dx, dy, this);
    }

    /** Transform the points in this path by matrix, and write the answer into
        dst.

        @param matrix   The matrix to apply to the path
        @param dst      The transformed path is written here
    */
    void transform(const SkMatrix& matrix, SkPath* dst) const;

    /** Transform the points in this path by matrix

        @param matrix The matrix to apply to the path
    */
    void transform(const SkMatrix& matrix) {
        this->transform(matrix, this);
    }

    /** Return the last point on the path. If no points have been added, (0,0)
        is returned.

        @param lastPt   The last point on the path is returned here
    */
    void getLastPt(SkPoint* lastPt) const;

    /** Set the last point on the path. If no points have been added,
        moveTo(x,y) is automatically called.

        @param x    The new x-coordinate for the last point
        @param y    The new y-coordinate for the last point
    */
    void setLastPt(SkScalar x, SkScalar y);

    /** Set the last point on the path. If no points have been added, moveTo(p)
        is automatically called.

        @param p    The new location for the last point
    */
    void setLastPt(const SkPoint& p) {
        this->setLastPt(p.fX, p.fY);
    }

    enum Verb {
        kMove_Verb,     //!< iter.next returns 1 point
        kLine_Verb,     //!< iter.next returns 2 points
        kQuad_Verb,     //!< iter.next returns 3 points
        kCubic_Verb,    //!< iter.next returns 4 points
        kClose_Verb,    //!< iter.next returns 1 point (the last point)
        kDone_Verb      //!< iter.next returns 0 points
    };

    /** Iterate through all of the segments (lines, quadratics, cubics) of
        each contours in a path.
    */
    class SK_API Iter {
    public:
                Iter();
                Iter(const SkPath&, bool forceClose);

        void setPath(const SkPath&, bool forceClose);

        /** Return the next verb in this iteration of the path. When all
            segments have been visited, return kDone_Verb.

            @param  pts The points representing the current verb and/or segment
            @return The verb for the current segment
        */
        Verb next(SkPoint pts[4]);

        /** If next() returns kLine_Verb, then this query returns true if the
            line was the result of a close() command (i.e. the end point is the
            initial moveto for this contour). If next() returned a different
            verb, this returns an undefined value.

            @return If the last call to next() returned kLine_Verb, return true
                    if it was the result of an explicit close command.
        */
        bool isCloseLine() const { return SkToBool(fCloseLine); }

        /** Returns true if the current contour is closed (has a kClose_Verb)
            @return true if the current contour is closed (has a kClose_Verb)
        */
        bool isClosedContour() const;

    private:
        const SkPoint*  fPts;
        const uint8_t*  fVerbs;
        const uint8_t*  fVerbStop;
        SkPoint         fMoveTo;
        SkPoint         fLastPt;
        SkBool8         fForceClose;
        SkBool8         fNeedClose;
        SkBool8         fNeedMoveTo;
        SkBool8         fCloseLine;

        bool cons_moveTo(SkPoint pts[1]);
        Verb autoClose(SkPoint pts[2]);
    };

    void dump(bool forceClose, const char title[] = NULL) const;
    void dump() const;

    void flatten(SkWriter32&) const;
    void unflatten(SkReader32&);

#ifdef ANDROID
    uint32_t getGenerationID() const;
#endif

    SkDEBUGCODE(void validate() const;)

private:
    SkTDArray<SkPoint>  fPts;
    SkTDArray<uint8_t>  fVerbs;
    mutable SkRect      fBounds;
    mutable uint8_t     fBoundsIsDirty;
    uint8_t             fFillType;
    mutable uint8_t     fConvexity;
#ifdef ANDROID
    uint32_t            fGenerationID;
#endif

    // called, if dirty, by getBounds()
    void computeBounds() const;

    friend class Iter;
    void cons_moveto();

    friend class SkPathStroker;
    /*  Append the first contour of path, ignoring path's initial point. If no
        moveTo() call has been made for this contour, the first point is
        automatically set to (0,0).
    */
    void pathTo(const SkPath& path);

    /*  Append, in reverse order, the first contour of path, ignoring path's
        last point. If no moveTo() call has been made for this contour, the
        first point is automatically set to (0,0).
    */
    void reversePathTo(const SkPath&);

    friend const SkPoint* sk_get_path_points(const SkPath&, int index);
    friend class SkAutoPathBoundsUpdate;
};

#endif


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPathEffect_DEFINED
#define SkPathEffect_DEFINED

#include "SkFlattenable.h"

class SkPath;

/** \class SkPathEffect

    SkPathEffect is the base class for objects in the SkPaint that affect
    the geometry of a drawing primitive before it is transformed by the
    canvas' matrix and drawn.

    Dashing is implemented as a subclass of SkPathEffect.
*/
class SK_API SkPathEffect : public SkFlattenable {
public:
    SkPathEffect() {}

    /** Given a src path and a width value, return true if the patheffect
        has produced a new path (dst) and a new width value. If false is returned,
        ignore dst and width.
        On input, width >= 0 means the src should be stroked
        On output, width >= 0 means the dst should be stroked
    */
    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) = 0;

private:
    // illegal
    SkPathEffect(const SkPathEffect&);
    SkPathEffect& operator=(const SkPathEffect&);
};

/** \class SkPairPathEffect

    Common baseclass for Compose and Sum. This subclass manages two pathEffects,
    including flattening them. It does nothing in filterPath, and is only useful
    for managing the lifetimes of its two arguments.
*/
class SkPairPathEffect : public SkPathEffect {
public:
    SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1);
    virtual ~SkPairPathEffect();

protected:
    SkPairPathEffect(SkFlattenableReadBuffer&);
    virtual void flatten(SkFlattenableWriteBuffer&);
    // these are visible to our subclasses
    SkPathEffect* fPE0, *fPE1;

private:
    typedef SkPathEffect INHERITED;
};

/** \class SkComposePathEffect

    This subclass of SkPathEffect composes its two arguments, to create
    a compound pathEffect.
*/
class SkComposePathEffect : public SkPairPathEffect {
public:
    /** Construct a pathEffect whose effect is to apply first the inner pathEffect
        and the the outer pathEffect (e.g. outer(inner(path)))
        The reference counts for outer and inner are both incremented in the constructor,
        and decremented in the destructor.
    */
    SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner)
        : INHERITED(outer, inner) {}

    // overrides

    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);

    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
        return SkNEW_ARGS(SkComposePathEffect, (buffer));
    }

protected:
    virtual Factory getFactory() { return CreateProc; }

private:
    SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}

    // illegal
    SkComposePathEffect(const SkComposePathEffect&);
    SkComposePathEffect& operator=(const SkComposePathEffect&);

    typedef SkPairPathEffect INHERITED;
};

/** \class SkSumPathEffect

    This subclass of SkPathEffect applies two pathEffects, one after the other.
    Its filterPath() returns true if either of the effects succeeded.
*/
class SkSumPathEffect : public SkPairPathEffect {
public:
    /** Construct a pathEffect whose effect is to apply two effects, in sequence.
        (e.g. first(path) + second(path))
        The reference counts for first and second are both incremented in the constructor,
        and decremented in the destructor.
    */
    SkSumPathEffect(SkPathEffect* first, SkPathEffect* second)
        : INHERITED(first, second) {}

    // overrides
    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);

    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)  {
        return SkNEW_ARGS(SkSumPathEffect, (buffer));
    }

protected:
    virtual Factory getFactory() { return CreateProc; }

private:
    SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}

    // illegal
    SkSumPathEffect(const SkSumPathEffect&);
    SkSumPathEffect& operator=(const SkSumPathEffect&);

    typedef SkPairPathEffect INHERITED;
};

#endif


code:
#ifndef SkPathHeap_DEFINED
#define SkPathHeap_DEFINED

#include "SkRefCnt.h"
#include "SkChunkAlloc.h"
#include "SkTDArray.h"

class SkPath;
class SkFlattenableReadBuffer;
class SkFlattenableWriteBuffer;

class SkPathHeap : public SkRefCnt {
public:
            SkPathHeap();
            SkPathHeap(SkFlattenableReadBuffer&);
    virtual ~SkPathHeap();

    /** Copy the path into the heap, and return the new total number of paths.
        Thus, the returned value will be index+1, where index is the index of
        this newly added (copied) path.
     */
    int append(const SkPath&);

    // called during picture-playback
    int count() const { return fPaths.count(); }
    const SkPath& operator[](int index) const {
        return *fPaths[index];
    }

    void flatten(SkFlattenableWriteBuffer&) const;

private:
    // we store the paths in the heap (placement new)
    SkChunkAlloc        fHeap;
    // we just store ptrs into fHeap here
    SkTDArray<SkPath*>  fPaths;
};

#endif


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPathMeasure_DEFINED
#define SkPathMeasure_DEFINED

#include "SkPath.h"
#include "SkTDArray.h"

class SkPathMeasure : SkNoncopyable {
public:
    SkPathMeasure();
    /** Initialize the pathmeasure with the specified path. The path must remain valid
        for the lifetime of the measure object, or until setPath() is called with
        a different path (or null), since the measure object keeps a pointer to the
        path object (does not copy its data).
    */
    SkPathMeasure(const SkPath& path, bool forceClosed);
    ~SkPathMeasure();

    /** Reset the pathmeasure with the specified path. The path must remain valid
        for the lifetime of the measure object, or until setPath() is called with
        a different path (or null), since the measure object keeps a pointer to the
        path object (does not copy its data).
    */
    void    setPath(const SkPath*, bool forceClosed);

    /** Return the total length of the current contour, or 0 if no path
        is associated (e.g. resetPath(null))
    */
    SkScalar getLength();

    /** Pins distance to 0 <= distance <= getLength(), and then computes
        the corresponding position and tangent.
        Returns false if there is no path, or a zero-length path was specified, in which case
        position and tangent are unchanged.
    */
    bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent);

    enum MatrixFlags {
        kGetPosition_MatrixFlag     = 0x01,
        kGetTangent_MatrixFlag      = 0x02,
        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
    };
    /** Pins distance to 0 <= distance <= getLength(), and then computes
        the corresponding matrix (by calling getPosTan).
        Returns false if there is no path, or a zero-length path was specified, in which case
        matrix is unchanged.
    */
    bool getMatrix(SkScalar distance, SkMatrix* matrix, MatrixFlags flags = kGetPosAndTan_MatrixFlag);
    /** Given a start and stop distance, return in dst the intervening segment(s).
        If the segment is zero-length, return false, else return true.
        startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD
        then return false (and leave dst untouched).
        Begin the segment with a moveTo if startWithMoveTo is true
    */
    bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);

    /** Return true if the current contour is closed()
    */
    bool isClosed();

    /** Move to the next contour in the path. Return true if one exists, or false if
        we're done with the path.
    */
    bool nextContour();

#ifdef SK_DEBUG
    void    dump();
#endif

private:
    SkPath::Iter    fIter;
    const SkPath*   fPath;
    SkScalar        fLength;            // relative to the current contour
    int             fFirstPtIndex;      // relative to the current contour
    bool            fIsClosed;          // relative to the current contour
    bool            fForceClosed;

    struct Segment {
        SkScalar    fDistance;  // total distance up to this point
        unsigned    fPtIndex : 15;
        unsigned    fTValue : 15;
        unsigned    fType : 2;

        SkScalar getScalarT() const;
    };
    SkTDArray<Segment>  fSegments;

    static const Segment* NextSegment(const Segment*);

    void     buildSegments();
    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
                                int mint, int maxt, int ptIndex);
    SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
                                int mint, int maxt, int ptIndex);
    const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
};

#endif


code:
/* libs/graphics/animator/SkPathParts.h
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef SkPathParts_DEFINED
#define SkPathParts_DEFINED

#include "SkDisplayable.h"
#include "SkMemberInfo.h"
#include "SkPath.h"

class SkDrawPath;
class SkDrawMatrix;

class SkPathPart : public SkDisplayable {
public:
    SkPathPart();
    virtual bool add() = 0;
    virtual void dirty();
    virtual SkDisplayable* getParent() const;
    virtual bool setParent(SkDisplayable* parent);
#ifdef SK_DEBUG
    virtual bool isPathPart() const { return true; }
#endif
protected:
    SkDrawPath* fPath;
};

class SkMoveTo : public SkPathPart {
    DECLARE_MEMBER_INFO(MoveTo);
    SkMoveTo();
    virtual bool add();
protected:
    SkScalar x;
    SkScalar y;
};

class SkRMoveTo : public SkMoveTo {
    DECLARE_MEMBER_INFO(RMoveTo);
    virtual bool add();
private:
    typedef SkMoveTo INHERITED;
};

class SkLineTo : public SkPathPart {
    DECLARE_MEMBER_INFO(LineTo);
    SkLineTo();
    virtual bool add();
protected:
    SkScalar x;
    SkScalar y;
};

class SkRLineTo : public SkLineTo {
    DECLARE_MEMBER_INFO(RLineTo);
    virtual bool add();
private:
    typedef SkLineTo INHERITED;
};

class SkQuadTo : public SkPathPart {
    DECLARE_MEMBER_INFO(QuadTo);
    SkQuadTo();
    virtual bool add();
protected:
    SkScalar x1;
    SkScalar y1;
    SkScalar x2;
    SkScalar y2;
};

class SkRQuadTo : public SkQuadTo {
    DECLARE_MEMBER_INFO(RQuadTo);
    virtual bool add();
private:
    typedef SkQuadTo INHERITED;
};

class SkCubicTo : public SkPathPart {
    DECLARE_MEMBER_INFO(CubicTo);
    SkCubicTo();
    virtual bool add();
protected:
    SkScalar x1;
    SkScalar y1;
    SkScalar x2;
    SkScalar y2;
    SkScalar x3;
    SkScalar y3;
};

class SkRCubicTo : public SkCubicTo {
    DECLARE_MEMBER_INFO(RCubicTo);
    virtual bool add();
private:
    typedef SkCubicTo INHERITED;
};

class SkClose : public SkPathPart {
    DECLARE_EMPTY_MEMBER_INFO(Close);
    virtual bool add();
};

class SkAddGeom : public SkPathPart {
    DECLARE_PRIVATE_MEMBER_INFO(AddGeom);
    SkAddGeom();
protected:
    int /*SkPath::Direction*/ direction;
};

class SkAddRect : public SkAddGeom {
    DECLARE_MEMBER_INFO(AddRect);
    SkAddRect();
    virtual bool add();
protected:
    SkRect fRect;
private:
    typedef SkAddGeom INHERITED;
};

class SkAddOval : public SkAddRect {
    DECLARE_MEMBER_INFO(AddOval);
    virtual bool add();
private:
    typedef SkAddRect INHERITED;
};

class SkAddCircle : public SkAddGeom {
    DECLARE_MEMBER_INFO(AddCircle);
    SkAddCircle();
    virtual bool add();
private:
    SkScalar radius;
    SkScalar x;
    SkScalar y;
    typedef SkAddGeom INHERITED;
};

class SkAddRoundRect : public SkAddRect {
    DECLARE_MEMBER_INFO(AddRoundRect);
    SkAddRoundRect();
    virtual bool add();
private:
    SkScalar rx;
    SkScalar ry;
    typedef SkAddRect INHERITED;
};

class SkAddPath : public SkPathPart {
    DECLARE_MEMBER_INFO(AddPath);
    SkAddPath();
    virtual bool add();
private:
    typedef SkPathPart INHERITED;
    SkDrawMatrix* matrix;
    SkDrawPath* path;
};

#endif // SkPathParts_DEFINED


code:
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPerspIter_DEFINED
#define SkPerspIter_DEFINED

#include "SkMatrix.h"

class SkPerspIter {
public:
    /** Iterate a line through the matrix [x,y] ... [x+count-1, y].
        @param m    The matrix we will be iterating a line through
        @param x    The initial X coordinate to be mapped through the matrix
        @param y    The initial Y coordinate to be mapped through the matrix
        @param count The number of points (x,y) (x+1,y) (x+2,y) ... we will eventually map
    */
    SkPerspIter(const SkMatrix& m, SkScalar x, SkScalar y, int count);

    /** Return the buffer of [x,y] fixed point values we will be filling.
        This always returns the same value, so it can be saved across calls to
        next().
    */
    const SkFixed* getXY() const { return fStorage; }

    /** Return the number of [x,y] pairs that have been filled in the getXY() buffer.
        When this returns 0, the iterator is finished.
    */
    int next();

private:
    enum {
        kShift  = 4,
        kCount  = (1 << kShift)
    };
    const SkMatrix& fMatrix;
    SkFixed         fStorage[kCount * 2];
    SkFixed         fX, fY;
    SkScalar        fSX, fSY;
    int             fCount;
};

#endif


code:
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkPicture_DEFINED
#define SkPicture_DEFINED

#include "SkRefCnt.h"

class SkCanvas;
class SkPicturePlayback;
class SkPictureRecord;
class SkStream;
class SkWStream;

/** \class SkPicture

    The SkPicture class records the drawing commands made to a canvas, to
    be played back at a later time.
*/
class SK_API SkPicture : public SkRefCnt {
public:
    /** The constructor prepares the picture to record.
        @param width the width of the virtual device the picture records.
        @param height the height of the virtual device the picture records.
    */
    SkPicture();
    /** Make a copy of the contents of src. If src records more drawing after
        this call, those elements will not appear in this picture.
    */
    SkPicture(const SkPicture& src);
    explicit SkPicture(SkStream*);
    virtual ~SkPicture();

    /**
     *  Swap the contents of the two pictures. Guaranteed to succeed.
     */
    void swap(SkPicture& other);

    enum RecordingFlags {
        /*  This flag specifies that when clipPath() is called, the path will
            be faithfully recorded, but the recording canvas' current clip will
            only see the path's bounds. This speeds up the recording process
            without compromising the fidelity of the playback. The only side-
            effect for recording is that calling getTotalClip() or related
            clip-query calls will reflect the path's bounds, not the actual
            path.
         */
        kUsePathBoundsForClip_RecordingFlag = 0x01
    };

    /** Returns the canvas that records the drawing commands.
        @param width the base width for the picture, as if the recording
                     canvas' bitmap had this width.
        @param height the base width for the picture, as if the recording
                     canvas' bitmap had this height.
        @param recordFlags optional flags that control recording.
        @return the picture canvas.
    */
    SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);

    /** Returns the recording canvas if one is active, or NULL if recording is
        not active. This does not alter the refcnt on the canvas (if present).
    */
    SkCanvas* getRecordingCanvas() const;
    /** Signal that the caller is done recording. This invalidates the canvas
        returned by beginRecording/getRecordingCanvas, and prepares the picture
        for drawing. Note: this happens implicitly the first time the picture
        is drawn.
    */
    void endRecording();

    /** Replays the drawing commands on the specified canvas. This internally
        calls endRecording() if that has not already been called.
        @param surface the canvas receiving the drawing commands.
    */
    void draw(SkCanvas* surface);

    /** Return the width of the picture's recording canvas. This
        value reflects what was passed to setSize(), and does not necessarily
        reflect the bounds of what has been recorded into the picture.
        @return the width of the picture's recording canvas
    */
    int width() const { return fWidth; }

    /** Return the height of the picture's recording canvas. This
        value reflects what was passed to setSize(), and does not necessarily
        reflect the bounds of what has been recorded into the picture.
        @return the height of the picture's recording canvas
    */
    int height() const { return fHeight; }

    void serialize(SkWStream*) const;

    /** Signals that the caller is prematurely done replaying the drawing
        commands. This can be called from a canvas virtual while the picture
        is drawing. Has no effect if the picture is not drawing.
    */
    void abortPlayback();

private:
    int fWidth, fHeight;
    SkPictureRecord* fRecord;
    SkPicturePlayback* fPlayback;

    friend class SkFlatPicture;
    friend class SkPicturePlayback;
};

class SkAutoPictureRecord : SkNoncopyable {
public:
    SkAutoPictureRecord(SkPicture* pict, int width, int height,
                        uint32_t recordingFlags = 0) {
        fPicture = pict;
        fCanvas = pict->beginRecording(width, height, recordingFlags);
    }
    ~SkAutoPictureRecord() {
        fPicture->endRecording();
    }

    /** Return the canvas to draw into for recording into the picture.
    */
    SkCanvas* getRecordingCanvas() const { return fCanvas; }

private:
    SkPicture*  fPicture;
    SkCanvas*   fCanvas;
};

#endif