code:
#ifndef SkScript2_DEFINED
#define SkScript2_DEFINED

#include "SkOperand2.h"
#include "SkStream.h"
#include "SkTDArray.h"
#include "SkTDArray_Experimental.h"
#include "SkTDict.h"
#include "SkTDStack.h"

typedef SkLongArray(SkString*) SkTDStringArray;

class SkAnimateMaker;
class SkScriptCallBack;

class SkScriptEngine2 {
public:
	enum Error {
		kNoError,
		kArrayIndexOutOfBounds,
		kCouldNotFindReferencedID,
		kFunctionCallFailed,
		kMemberOpFailed,
		kPropertyOpFailed
	};

	enum Attrs {
		kConstant,
		kVariable
	};

	SkScriptEngine2(SkOperand2::OpType returnType);
	~SkScriptEngine2();
	bool convertTo(SkOperand2::OpType , SkScriptValue2* );
	bool evaluateScript(const char** script, SkScriptValue2* value);
	void forget(SkOpArray* array);
	Error getError() { return fError; }
	SkOperand2::OpType getReturnType() { return fReturnType; }
	void track(SkOpArray* array) {
		SkASSERT(fTrackArray.find(array) < 0);
		*fTrackArray.append() = array; }
	void track(SkString* string) {
		SkASSERT(fTrackString.find(string) < 0);
		*fTrackString.append() = string;
	}
	static bool ConvertTo(SkScriptEngine2* , SkOperand2::OpType toType, SkScriptValue2* value);
	static SkScalar IntToScalar(int32_t );
	static bool ValueToString(const SkScriptValue2& value, SkString* string);

	enum Op {		// used by tokenizer attribute table
		kUnassigned,
		kAdd,
		kBitAnd,
		kBitNot,
		kBitOr,
		kDivide,
		kEqual,
		kFlipOps,
		kGreaterEqual,
		kLogicalAnd,
		kLogicalNot,
		kLogicalOr,
		kMinus,
		kModulo,
		kMultiply,
		kShiftLeft,
		kShiftRight,	// signed
		kSubtract,
		kXor,
// following not in attribute table
		kArrayOp,
		kElse,
		kIf,
		kParen,
		kLastLogicalOp,
		kArtificialOp = 0x20
	};

	enum TypeOp {	// generated by tokenizer
		kNop, // should never get generated
		kAccumulatorPop,
		kAccumulatorPush,
		kAddInt,
		kAddScalar,
		kAddString,	// string concat
		kArrayIndex,
		kArrayParam,
		kArrayToken,
		kBitAndInt,
		kBitNotInt,
		kBitOrInt,
		kBoxToken,
		kCallback,
		kDivideInt,
		kDivideScalar,
		kDotOperator,
		kElseOp,
		kEnd,
		kEqualInt,
		kEqualScalar,
		kEqualString,
		kFunctionCall,
		kFlipOpsOp,
		kFunctionToken,
		kGreaterEqualInt,
		kGreaterEqualScalar,
		kGreaterEqualString,
		kIfOp,
		kIntToScalar,
		kIntToScalar2,
		kIntToString,
		kIntToString2,
		kIntegerAccumulator,
		kIntegerOperand,
		kLogicalAndInt,
		kLogicalNotInt,
		kLogicalOrInt,
		kMemberOp,
		kMinusInt,
		kMinusScalar,
		kModuloInt,
		kModuloScalar,
		kMultiplyInt,
		kMultiplyScalar,
		kPropertyOp,
		kScalarAccumulator,
		kScalarOperand,
		kScalarToInt,
		kScalarToInt2,
		kScalarToString,
		kScalarToString2,
		kShiftLeftInt,
		kShiftRightInt,	// signed
		kStringAccumulator,
		kStringOperand,
		kStringToInt,
		kStringToScalar,
		kStringToScalar2,
		kStringTrack,
		kSubtractInt,
		kSubtractScalar,
		kToBool,
		kUnboxToken,
		kUnboxToken2,
		kXorInt,
		kLastTypeOp
	};

	enum OpBias {
		kNoBias,
		kTowardsNumber = 0,
		kTowardsString
	};

protected:

	enum BraceStyle {
	//	kStructBrace,
		kArrayBrace,
		kFunctionBrace
	};

	enum AddTokenRegister {
		kAccumulator,
		kOperand
	};

	enum ResultIsBoolean {
		kResultIsNotBoolean,
		kResultIsBoolean
	};

	struct OperatorAttributes {
		unsigned int fLeftType : 3;	// SkOpType union, but only lower values
		unsigned int fRightType : 3;	 // SkOpType union, but only lower values
		OpBias fBias : 1;
		ResultIsBoolean fResultIsBoolean : 1;
	};

	struct Branch {
		Branch() {
		}

		Branch(Op op, int depth, unsigned offset) : fOffset(offset), fOpStackDepth(depth), fOperator(op),
			fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
		}

		enum Primed {
			kIsNotPrimed,
			kIsPrimed
		};

		enum Done {
			kIsNotDone,
			kIsDone,
		};

		unsigned fOffset : 16; // offset in generated stream where branch needs to go
		int fOpStackDepth : 7; // depth when operator was found
		Op fOperator : 6; // operand which generated branch
		mutable Primed fPrimed : 1;	// mark when next instruction generates branch
		Done fDone : 1;	// mark when branch is complete
		void prime() { fPrimed = kIsPrimed; }
		void resolve(SkDynamicMemoryWStream* , size_t offset);
	};

	static const OperatorAttributes gOpAttributes[];
	static const signed char gPrecedence[];
	static const TypeOp gTokens[];
	void addToken(TypeOp );
	void addTokenConst(SkScriptValue2* , AddTokenRegister , SkOperand2::OpType , TypeOp );
	void addTokenInt(int );
	void addTokenScalar(SkScalar );
	void addTokenString(const SkString& );
	void addTokenValue(const SkScriptValue2& , AddTokenRegister );
	int arithmeticOp(char ch, char nextChar, bool lastPush);
	bool convertParams(SkTDArray<SkScriptValue2>* ,
		const SkOperand2::OpType* paramTypes, int paramTypeCount);
	void convertToString(SkOperand2* operand, SkOperand2::OpType type) {
		SkScriptValue2 scriptValue;
		scriptValue.fOperand = *operand;
		scriptValue.fType = type;
		convertTo(SkOperand2::kString, &scriptValue);
		*operand = scriptValue.fOperand;
	}
	bool evaluateDot(const char*& script);
	bool evaluateDotParam(const char*& script, const char* field, size_t fieldLength);
	bool functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params);
	size_t getTokenOffset();
	SkOperand2::OpType getUnboxType(SkOperand2 scriptValue);
	bool handleArrayIndexer(const char** scriptPtr);
	bool handleFunction(const char** scriptPtr);
	bool handleMember(const char* field, size_t len, void* object);
	bool handleMemberFunction(const char* field, size_t len, void* object,
		SkTDArray<SkScriptValue2>* params);
	bool handleProperty();
	bool handleUnbox(SkScriptValue2* scriptValue);
	bool innerScript(const char** scriptPtr, SkScriptValue2* value);
	int logicalOp(char ch, char nextChar);
	void processLogicalOp(Op op);
	bool processOp();
	void resolveBranch(Branch& );
//	void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; }
	SkDynamicMemoryWStream fStream;
	SkDynamicMemoryWStream* fActiveStream;
	SkTDStack<BraceStyle> fBraceStack;		// curly, square, function paren
	SkTDStack<Branch> fBranchStack;  // logical operators, slot to store forward branch
	SkLongArray(SkScriptCallBack*) fCallBackArray;
	SkTDStack<Op> fOpStack;
	SkTDStack<SkScriptValue2> fValueStack;
//	SkAnimateMaker* fMaker;
	SkLongArray(SkOpArray*) fTrackArray;
	SkTDStringArray fTrackString;
	const char* fToken; // one-deep stack
	size_t fTokenLength;
	SkOperand2::OpType fReturnType;
	Error fError;
	SkOperand2::OpType fAccumulatorType;	// tracking for code generation
	SkBool fBranchPopAllowed;
	SkBool fConstExpression;
	SkBool fOperandInUse;
private:
#ifdef SK_DEBUG
public:
	void decompile(const unsigned char* , size_t );
	static void UnitTest();
	static void ValidateDecompileTable();
#endif
};

#ifdef SK_DEBUG

struct SkScriptNAnswer2 {
	const char* fScript;
	SkOperand2::OpType fType;
	int32_t fIntAnswer;
	SkScalar fScalarAnswer;
	const char* fStringAnswer;
};

#endif

#endif // SkScript2_DEFINED


code:
#ifndef SkScriptCallBack_DEFINED
#define SkScriptCallBack_DEFINED

#include "SkOperand2.h"
#include "SkTDArray_Experimental.h"

class SkScriptCallBack {
public:
	enum Type {
		kBox,
		kFunction,
		kMember,
		kMemberFunction,
		kProperty,
		kUnbox
	};

	virtual bool getReference(const char* , size_t len, SkScriptValue2* result) {  return false; }
	virtual SkOperand2::OpType getReturnType(size_t ref, SkOperand2*) {
		return SkOperand2::kS32; }
	virtual Type getType() const = 0;
};

class SkScriptCallBackConvert : public SkScriptCallBack {
public:
	virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) = 0;
};

class SkScriptCallBackFunction : public SkScriptCallBack {
public:
	virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) = 0;
	virtual Type getType() const { return kFunction; }
	virtual bool invoke(size_t ref, SkOpArray* params, SkOperand2* value) = 0;
};

class SkScriptCallBackMember: public SkScriptCallBack {
public:
	bool getMemberReference(const char* , size_t len, void* object, SkScriptValue2* ref);
	virtual Type getType() const { return kMember; }
	virtual bool invoke(size_t ref, void* object, SkOperand2* value) = 0;
};

class SkScriptCallBackMemberFunction : public SkScriptCallBack {
public:
	bool getMemberReference(const char* , size_t len, void* object, SkScriptValue2* ref);
	virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) = 0;
	virtual Type getType() const { return kMemberFunction; }
	virtual bool invoke(size_t ref, void* object, SkOpArray* params, SkOperand2* value) = 0;
};

class SkScriptCallBackProperty : public SkScriptCallBack {
public:
	virtual bool getConstValue(const char* name, size_t len, SkOperand2* value) { return false; }
	virtual bool getResult(size_t ref, SkOperand2* answer) { return false; }
	virtual Type getType() const { return kProperty; }
};

#endif // SkScriptCallBack_DEFINED

license: mit


code:
#ifndef SkScriptRuntime_DEFINED
#define SkScriptRuntime_DEFINED

#include "SkOperand2.h"
#include "SkTDArray_Experimental.h"
#include "SkTDStack.h"

class SkScriptCallBack;

typedef SkLongArray(SkString*) SkTDStringArray;
typedef SkLongArray(SkScriptCallBack*) SkTDScriptCallBackArray;

class SkScriptRuntime {
public:
	enum SkError {
		kNoError,
		kArrayIndexOutOfBounds,
		kCouldNotFindReferencedID,
		kFunctionCallFailed,
		kMemberOpFailed,
		kPropertyOpFailed
	};

	SkScriptRuntime(SkTDScriptCallBackArray& callBackArray) : fCallBackArray(callBackArray)
		{  }
	~SkScriptRuntime();
	bool executeTokens(unsigned char* opCode);
	bool getResult(SkOperand2* result);
	void untrack(SkOpArray* array);
	void untrack(SkString* string);
private:
	void track(SkOpArray* array);
	void track(SkString* string);
	SkTDScriptCallBackArray& fCallBackArray;
	SkError fError;
	SkTDStack<SkOperand2> fRunStack;
	SkLongArray(SkOpArray*) fTrackArray;
	SkTDStringArray fTrackString;
	// illegal
	SkScriptRuntime& operator=(const SkScriptRuntime&);
};

#endif // SkScriptRuntime_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 SkScrollBarView_DEFINED
#define SkScrollBarView_DEFINED

#include "SkView.h"
#include "SkWidgetViews.h"
#include "SkAnimator.h"

class SkScrollBarView : public SkWidgetView {
public:
    SkScrollBarView();

    unsigned getStart() const { return fStartPoint; }
    unsigned getShown() const { return fShownLength; }
    unsigned getTotal() const { return fTotalLength; }

    void setStart(unsigned start);
    void setShown(unsigned shown);
    void setTotal(unsigned total);

protected:
    //overrides
    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
    virtual void onSizeChange();
    virtual void onDraw(SkCanvas* canvas);
    virtual bool onEvent(const SkEvent& evt);

private:
    SkAnimator  fAnim;
    unsigned    fTotalLength, fStartPoint, fShownLength;

    void adjust();

    typedef SkWidgetView INHERITED;
};
#endif


code:
#ifndef SkSfntUtils_DEFINED
#define SkSfntUtils_DEFINED

#include "SkFontHost.h"

struct SkSfntTable_head {
    SkFixed     fVersion;
    SkFixed     fRevision;
    uint32_t    fCheckSumAdjustment;
    uint32_t    fMagicNumber;
    uint16_t    fFlags;
    uint16_t    fUnitsPerEm;
    Sk64        fDateCreated;
    Sk64        fDateModified;
    int16_t     fXMin;
    int16_t     fYMin;
    int16_t     fXMax;
    int16_t     fYMax;
    uint16_t    fMacStyle;
    uint16_t    fLowestPPEM;
    int16_t     fFontDirectionHint;
    int16_t     fIndexToLocFormat;
    int16_t     fGlyphDataFormat;
};

struct SkSfntTable_maxp {
    SkFixed     fVersion;
    uint16_t    fNumGlyphs;
    uint16_t    fMaxPoints;
    uint16_t    fMaxContours;
    uint16_t    fMaxComponentPoints;
    uint16_t    fMaxComponentContours;
    uint16_t    fMaxZones;
    uint16_t    fMaxTwilightPoints;
    uint16_t    fMaxStorage;
    uint16_t    fMaxFunctionDefs;
    uint16_t    fMaxInstructionDefs;
    uint16_t    fMaxStackElements;
    uint16_t    fMaxSizeOfInstructions;
    uint16_t    fMaxComponentElements;
    uint16_t    fMaxComponentDepth;
};

class SkSfntUtils {
public:
    static bool ReadTable_head(SkFontID, SkSfntTable_head*);
    static bool ReadTable_maxp(SkFontID, SkSfntTable_maxp*);
};

#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 SkShader_DEFINED
#define SkShader_DEFINED

#include "SkBitmap.h"
#include "SkFlattenable.h"
#include "SkMask.h"
#include "SkMatrix.h"
#include "SkPaint.h"

class SkPath;

/** \class SkShader
 *
 *  SkShader is the based class for objects that return horizontal spans of
 *  colors during drawing. A subclass of SkShader is installed in a SkPaint
 *  calling paint.setShader(shader). After that any object (other than a bitmap)
 *  that is drawn with that paint will get its color(s) from the shader.
 */
class SK_API SkShader : public SkFlattenable {
public:
            SkShader();
    virtual ~SkShader();

    /**
     *  Return true if the shader has a non-identity local matrix.
     *  @param localM   Optional: If not null, return the shader's local matrix
     *  @return true if the shader has a non-identity local matrix.
     */
    bool getLocalMatrix(SkMatrix* localM) const;

    /**
     *  Set the shader's local matrix.
     *  @param localM   The shader's new local matrix.
     */
    void setLocalMatrix(const SkMatrix& localM);

    /**
     *  Reset the shader's local matrix to identity.
     */
    void resetLocalMatrix();

    enum TileMode {
        kClamp_TileMode,    //!< replicate the edge color if the shader draws outside of its original bounds
        kRepeat_TileMode,   //!< repeat the shader's image horizontally and vertically
        kMirror_TileMode,   //!< repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam

        kTileModeCount
    };

    // override these in your subclass

    enum Flags {
        //!< set if all of the colors will be opaque
        kOpaqueAlpha_Flag  = 0x01,

        //! set if this shader's shadeSpan16() method can be called
        kHasSpan16_Flag = 0x02,

        /** Set this bit if the shader's native data type is instrinsically 16
            bit, meaning that calling the 32bit shadeSpan() entry point will
            mean the the impl has to up-sample 16bit data into 32bit. Used as a
            a means of clearing a dither request if the it will have no effect
        */
        kIntrinsicly16_Flag = 0x04,

        /** set (after setContext) if the spans only vary in X (const in Y).
            e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
            that varies from left-to-right. This flag specifies this for
            shadeSpan().
         */
        kConstInY32_Flag = 0x08,

        /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
            which may not always be the case, since shadeSpan16 may be
            predithered, which would mean it was not const in Y, even though
            the 32bit shadeSpan() would be const.
         */
        kConstInY16_Flag = 0x10
    };

    /**
     *  Called sometimes before drawing with this shader. Return the type of
     *  alpha your shader will return. The default implementation returns 0.
     *  Your subclass should override if it can (even sometimes) report a
     *  non-zero value, since that will enable various blitters to perform
     *  faster.
     */
    virtual uint32_t getFlags() { return 0; }

    /**
     *  Return the alpha associated with the data returned by shadeSpan16(). If
     *  kHasSpan16_Flag is not set, this value is meaningless.
     */
    virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }

    /**
     *  Called once before drawing, with the current paint and device matrix.
     *  Return true if your shader supports these parameters, or false if not.
     *  If false is returned, nothing will be drawn.
     */
    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
                            const SkMatrix& matrix);

    /**
     *  Called for each span of the object being drawn. Your subclass should
     *  set the appropriate colors (with premultiplied alpha) that correspond
     *  to the specified device coordinates.
     */
    virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;

    /**
     *  Called only for 16bit devices when getFlags() returns
     *  kOpaqueAlphaFlag | kHasSpan16_Flag
     */
    virtual void shadeSpan16(int x, int y, uint16_t[], int count);

    /**
     *  Similar to shadeSpan, but only returns the alpha-channel for a span.
     *  The default implementation calls shadeSpan() and then extracts the alpha
     *  values from the returned colors.
     */
    virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);

    /**
     *  Helper function that returns true if this shader's shadeSpan16() method
     *  can be called.
     */
    bool canCallShadeSpan16() {
        return SkShader::CanCallShadeSpan16(this->getFlags());
    }

    /**
     *  Helper to check the flags to know if it is legal to call shadeSpan16()
     */
    static bool CanCallShadeSpan16(uint32_t flags) {
        return (flags & kHasSpan16_Flag) != 0;
    }

    /**
     *  Called before a session using the shader begins. Some shaders override
     *  this to defer some of their work (like calling bitmap.lockPixels()).
     *  Must be balanced by a call to endSession.
     */
    virtual void beginSession();
    virtual void endSession();

    /**
     Gives method bitmap should be read to implement a shader.
     Also determines number and interpretation of "extra" parameters returned
     by asABitmap
     */
    enum BitmapType {
        kNone_BitmapType,   //<! Shader is not represented as a bitmap
        kDefault_BitmapType,//<! Access bitmap using local coords transformed
                            //   by matrix. No extras
        kRadial_BitmapType, //<! Access bitmap by transforming local coordinates
                            //   by the matrix and taking the distance of result
                            //   from  (0,0) as bitmap column. Bitmap is 1 pixel
                            //   tall. No extras
        kSweep_BitmapType,  //<! Access bitmap by transforming local coordinates
                            //   by the matrix and taking the angle of result
                            //   to (0,0) as bitmap x coord, where angle = 0 is
                            //   bitmap left edge of bitmap = 2pi is the
                            //   right edge. Bitmap is 1 pixel tall. No extras
        kTwoPointRadial_BitmapType,
                            //<! Matrix transforms to space where (0,0) is
                            //   the center of the starting circle.  The second
                            //   circle will be centered (x, 0) where x  may be
                            //   0. The post-matrix space is normalized such
                            //   that 1 is the second radius - first radius.
                            //   Three extra parameters are returned:
                            //      0: x-offset of second circle center
                            //         to first.
                            //      1: radius of first circle in post-matrix
                            //         space
                            //      2: the second radius minus the first radius
                            //         in pre-transformed space.

       kLast_BitmapType = kTwoPointRadial_BitmapType
    };
    /** Optional methods for shaders that can pretend to be a bitmap/texture
        to play along with opengl. Default just returns kNone_BitmapType and
        ignores the out parameters.

        @param outTexture if non-NULL will be the bitmap representing the shader
                          after return.
        @param outMatrix  if non-NULL will be the matrix to apply to vertices
                          to access the bitmap after return.
        @param xy         if non-NULL will be the tile modes that should be
                          used to access the bitmap after return.
        @param twoPointRadialParams Two extra return values needed for two point
                                    radial bitmaps. The first is the x-offset of
                                    the second point and the second is the radius
                                    about the first point.
    */
    virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
                         TileMode xy[2], SkScalar* twoPointRadialParams) const;

    /**
     *  If the shader subclass can be represented as a gradient, asAGradient
     *  returns the matching GradientType enum (or kNone_GradientType if it
     *  cannot). Also, if info is not null, asAGradient populates info with
     *  the relevant (see below) parameters for the gradient.  fColorCount
     *  is both an input and output parameter.  On input, it indicates how
     *  many entries in fColors and fColorOffsets can be used, if they are
     *  non-NULL.  After asAGradient has run, fColorCount indicates how
     *  many color-offset pairs there are in the gradient.  If there is
     *  insufficient space to store all of the color-offset pairs, fColors
     *  and fColorOffsets will not be altered.  fColorOffsets specifies
     *  where on the range of 0 to 1 to transition to the given color.
     *  The meaning of fPoint and fRadius is dependant on the type of gradient.
     *
     *  None:
     *      info is ignored.
     *  Color:
     *      fColorOffsets[0] is meaningless.
     *  Linear:
     *      fPoint[0] and fPoint[1] are the end-points of the gradient
     *  Radial:
     *      fPoint[0] and fRadius[0] are the center and radius
     *  Radial2:
     *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle
     *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
     *  Sweep:
     *      fPoint[0] is the center of the sweep.
     */

    enum GradientType {
        kNone_GradientType,
        kColor_GradientType,
        kLinear_GradientType,
        kRadial_GradientType,
        kRadial2_GradientType,
        kSweep_GradientType,
        kLast_GradientType = kSweep_GradientType
    };

    struct GradientInfo {
        int         fColorCount;    //!< In-out parameter, specifies passed size
                                    //   of fColors/fColorOffsets on input, and
                                    //   actual number of colors/offsets on
                                    //   output.
        SkColor*    fColors;        //!< The colors in the gradient.
        SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.
        SkPoint     fPoint[2];      //!< Type specific, see above.
        SkScalar    fRadius[2];     //!< Type specific, see above.
        TileMode    fTileMode;      //!< The tile mode used.
    };

    virtual GradientType asAGradient(GradientInfo* info) const;

    //////////////////////////////////////////////////////////////////////////
    //  Factory methods for stock shaders

    /** Call this to create a new shader that will draw with the specified bitmap.
        @param src  The bitmap to use inside the shader
        @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
        @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
        @return     Returns a new shader object. Note: this function never returns null.
    */
    static SkShader* CreateBitmapShader(const SkBitmap& src,
                                        TileMode tmx, TileMode tmy);

    virtual void flatten(SkFlattenableWriteBuffer& );
protected:
    enum MatrixClass {
        kLinear_MatrixClass,            // no perspective
        kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each scanline
        kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
    };
    static MatrixClass ComputeMatrixClass(const SkMatrix&);

    // These can be called by your subclass after setContext() has been called
    uint8_t             getPaintAlpha() const { return fPaintAlpha; }
    SkBitmap::Config    getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
    const SkMatrix&     getTotalInverse() const { return fTotalInverse; }
    MatrixClass         getInverseClass() const { return (MatrixClass)fTotalInverseClass; }

    SkShader(SkFlattenableReadBuffer& );
private:
    SkMatrix*           fLocalMatrix;
    SkMatrix            fTotalInverse;
    uint8_t             fPaintAlpha;
    uint8_t             fDeviceConfig;
    uint8_t             fTotalInverseClass;
    SkDEBUGCODE(SkBool8 fInSession;)

    static SkShader* CreateBitmapShader(const SkBitmap& src,
                                        TileMode, TileMode,
                                        void* storage, size_t storageSize);
    friend class SkAutoBitmapShaderInstall;
    typedef SkFlattenable INHERITED;
};

#endif


code:
#ifndef SkShape_DEFINED
#define SkShape_DEFINED

#include "SkFlattenable.h"

class SkCanvas;
class SkMatrix;
class SkWStream;

class SkShape : public SkFlattenable {
public:
    SkShape();
    virtual ~SkShape();

    void draw(SkCanvas*);

    /** Draw the shape translated by (dx,dy), which is applied before the
        shape's matrix (if any).
     */
    void drawXY(SkCanvas*, SkScalar dx, SkScalar dy);

    /** Draw the shape with the specified matrix, applied before the shape's
        matrix (if any).
     */
    void drawMatrix(SkCanvas*, const SkMatrix&);

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

    // public for Registrar
    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);

protected:
    virtual void onDraw(SkCanvas*);

    SkShape(SkFlattenableReadBuffer&);

private:

    typedef SkFlattenable INHERITED;
};

#endif


code:
/* libs/corecg/SkSinTable.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 SkSinTable_DEFINED
#define SkSinTable_DEFINED

#include "SkTypes.h"

/* Fixed point values (low 16 bits) of sin(radians) for
    radians in [0...PI/2)
*/
static const uint16_t gSkSinTable[256] = {
    0x0000,
    0x0192,
    0x0324,
    0x04B6,
    0x0648,
    0x07DA,
    0x096C,
    0x0AFE,
    0x0C8F,
    0x0E21,
    0x0FB2,
    0x1144,
    0x12D5,
    0x1466,
    0x15F6,
    0x1787,
    0x1917,
    0x1AA7,
    0x1C37,
    0x1DC7,
    0x1F56,
    0x20E5,
    0x2273,
    0x2402,
    0x2590,
    0x271D,
    0x28AA,
    0x2A37,
    0x2BC4,
    0x2D50,
    0x2EDB,
    0x3066,
    0x31F1,
    0x337B,
    0x3505,
    0x368E,
    0x3817,
    0x399F,
    0x3B26,
    0x3CAD,
    0x3E33,
    0x3FB9,
    0x413E,
    0x42C3,
    0x4447,
    0x45CA,
    0x474D,
    0x48CE,
    0x4A50,
    0x4BD0,
    0x4D50,
    0x4ECF,
    0x504D,
    0x51CA,
    0x5347,
    0x54C3,
    0x563E,
    0x57B8,
    0x5931,
    0x5AAA,
    0x5C22,
    0x5D98,
    0x5F0E,
    0x6083,
    0x61F7,
    0x636A,
    0x64DC,
    0x664D,
    0x67BD,
    0x692D,
    0x6A9B,
    0x6C08,
    0x6D74,
    0x6EDF,
    0x7049,
    0x71B1,
    0x7319,
    0x7480,
    0x75E5,
    0x774A,
    0x78AD,
    0x7A0F,
    0x7B70,
    0x7CD0,
    0x7E2E,
    0x7F8B,
    0x80E7,
    0x8242,
    0x839C,
    0x84F4,
    0x864B,
    0x87A1,
    0x88F5,
    0x8A48,
    0x8B9A,
    0x8CEA,
    0x8E39,
    0x8F87,
    0x90D3,
    0x921E,
    0x9368,
    0x94B0,
    0x95F6,
    0x973C,
    0x987F,
    0x99C2,
    0x9B02,
    0x9C42,
    0x9D7F,
    0x9EBC,
    0x9FF6,
    0xA12F,
    0xA267,
    0xA39D,
    0xA4D2,
    0xA605,
    0xA736,
    0xA866,
    0xA994,
    0xAAC0,
    0xABEB,
    0xAD14,
    0xAE3B,
    0xAF61,
    0xB085,
    0xB1A8,
    0xB2C8,
    0xB3E7,
    0xB504,
    0xB620,
    0xB73A,
    0xB852,
    0xB968,
    0xBA7C,
    0xBB8F,
    0xBCA0,
    0xBDAE,
    0xBEBC,
    0xBFC7,
    0xC0D0,
    0xC1D8,
    0xC2DE,
    0xC3E2,
    0xC4E3,
    0xC5E4,
    0xC6E2,
    0xC7DE,
    0xC8D8,
    0xC9D1,
    0xCAC7,
    0xCBBB,
    0xCCAE,
    0xCD9F,
    0xCE8D,
    0xCF7A,
    0xD064,
    0xD14D,
    0xD233,
    0xD318,
    0xD3FA,
    0xD4DB,
    0xD5B9,
    0xD695,
    0xD770,
    0xD848,
    0xD91E,
    0xD9F2,
    0xDAC4,
    0xDB94,
    0xDC61,
    0xDD2D,
    0xDDF6,
    0xDEBE,
    0xDF83,
    0xE046,
    0xE106,
    0xE1C5,
    0xE282,
    0xE33C,
    0xE3F4,
    0xE4AA,
    0xE55E,
    0xE60F,
    0xE6BE,
    0xE76B,
    0xE816,
    0xE8BF,
    0xE965,
    0xEA09,
    0xEAAB,
    0xEB4B,
    0xEBE8,
    0xEC83,
    0xED1C,
    0xEDB2,
    0xEE46,
    0xEED8,
    0xEF68,
    0xEFF5,
    0xF080,
    0xF109,
    0xF18F,
    0xF213,
    0xF294,
    0xF314,
    0xF391,
    0xF40B,
    0xF484,
    0xF4FA,
    0xF56D,
    0xF5DE,
    0xF64D,
    0xF6BA,
    0xF724,
    0xF78B,
    0xF7F1,
    0xF853,
    0xF8B4,
    0xF912,
    0xF96E,
    0xF9C7,
    0xFA1E,
    0xFA73,
    0xFAC5,
    0xFB14,
    0xFB61,
    0xFBAC,
    0xFBF5,
    0xFC3B,
    0xFC7E,
    0xFCBF,
    0xFCFE,
    0xFD3A,
    0xFD74,
    0xFDAB,
    0xFDE0,
    0xFE13,
    0xFE43,
    0xFE70,
    0xFE9B,
    0xFEC4,
    0xFEEA,
    0xFF0E,
    0xFF2F,
    0xFF4E,
    0xFF6A,
    0xFF84,
    0xFF9C,
    0xFFB1,
    0xFFC3,
    0xFFD3,
    0xFFE1,
    0xFFEC,
    0xFFF4,
    0xFFFB,
    0xFFFE
};

#endif


code:
#ifndef SkSize_DEFINED
#define SkSize_DEFINED

template <typename T> struct SkTSize {
    T fWidth;
    T fHeight;

    static SkTSize Make(T w, T h) {
        SkTSize s;
        s.fWidth = w;
        s.fHeight = h;
        return s;
    }

    void set(T w, T h) {
        fWidth = w;
        fHeight = h;
    }

    /** Returns true iff fWidth == 0 && fHeight == 0
     */
    bool isZero() const {
        return 0 == fWidth && 0 == fHeight;
    }

    /** Returns true if either widht or height are <= 0 */
    bool isEmpty() const {
        return fWidth <= 0 || fHeight <= 0;
    }

    /** Set the width and height to 0 */
    void setEmpty() {
        fWidth = fHeight = 0;
    }

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

    /** If width or height is < 0, it is set to 0 */
    void clampNegToZero() {
        if (fWidth < 0) {
            fWidth = 0;
        }
        if (fHeight < 0) {
            fHeight = 0;
        }
    }

    bool equals(T w, T h) const {
        return fWidth == w && fHeight == h;
    }
};

template <typename T>
static inline bool operator==(const SkTSize<T>& a, const SkTSize<T>& b) {
    return a.fWidth == b.fWidth && a.fHeight == b.fHeight;
}

template <typename T>
static inline bool operator!=(const SkTSize<T>& a, const SkTSize<T>& b) {
    return !(a == b);
}

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

typedef SkTSize<int32_t> SkISize;

#include "SkScalar.h"

struct SkSize : public SkTSize<SkScalar> {
    static SkSize Make(SkScalar w, SkScalar h) {
        SkSize s;
        s.fWidth = w;
        s.fHeight = h;
        return s;
    }

    SkSize& operator=(const SkISize& src) {
        this->set(SkIntToScalar(src.fWidth), SkIntToScalar(src.fHeight));
        return *this;
    }

    SkISize toRound() const {
        SkISize s;
        s.set(SkScalarRound(fWidth), SkScalarRound(fHeight));
        return s;
    }

    SkISize toCeil() const {
        SkISize s;
        s.set(SkScalarCeil(fWidth), SkScalarCeil(fHeight));
        return s;
    }

    SkISize toFloor() const {
        SkISize s;
        s.set(SkScalarFloor(fWidth), SkScalarFloor(fHeight));
        return s;
    }
};

#endif


code:
/* libs/graphics/animator/SkSnapshot.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 SkSnapShot_DEFINED
#define SkSnapShot_DEFINED

#include "SkDrawable.h"
#include "SkImageDecoder.h"
#include "SkMemberInfo.h"
#include "SkString.h"

class SkSnapshot: public SkDrawable {
    DECLARE_MEMBER_INFO(Snapshot);
    SkSnapshot();
    virtual bool draw(SkAnimateMaker& );
    private:
    SkString filename;
    SkScalar quality;
    SkBool sequence;
    int /*SkImageEncoder::Type*/    type;
    int fSeqVal;
};

#endif // SkSnapShot_DEFINED


code:
/* libs/graphics/sgl/SkSpriteBlitter.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 SkSpriteBlitter_DEFINED
#define SkSpriteBlitter_DEFINED

#include "SkBlitter.h"
#include "SkBitmap.h"

class SkPaint;

class SkSpriteBlitter : public SkBlitter {
public:
            SkSpriteBlitter(const SkBitmap& source);
    virtual ~SkSpriteBlitter();

    virtual void setup(const SkBitmap& device, int left, int top,
                       const SkPaint& paint);

    // overrides
#ifdef SK_DEBUG
    virtual void    blitH(int x, int y, int width);
    virtual void    blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
    virtual void    blitV(int x, int y, int height, SkAlpha alpha);
    virtual void    blitMask(const SkMask&, const SkIRect& clip);
#endif

    static SkSpriteBlitter* ChooseD16(const SkBitmap& source, const SkPaint&,
                                      void* storage, size_t storageSize);
    static SkSpriteBlitter* ChooseD32(const SkBitmap& source, const SkPaint&,
                                      void* storage, size_t storageSize);

protected:
    const SkBitmap* fDevice;
    const SkBitmap* fSource;
    int             fLeft, fTop;
    const SkPaint*  fPaint;
};

#endif


code:
/* libs/graphics/sgl/SkSpriteBlitterTemplate.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.
*/

class SkSPRITE_CLASSNAME : public SkSpriteBlitter {
public:
    SkSPRITE_CLASSNAME(const SkBitmap& source SkSPRITE_ARGS)
        : SkSpriteBlitter(source) {
        SkSPRITE_INIT
    }

    virtual void blitRect(int x, int y, int width, int height) {
        SkASSERT(width > 0 && height > 0);
        int srcX = x - fLeft;
        int srcY = y - fTop;
        SkSPRITE_DST_TYPE* SK_RESTRICT dst =fDevice->SkSPRITE_DST_GETADDR(x, y);
        const SkSPRITE_SRC_TYPE* SK_RESTRICT src =
                                      fSource->SkSPRITE_SRC_GETADDR(srcX, srcY);
        unsigned dstRB = fDevice->rowBytes();
        unsigned srcRB = fSource->rowBytes();

        SkDEBUGCODE((void)fDevice->SkSPRITE_DST_GETADDR(x + width - 1, y + height - 1);)
        SkDEBUGCODE((void)fSource->SkSPRITE_SRC_GETADDR(srcX + width  - 1, srcY + height - 1);)

        SkSPRITE_PREAMBLE((*fSource), srcX, srcY);

        do {
            SkSPRITE_DST_TYPE* d = dst;
            const SkSPRITE_SRC_TYPE* s = src;
#ifdef SkSPRITE_BEGIN_ROW
            SkSPRITE_BEGIN_ROW
#endif

#ifdef SkSPRITE_ROW_PROC
            SkSPRITE_ROW_PROC(d, s, width, x, y);
#else
            int w = width;
            do {
                SkSPRITE_SRC_TYPE sc = *s++;
                SkSPRITE_BLIT_PIXEL(d, sc);
                d += 1;
            } while (--w != 0);
#endif
            dst = (SkSPRITE_DST_TYPE* SK_RESTRICT)((char*)dst + dstRB);
            src = (const SkSPRITE_SRC_TYPE* SK_RESTRICT)
                                            ((const char*)src + srcRB);
            SkSPRITE_NEXT_ROW
#ifdef SkSPRITE_ROW_PROC
            y += 1;
#endif
        } while (--height != 0);

        SkSPRITE_POSTAMBLE((*fSource));
    }

private:
    SkSPRITE_FIELDS
};

#undef SkSPRITE_BLIT_PIXEL
#undef SkSPRITE_CLASSNAME
#undef SkSPRITE_DST_TYPE
#undef SkSPRITE_SRC_TYPE
#undef SkSPRITE_DST_GETADDR
#undef SkSPRITE_SRC_GETADDR
#undef SkSPRITE_PREAMBLE
#undef SkSPRITE_POSTAMBLE
#undef SkSPRITE_ARGS
#undef SkSPRITE_FIELDS
#undef SkSPRITE_INIT
#undef SkSPRITE_NEXT_ROW
#undef SkSPRITE_BEGIN_ROW

#ifdef SkSPRITE_ROW_PROC
    #undef SkSPRITE_ROW_PROC
#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 SkStackViewLayout_DEFINED
#define SkStackViewLayout_DEFINED

#include "SkView.h"

class SkStackViewLayout : public SkView::Layout {
public:
    SkStackViewLayout();

    enum Orient {
        kHorizontal_Orient,
        kVertical_Orient,

        kOrientCount
    };
    Orient  getOrient() const { return (Orient)fOrient; }
    void    setOrient(Orient);

    void        getMargin(SkRect*) const;
    void        setMargin(const SkRect&);

    SkScalar    getSpacer() const { return fSpacer; }
    void        setSpacer(SkScalar);

    /** Controls the posititioning in the same direction as the orientation
    */
    enum Pack {
        kStart_Pack,
        kCenter_Pack,
        kEnd_Pack,

        kPackCount
    };
    Pack    getPack() const { return (Pack)fPack; }
    void    setPack(Pack);

    /** Controls the posititioning at right angles to the orientation
    */
    enum Align {
        kStart_Align,
        kCenter_Align,
        kEnd_Align,
        kStretch_Align,

        kAlignCount
    };
    Align   getAlign() const { return (Align)fAlign; }
    void    setAlign(Align);

    bool    getRound() const { return SkToBool(fRound); }
    void    setRound(bool);

protected:
    virtual void onLayoutChildren(SkView* parent);
    virtual void onInflate(const SkDOM&, const SkDOM::Node*);

private:
    SkRect      fMargin;
    SkScalar    fSpacer;
    uint8_t     fOrient, fPack, fAlign, fRound;
};

class SkFillViewLayout : public SkView::Layout {
public:
            SkFillViewLayout();
    void    getMargin(SkRect*) const;
    void    setMargin(const SkRect&);

protected:
    // overrides;
    virtual void onLayoutChildren(SkView* parent);
    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);

private:
    SkRect  fMargin;
    typedef SkView::Layout INHERITED;
};

#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 SkStream_DEFINED
#define SkStream_DEFINED

#include "SkRefCnt.h"
#include "SkScalar.h"

class SkData;

class SK_API SkStream : public SkRefCnt {
public:
    virtual ~SkStream();
    /** Called to rewind to the beginning of the stream. If this cannot be
        done, return false.
    */
    virtual bool rewind() = 0;
    /** If this stream represents a file, this method returns the file's name.
        If it does not, it returns NULL (the default behavior).
    */
    virtual const char* getFileName();
    /** Called to read or skip size number of bytes.
        If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
        If buffer is NULL and size == 0, return the total length of the stream.
        If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
        @param buffer   If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
        @param size The number of bytes to skip or copy
        @return bytes read on success
    */
    virtual size_t read(void* buffer, size_t size) = 0;

    /** Return the total length of the stream.
    */
    size_t getLength() { return this->read(NULL, 0); }

    /** Skip the specified number of bytes, returning the actual number
        of bytes that could be skipped.
    */
    size_t skip(size_t bytes);

    /** If the stream is backed by RAM, this method returns the starting
        address for the data. If not (i.e. it is backed by a file or other
        structure), this method returns NULL.
        The default implementation returns NULL.
    */
    virtual const void* getMemoryBase();

    int8_t   readS8();
    int16_t  readS16();
    int32_t  readS32();

    uint8_t  readU8() { return (uint8_t)this->readS8(); }
    uint16_t readU16() { return (uint16_t)this->readS16(); }
    uint32_t readU32() { return (uint32_t)this->readS32(); }

    bool     readBool() { return this->readU8() != 0; }
    SkScalar readScalar();
    size_t   readPackedUInt();
};

class SK_API SkWStream : SkNoncopyable {
public:
    virtual ~SkWStream();

    /** Called to write bytes to a SkWStream. Returns true on success
        @param buffer the address of at least size bytes to be written to the stream
        @param size The number of bytes in buffer to write to the stream
        @return true on success
    */
    virtual bool write(const void* buffer, size_t size) = 0;
    virtual void newline();
    virtual void flush();

    // helpers

    bool    write8(U8CPU);
    bool    write16(U16CPU);
    bool    write32(uint32_t);

    bool    writeText(const char text[]);
    bool    writeDecAsText(int32_t);
    bool    writeBigDecAsText(int64_t, int minDigits = 0);
    bool    writeHexAsText(uint32_t, int minDigits = 0);
    bool    writeScalarAsText(SkScalar);

    bool    writeBool(bool v) { return this->write8(v); }
    bool    writeScalar(SkScalar);
    bool    writePackedUInt(size_t);

    bool writeStream(SkStream* input, size_t length);

    bool writeData(const SkData*);
};

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

#include "SkString.h"

struct SkFILE;

/** A stream that reads from a FILE*, which is opened in the constructor and
    closed in the destructor
 */
class SK_API SkFILEStream : public SkStream {
public:
    /** Initialize the stream by calling fopen on the specified path. Will be
        closed in the destructor.
     */
    explicit SkFILEStream(const char path[] = NULL);
    virtual ~SkFILEStream();

    /** Returns true if the current path could be opened.
    */
    bool isValid() const { return fFILE != NULL; }
    /** Close the current file, and open a new file with the specified
        path. If path is NULL, just close the current file.
    */
    void setPath(const char path[]);

    virtual bool rewind();
    virtual size_t read(void* buffer, size_t size);
    virtual const char* getFileName();

private:
    SkFILE*     fFILE;
    SkString    fName;
};

/** A stream that reads from a file descriptor
 */
class SkFDStream : public SkStream {
public:
    /** Initialize the stream with a dup() of the specified file descriptor.
        If closeWhenDone is true, then the descriptor will be closed in the
        destructor.
     */
    SkFDStream(int fileDesc, bool closeWhenDone);
    virtual ~SkFDStream();

    /** Returns true if the current path could be opened.
     */
    bool isValid() const { return fFD >= 0; }

    virtual bool rewind();
    virtual size_t read(void* buffer, size_t size);
    virtual const char* getFileName() { return NULL; }

private:
    int     fFD;
    bool    fCloseWhenDone;
};

class SkMemoryStream : public SkStream {
public:
    SkMemoryStream();
    /** We allocate (and free) the memory. Write to it via getMemoryBase()
    */
    SkMemoryStream(size_t length);
    /** if copyData is true, the stream makes a private copy of the data
    */
    SkMemoryStream(const void* data, size_t length, bool copyData = false);
    virtual ~SkMemoryStream();

    /** Resets the stream to the specified data and length,
        just like the constructor.
        if copyData is true, the stream makes a private copy of the data
    */
    virtual void setMemory(const void* data, size_t length,
                           bool copyData = false);
    /** Replace any memory buffer with the specified buffer. The caller
        must have allocated data with sk_malloc or sk_realloc, since it
        will be freed with sk_free.
    */
    void setMemoryOwned(const void* data, size_t length);

    /**
     *  Return the stream's data in a SkData. The caller must call unref() when
     *  it is finished using the data.
     */
    SkData* copyToData() const;

    /**
     *  Use the specified data as the memory for this stream. The stream will
     *  call ref() on the data (assuming it is not null). The function returns
     *  the data parameter as a convenience.
     */
    SkData* setData(SkData*);

    void skipToAlign4();
    virtual bool rewind();
    virtual size_t read(void* buffer, size_t size);
    virtual const void* getMemoryBase();
    const void* getAtPos();
    size_t seek(size_t offset);
    size_t peek() const { return fOffset; }

private:
    SkData* fData;
    size_t  fOffset;
};

/** \class SkBufferStream
    This is a wrapper class that adds buffering to another stream.
    The caller can provide the buffer, or ask SkBufferStream to allocated/free
    it automatically.
*/
class SkBufferStream : public SkStream {
public:
    /** Provide the stream to be buffered (proxy), and the size of the buffer that
        should be used. This will be allocated and freed automatically. If bufferSize is 0,
        a default buffer size will be used.
        The proxy stream is referenced, and will be unreferenced in when the
        bufferstream is destroyed.
    */
    SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
    /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
        This buffer is owned by the caller, and must be at least bufferSize bytes big.
        Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
        If buffer is not NULL, it is an error for bufferSize to be 0.
     The proxy stream is referenced, and will be unreferenced in when the
     bufferstream is destroyed.
    */
    SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
    virtual ~SkBufferStream();

    virtual bool        rewind();
    virtual const char* getFileName();
    virtual size_t      read(void* buffer, size_t size);
    virtual const void* getMemoryBase();

private:
    enum {
        kDefaultBufferSize  = 128
    };
    // illegal
    SkBufferStream(const SkBufferStream&);
    SkBufferStream& operator=(const SkBufferStream&);

    SkStream*   fProxy;
    char*       fBuffer;
    size_t      fOrigBufferSize, fBufferSize, fBufferOffset;
    bool        fWeOwnTheBuffer;

    void    init(void*, size_t);
};

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

class SK_API SkFILEWStream : public SkWStream {
public:
            SkFILEWStream(const char path[]);
    virtual ~SkFILEWStream();

    /** Returns true if the current path could be opened.
    */
    bool isValid() const { return fFILE != NULL; }

    virtual bool write(const void* buffer, size_t size);
    virtual void flush();
private:
    SkFILE* fFILE;
};

class SkMemoryWStream : public SkWStream {
public:
    SkMemoryWStream(void* buffer, size_t size);
    virtual bool write(const void* buffer, size_t size);

private:
    char*   fBuffer;
    size_t  fMaxLength;
    size_t  fBytesWritten;
};

class SK_API SkDynamicMemoryWStream : public SkWStream {
public:
    SkDynamicMemoryWStream();
    virtual ~SkDynamicMemoryWStream();

    virtual bool write(const void* buffer, size_t size);
    // random access write
    // modifies stream and returns true if offset + size is less than or equal to getOffset()
    bool write(const void* buffer, size_t offset, size_t size);
    bool read(void* buffer, size_t offset, size_t size);
    size_t getOffset() const { return fBytesWritten; }
    size_t bytesWritten() const { return fBytesWritten; }

    // copy what has been written to the stream into dst
    void copyTo(void* dst) const;

    /**
     *  Return a copy of the data written so far. This call is responsible for
     *  calling unref() when they are finished with the data.
     */
    SkData* copyToData() const;

    // reset the stream to its original state
    void reset();
    void padToAlign4();
private:
    struct Block;
    Block*  fHead;
    Block*  fTail;
    size_t  fBytesWritten;
    mutable SkData* fCopy;  // is invalidated if we write after it is created

    void invalidateCopy();
};

class SkDebugWStream : public SkWStream {
public:
    // overrides
    virtual bool write(const void* buffer, size_t size);
    virtual void newline();
};

// for now
typedef SkFILEStream SkURLStream;

#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 SkStream_Win_DEFINED
#define SkStream_Win_DEFINED

#ifndef SK_BUILD_FOR_WIN
#error "only valid for windows and wince builds"
#endif

#ifndef SkStream_DEFINED
#include "SkStream.h"
#endif
#include "SkString.h"
#include "Wininet.h"

/** \cond ZERO */
class SkURLStream : public SkStream {
public:
    SkURLStream(const char url[] = NULL);
    virtual ~SkURLStream();

    /** Close the current URL, and open a new URL.
        If URL is null, just close the current URL.
    */
    void setURL(const char url[]);

    // overrides
    virtual bool rewind();
    virtual size_t read(void* buffer, size_t size);

private:
    SkString fURL;
    HINTERNET fConnection;
    HINTERNET fURLStream;
};

/** \endcond */
#endif // SkStream_Win_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 SkString_DEFINED
#define SkString_DEFINED

#include "SkScalar.h"

/*  Some helper functions for C strings
*/

bool SkStrStartsWith(const char string[], const char prefix[]);
bool SkStrEndsWith(const char string[], const char suffix[]);
int SkStrStartsWithOneOf(const char string[], const char prefixes[]);

#define SkStrAppendS32_MaxSize  11
char*   SkStrAppendS32(char buffer[], int32_t);
#define SkStrAppendS64_MaxSize  20
char*   SkStrAppendS64(char buffer[], int64_t, int minDigits);

/**
 *  Floats have at most 8 significant digits, so we limit our %g to that.
 *  However, the total string could be 15 characters: -1.2345678e-005
 *
 *  In theory we should only expect up to 2 digits for the exponent, but on
 *  some platforms we have seen 3 (as in the example above).
 */
#define SkStrAppendScalar_MaxSize  15

/**
 *  Write the scaler in decimal format into buffer, and return a pointer to
 *  the next char after the last one written. Note: a terminating 0 is not
 *  written into buffer, which must be at least SkStrAppendScalar_MaxSize.
 *  Thus if the caller wants to add a 0 at the end, buffer must be at least
 *  SkStrAppendScalar_MaxSize + 1 bytes large.
 */
#ifdef SK_SCALAR_IS_FLOAT
    #define SkStrAppendScalar SkStrAppendFloat
#else
    #define SkStrAppendScalar SkStrAppendFixed
#endif

#ifdef SK_CAN_USE_FLOAT
char* SkStrAppendFloat(char buffer[], float);
#endif
char* SkStrAppendFixed(char buffer[], SkFixed);

/** \class SkString

    Light weight class for managing strings. Uses reference
    counting to make string assignments and copies very fast
    with no extra RAM cost. Assumes UTF8 encoding.
*/
class SkString {
public:
                SkString();
    explicit    SkString(size_t len);
    explicit    SkString(const char text[]);
                SkString(const char text[], size_t len);
                SkString(const SkString&);
                ~SkString();

    bool        isEmpty() const { return fRec->fLength == 0; }
    size_t      size() const { return (size_t) fRec->fLength; }
    const char* c_str() const { return fRec->data(); }
    char operator[](size_t n) const { return this->c_str()[n]; }

    bool equals(const SkString&) const;
    bool equals(const char text[]) const;
    bool equals(const char text[], size_t len) const;

    bool startsWith(const char prefix[]) const {
        return SkStrStartsWith(fRec->data(), prefix);
    }
    bool endsWith(const char suffix[]) const {
        return SkStrEndsWith(fRec->data(), suffix);
    }

    friend int operator==(const SkString& a, const SkString& b) {
        return a.equals(b);
    }
    friend int operator!=(const SkString& a, const SkString& b) {
        return !a.equals(b);
    }

    // these methods edit the string

    SkString&   operator=(const SkString&);
    SkString&   operator=(const char text[]);

    char*   writable_str();
    char& operator[](size_t n) { return this->writable_str()[n]; }

    void reset();
    void resize(size_t len) { this->set(NULL, len); }
    void set(const SkString& src) { *this = src; }
    void set(const char text[]);
    void set(const char text[], size_t len);
    void setUTF16(const uint16_t[]);
    void setUTF16(const uint16_t[], size_t len);

    void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); }
    void insert(size_t offset, const char text[]);
    void insert(size_t offset, const char text[], size_t len);
    void insertUnichar(size_t offset, SkUnichar);
    void insertS32(size_t offset, int32_t value);
    void insertS64(size_t offset, int64_t value, int minDigits = 0);
    void insertHex(size_t offset, uint32_t value, int minDigits = 0);
    void insertScalar(size_t offset, SkScalar);

    void append(const SkString& str) { this->insert((size_t)-1, str); }
    void append(const char text[]) { this->insert((size_t)-1, text); }
    void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }
    void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }
    void appendS32(int32_t value) { this->insertS32((size_t)-1, value); }
    void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); }
    void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); }
    void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }

    void prepend(const SkString& str) { this->insert(0, str); }
    void prepend(const char text[]) { this->insert(0, text); }
    void prepend(const char text[], size_t len) { this->insert(0, text, len); }
    void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }
    void prependS32(int32_t value) { this->insertS32(0, value); }
    void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); }
    void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }
    void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }

    void printf(const char format[], ...);
    void appendf(const char format[], ...);
    void prependf(const char format[], ...);

    void remove(size_t offset, size_t length);

    SkString& operator+=(const SkString& s) { this->append(s); return *this; }
    SkString& operator+=(const char text[]) { this->append(text); return *this; }
    SkString& operator+=(const char c) { this->append(&c, 1); return *this; }

    /**
     *  Swap contents between this and other. This function is guaranteed
     *  to never fail or throw.
     */
    void swap(SkString& other);

private:
    struct Rec {
    public:
        uint16_t    fLength;
        uint16_t    fRefCnt;
        char        fBeginningOfData;

        char* data() { return &fBeginningOfData; }
        const char* data() const { return &fBeginningOfData; }
    };
    Rec* fRec;

#ifdef SK_DEBUG
    const char* fStr;
    void validate() const;
#else
    void validate() const {}
#endif

    static const Rec gEmptyRec;
    static Rec* AllocRec(const char text[], U16CPU len);
    static Rec* RefRec(Rec*);
};

class SkAutoUCS2 {
public:
    SkAutoUCS2(const char utf8[]);
    ~SkAutoUCS2();

    /** This returns the number of ucs2 characters
    */
    int count() const { return fCount; }

    /** This returns a null terminated ucs2 string
    */
    const uint16_t* getUCS2() const { return fUCS2; }

private:
    int         fCount;
    uint16_t*   fUCS2;
};

#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 SkStroke_DEFINED
#define SkStroke_DEFINED

#include "SkPoint.h"
#include "SkPaint.h"

struct SkRect;
class SkPath;

#define SK_DefaultStrokeWidth       SK_Scalar1
#define SK_DefaultMiterLimit        SkIntToScalar(4)

/** \class SkStroke
    SkStroke is the utility class that constructs paths by stroking
    geometries (lines, rects, ovals, roundrects, paths). This is
    invoked when a geometry or text is drawn in a canvas with the
    kStroke_Mask bit set in the paint.
*/
class SkStroke {
public:
    SkStroke();
    SkStroke(const SkPaint&);
    SkStroke(const SkPaint&, SkScalar width);   // width overrides paint.getStrokeWidth()

    SkPaint::Cap    getCap() const { return (SkPaint::Cap)fCap; }
    void        setCap(SkPaint::Cap);

    SkPaint::Join   getJoin() const { return (SkPaint::Join)fJoin; }
    void        setJoin(SkPaint::Join);

    void    setMiterLimit(SkScalar);
    void    setWidth(SkScalar);

    bool    getDoFill() const { return SkToBool(fDoFill); }
    void    setDoFill(bool doFill) { fDoFill = SkToU8(doFill); }

    void    strokeLine(const SkPoint& start, const SkPoint& end, SkPath*) const;
    void    strokeRect(const SkRect& rect, SkPath*) const;
    void    strokeOval(const SkRect& oval, SkPath*) const;
    void    strokeRRect(const SkRect& rect, SkScalar rx, SkScalar ry, SkPath*) const;
    void    strokePath(const SkPath& path, SkPath*) const;

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

private:
    SkScalar    fWidth, fMiterLimit;
    uint8_t     fCap, fJoin;
    SkBool8     fDoFill;

    friend class SkPaint;
};

#endif


code:
/* libs/graphics/sgl/SkStrokerPriv.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 SkStrokerPriv_DEFINED
#define SkStrokerPriv_DEFINED

#include "SkStroke.h"

#define CWX(x, y)   (-y)
#define CWY(x, y)   (x)
#define CCWX(x, y)  (y)
#define CCWY(x, y)  (-x)

#define CUBIC_ARC_FACTOR    ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3)

class SkStrokerPriv {
public:
    typedef void (*CapProc)(SkPath* path,
                            const SkPoint& pivot,
                            const SkVector& normal,
                            const SkPoint& stop,
                            SkPath* otherPath);

    typedef void (*JoinProc)(SkPath* outer, SkPath* inner,
                             const SkVector& beforeUnitNormal,
                             const SkPoint& pivot,
                             const SkVector& afterUnitNormal,
                             SkScalar radius, SkScalar invMiterLimit,
                             bool prevIsLine, bool currIsLine);

    static CapProc  CapFactory(SkPaint::Cap);
    static JoinProc JoinFactory(SkPaint::Join);
};

#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 SkSystemEventTypes_DEFINED
#define SkSystemEventTypes_DEFINED

/*
    The goal of these strings is two-fold:
    1) make funny strings (containing at least one char < 32) to avoid colliding with "user" strings
    2) keep them <= 4 bytes, so we can avoid an allocation in SkEvent::setType()
*/
#define SK_EventType_Delay      "\xd" "lay"
#define SK_EventType_Inval      "nv" "\xa" "l"
#define SK_EventType_Key        "key" "\x1"
#define SK_EventType_OnEnd "on" "\xe" "n"
#define SK_EventType_Unichar    "\xc" "har"
#define SK_EventType_KeyUp      "key" "\xf"

#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 SkTDArray_DEFINED
#define SkTDArray_DEFINED

#include "SkTypes.h"

template <typename T> class SK_API SkTDArray {
public:
    SkTDArray() {
        fReserve = fCount = 0;
        fArray = NULL;
#ifdef SK_DEBUG
        fData = NULL;
#endif
    }
    SkTDArray(const T src[], size_t count) {
        SkASSERT(src || count == 0);

        fReserve = fCount = 0;
        fArray = NULL;
#ifdef SK_DEBUG
        fData = NULL;
#endif
        if (count) {
            fArray = (T*)sk_malloc_throw(count * sizeof(T));
#ifdef SK_DEBUG
            fData = (ArrayT*)fArray;
#endif
            memcpy(fArray, src, sizeof(T) * count);
            fReserve = fCount = count;
        }
    }
    SkTDArray(const SkTDArray<T>& src) {
        fReserve = fCount = 0;
        fArray = NULL;
#ifdef SK_DEBUG
        fData = NULL;
#endif
        SkTDArray<T> tmp(src.fArray, src.fCount);
        this->swap(tmp);
    }
    ~SkTDArray() {
        sk_free(fArray);
    }

    SkTDArray<T>& operator=(const SkTDArray<T>& src) {
        if (this != &src) {
            if (src.fCount > fReserve) {
                SkTDArray<T> tmp(src.fArray, src.fCount);
                this->swap(tmp);
            } else {
                memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
                fCount = src.fCount;
            }
        }
        return *this;
    }

    friend int operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
        return  a.fCount == b.fCount &&
                (a.fCount == 0 ||
                 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));
    }

    void swap(SkTDArray<T>& other) {
        SkTSwap(fArray, other.fArray);
#ifdef SK_DEBUG
        SkTSwap(fData, other.fData);
#endif
        SkTSwap(fReserve, other.fReserve);
        SkTSwap(fCount, other.fCount);
    }

    /** Return a ptr to the array of data, to be freed with sk_free. This also
        resets the SkTDArray to be empty.
     */
    T* detach() {
        T* array = fArray;
        fArray = NULL;
        fReserve = fCount = 0;
        SkDEBUGCODE(fData = NULL;)
        return array;
    }

    bool isEmpty() const { return fCount == 0; }
    int count() const { return fCount; }
    T*  begin() const { return fArray; }
    T*  end() const { return fArray ? fArray + fCount : NULL; }
    T&  operator[](int index) const {
        SkASSERT((unsigned)index < fCount);
        return fArray[index];
    }

    void reset() {
        if (fArray) {
            sk_free(fArray);
            fArray = NULL;
#ifdef SK_DEBUG
            fData = NULL;
#endif
            fReserve = fCount = 0;
        } else {
            SkASSERT(fReserve == 0 && fCount == 0);
        }
    }

    void rewind() {
        // same as setCount(0)
        fCount = 0;
    }

    void setCount(size_t count) {
        if (count > fReserve) {
            this->growBy(count - fCount);
        } else {
            fCount = count;
        }
    }

    void setReserve(size_t reserve) {
        if (reserve > fReserve) {
            SkASSERT(reserve > fCount);
            size_t count = fCount;
            this->growBy(reserve - fCount);
            fCount = count;
        }
    }

    T* prepend() {
        this->growBy(1);
        memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
        return fArray;
    }

    T* append() {
        return this->append(1, NULL);
    }
    T* append(size_t count, const T* src = NULL) {
        unsigned oldCount = fCount;
        if (count)  {
            SkASSERT(src == NULL || fArray == NULL ||
                    src + count <= fArray || fArray + oldCount <= src);

            this->growBy(count);
            if (src) {
                memcpy(fArray + oldCount, src, sizeof(T) * count);
            }
        }
        return fArray + oldCount;
    }

    T* appendClear() {
        T* result = this->append();
        *result = 0;
        return result;
    }

    T* insert(size_t index) {
        return this->insert(index, 1, NULL);
    }
    T* insert(size_t index, size_t count, const T* src = NULL) {
        SkASSERT(count);
        SkASSERT(index <= fCount);
        int oldCount = fCount;
        this->growBy(count);
        T* dst = fArray + index;
        memmove(dst + count, dst, sizeof(T) * (oldCount - index));
        if (src) {
            memcpy(dst, src, sizeof(T) * count);
        }
        return dst;
    }

    void remove(size_t index, size_t count = 1) {
        SkASSERT(index + count <= fCount);
        fCount = fCount - count;
        memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));
    }

    void removeShuffle(size_t index) {
        SkASSERT(index < fCount);
        unsigned newCount = fCount - 1;
        fCount = newCount;
        if (index != newCount) {
            memcpy(fArray + index, fArray + newCount, sizeof(T));
        }
    }

    int find(const T& elem) const {
        const T* iter = fArray;
        const T* stop = fArray + fCount;

        for (; iter < stop; iter++) {
            if (*iter == elem) {
                return (int) (iter - fArray);
            }
        }
        return -1;
    }

    int rfind(const T& elem) const {
        const T* iter = fArray + fCount;
        const T* stop = fArray;

        while (iter > stop) {
            if (*--iter == elem) {
                return iter - stop;
            }
        }
        return -1;
    }

    // routines to treat the array like a stack
    T*          push() { return this->append(); }
    void        push(const T& elem) { *this->append() = elem; }
    const T&    top() const { return (*this)[fCount - 1]; }
    T&          top() { return (*this)[fCount - 1]; }
    void        pop(T* elem) { if (elem) *elem = (*this)[fCount - 1]; --fCount; }
    void        pop() { --fCount; }

    void deleteAll() {
        T*  iter = fArray;
        T*  stop = fArray + fCount;
        while (iter < stop) {
            delete (*iter);
            iter += 1;
        }
        this->reset();
    }

    void freeAll() {
        T*  iter = fArray;
        T*  stop = fArray + fCount;
        while (iter < stop) {
            sk_free(*iter);
            iter += 1;
        }
        this->reset();
    }

    void unrefAll() {
        T*  iter = fArray;
        T*  stop = fArray + fCount;
        while (iter < stop) {
            (*iter)->unref();
            iter += 1;
        }
        this->reset();
    }

    void safeUnrefAll() {
        T*  iter = fArray;
        T*  stop = fArray + fCount;
        while (iter < stop) {
            SkSafeUnref(*iter);
            iter += 1;
        }
        this->reset();
    }

#ifdef SK_DEBUG
    void validate() const {
        SkASSERT((fReserve == 0 && fArray == NULL) ||
                 (fReserve > 0 && fArray != NULL));
        SkASSERT(fCount <= fReserve);
        SkASSERT(fData == (ArrayT*)fArray);
    }
#endif

private:
#ifdef SK_DEBUG
    enum {
        kDebugArraySize = 16
    };
    typedef T ArrayT[kDebugArraySize];
    ArrayT* fData;
#endif
    T*      fArray;
    size_t  fReserve, fCount;

    void growBy(size_t extra) {
        SkASSERT(extra);

        if (fCount + extra > fReserve) {
            size_t size = fCount + extra + 4;
            size += size >> 2;

            fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T));
#ifdef SK_DEBUG
            fData = (ArrayT*)fArray;
#endif
            fReserve = size;
        }
        fCount += extra;
    }
};

#endif


code:
/* libs/graphics/animator/SkTDArray_Experimental.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 SkTDArray_Experimental_DEFINED
#define SkTDArray_Experimental_DEFINED

#include "SkTypes.h"

#ifdef SK_BUILD_FOR_UNIX
#define SK_BUILD_FOR_ADS_12
#endif

#ifndef SK_BUILD_FOR_ADS_12
#define SK_SMALLER_ARRAY_TEMPLATE_EXPERIMENT 1
#else
#define SK_SMALLER_ARRAY_TEMPLATE_EXPERIMENT 0
#endif

#if SK_SMALLER_ARRAY_TEMPLATE_EXPERIMENT == 0
#include "SkTDArray.h"
#define SkIntArray(type) SkTDArray<type>
#define SkLongArray(type) SkTDArray<type>
#else

class SkDS32Array {
protected:
    SkDS32Array();
    SkDS32Array(const SkDS32Array& src);
    SkDS32Array(const int32_t src[], U16CPU count);
    SkDS32Array& operator=(const SkDS32Array& src);
    friend int operator==(const SkDS32Array& a, const SkDS32Array& b);
    int32_t* append() { return this->append(1, NULL); }
    int32_t* append(U16CPU count, const int32_t* src = NULL);

    int32_t* appendClear()
    {
        int32_t* result = this->append();
        *result = 0;
        return result;
    }

    int find(const int32_t& elem) const;
    int32_t* insert(U16CPU index, U16CPU count, const int32_t* src);
    int rfind(const int32_t& elem) const;
    void swap(SkDS32Array& other);
public:
    bool isEmpty() const { return fCount == 0; }
    int count() const { return fCount; }

    void remove(U16CPU index, U16CPU count = 1)
    {
        SkASSERT(index + count <= fCount);
        fCount = SkToU16(fCount - count);
        memmove(fArray + index, fArray + index + count, sizeof(int32_t) * (fCount - index));
    }

    void reset()
    {
        if (fArray)
        {
            sk_free(fArray);
            fArray = NULL;
#ifdef SK_DEBUG
            fData = NULL;
#endif
            fReserve = fCount = 0;
        }
        else
        {
            SkASSERT(fReserve == 0 && fCount == 0);
        }
    }

    void setCount(U16CPU count)
    {
        if (count > fReserve)
            this->growBy(count - fCount);
        else
            fCount = SkToU16(count);
    }
protected:
#ifdef SK_DEBUG
    enum {
        kDebugArraySize = 24
    };
    int32_t(* fData)[kDebugArraySize];
#endif
    int32_t*    fArray;
    uint16_t    fReserve, fCount;
    void growBy(U16CPU extra);
};

#ifdef SK_DEBUG
    #define SYNC() fTData = (T (*)[kDebugArraySize]) fArray
#else
    #define SYNC()
#endif

template <typename T> class SkTDS32Array : public SkDS32Array {
public:
    SkTDS32Array() { SkDEBUGCODE(fTData=NULL); SkASSERT(sizeof(T) == sizeof(int32_t)); }
    SkTDS32Array(const SkTDS32Array<T>& src) : SkDS32Array(src) {}
    ~SkTDS32Array() { sk_free(fArray); }
    T&  operator[](int index) const { SYNC(); SkASSERT((unsigned)index < fCount); return ((T*) fArray)[index]; }
    SkTDS32Array<T>& operator=(const SkTDS32Array<T>& src) {
        return (SkTDS32Array<T>&) SkDS32Array::operator=(src); }
    friend int operator==(const SkTDS32Array<T>& a, const SkTDS32Array<T>& b) {
        return operator==((const SkDS32Array&) a, (const SkDS32Array&) b); }
    T* append() { return (T*) SkDS32Array::append(); }
    T* appendClear() { return (T*) SkDS32Array::appendClear(); }
    T* append(U16CPU count, const T* src = NULL) { return (T*) SkDS32Array::append(count, (const int32_t*) src); }
    T*  begin() const { SYNC(); return (T*) fArray; }
    T*  end() const { return (T*) (fArray ? fArray + fCount : NULL); }
    int find(const T& elem) const { return SkDS32Array::find((const int32_t&) elem); }
    T* insert(U16CPU index) { return this->insert(index, 1, NULL); }
    T* insert(U16CPU index, U16CPU count, const T* src = NULL) {
        return (T*) SkDS32Array::insert(index, count, (const int32_t*) src); }
    int rfind(const T& elem) const { return SkDS32Array::rfind((const int32_t&) elem); }
    T*          push() { return this->append(); }
    void        push(T& elem) { *this->append() = elem; }
    const T&    top() const { return (*this)[fCount - 1]; }
    T&          top() { return (*this)[fCount - 1]; }
    void        pop(T* elem) { if (elem) *elem = (*this)[fCount - 1]; --fCount; }
    void        pop() { --fCount; }
private:
#ifdef SK_DEBUG
    mutable T(* fTData)[kDebugArraySize];
#endif
};

#define SkIntArray(type) SkTDS32Array<type> // holds 32 bit data types
#define SkLongArray(type) SkTDS32Array<type>    // holds 32/64 bit data types depending on pointer size

#endif // SK_SMALLER_ARRAY_TEMPLATE_EXPERIMENT

#endif // SkTDArray_Experimental_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 SkTDStack_DEFINED
#define SkTDStack_DEFINED

#include "SkTypes.h"

template <typename T> class SkTDStack : SkNoncopyable {
public:
    SkTDStack() : fCount(0), fTotalCount(0) {
        fInitialRec.fNext = NULL;
        fRec = &fInitialRec;

    //  fCount = kSlotCount;
    }

    ~SkTDStack() {
        Rec* rec = fRec;
        while (rec != &fInitialRec) {
            Rec* next = rec->fNext;
            sk_free(rec);
            rec = next;
        }
    }

    int count() const { return fTotalCount; }
    int depth() const { return fTotalCount; }
    bool empty() const { return fTotalCount == 0; }

    T* push() {
        SkASSERT(fCount <= kSlotCount);
        if (fCount == kSlotCount) {
            Rec* rec = (Rec*)sk_malloc_throw(sizeof(Rec));
            rec->fNext = fRec;
            fRec = rec;
            fCount = 0;
        }
        ++fTotalCount;
        return &fRec->fSlots[fCount++];
    }

    void push(const T& elem) { *this->push() = elem; }

    const T& index(int idx) const {
        SkASSERT(fRec && fCount > idx);
        return fRec->fSlots[fCount - idx - 1];
    }

    T& index(int idx) {
        SkASSERT(fRec && fCount > idx);
        return fRec->fSlots[fCount - idx - 1];
    }

    const T& top() const {
        SkASSERT(fRec && fCount > 0);
        return fRec->fSlots[fCount - 1];
    }

    T& top() {
        SkASSERT(fRec && fCount > 0);
        return fRec->fSlots[fCount - 1];
    }

    void pop(T* elem) {
        if (elem) {
            *elem = fRec->fSlots[fCount - 1];
        }
        this->pop();
    }

    void pop() {
        SkASSERT(fCount > 0 && fRec);
        --fTotalCount;
        if (--fCount == 0) {
            if (fRec != &fInitialRec) {
                Rec* rec = fRec->fNext;
                sk_free(fRec);
                fCount = kSlotCount;
                fRec = rec;
            } else {
                SkASSERT(fTotalCount == 0);
            }
        }
    }

private:
    enum {
        kSlotCount  = 8
    };

    struct Rec;
    friend struct Rec;

    struct Rec {
        Rec* fNext;
        T    fSlots[kSlotCount];
    };
    Rec     fInitialRec;
    Rec*    fRec;
    int     fCount, fTotalCount;
};

#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 SkTDict_DEFINED
#define SkTDict_DEFINED

#include "SkChunkAlloc.h"
#include "SkTSearch.h"
#include "SkTDArray.h"

template <typename T> class SkTDict : SkNoncopyable {
public:
    SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {}

    void reset()
    {
        fArray.reset();
        fStrings.reset();
    }

    int count() const { return fArray.count(); }

    bool set(const char name[], const T& value)
    {
        return set(name, strlen(name), value);
    }

    bool set(const char name[], size_t len, const T& value)
    {
        SkASSERT(name);

        int index = this->find_index(name, len);

        if (index >= 0)
        {
            fArray[index].fValue = value;
            return false;
        }
        else
        {
            Pair*   pair = fArray.insert(~index);
            char*   copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
            memcpy(copy, name, len);
            copy[len] = '\0';
            pair->fName = copy;
            pair->fValue = value;
            return true;
        }
    }

    bool find(const char name[]) const
    {
        return this->find_index(name) >= 0;
    }

    bool find(const char name[], size_t len) const
    {
        return this->find_index(name, len) >= 0;
    }

    bool find(const char name[], T* value) const
    {
        return find(name, strlen(name), value);
    }

    bool find(const char name[], size_t len, T* value) const
    {
        int index = this->find_index(name, len);

        if (index >= 0)
        {
            if (value)
                *value = fArray[index].fValue;
            return true;
        }
        return false;
    }

    bool findKey(T& value, const char** name) const
    {
        Pair* end = fArray.end();
        for (Pair* pair = fArray.begin(); pair < end; pair++) {
            if (pair->fValue != value)
                continue;
            *name = pair->fName;
            return true;
        }
        return false;
    }

public:
    struct Pair {
        const char* fName;
        T           fValue;

        friend int operator<(const Pair& a, const Pair& b)
        {
            return strcmp(a.fName, b.fName);
        }
        friend int operator!=(const Pair& a, const Pair& b)
        {
            return strcmp(a.fName, b.fName);
        }
    };
    friend class Iter;

public:
    class Iter {
    public:
        Iter(const SkTDict<T>& dict)
        {
            fIter = dict.fArray.begin();
            fStop = dict.fArray.end();
        }
        const char* next(T* value)
        {
            const char* name = NULL;
            if (fIter < fStop)
            {
                name = fIter->fName;
                if (value)
                    *value = fIter->fValue;
                fIter += 1;
            }
            return name;
        }
    private:
        Pair*   fIter;
        Pair*   fStop;
    };

private:
    SkTDArray<Pair> fArray;
    SkChunkAlloc    fStrings;

    int find_index(const char name[]) const
    {
        return find_index(name, strlen(name));
    }

    int find_index(const char name[], size_t len) const
    {
        SkASSERT(name);

        int count = fArray.count();
        int index = ~0;

        if (count)
            index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair));
        return index;
    }
    friend class Iter;
};

#endif


code:
/*
    Copyright 2011 Google Inc.

    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 SkTLazy_DEFINED
#define SkTLazy_DEFINED

#include "SkTypes.h"

/**
 *  Efficient way to defer allocating/initializing a class until it is needed
 *  (if ever).
 */
template <typename T> class SkTLazy {
public:
    SkTLazy() : fPtr(NULL) {}

    explicit SkTLazy(const T* src) : fPtr(NULL) {
        if (src) {
            fPtr = new (fStorage) T(*src);
        }
    }

    SkTLazy(const SkTLazy<T>& src) : fPtr(NULL) {
        const T* ptr = src.get();
        if (ptr) {
            fPtr = new (fStorage) T(*ptr);
        }
    }

    ~SkTLazy() {
        if (fPtr) {
            fPtr->~T();
        }
    }

    /**
     *  Return a pointer to a default-initialized instance of the class. If a
     *  previous instance had been initialzied (either from init() or set()) it
     *  will first be destroyed, so that a freshly initialized instance is
     *  always returned.
     */
    T* init() {
        if (fPtr) {
            fPtr->~T();
        }
        fPtr = new (fStorage) T;
        return fPtr;
    }

    /**
     *  Copy src into this, and return a pointer to a copy of it. Note this
     *  will always return the same pointer, so if it is called on a lazy that
     *  has already been initialized, then this will copy over the previous
     *  contents.
     */
    T* set(const T& src) {
        if (fPtr) {
            *fPtr = src;
        } else {
            fPtr = new (fStorage) T(src);
        }
        return fPtr;
    }

    /**
     *  Returns either NULL, or a copy of the object that was passed to
     *  set() or the constructor.
     */
    T* get() const { return fPtr; }

private:
    T*   fPtr; // NULL or fStorage
    char fStorage[sizeof(T)];
};

#endif


code:
/*
 * Copyright 2009, 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 SkTRegistry_DEFINED
#define SkTRegistry_DEFINED

#include "SkTypes.h"

/** Template class that registers itself (in the constructor) into a linked-list
    and provides a function-pointer. This can be used to auto-register a set of
    services, e.g. a set of image codecs.
 */
template <typename T, typename P> class SkTRegistry : SkNoncopyable {
public:
    typedef T (*Factory)(P);

    SkTRegistry(Factory fact) {
#ifdef ANDROID
        // work-around for double-initialization bug
        {
            SkTRegistry* reg = gHead;
            while (reg) {
                if (reg == this) {
                    return;
                }
                reg = reg->fChain;
            }
        }
#endif
        fFact = fact;
        fChain = gHead;
        gHead = this;
    }

    static const SkTRegistry* Head() { return gHead; }

    const SkTRegistry* next() const { return fChain; }
    Factory factory() const { return fFact; }

private:
    Factory      fFact;
    SkTRegistry* fChain;

    static SkTRegistry* gHead;
};

// The caller still needs to declare an instance of this somewhere
template <typename T, typename P> SkTRegistry<T, P>* SkTRegistry<T, P>::gHead;

#endif


code:
/*
 * Copyright (C) 2011 Google Inc.
 *
 * 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 SkTScopedPtr_DEFINED
#define SkTScopedPtr_DEFINED

#include "SkTypes.h"

/** \class SkTScopedPtr
  A SkTScopedPtr<T> is like a T*, except that the destructor of SkTScopedPtr<T>
  automatically deletes the pointer it holds (if any).  That is, SkTScopedPtr<T>
  owns the T object that it points to.  Like a T*, a SkTScopedPtr<T> may hold
  either NULL or a pointer to a T object.  Also like T*, SkTScopedPtr<T> is
  thread-compatible, and once you dereference it, you get the threadsafety
  guarantees of T.

  The size of a SkTScopedPtr is small: sizeof(SkTScopedPtr<T>) == sizeof(T*)
*/
template <typename T> class SkTScopedPtr : SkNoncopyable {
public:
    explicit SkTScopedPtr(T* o = NULL) : fObj(o) {}
    ~SkTScopedPtr() {
        enum { kTypeMustBeComplete = sizeof(T) };
        delete fObj;
    }

    /** Delete the current object, if any.  Then take ownership of the
        passed object.
     */
    void reset(T* o = NULL) {
        if (o != fObj) {
            enum { kTypeMustBeComplete = sizeof(T) };
            delete fObj;
            fObj = o;
        }
    }

    /** Without deleting the current object, return it and forget about it.
        Similar to calling get() and reset(), but the object is not deleted.
     */
    T* release() {
        T* retVal = fObj;
        fObj = NULL;
        return retVal;
    }

    T& operator*() const {
        SkASSERT(fObj != NULL);
        return *fObj;
    }
    T* operator->() const  {
        SkASSERT(fObj != NULL);
        return fObj;
    }
    T* get() const { return fObj; }

    bool operator==(T* o) const { return fObj == o; }
    bool operator!=(T* o) const { return fObj != o; }

private:
    T* fObj;

    // Forbid comparison of SkTScopedPtr types.  If T2 != T, it doesn't make
    // sense, and if T2 == T, it still doesn't make sense because the same
    // object can't be owned by two different scoped_ptrs.
    template <class T2> bool operator==(SkTScopedPtr<T2> const& o2) const;
    template <class T2> bool operator!=(SkTScopedPtr<T2> const& o2) const;
};

#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 SkTSearch_DEFINED
#define SkTSearch_DEFINED

#include "SkTypes.h"

template <typename T>
int SkTSearch(const T* base, int count, const T& target, size_t elemSize)
{
    SkASSERT(count >= 0);
    if (count <= 0)
        return ~0;

    SkASSERT(base != NULL); // base may be NULL if count is zero

    int lo = 0;
    int hi = count - 1;

    while (lo < hi)
    {
        int mid = (hi + lo) >> 1;
        const T* elem = (const T*)((const char*)base + mid * elemSize);

        if (*elem < target)
            lo = mid + 1;
        else
            hi = mid;
    }

    const T* elem = (const T*)((const char*)base + hi * elemSize);
    if (*elem != target)
    {
        if (*elem < target)
            hi += 1;
        hi = ~hi;
    }
    return hi;
}

template <typename T>
int SkTSearch(const T* base, int count, const T& target, size_t elemSize,
              int (*compare)(const T&, const T&))
{
    SkASSERT(count >= 0);
    if (count <= 0) {
        return ~0;
    }

    SkASSERT(base != NULL); // base may be NULL if count is zero

    int lo = 0;
    int hi = count - 1;

    while (lo < hi) {
        int mid = (hi + lo) >> 1;
        const T* elem = (const T*)((const char*)base + mid * elemSize);

        if ((*compare)(*elem, target) < 0)
            lo = mid + 1;
        else
            hi = mid;
    }

    const T* elem = (const T*)((const char*)base + hi * elemSize);
    int pred = (*compare)(*elem, target);
    if (pred != 0) {
        if (pred < 0)
            hi += 1;
        hi = ~hi;
    }
    return hi;
}

template <typename T>
int SkTSearch(const T** base, int count, const T* target, size_t elemSize,
    int (*compare)(const T*, const T*))
{
    SkASSERT(count >= 0);
    if (count <= 0)
        return ~0;

    SkASSERT(base != NULL); // base may be NULL if count is zero

    int lo = 0;
    int hi = count - 1;

    while (lo < hi)
    {
        int mid = (hi + lo) >> 1;
        const T* elem = *(const T**)((const char*)base + mid * elemSize);

        if ((*compare)(elem, target) < 0)
            lo = mid + 1;
        else
            hi = mid;
    }

    const T* elem = *(const T**)((const char*)base + hi * elemSize);
    int pred = (*compare)(elem, target);
    if (pred != 0)
    {
        if (pred < 0)
            hi += 1;
        hi = ~hi;
    }
    return hi;
}

int SkStrSearch(const char*const* base, int count, const char target[],
                size_t target_len, size_t elemSize);
int SkStrSearch(const char*const* base, int count, const char target[],
                size_t elemSize);

/** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that
    base points to a table of lower-case strings.
*/
int SkStrLCSearch(const char*const* base, int count, const char target[],
                  size_t target_len, size_t elemSize);
int SkStrLCSearch(const char*const* base, int count, const char target[],
                  size_t elemSize);

/** Helper class to convert a string to lower-case, but only modifying the ascii
    characters. This makes the routine very fast and never changes the string
    length, but it is not suitable for linguistic purposes. Normally this is
    used for buiding and searching string tables.
*/
class SkAutoAsciiToLC {
public:
    SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1);
    ~SkAutoAsciiToLC();

    const char* lc() const { return fLC; }
    size_t      length() const { return fLength; }

private:
    char*   fLC;    // points to either the heap or fStorage
    size_t  fLength;
    enum {
        STORAGE = 64
    };
    char    fStorage[STORAGE+1];
};

extern "C" {
    typedef int (*SkQSortCompareProc)(const void*, const void*);
    void SkQSort(void* base, size_t count, size_t elemSize, SkQSortCompareProc);
}

#endif


code:
/* libs/graphics/sgl/SkTSort.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 SkTSort_DEFINED
#define SkTSort_DEFINED

#include "SkTypes.h"

template <typename T>
void SkTHeapSort_SiftDown(T array[], int root, int bottom) {
    while (root*2 + 1 <= bottom) {
        int child = root * 2 + 1;
        if (child+1 <= bottom && array[child] < array[child+1]) {
            child += 1;
        }
        if (array[root] < array[child]) {
            SkTSwap<T>(array[root], array[child]);
            root = child;
        } else {
            break;
        }
    }
}

template <typename T> void SkTHeapSort(T array[], int count) {
    int i;
    for (i = count/2 - 1; i >= 0; --i) {
        SkTHeapSort_SiftDown<T>(array, i, count-1);
    }
    for (i = count - 1; i > 0; --i) {
        SkTSwap<T>(array[0], array[i]);
        SkTHeapSort_SiftDown<T>(array, 0, i-1);
    }
}

#endif