grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/animator/SkAnimator.h b/include/animator/SkAnimator.h
new file mode 100644
index 0000000..04d342c
--- /dev/null
+++ b/include/animator/SkAnimator.h
@@ -0,0 +1,508 @@
+/*
+ * 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 SkAnimator_DEFINED
+#define SkAnimator_DEFINED
+
+#include "SkScalar.h"
+#include "SkKey.h"
+#include "SkEventSink.h"
+
+class SkAnimateMaker;
+class SkCanvas;
+class SkDisplayable;
+class SkEvent;
+class SkExtras;
+struct SkMemberInfo;
+class SkPaint;
+struct SkRect;
+class SkStream;
+class SkTypedArray;
+class SkXMLParserError;
+class SkDOM;
+struct SkDOMNode;
+
+/** SkElementType is the type of element: a rectangle, a color, an animator, and so on.
+    This enum is incomplete and will be fleshed out in a future release */
+enum SkElementType {
+    kElementDummyType
+};
+/** SkFieldType is the type of field: a scalar, a string, an integer, a boolean, and so on.
+    This enum is incomplete and will be fleshed out in a future release */
+enum SkFieldType {
+    kFieldDummyType
+};
+
+/** \class SkAnimator
+
+    The SkAnimator class decodes an XML stream into a display list. The
+    display list can be drawn statically as a picture, or can drawn 
+    different elements at different times to form a moving animation.
+
+    SkAnimator does not read the system time on its own; it relies on the
+    caller to pass the current time. The caller can pause, speed up, or
+    reverse the animation by varying the time passed in.
+
+    The XML describing the display list must conform to the schema 
+    described by SkAnimateSchema.xsd. 
+
+    The XML must contain an <event> element to draw. Usually, it contains
+    an <event kind="onload" /> block to add some drawing elements to the
+    display list when the document is first decoded.
+
+    Here's an "Hello World" XML sample:
+
+    <screenplay>
+        <event kind="onload" >
+            <text text="Hello World" y="20" />
+        </event>
+    </screenplay>
+
+    To read and draw this sample:
+
+        // choose one of these two
+        SkAnimator animator; // declare an animator instance on the stack
+    //  SkAnimator* animator = new SkAnimator() // or one could instantiate the class
+
+        // choose one of these three
+        animator.decodeMemory(buffer, size); // to read from RAM
+        animator.decodeStream(stream); // to read from a user-defined stream (e.g., a zip file)
+        animator.decodeURI(filename); // to read from a web location, or from a local text file
+
+        // to draw to the current window:
+        SkCanvas canvas(getBitmap()); // create a canvas
+        animator.draw(canvas, &paint, 0); // draw the scene
+*/
+class SkAnimator : public SkEventSink {
+public:
+    SkAnimator();
+    virtual ~SkAnimator();
+
+    /** Add a drawable extension to the graphics engine. Experimental. 
+        @param extras A derived class that implements methods that identify and instantiate the class
+    */
+    void addExtras(SkExtras* extras);
+
+    /** Read in XML from a stream, and append it to the current
+        animator. Returns false if an error was encountered.
+        Error diagnostics are stored in fErrorCode and fLineNumber.
+        @param stream  The stream to append.
+        @return true if the XML was parsed successfully.
+    */
+    bool appendStream(SkStream* stream);
+
+    /** Read in XML from memory. Returns true if the file can be 
+        read without error. Returns false if an error was encountered.
+        Error diagnostics are stored in fErrorCode and fLineNumber.
+        @param buffer  The XML text as UTF-8 characters.
+        @param size  The XML text length in bytes.
+        @return true if the XML was parsed successfully.
+    */
+    bool decodeMemory(const void* buffer, size_t size);
+
+    /** Read in XML from a stream. Returns true if the file can be 
+        read without error. Returns false if an error was encountered.
+        Error diagnostics are stored in fErrorCode and fLineNumber.
+        @param stream  The stream containg the XML text as UTF-8 characters.
+        @return true if the XML was parsed successfully.
+    */
+    virtual bool decodeStream(SkStream* stream);
+
+    /** Parse the DOM tree starting at the specified node. Returns true if it can be 
+        parsed without error. Returns false if an error was encountered.
+        Error diagnostics are stored in fErrorCode and fLineNumber.
+        @return true if the DOM was parsed successfully.
+    */
+    virtual bool decodeDOM(const SkDOM&, const SkDOMNode*);
+
+    /** Read in XML from a URI. Returns true if the file can be 
+        read without error. Returns false if an error was encountered.
+        Error diagnostics are stored in fErrorCode and fLineNumber.
+        @param uri The complete url path to be read (either ftp, http or https).
+        @return true if the XML was parsed successfully.
+    */
+    bool decodeURI(const char uri[]);
+
+    /** Pass a char event, usually a keyboard symbol, to the animator.
+        This triggers events of the form <event kind="keyChar" key="... />
+        @param ch  The character to match against <event> element "key" 
+            attributes.
+        @return true if the event was dispatched successfully.
+    */
+    bool doCharEvent(SkUnichar ch);
+
+    /** Experimental:
+        Pass a mouse click event along with the mouse coordinates to 
+        the animator. This triggers events of the form <event kind="mouseDown" ... />
+        and other mouse events.
+        @param state The mouse state, described by SkView::Click::State : values are
+        down == 0, moved == 1, up == 2
+        @param x    The x-position of the mouse
+        @param y The y-position of the mouse
+        @return true if the event was dispatched successfully.
+    */
+    bool doClickEvent(int state, SkScalar x, SkScalar y);
+
+    /** Pass a meta-key event, such as an arrow , to the animator.
+        This triggers events of the form <event kind="keyPress" code="... />
+        @param code  The key to match against <event> element "code" 
+            attributes.
+        @return true if the event was dispatched successfully.
+    */
+    bool doKeyEvent(SkKey code);
+    bool doKeyUpEvent(SkKey code);
+    
+    /** Send an event to the animator. The animator's clock is set 
+        relative to the current time.
+        @return true if the event was dispatched successfully.
+    */
+    bool doUserEvent(const SkEvent& evt);
+
+    /** The possible results from the draw function. 
+    */
+    enum DifferenceType {
+        kNotDifferent,
+        kDifferent,
+        kPartiallyDifferent
+    };
+    /** Draws one frame of the animation. The first call to draw always 
+        draws the initial frame of the animation. Subsequent calls draw 
+        the offset into the animation by 
+        subtracting the initial time from the current time.
+        @param canvas  The canvas to draw into.
+        @param paint     The paint to draw with.
+        @param time  The offset into the current animation.
+        @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and
+        kPartiallyDifferent if the document contains an active <bounds> element that specifies a minimal 
+        redraw area.
+    */
+    DifferenceType draw(SkCanvas* canvas, SkPaint* paint, SkMSec time);
+
+    /** Draws one frame of the animation, using a new Paint each time.
+        The first call to draw always 
+        draws the initial frame of the animation. Subsequent calls draw 
+        the offset into the animation by 
+        subtracting the initial time from the current time.
+        @param canvas  The canvas to draw into.
+        @param time  The offset into the current animation.
+        @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and
+        kPartiallyDifferent if the document contains an active <bounds> element that specifies a minimal 
+        redraw area.
+    */
+    DifferenceType draw(SkCanvas* canvas, SkMSec time);
+
+    /** Experimental:
+        Helper to choose whether to return a SkView::Click handler.
+        @param x ignored
+        @param y ignored
+        @return true if a mouseDown event handler is enabled.
+    */
+    bool findClickEvent(SkScalar x, SkScalar y); 
+
+
+    /** Get the nested animator associated with this element, if any.
+        Use this to access a movie's event sink, to send events to movies.
+        @param element the value returned by getElement
+        @return the internal animator.
+    */
+    const SkAnimator* getAnimator(const SkDisplayable* element) const;
+
+    /** Returns the scalar value of the specified element's attribute[index]
+        @param element the value returned by getElement
+        @param field the value returned by getField
+        @param index the array entry
+        @return the integer value to retrieve, or SK_NaN32 if unsuccessful
+    */
+    int32_t getArrayInt(const SkDisplayable* element, const SkMemberInfo* field, int index);
+
+    /** Returns the scalar value of the specified element's attribute[index]
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param index the array entry
+        @return the integer value to retrieve, or SK_NaN32 if unsuccessful
+    */
+    int32_t getArrayInt(const char* elementID, const char* fieldName, int index);
+
+    /** Returns the scalar value of the specified element's attribute[index]
+        @param element the value returned by getElement
+        @param field the value returned by getField
+        @param index the array entry
+        @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful
+    */
+    SkScalar getArrayScalar(const SkDisplayable* element, const SkMemberInfo* field, int index);
+
+    /** Returns the scalar value of the specified element's attribute[index]
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param index the array entry
+        @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful
+    */
+    SkScalar getArrayScalar(const char* elementID, const char* fieldName, int index);
+
+    /** Returns the string value of the specified element's attribute[index]
+        @param element is a value returned by getElement
+        @param field is a value returned by getField  
+        @param index the array entry
+        @return the string value to retrieve, or null if unsuccessful
+    */
+    const char* getArrayString(const SkDisplayable* element, const SkMemberInfo* field, int index);
+
+    /** Returns the string value of the specified element's attribute[index]
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param index the array entry
+        @return the string value to retrieve, or null if unsuccessful
+    */
+    const char* getArrayString(const char* elementID, const char* fieldName, int index);
+
+    /** Returns the XML element corresponding to the given ID.
+        @param elementID is the value of the id attribute in the XML of this element 
+        @return the element matching the ID, or null if the element can't be found
+    */
+    const SkDisplayable* getElement(const char* elementID);
+
+    /** Returns the element type corresponding to the XML element.
+        The element type matches the element name; for instance, <line> returns kElement_LineType
+        @param element is a value returned by getElement  
+        @return element type, or 0 if the element can't be found
+    */
+    SkElementType getElementType(const SkDisplayable* element);
+
+    /** Returns the element type corresponding to the given ID.
+        @param elementID is the value of the id attribute in the XML of this element 
+        @return element type, or 0 if the element can't be found
+    */
+    SkElementType getElementType(const char* elementID);
+
+    /** Returns the XML field of the named attribute in the XML element.
+        @param element is a value returned by getElement
+        @param fieldName is the attribute to return  
+        @return the attribute matching the fieldName, or null if the element can't be found
+    */
+    const SkMemberInfo* getField(const SkDisplayable* element, const char* fieldName);
+
+    /** Returns the XML field of the named attribute in the XML element matching the elementID.
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName is the attribute to return  
+        @return the attribute matching the fieldName, or null if the element can't be found
+    */
+    const SkMemberInfo* getField(const char* elementID, const char* fieldName);
+
+    /** Returns the value type coresponding to the element's attribute.
+        The value type matches the XML schema: and may be kField_BooleanType, kField_ScalarType, etc.
+        @param field is a value returned by getField  
+        @return the attribute type, or 0 if the element can't be found
+    */
+    SkFieldType getFieldType(const SkMemberInfo* field);
+
+    /** Returns the value type coresponding to the element's attribute.
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @return the attribute type, or 0 if the element can't be found
+    */
+    SkFieldType getFieldType(const char* elementID, const char* fieldName);
+
+    /** Returns the recommended animation interval. Returns zero if no
+        interval is specified.
+    */
+    SkMSec getInterval();
+
+    /** Returns the partial rectangle to invalidate after drawing. Call after draw() returns
+    kIsPartiallyDifferent to do a mimimal inval(). */
+    void getInvalBounds(SkRect* inval); 
+
+    /** Returns the details of any error encountered while parsing the XML. 
+    */
+    const SkXMLParserError* getParserError();
+    
+    /** Returns the details of any error encountered while parsing the XML as string. 
+    */
+    const char* getParserErrorString();
+    
+    /** Returns the scalar value of the specified element's attribute
+        @param element is a value returned by getElement
+        @param field is a value returned by getField  
+        @return the integer value to retrieve, or SK_NaN32 if not found
+    */
+    int32_t getInt(const SkDisplayable* element, const SkMemberInfo* field);
+
+    /** Returns the scalar value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @return the integer value to retrieve, or SK_NaN32 if not found
+    */
+    int32_t getInt(const char* elementID, const char* fieldName);
+
+    /** Returns the scalar value of the specified element's attribute
+        @param element is a value returned by getElement
+        @param field is a value returned by getField  
+        @return the scalar value to retrieve, or SK_ScalarNaN if not found
+    */
+    SkScalar getScalar(const SkDisplayable* element, const SkMemberInfo* field);
+
+    /** Returns the scalar value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @return the scalar value to retrieve, or SK_ScalarNaN if not found
+    */
+    SkScalar getScalar(const char* elementID, const char* fieldName);
+
+    /** Returns the string value of the specified element's attribute
+        @param element is a value returned by getElement
+        @param field is a value returned by getField  
+        @return the string value to retrieve, or null if not found
+    */
+    const char* getString(const SkDisplayable* element, const SkMemberInfo* field);
+
+    /** Returns the string value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @return the string value to retrieve, or null if not found
+    */
+    const char* getString(const char* elementID, const char* fieldName);
+
+    /** Gets the file default directory of the URL base path set explicitly or by reading the last URL. */
+    const char* getURIBase();
+
+    /** Resets the animator to a newly created state with no animation data. */
+    void initialize();
+
+    /** Experimental. Resets any active animations so that the next time passed is treated as 
+        time zero. */
+    void reset();
+    
+    /** Sets the scalar value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param array is the c-style array of integers
+        @param count is the length of the array
+        @return true if the value was set successfully
+    */
+    bool setArrayInt(const char* elementID, const char* fieldName, const int* array, int count);
+    
+    /** Sets the scalar value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param array is the c-style array of strings
+        @param count is the length of the array
+        @return true if the value was set successfully
+    */
+    bool setArrayString(const char* elementID, const char* fieldName, const char** array, int count);
+    
+    /** Sets the scalar value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param data the integer value to set
+        @return true if the value was set successfully
+    */
+    bool setInt(const char* elementID, const char* fieldName, int32_t data);
+
+    /** Sets the scalar value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param data the scalar value to set
+        @return true if the value was set successfully
+    */
+    bool setScalar(const char* elementID, const char* fieldName, SkScalar data);
+
+    /** Sets the string value of the specified element's attribute
+        @param elementID is the value of the id attribute in the XML of this element
+        @param fieldName specifies the name of the attribute  
+        @param data the string value to set
+        @return true if the value was set successfully
+    */
+    bool setString(const char* elementID, const char* fieldName, const char* data);
+
+    /** Sets the file default directory of the URL base path 
+        @param path the directory path 
+    */
+    void setURIBase(const char* path);
+
+    typedef void* Handler;
+    // This guy needs to be exported to java, so don't make it virtual
+    void setHostHandler(Handler handler) {
+        this->onSetHostHandler(handler);
+    }
+
+    /** \class Timeline
+    Returns current time to animator. To return a custom timeline, create a child
+    class and override the getMSecs method.
+    */
+    class Timeline {
+    public:
+        virtual ~Timeline() {}
+
+        /** Returns the current time in milliseconds */
+        virtual SkMSec getMSecs() const = 0;
+    };
+
+    /** Sets a user class to return the current time to the animator. 
+        Optional; if not called, the system clock will be used by calling SkTime::GetMSecs instead.
+        @param callBack the time function
+    */
+    void setTimeline(const Timeline& );
+
+    static void Init(bool runUnitTests);
+    static void Term();
+    
+    /** The event sink events generated by the animation are posted to. 
+        Screenplay also posts an inval event to this event sink after processing an
+        event to force a redraw.
+        @param target the event sink id
+    */
+    void setHostEventSinkID(SkEventSinkID hostID);
+    SkEventSinkID getHostEventSinkID() const;
+    
+    // helper
+    void setHostEventSink(SkEventSink* sink) {
+        this->setHostEventSinkID(sink ? sink->getSinkID() : 0);
+    }
+    
+    virtual void setJavaOwner(Handler owner);
+    
+#ifdef SK_DEBUG
+    virtual void eventDone(const SkEvent& evt);
+    virtual bool isTrackingEvents();
+    static bool NoLeaks();
+#endif  
+    
+protected:
+    virtual void onSetHostHandler(Handler handler);
+    virtual void onEventPost(SkEvent*, SkEventSinkID);
+    virtual void onEventPostTime(SkEvent*, SkEventSinkID, SkMSec time);
+
+private:
+// helper functions for setters
+    bool setArray(SkDisplayable* element, const SkMemberInfo* field, SkTypedArray array);
+    bool setArray(const char* elementID, const char* fieldName, SkTypedArray array);
+    bool setInt(SkDisplayable* element, const SkMemberInfo* field, int32_t data);
+    bool setScalar(SkDisplayable* element, const SkMemberInfo* field, SkScalar data);
+    bool setString(SkDisplayable* element, const SkMemberInfo* field, const char* data);
+    
+    virtual bool onEvent(const SkEvent&);
+    SkAnimateMaker* fMaker;
+    friend class SkAnimateMaker;
+    friend class SkAnimatorScript;
+    friend class SkAnimatorScript2;
+    friend class SkApply;
+    friend class SkDisplayMovie;
+    friend class SkDisplayType;
+    friend class SkPost;
+    friend class SkXMLAnimatorWriter;
+};
+
+#endif
+
diff --git a/include/animator/SkAnimatorView.h b/include/animator/SkAnimatorView.h
new file mode 100644
index 0000000..3c6c8a1
--- /dev/null
+++ b/include/animator/SkAnimatorView.h
@@ -0,0 +1,47 @@
+/*
+ * 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 SkAnimatorView_DEFINED
+#define SkAnimatorView_DEFINED
+
+#include "SkView.h"
+#include "SkAnimator.h"
+
+class SkAnimatorView : public SkView {
+public:
+            SkAnimatorView();
+    virtual ~SkAnimatorView();
+
+    SkAnimator* getAnimator() const { return fAnimator; }
+
+    bool    decodeFile(const char path[]);
+    bool    decodeMemory(const void* buffer, size_t size);
+    bool    decodeStream(SkStream* stream);
+
+protected:
+    // overrides
+    virtual bool onEvent(const SkEvent&);
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+    SkAnimator* fAnimator;
+
+    typedef SkView INHERITED;
+};
+
+#endif
+
diff --git a/include/core/Sk64.h b/include/core/Sk64.h
new file mode 100644
index 0000000..c4ae41e
--- /dev/null
+++ b/include/core/Sk64.h
@@ -0,0 +1,245 @@
+/*
+ * 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 Sk64_DEFINED
+#define Sk64_DEFINED
+
+#include "SkFixed.h"
+#include "SkMath.h"
+
+/** \class Sk64
+
+    Sk64 is a 64-bit math package that does not require long long support from the compiler.
+*/
+struct Sk64 {
+    int32_t  fHi;   //!< the high 32 bits of the number (including sign)
+    uint32_t fLo;   //!< the low 32 bits of the number
+
+    /** Returns non-zero if the Sk64 can be represented as a signed 32 bit integer
+    */
+    SkBool is32() const { return fHi == ((int32_t)fLo >> 31); }
+
+    /** Returns non-zero if the Sk64 cannot be represented as a signed 32 bit integer
+    */
+    SkBool is64() const { return fHi != ((int32_t)fLo >> 31); }
+
+    /** Returns non-zero if the Sk64 can be represented as a signed 48 bit integer. Used to know
+        if we can shift the value down by 16 to treat it as a SkFixed.
+    */
+    SkBool isFixed() const;
+
+    /** Return the signed 32 bit integer equivalent. Asserts that is32() returns non-zero.
+    */
+    int32_t get32() const { SkASSERT(this->is32()); return (int32_t)fLo; }
+
+    /** Return the number >> 16. Asserts that this does not loose any significant high bits.
+    */
+    SkFixed getFixed() const {
+        SkASSERT(this->isFixed());
+
+        uint32_t sum = fLo + (1 << 15);
+        int32_t  hi = fHi;
+        if (sum < fLo) {
+            hi += 1;
+        }
+        return (hi << 16) | (sum >> 16);
+    }
+
+    /** Return the number >> 30. Asserts that this does not loose any
+        significant high bits.
+    */
+    SkFract getFract() const;
+
+    /** Returns the square-root of the number as a signed 32 bit value. */
+    int32_t getSqrt() const;
+
+    /** Returns the number of leading zeros of the absolute value of this.
+        Will return in the range [0..64]
+    */
+    int getClzAbs() const;
+
+    /** Returns non-zero if the number is zero */
+    SkBool  isZero() const { return (fHi | fLo) == 0; }
+
+    /** Returns non-zero if the number is non-zero */
+    SkBool  nonZero() const { return fHi | fLo; }
+
+    /** Returns non-zero if the number is negative (number < 0) */
+    SkBool  isNeg() const { return (uint32_t)fHi >> 31; }
+
+    /** Returns non-zero if the number is positive (number > 0) */
+    SkBool  isPos() const { return ~(fHi >> 31) & (fHi | fLo); }
+
+    /** Returns -1,0,+1 based on the sign of the number */
+    int     sign() const { return (fHi >> 31) | Sk32ToBool(fHi | fLo); }
+
+    /** Negate the number */
+    void    negate();
+
+    /** If the number < 0, negate the number
+    */
+    void    abs();
+
+    /** Returns the number of bits needed to shift the Sk64 to the right
+        in order to make it fit in a signed 32 bit integer.
+    */
+    int     shiftToMake32() const;
+
+    /** Set the number to zero */
+    void    setZero() { fHi = fLo = 0; }
+
+    /** Set the high and low 32 bit values of the number */
+    void    set(int32_t hi, uint32_t lo) { fHi = hi; fLo = lo; }
+
+    /** Set the number to the specified 32 bit integer */
+    void    set(int32_t a) { fHi = a >> 31; fLo = a; }
+
+    /** Set the number to the product of the two 32 bit integers */
+    void    setMul(int32_t a, int32_t b);
+
+    /** extract 32bits after shifting right by bitCount.
+        Note: itCount must be [0..63].
+        Asserts that no significant high bits were lost.
+    */
+    int32_t getShiftRight(unsigned bitCount) const;
+
+    /** Shift the number left by the specified number of bits.
+        @param bits How far to shift left, must be [0..63]
+    */
+    void    shiftLeft(unsigned bits);
+
+    /** Shift the number right by the specified number of bits.
+        @param bits How far to shift right, must be [0..63]. This
+        performs an arithmetic right-shift (sign extending).
+    */
+    void    shiftRight(unsigned bits);
+
+    /** Shift the number right by the specified number of bits, but
+        round the result.
+        @param bits How far to shift right, must be [0..63]. This
+        performs an arithmetic right-shift (sign extending).
+    */
+    void    roundRight(unsigned bits);
+
+    /** Add the specified 32 bit integer to the number */
+    void add(int32_t lo) {
+        int32_t  hi = lo >> 31; // 0 or -1
+        uint32_t sum = fLo + (uint32_t)lo;
+
+        fHi = fHi + hi + (sum < fLo);
+        fLo = sum;
+    }
+    
+    /** Add the specified Sk64 to the number */
+    void add(int32_t hi, uint32_t lo) {
+        uint32_t sum = fLo + lo;
+
+        fHi = fHi + hi + (sum < fLo);
+        fLo = sum;
+    }
+    
+    /** Add the specified Sk64 to the number */
+    void    add(const Sk64& other) { this->add(other.fHi, other.fLo); }
+    
+    /** Subtract the specified Sk64 from the number. (*this) = (*this) - num
+    */
+    void    sub(const Sk64& num);
+    
+    /** Subtract the number from the specified Sk64. (*this) = num - (*this)
+    */
+    void    rsub(const Sk64& num);
+    
+    /** Multiply the number by the specified 32 bit integer
+    */
+    void    mul(int32_t);
+
+    enum DivOptions {
+        kTrunc_DivOption,   //!< truncate the result when calling div()
+        kRound_DivOption    //!< round the result when calling div()
+    };
+    
+    /** Divide the number by the specified 32 bit integer, using the specified
+        divide option (either truncate or round).
+    */
+    void    div(int32_t, DivOptions);
+
+    /** return (this + other >> 16) as a 32bit result */
+    SkFixed addGetFixed(const Sk64& other) const {
+        return this->addGetFixed(other.fHi, other.fLo);
+    }
+
+    /** return (this + Sk64(hi, lo) >> 16) as a 32bit result */
+    SkFixed addGetFixed(int32_t hi, uint32_t lo) const {
+#ifdef SK_DEBUG
+        Sk64    tmp(*this);
+        tmp.add(hi, lo);
+#endif
+
+        uint32_t sum = fLo + lo;
+        hi += fHi + (sum < fLo);
+        lo = sum;
+
+        sum = lo + (1 << 15);
+        if (sum < lo)
+            hi += 1;
+
+        hi = (hi << 16) | (sum >> 16);
+        SkASSERT(hi == tmp.getFixed());
+        return hi;
+    }
+
+    /** Return the result of dividing the number by denom, treating the answer
+        as a SkFixed. (*this) << 16 / denom. It is an error for denom to be 0.
+    */
+    SkFixed getFixedDiv(const Sk64& denom) const;
+
+    friend bool operator==(const Sk64& a, const Sk64& b) {
+        return a.fHi == b.fHi && a.fLo == b.fLo;
+    }
+
+    friend bool operator!=(const Sk64& a, const Sk64& b) {
+        return a.fHi != b.fHi || a.fLo != b.fLo;
+    }
+    
+    friend bool operator<(const Sk64& a, const Sk64& b) {
+        return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo < b.fLo);
+    }
+    
+    friend bool operator<=(const Sk64& a, const Sk64& b) {
+        return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo <= b.fLo);
+    }
+    
+    friend bool operator>(const Sk64& a, const Sk64& b) {
+        return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo > b.fLo);
+    }
+    
+    friend bool operator>=(const Sk64& a, const Sk64& b) {
+        return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo >= b.fLo);
+    }
+
+#ifdef SkLONGLONG
+    SkLONGLONG getLongLong() const;
+#endif
+
+#ifdef SK_DEBUG
+  /** @cond UNIT_TEST */
+    static void UnitTest();
+  /** @endcond */
+#endif
+};
+
+#endif
+
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
new file mode 100644
index 0000000..02c8cd9
--- /dev/null
+++ b/include/core/SkBitmap.h
@@ -0,0 +1,684 @@
+/*
+ * 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 SkBitmap_DEFINED
+#define SkBitmap_DEFINED
+
+#include "Sk64.h"
+#include "SkColor.h"
+#include "SkPoint.h"
+#include "SkRefCnt.h"
+
+#if defined(SK_BUILD_FOR_MAC)
+#include <carbon/carbon.h>
+#endif
+
+struct SkIRect;
+class SkColorTable;
+class SkPaint;
+class SkPixelRef;
+class SkRegion;
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+
+/** \class SkBitmap
+
+    The SkBitmap class specifies a raster bitmap. A bitmap has an integer width
+    and height, and a format (config), and a pointer to the actual pixels.
+    Bitmaps can be drawn into a SkCanvas, but they are also used to specify the target
+    of a SkCanvas' drawing operations.
+*/
+class SkBitmap {
+public:
+    class Allocator;
+
+    enum Config {
+        kNo_Config,         //!< bitmap has not been configured
+        kA1_Config,         //!< 1-bit per pixel, (0 is transparent, 1 is opaque)
+        kA8_Config,         //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque)
+        kIndex8_Config,     //!< 8-bits per pixel, using SkColorTable to specify the colors
+        kRGB_565_Config,    //!< 16-bits per pixel, (see SkColorPriv.h for packing)
+        kARGB_4444_Config,  //!< 16-bits per pixel, (see SkColorPriv.h for packing)
+        kARGB_8888_Config,  //!< 32-bits per pixel, (see SkColorPriv.h for packing)
+        kRLE_Index8_Config,
+
+        kConfigCount
+    };
+
+    /** Default construct creates a bitmap with zero width and height, and no pixels.
+        Its config is set to kNo_Config.
+    */
+    SkBitmap();
+    /** Constructor initializes the new bitmap by copying the src bitmap. All fields are copied,
+        but ownership of the pixels remains with the src bitmap.
+    */
+    SkBitmap(const SkBitmap& src);
+    /** Decrements our (shared) pixel ownership if needed.
+    */
+    ~SkBitmap();
+
+    /** Copies the src bitmap into this bitmap. Ownership of the src bitmap's pixels remains
+        with the src bitmap.
+    */
+    SkBitmap& operator=(const SkBitmap& src);
+    /** Swap the fields of the two bitmaps. This routine is guaranteed to never fail or throw.
+    */
+    //  This method is not exported to java.
+    void swap(SkBitmap& other);
+    
+    /** Return true iff the bitmap has empty dimensions.
+    */
+    bool empty() const { return 0 == fWidth || 0 == fHeight; }
+    
+    /** Return true iff the bitmap has no pixels nor a pixelref. Note: this can
+        return true even if the dimensions of the bitmap are > 0 (see empty()).
+    */
+    bool isNull() const { return NULL == fPixels && NULL == fPixelRef; }
+
+    /** Return the config for the bitmap.
+    */
+    Config  config() const { return (Config)fConfig; }
+    /** DEPRECATED, use config()
+    */
+    Config  getConfig() const { return this->config(); }
+    /** Return the bitmap's width, in pixels.
+    */
+    int width() const { return fWidth; }
+    /** Return the bitmap's height, in pixels.
+    */
+    int height() const { return fHeight; }
+    /** Return the number of bytes between subsequent rows of the bitmap.
+    */
+    int rowBytes() const { return fRowBytes; }
+    
+    /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for
+        2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0
+        for configs that are not at least 1-byte per pixel (e.g. kA1_Config
+        or kNo_Config)
+    */
+    int shiftPerPixel() const { return fBytesPerPixel >> 1; }
+
+    /** Return the number of bytes per pixel based on the config. If the config
+        does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned.
+    */
+    int bytesPerPixel() const { return fBytesPerPixel; }
+
+    /** Return the rowbytes expressed as a number of pixels (like width and
+        height). Note, for 1-byte per pixel configs like kA8_Config, this will
+        return the same as rowBytes(). Is undefined for configs that are less
+        than 1-byte per pixel (e.g. kA1_Config)
+    */
+    int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); }
+
+    /** Return the address of the pixels for this SkBitmap.
+    */
+    void* getPixels() const { return fPixels; }
+
+    /** Return the byte size of the pixels, based on the height and rowBytes.
+        Note this truncates the result to 32bits. Call getSize64() to detect
+        if the real size exceeds 32bits.
+    */
+    size_t getSize() const { return fHeight * fRowBytes; }
+    
+    /** Return the byte size of the pixels, based on the height and rowBytes.
+        This routine is slightly slower than getSize(), but does not truncate
+        the answer to 32bits.
+    */
+    Sk64 getSize64() const {
+        Sk64 size;
+        size.setMul(fHeight, fRowBytes);
+        return size;
+    }
+    
+    /** Returns true if the bitmap is opaque (has no translucent/transparent pixels).
+    */
+    bool isOpaque() const;
+    /** Specify if this bitmap's pixels are all opaque or not. Is only meaningful for configs
+        that support per-pixel alpha (RGB32, A1, A8).
+    */
+    void setIsOpaque(bool);
+
+    /** Reset the bitmap to its initial state (see default constructor). If we are a (shared)
+        owner of the pixels, that ownership is decremented.
+    */
+    void reset();
+
+    /** Given a config and a width, this computes the optimal rowBytes value. This is called automatically
+        if you pass 0 for rowBytes to setConfig().
+    */
+    static int ComputeRowBytes(Config c, int width);
+
+    /** Return the bytes-per-pixel for the specified config. If the config is
+        not at least 1-byte per pixel, return 0, including for kNo_Config.
+    */
+    static int ComputeBytesPerPixel(Config c);
+
+    /** Return the shift-per-pixel for the specified config. If the config is
+     not at least 1-byte per pixel, return 0, including for kNo_Config.
+     */
+    static int ComputeShiftPerPixel(Config c) {
+        return ComputeBytesPerPixel(c) >> 1;
+    }
+    
+    static Sk64 ComputeSize64(Config, int width, int height);
+    static size_t ComputeSize(Config, int width, int height);
+
+    /** Set the bitmap's config and dimensions. If rowBytes is 0, then
+        ComputeRowBytes() is called to compute the optimal value. This resets
+        any pixel/colortable ownership, just like reset().
+    */
+    void setConfig(Config, int width, int height, int rowBytes = 0);
+    /** Use this to assign a new pixel address for an existing bitmap. This
+        will automatically release any pixelref previously installed. Only call
+        this if you are handling ownership/lifetime of the pixel memory.
+     
+        If the bitmap retains a reference to the colortable (assuming it is
+        not null) it will take care of incrementing the reference count.
+
+        @param pixels   Address for the pixels, managed by the caller.
+        @param ctable   ColorTable (or null) that matches the specified pixels
+    */
+    void setPixels(void* p, SkColorTable* ctable = NULL);
+
+    /** Use the standard HeapAllocator to create the pixelref that manages the
+        pixel memory. It will be sized based on the current width/height/config.
+        If this is called multiple times, a new pixelref object will be created
+        each time.
+        
+        If the bitmap retains a reference to the colortable (assuming it is
+        not null) it will take care of incrementing the reference count.
+
+        @param ctable   ColorTable (or null) to use with the pixels that will
+                        be allocated. Only used if config == Index8_Config
+        @return true if the allocation succeeds. If not the pixelref field of
+                     the bitmap will be unchanged.
+    */
+    bool allocPixels(SkColorTable* ctable = NULL) {
+        return this->allocPixels(NULL, ctable);
+    }
+    
+    /** Use the specified Allocator to create the pixelref that manages the
+        pixel memory. It will be sized based on the current width/height/config.
+        If this is called multiple times, a new pixelref object will be created
+        each time.
+        
+        If the bitmap retains a reference to the colortable (assuming it is
+        not null) it will take care of incrementing the reference count.
+     
+        @param allocator The Allocator to use to create a pixelref that can
+                         manage the pixel memory for the current
+                         width/height/config. If allocator is NULL, the standard
+                         HeapAllocator will be used.
+        @param ctable   ColorTable (or null) to use with the pixels that will
+                        be allocated. Only used if config == Index8_Config.
+                        If it is non-null and the config is not Index8, it will
+                        be ignored.
+        @return true if the allocation succeeds. If not the pixelref field of
+                     the bitmap will be unchanged.
+    */
+    bool allocPixels(Allocator* allocator, SkColorTable* ctable);
+    
+    /** Return the current pixelref object, of any
+    */
+    SkPixelRef* pixelRef() const { return fPixelRef; }
+    /** Return the offset into the pixelref, if any. Will return 0 if there is
+        no pixelref installed.
+    */
+    size_t pixelRefOffset() const { return fPixelRefOffset; }
+    /** Assign a pixelref and optional offset. Pixelrefs are reference counted,
+        so the existing one (if any) will be unref'd and the new one will be
+        ref'd.
+    */
+    SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset = 0);
+    
+    /** Call this to ensure that the bitmap points to the current pixel address
+        in the pixelref. Balance it with a call to unlockPixels(). These calls
+        are harmless if there is no pixelref.
+    */
+    void lockPixels() const;
+    /** When you are finished access the pixel memory, call this to balance a
+        previous call to lockPixels(). This allows pixelrefs that implement
+        cached/deferred image decoding to know when there are active clients of
+        a given image.
+    */
+    void unlockPixels() const;
+    
+    /** Call this to be sure that the bitmap is valid enough to be drawn (i.e.
+        it has non-null pixels, and if required by its config, it has a
+        non-null colortable. Returns true if all of the above are met.
+    */
+    bool readyToDraw() const {
+        return this->getPixels() != NULL &&
+               ((this->config() != kIndex8_Config && this->config() != kRLE_Index8_Config) ||
+                       fColorTable != NULL);
+    }
+
+    /** Return the bitmap's colortable (if any). Does not affect the colortable's
+        reference count.
+    */
+    SkColorTable* getColorTable() const { return fColorTable; }
+
+    /** Returns a non-zero, unique value corresponding to the pixels in our
+        pixelref, or 0 if we do not have a pixelref. Each time the pixels are
+        changed (and notifyPixelsChanged is called), a different generation ID
+        will be returned.
+    */
+    uint32_t getGenerationID() const;
+    
+    /** Call this if you have changed the contents of the pixels. This will in-
+        turn cause a different generation ID value to be returned from
+        getGenerationID().
+    */
+    void notifyPixelsChanged() const;
+
+    /** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format
+        for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is ignored.
+        If the config is kA8_Config, then the r,g,b parameters are ignored.
+    */
+    void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const;
+    /** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format
+        for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is presumed
+        to be 0xFF. If the config is kA8_Config, then the r,g,b parameters are ignored and the
+        pixels are all set to 0xFF.
+    */
+    void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {
+        this->eraseARGB(0xFF, r, g, b);
+    }
+    /** Initialize the bitmap's pixels with the specified color, automatically converting into the correct format
+        for the bitmap's config. If the config is kRGB_565_Config, then the color's alpha value is presumed
+        to be 0xFF. If the config is kA8_Config, then only the color's alpha value is used.
+    */
+    void eraseColor(SkColor c) const {
+        this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c),
+                        SkColorGetB(c));
+    }
+    
+    /** Scroll (a subset of) the contents of this bitmap by dx/dy. If there are
+        no pixels allocated (i.e. getPixels() returns null) the method will
+        still update the inval region (if present).
+
+        @param subset The subset of the bitmap to scroll/move. To scroll the
+                      entire contents, specify [0, 0, width, height] or just
+                      pass null.
+        @param dx The amount to scroll in X
+        @param dy The amount to scroll in Y
+        @param inval Optional (may be null). Returns the area of the bitmap that
+                     was scrolled away. E.g. if dx = dy = 0, then inval would
+                     be set to empty. If dx >= width or dy >= height, then
+                     inval would be set to the entire bounds of the bitmap.
+        @return true if the scroll was doable. Will return false if the bitmap
+                     uses an unsupported config for scrolling (only kA8,
+                     kIndex8, kRGB_565, kARGB_4444, kARGB_8888 are supported).
+                     If no pixels are present (i.e. getPixels() returns false)
+                     inval will still be updated, and true will be returned.
+    */
+    bool scrollRect(const SkIRect* subset, int dx, int dy,
+                    SkRegion* inval = NULL) const;
+
+    /** Returns the address of the specified pixel. This performs a runtime
+        check to know the size of the pixels, and will return the same answer
+        as the corresponding size-specific method (e.g. getAddr16). Since the
+        check happens at runtime, it is much slower than using a size-specific
+        version. Unlike the size-specific methods, this routine also checks if
+        getPixels() returns null, and returns that. The size-specific routines
+        perform a debugging assert that getPixels() is not null, but they do
+        not do any runtime checks.
+    */
+    void* getAddr(int x, int y) const;
+
+    /** Returns the address of the pixel specified by x,y for 32bit pixels.
+    */
+    inline uint32_t* getAddr32(int x, int y) const;
+    /** Returns the address of the pixel specified by x,y for 16bit pixels.
+    */
+    inline uint16_t* getAddr16(int x, int y) const;
+    /** Returns the address of the pixel specified by x,y for 8bit pixels.
+    */
+    inline uint8_t* getAddr8(int x, int y) const;
+    /** Returns the address of the byte containing the pixel specified by x,y
+        for 1bit pixels.
+        */
+    inline uint8_t* getAddr1(int x, int y) const;
+
+    /** Returns the color corresponding to the pixel specified by x,y for
+        colortable based bitmaps.
+    */
+    inline SkPMColor getIndex8Color(int x, int y) const;
+
+    //  OS-specific helpers
+#ifndef SK_USE_WXWIDGETS
+#ifdef SK_BUILD_FOR_WIN
+    /** On Windows and PocketPC builds, this will draw the SkBitmap onto the
+        specified HDC
+    */
+    void drawToHDC(HDC, int left, int top) const;
+#elif defined(SK_BUILD_FOR_MAC)
+    /** On Mac OS X and Carbon builds, this will draw the SkBitmap onto the
+        specified WindowRef
+    */
+    void drawToPort(WindowRef, CGContextRef) const;
+#endif
+#endif
+
+    /** Set dst to be a setset of this bitmap. If possible, it will share the
+        pixel memory, and just point into a subset of it. However, if the config
+        does not support this, a local copy will be made and associated with
+        the dst bitmap. If the subset rectangle, intersected with the bitmap's
+        dimensions is empty, or if there is an unsupported config, false will be
+        returned and dst will be untouched.
+        @param dst  The bitmap that will be set to a subset of this bitmap
+        @param subset The rectangle of pixels in this bitmap that dst will
+                      reference.
+        @return true if the subset copy was successfully made.
+    */
+    bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
+
+    /** Tries to make a new bitmap based on the dimensions of this bitmap,
+        setting the new bitmap's config to the one specified, and then copying
+        this bitmap's pixels into the new bitmap. If the conversion is not
+        supported, or the allocator fails, then this method returns false and
+        dst is left unchanged.
+        @param dst  The bitmap to be sized and allocated
+        @param c The desired config for dst
+        @param allocator Allocator used to allocate the pixelref for the dst
+                         bitmap. If this is null, the standard HeapAllocator
+                         will be used.
+        @return true if the copy could be made.
+    */
+    bool copyTo(SkBitmap* dst, Config c, Allocator* allocator = NULL) const;
+
+    bool hasMipMap() const;
+    void buildMipMap(bool forceRebuild = false);
+    void freeMipMap();
+
+    /** Given scale factors sx, sy, determine the miplevel available in the
+        bitmap, and return it (this is the amount to shift matrix iterators
+        by). If dst is not null, it is set to the correct level.
+    */
+    int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
+
+    void extractAlpha(SkBitmap* dst) const {
+        this->extractAlpha(dst, NULL, NULL);
+    }
+
+    void extractAlpha(SkBitmap* dst, const SkPaint* paint,
+                      SkIPoint* offset) const;
+    
+    void flatten(SkFlattenableWriteBuffer&) const;
+    void unflatten(SkFlattenableReadBuffer&);
+
+    SkDEBUGCODE(void validate() const;)
+
+    class Allocator : public SkRefCnt {
+    public:
+        /** Allocate the pixel memory for the bitmap, given its dimensions and
+            config. Return true on success, where success means either setPixels
+            or setPixelRef was called. The pixels need not be locked when this
+            returns. If the config requires a colortable, it also must be
+            installed via setColorTable. If false is returned, the bitmap and
+            colortable should be left unchanged.
+        */
+        virtual bool allocPixelRef(SkBitmap*, SkColorTable*) = 0;
+    };
+
+    /** Subclass of Allocator that returns a pixelref that allocates its pixel
+        memory from the heap. This is the default Allocator invoked by
+        allocPixels().
+    */
+    class HeapAllocator : public Allocator {
+    public:
+        virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
+    };
+
+    class RLEPixels {
+    public:
+        RLEPixels(int width, int height);
+        virtual ~RLEPixels();
+        
+        uint8_t* packedAtY(int y) const {
+            SkASSERT((unsigned)y < (unsigned)fHeight);
+            return fYPtrs[y];
+        }
+        
+        // called by subclasses during creation
+        void setPackedAtY(int y, uint8_t* addr) {
+            SkASSERT((unsigned)y < (unsigned)fHeight);
+            fYPtrs[y] = addr;
+        }
+            
+    private:
+        uint8_t** fYPtrs;
+        int       fHeight;
+    };
+        
+private:
+#ifdef SK_SUPPORT_MIPMAP
+    struct MipMap;
+    mutable MipMap* fMipMap;
+#endif
+
+    mutable SkPixelRef* fPixelRef;
+    mutable size_t      fPixelRefOffset;
+    mutable int         fPixelLockCount;
+    // either user-specified (in which case it is not treated as mutable)
+    // or a cache of the returned value from fPixelRef->lockPixels()
+    mutable void*       fPixels;
+    mutable SkColorTable* fColorTable;    // only meaningful for kIndex8
+
+    enum Flags {
+        kImageIsOpaque_Flag  = 0x01
+    };
+
+    uint32_t    fRowBytes;
+    uint16_t    fWidth, fHeight;
+    uint8_t     fConfig;
+    uint8_t     fFlags;
+    uint8_t     fBytesPerPixel; // based on config
+
+    /*  Unreference any pixelrefs or colortables
+    */
+    void freePixels();
+    void updatePixelsFromRef() const;
+    
+    static SkFixed ComputeMipLevel(SkFixed sx, SkFixed dy);
+};
+
+/** \class SkColorTable
+
+    SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by
+    8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable.
+*/
+class SkColorTable : public SkRefCnt {
+public:
+    /** Constructs an empty color table (zero colors).
+    */
+    explicit SkColorTable(int count);
+    explicit SkColorTable(SkFlattenableReadBuffer&);
+    SkColorTable(const SkPMColor colors[], int count);
+    virtual ~SkColorTable();
+
+    enum Flags {
+        kColorsAreOpaque_Flag   = 0x01  //!< if set, all of the colors in the table are opaque (alpha==0xFF)
+    };
+    /** Returns the flag bits for the color table. These can be changed with setFlags().
+    */
+    unsigned getFlags() const { return fFlags; }
+    /** Set the flags for the color table. See the Flags enum for possible values.
+    */
+    void    setFlags(unsigned flags);
+
+    /** Returns the number of colors in the table.
+    */
+    int count() const { return fCount; }
+
+    /** Returns the specified color from the table. In the debug build, this asserts that
+        the index is in range (0 <= index < count).
+    */
+    SkPMColor operator[](int index) const {
+        SkASSERT(fColors != NULL && (unsigned)index < fCount);
+        return fColors[index];
+    }
+
+    /** Specify the number of colors in the color table. This does not initialize the colors
+        to any value, just allocates memory for them. To initialize the values, either call
+        setColors(array, count), or follow setCount(count) with a call to
+        lockColors()/{set the values}/unlockColors(true).
+    */
+//    void    setColors(int count) { this->setColors(NULL, count); }
+//    void    setColors(const SkPMColor[], int count);
+
+    /** Return the array of colors for reading and/or writing. This must be
+        balanced by a call to unlockColors(changed?), telling the colortable if
+        the colors were changed during the lock.
+    */
+    SkPMColor* lockColors() {
+        SkDEBUGCODE(fColorLockCount += 1;)
+        return fColors;
+    }
+    /** Balancing call to lockColors(). If the colors have been changed, pass true.
+    */
+    void unlockColors(bool changed);
+
+    /** Similar to lockColors(), lock16BitCache() returns the array of
+        RGB16 colors that mirror the 32bit colors. However, this function
+        will return null if kColorsAreOpaque_Flag is not set.
+        Also, unlike lockColors(), the returned array here cannot be modified.
+    */
+    const uint16_t* lock16BitCache();
+    /** Balancing call to lock16BitCache().
+    */
+    void unlock16BitCache() {
+        SkASSERT(f16BitCacheLockCount > 0);
+        SkDEBUGCODE(f16BitCacheLockCount -= 1);
+    }
+
+    void flatten(SkFlattenableWriteBuffer&) const;
+
+private:
+    SkPMColor*  fColors;
+    uint16_t*   f16BitCache;
+    uint16_t    fCount;
+    uint8_t     fFlags;
+    SkDEBUGCODE(int fColorLockCount;)
+    SkDEBUGCODE(int f16BitCacheLockCount;)
+
+    void inval16BitCache();
+};
+
+class SkAutoLockPixels {
+public:
+    SkAutoLockPixels(const SkBitmap& bitmap) : fBitmap(bitmap) {
+        bitmap.lockPixels();
+    }
+    ~SkAutoLockPixels() {
+        fBitmap.unlockPixels();
+    }
+
+private:
+    const SkBitmap& fBitmap;
+};
+
+/** Helper class that performs the lock/unlockColors calls on a colortable.
+    The destructor will call unlockColors(false) if it has a bitmap's colortable
+*/
+class SkAutoLockColors : public SkNoncopyable {
+public:
+    /** Initialize with no bitmap. Call lockColors(bitmap) to lock bitmap's
+        colortable
+     */
+    SkAutoLockColors() : fCTable(NULL), fColors(NULL) {}
+    /** Initialize with bitmap, locking its colortable if present
+     */
+    explicit SkAutoLockColors(const SkBitmap& bm) {
+        fCTable = bm.getColorTable();
+        fColors = fCTable ? fCTable->lockColors() : NULL;
+    }
+    /** Initialize with a colortable (may be null)
+     */
+    explicit SkAutoLockColors(SkColorTable* ctable) {
+        fCTable = ctable;
+        fColors = ctable ? ctable->lockColors() : NULL;
+    }
+    ~SkAutoLockColors() {
+        if (fCTable) {
+            fCTable->unlockColors(false);
+        }
+    }
+    
+    /** Return the currently locked colors, or NULL if no bitmap's colortable
+        is currently locked.
+    */
+    const SkPMColor* colors() const { return fColors; }
+    
+    /** If a previous bitmap has been locked by this object, unlock its colors
+        first. If the specified bitmap has a colortable, lock its colors and
+        return them.
+    */
+    const SkPMColor* lockColors(const SkBitmap& bm) {
+        if (fCTable) {
+            fCTable->unlockColors(false);
+        }
+        fCTable = bm.getColorTable();
+        fColors = fCTable ? fCTable->lockColors() : NULL;
+        return fColors;
+    }
+
+private:
+    SkColorTable*    fCTable;
+    const SkPMColor* fColors;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
+    SkASSERT(fPixels);
+    SkASSERT(fConfig == kARGB_8888_Config);
+    SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+    return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
+}
+
+inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
+    SkASSERT(fPixels);
+    SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config);
+    SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+    return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
+}
+
+inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
+    SkASSERT(fPixels);
+    SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
+    SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+    return (uint8_t*)fPixels + y * fRowBytes + x;
+}
+
+inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
+    SkASSERT(fPixels);
+    SkASSERT(fConfig == kIndex8_Config);
+    SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+    SkASSERT(fColorTable);
+    return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
+}
+
+// returns the address of the byte that contains the x coordinate
+inline uint8_t* SkBitmap::getAddr1(int x, int y) const {
+    SkASSERT(fPixels);
+    SkASSERT(fConfig == kA1_Config);
+    SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+    return (uint8_t*)fPixels + y * fRowBytes + (x >> 3);
+}
+
+#endif
+
diff --git a/include/core/SkBounder.h b/include/core/SkBounder.h
new file mode 100644
index 0000000..f20961d
--- /dev/null
+++ b/include/core/SkBounder.h
@@ -0,0 +1,72 @@
+/*
+ * 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 SkBounder_DEFINED
+#define SkBounder_DEFINED
+
+#include "SkTypes.h"
+#include "SkRefCnt.h"
+
+struct SkIRect;
+struct SkPoint;
+struct SkRect;
+class SkPaint;
+class SkPath;
+class SkRegion;
+
+/** \class SkBounder
+
+    Base class for intercepting the device bounds of shapes before they are drawn.
+    Install a subclass of this in your canvas.
+*/
+class SkBounder : public SkRefCnt {
+public:
+    /* Call to perform a clip test before calling onIRect. 
+       Returns the result from onIRect.
+    */
+    bool doIRect(const SkIRect&);
+
+protected:
+    /** Override in your subclass. This is called with the device bounds of an
+        object (text, geometry, image) just before it is drawn. If your method
+        returns false, the drawing for that shape is aborted. If your method
+        returns true, drawing continues. The bounds your method receives have already
+        been transformed in to device coordinates, and clipped to the current clip.
+    */
+    virtual bool onIRect(const SkIRect&) = 0;
+
+    /** Called after each shape has been drawn. The default implementation does
+        nothing, but your override could use this notification to signal itself
+        that the offscreen being rendered into needs to be updated to the screen.
+    */
+    virtual void commit();
+
+private:
+    bool doHairline(const SkPoint&, const SkPoint&, const SkPaint&);
+    bool doRect(const SkRect&, const SkPaint&);
+    bool doPath(const SkPath&, const SkPaint&, bool doFill);
+    void setClip(const SkRegion* clip) { fClip = clip; }
+
+    const SkRegion* fClip;
+    friend class SkAutoBounderCommit;
+    friend class SkDraw;
+    friend class SkDrawIter;
+    friend struct Draw1Glyph;
+    friend class SkMaskFilter;
+};
+
+#endif
+
diff --git a/include/core/SkBuffer.h b/include/core/SkBuffer.h
new file mode 100644
index 0000000..bc11a1e
--- /dev/null
+++ b/include/core/SkBuffer.h
@@ -0,0 +1,141 @@
+/*
+ * 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 SkBuffer_DEFINED
+#define SkBuffer_DEFINED
+
+#include "SkScalar.h"
+
+/** \class SkRBuffer
+
+    Light weight class for reading data from a memory block.
+    The RBuffer is given the buffer to read from, with either a specified size
+    or no size (in which case no range checking is performed). It is iillegal
+    to attempt to read a value from an empty RBuffer (data == null). 
+*/
+class SkRBuffer : SkNoncopyable {
+public:
+    SkRBuffer() : fData(0), fPos(0), fStop(0) {}
+    /** Initialize RBuffer with a data pointer, but no specified length.
+        This signals the RBuffer to not perform range checks during reading.
+    */
+    SkRBuffer(const void* data)
+    {
+        fData = (const char*)data;
+        fPos = (const char*)data;
+        fStop = 0;  // no bounds checking
+    }
+    /** Initialize RBuffer with a data point and length.
+    */
+    SkRBuffer(const void* data, size_t size)
+    {
+        SkASSERT(data != 0 || size == 0);
+        fData = (const char*)data;
+        fPos = (const char*)data;
+        fStop = (const char*)data + size;
+    }
+    
+    /** Return the number of bytes that have been read from the beginning
+        of the data pointer.
+    */
+    size_t  pos() const { return fPos - fData; }
+    /** Return the total size of the data pointer. Only defined if the length was
+        specified in the constructor or in a call to reset().
+    */
+    size_t  size() const { return fStop - fData; }
+    /** Return true if the buffer has read to the end of the data pointer.
+        Only defined if the length was specified in the constructor or in a call
+        to reset(). Always returns true if the length was not specified.
+    */
+    bool    eof() const { return fPos >= fStop; }
+
+    /** Read the specified number of bytes from the data pointer. If buffer is not
+        null, copy those bytes into buffer.
+    */
+    void    read(void* buffer, size_t size) { if (size) this->readNoSizeCheck(buffer, size); }
+    const void* skip(size_t size); // return start of skipped data
+    size_t  skipToAlign4();
+
+    void*       readPtr() { void* ptr; read(&ptr, sizeof(ptr)); return ptr; }
+    SkScalar    readScalar() { SkScalar x; read(&x, 4); return x; }
+    uint32_t    readU32() { uint32_t x; read(&x, 4); return x; }
+    int32_t     readS32() { int32_t x; read(&x, 4); return x; }
+    uint16_t    readU16() { uint16_t x; read(&x, 2); return x; }
+    int16_t     readS16() { int16_t x; read(&x, 2); return x; }
+    uint8_t     readU8() { uint8_t x; read(&x, 1); return x; }
+    bool        readBool() { return this->readU8() != 0; }
+
+protected:
+    void    readNoSizeCheck(void* buffer, size_t size);
+
+    const char* fData;
+    const char* fPos;
+    const char* fStop;
+};
+
+/** \class SkWBuffer
+
+    Light weight class for writing data to a memory block.
+    The WBuffer is given the buffer to write into, with either a specified size
+    or no size, in which case no range checking is performed. An empty WBuffer
+    is legal, in which case no data is ever written, but the relative pos()
+    is updated.
+*/
+class SkWBuffer : SkNoncopyable {
+public:
+    SkWBuffer() : fData(0), fPos(0), fStop(0) {}
+    SkWBuffer(void* data) { reset(data); }
+    SkWBuffer(void* data, size_t size) { reset(data, size); }
+
+    void reset(void* data)
+    {
+        fData = (char*)data;
+        fPos = (char*)data;
+        fStop = 0;  // no bounds checking
+    }
+    void reset(void* data, size_t size)
+    {
+        SkASSERT(data != 0 || size == 0);
+        fData = (char*)data;
+        fPos = (char*)data;
+        fStop = (char*)data + size;
+    }
+    
+    void*   data() const { return fData; }
+    size_t  pos() const { return fPos - fData; }
+    size_t  size() const { return fStop - fData; }
+    bool    eof() const { return fPos >= fStop; }
+    void*   skip(size_t size); // return start of skipped data
+    void    write(const void* buffer, size_t size) { if (size) this->writeNoSizeCheck(buffer, size); }
+    size_t  padToAlign4();
+
+    void    writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); }
+    void    writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); }
+    void    write32(int32_t x) { this->writeNoSizeCheck(&x, 4); }
+    void    write16(int16_t x) { this->writeNoSizeCheck(&x, 2); }
+    void    write8(int8_t x) { this->writeNoSizeCheck(&x, 1); }
+    void    writeBool(bool x) { this->write8(x); }
+
+protected:
+    void    writeNoSizeCheck(const void* buffer, size_t size);
+
+    char* fData;
+    char* fPos;
+    char* fStop;
+};
+
+#endif
+
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
new file mode 100644
index 0000000..a19a5ae
--- /dev/null
+++ b/include/core/SkCanvas.h
@@ -0,0 +1,794 @@
+/*
+ * 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 SkCanvas_DEFINED
+#define SkCanvas_DEFINED
+
+#include "SkTypes.h"
+#include "SkBitmap.h"
+#include "SkDeque.h"
+#include "SkPaint.h"
+#include "SkRefCnt.h"
+#include "SkPorterDuff.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkScalarCompare.h"
+
+class SkBounder;
+class SkDevice;
+class SkDraw;
+class SkDrawFilter;
+class SkPicture;
+
+/** \class SkCanvas
+
+    A Canvas encapsulates all of the state about drawing into a device (bitmap).
+    This includes a reference to the device itself, and a stack of matrix/clip
+    values. For any given draw call (e.g. drawRect), the geometry of the object
+    being drawn is transformed by the concatenation of all the matrices in the
+    stack. The transformed geometry is clipped by the intersection of all of
+    the clips in the stack.
+
+    While the Canvas holds the state of the drawing device, the state (style)
+    of the object being drawn is held by the Paint, which is provided as a
+    parameter to each of the draw() methods. The Paint holds attributes such as
+    color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
+    etc.
+*/
+class SkCanvas : public SkRefCnt {
+public:
+    /** Construct a canvas with the specified bitmap to draw into.
+        @param bitmap   Specifies a bitmap for the canvas to draw into. Its
+                        structure are copied to the canvas.
+    */
+    explicit SkCanvas(const SkBitmap& bitmap);
+    /** Construct a canvas with the specified device to draw into.
+        @param device   Specifies a device for the canvas to draw into. The
+                        device may be null.
+    */
+    explicit SkCanvas(SkDevice* device = NULL);
+    virtual ~SkCanvas();
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** If this subclass of SkCanvas supports GL viewports, return true and set
+        size (if not null) to the size of the viewport. If it is not supported,
+        ignore vp and return false.
+    */
+    virtual bool getViewport(SkIPoint* size) const;
+    
+    /** If this subclass of SkCanvas supports GL viewports, return true and set
+        the viewport to the specified x and y dimensions. If it is not
+        supported, ignore x and y and return false.
+    */
+    virtual bool setViewport(int x, int y);
+
+    /** Return the canvas' device object, which may be null. The device holds
+        the bitmap of the pixels that the canvas draws into. The reference count
+        of the returned device is not changed by this call.
+    */
+    SkDevice* getDevice() const;
+
+    /** Specify a device for this canvas to draw into. If it is not null, its
+        reference count is incremented. If the canvas was already holding a
+        device, its reference count is decremented. The new device is returned.
+    */
+    SkDevice* setDevice(SkDevice* device);
+    
+    /** Specify a bitmap for the canvas to draw into. This is a help method for
+        setDevice(), and it creates a device for the bitmap by calling
+        createDevice(). The structure of the bitmap is copied into the device.
+    */
+    virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
+
+    ///////////////////////////////////////////////////////////////////////////
+    
+    enum SaveFlags {
+        /** save the matrix state, restoring it on restore() */
+        kMatrix_SaveFlag            = 0x01,
+        /** save the clip state, restoring it on restore() */
+        kClip_SaveFlag              = 0x02,
+        /** the layer needs to support per-pixel alpha */
+        kHasAlphaLayer_SaveFlag     = 0x04,
+        /** the layer needs to support 8-bits per color component */
+        kFullColorLayer_SaveFlag    = 0x08,
+        /** the layer should clip against the bounds argument */
+        kClipToLayer_SaveFlag       = 0x10,
+
+        // helper masks for common choices
+        kMatrixClip_SaveFlag        = 0x03,
+        kARGB_NoClipLayer_SaveFlag  = 0x0F,
+        kARGB_ClipLayer_SaveFlag    = 0x1F
+    };
+
+    /** This call saves the current matrix and clip information, and pushes a
+        copy onto a private stack. Subsequent calls to translate, scale,
+        rotate, skew, concat or clipRect, clipPath all operate on this copy.
+        When the balancing call to restore() is made, this copy is deleted and
+        the previous matrix/clip state is restored.
+        @return The value to pass to restoreToCount() to balance this save()
+    */
+    virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
+
+    /** This behaves the same as save(), but in addition it allocates an
+        offscreen bitmap. All drawing calls are directed there, and only when
+        the balancing call to restore() is made is that offscreen transfered to
+        the canvas (or the previous layer). Subsequent calls to translate,
+        scale, rotate, skew, concat or clipRect, clipPath all operate on this
+        copy. When the balancing call to restore() is made, this copy is deleted
+        and the previous matrix/clip state is restored.
+        @param bounds (may be null) the maximum size the offscreen bitmap needs
+                      to be (in local coordinates)
+        @param paint (may be null) This is copied, and is applied to the
+                     offscreen when restore() is called
+        @param flags  LayerFlags
+        @return The value to pass to restoreToCount() to balance this save()
+    */
+    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+                          SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+
+    /** This behaves the same as save(), but in addition it allocates an
+        offscreen bitmap. All drawing calls are directed there, and only when
+        the balancing call to restore() is made is that offscreen transfered to
+        the canvas (or the previous layer). Subsequent calls to translate,
+        scale, rotate, skew, concat or clipRect, clipPath all operate on this
+        copy. When the balancing call to restore() is made, this copy is deleted
+        and the previous matrix/clip state is restored.
+        @param bounds (may be null) the maximum size the offscreen bitmap needs
+                      to be (in local coordinates)
+        @param alpha  This is applied to the offscreen when restore() is called.
+        @param flags  LayerFlags
+        @return The value to pass to restoreToCount() to balance this save()
+    */
+    int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
+                       SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+
+    /** This call balances a previous call to save(), and is used to remove all
+        modifications to the matrix/clip state since the last save call. It is
+        an error to call restore() more times than save() was called.
+    */
+    virtual void restore();
+
+    /** Returns the number of matrix/clip states on the SkCanvas' private stack.
+        This will equal # save() calls - # restore() calls.
+    */
+    int getSaveCount() const;
+
+    /** Efficient way to pop any calls to save() that happened after the save
+        count reached saveCount. It is an error for saveCount to be less than
+        getSaveCount()
+        @param saveCount    The number of save() levels to restore from
+    */
+    void restoreToCount(int saveCount);
+
+    /** Preconcat the current matrix with the specified translation
+        @param dx   The distance to translate in X
+        @param dy   The distance to translate in Y
+        returns true if the operation succeeded (e.g. did not overflow)
+    */
+    virtual bool translate(SkScalar dx, SkScalar dy);
+
+    /** Preconcat the current matrix with the specified scale.
+        @param sx   The amount to scale in X
+        @param sy   The amount to scale in Y
+        returns true if the operation succeeded (e.g. did not overflow)
+    */
+    virtual bool scale(SkScalar sx, SkScalar sy);
+
+    /** Preconcat the current matrix with the specified rotation.
+        @param degrees  The amount to rotate, in degrees
+        returns true if the operation succeeded (e.g. did not overflow)
+    */
+    virtual bool rotate(SkScalar degrees);
+
+    /** Preconcat the current matrix with the specified skew.
+        @param sx   The amount to skew in X
+        @param sy   The amount to skew in Y
+        returns true if the operation succeeded (e.g. did not overflow)
+    */
+    virtual bool skew(SkScalar sx, SkScalar sy);
+
+    /** Preconcat the current matrix with the specified matrix.
+        @param matrix   The matrix to preconcatenate with the current matrix
+        @return true if the operation succeeded (e.g. did not overflow)
+    */
+    virtual bool concat(const SkMatrix& matrix);
+    
+    /** Replace the current matrix with a copy of the specified matrix.
+        @param matrix The matrix that will be copied into the current matrix.
+    */
+    virtual void setMatrix(const SkMatrix& matrix);
+    
+    /** Helper for setMatrix(identity). Sets the current matrix to identity.
+    */
+    void resetMatrix();
+
+    /** Modify the current clip with the specified rectangle.
+        @param rect The rect to intersect with the current clip
+        @param op The region op to apply to the current clip
+        @return true if the canvas' clip is non-empty
+    */
+    virtual bool clipRect(const SkRect& rect,
+                          SkRegion::Op op = SkRegion::kIntersect_Op);
+
+    /** Modify the current clip with the specified path.
+        @param path The path to apply to the current clip
+        @param op The region op to apply to the current clip
+        @return true if the canvas' new clip is non-empty
+    */
+    virtual bool clipPath(const SkPath& path,
+                          SkRegion::Op op = SkRegion::kIntersect_Op);
+
+    /** Modify the current clip with the specified region. Note that unlike
+        clipRect() and clipPath() which transform their arguments by the current
+        matrix, clipRegion() assumes its argument is already in device
+        coordinates, and so no transformation is performed.
+        @param deviceRgn    The region to apply to the current clip
+        @param op The region op to apply to the current clip
+        @return true if the canvas' new clip is non-empty
+    */
+    virtual bool clipRegion(const SkRegion& deviceRgn,
+                            SkRegion::Op op = SkRegion::kIntersect_Op);
+
+    /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
+        specified region. This does not intersect or in any other way account
+        for the existing clip region.
+        @param deviceRgn The region to copy into the current clip.
+        @return true if the new clip region is non-empty
+    */
+    bool setClipRegion(const SkRegion& deviceRgn) {
+        return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
+    }
+
+    /** Enum describing how to treat edges when performing quick-reject tests
+        of a geometry against the current clip. Treating them as antialiased
+        (kAA_EdgeType) will take into account the extra pixels that may be drawn
+        if the edge does not lie exactly on a device pixel boundary (after being
+        transformed by the current matrix).
+    */
+    enum EdgeType {
+        /** Treat the edges as B&W (not antialiased) for the purposes of testing
+            against the current clip
+        */
+        kBW_EdgeType,
+        /** Treat the edges as antialiased for the purposes of testing
+            against the current clip
+        */
+        kAA_EdgeType
+    };
+
+    /** Return true if the specified rectangle, after being transformed by the
+        current matrix, would lie completely outside of the current clip. Call
+        this to check if an area you intend to draw into is clipped out (and
+        therefore you can skip making the draw calls).
+        @param rect the rect to compare with the current clip
+        @param et  specifies how to treat the edges (see EdgeType)
+        @return true if the rect (transformed by the canvas' matrix) does not
+                     intersect with the canvas' clip
+    */
+    bool quickReject(const SkRect& rect, EdgeType et) const;
+
+    /** Return true if the specified path, after being transformed by the
+        current matrix, would lie completely outside of the current clip. Call
+        this to check if an area you intend to draw into is clipped out (and
+        therefore you can skip making the draw calls). Note, for speed it may
+        return false even if the path itself might not intersect the clip
+        (i.e. the bounds of the path intersects, but the path does not).
+        @param path The path to compare with the current clip
+        @param et  specifies how to treat the edges (see EdgeType)
+        @return true if the path (transformed by the canvas' matrix) does not
+                     intersect with the canvas' clip
+    */
+    bool quickReject(const SkPath& path, EdgeType et) const;
+
+    /** Return true if the horizontal band specified by top and bottom is
+        completely clipped out. This is a conservative calculation, meaning
+        that it is possible that if the method returns false, the band may still
+        in fact be clipped out, but the converse is not true. If this method
+        returns true, then the band is guaranteed to be clipped out.
+        @param top  The top of the horizontal band to compare with the clip
+        @param bottom The bottom of the horizontal and to compare with the clip
+        @return true if the horizontal band is completely clipped out (i.e. does
+                     not intersect the current clip)
+    */
+    bool quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const;
+
+    /** Return the bounds of the current clip (in local coordinates) in the
+        bounds parameter, and return true if it is non-empty. This can be useful
+        in a way similar to quickReject, in that it tells you that drawing
+        outside of these bounds will be clipped out.
+    */
+    bool getClipBounds(SkRect* bounds, EdgeType et = kAA_EdgeType) const;
+
+    /** Fill the entire canvas' bitmap (restricted to the current clip) with the
+        specified ARGB color, using the specified PorterDuff mode.
+        @param a    the alpha component (0..255) of the color to fill the canvas
+        @param r    the red component (0..255) of the color to fill the canvas
+        @param g    the green component (0..255) of the color to fill the canvas
+        @param b    the blue component (0..255) of the color to fill the canvas
+        @param mode the mode to apply the color in (defaults to SrcOver)
+    */
+    void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
+                  SkPorterDuff::Mode mode = SkPorterDuff::kSrcOver_Mode);
+
+    /** Fill the entire canvas' bitmap (restricted to the current clip) with the
+        specified color and porter-duff xfermode.
+        @param color    the color to draw with
+        @param mode the mode to apply the color in (defaults to SrcOver)
+    */
+    void drawColor(SkColor color,
+                   SkPorterDuff::Mode mode = SkPorterDuff::kSrcOver_Mode);
+
+    /** Fill the entire canvas' bitmap (restricted to the current clip) with the
+        specified paint.
+        @param paint    The paint used to fill the canvas
+    */
+    virtual void drawPaint(const SkPaint& paint);
+
+    enum PointMode {
+        /** drawPoints draws each point separately */
+        kPoints_PointMode,
+        /** drawPoints draws each pair of points as a line segment */
+        kLines_PointMode,
+        /** drawPoints draws the array of points as a polygon */
+        kPolygon_PointMode
+    };
+
+    /** Draw a series of points, interpreted based on the PointMode mode. For
+        all modes, the count parameter is interpreted as the total number of
+        points. For kLine mode, count/2 line segments are drawn.
+        For kPoint mode, each point is drawn centered at its coordinate, and its
+        size is specified by the paint's stroke-width. It draws as a square,
+        unless the paint's cap-type is round, in which the points are drawn as
+        circles.
+        For kLine mode, each pair of points is drawn as a line segment,
+        respecting the paint's settings for cap/join/width.
+        For kPolygon mode, the entire array is drawn as a series of connected
+        line segments.
+        Note that, while similar, kLine and kPolygon modes draw slightly
+        differently than the equivalent path built with a series of moveto,
+        lineto calls, in that the path will draw all of its contours at once,
+        with no interactions if contours intersect each other (think XOR
+        xfermode). drawPoints always draws each element one at a time.
+        @param mode     PointMode specifying how to draw the array of points.
+        @param count    The number of points in the array
+        @param pts      Array of points to draw
+        @param paint    The paint used to draw the points
+    */
+    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                            const SkPaint& paint);
+
+    /** Helper method for drawing a single point. See drawPoints() for a more
+        details.
+    */
+    void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
+    
+    /** Draws a single pixel in the specified color.
+        @param x        The X coordinate of which pixel to draw
+        @param y        The Y coordiante of which pixel to draw
+        @param color    The color to draw
+    */
+    void drawPoint(SkScalar x, SkScalar y, SkColor color);
+
+    /** Draw a line segment with the specified start and stop x,y coordinates,
+        using the specified paint. NOTE: since a line is always "framed", the
+        paint's Style is ignored.
+        @param x0    The x-coordinate of the start point of the line
+        @param y0    The y-coordinate of the start point of the line
+        @param x1    The x-coordinate of the end point of the line
+        @param y1    The y-coordinate of the end point of the line
+        @param paint The paint used to draw the line
+    */
+    void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
+                  const SkPaint& paint);
+
+    /** Draw the specified rectangle using the specified paint. The rectangle
+        will be filled or stroked based on the Style in the paint.
+        @param rect     The rect to be drawn
+        @param paint    The paint used to draw the rect
+    */
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint);
+
+    /** Draw the specified rectangle using the specified paint. The rectangle
+        will be filled or framed based on the Style in the paint.
+        @param rect     The rect to be drawn
+        @param paint    The paint used to draw the rect
+    */
+    void drawIRect(const SkIRect& rect, const SkPaint& paint)
+    {
+        SkRect r;
+        r.set(rect);    // promotes the ints to scalars
+        this->drawRect(r, paint);
+    }
+    
+    /** Draw the specified rectangle using the specified paint. The rectangle
+        will be filled or framed based on the Style in the paint.
+        @param left     The left side of the rectangle to be drawn
+        @param top      The top side of the rectangle to be drawn
+        @param right    The right side of the rectangle to be drawn
+        @param bottom   The bottom side of the rectangle to be drawn
+        @param paint    The paint used to draw the rect
+    */
+    void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
+                        SkScalar bottom, const SkPaint& paint);
+
+    /** Draw the specified oval using the specified paint. The oval will be
+        filled or framed based on the Style in the paint.
+        @param oval     The rectangle bounds of the oval to be drawn
+        @param paint    The paint used to draw the oval
+    */
+    void drawOval(const SkRect& oval, const SkPaint&);
+
+    /** Draw the specified circle using the specified paint. If radius is <= 0,
+        then nothing will be drawn. The circle will be filled
+        or framed based on the Style in the paint.
+        @param cx       The x-coordinate of the center of the cirle to be drawn
+        @param cy       The y-coordinate of the center of the cirle to be drawn
+        @param radius   The radius of the cirle to be drawn
+        @param paint    The paint used to draw the circle
+    */
+    void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
+                    const SkPaint& paint);
+
+    /** Draw the specified arc, which will be scaled to fit inside the
+        specified oval. If the sweep angle is >= 360, then the oval is drawn
+        completely. Note that this differs slightly from SkPath::arcTo, which
+        treats the sweep angle mod 360.
+        @param oval The bounds of oval used to define the shape of the arc
+        @param startAngle Starting angle (in degrees) where the arc begins
+        @param sweepAngle Sweep angle (in degrees) measured clockwise
+        @param useCenter true means include the center of the oval. For filling
+                         this will draw a wedge. False means just use the arc.
+        @param paint    The paint used to draw the arc
+    */
+    void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+                 bool useCenter, const SkPaint& paint);
+
+    /** Draw the specified round-rect using the specified paint. The round-rect
+        will be filled or framed based on the Style in the paint.
+        @param rect     The rectangular bounds of the roundRect to be drawn
+        @param rx       The x-radius of the oval used to round the corners
+        @param ry       The y-radius of the oval used to round the corners
+        @param paint    The paint used to draw the roundRect
+    */
+    void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+                       const SkPaint& paint);
+
+    /** Draw the specified path using the specified paint. The path will be
+        filled or framed based on the Style in the paint.
+        @param path     The path to be drawn
+        @param paint    The paint used to draw the path
+    */
+    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+
+    /** Draw the specified bitmap, with its top/left corner at (x,y), using the
+        specified paint, transformed by the current matrix. Note: if the paint
+        contains a maskfilter that generates a mask which extends beyond the
+        bitmap's original width/height, then the bitmap will be drawn as if it
+        were in a Shader with CLAMP mode. Thus the color outside of the original
+        width/height will be the edge color replicated.
+        @param bitmap   The bitmap to be drawn
+        @param left     The position of the left side of the bitmap being drawn
+        @param top      The position of the top side of the bitmap being drawn
+        @param paint    The paint used to draw the bitmap, or NULL
+    */
+    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+                            const SkPaint* paint = NULL);
+
+    /** Draw the specified bitmap, with the specified matrix applied (before the
+        canvas' matrix is applied).
+        @param bitmap   The bitmap to be drawn
+        @param src      Optional: specify the subset of the bitmap to be drawn
+        @param dst      The destination rectangle where the scaled/translated
+                        image will be drawn
+        @param paint    The paint used to draw the bitmap, or NULL
+    */
+    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+                                const SkRect& dst, const SkPaint* paint = NULL);
+
+    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+                                  const SkPaint* paint = NULL);
+    
+    /** Draw the specified bitmap, with its top/left corner at (x,y),
+        NOT transformed by the current matrix. Note: if the paint
+        contains a maskfilter that generates a mask which extends beyond the
+        bitmap's original width/height, then the bitmap will be drawn as if it
+        were in a Shader with CLAMP mode. Thus the color outside of the original
+        width/height will be the edge color replicated.
+        @param bitmap   The bitmap to be drawn
+        @param left     The position of the left side of the bitmap being drawn
+        @param top      The position of the top side of the bitmap being drawn
+        @param paint    The paint used to draw the bitmap, or NULL
+    */
+    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+                            const SkPaint* paint = NULL);
+
+    /** Draw the text, with origin at (x,y), using the specified paint.
+        The origin is interpreted based on the Align setting in the paint.
+        @param text The text to be drawn
+        @param byteLength   The number of bytes to read from the text parameter
+        @param x        The x-coordinate of the origin of the text being drawn
+        @param y        The y-coordinate of the origin of the text being drawn
+        @param paint    The paint used for the text (e.g. color, size, style)
+    */
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint);
+
+    /** Draw the text, with each character/glyph origin specified by the pos[]
+        array. The origin is interpreted by the Align setting in the paint. 
+        @param text The text to be drawn
+        @param byteLength   The number of bytes to read from the text parameter
+        @param pos      Array of positions, used to position each character
+        @param paint    The paint used for the text (e.g. color, size, style)
+        */
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint);
+    
+    /** Draw the text, with each character/glyph origin specified by the x
+        coordinate taken from the xpos[] array, and the y from the constY param.
+        The origin is interpreted by the Align setting in the paint. 
+        @param text The text to be drawn
+        @param byteLength   The number of bytes to read from the text parameter
+        @param xpos     Array of x-positions, used to position each character
+        @param constY   The shared Y coordinate for all of the positions
+        @param paint    The paint used for the text (e.g. color, size, style)
+        */
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint);
+    
+    /** Draw the text, with origin at (x,y), using the specified paint, along
+        the specified path. The paint's Align setting determins where along the
+        path to start the text.
+        @param text The text to be drawn
+        @param byteLength   The number of bytes to read from the text parameter
+        @param path         The path the text should follow for its baseline
+        @param hOffset      The distance along the path to add to the text's
+                            starting position
+        @param vOffset      The distance above(-) or below(+) the path to
+                            position the text
+        @param paint        The paint used for the text
+    */
+    void drawTextOnPathHV(const void* text, size_t byteLength,
+                          const SkPath& path, SkScalar hOffset,
+                          SkScalar vOffset, const SkPaint& paint);
+
+    /** Draw the text, with origin at (x,y), using the specified paint, along
+        the specified path. The paint's Align setting determins where along the
+        path to start the text.
+        @param text The text to be drawn
+        @param byteLength   The number of bytes to read from the text parameter
+        @param path         The path the text should follow for its baseline
+        @param matrix       (may be null) Applied to the text before it is
+                            mapped onto the path
+        @param paint        The paint used for the text
+        */
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint);
+
+    /** Draw the picture into this canvas. This method effective brackets the
+        playback of the picture's draw calls with save/restore, so the state
+        of this canvas will be unchanged after this call. This contrasts with
+        the more immediate method SkPicture::draw(), which does not bracket
+        the canvas with save/restore, thus the canvas may be left in a changed
+        state after the call.
+        @param picture The recorded drawing commands to playback into this
+                       canvas.
+    */
+    virtual void drawPicture(SkPicture& picture);
+    
+    enum VertexMode {
+        kTriangles_VertexMode,
+        kTriangleStrip_VertexMode,
+        kTriangleFan_VertexMode
+    };
+    
+    /** Draw the array of vertices, interpreted as triangles (based on mode).
+        @param vmode How to interpret the array of vertices
+        @param vertexCount The number of points in the vertices array (and
+                    corresponding texs and colors arrays if non-null)
+        @param vertices Array of vertices for the mesh
+        @param texs May be null. If not null, specifies the coordinate
+                             in texture space for each vertex.
+        @param colors May be null. If not null, specifies a color for each
+                      vertex, to be interpolated across the triangle.
+        @param xmode Used if both texs and colors are present. In this
+                    case the colors are combined with the texture using mode,
+                    before being drawn using the paint. If mode is null, then
+                    the porter-duff MULTIPLY mode is used.
+        @param indices If not null, array of indices to reference into the
+                    vertex (texs, colors) array.
+        @param indexCount number of entries in the indices array (if not null)
+        @param paint Specifies the shader/texture if present. 
+    */
+    virtual void drawVertices(VertexMode vmode, int vertexCount,
+                              const SkPoint vertices[], const SkPoint texs[],
+                              const SkColor colors[], SkXfermode* xmode,
+                              const uint16_t indices[], int indexCount,
+                              const SkPaint& paint);
+
+    //////////////////////////////////////////////////////////////////////////
+    
+    /** Get the current bounder object.
+        The bounder's reference count is unchaged.
+        @return the canva's bounder (or NULL).
+    */
+    SkBounder*  getBounder() const { return fBounder; }
+
+    /** Set a new bounder (or NULL).
+        Pass NULL to clear any previous bounder.
+        As a convenience, the parameter passed is also returned.
+        If a previous bounder exists, its reference count is decremented.
+        If bounder is not NULL, its reference count is incremented.
+        @param bounder the new bounder (or NULL) to be installed in the canvas
+        @return the set bounder object
+    */
+    virtual SkBounder* setBounder(SkBounder* bounder);
+ 
+    /** Get the current filter object. The filter's reference count is not
+        affected. The filter is part of the state this is affected by
+        save/restore.
+        @return the canvas' filter (or NULL).
+    */
+    SkDrawFilter* getDrawFilter() const;
+    
+    /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
+        As a convenience, the parameter is returned. If an existing filter
+        exists, its refcnt is decrement. If the new filter is not null, its
+        refcnt is incremented. The filter is part of the state this is affected
+        by save/restore.
+        @param filter the new filter (or NULL)
+        @return the new filter
+    */
+    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
+
+    //////////////////////////////////////////////////////////////////////////
+
+    /** Return the current matrix on the canvas.
+        This does not account for the translate in any of the devices.
+        @return The current matrix on the canvas.
+    */
+    const SkMatrix& getTotalMatrix() const;
+
+    /** Return the current device clip (concatenation of all clip calls).
+        This does not account for the translate in any of the devices.
+        @return the current device clip (concatenation of all clip calls).
+    */
+    const SkRegion& getTotalClip() const;
+
+    /** May be overridden by subclasses. This returns a compatible device
+        for this canvas, with the specified config/width/height. If isOpaque
+        is true, then the underlying bitmap is optimized to assume that every
+        pixel will be drawn to, and thus it does not need to clear the alpha
+        channel ahead of time (assuming the specified config supports per-pixel
+        alpha.) If isOpaque is false, then the bitmap should clear its alpha
+        channel.
+    */
+    virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
+                                   bool isOpaque, bool isForLayer);
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** After calling saveLayer(), there can be any number of devices that make
+        up the top-most drawing area. LayerIter can be used to iterate through
+        those devices. Note that the iterator is only valid until the next API
+        call made on the canvas. Ownership of all pointers in the iterator stays
+        with the canvas, so none of them should be modified or deleted.
+    */
+    class LayerIter /*: SkNoncopyable*/ {
+    public:
+        /** Initialize iterator with canvas, and set values for 1st device */
+        LayerIter(SkCanvas*, bool skipEmptyClips);
+        ~LayerIter();
+        
+        /** Return true if the iterator is done */
+        bool done() const { return fDone; }
+        /** Cycle to the next device */
+        void next();
+        
+        // These reflect the current device in the iterator
+
+        SkDevice*       device() const;
+        const SkMatrix& matrix() const;
+        const SkRegion& clip() const;
+        const SkPaint&  paint() const;
+        int             x() const;
+        int             y() const;
+        
+    private:
+        // used to embed the SkDrawIter object directly in our instance, w/o
+        // having to expose that class def to the public. There is an assert
+        // in our constructor to ensure that fStorage is large enough
+        // (though needs to be a compile-time-assert!). We use intptr_t to work
+        // safely with 32 and 64 bit machines (to ensure the storage is enough)
+        intptr_t          fStorage[12];
+        class SkDrawIter* fImpl;    // this points at fStorage
+        SkPaint           fDefaultPaint;
+        bool              fDone;
+    };
+
+protected:
+    // all of the drawBitmap variants call this guy
+    virtual void commonDrawBitmap(const SkBitmap&, const SkMatrix& m,
+                                  const SkPaint& paint);
+    
+private:
+    class MCRec;
+
+    SkDeque     fMCStack;
+    // points to top of stack
+    MCRec*      fMCRec;
+    // the first N recs that can fit here mean we won't call malloc
+    uint32_t    fMCRecStorage[32];
+
+    SkBounder*  fBounder;
+
+    void prepareForDeviceDraw(SkDevice*);
+    
+    bool fDeviceCMDirty;            // cleared by updateDeviceCMCache()
+    void updateDeviceCMCache();
+
+    friend class SkDrawIter;    // needs setupDrawForLayerDevice()
+
+    SkDevice* init(SkDevice*);
+    void internalDrawBitmap(const SkBitmap&, const SkMatrix& m,
+                                  const SkPaint* paint);
+    void drawDevice(SkDevice*, int x, int y, const SkPaint*);
+    // shared by save() and saveLayer()
+    int internalSave(SaveFlags flags);
+    void internalRestore();
+    
+    /*  These maintain a cache of the clip bounds in local coordinates,
+        (converted to 2s-compliment if floats are slow).
+     */
+    mutable SkRectCompareType fLocalBoundsCompareType;
+    mutable bool              fLocalBoundsCompareTypeDirty;
+
+    const SkRectCompareType& getLocalClipBoundsCompareType() const {
+        if (fLocalBoundsCompareTypeDirty) {
+            this->computeLocalClipBoundsCompareType();
+            fLocalBoundsCompareTypeDirty = false;
+        }
+        return fLocalBoundsCompareType;
+    }
+    void computeLocalClipBoundsCompareType() const;
+};
+
+/** Stack helper class to automatically call restoreToCount() on the canvas
+    when this object goes out of scope. Use this to guarantee that the canvas
+    is restored to a known state.
+*/
+class SkAutoCanvasRestore : SkNoncopyable {
+public:
+    SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
+        SkASSERT(canvas);
+        fSaveCount = canvas->getSaveCount();
+        if (doSave) {
+            canvas->save();
+        }
+    }
+    ~SkAutoCanvasRestore() {
+        fCanvas->restoreToCount(fSaveCount);
+    }
+
+private:
+    SkCanvas*   fCanvas;
+    int         fSaveCount;
+};
+
+#endif
+
diff --git a/include/core/SkChunkAlloc.h b/include/core/SkChunkAlloc.h
new file mode 100644
index 0000000..0e9ad18
--- /dev/null
+++ b/include/core/SkChunkAlloc.h
@@ -0,0 +1,61 @@
+/*
+ * 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 SkChunkAlloc_DEFINED
+#define SkChunkAlloc_DEFINED
+
+#include "SkTypes.h"
+
+class SkChunkAlloc : SkNoncopyable {
+public:
+    SkChunkAlloc(size_t minSize);
+    ~SkChunkAlloc();
+
+    /** Free up all allocated blocks. This invalidates all returned
+        pointers.
+    */
+    void reset();
+
+    /** Reuse all allocated blocks. This invalidates all returned
+        pointers (like reset) but doesn't necessarily free up all
+        of the privately allocated blocks. This is more efficient
+        if you plan to reuse the allocator multiple times.
+    */
+    void reuse();
+
+    enum AllocFailType {
+        kReturnNil_AllocFailType,
+        kThrow_AllocFailType
+    };
+    
+    void* alloc(size_t bytes, AllocFailType);
+    void* allocThrow(size_t bytes) {
+        return this->alloc(bytes, kThrow_AllocFailType);
+    }
+    
+    size_t totalCapacity() const { return fTotalCapacity; }
+    
+private:
+    struct Block;
+    Block*  fBlock;
+    size_t  fMinSize;
+    Block*  fPool;
+    size_t  fTotalCapacity;
+
+    Block* newBlock(size_t bytes, AllocFailType ftype);
+};
+
+#endif
diff --git a/include/core/SkColor.h b/include/core/SkColor.h
new file mode 100644
index 0000000..c97a8ec
--- /dev/null
+++ b/include/core/SkColor.h
@@ -0,0 +1,155 @@
+/*
+ * 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 SkColor_DEFINED
+#define SkColor_DEFINED
+
+#include "SkScalar.h"
+
+/** \file SkColor.h
+
+    Types and macros for colors
+*/
+
+/** 8-bit type for an alpha value. 0xFF is 100% opaque, 0x00 is 100% transparent.
+*/
+typedef uint8_t SkAlpha;
+/** 32 bit ARGB color value, not premultiplied. The color components are always in
+    a known order. This is different from SkPMColor, which has its bytes in a configuration
+    dependent order, to match the format of kARGB32 bitmaps. SkColor is the type used to
+    specify colors in SkPaint and in gradients.
+*/
+typedef uint32_t SkColor;
+
+/** Return a SkColor value from 8 bit component values
+*/
+static inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
+{
+    SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255);
+
+    return (a << 24) | (r << 16) | (g << 8) | (b << 0);
+}
+
+/** Return a SkColor value from 8 bit component values, with an implied value
+    of 0xFF for alpha (fully opaque)
+*/
+#define SkColorSetRGB(r, g, b)  SkColorSetARGB(0xFF, r, g, b)
+
+/** return the alpha byte from a SkColor value */
+#define SkColorGetA(color)      (((color) >> 24) & 0xFF)
+/** return the red byte from a SkColor value */
+#define SkColorGetR(color)      (((color) >> 16) & 0xFF)
+/** return the green byte from a SkColor value */
+#define SkColorGetG(color)      (((color) >>  8) & 0xFF)
+/** return the blue byte from a SkColor value */
+#define SkColorGetB(color)      (((color) >>  0) & 0xFF)
+
+static inline SkColor SkColorSetA(SkColor c, U8CPU a) {
+    return (c & 0x00FFFFFF) | (a << 24);
+}
+
+// common colors
+
+#define SK_ColorBLACK   0xFF000000  //!< black SkColor value
+#define SK_ColorDKGRAY  0xFF444444  //!< dark gray SkColor value
+#define SK_ColorGRAY    0xFF888888  //!< gray SkColor value
+#define SK_ColorLTGRAY  0xFFCCCCCC  //!< light gray SkColor value
+#define SK_ColorWHITE   0xFFFFFFFF  //!< white SkColor value
+
+#define SK_ColorRED     0xFFFF0000  //!< red SkColor value
+#define SK_ColorGREEN   0xFF00FF00  //!< green SkColor value
+#define SK_ColorBLUE    0xFF0000FF  //!< blue SkColor value
+#define SK_ColorYELLOW  0xFFFFFF00  //!< yellow SkColor value
+#define SK_ColorCYAN    0xFF00FFFF  //!< cyan SkColor value
+#define SK_ColorMAGENTA 0xFFFF00FF  //!< magenta SkColor value
+
+////////////////////////////////////////////////////////////////////////
+
+/** Convert RGB components to HSV.
+        hsv[0] is Hue [0 .. 360)
+        hsv[1] is Saturation [0...1]
+        hsv[2] is Value [0...1]
+    @param red  red component value [0..255]
+    @param green  green component value [0..255]
+    @param blue  blue component value [0..255]
+    @param hsv  3 element array which holds the resulting HSV components.
+*/
+void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
+
+/** Convert the argb color to its HSV components.
+        hsv[0] is Hue [0 .. 360)
+        hsv[1] is Saturation [0...1]
+        hsv[2] is Value [0...1]
+    @param color the argb color to convert. Note: the alpha component is ignored.
+    @param hsv  3 element array which holds the resulting HSV components.
+*/
+static inline void SkColorToHSV(SkColor color, SkScalar hsv[3])
+{
+    SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);
+}
+
+/** Convert HSV components to an ARGB color. The alpha component is passed through unchanged.
+        hsv[0] is Hue [0 .. 360)
+        hsv[1] is Saturation [0...1]
+        hsv[2] is Value [0...1]
+    If hsv values are out of range, they are pinned.
+    @param alpha the alpha component of the returned argb color.
+    @param hsv  3 element array which holds the input HSV components.
+    @return the resulting argb color
+*/
+SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
+
+/** Convert HSV components to an ARGB color. The alpha component set to 0xFF.
+        hsv[0] is Hue [0 .. 360)
+        hsv[1] is Saturation [0...1]
+        hsv[2] is Value [0...1]
+    If hsv values are out of range, they are pinned.
+    @param hsv  3 element array which holds the input HSV components.
+    @return the resulting argb color
+*/
+static inline SkColor SkHSVToColor(const SkScalar hsv[3])
+{
+    return SkHSVToColor(0xFF, hsv);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+/** 32 bit ARGB color value, premultiplied. The byte order for this value is
+    configuration dependent, matching the format of kARGB32 bitmaps. This is different
+    from SkColor, which is nonpremultiplied, and is always in the same byte order.
+*/
+typedef uint32_t SkPMColor;
+
+/** Return a SkPMColor value from unpremultiplied 8 bit component values
+*/
+SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+/** Return a SkPMColor value from a SkColor value. This is done by multiplying the color
+    components by the color's alpha, and by arranging the bytes in a configuration
+    dependent order, to match the format of kARGB32 bitmaps.
+*/
+SkPMColor SkPreMultiplyColor(SkColor c);
+
+/** Define a function pointer type for combining two premultiplied colors
+*/
+typedef SkPMColor (*SkXfermodeProc)(SkPMColor src, SkPMColor dst);
+
+/** Define a function pointer type for combining a premultiplied src color
+    and a 16bit device color.
+*/
+typedef uint16_t (*SkXfermodeProc16)(SkPMColor src, uint16_t dst);
+
+#endif
+
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
new file mode 100644
index 0000000..a1b3171
--- /dev/null
+++ b/include/core/SkColorFilter.h
@@ -0,0 +1,125 @@
+/*
+ * 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 SkColorFilter_DEFINED
+#define SkColorFilter_DEFINED
+
+#include "SkColor.h"
+#include "SkFlattenable.h"
+#include "SkPorterDuff.h"
+
+class SkColorFilter : public SkFlattenable {
+public:
+    /** Called with a scanline of colors, as if there was a shader installed.
+        The implementation writes out its filtered version into result[].
+        Note: shader and result may be the same buffer.
+        @param src      array of colors, possibly generated by a shader
+        @param count    the number of entries in the src[] and result[] arrays
+        @param result   written by the filter
+    */
+    virtual void filterSpan(const SkPMColor src[], int count,
+                            SkPMColor result[]) = 0;
+    /** Called with a scanline of colors, as if there was a shader installed.
+        The implementation writes out its filtered version into result[].
+        Note: shader and result may be the same buffer.
+        @param src      array of colors, possibly generated by a shader
+        @param count    the number of entries in the src[] and result[] arrays
+        @param result   written by the filter
+    */
+    virtual void filterSpan16(const uint16_t shader[], int count,
+                              uint16_t result[]);
+
+    enum Flags {
+        /** If set the filter methods will not change the alpha channel of the
+            colors.
+        */
+        kAlphaUnchanged_Flag = 0x01,
+        /** If set, this subclass implements filterSpan16(). If this flag is
+            set, then kAlphaUnchanged_Flag must also be set.
+        */
+        kHasFilter16_Flag    = 0x02
+    };
+
+    /** Returns the flags for this filter. Override in subclasses to return
+        custom flags.
+    */
+    virtual uint32_t getFlags() { return 0; }
+
+    /** Create a colorfilter that uses the specified color and porter-duff mode.
+        If porterDuffMode is DST, this function will return NULL (since that
+        mode will have no effect on the result).
+        @param srcColor The source color used with the specified mode
+        @param mode     The porter-duff mode that is applied to each color in
+                        the colorfilter's filterSpan[16,32] methods
+        @return colorfilter object that applies the src color and porter-duff
+                mode, or NULL if the mode will have no effect.
+    */
+    static SkColorFilter* CreatePorterDuffFilter(SkColor srcColor,
+                                                 SkPorterDuff::Mode mode);
+
+    /** Create a colorfilter that calls through to the specified procs to
+        filter the colors. The SkXfermodeProc parameter must be non-null, but
+        the SkXfermodeProc16 is optional, and may be null.
+    */
+    static SkColorFilter* CreatXfermodeProcFilter(SkColor srcColor,
+                                              SkXfermodeProc proc,
+                                              SkXfermodeProc16 proc16 = NULL);
+
+    /** Create a colorfilter that multiplies the RGB channels by one color, and
+        then adds a second color, pinning the result for each component to
+        [0..255]. The alpha components of the mul and add arguments
+        are ignored.
+    */
+    static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
+    
+protected:
+    SkColorFilter() {}
+    SkColorFilter(SkFlattenableReadBuffer& rb) : INHERITED(rb) {}
+    
+private:
+    typedef SkFlattenable INHERITED;
+};
+
+#include "SkShader.h"
+
+class SkFilterShader : public SkShader {
+public:
+    SkFilterShader(SkShader* shader, SkColorFilter* filter);
+    virtual ~SkFilterShader();
+
+    // override
+    virtual uint32_t getFlags();
+    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
+                            const SkMatrix& matrix);
+    virtual void shadeSpan(int x, int y, SkPMColor result[], int count);
+    virtual void shadeSpan16(int x, int y, uint16_t result[], int count);
+    virtual void beginSession();
+    virtual void endSession();
+    
+protected:
+    SkFilterShader(SkFlattenableReadBuffer& );
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory() { return CreateProc; }
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 
+        return SkNEW_ARGS(SkFilterShader, (buffer)); }
+    SkShader*       fShader;
+    SkColorFilter*  fFilter;
+    
+    typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/include/core/SkColorPriv.h b/include/core/SkColorPriv.h
new file mode 100644
index 0000000..041c038
--- /dev/null
+++ b/include/core/SkColorPriv.h
@@ -0,0 +1,657 @@
+/*
+ * 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 SkColorPriv_DEFINED
+#define SkColorPriv_DEFINED
+
+// turn this own for extra debug checking when blending onto 565
+#ifdef SK_DEBUG
+    #define CHECK_FOR_565_OVERFLOW
+#endif
+
+#include "SkColor.h"
+#include "SkMath.h"
+
+/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
+    byte into a scale value, so that we can say scale * value >> 8 instead of
+    alpha * value / 255.
+ 
+    In debugging, asserts that alpha is 0..255
+*/
+static inline unsigned SkAlpha255To256(U8CPU alpha) {
+    SkASSERT(SkToU8(alpha) == alpha);
+    return alpha + (alpha >> 7);
+}
+
+/** Multiplify value by 0..256, and shift the result down 8
+    (i.e. return (value * alpha256) >> 8)
+ */
+#define SkAlphaMul(value, alpha256)     (SkMulS16(value, alpha256) >> 8)
+
+//  The caller may want negative values, so keep all params signed (int)
+//  so we don't accidentally slip into unsigned math and lose the sign
+//  extension when we shift (in SkAlphaMul)
+inline int SkAlphaBlend(int src, int dst, int scale256) {
+    SkASSERT((unsigned)scale256 <= 256);
+    return dst + SkAlphaMul(src - dst, scale256);
+}
+
+#define SK_R16_BITS     5
+#define SK_G16_BITS     6
+#define SK_B16_BITS     5
+
+#define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
+#define SK_G16_SHIFT    (SK_B16_BITS)
+#define SK_B16_SHIFT    0
+
+#define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
+#define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
+#define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
+
+#define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
+#define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
+#define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
+
+#define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
+#define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
+#define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
+
+static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
+    SkASSERT(r <= SK_R16_MASK);
+    SkASSERT(g <= SK_G16_MASK);
+    SkASSERT(b <= SK_B16_MASK);
+
+    return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
+}
+
+#define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
+#define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
+#define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
+
+/** Expand the 16bit color into a 32bit value that can be scaled all at once
+    by a value up to 32. Used in conjunction with SkCompact_rgb_16.
+*/
+static inline uint32_t SkExpand_rgb_16(U16CPU c) {
+    SkASSERT(c == (uint16_t)c);
+
+    return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
+}
+
+/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
+    color value. The computation yields only 16bits of valid data, but we claim
+    to return 32bits, so that the compiler won't generate extra instructions to
+    "clean" the top 16bits. However, the top 16 can contain garbage, so it is
+    up to the caller to safely ignore them.
+*/
+static inline U16CPU SkCompact_rgb_16(uint32_t c) {
+    return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
+}
+
+/** Scale the 16bit color value by the 0..256 scale parameter.
+    The computation yields only 16bits of valid data, but we claim
+    to return 32bits, so that the compiler won't generate extra instructions to
+    "clean" the top 16bits.
+*/
+static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
+    return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
+}
+
+// this helper explicitly returns a clean 16bit value (but slower)
+#define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
+
+/** Blend src and dst 16bit colors by the 0..256 scale parameter.
+    The computation yields only 16bits of valid data, but we claim
+    to return 32bits, so that the compiler won't generate extra instructions to
+    "clean" the top 16bits.
+*/
+static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
+    SkASSERT((unsigned)srcScale <= 256);
+
+    srcScale >>= 3;
+
+    uint32_t src32 = SkExpand_rgb_16(src);
+    uint32_t dst32 = SkExpand_rgb_16(dst);
+    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
+}
+
+static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
+                                int srcScale, int count) {
+    SkASSERT(count > 0);
+    SkASSERT((unsigned)srcScale <= 256);
+ 
+    srcScale >>= 3;
+
+    do {
+        uint32_t src32 = SkExpand_rgb_16(*src++);
+        uint32_t dst32 = SkExpand_rgb_16(*dst);
+        *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
+    } while (--count > 0);
+}
+
+#ifdef SK_DEBUG
+    static U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
+        SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
+        SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
+        SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
+        
+        return a + b;
+    }
+#else
+    #define SkRGB16Add(a, b)  ((a) + (b))
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+#define SK_A32_BITS     8
+#define SK_R32_BITS     8
+#define SK_G32_BITS     8
+#define SK_B32_BITS     8
+
+/* we check to see if the SHIFT value has already been defined (SkUserConfig.h)
+    if not, we define it ourself to some default values. We default to OpenGL
+    order (in memory: r,g,b,a)
+*/
+#ifndef SK_A32_SHIFT
+    #ifdef SK_CPU_BENDIAN
+        #define SK_R32_SHIFT    24
+        #define SK_G32_SHIFT    16
+        #define SK_B32_SHIFT    8
+        #define SK_A32_SHIFT    0
+    #else
+        #define SK_R32_SHIFT    0
+        #define SK_G32_SHIFT    8
+        #define SK_B32_SHIFT    16
+        #define SK_A32_SHIFT    24
+    #endif
+#endif
+
+#define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
+#define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
+#define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
+#define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
+
+#define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
+#define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
+#define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
+#define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
+
+#define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
+#define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
+#define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
+#define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
+
+#ifdef SK_DEBUG
+    inline void SkPMColorAssert(SkPMColor c) {
+        unsigned a = SkGetPackedA32(c);
+        unsigned r = SkGetPackedR32(c);
+        unsigned g = SkGetPackedG32(c);
+        unsigned b = SkGetPackedB32(c);
+        
+        SkA32Assert(a);
+        SkASSERT(r <= a);
+        SkASSERT(g <= a);
+        SkASSERT(b <= a);
+    }
+#else
+    #define SkPMColorAssert(c)
+#endif
+
+inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+    SkA32Assert(a);
+    SkASSERT(r <= a);
+    SkASSERT(g <= a);
+    SkASSERT(b <= a);
+
+    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+extern const uint32_t gMask_00FF00FF;
+
+inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
+    uint32_t mask = gMask_00FF00FF;
+//    uint32_t mask = 0xFF00FF;
+
+    uint32_t rb = ((c & mask) * scale) >> 8;
+    uint32_t ag = ((c >> 8) & mask) * scale;
+    return (rb & mask) | (ag & ~mask);
+}
+
+inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
+    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
+}
+
+inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
+    SkASSERT((unsigned)aa <= 255);
+
+    unsigned src_scale = SkAlpha255To256(aa);
+    unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
+
+    return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Convert a 32bit pixel to a 16bit pixel (no dither)
+
+#define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
+#define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
+#define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
+
+#ifdef SK_DEBUG
+    inline unsigned SkR32ToR16(unsigned r)
+    {
+        SkR32Assert(r);
+        return SkR32ToR16_MACRO(r);
+    }
+    inline unsigned SkG32ToG16(unsigned g)
+    {
+        SkG32Assert(g);
+        return SkG32ToG16_MACRO(g);
+    }
+    inline unsigned SkB32ToB16(unsigned b)
+    {
+        SkB32Assert(b);
+        return SkB32ToB16_MACRO(b);
+    }
+#else
+    #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
+    #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
+    #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
+#endif
+
+#define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
+#define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
+#define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
+
+inline U16CPU SkPixel32ToPixel16(SkPMColor c)
+{
+    unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
+    unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
+    unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
+    return r | g | b;
+}
+
+inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b)
+{
+    return  (SkR32ToR16(r) << SK_R16_SHIFT) |
+            (SkG32ToG16(g) << SK_G16_SHIFT) |
+            (SkB32ToB16(b) << SK_B16_SHIFT);
+}
+
+#define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Fast dither from 32->16
+
+#define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
+
+inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b)
+{
+    r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
+    g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
+    b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
+    
+    return SkPackRGB16(r, g, b);
+}
+
+inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c)
+{
+    return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
+}
+
+/*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
+    It is now suitable for combining with a scaled expanded_rgb_16 color
+    as in SkSrcOver32To16().
+    We must do this 565 high-bit replication, in order for the subsequent add
+    to saturate properly (and not overflow). If we take the 8 bits as is, it is
+    possible to overflow.
+*/
+static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c)
+{
+    unsigned sr = SkPacked32ToR16(c);
+    unsigned sg = SkPacked32ToG16(c);
+    unsigned sb = SkPacked32ToB16(c);
+    
+    sr = (sr << 5) | sr;
+    sg = (sg << 5) | (sg >> 1);
+    sb = (sb << 5) | sb;
+    return (sr << 11) | (sg << 21) | (sb << 0);
+}
+
+/*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
+    (with dirt in the high 16bits, so caller beware).
+*/
+static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
+    unsigned sr = SkGetPackedR32(src);
+    unsigned sg = SkGetPackedG32(src);
+    unsigned sb = SkGetPackedB32(src);
+    
+    unsigned dr = SkGetPackedR16(dst);
+    unsigned dg = SkGetPackedG16(dst);
+    unsigned db = SkGetPackedB16(dst);
+    
+    unsigned isa = 255 - SkGetPackedA32(src);
+    
+    dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
+    dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
+    db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
+    
+    return SkPackRGB16(dr, dg, db);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Convert a 16bit pixel to a 32bit pixel
+
+inline unsigned SkR16ToR32(unsigned r)
+{
+    return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
+}
+inline unsigned SkG16ToG32(unsigned g)
+{
+    return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
+}
+inline unsigned SkB16ToB32(unsigned b)
+{
+    return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
+}
+
+#define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
+#define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
+#define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
+
+inline SkPMColor SkPixel16ToPixel32(U16CPU src)
+{
+    SkASSERT(src == SkToU16(src));
+
+    unsigned    r = SkPacked16ToR32(src);
+    unsigned    g = SkPacked16ToG32(src);
+    unsigned    b = SkPacked16ToB32(src);
+
+    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
+    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
+    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
+
+    return SkPackARGB32(0xFF, r, g, b);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef uint16_t SkPMColor16;
+
+// Put in OpenGL order (r g b a)
+#define SK_A4444_SHIFT    0
+#define SK_R4444_SHIFT    12
+#define SK_G4444_SHIFT    8
+#define SK_B4444_SHIFT    4
+
+#define SkA32To4444(a)  ((unsigned)(a) >> 4)
+#define SkR32To4444(r)  ((unsigned)(r) >> 4)
+#define SkG32To4444(g)  ((unsigned)(g) >> 4)
+#define SkB32To4444(b)  ((unsigned)(b) >> 4)
+
+static U8CPU SkReplicateNibble(unsigned nib)
+{
+    SkASSERT(nib <= 0xF);
+    return (nib << 4) | nib;
+}
+
+#define SkA4444ToA32(a)     SkReplicateNibble(a)
+#define SkR4444ToR32(r)     SkReplicateNibble(r)
+#define SkG4444ToG32(g)     SkReplicateNibble(g)
+#define SkB4444ToB32(b)     SkReplicateNibble(b)
+
+#define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
+#define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
+#define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
+#define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
+
+#define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
+#define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
+#define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
+#define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
+
+#ifdef SK_DEBUG
+static inline void SkPMColor16Assert(U16CPU c)
+{
+    unsigned a = SkGetPackedA4444(c);
+    unsigned r = SkGetPackedR4444(c);
+    unsigned g = SkGetPackedG4444(c);
+    unsigned b = SkGetPackedB4444(c);
+    
+    SkASSERT(a <= 0xF);
+    SkASSERT(r <= a);
+    SkASSERT(g <= a);
+    SkASSERT(b <= a);
+}
+#else
+#define SkPMColor16Assert(c)
+#endif
+
+static inline unsigned SkAlpha15To16(unsigned a)
+{
+    SkASSERT(a <= 0xF);
+    return a + (a >> 3);
+}
+
+#ifdef SK_DEBUG
+    static inline int SkAlphaMul4(int value, int scale)
+    {
+        SkASSERT((unsigned)scale <= 0x10);
+        return value * scale >> 4;
+    }
+#else
+    #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
+#endif
+
+static inline unsigned SkR4444ToR565(unsigned r)
+{
+    SkASSERT(r <= 0xF);
+    return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
+}
+
+static inline unsigned SkG4444ToG565(unsigned g)
+{
+    SkASSERT(g <= 0xF);
+    return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
+}
+
+static inline unsigned SkB4444ToB565(unsigned b)
+{
+    SkASSERT(b <= 0xF);
+    return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
+}
+
+static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
+                                         unsigned g, unsigned b)
+{
+    SkASSERT(a <= 0xF);
+    SkASSERT(r <= a);
+    SkASSERT(g <= a);
+    SkASSERT(b <= a);
+    
+    return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
+                         (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
+}
+
+extern const uint16_t gMask_0F0F;
+
+inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale)
+{
+    SkASSERT(scale <= 16);
+
+    const unsigned mask = 0xF0F;    //gMask_0F0F;
+    
+#if 0
+    unsigned rb = ((c & mask) * scale) >> 4;
+    unsigned ag = ((c >> 4) & mask) * scale;
+    return (rb & mask) | (ag & ~mask);
+#else
+    c = (c & mask) | ((c & (mask << 4)) << 12);
+    c = c * scale >> 4;
+    return (c & mask) | ((c >> 12) & (mask << 4));
+#endif
+}
+
+/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
+    once by a value up to 16. Used in conjunction with SkCompact_4444.
+*/
+inline uint32_t SkExpand_4444(U16CPU c)
+{
+    SkASSERT(c == (uint16_t)c);
+    
+    const unsigned mask = 0xF0F;    //gMask_0F0F;
+    return (c & mask) | ((c & ~mask) << 12);
+}
+
+/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
+    NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
+    It does this for speed, since if it is being written directly to 16bits of
+    memory, the top 16bits will be ignored. Casting the result to uint16_t here
+    would add 2 more instructions, slow us down. It is up to the caller to
+    perform the cast if needed.
+*/
+static inline U16CPU SkCompact_4444(uint32_t c)
+{
+    const unsigned mask = 0xF0F;    //gMask_0F0F;
+    return (c & mask) | ((c >> 12) & ~mask);
+}
+
+static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d)
+{
+    unsigned sa = SkGetPackedA4444(s);
+    unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
+    unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
+    unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
+
+    // To avoid overflow, we have to clear the low bit of the synthetic sg
+    // if the src alpha is <= 7.
+    // to see why, try blending 0x4444 on top of 565-white and watch green
+    // overflow (sum == 64)
+    sg &= ~(~(sa >> 3) & 1);
+
+    unsigned scale = SkAlpha15To16(15 - sa);
+    unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
+    unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
+    unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
+    
+#if 0
+    if (sg + dg > 63) {
+        SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
+    }
+#endif
+    return SkPackRGB16(sr + dr, sg + dg, sb + db);
+}
+
+static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16)
+{
+    SkASSERT((unsigned)scale16 <= 16);
+    
+    return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
+}
+
+static inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16)
+{
+    SkASSERT((unsigned)scale16 <= 16);
+    
+    uint32_t src32 = SkExpand_4444(src) * scale16;
+    // the scaled srcAlpha is the bottom byte
+#ifdef SK_DEBUG
+    {
+        unsigned srcA = SkGetPackedA4444(src) * scale16;
+        SkASSERT(srcA == (src32 & 0xFF));
+    }
+#endif
+    unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
+    uint32_t dst32 = SkExpand_4444(dst) * dstScale;
+    return SkCompact_4444((src32 + dst32) >> 4);
+}
+
+static inline SkPMColor SkPixel4444ToPixel32(U16CPU c)
+{
+    uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
+                 (SkGetPackedR4444(c) << SK_R32_SHIFT) |
+                 (SkGetPackedG4444(c) << SK_G32_SHIFT) |
+                 (SkGetPackedB4444(c) << SK_B32_SHIFT);
+    return d | (d << 4);
+}
+
+static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c)
+{
+    return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
+    (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
+    (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
+    (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
+}
+
+// cheap 2x2 dither
+static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
+                                               U8CPU g, U8CPU b)
+{
+    a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
+    r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
+    g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
+    b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
+    
+    return SkPackARGB4444(a, r, g, b);
+}
+
+static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c)
+{
+    return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
+                                SkGetPackedG32(c), SkGetPackedB32(c));
+}
+
+/*  Assumes 16bit is in standard RGBA order.
+    Transforms a normal ARGB_8888 into the same byte order as
+    expanded ARGB_4444, but keeps each component 8bits
+*/
+static uint32_t SkExpand_8888(SkPMColor c)
+{
+    return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
+            (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
+            (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
+            (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
+}
+
+/*  Undo the operation of SkExpand_8888, turning the argument back into
+    a SkPMColor.
+*/
+static SkPMColor SkCompact_8888(uint32_t c)
+{
+    return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
+            (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
+            (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
+            (((c >>  0) & 0xFF) << SK_A32_SHIFT);
+}
+
+/*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
+    but this routine just keeps the high 4bits of each component in the low
+    4bits of the result (just like a newly expanded PMColor16).
+*/
+static uint32_t SkExpand32_4444(SkPMColor c)
+{
+    return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
+            (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
+            (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
+            (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
+}
+
+// takes two values and alternamtes them as part of a memset16
+// used for cheap 2x2 dithering when the colors are opaque
+void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
+
+#endif
+
diff --git a/include/core/SkColorShader.h b/include/core/SkColorShader.h
new file mode 100644
index 0000000..f9c3dc3
--- /dev/null
+++ b/include/core/SkColorShader.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkColorShader_DEFINED
+#define SkColorShader_DEFINED
+
+#include "SkShader.h"
+
+/** \class SkColorShader
+    A Shader that represents a single color. In general, this effect can be
+    accomplished by just using the color field on the paint, but if an
+    actual shader object is needed, this provides that feature.
+*/
+class SkColorShader : public SkShader {
+public:
+    /** Create a ColorShader that will inherit its color from the Paint
+        at draw time.
+    */
+    SkColorShader() : fInheritColor(true) {}
+    /** Create a ColorShader that ignores the color in the paint, and uses the
+        specified color. Note: like all shaders, at draw time the paint's alpha
+        will be respected, and is applied to the specified color.
+    */
+    SkColorShader(SkColor c) : fColor(c), fInheritColor(false) {}
+    
+    virtual uint32_t getFlags();
+    virtual uint8_t getSpan16Alpha() const;
+    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
+                            const SkMatrix& matrix);
+    virtual void shadeSpan(int x, int y, SkPMColor span[], int count);
+    virtual void shadeSpan16(int x, int y, uint16_t span[], int count);
+    virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
+
+protected:
+    SkColorShader(SkFlattenableReadBuffer& );
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory() { return CreateProc; }
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 
+        return SkNEW_ARGS(SkColorShader, (buffer)); 
+    }
+    SkColor     fColor;         // ignored if fInheritColor is true
+    SkPMColor   fPMColor;       // cached after setContext()
+    uint16_t    fColor16;       // cached after setContext()
+    SkBool8     fInheritColor;
+
+    typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/include/core/SkComposeShader.h b/include/core/SkComposeShader.h
new file mode 100644
index 0000000..0b198f6
--- /dev/null
+++ b/include/core/SkComposeShader.h
@@ -0,0 +1,66 @@
+/*
+ * 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 SkComposeShader_DEFINED
+#define SkComposeShader_DEFINED
+
+#include "SkShader.h"
+
+class SkXfermode;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/** \class SkComposeShader
+    This subclass of shader returns the coposition of two other shaders, combined by
+    a xfermode.
+*/
+class SkComposeShader : public SkShader {
+public:
+    /** Create a new compose shader, given shaders A, B, and a combining xfermode mode.
+        When the xfermode is called, it will be given the result from shader A as its
+        "dst", and the result of from shader B as its "src".
+        mode->xfer32(sA_result, sB_result, ...)
+        @param shaderA  The colors from this shader are seen as the "dst" by the xfermode
+        @param shaderB  The colors from this shader are seen as the "src" by the xfermode
+        @param mode     The xfermode that combines the colors from the two shaders. If mode
+                        is null, then SRC_OVER is assumed.
+    */
+    SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode = NULL);
+    virtual ~SkComposeShader();
+    
+    // override
+    virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix);
+    virtual void shadeSpan(int x, int y, SkPMColor result[], int count);
+    virtual void beginSession();
+    virtual void endSession();
+
+protected:
+    SkComposeShader(SkFlattenableReadBuffer& );
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory() { return CreateProc; }
+
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 
+        return SkNEW_ARGS(SkComposeShader, (buffer)); }
+
+    SkShader*   fShaderA;
+    SkShader*   fShaderB;
+    SkXfermode* fMode;
+
+    typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/include/core/SkDeque.h b/include/core/SkDeque.h
new file mode 100644
index 0000000..cbed930
--- /dev/null
+++ b/include/core/SkDeque.h
@@ -0,0 +1,74 @@
+/*
+ * 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 SkDeque_DEFINED
+#define SkDeque_DEFINED
+
+#include "SkTypes.h"
+
+class SkDeque : SkNoncopyable {
+public:
+    explicit SkDeque(size_t elemSize);
+    SkDeque(size_t elemSize, void* storage, size_t storageSize);
+    ~SkDeque();
+
+    bool    empty() const { return 0 == fCount; }
+    int     count() const { return fCount; }
+    size_t  elemSize() const { return fElemSize; }
+
+    const void* front() const;
+    const void* back() const;
+
+    void* front() {
+        return (void*)((const SkDeque*)this)->front();
+    }
+
+    void* back() {
+        return (void*)((const SkDeque*)this)->back();
+    }
+
+    void* push_front();
+    void* push_back();
+    
+    void pop_front();
+    void pop_back();
+
+private:
+    struct Head;
+
+public:
+    class Iter {
+    public:
+        Iter(const SkDeque& d);
+        void* next();
+
+    private:
+        SkDeque::Head*  fHead;
+        char*           fPos;
+        size_t          fElemSize;
+    };
+
+private:
+    Head*   fFront;
+    Head*   fBack;
+    size_t  fElemSize;
+    void*   fInitialStorage;
+    int     fCount;
+    
+    friend class Iter;
+};
+
+#endif
diff --git a/include/core/SkDescriptor.h b/include/core/SkDescriptor.h
new file mode 100644
index 0000000..8074cff
--- /dev/null
+++ b/include/core/SkDescriptor.h
@@ -0,0 +1,187 @@
+/*
+ * 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 SkDescriptor_DEFINED
+#define SkDescriptor_DEFINED
+
+#include "SkTypes.h"
+
+class SkDescriptor : SkNoncopyable {
+public:
+    static size_t ComputeOverhead(int entryCount)
+    {
+        SkASSERT(entryCount >= 0);
+        return sizeof(SkDescriptor) + entryCount * sizeof(Entry);
+    }
+
+    static SkDescriptor* Alloc(size_t length)
+    {
+        SkASSERT(SkAlign4(length) == length);
+        SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length);
+        return desc;
+    }
+
+    static void Free(SkDescriptor* desc)
+    {
+        sk_free(desc);
+    }
+
+    void init()
+    {
+        fLength = sizeof(SkDescriptor);
+        fCount  = 0;
+    }
+
+    uint32_t getLength() const { return fLength; }
+
+    void* addEntry(uint32_t tag, uint32_t length, const void* data = NULL)
+    {
+        SkASSERT(tag);
+        SkASSERT(SkAlign4(length) == length);
+        SkASSERT(this->findEntry(tag, NULL) == NULL);
+
+        Entry*  entry = (Entry*)((char*)this + fLength);
+        entry->fTag = tag;
+        entry->fLen = length;
+        if (data)
+            memcpy(entry + 1, data, length);
+
+        fCount += 1;
+        fLength += sizeof(Entry) + length;
+        return (entry + 1); // return its data
+    }
+
+    void computeChecksum()
+    {
+        fChecksum = SkDescriptor::ComputeChecksum(this);
+    }
+
+#ifdef SK_DEBUG
+    void assertChecksum() const
+    {
+        SkASSERT(fChecksum == SkDescriptor::ComputeChecksum(this));
+    }
+#endif
+
+    const void* findEntry(uint32_t tag, uint32_t* length) const
+    {
+        const Entry* entry = (const Entry*)(this + 1);
+        int          count = fCount;
+
+        while (--count >= 0)
+        {
+            if (entry->fTag == tag)
+            {
+                if (length)
+                    *length = entry->fLen;
+                return entry + 1;
+            }
+            entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
+        }
+        return NULL;
+    }
+
+    SkDescriptor* copy() const
+    {
+        SkDescriptor* desc = SkDescriptor::Alloc(fLength);
+        memcpy(desc, this, fLength);
+        return desc;
+    }
+
+    bool equals(const SkDescriptor& other) const
+    {
+        // probe to see if we have a good checksum algo
+//        SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0);
+
+        // the first value we should look at is the checksum, so this loop
+        // should terminate early if they descriptors are different.
+        // NOTE: if we wrote a sentinel value at the end of each, we chould
+        //       remove the aa < stop test in the loop...
+        const uint32_t* aa = (const uint32_t*)this;
+        const uint32_t* bb = (const uint32_t*)&other;
+        const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
+        do {
+            if (*aa++ != *bb++)
+                return false;
+        } while (aa < stop);
+        return true;
+    }
+
+    struct Entry {
+        uint32_t fTag;
+        uint32_t fLen;
+    };
+
+#ifdef SK_DEBUG
+    uint32_t getChecksum() const { return fChecksum; }
+    uint32_t getCount() const { return fCount; }
+#endif
+
+private:
+    uint32_t fChecksum;  // must be first
+    uint32_t fLength;    // must be second
+    uint32_t fCount;
+
+    static uint32_t ComputeChecksum(const SkDescriptor* desc)
+    {
+        const uint32_t*  ptr = (const uint32_t*)desc + 1; // skip the checksum field
+        const uint32_t*  stop = (const uint32_t*)((const char*)desc + desc->fLength);
+        uint32_t         sum = 0;
+
+        SkASSERT(ptr < stop);
+        do {
+            sum = (sum << 1) | (sum >> 31);
+            sum ^= *ptr++;
+        } while (ptr < stop);
+
+        return sum;
+    }
+    
+    // private so no one can create one except our factories
+    SkDescriptor() {}
+};
+
+#include "SkScalerContext.h"
+
+class SkAutoDescriptor : SkNoncopyable {
+public:
+    SkAutoDescriptor(size_t size)
+    {
+        if (size <= sizeof(fStorage))
+            fDesc = (SkDescriptor*)(void*)fStorage;
+        else
+            fDesc = SkDescriptor::Alloc(size);
+    }
+    ~SkAutoDescriptor()
+    {
+        if (fDesc != (SkDescriptor*)(void*)fStorage)
+            SkDescriptor::Free(fDesc);
+    }
+    SkDescriptor* getDesc() const { return fDesc; }
+private:
+    enum {
+        kStorageSize =  sizeof(SkDescriptor)
+                        + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec)    // for rec
+                        + sizeof(SkDescriptor::Entry) + sizeof(void*)                   // for typeface
+                        + 32   // slop for occational small extras
+    };
+    SkDescriptor*   fDesc;
+    uint32_t        fStorage[(kStorageSize + 3) >> 2];
+};
+
+
+#endif
+
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
new file mode 100644
index 0000000..4d678c6
--- /dev/null
+++ b/include/core/SkDevice.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkDevice_DEFINED
+#define SkDevice_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+
+class SkDraw;
+struct SkIRect;
+class SkMatrix;
+class SkRegion;
+
+class SkDevice : public SkRefCnt {
+public:
+    SkDevice();
+    /** Construct a new device, extracting the width/height/config/isOpaque values from
+        the bitmap. If transferPixelOwnership is true, and the bitmap claims to own its
+        own pixels (getOwnsPixels() == true), then transfer this responsibility to the
+        device, and call setOwnsPixels(false) on the bitmap.
+        
+        Subclasses may override the destructor, which is virtual, even though this class
+        doesn't have one. SkRefCnt does.
+    
+        @param bitmap   A copy of this bitmap is made and stored in the device
+    */
+    SkDevice(const SkBitmap& bitmap);
+
+    /** Return the width of the device (in pixels).
+    */
+    int width() const { return fBitmap.width(); }
+    /** Return the height of the device (in pixels).
+    */
+    int height() const { return fBitmap.height(); }
+    /** Return the bitmap config of the device's pixels
+    */
+    SkBitmap::Config config() const { return fBitmap.getConfig(); }
+    /** Returns true if the device's bitmap's config treats every pixels as
+        implicitly opaque.
+    */
+    bool isOpaque() const { return fBitmap.isOpaque(); }
+    
+    /** Return the bounds of the device
+    */
+    void getBounds(SkIRect* bounds) const;
+    
+    /** Return true if the specified rectangle intersects the bounds of the
+        device. If sect is not NULL and there is an intersection, sect returns
+        the intersection.
+    */
+    bool intersects(const SkIRect& r, SkIRect* sect = NULL) const;
+
+    /** Return the bitmap associated with this device. Call this each time you need
+        to access the bitmap, as it notifies the subclass to perform any flushing
+        etc. before you examine the pixels.
+        @param changePixels set to true if the caller plans to change the pixels
+        @return the device's bitmap
+    */
+    const SkBitmap& accessBitmap(bool changePixels);
+
+    /** Helper to erase the entire device to the specified color (including
+        alpha).
+    */
+    void eraseColor(SkColor eraseColor);
+
+    /** Called when this device is installed into a Canvas. Balanaced by a call
+        to unlockPixels() when the device is removed from a Canvas.
+    */
+    virtual void lockPixels();
+    virtual void unlockPixels();
+
+    /** Called with the correct matrix and clip before this device is drawn
+        to using those settings. If your subclass overrides this, be sure to
+        call through to the base class as well.
+    */
+    virtual void setMatrixClip(const SkMatrix&, const SkRegion&);
+
+    /** Called when this device gains focus (i.e becomes the current device
+        for drawing).
+    */
+    virtual void gainFocus(SkCanvas*) {}
+
+    /** These are called inside the per-device-layer loop for each draw call.
+     When these are called, we have already applied any saveLayer operations,
+     and are handling any looping from the paint, and any effects from the
+     DrawFilter.
+     */
+    virtual void drawPaint(const SkDraw&, const SkPaint& paint);
+    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
+                            const SkPoint[], const SkPaint& paint);
+    virtual void drawRect(const SkDraw&, const SkRect& r,
+                          const SkPaint& paint);
+    virtual void drawPath(const SkDraw&, const SkPath& path,
+                          const SkPaint& paint);
+    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+                            const SkMatrix& matrix, const SkPaint& paint);
+    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
+                            int x, int y, const SkPaint& paint);
+    virtual void drawText(const SkDraw&, const void* text, size_t len,
+                          SkScalar x, SkScalar y, const SkPaint& paint);
+    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
+                             const SkScalar pos[], SkScalar constY,
+                             int scalarsPerPos, const SkPaint& paint);
+    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint);
+    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
+                              const SkPoint verts[], const SkPoint texs[],
+                              const SkColor colors[], SkXfermode* xmode,
+                              const uint16_t indices[], int indexCount,
+                              const SkPaint& paint);
+    virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
+                            const SkPaint&);
+
+protected:
+    /** Update as needed the pixel value in the bitmap, so that the caller can access
+        the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes
+        must remain unchanged.
+    */
+    virtual void onAccessBitmap(SkBitmap*);
+
+private:
+    SkBitmap fBitmap;
+};
+
+#endif
diff --git a/include/core/SkDither.h b/include/core/SkDither.h
new file mode 100644
index 0000000..5b2552d
--- /dev/null
+++ b/include/core/SkDither.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkDither_DEFINED
+#define SkDither_DEFINED
+
+#include "SkColorPriv.h"
+
+#define SK_DitherValueMax4444   15
+#define SK_DitherValueMax565    7
+
+/*  need to use macros for bit-counts for each component, and then
+    move these into SkColorPriv.h
+*/
+
+#define SkDITHER_R32_FOR_565_MACRO(r, d)    (r + d - (r >> 5))
+#define SkDITHER_G32_FOR_565_MACRO(g, d)    (g + (d >> 1) - (g >> 6))
+#define SkDITHER_B32_FOR_565_MACRO(b, d)    (b + d - (b >> 5))
+
+#define SkDITHER_A32_FOR_4444_MACRO(a, d)    (a + 15 - (a >> 4))
+#define SkDITHER_R32_FOR_4444_MACRO(r, d)    (r + d - (r >> 4))
+#define SkDITHER_G32_FOR_4444_MACRO(g, d)    (g + d - (g >> 4))
+#define SkDITHER_B32_FOR_4444_MACRO(b, d)    (b + d - (b >> 4))
+
+#ifdef SK_DEBUG
+    inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
+    {
+        SkASSERT(d <= SK_DitherValueMax565);
+        SkA32Assert(r);
+        r = SkDITHER_R32_FOR_565_MACRO(r, d);
+        SkA32Assert(r);
+        return r;
+    }
+    inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
+    {
+        SkASSERT(d <= SK_DitherValueMax565);
+        SkG32Assert(g);
+        g = SkDITHER_G32_FOR_565_MACRO(g, d);
+        SkG32Assert(g);
+        return g;
+    }
+    inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
+    {
+        SkASSERT(d <= SK_DitherValueMax565);
+        SkB32Assert(b);
+        b = SkDITHER_B32_FOR_565_MACRO(b, d);
+        SkB32Assert(b);
+        return b;
+    }
+#else
+    #define SkDITHER_R32_FOR_565(r, d)  SkDITHER_R32_FOR_565_MACRO(r, d)
+    #define SkDITHER_G32_FOR_565(g, d)  SkDITHER_G32_FOR_565_MACRO(g, d)
+    #define SkDITHER_B32_FOR_565(b, d)  SkDITHER_B32_FOR_565_MACRO(b, d)
+#endif
+
+#define SkDITHER_R32To565(r, d)  SkR32ToR16(SkDITHER_R32_FOR_565(r, d))
+#define SkDITHER_G32To565(g, d)  SkG32ToG16(SkDITHER_G32_FOR_565(g, d))
+#define SkDITHER_B32To565(b, d)  SkB32ToB16(SkDITHER_B32_FOR_565(b, d))
+
+#define SkDITHER_A32To4444(a, d)  SkA32To4444(SkDITHER_A32_FOR_4444_MACRO(a, d))
+#define SkDITHER_R32To4444(r, d)  SkR32To4444(SkDITHER_R32_FOR_4444_MACRO(r, d))
+#define SkDITHER_G32To4444(g, d)  SkG32To4444(SkDITHER_G32_FOR_4444_MACRO(g, d))
+#define SkDITHER_B32To4444(b, d)  SkB32To4444(SkDITHER_B32_FOR_4444_MACRO(b, d))
+
+static inline SkPMColor SkDitherARGB32For565(SkPMColor c, unsigned dither)
+{
+    SkASSERT(dither <= SK_DitherValueMax565);
+    
+    unsigned sa = SkGetPackedA32(c);
+    dither = SkAlphaMul(dither, SkAlpha255To256(sa));
+
+    unsigned sr = SkGetPackedR32(c);
+    unsigned sg = SkGetPackedG32(c);
+    unsigned sb = SkGetPackedB32(c);
+    sr = SkDITHER_R32_FOR_565(sr, dither);
+    sg = SkDITHER_G32_FOR_565(sg, dither);
+    sb = SkDITHER_B32_FOR_565(sb, dither);
+    
+    return SkPackARGB32(sa, sr, sg, sb);
+}
+
+static inline SkPMColor SkDitherRGB32For565(SkPMColor c, unsigned dither)
+{
+    SkASSERT(dither <= SK_DitherValueMax565);
+    
+    unsigned sr = SkGetPackedR32(c);
+    unsigned sg = SkGetPackedG32(c);
+    unsigned sb = SkGetPackedB32(c);
+    sr = SkDITHER_R32_FOR_565(sr, dither);
+    sg = SkDITHER_G32_FOR_565(sg, dither);
+    sb = SkDITHER_B32_FOR_565(sb, dither);
+    
+    return SkPackARGB32(0xFF, sr, sg, sb);
+}
+
+static inline uint16_t SkDitherRGBTo565(U8CPU r, U8CPU g, U8CPU b,
+                                              unsigned dither)
+{
+    SkASSERT(dither <= SK_DitherValueMax565);
+    r = SkDITHER_R32To565(r, dither);
+    g = SkDITHER_G32To565(g, dither);
+    b = SkDITHER_B32To565(b, dither);
+    return SkPackRGB16(r, g, b);
+}
+
+static inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
+{
+    SkASSERT(dither <= SK_DitherValueMax565);
+    
+    unsigned sr = SkGetPackedR32(c);
+    unsigned sg = SkGetPackedG32(c);
+    unsigned sb = SkGetPackedB32(c);
+    sr = SkDITHER_R32To565(sr, dither);
+    sg = SkDITHER_G32To565(sg, dither);
+    sb = SkDITHER_B32To565(sb, dither);
+    
+    return SkPackRGB16(sr, sg, sb);
+}
+
+static inline uint16_t SkDitherARGB32To565(U8CPU sa, SkPMColor c, unsigned dither)
+{
+    SkASSERT(dither <= SK_DitherValueMax565);    
+    dither = SkAlphaMul(dither, SkAlpha255To256(sa));
+    
+    unsigned sr = SkGetPackedR32(c);
+    unsigned sg = SkGetPackedG32(c);
+    unsigned sb = SkGetPackedB32(c);
+    sr = SkDITHER_R32To565(sr, dither);
+    sg = SkDITHER_G32To565(sg, dither);
+    sb = SkDITHER_B32To565(sb, dither);
+    
+    return SkPackRGB16(sr, sg, sb);
+}
+
+///////////////////////// 4444
+
+static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, U8CPU g,
+                                               U8CPU b, unsigned dither)
+{
+    dither = SkAlphaMul(dither, SkAlpha255To256(a));
+
+    a = SkDITHER_A32To4444(a, dither);
+    r = SkDITHER_R32To4444(r, dither);
+    g = SkDITHER_G32To4444(g, dither);
+    b = SkDITHER_B32To4444(b, dither);
+    
+    return SkPackARGB4444(a, r, g, b);
+}
+
+static inline SkPMColor16 SkDitherARGB32To4444(SkPMColor c, unsigned dither)
+{
+    unsigned a = SkGetPackedA32(c);
+    unsigned r = SkGetPackedR32(c);
+    unsigned g = SkGetPackedG32(c);
+    unsigned b = SkGetPackedB32(c);
+
+    dither = SkAlphaMul(dither, SkAlpha255To256(a));
+
+    a = SkDITHER_A32To4444(a, dither);
+    r = SkDITHER_R32To4444(r, dither);
+    g = SkDITHER_G32To4444(g, dither);
+    b = SkDITHER_B32To4444(b, dither);
+    
+    return SkPackARGB4444(a, r, g, b);
+}
+
+// TODO: need dither routines for 565 -> 4444
+
+// this toggles between a 4x4 and a 1x4 array
+//#define ENABLE_DITHER_MATRIX_4X4
+
+#ifdef ENABLE_DITHER_MATRIX_4X4
+    extern const uint8_t gDitherMatrix_4Bit_4X4[4][4];
+    extern const uint8_t gDitherMatrix_3Bit_4X4[4][4];
+
+    #define DITHER_4444_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_4Bit_4X4[(y) & 3]
+    #define DITHER_565_SCAN(y)  const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3]
+
+    #define DITHER_VALUE(x) dither_scan[(x) & 3]
+#else
+    extern const uint16_t gDitherMatrix_4Bit_16[4];
+    extern const uint16_t gDitherMatrix_3Bit_16[4];
+
+    #define DITHER_4444_SCAN(y) const uint16_t dither_scan = gDitherMatrix_4Bit_16[(y) & 3]
+    #define DITHER_565_SCAN(y)  const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3]
+
+    #define DITHER_VALUE(x) ((dither_scan >> (((x) & 3) << 2)) & 0xF)
+#endif
+
+#define DITHER_INC_X(x) ++(x)
+
+#endif
diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h
new file mode 100644
index 0000000..2d775a4
--- /dev/null
+++ b/include/core/SkDraw.h
@@ -0,0 +1,124 @@
+/*
+ * 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 SkDraw_DEFINED
+#define SkDraw_DEFINED
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkMask.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+#include "SkRect.h"
+#include "SkAutoKern.h"
+
+class SkBounder;
+class SkDevice;
+class SkPath;
+class SkRegion;
+struct SkDrawProcs;
+
+class SkDraw {
+public:
+    SkDraw() : fDevice(NULL), fBounder(NULL), fProcs(NULL) {}
+    SkDraw(const SkDraw& src);
+
+    void    drawPaint(const SkPaint&) const;
+    void    drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[],
+                       const SkPaint&) const;
+    void    drawRect(const SkRect&, const SkPaint&) const;
+    /*  To save on mallocs, we allow a flag that tells us that srcPath is
+        mutable, so that we don't have to make copies of it as we transform it.
+    */
+    void    drawPath(const SkPath& srcPath, const SkPaint&,
+                     const SkMatrix* prePathMatrix, bool pathIsMutable) const;
+    void    drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const;
+    void    drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const;
+    void    drawText(const char text[], size_t byteLength, SkScalar x,
+                     SkScalar y, const SkPaint& paint) const;
+    void    drawPosText(const char text[], size_t byteLength,
+                        const SkScalar pos[], SkScalar constY,
+                        int scalarsPerPosition, const SkPaint& paint) const;
+    void    drawTextOnPath(const char text[], size_t byteLength,
+                        const SkPath&, const SkMatrix*, const SkPaint&) const;
+    void    drawVertices(SkCanvas::VertexMode mode, int count,
+                         const SkPoint vertices[], const SkPoint textures[],
+                         const SkColor colors[], SkXfermode* xmode,
+                         const uint16_t indices[], int ptCount,
+                         const SkPaint& paint) const;
+        
+    void drawPath(const SkPath& src, const SkPaint& paint) const {
+        this->drawPath(src, paint, NULL, false);
+    }
+
+    /** Helper function that creates a mask from a path and an optional maskfilter.
+        Note however, that the resulting mask will not have been actually filtered,
+        that must be done afterwards (by calling filterMask). The maskfilter is provided
+        solely to assist in computing the mask's bounds (if the mode requests that).
+    */
+    static bool DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
+                           SkMaskFilter* filter, const SkMatrix* filterMatrix,
+                           SkMask* mask, SkMask::CreateMode mode);
+
+private:
+    void    drawText_asPaths(const char text[], size_t byteLength,
+                             SkScalar x, SkScalar y, const SkPaint&) const;
+    void    drawDevMask(const SkMask& mask, const SkPaint&) const;
+    void    drawBitmapAsMask(const SkBitmap&, const SkPaint&) const;
+
+public:
+    const SkBitmap* fBitmap;        // required
+    const SkMatrix* fMatrix;        // required
+    const SkRegion* fClip;          // required
+    SkDevice*       fDevice;        // optional
+    SkBounder*      fBounder;       // optional
+    SkDrawProcs*    fProcs;         // optional
+
+#ifdef SK_DEBUG
+    void    validate() const;
+#endif
+};
+
+#include "SkGlyphCache.h"
+
+class SkTextToPathIter {
+public:
+    SkTextToPathIter(const char text[], size_t length, const SkPaint&,
+                     bool applyStrokeAndPathEffects, bool forceLinearTextOn);
+    ~SkTextToPathIter();
+
+    const SkPaint&  getPaint() const { return fPaint; }
+    SkScalar        getPathScale() const { return fScale; }
+
+    const SkPath*   next(SkScalar* xpos);   //!< returns nil when there are no more paths
+
+private:
+    SkGlyphCache*   fCache;
+    SkPaint         fPaint;
+    SkScalar        fScale;
+    SkFixed         fPrevAdvance;
+    const char*     fText;
+    const char*     fStop;
+    SkMeasureCacheProc fGlyphCacheProc;
+
+    const SkPath*   fPath;      // returned in next
+    SkScalar        fXPos;      // accumulated xpos, returned in next
+    SkAutoKern      fAutoKern;
+};
+
+#endif
+
+
diff --git a/include/core/SkDrawFilter.h b/include/core/SkDrawFilter.h
new file mode 100644
index 0000000..db5a685
--- /dev/null
+++ b/include/core/SkDrawFilter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkDrawFilter_DEFINED
+#define SkDrawFilter_DEFINED
+
+#include "SkRefCnt.h"
+
+////////////////// EXPERIMENTAL //////////////////////////
+
+class SkCanvas;
+class SkPaint;
+
+/** Right before something is being draw, filter() is called with the
+    current canvas and paint. If it returns true, then drawing proceeds
+    with the (possibly modified) canvas/paint, and then restore() is called
+    to restore the canvas/paint to their state before filter() was called.
+    If filter returns false, canvas/paint should not have been changed, and
+    restore() will not be called.
+*/
+class SkDrawFilter : public SkRefCnt {
+public:
+    enum Type {
+        kPaint_Type,
+        kPoint_Type,
+        kLine_Type,
+        kBitmap_Type,
+        kRect_Type,
+        kPath_Type,
+        kText_Type
+    };
+
+    /** Return true to allow the draw to continue (with possibly modified
+        canvas/paint). If true is returned, then restore() will be called.
+    */
+    virtual bool filter(SkCanvas*, SkPaint*, Type) = 0;
+    /** If filter() returned true, then restore() will be called to restore the
+        canvas/paint to their previous states
+    */
+    virtual void restore(SkCanvas*, SkPaint*, Type) = 0;
+};
+
+#endif
diff --git a/include/core/SkDrawLooper.h b/include/core/SkDrawLooper.h
new file mode 100644
index 0000000..333fb41
--- /dev/null
+++ b/include/core/SkDrawLooper.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkDrawLooper_DEFINED
+#define SkDrawLooper_DEFINED
+
+#include "SkFlattenable.h"
+
+////////////////// EXPERIMENTAL //////////////////////////
+
+class SkCanvas;
+class SkPaint;
+
+/** \class SkDrawLooper
+    Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
+    and something is drawn to a canvas with that paint, the looper subclass will
+    be called, allowing it to modify the canvas and/or paint for that draw call.
+    More than that, via the next() method, the looper can modify the draw to be
+    invoked multiple times (hence the name loop-er), allow it to perform effects
+    like shadows or frame/fills, that require more than one pass.
+*/
+class SkDrawLooper : public SkFlattenable {
+public:
+    /** Called right before something is being drawn to the specified canvas
+        with the specified paint. Subclass that want to modify either parameter
+        can do so now.
+    */
+    virtual void init(SkCanvas*, SkPaint*) {}
+    /** Called in a loop (after init()). Each time true is returned, the object
+        is drawn (possibly with a modified canvas and/or paint). When false is
+        finally returned, drawing for the object stops.
+    */
+    virtual bool next() { return false; }
+    /** Called after the looper has finally returned false from next(), allowing
+        the looper to restore the canvas/paint to their original states.
+        is this required, since the subclass knows when it is done???
+        should we pass the canvas/paint here, and/or to the next call
+        so that subclasses don't need to retain pointers to them during the 
+        loop?
+    */
+    virtual void restore() {}
+    
+protected:
+    SkDrawLooper() {}
+    SkDrawLooper(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+    typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/include/core/SkEndian.h b/include/core/SkEndian.h
new file mode 100644
index 0000000..f08a9a9
--- /dev/null
+++ b/include/core/SkEndian.h
@@ -0,0 +1,98 @@
+/*
+ * 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 SkEndian_DEFINED
+#define SkEndian_DEFINED
+
+#include "SkTypes.h"
+
+/** \file SkEndian.h
+
+    Macros and helper functions for handling 16 and 32 bit values in
+    big and little endian formats.
+*/
+
+#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
+    #error "can't have both LENDIAN and BENDIAN defined"
+#endif
+
+#if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
+    #error "need either LENDIAN or BENDIAN defined"
+#endif
+
+/** Swap the two bytes in the low 16bits of the parameters.
+    e.g. 0x1234 -> 0x3412
+*/
+inline uint16_t SkEndianSwap16(U16CPU value)
+{
+    SkASSERT(value == (uint16_t)value);
+    return (uint16_t)((value >> 8) | (value << 8));
+}
+
+/** Vector version of SkEndianSwap16(), which swaps the
+    low two bytes of each value in the array.
+*/
+inline void SkEndianSwap16s(uint16_t array[], int count)
+{
+    SkASSERT(count == 0 || array != NULL);
+
+    while (--count >= 0)
+    {
+        *array = SkEndianSwap16(*array);
+        array += 1;
+    }
+}
+
+/** Reverse all 4 bytes in a 32bit value.
+    e.g. 0x12345678 -> 0x78563412
+*/
+inline uint32_t SkEndianSwap32(uint32_t value)
+{
+    return  ((value & 0xFF) << 24) |
+            ((value & 0xFF00) << 8) |
+            ((value & 0xFF0000) >> 8) |
+            (value >> 24);
+}
+
+/** Vector version of SkEndianSwap16(), which swaps the
+    bytes of each value in the array.
+*/
+inline void SkEndianSwap32s(uint32_t array[], int count)
+{
+    SkASSERT(count == 0 || array != NULL);
+
+    while (--count >= 0)
+    {
+        *array = SkEndianSwap32(*array);
+        array += 1;
+    }
+}
+
+#ifdef SK_CPU_LENDIAN
+    #define SkEndian_SwapBE16(n)    SkEndianSwap16(n)
+    #define SkEndian_SwapBE32(n)    SkEndianSwap32(n)
+    #define SkEndian_SwapLE16(n)    (n)
+    #define SkEndian_SwapLE32(n)    (n)
+#else   // SK_CPU_BENDIAN
+    #define SkEndian_SwapBE16(n)    (n)
+    #define SkEndian_SwapBE32(n)    (n)
+    #define SkEndian_SwapLE16(n)    SkEndianSwap16(n)
+    #define SkEndian_SwapLE32(n)    SkEndianSwap32(n)
+#endif
+
+
+#endif
+
diff --git a/include/core/SkFDot6.h b/include/core/SkFDot6.h
new file mode 100644
index 0000000..a4b9cf7
--- /dev/null
+++ b/include/core/SkFDot6.h
@@ -0,0 +1,67 @@
+/*
+ * 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 SkFDot6_DEFINED
+#define SkFDot6_DEFINED
+
+#include "SkMath.h"
+
+typedef int32_t SkFDot6;
+
+#define SK_FDot61           (64)
+#define SK_FDot6Half        (32)
+
+#ifdef SK_DEBUG
+    inline SkFDot6 SkIntToFDot6(S16CPU x)
+    {
+        SkASSERT(SkToS16(x) == x);
+        return x << 6;
+    }
+#else
+    #define SkIntToFDot6(x) ((x) << 6)
+#endif
+
+#define SkFDot6Floor(x)     ((x) >> 6)
+#define SkFDot6Ceil(x)      (((x) + 63) >> 6)
+#define SkFDot6Round(x)     (((x) + 32) >> 6)
+
+#define SkFixedToFDot6(x)   ((x) >> 10)
+
+inline SkFixed SkFDot6ToFixed(SkFDot6 x)
+{
+    SkASSERT((x << 10 >> 10) == x);
+
+    return x << 10;
+}
+
+#ifdef SK_SCALAR_IS_FLOAT
+    #define SkScalarToFDot6(x)  (SkFDot6)((x) * 64)
+#else
+    #define SkScalarToFDot6(x)  ((x) >> 10)
+#endif
+
+inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b)
+{
+    SkASSERT(b != 0);
+
+    if (a == (int16_t)a)
+        return (a << 16) / b;
+    else
+        return SkFixedDiv(a, b);
+}
+
+#endif
+
diff --git a/include/core/SkFixed.h b/include/core/SkFixed.h
new file mode 100644
index 0000000..be4bf99
--- /dev/null
+++ b/include/core/SkFixed.h
@@ -0,0 +1,253 @@
+/*
+ * 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 SkFixed_DEFINED
+#define SkFixed_DEFINED
+
+#include "SkTypes.h"
+
+/** \file SkFixed.h
+
+    Types and macros for 16.16 fixed point
+*/
+
+/** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point
+*/
+typedef int32_t             SkFixed;
+#define SK_Fixed1           (1 << 16)
+#define SK_FixedHalf        (1 << 15)
+#define SK_FixedMax         (0x7FFFFFFF)
+#define SK_FixedMin         (0x1)
+#define SK_FixedNaN         ((int) 0x80000000)
+#define SK_FixedPI          (0x3243F)
+#define SK_FixedSqrt2       (92682)
+#define SK_FixedTanPIOver8  (0x6A0A)
+#define SK_FixedRoot2Over2  (0xB505)
+
+#ifdef SK_CAN_USE_FLOAT
+    #define SkFixedToFloat(x)   ((x) * 1.5258789e-5f)
+    #define SkFloatToFixed(x)   ((SkFixed)((x) * SK_Fixed1))
+
+    #define SkFixedToDouble(x)  ((x) * 1.5258789e-5)
+    #define SkDoubleToFixed(x)  ((SkFixed)((x) * SK_Fixed1))
+#endif
+
+/** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point
+*/
+typedef int32_t             SkFract;
+#define SK_Fract1           (1 << 30)
+#define Sk_FracHalf         (1 << 29)
+#define SK_FractPIOver180   (0x11DF46A)
+
+#ifdef SK_CAN_USE_FLOAT
+    #define SkFractToFloat(x)   ((float)(x) * 0.00000000093132257f)
+    #define SkFloatToFract(x)   ((SkFract)((x) * SK_Fract1))
+#endif
+
+/** Converts an integer to a SkFixed, asserting that the result does not overflow
+    a 32 bit signed integer
+*/
+#ifdef SK_DEBUG
+    inline SkFixed SkIntToFixed(int n)
+    {
+        SkASSERT(n >= -32768 && n <= 32767);
+        return n << 16;
+    }
+#else
+    //  force the cast to SkFixed to ensure that the answer is signed (like the debug version)
+    #define SkIntToFixed(n)     (SkFixed)((n) << 16)
+#endif
+
+/** Converts a SkFixed to a SkFract, asserting that the result does not overflow
+    a 32 bit signed integer
+*/
+#ifdef SK_DEBUG
+    inline SkFract SkFixedToFract(SkFixed x)
+    {
+        SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1);
+        return x << 14;
+    }
+#else
+    #define SkFixedToFract(x)   ((x) << 14)
+#endif
+
+/** Returns the signed fraction of a SkFixed
+*/
+inline SkFixed SkFixedFraction(SkFixed x)
+{
+    SkFixed mask = x >> 31 << 16;
+    return (x & 0xFFFF) | mask;
+}
+
+/** Converts a SkFract to a SkFixed
+*/
+#define SkFractToFixed(x)   ((x) >> 14)
+/** Round a SkFixed to an integer
+*/
+#define SkFixedRound(x)     (((x) + SK_FixedHalf) >> 16)
+#define SkFixedCeil(x)      (((x) + SK_Fixed1 - 1) >> 16)
+#define SkFixedFloor(x)     ((x) >> 16)
+#define SkFixedAbs(x)       SkAbs32(x)
+#define SkFixedAve(a, b)    (((a) + (b)) >> 1)
+
+SkFixed SkFixedMul_portable(SkFixed, SkFixed);
+SkFract SkFractMul_portable(SkFract, SkFract);
+inline SkFixed SkFixedSquare_portable(SkFixed value)
+{
+    uint32_t a = SkAbs32(value);
+    uint32_t ah = a >> 16;
+    uint32_t al = a & 0xFFFF;
+    return ah * a + al * ah + (al * al >> 16);
+}
+
+#define SkFixedDiv(numer, denom)    SkDivBits(numer, denom, 16)
+SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
+SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
+#define SkFixedInvert(n)            SkDivBits(SK_Fixed1, n, 16)
+SkFixed SkFixedFastInvert(SkFixed n);
+#define SkFixedSqrt(n)              SkSqrtBits(n, 23)
+SkFixed SkFixedMean(SkFixed a, SkFixed b);  //*< returns sqrt(x*y)
+int SkFixedMulCommon(SkFixed, int , int bias);  // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound
+
+#define SkFractDiv(numer, denom)    SkDivBits(numer, denom, 30)
+#define SkFractSqrt(n)              SkSqrtBits(n, 30)
+
+SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
+#define SkFixedSin(radians)         SkFixedSinCos(radians, NULL)
+inline SkFixed SkFixedCos(SkFixed radians)
+{
+    SkFixed cosValue;
+    (void)SkFixedSinCos(radians, &cosValue);
+    return cosValue;
+}
+SkFixed SkFixedTan(SkFixed radians);
+SkFixed SkFixedASin(SkFixed);
+SkFixed SkFixedACos(SkFixed);
+SkFixed SkFixedATan2(SkFixed y, SkFixed x);
+SkFixed SkFixedExp(SkFixed);
+SkFixed SkFixedLog(SkFixed);
+
+#define SK_FixedNearlyZero          (SK_Fixed1 >> 12)
+
+inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
+{
+    SkASSERT(tolerance > 0);
+    return SkAbs32(x) < tolerance;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// Now look for ASM overrides for our portable versions (should consider putting this in its own file)
+
+#ifdef SkLONGLONG
+    inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
+    {
+        return (SkFixed)((SkLONGLONG)a * b >> 16);
+    }
+    inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
+    {
+        return (SkFixed)((SkLONGLONG)a * b >> 30);
+    }
+    inline SkFixed SkFixedSquare_longlong(SkFixed value)
+    {
+        return (SkFixed)((SkLONGLONG)value * value >> 16);
+    }
+    #define SkFixedMul(a,b)     SkFixedMul_longlong(a,b)
+    #define SkFractMul(a,b)     SkFractMul_longlong(a,b)
+    #define SkFixedSquare(a)    SkFixedSquare_longlong(a)
+#endif
+
+#if defined(__arm__) && !defined(__thumb__)
+    /* This guy does not handle NaN or other obscurities, but is faster than
+       than (int)(x*65536) when we only have software floats
+    */
+    inline SkFixed SkFloatToFixed_arm(float x)
+    {
+        register int32_t y, z;
+        asm("movs    %1, %3, lsl #1         \n"
+            "mov     %2, #0x8E              \n"
+            "sub     %1, %2, %1, lsr #24    \n"
+            "mov     %2, %3, lsl #8         \n"
+            "orr     %2, %2, #0x80000000    \n"
+            "mov     %1, %2, lsr %1         \n"
+            "rsbcs   %1, %1, #0             \n"
+            : "=r"(x), "=&r"(y), "=&r"(z)
+            : "r"(x)
+            : "cc"
+            );
+        return y;
+    }
+    inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
+    {
+        register int32_t t;
+        asm("smull  %0, %2, %1, %3          \n"
+            "mov    %0, %0, lsr #16         \n"
+            "orr    %0, %0, %2, lsl #16     \n"
+            : "=r"(x), "=&r"(y), "=r"(t)
+            : "r"(x), "1"(y)
+            :
+            );
+        return x;
+    }
+    inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a)
+    {
+        register int32_t t;
+        asm("smull  %0, %3, %1, %4          \n"
+            "add    %0, %2, %0, lsr #16     \n"
+            "add    %0, %0, %3, lsl #16     \n"
+            : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t)
+            : "%r"(x), "1"(y), "2"(a)
+            :
+            );
+        return x;
+    }
+    inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y)
+    {
+        register int32_t t;
+        asm("smull  %0, %2, %1, %3          \n"
+            "mov    %0, %0, lsr #30         \n"
+            "orr    %0, %0, %2, lsl #2      \n"
+            : "=r"(x), "=&r"(y), "=r"(t)
+            : "r"(x), "1"(y)
+            :
+            );
+        return x;
+    }
+    #undef SkFixedMul
+    #undef SkFractMul
+    #define SkFixedMul(x, y)        SkFixedMul_arm(x, y)
+    #define SkFractMul(x, y)        SkFractMul_arm(x, y)
+    #define SkFixedMulAdd(x, y, a)  SkFixedMulAdd_arm(x, y, a)
+
+    #undef SkFloatToFixed
+    #define SkFloatToFixed(x)  SkFloatToFixed_arm(x)
+#endif
+
+/////////////////////// Now define our macros to the portable versions if they weren't overridden
+
+#ifndef SkFixedSquare
+    #define SkFixedSquare(x)    SkFixedSquare_portable(x)
+#endif
+#ifndef SkFixedMul
+    #define SkFixedMul(x, y)    SkFixedMul_portable(x, y)
+#endif
+#ifndef SkFractMul
+    #define SkFractMul(x, y)    SkFractMul_portable(x, y)
+#endif
+#ifndef SkFixedMulAdd
+    #define SkFixedMulAdd(x, y, a)  (SkFixedMul(x, y) + (a))
+#endif
+
+#endif
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
new file mode 100644
index 0000000..6958462
--- /dev/null
+++ b/include/core/SkFlattenable.h
@@ -0,0 +1,207 @@
+/*
+ * 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 SkFlattenable_DEFINED
+#define SkFlattenable_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkBitmap.h"
+#include "SkReader32.h"
+#include "SkTDArray.h"
+#include "SkWriter32.h"
+
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+class SkString;
+
+/** \class SkFlattenable
+ 
+ SkFlattenable is the base class for objects that need to be flattened
+ into a data stream for either transport or as part of the key to the
+ font cache.
+ */
+class SkFlattenable : public SkRefCnt {
+public:
+    typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
+    
+    SkFlattenable() {}
+    
+    /** Implement this to return a factory function pointer that can be called
+     to recreate your class given a buffer (previously written to by your
+     override of flatten().
+     */
+    virtual Factory getFactory() = 0;
+    /** Override this to write data specific to your subclass into the buffer,
+     being sure to call your super-class' version first. This data will later
+     be passed to your Factory function, returned by getFactory().
+     */
+    virtual void flatten(SkFlattenableWriteBuffer&);
+    
+    /** Set the string to describe the sublass and return true. If this is not
+        overridden, ignore the string param and return false.
+     */
+    virtual bool toDumpString(SkString*) const;
+
+    static Factory NameToFactory(const char name[]);
+    static const char* FactoryToName(Factory);
+    static void Register(const char name[], Factory);
+    
+    class Registrar {
+    public:
+        Registrar(const char name[], Factory factory) {
+            SkFlattenable::Register(name, factory);
+        }
+    };
+    
+protected:
+    SkFlattenable(SkFlattenableReadBuffer&) {}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class SkTypeface;
+
+class SkFlattenableReadBuffer : public SkReader32 {
+public:
+    SkFlattenableReadBuffer();
+    explicit SkFlattenableReadBuffer(const void* data);
+    SkFlattenableReadBuffer(const void* data, size_t size);
+    
+    void setRefCntArray(SkRefCnt* array[], int count) {
+        fRCArray = array;
+        fRCCount = count;
+    }
+    
+    void setTypefaceArray(SkTypeface* array[], int count) {
+        fTFArray = array;
+        fTFCount = count;
+    }
+    
+    void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
+        fFactoryArray = array;
+        fFactoryCount = count;
+    }
+    
+    SkTypeface* readTypeface();
+    SkRefCnt* readRefCnt();
+    void* readFunctionPtr();
+    SkFlattenable* readFlattenable();
+    
+private:
+    SkRefCnt** fRCArray;
+    int        fRCCount;
+    
+    SkTypeface** fTFArray;
+    int        fTFCount;
+    
+    SkFlattenable::Factory* fFactoryArray;
+    int                     fFactoryCount;
+    
+    typedef SkReader32 INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkPtrRecorder.h"
+
+class SkRefCntRecorder : public SkPtrRecorder {
+public:
+    virtual ~SkRefCntRecorder();
+    
+    /** Add a refcnt object to the set and ref it if not already present,
+        or if it is already present, do nothing. Either way, returns 0 if obj
+        is null, or a base-1 index if obj is not null.
+    */
+    uint32_t record(SkRefCnt* ref) {
+        return this->recordPtr(ref);
+    }
+
+    // This does not change the owner counts on the objects
+    void get(SkRefCnt* array[]) const {
+        this->getPtrs((void**)array);
+    }
+
+protected:
+    // overrides
+    virtual void incPtr(void*);
+    virtual void decPtr(void*);
+
+private:
+    typedef SkPtrRecorder INHERITED;
+};
+
+class SkFactoryRecorder : public SkPtrRecorder {
+public:
+    /** Add a factory to the set. If it is null return 0, otherwise return a
+        base-1 index for the factory.
+    */
+    uint32_t record(SkFlattenable::Factory fact) {
+        return this->recordPtr((void*)fact);
+    }
+    
+    void get(SkFlattenable::Factory array[]) const {
+        this->getPtrs((void**)array);
+    }
+    
+private:
+    typedef SkPtrRecorder INHERITED;
+};
+
+class SkFlattenableWriteBuffer : public SkWriter32 {
+public:
+    SkFlattenableWriteBuffer(size_t minSize);
+    virtual ~SkFlattenableWriteBuffer();
+
+    void writeTypeface(SkTypeface*);
+    void writeRefCnt(SkRefCnt*);
+    void writeFunctionPtr(void*);
+    void writeFlattenable(SkFlattenable* flattenable);
+    
+    SkRefCntRecorder* getTypefaceRecorder() const { return fTFRecorder; }
+    SkRefCntRecorder* setTypefaceRecorder(SkRefCntRecorder*);
+    
+    SkRefCntRecorder* getRefCntRecorder() const { return fRCRecorder; }
+    SkRefCntRecorder* setRefCntRecorder(SkRefCntRecorder*);
+    
+    SkFactoryRecorder* getFactoryRecorder() const { return fFactoryRecorder; }
+    SkFactoryRecorder* setFactoryRecorder(SkFactoryRecorder*);
+
+    enum Flags {
+        kCrossProcess_Flag      = 0x01
+    };
+    Flags getFlags() const { return fFlags; }
+    void setFlags(Flags flags) { fFlags = flags; }
+    
+    bool isCrossProcess() const { return (fFlags & kCrossProcess_Flag) != 0; }
+
+    bool persistBitmapPixels() const {
+        return (fFlags & kCrossProcess_Flag) != 0;
+    }
+    
+    bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
+
+private:
+    Flags               fFlags;
+    SkRefCntRecorder*   fTFRecorder;
+    SkRefCntRecorder*   fRCRecorder;
+    SkFactoryRecorder*  fFactoryRecorder;
+    
+    typedef SkWriter32 INHERITED;
+};
+
+#endif
+
diff --git a/include/core/SkFloatBits.h b/include/core/SkFloatBits.h
new file mode 100644
index 0000000..1628f6e
--- /dev/null
+++ b/include/core/SkFloatBits.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkFloatBits_DEFINED
+#define SkFloatBits_DEFINED
+
+#include "SkTypes.h"
+
+/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
+    int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
+    it to be compared using normal C operators (<, <=, etc.)
+*/
+static inline int32_t SkSignBitTo2sCompliment(int32_t x) {
+    if (x < 0) {
+        x &= 0x7FFFFFFF;
+        x = -x;
+    }
+    return x;
+}
+
+/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).
+    This undoes the result of SkSignBitTo2sCompliment().
+ */
+static inline int32_t Sk2sComplimentToSignBit(int32_t x) {
+    int sign = x >> 31;
+    // make x positive
+    x = (x ^ sign) - sign;
+    // set the sign bit as needed
+    x |= sign << 31;
+    return x;
+}
+
+/** Given the bit representation of a float, return its value cast to an int.
+    If the value is out of range, or NaN, return return +/- SK_MaxS32
+*/
+int32_t SkFloatBits_toIntCast(int32_t floatBits);
+
+/** Given the bit representation of a float, return its floor as an int.
+    If the value is out of range, or NaN, return return +/- SK_MaxS32
+ */
+int32_t SkFloatBits_toIntFloor(int32_t floatBits);
+
+/** Given the bit representation of a float, return it rounded to an int.
+    If the value is out of range, or NaN, return return +/- SK_MaxS32
+ */
+int32_t SkFloatBits_toIntRound(int32_t floatBits);
+
+/** Given the bit representation of a float, return its ceiling as an int.
+    If the value is out of range, or NaN, return return +/- SK_MaxS32
+ */
+int32_t SkFloatBits_toIntCeil(int32_t floatBits);
+
+
+#ifdef SK_CAN_USE_FLOAT
+
+union SkFloatIntUnion {
+    float   fFloat;
+    int32_t fSignBitInt;
+};
+
+// Helper to see a float as its bit pattern (w/o aliasing warnings)
+static inline int32_t SkFloat2Bits(float x) {
+    SkFloatIntUnion data;
+    data.fFloat = x;
+    return data.fSignBitInt;
+}
+
+// Helper to see a bit pattern as a float (w/o aliasing warnings)
+static inline float SkBits2Float(int32_t floatAsBits) {
+    SkFloatIntUnion data;
+    data.fSignBitInt = floatAsBits;
+    return data.fFloat;
+}
+
+/** Return the float as a 2s compliment int. Just to be used to compare floats
+    to each other or against positive float-bit-constants (like 0). This does
+    not return the int equivalent of the float, just something cheaper for
+    compares-only.
+ */
+static inline int32_t SkFloatAs2sCompliment(float x) {
+    return SkSignBitTo2sCompliment(SkFloat2Bits(x));
+}
+
+/** Return the 2s compliment int as a float. This undos the result of
+    SkFloatAs2sCompliment
+ */
+static inline float Sk2sComplimentAsFloat(int32_t x) {
+    return SkBits2Float(Sk2sComplimentToSignBit(x));
+}
+
+/** Return x cast to a float (i.e. (float)x)
+*/
+float SkIntToFloatCast(int x);
+float SkIntToFloatCast_NoOverflowCheck(int x);
+
+/** Return the float cast to an int.
+    If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntCast(float x) {
+    return SkFloatBits_toIntCast(SkFloat2Bits(x));
+}
+
+/** Return the floor of the float as an int.
+    If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntFloor(float x) {
+    return SkFloatBits_toIntFloor(SkFloat2Bits(x));
+}
+
+/** Return the float rounded to an int.
+    If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntRound(float x) {
+    return SkFloatBits_toIntRound(SkFloat2Bits(x));
+}
+
+/** Return the ceiling of the float as an int.
+    If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntCeil(float x) {
+    return SkFloatBits_toIntCeil(SkFloat2Bits(x));
+}
+
+#endif
+
+//  Scalar wrappers for float-bit routines
+
+#ifdef SK_SCALAR_IS_FLOAT
+    #define SkScalarAs2sCompliment(x)    SkFloatAs2sCompliment(x)
+    #define Sk2sComplimentAsScalar(x)    Sk2sComplimentAsFloat(x)
+#else
+    #define SkScalarAs2sCompliment(x)    (x)
+    #define Sk2sComplimentAsScalar(x)    (x)
+#endif
+
+#endif
+
diff --git a/include/core/SkFloatingPoint.h b/include/core/SkFloatingPoint.h
new file mode 100644
index 0000000..d3a6fc5
--- /dev/null
+++ b/include/core/SkFloatingPoint.h
@@ -0,0 +1,75 @@
+/*
+ * 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 SkFloatingPoint_DEFINED
+#define SkFloatingPoint_DEFINED
+
+#include "SkTypes.h"
+
+#ifdef SK_CAN_USE_FLOAT
+
+#include <math.h>
+#include <float.h>
+#include "SkFloatBits.h"
+
+#ifdef SK_BUILD_FOR_WINCE
+    #define sk_float_sqrt(x)        (float)::sqrt(x)
+    #define sk_float_sin(x)         (float)::sin(x)
+    #define sk_float_cos(x)         (float)::cos(x)
+    #define sk_float_tan(x)         (float)::tan(x)
+    #define sk_float_acos(x)        (float)::acos(x)
+    #define sk_float_asin(x)        (float)::asin(x)
+    #define sk_float_atan2(y,x)     (float)::atan2(y,x)
+    #define sk_float_abs(x)         (float)::fabs(x)
+    #define sk_float_mod(x,y)       (float)::fmod(x,y)
+    #define sk_float_exp(x)         (float)::exp(x)
+    #define sk_float_log(x)         (float)::log(x)
+    #define sk_float_floor(x)       (float)::floor(x)
+    #define sk_float_ceil(x)        (float)::ceil(x)
+#else
+    #define sk_float_sqrt(x)        sqrtf(x)
+    #define sk_float_sin(x)         sinf(x)
+    #define sk_float_cos(x)         cosf(x)
+    #define sk_float_tan(x)         tanf(x)
+    #define sk_float_floor(x)       floorf(x)
+    #define sk_float_ceil(x)        ceilf(x)
+#ifdef SK_BUILD_FOR_MAC
+    #define sk_float_acos(x)        acos(x)
+    #define sk_float_asin(x)        asin(x)
+#else
+    #define sk_float_acos(x)        acosf(x)
+    #define sk_float_asin(x)        asinf(x)
+#endif
+    #define sk_float_atan2(y,x) atan2f(y,x)
+    #define sk_float_abs(x)         fabsf(x)
+    #define sk_float_mod(x,y)       fmodf(x,y)
+    #define sk_float_exp(x)         expf(x)
+    #define sk_float_log(x)         logf(x)
+    #define sk_float_isNaN(x)       _isnan(x)
+#endif
+
+#ifdef SK_USE_FLOATBITS
+    #define sk_float_floor2int(x)   SkFloatToIntFloor(x)
+    #define sk_float_round2int(x)   SkFloatToIntRound(x)
+    #define sk_float_ceil2int(x)    SkFloatToIntCeil(x)
+#else
+    #define sk_float_floor2int(x)   (int)sk_float_floor(x)
+    #define sk_float_round2int(x)   (int)sk_float_floor((x) + 0.5f)
+    #define sk_float_ceil2int(x)    (int)sk_float_ceil(x)
+#endif
+
+#endif
+#endif
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
new file mode 100644
index 0000000..ede40b7
--- /dev/null
+++ b/include/core/SkFontHost.h
@@ -0,0 +1,122 @@
+/*
+ * 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 SkFontHost_DEFINED
+#define SkFontHost_DEFINED
+
+#include "SkScalerContext.h"
+#include "SkTypeface.h"
+
+class SkDescriptor;
+class SkStream;
+class SkWStream;
+
+/** \class SkFontHost
+
+    This class is ported to each environment. It is responsible for bridging the gap
+    between SkTypeface and the resulting platform-specific instance of SkScalerContext.
+*/
+class SkFontHost {
+public:
+    /** Return the closest matching typeface given either an existing family
+        (specified by a typeface in that family) or by a familyName, and a
+        requested style.
+        1) If familyFace is null, use famillyName.
+        2) If famillyName is null, use familyFace.
+        3) If both are null, return the default font that best matches style
+
+        NOTE: this does not return a new typeface, nor does it affect the
+        owner count of an existing one, so the caller is free to ignore the
+        return result, or just compare it against null.
+     */
+    static SkTypeface* FindTypeface(const SkTypeface* familyFace,
+                                    const char famillyName[],
+                                    SkTypeface::Style style);
+
+    /** Return the typeface associated with the uniqueID, or null if that ID
+        does not match any faces.
+
+        NOTE: this does not return a new typeface, nor does it affect the
+        owner count of an existing one, so the caller is free to ignore the
+        return result, or just compare it against null.
+    */
+    static SkTypeface* ResolveTypeface(uint32_t uniqueID);
+    
+    /** Return a new stream to read the font data, or null if the uniqueID does
+        not match an existing typeface. The caller must call CloseStream() when
+        it is finished reading the stream.
+    */
+    static SkStream* OpenStream(uint32_t uniqueID);
+    
+    /** Call this when finished reading from the stream returned by OpenStream.
+        The caller should NOT try to delete the stream.
+     */
+    static void CloseStream(uint32_t uniqueID, SkStream*);
+
+    /** Return a new typeface given the data buffer (owned by the caller).
+        If the data does not represent a valid font, return null. The caller is
+        responsible for unref-ing the returned typeface (if it is not null).
+    */
+    static SkTypeface* CreateTypeface(SkStream*);
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** Write a unique identifier to the stream, so that the same typeface can
+        be retrieved with Deserialize().
+    */
+    static void Serialize(const SkTypeface*, SkWStream*);
+
+    /** Given a stream created by Serialize(), return the corresponding typeface
+        or null if no match is found.
+
+        NOTE: this does not return a new typeface, nor does it affect the
+        owner count of an existing one, so the caller is free to ignore the
+        return result, or just compare it against null.
+     */
+    static SkTypeface* Deserialize(SkStream*);
+
+    ///////////////////////////////////////////////////////////////////////////
+    
+    /** Return a subclass of SkScalarContext
+    */
+    static SkScalerContext* CreateScalerContext(const SkDescriptor* desc);
+
+    /** Return a scalercontext using the "fallback" font. If there is no designated
+        fallback, return null.
+    */
+    static SkScalerContext* CreateFallbackScalerContext(const SkScalerContext::Rec&);
+
+    /** Return the number of bytes (approx) that should be purged from the font
+        cache. The input parameter is the cache's estimate of how much as been
+        allocated by the cache so far.
+        To purge (basically) everything, return the input parameter.
+        To purge nothing, return 0
+    */
+    static size_t ShouldPurgeFontCache(size_t sizeAllocatedSoFar);
+
+    /** Return SkScalerContext gamma flag, or 0, based on the paint that will be
+        used to draw something with antialiasing.
+    */
+    static int ComputeGammaFlag(const SkPaint& paint);
+
+    /** Return NULL or a pointer to 256 bytes for the black (table[0]) and
+        white (table[1]) gamma tables.
+    */
+    static void GetGammaTables(const uint8_t* tables[2]);
+};
+
+#endif
+
diff --git a/include/core/SkGlobals.h b/include/core/SkGlobals.h
new file mode 100644
index 0000000..8e28290
--- /dev/null
+++ b/include/core/SkGlobals.h
@@ -0,0 +1,67 @@
+/*
+ * 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 SkGlobals_DEFINED
+#define SkGlobals_DEFINED
+
+#include "SkThread.h"
+
+class SkGlobals {
+public:
+    class Rec {
+    public:
+        virtual ~Rec();
+    private:
+        Rec*        fNext;
+        uint32_t    fTag;
+
+        friend class SkGlobals;
+    };
+
+    /** Look for a matching Rec for the specified tag. If one is found, return it.
+        If one is not found, if create_proc is null, return null, else
+        call the proc, and if it returns a Rec, add it to the global list
+        and return it.
+
+        create_proc can NOT call back into SkGlobals::Find (it would deadlock)
+    */
+    static Rec* Find(uint32_t tag, Rec* (*create_proc)());
+    /** Helper for Find, when you want to assert that the Rec is already in the list
+    */
+    static Rec* Get(uint32_t tag)
+    {
+        Rec* rec = SkGlobals::Find(tag, NULL);
+        SkASSERT(rec);
+        return rec;
+    }
+
+    // used by porting layer
+    struct BootStrap {
+        SkMutex fMutex;
+        Rec*    fHead;
+    };
+
+private:
+    static void Init();
+    static void Term();
+    friend class SkGraphics;
+
+    //  This last function is implemented in the porting layer
+    static BootStrap& GetBootStrap();
+};
+
+#endif
+
diff --git a/include/core/SkGraphics.h b/include/core/SkGraphics.h
new file mode 100644
index 0000000..cb06128
--- /dev/null
+++ b/include/core/SkGraphics.h
@@ -0,0 +1,46 @@
+/*
+ * 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 SkGraphics_DEFINED
+#define SkGraphics_DEFINED
+
+#include "SkTypes.h"
+
+class SkGraphics {
+public:
+    static void Init(bool runUnitTests);
+    static void Term();
+
+    /** Return the (approximate) number of bytes used by the font cache.
+    */
+    static size_t GetFontCacheUsed();
+    
+    /** Attempt to purge the font cache until <= the specified amount remains
+        in the cache. Specifying 0 will attempt to purge the entire cache.
+        Returns true if some amount was purged from the font cache.
+    */
+    static bool SetFontCacheUsed(size_t usageInBytes);
+    
+private:
+    /** This is automatically called by SkGraphics::Init(), and must be
+        implemented by the host OS. This allows the host OS to register a callback
+        with the C++ runtime to call SkGraphics::FreeCaches()
+    */
+    static void InstallNewHandler();
+};
+
+#endif
+
diff --git a/include/core/SkMMapStream.h b/include/core/SkMMapStream.h
new file mode 100644
index 0000000..600c621
--- /dev/null
+++ b/include/core/SkMMapStream.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkMMapStream_DEFINED
+#define SkMMapStream_DEFINED
+
+#include "SkStream.h"
+
+class SkMMAPStream : public SkMemoryStream {
+public:
+    SkMMAPStream(const char filename[]);
+    virtual ~SkMMAPStream();
+
+    virtual void setMemory(const void* data, size_t length);
+private:
+    int     fFildes;
+    void*   fAddr;
+    size_t  fSize;
+    
+    void closeMMap();
+    
+    typedef SkMemoryStream INHERITED;
+};
+
+#endif
diff --git a/include/core/SkMallocPixelRef.h b/include/core/SkMallocPixelRef.h
new file mode 100644
index 0000000..b6a013d
--- /dev/null
+++ b/include/core/SkMallocPixelRef.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkMallocPixelRef_DEFINED
+#define SkMallocPixelRef_DEFINED
+
+#include "SkPixelRef.h"
+
+/** We explicitly use the same allocator for our pixels that SkMask does,
+    so that we can freely assign memory allocated by one class to the other.
+*/
+class SkMallocPixelRef : public SkPixelRef {
+public:
+    /** Allocate the specified buffer for pixels. The memory is freed when the
+        last owner of this pixelref is gone.
+     */
+    SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable);
+    virtual ~SkMallocPixelRef();
+    
+    //! Return the allocation size for the pixels
+    size_t getSize() const { return fSize; }
+
+    // overrides from SkPixelRef
+    virtual void flatten(SkFlattenableWriteBuffer&) const;
+    virtual Factory getFactory() const {
+        return Create;
+    }
+    static SkPixelRef* Create(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkMallocPixelRef, (buffer));
+    }
+
+protected:
+    // overrides from SkPixelRef
+    virtual void* onLockPixels(SkColorTable**);
+    virtual void onUnlockPixels();
+
+    SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
+
+private:
+    void*           fStorage;
+    size_t          fSize;
+    SkColorTable*   fCTable;
+
+    typedef SkPixelRef INHERITED;
+};
+
+#endif
diff --git a/include/core/SkMask.h b/include/core/SkMask.h
new file mode 100644
index 0000000..764ead6
--- /dev/null
+++ b/include/core/SkMask.h
@@ -0,0 +1,86 @@
+/*
+ * 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 SkMask_DEFINED
+#define SkMask_DEFINED
+
+#include "SkRect.h"
+
+/** \class SkMask
+    SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
+    the 3-channel 3D format. These are passed to SkMaskFilter objects.
+*/
+struct SkMask {
+    enum Format {
+        kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
+        kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
+        k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
+        kLCD_Format //!< 3 bytes/pixel: r/g/b
+    };
+    
+    enum {
+        kCountMaskFormats = kLCD_Format + 1
+    };
+
+    uint8_t*    fImage;
+    SkIRect     fBounds;
+    uint16_t    fRowBytes;
+    uint8_t     fFormat;    // Format
+
+    /** Return the byte size of the mask, assuming only 1 plane.
+        Does not account for k3D_Format. For that, use computeFormatImageSize()
+    */
+    size_t computeImageSize() const;
+    /** Return the byte size of the mask, taking into account
+        any extra planes (e.g. k3D_Format).
+    */
+    size_t computeTotalImageSize() const;
+
+    /** Returns the address of the byte that holds the specified bit.
+        Asserts that the mask is kBW_Format, and that x,y are in range.
+        x,y are in the same coordiate space as fBounds.
+    */
+    uint8_t* getAddr1(int x, int y) const
+    {
+        SkASSERT(fFormat == kBW_Format);
+        SkASSERT(fBounds.contains(x, y));
+        SkASSERT(fImage != NULL);
+        return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes;
+    }
+    /** Returns the address of the specified byte.
+        Asserts that the mask is kA8_Format, and that x,y are in range.
+        x,y are in the same coordiate space as fBounds.
+    */
+    uint8_t* getAddr(int x, int y) const
+    {
+        SkASSERT(fFormat != kBW_Format);
+        SkASSERT(fBounds.contains(x, y));
+        SkASSERT(fImage != NULL);
+        return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
+    }
+
+    static uint8_t* AllocImage(size_t bytes);
+    static void FreeImage(void* image);
+    
+    enum CreateMode {
+        kJustComputeBounds_CreateMode,      //!< compute bounds and return
+        kJustRenderImage_CreateMode,        //!< render into preallocate mask
+        kComputeBoundsAndRenderImage_CreateMode  //!< compute bounds, alloc image and render into it
+    };
+};
+
+#endif
+
diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h
new file mode 100644
index 0000000..749a73a
--- /dev/null
+++ b/include/core/SkMaskFilter.h
@@ -0,0 +1,100 @@
+/*
+ * 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 SkMaskFilter_DEFINED
+#define SkMaskFilter_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkMask.h"
+
+class SkBlitter;
+class SkBounder;
+class SkMatrix;
+class SkPath;
+class SkRegion;
+
+/** \class SkMaskFilter
+
+    SkMaskFilter is the base class for object that perform transformations on
+    an alpha-channel mask before drawing it. A subclass of SkMaskFilter may be
+    installed into a SkPaint. Once there, each time a primitive is drawn, it
+    is first scan converted into a SkMask::kA8_Format mask, and handed to the
+    filter, calling its filterMask() method. If this returns true, then the
+    new mask is used to render into the device.
+
+    Blur and emboss are implemented as subclasses of SkMaskFilter.
+*/
+class SkMaskFilter : public SkFlattenable {
+public:
+    SkMaskFilter() {}
+
+    /** Returns the format of the resulting mask that this subclass will return
+        when its filterMask() method is called.
+    */
+    virtual SkMask::Format  getFormat() = 0;
+
+    /** Create a new mask by filter the src mask.
+        If src.fImage == null, then do not allocate or create the dst image
+        but do fill out the other fields in dstMask.
+        If you do allocate a dst image, use SkMask::AllocImage()
+        If this returns false, dst mask is ignored.
+        @param  dst the result of the filter. If src.fImage == null, dst should not allocate its image
+        @param src the original image to be filtered.
+        @param matrix the CTM
+        @param margin   if not null, return the buffer dx/dy need when calculating the effect. Used when
+                        drawing a clipped object to know how much larger to allocate the src before
+                        applying the filter. If returning false, ignore this parameter.
+        @return true if the dst mask was correctly created.
+    */
+    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkIPoint* margin);
+
+    /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask
+        and then call filterMask(). If this returns true, the specified blitter will be called
+        to render that mask. Returns false if filterMask() returned false.
+        This method is not exported to java.
+    */
+    bool filterPath(const SkPath& devPath, const SkMatrix& devMatrix,
+                    const SkRegion& devClip, SkBounder*, SkBlitter* blitter);
+
+    virtual void flatten(SkFlattenableWriteBuffer& ) {}
+protected:
+    // empty for now, but lets get our subclass to remember to init us for the future
+    SkMaskFilter(SkFlattenableReadBuffer&) {}
+};
+
+/** \class SkAutoMaskImage
+
+    Stack class used to manage the fImage buffer in a SkMask.
+    When this object loses scope, the buffer is freed with SkMask::FreeImage().
+*/
+class SkAutoMaskImage {
+public:
+    SkAutoMaskImage(SkMask* mask, bool alloc)
+    {
+        if (alloc)
+            mask->fImage = SkMask::AllocImage(mask->computeImageSize());
+        fImage = mask->fImage;
+    }
+    ~SkAutoMaskImage()
+    {
+        SkMask::FreeImage(fImage);
+    }
+private:
+    uint8_t*    fImage;
+};
+
+#endif
+
diff --git a/include/core/SkMath.h b/include/core/SkMath.h
new file mode 100644
index 0000000..5c2b475
--- /dev/null
+++ b/include/core/SkMath.h
@@ -0,0 +1,230 @@
+/*
+ * 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 SkMath_DEFINED
+#define SkMath_DEFINED
+
+#include "SkTypes.h"
+
+//! Returns the number of leading zero bits (0...32)
+int SkCLZ_portable(uint32_t);
+
+/** Computes the 64bit product of a * b, and then shifts the answer down by
+    shift bits, returning the low 32bits. shift must be [0..63]
+    e.g. to perform a fixedmul, call SkMulShift(a, b, 16)
+*/
+int32_t SkMulShift(int32_t a, int32_t b, unsigned shift);
+
+/** Computes numer1 * numer2 / denom in full 64 intermediate precision.
+    It is an error for denom to be 0. There is no special handling if
+    the result overflows 32bits.
+*/
+int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom);
+
+/** Computes (numer1 << shift) / denom in full 64 intermediate precision.
+    It is an error for denom to be 0. There is no special handling if
+    the result overflows 32bits.
+*/
+int32_t SkDivBits(int32_t numer, int32_t denom, int shift);
+
+/** Return the integer square root of value, with a bias of bitBias
+*/
+int32_t SkSqrtBits(int32_t value, int bitBias);
+
+/** Return the integer square root of n, treated as a SkFixed (16.16)
+*/
+#define SkSqrt32(n)         SkSqrtBits(n, 15)
+
+/** Return the integer cube root of value, with a bias of bitBias
+ */
+int32_t SkCubeRootBits(int32_t value, int bitBias);
+
+/** Returns -1 if n < 0, else returns 0
+*/
+#define SkExtractSign(n)    ((int32_t)(n) >> 31)
+
+/** If sign == -1, returns -n, else sign must be 0, and returns n.
+    Typically used in conjunction with SkExtractSign().
+*/
+static inline int32_t SkApplySign(int32_t n, int32_t sign) {
+    SkASSERT(sign == 0 || sign == -1);
+    return (n ^ sign) - sign;
+}
+
+/** Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches)
+*/
+static inline int SkClampPos(int value) {
+    return value & ~(value >> 31);
+}
+
+/** Given an integer and a positive (max) integer, return the value
+    pinned against 0 and max, inclusive.
+    Note: only works as long as max - value doesn't wrap around
+    @param value    The value we want returned pinned between [0...max]
+    @param max      The positive max value
+    @return 0 if value < 0, max if value > max, else value
+*/
+static inline int SkClampMax(int value, int max) {
+    // ensure that max is positive
+    SkASSERT(max >= 0);
+    // ensure that if value is negative, max - value doesn't wrap around
+    SkASSERT(value >= 0 || max - value > 0);
+
+#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
+    if (value < 0) {
+        value = 0;
+    }
+    if (value > max) {
+        value = max;
+    }
+    return value;
+#else
+
+    int diff = max - value;
+    // clear diff if diff is positive
+    diff &= diff >> 31;
+
+    // clear the result if value < 0
+    return (value + diff) & ~(value >> 31);
+#endif
+}
+
+/** Given a positive value and a positive max, return the value
+    pinned against max.
+    Note: only works as long as max - value doesn't wrap around
+    @return max if value >= max, else value
+*/
+static inline unsigned SkClampUMax(unsigned value, unsigned max) {
+#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
+    if (value > max) {
+        value = max;
+    }
+    return value;
+#else
+    int diff = max - value;
+    // clear diff if diff is positive
+    diff &= diff >> 31;
+
+    return value + diff;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(__arm__) && !defined(__thumb__)
+    #define SkCLZ(x)    __builtin_clz(x)
+#endif
+
+#ifndef SkCLZ
+    #define SkCLZ(x)    SkCLZ_portable(x)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Returns the smallest power-of-2 that is >= the specified value. If value
+    is already a power of 2, then it is returned unchanged. It is undefined
+    if value is <= 0.
+*/
+static inline int SkNextPow2(int value) {
+    SkASSERT(value > 0);
+    return 1 << (32 - SkCLZ(value - 1));
+}
+
+/** Returns the log2 of the specified value, were that value to be rounded up
+    to the next power of 2. It is undefined to pass 0. Examples:
+         SkNextLog2(1) -> 0
+         SkNextLog2(2) -> 1
+         SkNextLog2(3) -> 2
+         SkNextLog2(4) -> 2
+         SkNextLog2(5) -> 3
+*/
+static inline int SkNextLog2(uint32_t value) {
+    SkASSERT(value != 0);
+    return 32 - SkCLZ(value - 1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t.
+    With this requirement, we can generate faster instructions on some
+    architectures.
+*/
+#if defined(__arm__) && !defined(__thumb__)
+    static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
+        SkASSERT((int16_t)x == x);
+        SkASSERT((int16_t)y == y);
+        int32_t product;
+        asm("smulbb %0, %1, %2 \n"
+            : "=r"(product)
+            : "r"(x), "r"(y)
+            :
+            );
+        return product;
+    }
+#else
+    #ifdef SK_DEBUG
+        static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
+            SkASSERT((int16_t)x == x);
+            SkASSERT((int16_t)y == y);
+            return x * y;
+        }
+    #else
+        #define SkMulS16(x, y)  ((x) * (y))
+    #endif
+#endif
+
+/** Return a*b/255, truncating away any fractional bits. Only valid if both
+    a and b are 0..255
+*/
+static inline U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b) {
+    SkASSERT((uint8_t)a == a);
+    SkASSERT((uint8_t)b == b);
+    unsigned prod = SkMulS16(a, b) + 1;
+    return (prod + (prod >> 8)) >> 8;
+}
+
+/** Return a*b/255, rounding any fractional bits. Only valid if both
+    a and b are 0..255
+ */
+static inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) {
+    SkASSERT((uint8_t)a == a);
+    SkASSERT((uint8_t)b == b);
+    unsigned prod = SkMulS16(a, b) + 128;
+    return (prod + (prod >> 8)) >> 8;
+}
+
+/** Return a*b/((1 << shift) - 1), rounding any fractional bits.
+    Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
+*/
+static inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) {
+    SkASSERT(a <= 32767);
+    SkASSERT(b <= 32767);
+    SkASSERT(shift > 0 && shift <= 8);
+    unsigned prod = SkMulS16(a, b) + (1 << (shift - 1));
+    return (prod + (prod >> shift)) >> shift;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG
+    class SkMath {
+    public:
+        static void UnitTest();
+    };
+#endif
+
+#endif
+
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
new file mode 100644
index 0000000..2b25dca
--- /dev/null
+++ b/include/core/SkMatrix.h
@@ -0,0 +1,479 @@
+/*
+ * 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 SkMatrix_DEFINED
+#define SkMatrix_DEFINED
+
+#include "SkRect.h"
+
+class SkString;
+
+/** \class SkMatrix
+
+    The SkMatrix class holds a 3x3 matrix for transforming coordinates.
+    SkMatrix does not have a constructor, so it must be explicitly initialized
+    using either reset() - to construct an identity matrix, or one of the set
+    functions (e.g. setTranslate, setRotate, etc.).
+*/
+class SkMatrix {
+public:
+    /** Enum of bit fields for the mask return by getType().
+        Use this to identify the complexity of the matrix.
+    */
+    enum TypeMask {
+        kIdentity_Mask      = 0,
+        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
+        kScale_Mask         = 0x02,  //!< set if the matrix has X or Y scale
+        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
+        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
+    };
+
+    /** Returns a mask bitfield describing the types of transformations
+        that the matrix will perform. This information is used by routines
+        like mapPoints, to optimize its inner loops to only perform as much
+        arithmetic as is necessary.
+    */
+    TypeMask getType() const {
+        if (fTypeMask & kUnknown_Mask) {
+            fTypeMask = this->computeTypeMask();
+        }
+        // only return the public masks
+        return (TypeMask)(fTypeMask & 0xF);
+    }
+
+    /** Returns true if the matrix is identity.
+    */
+    bool isIdentity() const {
+        return this->getType() == 0;
+    }
+
+    /** Returns true if will map a rectangle to another rectangle. This can be
+        true if the matrix is identity, scale-only, or rotates a multiple of
+        90 degrees.
+    */
+    bool rectStaysRect() const {
+        if (fTypeMask & kUnknown_Mask) {
+            fTypeMask = this->computeTypeMask();
+        }
+        return (fTypeMask & kRectStaysRect_Mask) != 0;
+    }
+
+    enum {
+        kMScaleX,
+        kMSkewX,
+        kMTransX,
+        kMSkewY,
+        kMScaleY,
+        kMTransY,
+        kMPersp0,
+        kMPersp1,
+        kMPersp2
+    };
+    
+    SkScalar operator[](int index) const {
+        SkASSERT((unsigned)index < 9);
+        return fMat[index];
+    }
+    
+    SkScalar get(int index) const {
+        SkASSERT((unsigned)index < 9);
+        return fMat[index];
+    }
+    
+    SkScalar getScaleX() const { return fMat[kMScaleX]; }
+    SkScalar getScaleY() const { return fMat[kMScaleY]; }
+    SkScalar getSkewY() const { return fMat[kMSkewY]; }
+    SkScalar getSkewX() const { return fMat[kMSkewX]; }
+    SkScalar getTranslateX() const { return fMat[kMTransX]; }
+    SkScalar getTranslateY() const { return fMat[kMTransY]; }
+    SkScalar getPerspX() const { return fMat[kMPersp0]; }
+    SkScalar getPerspY() const { return fMat[kMPersp1]; }
+
+    void set(int index, SkScalar value) {
+        SkASSERT((unsigned)index < 9);
+        fMat[index] = value;
+        this->setTypeMask(kUnknown_Mask);
+    }
+
+    void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
+    void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
+    void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
+    void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
+    void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
+    void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
+    void setPerspX(SkScalar v) { this->set(kMPersp0, v); }
+    void setPerspY(SkScalar v) { this->set(kMPersp1, v); }
+
+    /** Set the matrix to identity
+    */
+    void reset();
+    
+    /** Set the matrix to translate by (dx, dy).
+    */
+    void setTranslate(SkScalar dx, SkScalar dy);
+    /** Set the matrix to scale by sx and sy, with a pivot point at (px, py).
+        The pivot point is the coordinate that should remain unchanged by the
+        specified transformation.
+    */
+    void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+    /** Set the matrix to scale by sx and sy.
+    */
+    void setScale(SkScalar sx, SkScalar sy);
+    /** Set the matrix to rotate by the specified number of degrees, with a
+        pivot point at (px, py). The pivot point is the coordinate that should
+        remain unchanged by the specified transformation.
+    */
+    void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
+    /** Set the matrix to rotate about (0,0) by the specified number of degrees.
+    */
+    void setRotate(SkScalar degrees);
+    /** Set the matrix to rotate by the specified sine and cosine values, with
+        a pivot point at (px, py). The pivot point is the coordinate that
+        should remain unchanged by the specified transformation.
+    */
+    void setSinCos(SkScalar sinValue, SkScalar cosValue,
+                   SkScalar px, SkScalar py);
+    /** Set the matrix to rotate by the specified sine and cosine values.
+    */
+    void setSinCos(SkScalar sinValue, SkScalar cosValue);
+    /** Set the matrix to skew by sx and sy, with a pivot point at (px, py).
+        The pivot point is the coordinate that should remain unchanged by the
+        specified transformation.
+    */
+    void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+    /** Set the matrix to skew by sx and sy.
+    */
+    void setSkew(SkScalar kx, SkScalar ky);
+    /** Set the matrix to the concatenation of the two specified matrices,
+        returning true if the the result can be represented. Either of the
+        two matrices may also be the target matrix. *this = a * b;
+    */
+    bool setConcat(const SkMatrix& a, const SkMatrix& b);
+
+    /** Preconcats the matrix with the specified translation.
+        M' = M * T(dx, dy)
+    */
+    bool preTranslate(SkScalar dx, SkScalar dy);
+    /** Preconcats the matrix with the specified scale.
+        M' = M * S(sx, sy, px, py)
+    */
+    bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+    /** Preconcats the matrix with the specified scale.
+        M' = M * S(sx, sy)
+    */
+    bool preScale(SkScalar sx, SkScalar sy);
+    /** Preconcats the matrix with the specified rotation.
+        M' = M * R(degrees, px, py)
+    */
+    bool preRotate(SkScalar degrees, SkScalar px, SkScalar py);
+    /** Preconcats the matrix with the specified rotation.
+        M' = M * R(degrees)
+    */
+    bool preRotate(SkScalar degrees);
+    /** Preconcats the matrix with the specified skew.
+        M' = M * K(kx, ky, px, py)
+    */
+    bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+    /** Preconcats the matrix with the specified skew.
+        M' = M * K(kx, ky)
+    */
+    bool preSkew(SkScalar kx, SkScalar ky);
+    /** Preconcats the matrix with the specified matrix.
+        M' = M * other
+    */
+    bool preConcat(const SkMatrix& other);
+
+    /** Postconcats the matrix with the specified translation.
+        M' = T(dx, dy) * M
+    */
+    bool postTranslate(SkScalar dx, SkScalar dy);
+    /** Postconcats the matrix with the specified scale.
+        M' = S(sx, sy, px, py) * M
+    */
+    bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+    /** Postconcats the matrix with the specified scale.
+        M' = S(sx, sy) * M
+    */
+    bool postScale(SkScalar sx, SkScalar sy);
+    /** Postconcats the matrix by dividing it by the specified integers.
+        M' = S(1/divx, 1/divy, 0, 0) * M
+    */
+    bool postIDiv(int divx, int divy);
+    /** Postconcats the matrix with the specified rotation.
+        M' = R(degrees, px, py) * M
+    */
+    bool postRotate(SkScalar degrees, SkScalar px, SkScalar py);
+    /** Postconcats the matrix with the specified rotation.
+        M' = R(degrees) * M
+    */
+    bool postRotate(SkScalar degrees);
+    /** Postconcats the matrix with the specified skew.
+        M' = K(kx, ky, px, py) * M
+    */
+    bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+    /** Postconcats the matrix with the specified skew.
+        M' = K(kx, ky) * M
+    */
+    bool postSkew(SkScalar kx, SkScalar ky);
+    /** Postconcats the matrix with the specified matrix.
+        M' = other * M
+    */
+    bool postConcat(const SkMatrix& other);
+
+    enum ScaleToFit {
+        /**
+         * Scale in X and Y independently, so that src matches dst exactly.
+         * This may change the aspect ratio of the src.
+         */
+        kFill_ScaleToFit,
+        /**
+         * Compute a scale that will maintain the original src aspect ratio,
+         * but will also ensure that src fits entirely inside dst. At least one
+         * axis (X or Y) will fit exactly. kStart aligns the result to the
+         * left and top edges of dst.
+         */
+        kStart_ScaleToFit,
+        /**
+         * Compute a scale that will maintain the original src aspect ratio,
+         * but will also ensure that src fits entirely inside dst. At least one
+         * axis (X or Y) will fit exactly. The result is centered inside dst.
+         */
+        kCenter_ScaleToFit,
+        /**
+         * Compute a scale that will maintain the original src aspect ratio,
+         * but will also ensure that src fits entirely inside dst. At least one
+         * axis (X or Y) will fit exactly. kEnd aligns the result to the
+         * right and bottom edges of dst.
+         */
+        kEnd_ScaleToFit
+    };
+
+    /** Set the matrix to the scale and translate values that map the source
+        rectangle to the destination rectangle, returning true if the the result
+        can be represented.
+        @param src the source rectangle to map from.
+        @param dst the destination rectangle to map to.
+        @param stf the ScaleToFit option
+        @return true if the matrix can be represented by the rectangle mapping.
+    */
+    bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
+    
+    /** Set the matrix such that the specified src points would map to the
+        specified dst points. count must be within [0..4].
+        @param src  The array of src points
+        @param dst  The array of dst points
+        @param count The number of points to use for the transformation
+        @return true if the matrix was set to the specified transformation
+    */
+    bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
+
+    /** If this matrix can be inverted, return true and if inverse is not null,
+        set inverse to be the inverse of this matrix. If this matrix cannot be
+        inverted, ignore inverse and return false
+    */
+    bool invert(SkMatrix* inverse) const;
+
+    /** Apply this matrix to the array of points specified by src, and write
+        the transformed points into the array of points specified by dst.
+        dst[] = M * src[]
+        @param dst  Where the transformed coordinates are written. It must
+                    contain at least count entries
+        @param src  The original coordinates that are to be transformed. It
+                    must contain at least count entries
+        @param count The number of points in src to read, and then transform
+                     into dst.
+    */
+    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
+
+    /** Apply this matrix to the array of points, overwriting it with the
+        transformed values.
+        dst[] = M * pts[]
+        @param pts  The points to be transformed. It must contain at least
+                    count entries
+        @param count The number of points in pts.
+    */
+    void mapPoints(SkPoint pts[], int count) const {
+        this->mapPoints(pts, pts, count);
+    }
+    
+    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
+        SkASSERT(result);
+        this->getMapXYProc()(*this, x, y, result);
+    }
+
+    /** Apply this matrix to the array of vectors specified by src, and write
+        the transformed vectors into the array of vectors specified by dst.
+        This is similar to mapPoints, but ignores any translation in the matrix.
+        @param dst  Where the transformed coordinates are written. It must
+                    contain at least count entries
+        @param src  The original coordinates that are to be transformed. It
+                    must contain at least count entries
+        @param count The number of vectors in src to read, and then transform
+                     into dst.
+    */
+    void mapVectors(SkVector dst[], const SkVector src[], int count) const;
+
+    /** Apply this matrix to the array of vectors specified by src, and write
+        the transformed vectors into the array of vectors specified by dst.
+        This is similar to mapPoints, but ignores any translation in the matrix.
+        @param vecs The vectors to be transformed. It must contain at least
+                    count entries
+        @param count The number of vectors in vecs.
+    */
+    void mapVectors(SkVector vecs[], int count) const {
+        this->mapVectors(vecs, vecs, count);
+    }
+
+    /** Apply this matrix to the src rectangle, and write the transformed
+        rectangle into dst. This is accomplished by transforming the 4 corners
+        of src, and then setting dst to the bounds of those points.
+        @param dst  Where the transformed rectangle is written.
+        @param src  The original rectangle to be transformed.
+        @return the result of calling rectStaysRect()
+    */
+    bool mapRect(SkRect* dst, const SkRect& src) const;
+
+    /** Apply this matrix to the rectangle, and write the transformed rectangle
+        back into it. This is accomplished by transforming the 4 corners of
+        rect, and then setting it to the bounds of those points
+        @param rect The rectangle to transform.
+        @return the result of calling rectStaysRect()
+    */
+    bool mapRect(SkRect* rect) const {
+        return this->mapRect(rect, *rect);
+    }
+
+    /** Return the mean radius of a circle after it has been mapped by
+        this matrix. NOTE: in perspective this value assumes the circle
+        has its center at the origin.
+    */
+    SkScalar mapRadius(SkScalar radius) const;
+
+    typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
+                                 SkPoint* result);
+
+    static MapXYProc GetMapXYProc(TypeMask mask) {
+        SkASSERT((mask & ~kAllMasks) == 0);
+        return gMapXYProcs[mask & kAllMasks];
+    }
+    
+    MapXYProc getMapXYProc() const {
+        return GetMapXYProc(this->getType());
+    }
+
+    typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
+                                  const SkPoint src[], int count);
+
+    static MapPtsProc GetMapPtsProc(TypeMask mask) {
+        SkASSERT((mask & ~kAllMasks) == 0);
+        return gMapPtsProcs[mask & kAllMasks];
+    }
+    
+    MapPtsProc getMapPtsProc() const {
+        return GetMapPtsProc(this->getType());
+    }
+
+    /** If the matrix can be stepped in X (not complex perspective)
+        then return true and if step[XY] is not null, return the step[XY] value.
+        If it cannot, return false and ignore step.
+    */
+    bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const;
+
+    friend bool operator==(const SkMatrix& a, const SkMatrix& b) {
+        return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) == 0;
+    }
+
+    friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
+        return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) != 0;
+    }
+    
+    void dump() const;
+    void toDumpString(SkString*) const;
+
+#ifdef SK_DEBUG
+  /** @cond UNIT_TEST */
+
+    static void UnitTest();
+  /** @endcond */
+#endif
+
+private:
+    enum {
+        /** Set if the matrix will map a rectangle to another rectangle. This
+            can be true if the matrix is scale-only, or rotates a multiple of
+            90 degrees. This bit is not set if the matrix is identity.
+             
+            This bit will be set on identity matrices
+        */
+        kRectStaysRect_Mask = 0x10,
+
+        kUnknown_Mask = 0x80,
+        
+        kAllMasks = kTranslate_Mask |
+                    kScale_Mask |
+                    kAffine_Mask |
+                    kPerspective_Mask |
+                    kRectStaysRect_Mask
+    };
+
+    SkScalar        fMat[9];
+    mutable uint8_t fTypeMask;
+
+    uint8_t computeTypeMask() const;
+
+    void setTypeMask(int mask) {
+        // allow kUnknown or a valid mask
+        SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask);
+        fTypeMask = SkToU8(mask);
+    }
+    
+    void clearTypeMask(int mask) {
+        // only allow a valid mask
+        SkASSERT((mask & kAllMasks) == mask);
+        fTypeMask &= ~mask;
+    }
+    
+    static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
+    static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
+    static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
+
+    static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    
+    static const MapXYProc gMapXYProcs[];
+    
+    static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
+    static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+    static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+    static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
+                               int count);
+    static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+    static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
+                             int count);
+    static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+    
+    static const MapPtsProc gMapPtsProcs[];
+
+    friend class SkPerspIter;
+};
+
+#endif
+
diff --git a/include/core/SkPackBits.h b/include/core/SkPackBits.h
new file mode 100644
index 0000000..c11231b
--- /dev/null
+++ b/include/core/SkPackBits.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPackBits_DEFINED
+#define SkPackBits_DEFINED
+
+#include "SkTypes.h"
+
+class SkPackBits {
+public:
+    /** Given the number of 16bit values that will be passed to Pack16,
+        returns the worst-case size needed for the dst[] buffer.
+    */
+    static size_t ComputeMaxSize16(int count);
+
+    /** Given the number of 8bit values that will be passed to Pack8,
+        returns the worst-case size needed for the dst[] buffer.
+    */
+    static size_t ComputeMaxSize8(int count);
+
+    /** Write the src array into a packed format. The packing process may end
+        up writing more bytes than it read, so dst[] must be large enough.
+        @param src      Input array of 16bit values
+        @param count    Number of entries in src[]
+        @param dst      Buffer (allocated by caller) to write the packed data
+                        into
+        @return the number of bytes written to dst[]
+    */
+    static size_t Pack16(const uint16_t src[], int count, uint8_t dst[]);
+
+    /** Write the src array into a packed format. The packing process may end
+        up writing more bytes than it read, so dst[] must be large enough.
+        @param src      Input array of 8bit values
+        @param count    Number of entries in src[]
+        @param dst      Buffer (allocated by caller) to write the packed data
+                        into
+        @return the number of bytes written to dst[]
+    */
+    static size_t Pack8(const uint8_t src[], int count, uint8_t dst[]);
+
+    /** Unpack the data in src[], and expand it into dst[]. The src[] data was
+        written by a previous call to Pack16.
+        @param src  Input data to unpack, previously created by Pack16.
+        @param srcSize  Number of bytes of src to unpack
+        @param dst  Buffer (allocated by caller) to expand the src[] into.
+        @return the number of dst elements (not bytes) written into dst.
+    */
+    static int Unpack16(const uint8_t src[], size_t srcSize, uint16_t dst[]);
+
+    /** Unpack the data in src[], and expand it into dst[]. The src[] data was
+        written by a previous call to Pack8.
+        @param src      Input data to unpack, previously created by Pack8.
+        @param srcSize  Number of bytes of src to unpack
+        @param dst      Buffer (allocated by caller) to expand the src[] into.
+        @return the number of bytes written into dst.
+    */
+    static int Unpack8(const uint8_t src[], size_t srcSize, uint8_t dst[]);
+
+    /** Unpack the data from src[], skip the first dstSkip bytes, then write
+        dstWrite bytes into dst[]. The src[] data was written by a previous
+        call to Pack8. Return the number of bytes actually writtten into dst[]
+        @param src      Input data to unpack, previously created by Pack8.
+        @param dst      Buffer (allocated by caller) to expand the src[] into.
+        @param dstSkip  Number of bytes of unpacked src to skip before writing
+                        into dst
+        @param dstWrite Number of bytes of unpacked src to write into dst (after
+                        skipping dstSkip bytes)
+    */
+    static void Unpack8(uint8_t dst[], size_t dstSkip, size_t dstWrite,
+                        const uint8_t src[]);
+};
+
+#endif
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
new file mode 100644
index 0000000..fc390ab
--- /dev/null
+++ b/include/core/SkPaint.h
@@ -0,0 +1,814 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPaint_DEFINED
+#define SkPaint_DEFINED
+
+#include "SkColor.h"
+#include "SkMath.h"
+#include "SkPorterDuff.h"
+
+class SkAutoGlyphCache;
+class SkColorFilter;
+class SkDescriptor;
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+struct SkGlyph;
+struct SkRect;
+class SkGlyphCache;
+class SkMaskFilter;
+class SkMatrix;
+class SkPath;
+class SkPathEffect;
+class SkRasterizer;
+class SkShader;
+class SkDrawLooper;
+class SkTypeface;
+class SkXfermode;
+
+typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**,
+                                           SkFixed x, SkFixed y);
+
+typedef const SkGlyph& (*SkMeasureCacheProc)(SkGlyphCache*, const char**);
+
+/** \class SkPaint
+
+    The SkPaint class holds the style and color information about how to draw
+    geometries, text and bitmaps.
+*/
+class SkPaint {
+public:
+    SkPaint();
+    SkPaint(const SkPaint& paint);
+    ~SkPaint();
+
+    SkPaint& operator=(const SkPaint&);
+
+    friend int operator==(const SkPaint& a, const SkPaint& b);
+    friend int operator!=(const SkPaint& a, const SkPaint& b)
+    {
+        return !(a == b);
+    }
+    
+    void flatten(SkFlattenableWriteBuffer&) const;
+    void unflatten(SkFlattenableReadBuffer&);
+
+    /** Restores the paint to its initial settings.
+    */
+    void reset();
+
+    /** Specifies the bit values that are stored in the paint's flags.
+    */
+    enum Flags {
+        kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing
+        kFilterBitmap_Flag    = 0x02,   //!< mask to enable bitmap filtering
+        kDither_Flag          = 0x04,   //!< mask to enable dithering
+        kUnderlineText_Flag   = 0x08,   //!< mask to enable underline text
+        kStrikeThruText_Flag  = 0x10,   //!< mask to enable strike-thru text
+        kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text
+        kLinearText_Flag      = 0x40,   //!< mask to enable linear-text
+        kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel-text
+        kDevKernText_Flag     = 0x100,  //!< mask to enable device kerning text
+
+        kAllFlags = 0x1FF
+    };
+
+    /** Return the paint's flags. Use the Flag enum to test flag values.
+        @return the paint's flags (see enums ending in _Flag for bit masks)
+    */
+    uint32_t getFlags() const { return fFlags; }
+
+    /** Set the paint's flags. Use the Flag enum to specific flag values.
+        @param flags    The new flag bits for the paint (see Flags enum)
+    */
+    void setFlags(uint32_t flags);
+
+    /** Helper for getFlags(), returning true if kAntiAlias_Flag bit is set
+        @return true if the antialias bit is set in the paint's flags.
+        */
+    bool isAntiAlias() const
+    {
+        return SkToBool(this->getFlags() & kAntiAlias_Flag);
+    }
+    
+    /** Helper for setFlags(), setting or clearing the kAntiAlias_Flag bit
+        @param aa   true to enable antialiasing, false to disable it
+        */
+    void setAntiAlias(bool aa);
+    
+    /** Helper for getFlags(), returning true if kDither_Flag bit is set
+        @return true if the dithering bit is set in the paint's flags.
+        */
+    bool isDither() const
+    {
+        return SkToBool(this->getFlags() & kDither_Flag);
+    }
+    
+    /** Helper for setFlags(), setting or clearing the kDither_Flag bit
+        @param dither   true to enable dithering, false to disable it
+        */
+    void setDither(bool dither);
+    
+    /** Helper for getFlags(), returning true if kLinearText_Flag bit is set
+        @return true if the lineartext bit is set in the paint's flags
+    */
+    bool isLinearText() const
+    {
+        return SkToBool(this->getFlags() & kLinearText_Flag);
+    }
+
+    /** Helper for setFlags(), setting or clearing the kLinearText_Flag bit
+        @param linearText true to set the linearText bit in the paint's flags,
+                          false to clear it.
+    */
+    void setLinearText(bool linearText);
+
+    /** Helper for getFlags(), returning true if kSubpixelText_Flag bit is set
+        @return true if the lineartext bit is set in the paint's flags
+    */
+    bool isSubpixelText() const
+    {
+        return SkToBool(this->getFlags() & kSubpixelText_Flag);
+    }
+    
+    /** Helper for setFlags(), setting or clearing the kSubpixelText_Flag bit
+        @param subpixelText true to set the subpixelText bit in the paint's
+                            flags, false to clear it.
+    */
+    void setSubpixelText(bool subpixelText);
+    
+    /** Helper for getFlags(), returning true if kUnderlineText_Flag bit is set
+        @return true if the underlineText bit is set in the paint's flags.
+    */
+    bool isUnderlineText() const
+    {
+        return SkToBool(this->getFlags() & kUnderlineText_Flag);
+    }
+
+    /** Helper for setFlags(), setting or clearing the kUnderlineText_Flag bit
+        @param underlineText true to set the underlineText bit in the paint's
+                             flags, false to clear it.
+    */
+    void setUnderlineText(bool underlineText);
+
+    /** Helper for getFlags(), returns true if kStrikeThruText_Flag bit is set
+        @return true if the strikeThruText bit is set in the paint's flags.
+    */
+    bool    isStrikeThruText() const
+    {
+        return SkToBool(this->getFlags() & kStrikeThruText_Flag);
+    }
+
+    /** Helper for setFlags(), setting or clearing the kStrikeThruText_Flag bit
+        @param strikeThruText   true to set the strikeThruText bit in the
+                                paint's flags, false to clear it.
+    */
+    void setStrikeThruText(bool strikeThruText);
+
+    /** Helper for getFlags(), returns true if kFakeBoldText_Flag bit is set
+        @return true if the kFakeBoldText_Flag bit is set in the paint's flags.
+    */
+    bool isFakeBoldText() const
+    {
+        return SkToBool(this->getFlags() & kFakeBoldText_Flag);
+    }
+
+    /** Helper for setFlags(), setting or clearing the kFakeBoldText_Flag bit
+        @param fakeBoldText true to set the kFakeBoldText_Flag bit in the paint's
+                            flags, false to clear it.
+    */
+    void setFakeBoldText(bool fakeBoldText);
+
+    /** Helper for getFlags(), returns true if kDevKernText_Flag bit is set
+        @return true if the kernText bit is set in the paint's flags.
+    */
+    bool isDevKernText() const
+    {
+        return SkToBool(this->getFlags() & kDevKernText_Flag);
+    }
+
+    /** Helper for setFlags(), setting or clearing the kKernText_Flag bit
+        @param kernText true to set the kKernText_Flag bit in the paint's
+                            flags, false to clear it.
+    */
+    void setDevKernText(bool devKernText);
+
+    bool isFilterBitmap() const
+    {
+        return SkToBool(this->getFlags() & kFilterBitmap_Flag);
+    }
+    
+    void setFilterBitmap(bool filterBitmap);
+
+    /** Styles apply to rect, oval, path, and text.
+        Bitmaps are always drawn in "fill", and lines are always drawn in
+        "stroke".
+    */
+    enum Style {
+        kFill_Style,            //!< fill with the paint's color
+        kStroke_Style,          //!< stroke with the paint's color
+        kStrokeAndFill_Style,   //!< fill and stroke with the paint's color
+
+        kStyleCount,
+    };
+
+    /** Return the paint's style, used for controlling how primitives'
+        geometries are interpreted (except for drawBitmap, which always assumes
+        kFill_Style).
+        @return the paint's Style
+    */
+    Style getStyle() const { return (Style)fStyle; }
+
+    /** Set the paint's style, used for controlling how primitives'
+        geometries are interpreted (except for drawBitmap, which always assumes
+        Fill).
+        @param style    The new style to set in the paint
+    */
+    void setStyle(Style style);
+
+    /** Return the paint's color. Note that the color is a 32bit value
+        containing alpha as well as r,g,b. This 32bit value is not
+        premultiplied, meaning that its alpha can be any value, regardless of
+        the values of r,g,b.
+        @return the paint's color (and alpha).
+    */
+    SkColor getColor() const { return fColor; }
+
+    /** Set the paint's color. Note that the color is a 32bit value containing
+        alpha as well as r,g,b. This 32bit value is not premultiplied, meaning
+        that its alpha can be any value, regardless of the values of r,g,b.
+        @param color    The new color (including alpha) to set in the paint.
+    */
+    void setColor(SkColor color);
+
+    /** Helper to getColor() that just returns the color's alpha value.
+        @return the alpha component of the paint's color.
+        */
+    uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }
+    
+    /** Helper to setColor(), that only assigns the color's alpha value,
+        leaving its r,g,b values unchanged.
+        @param a    set the alpha component (0..255) of the paint's color.
+    */
+    void setAlpha(U8CPU a);
+
+    /** Helper to setColor(), that takes a,r,g,b and constructs the color value
+        using SkColorSetARGB()
+        @param a    The new alpha component (0..255) of the paint's color.
+        @param r    The new red component (0..255) of the paint's color.
+        @param g    The new green component (0..255) of the paint's color.
+        @param b    The new blue component (0..255) of the paint's color.
+    */
+    void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+    /** Return the width for stroking. 
+        <p />
+        A value of 0 strokes in hairline mode.
+        Hairlines always draw 1-pixel wide, regardless of the matrix.
+        @return the paint's stroke width, used whenever the paint's style is
+                Stroke or StrokeAndFill.
+    */
+    SkScalar getStrokeWidth() const { return fWidth; }
+
+    /** Set the width for stroking. 
+        Pass 0 to stroke in hairline mode.
+        Hairlines always draw 1-pixel wide, regardless of the matrix.
+        @param width set the paint's stroke width, used whenever the paint's
+                     style is Stroke or StrokeAndFill.
+    */
+    void setStrokeWidth(SkScalar width);
+
+    /** Return the paint's stroke miter value. This is used to control the
+        behavior of miter joins when the joins angle is sharp.
+        @return the paint's miter limit, used whenever the paint's style is
+                Stroke or StrokeAndFill.
+    */
+    SkScalar getStrokeMiter() const { return fMiterLimit; }
+
+    /** Set the paint's stroke miter value. This is used to control the
+        behavior of miter joins when the joins angle is sharp. This value must
+        be >= 0.
+        @param miter    set the miter limit on the paint, used whenever the
+                        paint's style is Stroke or StrokeAndFill.
+    */
+    void setStrokeMiter(SkScalar miter);
+
+    /** Cap enum specifies the settings for the paint's strokecap. This is the
+        treatment that is applied to the beginning and end of each non-closed
+        contour (e.g. lines).
+    */
+    enum Cap {
+        kButt_Cap,      //!< begin/end contours with no extension
+        kRound_Cap,     //!< begin/end contours with a semi-circle extension
+        kSquare_Cap,    //!< begin/end contours with a half square extension
+
+        kCapCount,
+        kDefault_Cap = kButt_Cap
+    };
+
+    /** Join enum specifies the settings for the paint's strokejoin. This is
+        the treatment that is applied to corners in paths and rectangles.
+    */
+    enum Join {
+        kMiter_Join,    //!< connect path segments with a sharp join
+        kRound_Join,    //!< connect path segments with a round join
+        kBevel_Join,    //!< connect path segments with a flat bevel join
+
+        kJoinCount,
+        kDefault_Join = kMiter_Join
+    };
+
+    /** Return the paint's stroke cap type, controlling how the start and end
+        of stroked lines and paths are treated.
+        @return the line cap style for the paint, used whenever the paint's
+                style is Stroke or StrokeAndFill.
+    */
+    Cap getStrokeCap() const { return (Cap)fCapType; }
+
+    /** Set the paint's stroke cap type.
+        @param cap  set the paint's line cap style, used whenever the paint's
+                    style is Stroke or StrokeAndFill.
+    */
+    void setStrokeCap(Cap cap);
+
+    /** Return the paint's stroke join type.
+        @return the paint's line join style, used whenever the paint's style is
+                Stroke or StrokeAndFill.
+    */
+    Join getStrokeJoin() const { return (Join)fJoinType; }
+
+    /** Set the paint's stroke join type.
+        @param join set the paint's line join style, used whenever the paint's
+                    style is Stroke or StrokeAndFill.
+    */
+    void setStrokeJoin(Join join);
+
+    /** Applies any/all effects (patheffect, stroking) to src, returning the
+        result in dst. The result is that drawing src with this paint will be
+        the same as drawing dst with a default paint (at least from the
+        geometric perspective).
+        @param src  input path
+        @param dst  output path (may be the same as src)
+        @return     true if the path should be filled, or false if it should be
+                    drawn with a hairline (width == 0)
+    */
+    bool getFillPath(const SkPath& src, SkPath* dst) const;
+
+    /** Returns true if the current paint settings allow for fast computation of
+        bounds (i.e. there is nothing complex like a patheffect that would make
+        the bounds computation expensive.
+    */
+    bool canComputeFastBounds() const;
+    
+    /** Only call this if canComputeFastBounds() returned true. This takes a
+        raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
+        effects in the paint (e.g. stroking). If needed, it uses the storage
+        rect parameter. It returns the adjusted bounds that can then be used
+        for quickReject tests.
+     
+        The returned rect will either be orig or storage, thus the caller
+        should not rely on storage being set to the result, but should always
+        use the retured value. It is legal for orig and storage to be the same
+        rect.
+        
+        e.g.
+        if (paint.canComputeFastBounds()) {
+            SkRect r, storage;
+            path.computeBounds(&r, SkPath::kFast_BoundsType);
+            const SkRect& fastR = paint.computeFastBounds(r, &storage);
+            if (canvas->quickReject(fastR, ...)) {
+                // don't draw the path
+            }
+        }
+    */
+    const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const;
+
+    /** Get the paint's shader object.
+        <p />
+      The shader's reference count is not affected.
+        @return the paint's shader (or NULL)
+    */
+    SkShader* getShader() const { return fShader; }
+
+    /** Set or clear the shader object.
+        <p />
+        Pass NULL to clear any previous shader.
+        As a convenience, the parameter passed is also returned.
+        If a previous shader exists, its reference count is decremented.
+        If shader is not NULL, its reference count is incremented.
+        @param shader   May be NULL. The shader to be installed in the paint
+        @return         shader
+    */
+    SkShader* setShader(SkShader* shader);
+    
+    /** Get the paint's colorfilter. If there is a colorfilter, its reference
+        count is not changed.
+        @return the paint's colorfilter (or NULL)
+    */
+    SkColorFilter* getColorFilter() const { return fColorFilter; }
+
+    /** Set or clear the paint's colorfilter, returning the parameter.
+        <p />
+        If the paint already has a filter, its reference count is decremented.
+        If filter is not NULL, its reference count is incremented.
+        @param filter   May be NULL. The filter to be installed in the paint
+        @return         filter
+    */
+    SkColorFilter* setColorFilter(SkColorFilter* filter);
+
+    /** Get the paint's xfermode object.
+        <p />
+      The xfermode's reference count is not affected.
+        @return the paint's xfermode (or NULL)
+    */
+    SkXfermode* getXfermode() const { return fXfermode; }
+
+    /** Set or clear the xfermode object.
+        <p />
+        Pass NULL to clear any previous xfermode.
+        As a convenience, the parameter passed is also returned.
+        If a previous xfermode exists, its reference count is decremented.
+        If xfermode is not NULL, its reference count is incremented.
+        @param xfermode May be NULL. The new xfermode to be installed in the
+                        paint
+        @return         xfermode
+    */
+    SkXfermode* setXfermode(SkXfermode* xfermode);
+    
+    /** Helper for setXfermode, passing the corresponding xfermode object
+        returned from the PorterDuff factory.
+        @param mode The porter-duff mode used to create an xfermode for the
+                    paint.
+        @return     the resulting xfermode object (or NULL if the mode is
+                    SrcOver)
+    */
+    SkXfermode* setPorterDuffXfermode(SkPorterDuff::Mode mode);
+
+    /** Get the paint's patheffect object.
+        <p />
+      The patheffect reference count is not affected.
+        @return the paint's patheffect (or NULL)
+    */
+    SkPathEffect* getPathEffect() const { return fPathEffect; }
+
+    /** Set or clear the patheffect object.
+        <p />
+        Pass NULL to clear any previous patheffect.
+        As a convenience, the parameter passed is also returned.
+        If a previous patheffect exists, its reference count is decremented.
+        If patheffect is not NULL, its reference count is incremented.
+        @param effect   May be NULL. The new patheffect to be installed in the
+                        paint
+        @return         effect
+    */
+    SkPathEffect* setPathEffect(SkPathEffect* effect);
+
+    /** Get the paint's maskfilter object.
+        <p />
+      The maskfilter reference count is not affected.
+        @return the paint's maskfilter (or NULL)
+    */
+    SkMaskFilter* getMaskFilter() const { return fMaskFilter; }
+
+    /** Set or clear the maskfilter object.
+        <p />
+        Pass NULL to clear any previous maskfilter.
+        As a convenience, the parameter passed is also returned.
+        If a previous maskfilter exists, its reference count is decremented.
+        If maskfilter is not NULL, its reference count is incremented.
+        @param maskfilter   May be NULL. The new maskfilter to be installed in
+                            the paint
+        @return             maskfilter
+    */
+    SkMaskFilter* setMaskFilter(SkMaskFilter* maskfilter);
+
+    // These attributes are for text/fonts
+
+    /** Get the paint's typeface object.
+        <p />
+        The typeface object identifies which font to use when drawing or
+        measuring text. The typeface reference count is not affected.
+        @return the paint's typeface (or NULL)
+    */
+    SkTypeface* getTypeface() const { return fTypeface; }
+
+    /** Set or clear the typeface object.
+        <p />
+        Pass NULL to clear any previous typeface.
+        As a convenience, the parameter passed is also returned.
+        If a previous typeface exists, its reference count is decremented.
+        If typeface is not NULL, its reference count is incremented.
+        @param typeface May be NULL. The new typeface to be installed in the
+                        paint
+        @return         typeface
+    */
+    SkTypeface* setTypeface(SkTypeface* typeface);
+
+    /** Get the paint's rasterizer (or NULL).
+        <p />
+        The raster controls how paths/text are turned into alpha masks.
+        @return the paint's rasterizer (or NULL)
+    */
+    SkRasterizer* getRasterizer() const { return fRasterizer; }
+
+    /** Set or clear the rasterizer object.
+        <p />
+        Pass NULL to clear any previous rasterizer.
+        As a convenience, the parameter passed is also returned.
+        If a previous rasterizer exists in the paint, its reference count is
+        decremented. If rasterizer is not NULL, its reference count is
+        incremented.
+        @param rasterizer May be NULL. The new rasterizer to be installed in
+                          the paint.
+        @return           rasterizer
+    */
+    SkRasterizer* setRasterizer(SkRasterizer* rasterizer);
+
+    SkDrawLooper* getLooper() const { return fLooper; }
+    SkDrawLooper* setLooper(SkDrawLooper*);
+
+    enum Align {
+        kLeft_Align,
+        kCenter_Align,
+        kRight_Align,
+
+        kAlignCount
+    };
+    /** Return the paint's Align value for drawing text.
+        @return the paint's Align value for drawing text.
+    */
+    Align   getTextAlign() const { return (Align)fTextAlign; }
+    /** Set the paint's text alignment.
+        @param align set the paint's Align value for drawing text.
+    */
+    void    setTextAlign(Align align);
+
+    /** Return the paint's text size.
+        @return the paint's text size.
+    */
+    SkScalar getTextSize() const { return fTextSize; }
+
+    /** Set the paint's text size. This value must be > 0
+        @param textSize set the paint's text size.
+    */
+    void setTextSize(SkScalar textSize);
+
+    /** Return the paint's horizontal scale factor for text. The default value
+        is 1.0.
+        @return the paint's scale factor in X for drawing/measuring text
+    */
+    SkScalar getTextScaleX() const { return fTextScaleX; }
+
+    /** Set the paint's horizontal scale factor for text. The default value
+        is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
+        stretch the text narrower.
+        @param scaleX   set the paint's scale factor in X for drawing/measuring
+                        text.
+    */
+    void setTextScaleX(SkScalar scaleX);
+
+    /** Return the paint's horizontal skew factor for text. The default value
+        is 0.
+        @return the paint's skew factor in X for drawing text.
+    */
+    SkScalar getTextSkewX() const { return fTextSkewX; }
+
+    /** Set the paint's horizontal skew factor for text. The default value
+        is 0. For approximating oblique text, use values around -0.25.
+        @param skewX set the paint's skew factor in X for drawing text.
+    */
+    void setTextSkewX(SkScalar skewX);
+
+    /** Describes how to interpret the text parameters that are passed to paint
+        methods like measureText() and getTextWidths().
+    */
+    enum TextEncoding {
+        kUTF8_TextEncoding,     //!< the text parameters are UTF8
+        kUTF16_TextEncoding,    //!< the text parameters are UTF16
+        kGlyphID_TextEncoding   //!< the text parameters are glyph indices
+    };
+    
+    TextEncoding getTextEncoding() const
+    {
+        return (TextEncoding)fTextEncoding;
+    }
+
+    void setTextEncoding(TextEncoding encoding);
+
+    struct FontMetrics {
+        SkScalar    fTop;       //!< The greatest distance above the baseline for any glyph (will be <= 0)
+        SkScalar    fAscent;    //!< The recommended distance above the baseline (will be <= 0)
+        SkScalar    fDescent;   //!< The recommended distance below the baseline (will be >= 0)
+        SkScalar    fBottom;    //!< The greatest distance below the baseline for any glyph (will be >= 0)
+        SkScalar    fLeading;   //!< The recommended distance to add between lines of text (will be >= 0)
+    };
+    
+    /** Return the recommend spacing between lines (which will be
+        fDescent - fAscent + fLeading).
+        If metrics is not null, return in it the font metrics for the
+        typeface/pointsize/etc. currently set in the paint. 
+        @param metrics      If not null, returns the font metrics for the
+                            current typeface/pointsize/etc setting in this
+                            paint.
+        @param scale        If not 0, return width as if the canvas were scaled
+                            by this value
+        @param return the recommended spacing between lines
+    */
+    SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;
+    
+    /** Return the recommend line spacing. This will be
+        fDescent - fAscent + fLeading
+    */
+    SkScalar getFontSpacing() const { return this->getFontMetrics(NULL, 0); }
+
+    /** Convert the specified text into glyph IDs, returning the number of
+        glyphs ID written. If glyphs is NULL, it is ignore and only the count
+        is returned.
+    */
+    int textToGlyphs(const void* text, size_t byteLength,
+                     uint16_t glyphs[]) const;
+
+    /** Return the number of drawable units in the specified text buffer.
+        This looks at the current TextEncoding field of the paint. If you also
+        want to have the text converted into glyph IDs, call textToGlyphs
+        instead.
+    */
+    int countText(const void* text, size_t byteLength) const
+    {
+        return this->textToGlyphs(text, byteLength, NULL);
+    }
+
+    /** Return the width of the text.
+        @param text         The text to be measured
+        @param length       Number of bytes of text to measure
+        @param bounds       If not NULL, returns the bounds of the text,
+                            relative to (0, 0).
+        @param scale        If not 0, return width as if the canvas were scaled
+                            by this value
+        @return             The advance width of the text
+    */
+    SkScalar    measureText(const void* text, size_t length,
+                            SkRect* bounds, SkScalar scale = 0) const;
+
+    /** Return the width of the text.
+        @param text         Address of the text
+        @param length       Number of bytes of text to measure
+        @return The width of the text
+    */
+    SkScalar measureText(const void* text, size_t length) const
+    {
+        return this->measureText(text, length, NULL, 0);
+    }
+    
+    /** Specify the direction the text buffer should be processed in breakText()
+    */
+    enum TextBufferDirection {
+        /** When measuring text for breakText(), begin at the start of the text
+            buffer and proceed forward through the data. This is the default.
+        */
+        kForward_TextBufferDirection,
+        /** When measuring text for breakText(), begin at the end of the text
+            buffer and proceed backwards through the data.
+        */
+        kBackward_TextBufferDirection
+    };
+
+    /** Return the width of the text.
+        @param text     The text to be measured
+        @param length   Number of bytes of text to measure
+        @param maxWidth Maximum width. Only the subset of text whose accumulated
+                        widths are <= maxWidth are measured.
+        @param measuredWidth Optional. If non-null, this returns the actual
+                        width of the measured text.
+        @param tbd      Optional. The direction the text buffer should be
+                        traversed during measuring.
+        @return         The number of bytes of text that were measured. Will be
+                        <= length.
+    */
+    size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
+                      SkScalar* measuredWidth = NULL,
+                      TextBufferDirection tbd = kForward_TextBufferDirection)
+                      const;
+
+    /** Return the advance widths for the characters in the string.
+        @param text         the text
+        @param byteLength   number of bytes to of text
+        @param widths       If not null, returns the array of advance widths of
+                            the glyphs. If not NULL, must be at least a large
+                            as the number of unichars in the specified text.
+        @param bounds       If not null, returns the bounds for each of
+                            character, relative to (0, 0)
+        @return the number of unichars in the specified text.
+    */
+    int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
+                      SkRect bounds[] = NULL) const;
+
+    /** Return the path (outline) for the specified text.
+        Note: just like SkCanvas::drawText, this will respect the Align setting
+              in the paint.
+    */
+    void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
+                     SkPath* path) const;
+
+private:
+    SkTypeface*     fTypeface;
+    SkScalar        fTextSize;
+    SkScalar        fTextScaleX;
+    SkScalar        fTextSkewX;
+
+    SkPathEffect*   fPathEffect;
+    SkShader*       fShader;
+    SkXfermode*     fXfermode;
+    SkMaskFilter*   fMaskFilter;
+    SkColorFilter*  fColorFilter;
+    SkRasterizer*   fRasterizer;
+    SkDrawLooper*   fLooper;
+
+    SkColor         fColor;
+    SkScalar        fWidth;
+    SkScalar        fMiterLimit;
+    unsigned        fFlags : 9;
+    unsigned        fTextAlign : 2;
+    unsigned        fCapType : 2;
+    unsigned        fJoinType : 2;
+    unsigned        fStyle : 2;
+    unsigned        fTextEncoding : 2;  // 3 values
+
+    SkDrawCacheProc    getDrawCacheProc() const;
+    SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir,
+                                           bool needFullMetrics) const;
+
+    SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
+                          int* count, SkRect* bounds) const;
+
+    SkGlyphCache*   detachCache(const SkMatrix*) const;
+
+    void descriptorProc(const SkMatrix* deviceMatrix,
+                        void (*proc)(const SkDescriptor*, void*),
+                        void* context) const;
+        
+    enum {
+        kCanonicalTextSizeForPaths = 64
+    };
+    friend class SkCanvas;
+    friend class SkDraw;
+    friend class SkAutoGlyphCache;
+    friend class SkTextToPathIter;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "SkPathEffect.h"
+
+/** \class SkStrokePathEffect
+
+    SkStrokePathEffect simulates stroking inside a patheffect, allowing the
+    caller to have explicit control of when to stroke a path. Typically this is
+    used if the caller wants to stroke before another patheffect is applied
+    (using SkComposePathEffect or SkSumPathEffect).
+*/
+class SkStrokePathEffect : public SkPathEffect {
+public:
+    SkStrokePathEffect(const SkPaint&);
+    SkStrokePathEffect(SkScalar width, SkPaint::Style, SkPaint::Join,
+                       SkPaint::Cap, SkScalar miterLimit = -1);
+
+    // overrides
+    // This method is not exported to java.
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+    // overrides for SkFlattenable
+    // This method is not exported to java.
+    virtual void flatten(SkFlattenableWriteBuffer&);
+    // This method is not exported to java.
+    virtual Factory getFactory();
+
+private:
+    SkScalar    fWidth, fMiter;
+    uint8_t     fStyle, fJoin, fCap;
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+    SkStrokePathEffect(SkFlattenableReadBuffer&);
+
+    typedef SkPathEffect INHERITED;
+
+    // illegal
+    SkStrokePathEffect(const SkStrokePathEffect&);
+    SkStrokePathEffect& operator=(const SkStrokePathEffect&);
+};
+
+#endif
+
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
new file mode 100644
index 0000000..e2409ad
--- /dev/null
+++ b/include/core/SkPath.h
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPath_DEFINED
+#define SkPath_DEFINED
+
+#include "SkMatrix.h"
+#include "SkTDArray.h"
+
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+class SkAutoPathBoundsUpdate;
+class SkString;
+
+/** \class SkPath
+
+    The SkPath class encapsulates compound (multiple contour) geometric paths
+    consisting of straight line segments, quadratic curves, and cubic curves.
+*/
+class SkPath {
+public:
+    SkPath();
+    SkPath(const SkPath&);
+    ~SkPath();
+
+    SkPath& operator=(const SkPath&);
+
+    enum FillType {
+        /** Specifies that "inside" is computed by a non-zero sum of signed
+            edge crossings
+        */
+        kWinding_FillType,
+        /** Specifies that "inside" is computed by an odd number of edge
+            crossings
+        */
+        kEvenOdd_FillType,
+        /** Same as Winding, but draws outside of the path, rather than inside
+        */
+        kInverseWinding_FillType,
+        /** Same as EvenOdd, but draws outside of the path, rather than inside
+         */
+        kInverseEvenOdd_FillType
+    };
+
+    /** Return the path's fill type. This is used to define how "inside" is
+        computed. The default value is kWinding_FillType.
+
+        @return the path's fill type
+    */
+    FillType getFillType() const { return (FillType)fFillType; }
+
+    /** Set the path's fill type. This is used to define how "inside" is
+        computed. The default value is kWinding_FillType.
+     
+        @param ft The new fill type for this path
+    */
+    void setFillType(FillType ft) { fFillType = SkToU8(ft); }
+
+    /** Returns true if the filltype is one of the Inverse variants */
+    bool isInverseFillType() const { return (fFillType & 2) != 0; }
+
+    /** Toggle between inverse and normal filltypes. This reverse the return
+        value of isInverseFillType()
+    */
+    void toggleInverseFillType() { fFillType ^= 2; }
+
+    /** Clear any lines and curves from the path, making it empty. This frees up
+        internal storage associated with those segments.
+        This does NOT change the fill-type setting.
+    */
+    void reset();
+    
+    /** Similar to reset(), in that all lines and curves are removed from the
+        path. However, any internal storage for those lines/curves is retained,
+        making reuse of the path potentially faster.
+        This does NOT change the fill-type setting.
+    */
+    void rewind();
+
+    /** Returns true if the path is empty (contains no lines or curves)
+
+        @return true if the path is empty (contains no lines or curves)
+    */
+    bool isEmpty() const;
+
+    /** Returns true if the path specifies a rectangle. If so, and if rect is
+        not null, set rect to the bounds of the path. If the path does not
+        specify a rectangle, return false and ignore rect.
+     
+        @param rect If not null, returns the bounds of the path if it specifies
+                    a rectangle
+        @return true if the path specifies a rectangle
+    */
+    bool isRect(SkRect* rect) const;
+
+    /** Returns the number of points in the path. Up to max points are copied.
+     
+        @param points If not null, receives up to max points
+        @param max The maximum number of points to copy into points
+        @return the actual number of points in the path
+    */
+    int getPoints(SkPoint points[], int max) const;
+
+    //! Swap contents of this and other. Guaranteed not to throw
+    void swap(SkPath& other);
+
+    enum BoundsType {
+        /** compute the bounds of the path's control points, may be larger than
+            with kExact_BoundsType, but may be faster to compute
+        */
+        kFast_BoundsType,
+        /** compute the exact bounds of the path, may be smaller than with
+            kFast_BoundsType, but may be slower to compute
+        */
+        kExact_BoundsType
+    };
+
+    /** Compute the bounds of the path, and write the answer into bounds. If the
+        path contains 0 or 1 points, the bounds is set to (0,0,0,0)
+     
+        @param bounds   Returns the computed bounds of the path
+        @param btype    Specifies if the computed bounds should be exact
+                        (slower) or approximate (faster)
+    */
+    void computeBounds(SkRect* bounds, BoundsType btype) const;
+
+    /** Calling this will, if the internal cache of the bounds is out of date,
+        update it so that subsequent calls to computeBounds will be instanteous.
+        This also means that any copies or simple transformations of the path
+        will inherit the cached bounds.
+    */
+    void updateBoundsCache() const;
+
+    //  Construction methods
+
+    /** Hint to the path to prepare for adding more points. This can allow the
+        path to more efficiently grow its storage.
+    
+        @param extraPtCount The number of extra points the path should
+                            preallocate for.
+    */
+    void incReserve(unsigned extraPtCount);
+
+    /** Set the beginning of the next contour to the point (x,y).
+     
+        @param x    The x-coordinate of the start of a new contour
+        @param y    The y-coordinate of the start of a new contour
+    */
+    void moveTo(SkScalar x, SkScalar y);
+
+    /** Set the beginning of the next contour to the point
+     
+        @param p    The start of a new contour
+    */
+    void moveTo(const SkPoint& p) {
+        this->moveTo(p.fX, p.fY);
+    }
+
+    /** Set the beginning of the next contour relative to the last point on the
+        previous contour. If there is no previous contour, this is treated the
+        same as moveTo().
+     
+        @param dx   The amount to add to the x-coordinate of the end of the
+                    previous contour, to specify the start of a new contour
+        @param dy   The amount to add to the y-coordinate of the end of the
+                    previous contour, to specify the start of a new contour
+    */
+    void rMoveTo(SkScalar dx, SkScalar dy);
+
+    /** Add a line from the last point to the specified point (x,y). If no
+        moveTo() call has been made for this contour, the first point is
+        automatically set to (0,0).
+
+        @param x    The x-coordinate of the end of a line
+        @param y    The y-coordinate of the end of a line
+    */
+    void lineTo(SkScalar x, SkScalar y);
+
+    /** Add a line from the last point to the specified point. If no moveTo()
+        call has been made for this contour, the first point is automatically
+        set to (0,0).
+
+        @param p    The end of a line
+    */
+    void lineTo(const SkPoint& p) {
+        this->lineTo(p.fX, p.fY);
+    }
+
+    /** Same as lineTo, but the coordinates are considered relative to the last
+        point on this contour. If there is no previous point, then a moveTo(0,0)
+        is inserted automatically.
+     
+        @param dx   The amount to add to the x-coordinate of the previous point
+                    on this contour, to specify a line
+        @param dy   The amount to add to the y-coordinate of the previous point
+                    on this contour, to specify a line
+    */
+    void rLineTo(SkScalar dx, SkScalar dy);
+
+    /** Add a quadratic bezier from the last point, approaching control point
+        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
+        this contour, the first point is automatically set to (0,0).
+     
+        @param x1   The x-coordinate of the control point on a quadratic curve
+        @param y1   The y-coordinate of the control point on a quadratic curve
+        @param x2   The x-coordinate of the end point on a quadratic curve
+        @param y2   The y-coordinate of the end point on a quadratic curve
+    */
+    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
+
+    /** Add a quadratic bezier from the last point, approaching control point
+        p1, and ending at p2. If no moveTo() call has been made for this
+        contour, the first point is automatically set to (0,0).
+     
+        @param p1   The control point on a quadratic curve
+        @param p2   The end point on a quadratic curve
+    */
+    void quadTo(const SkPoint& p1, const SkPoint& p2) {
+        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
+    }
+
+    /** Same as quadTo, but the coordinates are considered relative to the last
+        point on this contour. If there is no previous point, then a moveTo(0,0)
+        is inserted automatically.
+
+        @param dx1   The amount to add to the x-coordinate of the last point on
+                this contour, to specify the control point of a quadratic curve
+        @param dy1   The amount to add to the y-coordinate of the last point on
+                this contour, to specify the control point of a quadratic curve
+        @param dx2   The amount to add to the x-coordinate of the last point on
+                     this contour, to specify the end point of a quadratic curve
+        @param dy2   The amount to add to the y-coordinate of the last point on
+                     this contour, to specify the end point of a quadratic curve
+    */
+    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
+
+    /** Add a cubic bezier from the last point, approaching control points
+        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
+        made for this contour, the first point is automatically set to (0,0).
+     
+        @param x1   The x-coordinate of the 1st control point on a cubic curve
+        @param y1   The y-coordinate of the 1st control point on a cubic curve
+        @param x2   The x-coordinate of the 2nd control point on a cubic curve
+        @param y2   The y-coordinate of the 2nd control point on a cubic curve
+        @param x3   The x-coordinate of the end point on a cubic curve
+        @param y3   The y-coordinate of the end point on a cubic curve
+    */
+    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                 SkScalar x3, SkScalar y3);
+
+    /** Add a cubic bezier from the last point, approaching control points p1
+        and p2, and ending at p3. If no moveTo() call has been made for this
+        contour, the first point is automatically set to (0,0).
+     
+        @param p1   The 1st control point on a cubic curve
+        @param p2   The 2nd control point on a cubic curve
+        @param p3   The end point on a cubic curve
+    */
+    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
+        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
+    }
+
+    /** Same as cubicTo, but the coordinates are considered relative to the
+        current point on this contour. If there is no previous point, then a
+        moveTo(0,0) is inserted automatically.
+     
+        @param dx1   The amount to add to the x-coordinate of the last point on
+                this contour, to specify the 1st control point of a cubic curve
+        @param dy1   The amount to add to the y-coordinate of the last point on
+                this contour, to specify the 1st control point of a cubic curve
+        @param dx2   The amount to add to the x-coordinate of the last point on
+                this contour, to specify the 2nd control point of a cubic curve
+        @param dy2   The amount to add to the y-coordinate of the last point on
+                this contour, to specify the 2nd control point of a cubic curve
+        @param dx3   The amount to add to the x-coordinate of the last point on
+                     this contour, to specify the end point of a cubic curve
+        @param dy3   The amount to add to the y-coordinate of the last point on
+                     this contour, to specify the end point of a cubic curve
+    */
+    void    rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                     SkScalar x3, SkScalar y3);
+
+    /** Append the specified arc to the path as a new contour. If the start of
+        the path is different from the path's current last point, then an
+        automatic lineTo() is added to connect the current contour to the start
+        of the arc. However, if the path is empty, then we call moveTo() with
+        the first point of the arc. The sweep angle is treated mod 360.
+     
+        @param oval The bounding oval defining the shape and size of the arc
+        @param startAngle Starting angle (in degrees) where the arc begins
+        @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
+                          treated mod 360.
+        @param forceMoveTo If true, always begin a new contour with the arc
+    */
+    void    arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+                  bool forceMoveTo);
+
+    /** Append a line and arc to the current path. This is the same as the
+        PostScript call "arct".
+    */
+    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+               SkScalar radius);
+
+    /** Append a line and arc to the current path. This is the same as the
+        PostScript call "arct".
+    */
+    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
+        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
+    }
+
+    /** Close the current contour. If the current point is not equal to the
+        first point of the contour, a line segment is automatically added.
+    */
+    void close();
+
+    enum Direction {
+        /** clockwise direction for adding closed contours */
+        kCW_Direction,
+        /** counter-clockwise direction for adding closed contours */
+        kCCW_Direction
+    };
+
+    /** Add a closed rectangle contour to the path
+        @param rect The rectangle to add as a closed contour to the path
+        @param dir  The direction to wind the rectangle's contour
+    */
+    void    addRect(const SkRect& rect, Direction dir = kCW_Direction);
+
+    /** Add a closed rectangle contour to the path
+
+        @param left     The left side of a rectangle to add as a closed contour
+                        to the path
+        @param top      The top of a rectangle to add as a closed contour to the
+                        path
+        @param right    The right side of a rectangle to add as a closed contour
+                        to the path
+        @param bottom   The bottom of a rectangle to add as a closed contour to
+                        the path
+        @param dir      The direction to wind the rectangle's contour
+    */
+    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
+                 Direction dir = kCW_Direction);
+
+    /** Add a closed oval contour to the path
+
+        @param oval The bounding oval to add as a closed contour to the path
+        @param dir  The direction to wind the oval's contour
+    */
+    void addOval(const SkRect& oval, Direction dir = kCW_Direction);
+
+    /** Add a closed circle contour to the path
+
+        @param x        The x-coordinate of the center of a circle to add as a
+                        closed contour to the path
+        @param y        The y-coordinate of the center of a circle to add as a
+                        closed contour to the path
+        @param radius   The radius of a circle to add as a closed contour to the
+                        path
+        @param dir      The direction to wind the circle's contour
+    */
+    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
+                   Direction dir = kCW_Direction);
+
+    /** Add the specified arc to the path as a new contour.
+     
+        @param oval The bounds of oval used to define the size of the arc
+        @param startAngle Starting angle (in degrees) where the arc begins
+        @param sweepAngle Sweep angle (in degrees) measured clockwise
+    */
+    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
+
+    /** Add a closed round-rectangle contour to the path
+        @param rect The bounds of a round-rectangle to add as a closed contour
+        @param rx   The x-radius of the rounded corners on the round-rectangle
+        @param ry   The y-radius of the rounded corners on the round-rectangle
+        @param dir  The direction to wind the round-rectangle's contour
+    */
+    void    addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+                         Direction dir = kCW_Direction);
+
+    /** Add a closed round-rectangle contour to the path. Each corner receives
+        two radius values [X, Y]. The corners are ordered top-left, top-right,
+        bottom-right, bottom-left.
+        @param rect The bounds of a round-rectangle to add as a closed contour
+        @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
+        @param dir  The direction to wind the round-rectangle's contour
+        */
+    void addRoundRect(const SkRect& rect, const SkScalar radii[],
+                      Direction dir = kCW_Direction);
+
+    /** Add a copy of src to the path, offset by (dx,dy)
+        @param src  The path to add as a new contour
+        @param dx   The amount to translate the path in X as it is added
+        @param dx   The amount to translate the path in Y as it is added
+    */
+    void    addPath(const SkPath& src, SkScalar dx, SkScalar dy);
+
+    /** Add a copy of src to the path
+    */
+    void addPath(const SkPath& src) {
+        SkMatrix m;
+        m.reset();
+        this->addPath(src, m);
+    }
+
+    /** Add a copy of src to the path, transformed by matrix
+        @param src  The path to add as a new contour
+    */
+    void addPath(const SkPath& src, const SkMatrix& matrix);
+
+    /** Offset the path by (dx,dy), returning true on success
+     
+        @param dx   The amount in the X direction to offset the entire path 
+        @param dy   The amount in the Y direction to offset the entire path 
+        @param dst  The translated path is written here
+    */
+    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
+
+    /** Offset the path by (dx,dy), returning true on success
+     
+        @param dx   The amount in the X direction to offset the entire path 
+        @param dy   The amount in the Y direction to offset the entire path 
+    */
+    void offset(SkScalar dx, SkScalar dy) {
+        this->offset(dx, dy, this);
+    }
+
+    /** Transform the points in this path by matrix, and write the answer into
+        dst.
+     
+        @param matrix   The matrix to apply to the path
+        @param dst      The transformed path is written here
+    */
+    void transform(const SkMatrix& matrix, SkPath* dst) const;
+
+    /** Transform the points in this path by matrix
+
+        @param matrix The matrix to apply to the path
+    */
+    void transform(const SkMatrix& matrix) {
+        this->transform(matrix, this);
+    }
+
+    /** Return the last point on the path. If no points have been added, (0,0)
+        is returned.
+     
+        @param lastPt   The last point on the path is returned here
+    */
+    void getLastPt(SkPoint* lastPt) const;
+
+    /** Set the last point on the path. If no points have been added,
+        moveTo(x,y) is automatically called.
+     
+        @param x    The new x-coordinate for the last point
+        @param y    The new y-coordinate for the last point
+    */
+    void setLastPt(SkScalar x, SkScalar y);
+
+    /** Set the last point on the path. If no points have been added, moveTo(p)
+        is automatically called.
+
+        @param p    The new location for the last point
+    */
+    void setLastPt(const SkPoint& p) {
+        this->setLastPt(p.fX, p.fY);
+    }
+
+    enum Verb {
+        kMove_Verb,     //!< iter.next returns 1 point
+        kLine_Verb,     //!< iter.next returns 2 points
+        kQuad_Verb,     //!< iter.next returns 3 points
+        kCubic_Verb,    //!< iter.next returns 4 points
+        kClose_Verb,    //!< iter.next returns 1 point (the last point)
+        kDone_Verb      //!< iter.next returns 0 points
+    };
+
+    /** Iterate through all of the segments (lines, quadratics, cubics) of
+        each contours in a path.
+    */
+    class Iter {
+    public:
+                Iter();
+                Iter(const SkPath&, bool forceClose);
+
+        void setPath(const SkPath&, bool forceClose);
+
+        /** Return the next verb in this iteration of the path. When all
+            segments have been visited, return kDone_Verb.
+         
+            @param  pts The points representing the current verb and/or segment
+            @return The verb for the current segment
+        */
+        Verb next(SkPoint pts[4]);
+
+        /** If next() returns kLine_Verb, then this query returns true if the
+            line was the result of a close() command (i.e. the end point is the
+            initial moveto for this contour). If next() returned a different
+            verb, this returns an undefined value.
+         
+            @return If the last call to next() returned kLine_Verb, return true
+                    if it was the result of an explicit close command.
+        */
+        bool isCloseLine() const { return SkToBool(fCloseLine); }
+        
+        /** Returns true if the current contour is closed (has a kClose_Verb)
+            @return true if the current contour is closed (has a kClose_Verb)
+        */
+        bool isClosedContour() const;
+
+    private:
+        const SkPoint*  fPts;
+        const uint8_t*  fVerbs;
+        const uint8_t*  fVerbStop;
+        SkPoint         fMoveTo;
+        SkPoint         fLastPt;
+        SkBool8         fForceClose;
+        SkBool8         fNeedClose;
+        SkBool8         fNeedMoveTo;
+        SkBool8         fCloseLine;
+
+        bool cons_moveTo(SkPoint pts[1]);
+        Verb autoClose(SkPoint pts[2]);
+    };
+
+#ifdef SK_DEBUG
+  /** @cond UNIT_TEST */
+    void dump(bool forceClose, const char title[] = NULL) const;
+    static void UnitTest();
+  /** @endcond */
+#endif
+
+    void flatten(SkFlattenableWriteBuffer&) const;
+    void unflatten(SkFlattenableReadBuffer&);
+
+    /** Subdivide the path so that no segment is longer that dist.
+        If bendLines is true, then turn all line segments into curves.
+        If dst == null, then the original path itself is modified (not const!)
+    */
+    void subdivide(SkScalar dist, bool bendLines, SkPath* dst = NULL) const;
+
+    /** Return an SVG-compatible string of the path.
+    */
+    void toString(SkString*) const;
+
+    SkDEBUGCODE(void validate() const;)
+
+private:
+    SkTDArray<SkPoint>  fPts;
+    SkTDArray<uint8_t>  fVerbs;
+    mutable SkRect      fFastBounds;
+    mutable uint8_t     fFastBoundsIsDirty;
+    uint8_t             fFillType;
+
+    friend class Iter;
+    void cons_moveto();
+
+    friend class SkPathStroker;
+    /*  Append the first contour of path, ignoring path's initial point. If no
+        moveTo() call has been made for this contour, the first point is
+        automatically set to (0,0).
+    */
+    void pathTo(const SkPath& path);
+
+    /*  Append, in reverse order, the first contour of path, ignoring path's
+        last point. If no moveTo() call has been made for this contour, the
+        first point is automatically set to (0,0).
+    */
+    void reversePathTo(const SkPath&);
+
+    friend const SkPoint* sk_get_path_points(const SkPath&, int index);
+    friend class SkAutoPathBoundsUpdate;
+};
+
+#endif
+
diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h
new file mode 100644
index 0000000..f97adb7
--- /dev/null
+++ b/include/core/SkPathEffect.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPathEffect_DEFINED
+#define SkPathEffect_DEFINED
+
+#include "SkFlattenable.h"
+
+class SkPath;
+
+/** \class SkPathEffect
+
+    SkPathEffect is the base class for objects in the SkPaint that affect
+    the geometry of a drawing primitive before it is transformed by the
+    canvas' matrix and drawn.
+
+    Dashing is implemented as a subclass of SkPathEffect.
+*/
+class SkPathEffect : public SkFlattenable {
+public:
+    //  This method is not exported to java.
+    SkPathEffect() {}
+
+    /** Given a src path and a width value, return true if the patheffect
+        has produced a new path (dst) and a new width value. If false is returned,
+        ignore dst and width.
+        On input, width >= 0 means the src should be stroked
+        On output, width >= 0 means the dst should be stroked
+    */
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) = 0;
+
+private:
+    // illegal
+    SkPathEffect(const SkPathEffect&);
+    SkPathEffect& operator=(const SkPathEffect&);
+};
+
+/** \class SkPairPathEffect
+
+    Common baseclass for Compose and Sum. This subclass manages two pathEffects,
+    including flattening them. It does nothing in filterPath, and is only useful
+    for managing the lifetimes of its two arguments.
+*/
+class SkPairPathEffect : public SkPathEffect {
+public:
+    SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1);
+    virtual ~SkPairPathEffect();
+
+protected:
+    SkPairPathEffect(SkFlattenableReadBuffer&);
+    virtual void flatten(SkFlattenableWriteBuffer&);
+    // these are visible to our subclasses
+    SkPathEffect* fPE0, *fPE1;
+    
+private:
+    typedef SkPathEffect INHERITED;
+};
+
+/** \class SkComposePathEffect
+
+    This subclass of SkPathEffect composes its two arguments, to create
+    a compound pathEffect.
+*/
+class SkComposePathEffect : public SkPairPathEffect {
+public:
+    /** Construct a pathEffect whose effect is to apply first the inner pathEffect
+        and the the outer pathEffect (e.g. outer(inner(path)))
+        The reference counts for outer and inner are both incremented in the constructor,
+        and decremented in the destructor.
+    */
+    SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner)
+        : INHERITED(outer, inner) {}
+
+    // overrides
+    
+    //  This method is not exported to java.
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkComposePathEffect, (buffer));
+    }
+    SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+    // illegal
+    SkComposePathEffect(const SkComposePathEffect&);
+    SkComposePathEffect& operator=(const SkComposePathEffect&);
+    
+    typedef SkPairPathEffect INHERITED;
+};
+
+/** \class SkSumPathEffect
+
+    This subclass of SkPathEffect applies two pathEffects, one after the other.
+    Its filterPath() returns true if either of the effects succeeded.
+*/
+class SkSumPathEffect : public SkPairPathEffect {
+public:
+    /** Construct a pathEffect whose effect is to apply two effects, in sequence.
+        (e.g. first(path) + second(path))
+        The reference counts for first and second are both incremented in the constructor,
+        and decremented in the destructor.
+    */
+    SkSumPathEffect(SkPathEffect* first, SkPathEffect* second)
+        : INHERITED(first, second) {}
+
+    // overrides
+    //  This method is not exported to java.
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)  {
+        return SkNEW_ARGS(SkSumPathEffect, (buffer));
+    }
+    SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+    // illegal
+    SkSumPathEffect(const SkSumPathEffect&);
+    SkSumPathEffect& operator=(const SkSumPathEffect&);
+
+    typedef SkPairPathEffect INHERITED;
+};
+
+#endif
+
diff --git a/include/core/SkPathMeasure.h b/include/core/SkPathMeasure.h
new file mode 100644
index 0000000..5ab97ca
--- /dev/null
+++ b/include/core/SkPathMeasure.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPathMeasure_DEFINED
+#define SkPathMeasure_DEFINED
+
+#include "SkPath.h"
+#include "SkTDArray.h"
+
+class SkPathMeasure : SkNoncopyable {
+public:
+    SkPathMeasure();
+    /** Initialize the pathmeasure with the specified path. The path must remain valid
+        for the lifetime of the measure object, or until setPath() is called with
+        a different path (or null), since the measure object keeps a pointer to the
+        path object (does not copy its data).
+    */
+    SkPathMeasure(const SkPath& path, bool forceClosed);
+    ~SkPathMeasure();
+
+    /** Reset the pathmeasure with the specified path. The path must remain valid
+        for the lifetime of the measure object, or until setPath() is called with
+        a different path (or null), since the measure object keeps a pointer to the
+        path object (does not copy its data).
+    */
+    void    setPath(const SkPath*, bool forceClosed);
+
+    /** Return the total length of the current contour, or 0 if no path
+        is associated (e.g. resetPath(null))
+    */
+    SkScalar getLength();
+
+    /** Pins distance to 0 <= distance <= getLength(), and then computes
+        the corresponding position and tangent.
+        Returns false if there is no path, or a zero-length path was specified, in which case
+        position and tangent are unchanged.
+    */
+    bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent);
+
+    enum MatrixFlags {
+        kGetPosition_MatrixFlag     = 0x01,
+        kGetTangent_MatrixFlag      = 0x02,
+        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
+    };
+    /** Pins distance to 0 <= distance <= getLength(), and then computes
+        the corresponding matrix (by calling getPosTan).
+        Returns false if there is no path, or a zero-length path was specified, in which case
+        matrix is unchanged.
+    */
+    bool getMatrix(SkScalar distance, SkMatrix* matrix, MatrixFlags flags = kGetPosAndTan_MatrixFlag);
+    /** Given a start and stop distance, return in dst the intervening segment(s).
+        If the segment is zero-length, return false, else return true.
+        startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD
+        then return false (and leave dst untouched).
+        Begin the segment with a moveTo if startWithMoveTo is true
+    */
+    bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);
+
+    /** Return true if the current contour is closed()
+    */
+    bool isClosed();
+
+    /** Move to the next contour in the path. Return true if one exists, or false if
+        we're done with the path.
+    */
+    bool nextContour();
+
+#ifdef SK_DEBUG
+    void    dump();
+    static void UnitTest();
+#endif
+
+private:
+    SkPath::Iter    fIter;
+    const SkPath*   fPath;
+    SkScalar        fLength;            // relative to the current contour
+    int             fFirstPtIndex;      // relative to the current contour
+    bool            fIsClosed;          // relative to the current contour
+    bool            fForceClosed;
+
+    struct Segment {
+        SkScalar    fDistance;  // total distance up to this point
+        unsigned    fPtIndex : 15;
+        unsigned    fTValue : 15;
+        unsigned    fType : 2;
+
+        SkScalar getScalarT() const;
+    };
+    SkTDArray<Segment>  fSegments;
+
+    static const Segment* NextSegment(const Segment*);
+
+    void     buildSegments();
+    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
+                                int mint, int maxt, int ptIndex);
+    SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
+                                int mint, int maxt, int ptIndex);
+    const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
+};
+
+#endif
+
diff --git a/include/core/SkPerspIter.h b/include/core/SkPerspIter.h
new file mode 100644
index 0000000..81ce7c8
--- /dev/null
+++ b/include/core/SkPerspIter.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPerspIter_DEFINED
+#define SkPerspIter_DEFINED
+
+#include "SkMatrix.h"
+
+class SkPerspIter {
+public:
+    /** Iterate a line through the matrix [x,y] ... [x+count-1, y].
+        @param m    The matrix we will be iterating a line through
+        @param x    The initial X coordinate to be mapped through the matrix
+        @param y    The initial Y coordinate to be mapped through the matrix
+        @param count The number of points (x,y) (x+1,y) (x+2,y) ... we will eventually map
+    */
+    SkPerspIter(const SkMatrix& m, SkScalar x, SkScalar y, int count);
+    
+    /** Return the buffer of [x,y] fixed point values we will be filling.
+        This always returns the same value, so it can be saved across calls to
+        next().
+    */
+    const SkFixed* getXY() const { return fStorage; }
+
+    /** Return the number of [x,y] pairs that have been filled in the getXY() buffer.
+        When this returns 0, the iterator is finished.
+    */
+    int next();
+    
+private:
+    enum {
+        kShift  = 4,
+        kCount  = (1 << kShift)
+    };
+    const SkMatrix& fMatrix;
+    SkFixed         fStorage[kCount * 2];
+    SkFixed         fX, fY;
+    SkScalar        fSX, fSY;
+    int             fCount;
+};
+
+#endif
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
new file mode 100644
index 0000000..fa614c9
--- /dev/null
+++ b/include/core/SkPicture.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPicture_DEFINED
+#define SkPicture_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkCanvas;
+class SkPicturePlayback;
+class SkPictureRecord;
+class SkStream;
+class SkWStream;
+
+/** \class SkPicture
+
+    The SkPicture class records the drawing commands made to a canvas, to
+    be played back at a later time.
+*/
+class SkPicture : public SkRefCnt {
+public:
+    /** The constructor prepares the picture to record.
+        @param width the width of the virtual device the picture records.
+        @param height the height of the virtual device the picture records.
+    */
+    SkPicture();
+    /** Make a copy of the contents of src. If src records more drawing after
+        this call, those elements will not appear in this picture.
+    */
+    SkPicture(const SkPicture& src);
+    explicit SkPicture(SkStream*);
+    virtual ~SkPicture();
+    
+    /**
+     *  Swap the contents of the two pictures. Guaranteed to succeed.
+     */
+    void swap(SkPicture& other);
+    
+    /** Returns the canvas that records the drawing commands.
+        @return the picture canvas.
+    */
+    SkCanvas* beginRecording(int width, int height);
+    /** Returns the recording canvas if one is active, or NULL if recording is
+        not active. This does not alter the refcnt on the canvas (if present).
+    */
+    SkCanvas* getRecordingCanvas() const;
+    /** Signal that the caller is done recording. This invalidates the canvas
+        returned by beginRecording/getRecordingCanvas, and prepares the picture
+        for drawing. Note: this happens implicitly the first time the picture
+        is drawn.
+    */
+    void endRecording();
+    
+    /** Replays the drawing commands on the specified canvas. This internally
+        calls endRecording() if that has not already been called.
+        @param surface the canvas receiving the drawing commands.
+    */
+    void draw(SkCanvas* surface);
+    
+    /** Return the width of the picture's recording canvas. This
+        value reflects what was passed to setSize(), and does not necessarily
+        reflect the bounds of what has been recorded into the picture.
+        @return the width of the picture's recording canvas
+    */
+    int width() const { return fWidth; }
+
+    /** Return the height of the picture's recording canvas. This
+        value reflects what was passed to setSize(), and does not necessarily
+        reflect the bounds of what has been recorded into the picture.
+        @return the height of the picture's recording canvas
+    */
+    int height() const { return fHeight; }
+
+    void serialize(SkWStream*) const;
+
+    /** Signals that the caller is prematurely done replaying the drawing
+        commands. This can be called from a canvas virtual while the picture
+        is drawing. Has no effect if the picture is not drawing. 
+    */
+    void abortPlayback();
+    
+private:
+    int fWidth, fHeight;
+    SkPictureRecord* fRecord;
+    SkPicturePlayback* fPlayback;
+
+    friend class SkFlatPicture;
+    friend class SkPicturePlayback;
+};
+
+class SkAutoPictureRecord : SkNoncopyable {
+public:
+    SkAutoPictureRecord(SkPicture* pict, int width, int height) {
+        fPicture = pict;
+        fCanvas = pict->beginRecording(width, height);
+    }
+    ~SkAutoPictureRecord() {
+        fPicture->endRecording();
+    }
+    
+    /** Return the canvas to draw into for recording into the picture.
+    */
+    SkCanvas* getRecordingCanvas() const { return fCanvas; }
+    
+private:
+    SkPicture*  fPicture;
+    SkCanvas*   fCanvas;
+};
+
+
+#endif
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
new file mode 100644
index 0000000..82e5ca7
--- /dev/null
+++ b/include/core/SkPixelRef.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPixelRef_DEFINED
+#define SkPixelRef_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkString.h"
+
+class SkColorTable;
+class SkMutex;
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+
+/** \class SkPixelRef
+
+    This class is the smart container for pixel memory, and is used with
+    SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
+    access the actual pixel memory by calling lockPixels/unlockPixels.
+
+    This class can be shared/accessed between multiple threads.
+*/
+class SkPixelRef : public SkRefCnt {
+public:
+    explicit SkPixelRef(SkMutex* mutex = NULL);
+    
+    /** Return the pixel memory returned from lockPixels, or null if the
+        lockCount is 0.
+    */
+    void* pixels() const { return fPixels; }
+
+    /** Return the current colorTable (if any) if pixels are locked, or null.
+    */
+    SkColorTable* colorTable() const { return fColorTable; }
+
+    /** Return the current lockcount (defaults to 0)
+    */
+    int getLockCount() const { return fLockCount; }
+
+    /** Call to access the pixel memory, which is returned. Balance with a call
+        to unlockPixels().
+    */
+    void lockPixels();
+    /** Call to balanace a previous call to lockPixels(). Returns the pixels
+        (or null) after the unlock. NOTE: lock calls can be nested, but the
+        matching number of unlock calls must be made in order to free the
+        memory (if the subclass implements caching/deferred-decoding.)
+    */
+    void unlockPixels();
+    
+    /** Returns a non-zero, unique value corresponding to the pixels in this
+        pixelref. Each time the pixels are changed (and notifyPixelsChanged is
+        called), a different generation ID will be returned.
+    */
+    uint32_t getGenerationID() const;
+    
+    /** Call this if you have changed the contents of the pixels. This will in-
+        turn cause a different generation ID value to be returned from
+        getGenerationID().
+    */
+    void notifyPixelsChanged();
+
+    /** Returns true if this pixelref is marked as immutable, meaning that the
+        contents of its pixels will not change for the lifetime of the pixelref.
+    */
+    bool isImmutable() const { return fIsImmutable; }
+    
+    /** Marks this pixelref is immutable, meaning that the contents of its
+        pixels will not change for the lifetime of the pixelref. This state can
+        be set on a pixelref, but it cannot be cleared once it is set.
+    */
+    void setImmutable();
+
+    /** Return the optional URI string associated with this pixelref. May be
+        null.
+    */
+    const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
+
+    /** Copy a URI string to this pixelref, or clear the URI if the uri is null
+     */
+    void setURI(const char uri[]) {
+        fURI.set(uri);
+    }
+    
+    /** Copy a URI string to this pixelref
+     */
+    void setURI(const char uri[], size_t len) {
+        fURI.set(uri, len);
+    }
+    
+    /** Assign a URI string to this pixelref.
+    */
+    void setURI(const SkString& uri) { fURI = uri; }
+
+    // serialization
+
+    typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&);
+
+    virtual Factory getFactory() const { return NULL; }
+    virtual void flatten(SkFlattenableWriteBuffer&) const;
+
+    static Factory NameToFactory(const char name[]);
+    static const char* FactoryToName(Factory);
+    static void Register(const char name[], Factory);
+    
+    class Registrar {
+    public:
+        Registrar(const char name[], Factory factory) {
+            SkPixelRef::Register(name, factory);
+        }
+    };
+
+protected:
+    /** Called when the lockCount goes from 0 to 1. The caller will have already
+        acquire a mutex for thread safety, so this method need not do that.
+    */
+    virtual void* onLockPixels(SkColorTable**) = 0;
+    /** Called when the lock count goes from 1 to 0. The caller will have
+        already acquire a mutex for thread safety, so this method need not do
+        that.
+    */
+    virtual void onUnlockPixels() = 0;
+
+    /** Return the mutex associated with this pixelref. This value is assigned
+        in the constructor, and cannot change during the lifetime of the object.
+    */
+    SkMutex* mutex() const { return fMutex; }
+
+    SkPixelRef(SkFlattenableReadBuffer&, SkMutex*);
+
+private:
+    SkMutex*        fMutex; // must remain in scope for the life of this object
+    void*           fPixels;
+    SkColorTable*   fColorTable;    // we do not track ownership, subclass does
+    int             fLockCount;
+    
+    mutable uint32_t fGenerationID;
+    
+    SkString    fURI;
+
+    // can go from false to true, but never from true to false
+    bool    fIsImmutable;
+};
+
+#endif
diff --git a/include/core/SkPoint.h b/include/core/SkPoint.h
new file mode 100644
index 0000000..f038afb
--- /dev/null
+++ b/include/core/SkPoint.h
@@ -0,0 +1,288 @@
+/*
+ * 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 SkPoint_DEFINED
+#define SkPoint_DEFINED
+
+#include "SkMath.h"
+#include "SkScalar.h"
+
+/** \struct SkIPoint
+
+    SkIPoint holds two 32 bit integer coordinates
+*/
+struct SkIPoint {
+    int32_t fX, fY;
+
+    /** Set the x and y values of the point. */
+    void set(int32_t x, int32_t y) { fX = x; fY = y; }
+
+    /** Rotate the point clockwise, writing the new point into dst
+        It is legal for dst == this
+    */
+    void rotateCW(SkIPoint* dst) const;
+
+    /** Rotate the point clockwise, writing the new point back into the point
+    */
+
+    void rotateCW() { this->rotateCW(this); }
+
+    /** Rotate the point counter-clockwise, writing the new point into dst.
+        It is legal for dst == this
+    */
+    void rotateCCW(SkIPoint* dst) const;
+
+    /** Rotate the point counter-clockwise, writing the new point back into
+        the point
+    */
+    void rotateCCW() { this->rotateCCW(this); }
+    
+    /** Negate the X and Y coordinates of the point.
+    */
+    void negate() { fX = -fX; fY = -fY; }
+    
+    /** Return a new point whose X and Y coordinates are the negative of the
+        original point's
+    */
+    SkIPoint operator-() const {
+        SkIPoint neg;
+        neg.fX = -fX;
+        neg.fY = -fY;
+        return neg;
+    }
+
+    /** Add v's coordinates to this point's */
+    void operator+=(const SkIPoint& v) {
+        fX += v.fX;
+        fY += v.fY;
+    }
+    
+    /** Subtract v's coordinates from this point's */
+    void operator-=(const SkIPoint& v) {
+        fX -= v.fX;
+        fY -= v.fY;
+    }
+
+    /** Returns true if the point's coordinates equal (x,y) */
+    bool equals(int32_t x, int32_t y) const {
+        return fX == x && fY == y;
+    }
+
+    friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
+        return a.fX == b.fX && a.fY == b.fY;
+    }
+    
+    friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
+        return a.fX != b.fX || a.fY != b.fY;
+    }
+
+    /** Returns a new point whose coordinates are the difference between
+        a and b (i.e. a - b)
+    */
+    friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
+        SkIPoint v;
+        v.set(a.fX - b.fX, a.fY - b.fY);
+        return v;
+    }
+
+    /** Returns a new point whose coordinates are the sum of a and b (a + b)
+    */
+    friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
+        SkIPoint v;
+        v.set(a.fX + b.fX, a.fY + b.fY);
+        return v;
+    }
+    
+    /** Returns the dot product of a and b, treating them as 2D vectors
+    */
+    static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
+        return a.fX * b.fX + a.fY * b.fY;
+    }
+
+    /** Returns the cross product of a and b, treating them as 2D vectors
+    */
+    static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
+        return a.fX * b.fY - a.fY * b.fX;
+    }
+};
+
+struct SkPoint {
+    SkScalar    fX, fY;
+
+    /** Set the point's X and Y coordinates */
+    void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
+    
+    /** Set the point's X and Y coordinates by automatically promoting (x,y) to
+        SkScalar values.
+    */
+    void iset(int32_t x, int32_t y) {
+        fX = SkIntToScalar(x);
+        fY = SkIntToScalar(y);
+    }
+    
+    /** Set the point's X and Y coordinates by automatically promoting p's
+        coordinates to SkScalar values.
+    */
+    void iset(const SkIPoint& p) {
+        fX = SkIntToScalar(p.fX);
+        fY = SkIntToScalar(p.fY);
+    }
+
+    /** Return the euclidian distance from (0,0) to the point
+    */
+    SkScalar length() const { return SkPoint::Length(fX, fY); }
+
+    /** Set the point (vector) to be unit-length in the same direction as it
+        currently is, and return its old length. If the old length is
+        degenerately small (nearly zero), do nothing and return false, otherwise
+        return true.
+    */
+    bool normalize();
+    
+    /** Set the point (vector) to be unit-length in the same direction as the
+        x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
+        then return false and do nothing, otherwise return true.
+    */
+    bool setNormalize(SkScalar x, SkScalar y);
+    
+    /** Scale the point (vector) to have the specified length, and return that
+        length. If the original length is degenerately small (nearly zero),
+        do nothing and return false, otherwise return true.
+    */
+    bool setLength(SkScalar length);
+    
+    /** Set the point (vector) to have the specified length in the same
+     direction as (x,y). If the vector (x,y) has a degenerate length
+     (i.e. nearly 0) then return false and do nothing, otherwise return true.
+    */
+    bool setLength(SkScalar x, SkScalar y, SkScalar length);
+
+    /** Scale the point's coordinates by scale, writing the answer into dst.
+        It is legal for dst == this.
+    */
+    void scale(SkScalar scale, SkPoint* dst) const;
+    
+    /** Scale the point's coordinates by scale, writing the answer back into
+        the point.
+    */
+    void scale(SkScalar scale) { this->scale(scale, this); }
+
+    /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
+        It is legal for dst == this.
+    */
+    void rotateCW(SkPoint* dst) const;
+    
+    /** Rotate the point clockwise by 90 degrees, writing the answer back into
+        the point.
+    */
+    void rotateCW() { this->rotateCW(this); }
+    
+    /** Rotate the point counter-clockwise by 90 degrees, writing the answer
+        into dst. It is legal for dst == this.
+    */
+    void rotateCCW(SkPoint* dst) const;
+    
+    /** Rotate the point counter-clockwise by 90 degrees, writing the answer
+        back into the point.
+    */
+    void rotateCCW() { this->rotateCCW(this); }
+    
+    /** Negate the point's coordinates
+    */
+    void negate() {
+        fX = -fX;
+        fY = -fY;
+    }
+    
+    /** Returns a new point whose coordinates are the negative of the point's
+    */
+    SkPoint operator-() const {
+        SkPoint neg;
+        neg.fX = -fX;
+        neg.fY = -fY;
+        return neg;
+    }
+
+    /** Add v's coordinates to the point's
+    */
+    void operator+=(const SkPoint& v) {
+        fX += v.fX;
+        fY += v.fY;
+    }
+    
+    /** Subtract v's coordinates from the point's
+    */
+    void operator-=(const SkPoint& v) {
+        fX -= v.fX;
+        fY -= v.fY;
+    }
+
+    /** Returns true if the point's coordinates equal (x,y)
+    */
+    bool equals(SkScalar x, SkScalar y) const { return fX == x && fY == y; }
+
+    friend bool operator==(const SkPoint& a, const SkPoint& b) {
+        return a.fX == b.fX && a.fY == b.fY;
+    }
+    
+    friend bool operator!=(const SkPoint& a, const SkPoint& b) {
+        return a.fX != b.fX || a.fY != b.fY;
+    }
+
+    /** Returns a new point whose coordinates are the difference between
+        a's and b's (a - b)
+    */
+    friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
+        SkPoint v;
+        v.set(a.fX - b.fX, a.fY - b.fY);
+        return v;
+    }
+
+    /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
+    */
+    friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
+        SkPoint v;
+        v.set(a.fX + b.fX, a.fY + b.fY);
+        return v;
+    }
+
+    /** Returns the euclidian distance from (0,0) to (x,y)
+    */
+    static SkScalar Length(SkScalar x, SkScalar y);
+    
+    /** Returns the euclidian distance between a and b
+    */
+    static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
+        return Length(a.fX - b.fX, a.fY - b.fY);
+    }
+
+    /** Returns the dot product of a and b, treating them as 2D vectors
+    */
+    static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
+        return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY);
+    }
+
+    /** Returns the cross product of a and b, treating them as 2D vectors
+    */
+    static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
+        return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX);
+    }
+};
+
+typedef SkPoint SkVector;
+
+#endif
+
diff --git a/include/core/SkPorterDuff.h b/include/core/SkPorterDuff.h
new file mode 100644
index 0000000..f03e9cb
--- /dev/null
+++ b/include/core/SkPorterDuff.h
@@ -0,0 +1,79 @@
+/*
+ * 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 SkPorterDuff_DEFINED
+#define SkPorterDuff_DEFINED
+
+#include "SkColor.h"
+
+class SkXfermode;
+
+class SkPorterDuff {
+public:
+    /** List of predefined xfermodes. In general, the algebra for the modes
+        uses the following symbols:
+        Sa, Sc  - source alpha and color
+        Da, Dc - destination alpha and color (before compositing)
+        [a, c] - Resulting (alpha, color) values
+        For these equations, the colors are in premultiplied state.
+        If no xfermode is specified, kSrcOver is assumed.
+    */
+    enum Mode {
+        kClear_Mode,    //!< [0, 0]
+        kSrc_Mode,      //!< [Sa, Sc]
+        kDst_Mode,      //!< [Da, Dc]
+        kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
+        kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
+        kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
+        kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
+        kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
+        kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
+        kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
+        kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
+        kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
+        kDarken_Mode,   //!< [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]
+        kLighten_Mode,  //!< [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]
+        kMultiply_Mode, //!< [Sa * Da, Sc * Dc]
+        kScreen_Mode,   //!< [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
+
+        kModeCount
+    };
+    /** Return an SkXfermode object for the specified mode.
+    */
+    static SkXfermode* CreateXfermode(Mode mode);
+    
+    /** Return a function pointer to a routine that applies the specified
+        porter-duff transfer mode.
+    */
+    static SkXfermodeProc GetXfermodeProc(Mode mode);
+    
+    /** Return a function pointer to a routine that applies the specified
+        porter-duff transfer mode and srcColor to a 16bit device color. Note,
+        if the mode+srcColor might return a non-opaque color, then there is not
+        16bit proc, and this will return NULL.
+    */
+    static SkXfermodeProc16 GetXfermodeProc16(Mode mode, SkColor srcColor);
+    
+    /** If the specified xfermode advertises itself as one of the porterduff
+        modes (via SkXfermode::Coeff), return true and if not null, set mode
+        to the corresponding porterduff mode. If it is not recognized as a one,
+        return false and ignore the mode parameter.
+    */
+    static bool IsMode(SkXfermode*, Mode* mode);
+};
+
+#endif
+
diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h
new file mode 100644
index 0000000..e32d6a1
--- /dev/null
+++ b/include/core/SkPostConfig.h
@@ -0,0 +1,216 @@
+/*
+ * 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 SkPostConfig_DEFINED
+#define SkPostConfig_DEFINED
+
+#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE)
+    #define SK_BUILD_FOR_WIN
+#endif
+
+#if defined(SK_DEBUG) && defined(SK_RELEASE)
+    #error "cannot define both SK_DEBUG and SK_RELEASE"
+#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
+    #error "must define either SK_DEBUG or SK_RELEASE"
+#endif
+
+#if defined SK_SUPPORT_UNITTEST && !defined(SK_DEBUG)
+    #error "can't have unittests without debug"
+#endif
+
+#if defined(SK_SCALAR_IS_FIXED) && defined(SK_SCALAR_IS_FLOAT)
+    #error "cannot define both SK_SCALAR_IS_FIXED and SK_SCALAR_IS_FLOAT"
+#elif !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT)
+    #ifdef SK_CAN_USE_FLOAT
+        #define SK_SCALAR_IS_FLOAT
+    #else
+        #define SK_SCALAR_IS_FIXED
+    #endif
+#endif
+
+#if defined(SK_SCALAR_IS_FLOAT) && !defined(SK_CAN_USE_FLOAT)
+    #define SK_CAN_USE_FLOAT
+    // we do nothing in the else case: fixed-scalars can have floats or not
+#endif
+
+#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
+    #error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
+#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
+    #error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
+#endif
+
+// ensure the port has defined all of these, or none of them
+#ifdef SK_A32_SHIFT
+    #if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT)
+        #error "all or none of the 32bit SHIFT amounts must be defined"
+    #endif
+#else
+    #if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT)
+        #error "all or none of the 32bit SHIFT amounts must be defined"
+    #endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SkNEW
+    #define SkNEW(type_name)                new type_name
+    #define SkNEW_ARGS(type_name, args)     new type_name args
+    #define SkNEW_ARRAY(type_name, count)   new type_name[count]
+    #define SkDELETE(obj)                   delete obj
+    #define SkDELETE_ARRAY(array)           delete[] array
+#endif
+
+#ifndef SK_CRASH
+#if 1   // set to 0 for infinite loop, which can help connecting gdb
+    #define SK_CRASH() *(int *)(uintptr_t)0xbbadbeef = 0
+#else
+    #define SK_CRASH()  do {} while (true)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(SK_SOFTWARE_FLOAT) && defined(SK_SCALAR_IS_FLOAT)
+    // if this is defined, we convert floats to 2scompliment ints for compares
+    #ifndef SK_SCALAR_SLOW_COMPARES
+        #define SK_SCALAR_SLOW_COMPARES
+    #endif
+#endif
+
+#ifdef SK_BUILD_FOR_WIN
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+    #undef WIN32_LEAN_AND_MEAN
+
+    #ifndef SK_DEBUGBREAK
+        #define SK_DEBUGBREAK(cond)     do { if (!(cond)) DebugBreak(); } while (false)
+    #endif
+
+    #ifdef SK_BUILD_FOR_WIN32
+        #define strcasecmp(a, b)        stricmp(a, b)
+        #define strncasecmp(a, b, c)    strnicmp(a, b, c)
+    #elif defined(SK_BUILD_FOR_WINCE)
+        #define strcasecmp(a, b)        _stricmp(a, b)
+        #define strncasecmp(a, b, c)    _strnicmp(a, b, c)
+    #endif
+#elif defined(SK_BUILD_FOR_MAC)
+    #ifndef SK_DEBUGBREAK
+        #define SK_DEBUGBREAK(cond)     do { if (!(cond)) SK_CRASH(); } while (false)
+    #endif
+#else
+    #ifdef SK_DEBUG
+        #include <stdio.h>
+        #ifndef SK_DEBUGBREAK
+            #define SK_DEBUGBREAK(cond) do { if (cond) break; \
+                SkDebugf("%s:%d: failed assertion \"%s\"\n", \
+                __FILE__, __LINE__, #cond); SK_CRASH(); } while (false)
+        #endif
+    #endif
+#endif
+
+//  stdlib macros
+
+#if 0
+#if !defined(strlen) && defined(SK_DEBUG)
+    extern size_t sk_strlen(const char*);
+    #define strlen(s)   sk_strlen(s)
+#endif
+#ifndef sk_strcpy
+    #define sk_strcpy(dst, src)     strcpy(dst, src)
+#endif
+#ifndef sk_strchr
+    #define sk_strchr(s, c)         strchr(s, c)
+#endif
+#ifndef sk_strrchr
+    #define sk_strrchr(s, c)        strrchr(s, c)
+#endif
+#ifndef sk_strcmp
+    #define sk_strcmp(s, t)         strcmp(s, t)
+#endif
+#ifndef sk_strncmp
+    #define sk_strncmp(s, t, n)     strncmp(s, t, n)
+#endif
+#ifndef sk_memcpy
+    #define sk_memcpy(dst, src, n)  memcpy(dst, src, n)
+#endif
+#ifndef memmove
+    #define memmove(dst, src, n)    memmove(dst, src, n)
+#endif
+#ifndef sk_memset
+    #define sk_memset(dst, val, n)  memset(dst, val, n)
+#endif
+#ifndef sk_memcmp
+    #define sk_memcmp(s, t, n)      memcmp(s, t, n)
+#endif
+
+#define sk_strequal(s, t)           (!sk_strcmp(s, t))
+#define sk_strnequal(s, t, n)       (!sk_strncmp(s, t, n))
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+#ifndef SK_BUILD_FOR_WINCE
+#include <string.h>
+#include <stdlib.h>
+#else
+#define _CMNINTRIN_DECLARE_ONLY
+#include "cmnintrin.h"
+#endif
+
+#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32
+//#define _CRTDBG_MAP_ALLOC
+#ifdef free
+#undef free
+#endif
+#include <crtdbg.h>
+#undef free
+
+#ifdef SK_DEBUGx
+#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus)
+    void * operator new(
+        size_t cb,
+        int nBlockUse,
+        const char * szFileName,
+        int nLine,
+        int foo
+        );
+    void * operator new[](
+        size_t cb,
+        int nBlockUse,
+        const char * szFileName,
+        int nLine,
+        int foo
+        );
+    void operator delete(
+        void *pUserData,
+        int, const char*, int, int
+        );
+    void operator delete(
+        void *pUserData
+        );
+    void operator delete[]( void * p );
+    #define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__, 0)
+#else
+    #define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
+#endif
+    #define new DEBUG_CLIENTBLOCK
+#else
+#define DEBUG_CLIENTBLOCK
+#endif // _DEBUG
+
+#endif
+
+#endif
+
diff --git a/include/core/SkPreConfig.h b/include/core/SkPreConfig.h
new file mode 100644
index 0000000..04f1987
--- /dev/null
+++ b/include/core/SkPreConfig.h
@@ -0,0 +1,110 @@
+/*
+ * 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 SkPreConfig_DEFINED
+#define SkPreConfig_DEFINED
+
+#ifdef ANDROID
+    #define SK_BUILD_FOR_UNIX
+    #define SkLONGLONG  int64_t
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_SYMBIAN) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC)
+
+    #if defined(PALMOS_SDK_VERSION)
+        #define SK_BUILD_FOR_PALM
+    #elif defined(UNDER_CE)
+        #define SK_BUILD_FOR_WINCE
+    #elif defined(WIN32)
+        #define SK_BUILD_FOR_WIN32
+    #elif defined(__SYMBIAN32__)
+        #define SK_BUILD_FOR_WIN32
+    #elif defined(linux)
+        #define SK_BUILD_FOR_UNIX
+    #else
+        #define SK_BUILD_FOR_MAC
+    #endif
+
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_DEBUG) && !defined(SK_RELEASE)
+    #ifdef NDEBUG
+        #define SK_RELEASE
+    #else
+        #define SK_DEBUG
+    #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+// define to blank or change this in SkUserConfig.h as needed
+#define SK_RESTRICT __restrict__
+
+//////////////////////////////////////////////////////////////////////
+
+#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC)
+    #ifndef SK_CAN_USE_FLOAT
+        #define SK_CAN_USE_FLOAT
+    #endif
+    #if !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT)
+        #define SK_SCALAR_IS_FIXED
+    #endif
+
+    #ifndef SkLONGLONG
+        #ifdef SK_BUILD_FOR_WIN32
+            #define SkLONGLONG  __int64
+        #else
+            #define SkLONGLONG  long long
+        #endif
+    #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
+    #if defined (__ppc__) || defined(__ppc64__)
+        #define SK_CPU_BENDIAN
+    #else
+        #define SK_CPU_LENDIAN
+    #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if (defined(__arm__) && !defined(__thumb__)) || defined(SK_BUILD_FOR_BREW) || defined(SK_BUILD_FOR_WINCE) || (defined(SK_BUILD_FOR_SYMBIAN) && !defined(__MARM_THUMB__))
+    /* e.g. the ARM instructions have conditional execution, making tiny branches cheap */
+    #define SK_CPU_HAS_CONDITIONAL_INSTR
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Conditional features based on build target
+
+#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
+    #ifndef SK_BUILD_NO_IMAGE_ENCODE
+        #define SK_SUPPORT_IMAGE_ENCODE
+    #endif
+#endif
+
+#ifdef SK_BUILD_FOR_SYMBIAN
+    #define SK_USE_RUNTIME_GLOBALS
+#endif
+
+#endif
+
diff --git a/include/core/SkPtrRecorder.h b/include/core/SkPtrRecorder.h
new file mode 100644
index 0000000..ff1e14d
--- /dev/null
+++ b/include/core/SkPtrRecorder.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPtrRecorder_DEFINED
+#define SkPtrRecorder_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTDArray.h"
+
+class SkPtrRecorder : public SkRefCnt {
+public:
+    uint32_t recordPtr(void*);
+    
+    int count() const { return fList.count(); }
+    void getPtrs(void* array[]) const;
+
+    void reset();
+
+protected:
+    virtual void incPtr(void* ptr) {}
+    virtual void decPtr(void* ptr) {}
+
+private:
+    struct Pair {
+        void*       fPtr;
+        uint32_t    fIndex;
+    };
+    SkTDArray<Pair>  fList;
+    
+    static int Cmp(const Pair& a, const Pair& b);
+    
+    typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/include/core/SkRandom.h b/include/core/SkRandom.h
new file mode 100644
index 0000000..33b563a
--- /dev/null
+++ b/include/core/SkRandom.h
@@ -0,0 +1,110 @@
+/*
+ * 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 SkRandom_DEFINED
+#define SkRandom_DEFINED
+
+#include "Sk64.h"
+#include "SkScalar.h"
+
+/** \class SkRandom
+
+    Utility class that implements pseudo random 32bit numbers using a fast
+    linear equation. Unlike rand(), this class holds its own seed (initially
+    set to 0), so that multiple instances can be used with no side-effects.
+*/
+class SkRandom {
+public:
+    SkRandom() : fSeed(0) {}
+    SkRandom(uint32_t seed) : fSeed(seed) {}
+
+    /** Return the next pseudo random number as an unsigned 32bit value.
+    */
+    uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; }
+
+    /** Return the next pseudo random number as a signed 32bit value.
+    */
+    int32_t nextS() { return (int32_t)this->nextU(); }
+
+    /** Return the next pseudo random number as an unsigned 16bit value.
+    */
+    U16CPU nextU16() { return this->nextU() >> 16; }
+
+    /** Return the next pseudo random number as a signed 16bit value.
+    */
+    S16CPU nextS16() { return this->nextS() >> 16; }
+
+    /** Return the next pseudo random number, as an unsigned value of
+        at most bitCount bits.
+        @param bitCount The maximum number of bits to be returned
+    */
+    uint32_t nextBits(unsigned bitCount) {
+        SkASSERT(bitCount > 0 && bitCount <= 32);
+        return this->nextU() >> (32 - bitCount);
+    }
+
+    /** Return the next pseudo random unsigned number, mapped to lie within
+        [min, max] inclusive.
+    */
+    uint32_t nextRangeU(uint32_t min, uint32_t max) {
+        SkASSERT(min <= max);
+        return min + this->nextU() % (max - min + 1);
+    }
+
+    /** Return the next pseudo random number expressed as an unsigned SkFixed
+        in the range [0..SK_Fixed1).
+    */
+    SkFixed nextUFixed1() { return this->nextU() >> 16; }
+
+    /** Return the next pseudo random number expressed as a signed SkFixed
+        in the range (-SK_Fixed1..SK_Fixed1).
+    */
+    SkFixed nextSFixed1() { return this->nextS() >> 15; }
+
+    /** Return the next pseudo random number expressed as a SkScalar
+        in the range [0..SK_Scalar1).
+    */
+    SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
+
+    /** Return the next pseudo random number expressed as a SkScalar
+        in the range (-SK_Scalar1..SK_Scalar1).
+    */
+    SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
+
+    /** Return the next pseudo random number as a signed 64bit value.
+    */
+    void next64(Sk64* a) {
+        SkASSERT(a);
+        a->set(this->nextS(), this->nextU());
+    }
+
+    /** Set the seed of the random object. The seed is initialized to 0 when the
+        object is first created, and is updated each time the next pseudo random
+        number is requested.
+    */
+    void setSeed(int32_t seed) { fSeed = (uint32_t)seed; }
+
+private:
+    //  See "Numerical Recipes in C", 1992 page 284 for these constants
+    enum {
+        kMul = 1664525,
+        kAdd = 1013904223
+    };
+    uint32_t fSeed;
+};
+
+#endif
+
diff --git a/include/core/SkRasterizer.h b/include/core/SkRasterizer.h
new file mode 100644
index 0000000..d81e613
--- /dev/null
+++ b/include/core/SkRasterizer.h
@@ -0,0 +1,50 @@
+/*
+ * 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 SkRasterizer_DEFINED
+#define SkRasterizer_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkMask.h"
+
+class SkMaskFilter;
+class SkMatrix;
+class SkPath;
+struct SkIRect;
+
+class SkRasterizer : public SkFlattenable {
+public:
+    SkRasterizer() {}
+
+    /** Turn the path into a mask, respecting the specified local->device matrix.
+    */
+    bool rasterize(const SkPath& path, const SkMatrix& matrix,
+                   const SkIRect* clipBounds, SkMaskFilter* filter,
+                   SkMask* mask, SkMask::CreateMode mode);
+
+    virtual void flatten(SkFlattenableWriteBuffer& ) {}
+protected:
+    SkRasterizer(SkFlattenableReadBuffer&);
+
+    virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix,
+                             const SkIRect* clipBounds,
+                             SkMask* mask, SkMask::CreateMode mode);
+
+private:
+    typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/include/core/SkReader32.h b/include/core/SkReader32.h
new file mode 100644
index 0000000..1c72a87
--- /dev/null
+++ b/include/core/SkReader32.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkReader32_DEFINED
+#define SkReader32_DEFINED
+
+#include "SkTypes.h"
+
+#include "SkScalar.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+
+class SkReader32 : SkNoncopyable {
+public:
+    SkReader32() : fCurr(NULL), fStop(NULL), fBase(NULL) {}
+    SkReader32(const void* data, size_t size)  {
+        this->setMemory(data, size);
+    }
+
+    void setMemory(const void* data, size_t size) {
+        SkASSERT(ptr_align_4(data));
+        SkASSERT(SkAlign4(size) == size);
+        
+        fBase = fCurr = (const char*)data;
+        fStop = (const char*)data + size;
+    }
+    
+    uint32_t size() const { return fStop - fBase; }
+    uint32_t offset() const { return fCurr - fBase; }
+    bool eof() const { return fCurr >= fStop; }
+    const void* base() const { return fBase; }
+    const void* peek() const { return fCurr; }
+    void rewind() { fCurr = fBase; }
+
+    void setOffset(size_t offset) {
+        SkASSERT(SkAlign4(offset) == offset);
+        SkASSERT(offset <= this->size());
+        fCurr = fBase + offset;
+    }
+    
+    bool readBool() { return this->readInt() != 0; }
+    
+    int32_t readInt() {
+        SkASSERT(ptr_align_4(fCurr));
+        int32_t value = *(const int32_t*)fCurr;
+        fCurr += sizeof(value);
+        SkASSERT(fCurr <= fStop);
+        return value;
+    }
+    
+    SkScalar readScalar() {
+        SkASSERT(ptr_align_4(fCurr));
+        SkScalar value = *(const SkScalar*)fCurr;
+        fCurr += sizeof(value);
+        SkASSERT(fCurr <= fStop);
+        return value;
+    }
+    
+    const SkPoint* skipPoint() {
+        return (const SkPoint*)this->skip(sizeof(SkPoint));
+    }
+    
+    const SkRect* skipRect() {
+        return (const SkRect*)this->skip(sizeof(SkRect));
+    }
+
+    const void* skip(size_t size) {
+        SkASSERT(ptr_align_4(fCurr));
+        const void* addr = fCurr;
+        fCurr += SkAlign4(size);
+        SkASSERT(fCurr <= fStop);
+        return addr;
+    }
+    
+    void read(void* dst, size_t size) {
+        SkASSERT(dst != NULL);
+        SkASSERT(ptr_align_4(fCurr));
+        memcpy(dst, fCurr, size);
+        fCurr += SkAlign4(size);
+        SkASSERT(fCurr <= fStop);
+    }
+    
+    uint8_t readU8() { return (uint8_t)this->readInt(); }
+    uint16_t readU16() { return (uint16_t)this->readInt(); }
+    int32_t readS32() { return this->readInt(); }
+    uint32_t readU32() { return this->readInt(); }
+    
+private:
+    // these are always 4-byte aligned
+    const char* fCurr;  // current position within buffer
+    const char* fStop;  // end of buffer
+    const char* fBase;  // beginning of buffer
+    
+#ifdef SK_DEBUG
+    static bool ptr_align_4(const void* ptr)
+    {
+        return (((const char*)ptr - (const char*)NULL) & 3) == 0;
+    }
+#endif
+};
+
+#endif
diff --git a/include/core/SkRect.h b/include/core/SkRect.h
new file mode 100644
index 0000000..a9f25aa
--- /dev/null
+++ b/include/core/SkRect.h
@@ -0,0 +1,435 @@
+/*
+ * 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 SkRect_DEFINED
+#define SkRect_DEFINED
+
+#include "SkPoint.h"
+
+/** \struct SkIRect
+
+    SkIRect holds four 32 bit integer coordinates for a rectangle
+*/
+struct SkIRect {
+    int32_t fLeft, fTop, fRight, fBottom;
+
+    /** Return true if the rectangle's width or height are <= 0
+    */
+    bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+
+    /** Returns the rectangle's width. This does not check for a valid rectangle (i.e. left <= right)
+        so the result may be negative.
+    */
+    int width() const { return fRight - fLeft; }
+
+    /** Returns the rectangle's height. This does not check for a valid rectangle (i.e. top <= bottom)
+        so the result may be negative.
+    */
+    int height() const { return fBottom - fTop; }
+
+    friend int operator==(const SkIRect& a, const SkIRect& b)
+    {
+        return !memcmp(&a, &b, sizeof(a));
+    }
+    friend int operator!=(const SkIRect& a, const SkIRect& b)
+    {
+        return memcmp(&a, &b, sizeof(a));
+    }
+
+    /** Set the rectangle to (0,0,0,0)
+    */
+    void setEmpty() { memset(this, 0, sizeof(*this)); }
+
+    void set(int32_t left, int32_t top, int32_t right, int32_t bottom)
+    {
+        fLeft   = left;
+        fTop    = top;
+        fRight  = right;
+        fBottom = bottom;
+    }
+
+    /** Offset set the rectangle by adding dx to its left and right,
+        and adding dy to its top and bottom.
+    */
+    void offset(int32_t dx, int32_t dy)
+    {
+        fLeft   += dx;
+        fTop    += dy;
+        fRight  += dx;
+        fBottom += dy;
+    }
+
+    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
+        making the rectangle narrower. If dx is negative, then the sides are moved outwards,
+        making the rectangle wider. The same hods true for dy and the top and bottom.
+    */
+    void inset(int32_t dx, int32_t dy)
+    {
+        fLeft   += dx;
+        fTop    += dy;
+        fRight  -= dx;
+        fBottom -= dy;
+    }
+    /** Returns true if (x,y) is inside the rectangle and the rectangle is not
+        empty. The left and top are considered to be inside, while the right
+        and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
+        points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
+    */
+    bool contains(int32_t x, int32_t y) const
+    {
+        return  (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
+                (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
+    }
+
+    /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
+        If either rectangle is empty, contains() returns false.
+    */
+    bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const
+    {
+        return  left < right && top < bottom && !this->isEmpty() && // check for empties
+                fLeft <= left && fTop <= top &&
+                fRight >= right && fBottom >= bottom;
+    }
+
+    /** Returns true if the specified rectangle r is inside or equal to this rectangle.
+    */
+    bool contains(const SkIRect& r) const
+    {
+        return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
+                fLeft <= r.fLeft && fTop <= r.fTop &&
+                fRight >= r.fRight && fBottom >= r.fBottom;
+    }
+
+    /** Return true if this rectangle contains the specified rectangle.
+		For speed, this method does not check if either this or the specified
+		rectangles are empty, and if either is, its return value is undefined.
+		In the debugging build however, we assert that both this and the
+		specified rectangles are non-empty.
+    */
+    bool containsNoEmptyCheck(int32_t left, int32_t top,
+							  int32_t right, int32_t bottom) const
+    {
+		SkASSERT(fLeft < fRight && fTop < fBottom);
+        SkASSERT(left < right && top < bottom);
+
+        return fLeft <= left && fTop <= top &&
+			   fRight >= right && fBottom >= bottom;
+    }
+    
+    /** If r intersects this rectangle, return true and set this rectangle to that
+        intersection, otherwise return false and do not change this rectangle.
+        If either rectangle is empty, do nothing and return false.
+    */
+    bool intersect(const SkIRect& r)
+    {
+        SkASSERT(&r);
+        return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
+    }
+
+    /** If rectangles a and b intersect, return true and set this rectangle to
+        that intersection, otherwise return false and do not change this
+        rectangle. If either rectangle is empty, do nothing and return false.
+    */
+    bool intersect(const SkIRect& a, const SkIRect& b)
+    {
+        SkASSERT(&a && &b);
+        
+        if (!a.isEmpty() && !b.isEmpty() &&
+            a.fLeft < b.fRight && b.fLeft < a.fRight &&
+            a.fTop < b.fBottom && b.fTop < a.fBottom)
+        {
+            fLeft   = SkMax32(a.fLeft,   b.fLeft);
+            fTop    = SkMax32(a.fTop,    b.fTop);
+            fRight  = SkMin32(a.fRight,  b.fRight);
+            fBottom = SkMin32(a.fBottom, b.fBottom);
+            return true;
+        }
+        return false;
+    }
+    
+    /** If rectangles a and b intersect, return true and set this rectangle to
+        that intersection, otherwise return false and do not change this
+        rectangle. For speed, no check to see if a or b are empty is performed.
+        If either is, then the return result is undefined. In the debug build,
+        we assert that both rectangles are non-empty.
+    */
+    bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b)
+    {
+        SkASSERT(&a && &b);
+        SkASSERT(!a.isEmpty() && !b.isEmpty());
+        
+        if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
+            a.fTop < b.fBottom && b.fTop < a.fBottom)
+        {
+            fLeft   = SkMax32(a.fLeft,   b.fLeft);
+            fTop    = SkMax32(a.fTop,    b.fTop);
+            fRight  = SkMin32(a.fRight,  b.fRight);
+            fBottom = SkMin32(a.fBottom, b.fBottom);
+            return true;
+        }
+        return false;
+    }
+
+    /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
+        return true and set this rectangle to that intersection,
+        otherwise return false and do not change this rectangle.
+        If either rectangle is empty, do nothing and return false.
+    */
+    bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom)
+    {
+        if (left < right && top < bottom && !this->isEmpty() &&
+            fLeft < right && left < fRight && fTop < bottom && top < fBottom)
+        {
+            if (fLeft < left) fLeft = left;
+            if (fTop < top) fTop = top;
+            if (fRight > right) fRight = right;
+            if (fBottom > bottom) fBottom = bottom;
+            return true;
+        }
+        return false;
+    }
+    
+    /** Returns true if a and b are not empty, and they intersect
+    */
+    static bool Intersects(const SkIRect& a, const SkIRect& b)
+    {
+        return  !a.isEmpty() && !b.isEmpty() &&              // check for empties
+                a.fLeft < b.fRight && b.fLeft < a.fRight &&
+                a.fTop < b.fBottom && b.fTop < a.fBottom;
+    }
+    
+    /** Update this rectangle to enclose itself and the specified rectangle.
+        If this rectangle is empty, just set it to the specified rectangle. If the specified
+        rectangle is empty, do nothing.
+    */
+    void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+    /** Update this rectangle to enclose itself and the specified rectangle.
+        If this rectangle is empty, just set it to the specified rectangle. If the specified
+        rectangle is empty, do nothing.
+    */
+    void join(const SkIRect& r)
+    {
+        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
+    }
+
+    /** Swap top/bottom or left/right if there are flipped.
+        This can be called if the edges are computed separately,
+        and may have crossed over each other.
+        When this returns, left <= right && top <= bottom
+    */
+    void sort();
+};
+
+/** \struct SkRect
+*/
+struct SkRect {
+    SkScalar    fLeft, fTop, fRight, fBottom;
+
+    /** Return true if the rectangle's width or height are <= 0
+    */
+    bool        isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+    SkScalar    width() const { return fRight - fLeft; }
+    SkScalar    height() const { return fBottom - fTop; }
+    SkScalar    centerX() const { return SkScalarHalf(fLeft + fRight); }
+    SkScalar    centerY() const { return SkScalarHalf(fTop + fBottom); }
+
+    friend int operator==(const SkRect& a, const SkRect& b)
+    {
+        return !memcmp(&a, &b, sizeof(a));
+    }
+    friend int operator!=(const SkRect& a, const SkRect& b)
+    {
+        return memcmp(&a, &b, sizeof(a));
+    }
+
+    /** return the 4 points that enclose the rectangle
+    */
+    void toQuad(SkPoint quad[4]) const;
+
+    /** Set this rectangle to the empty rectangle (0,0,0,0)
+    */
+    void setEmpty() { memset(this, 0, sizeof(*this)); }
+
+    void set(const SkIRect& src)
+    {
+        fLeft   = SkIntToScalar(src.fLeft);
+        fTop    = SkIntToScalar(src.fTop);
+        fRight  = SkIntToScalar(src.fRight);
+        fBottom = SkIntToScalar(src.fBottom);
+    }
+
+    void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom)
+    {
+        fLeft   = left;
+        fTop    = top;
+        fRight  = right;
+        fBottom = bottom;
+    }
+    
+    /** Initialize the rect with the 4 specified integers. The routine handles
+        converting them to scalars (by calling SkIntToScalar)
+     */
+    void iset(int left, int top, int right, int bottom) {
+        fLeft   = SkIntToScalar(left);
+        fTop    = SkIntToScalar(top);
+        fRight  = SkIntToScalar(right);
+        fBottom = SkIntToScalar(bottom);
+    }
+
+    /** Set this rectangle to be the bounds of the array of points.
+        If the array is empty (count == 0), then set this rectangle
+        to the empty rectangle (0,0,0,0)
+    */
+    void set(const SkPoint pts[], int count);
+
+    /** Offset set the rectangle by adding dx to its left and right,
+        and adding dy to its top and bottom.
+    */
+    void offset(SkScalar dx, SkScalar dy)
+    {
+        fLeft   += dx;
+        fTop    += dy;
+        fRight  += dx;
+        fBottom += dy;
+    }   
+
+    /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
+        making the rectangle narrower. If dx is negative, then the sides are moved outwards,
+        making the rectangle wider. The same hods true for dy and the top and bottom.
+    */
+    void inset(SkScalar dx, SkScalar dy)
+    {
+        fLeft   += dx;
+        fTop    += dy;
+        fRight  -= dx;
+        fBottom -= dy;
+    }
+
+    /** If this rectangle intersects r, return true and set this rectangle to that
+        intersection, otherwise return false and do not change this rectangle.
+        If either rectangle is empty, do nothing and return false.
+    */
+    bool intersect(const SkRect& r);
+
+    /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
+        return true and set this rectangle to that intersection, otherwise return false
+        and do not change this rectangle.
+        If either rectangle is empty, do nothing and return false.
+    */
+    bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+    /** Return true if this rectangle is not empty, and the specified sides of
+        a rectangle are not empty, and they intersect.
+    */
+    bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const
+    {
+        return // first check that both are not empty
+               left < right && top < bottom &&
+               fLeft < fRight && fTop < fBottom &&
+               // now check for intersection
+               fLeft < right && left < fRight &&
+               fTop < bottom && top < fBottom;
+    }
+    
+    /** Return true if rectangles a and b are not empty and intersect.
+        */
+    static bool Intersects(const SkRect& a, const SkRect& b)
+    {
+        return  !a.isEmpty() && !b.isEmpty() &&             // check for empties
+        a.fLeft < b.fRight && b.fLeft < a.fRight &&
+        a.fTop < b.fBottom && b.fTop < a.fBottom;
+    }
+    
+    /** Update this rectangle to enclose itself and the specified rectangle.
+        If this rectangle is empty, just set it to the specified rectangle. If the specified
+        rectangle is empty, do nothing.
+    */
+    void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+    /** Update this rectangle to enclose itself and the specified rectangle.
+        If this rectangle is empty, just set it to the specified rectangle. If the specified
+        rectangle is empty, do nothing.
+    */
+    void join(const SkRect& r)
+    {
+        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
+    }
+    
+    /** Returns true if (p.fX,p.fY) is inside the rectangle. The left and top coordinates of
+        the rectangle are considered to be inside, while the right and bottom coordinates
+        are not. Thus for the rectangle (0, 0, 5, 10), the points (0,0) and (0,9) are inside,
+        while (-1,0) and (5,9) are not.
+        If this rectangle is empty, return false.
+    */
+    bool contains(const SkPoint& p) const
+    {
+        return  !this->isEmpty() &&
+                fLeft <= p.fX && p.fX < fRight &&
+                fTop <= p.fY && p.fY < fBottom;
+    }
+
+    /** Returns true if (x,y) is inside the rectangle. The left and top coordinates of
+        the rectangle are considered to be inside, while the right and bottom coordinates
+        are not. Thus for the rectangle (0, 0, 5, 10), the points (0,0) and (0,9) are inside,
+        while (-1,0) and (5,9) are not.
+        If this rectangle is empty, return false.
+    */
+    bool contains(SkScalar x, SkScalar y) const
+    {
+        return  !this->isEmpty() &&
+                fLeft <= x && x < fRight &&
+                fTop <= y && y < fBottom;
+    }
+
+    /** Return true if this rectangle contains r.
+        If either rectangle is empty, return false.
+    */
+    bool contains(const SkRect& r) const
+    {
+        return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
+                fLeft <= r.fLeft && fTop <= r.fTop &&
+                fRight >= r.fRight && fBottom >= r.fBottom;
+    }
+
+    /** Set the dst integer rectangle by rounding this rectangle's coordinates
+        to their nearest integer values.
+    */
+    void round(SkIRect* dst) const
+    {
+        SkASSERT(dst);
+        dst->set(SkScalarRound(fLeft), SkScalarRound(fTop), SkScalarRound(fRight), SkScalarRound(fBottom));
+    }
+
+    /** Set the dst integer rectangle by rounding "out" this rectangle, choosing the floor of top and left,
+        and the ceiling of right and bototm.
+    */
+    void roundOut(SkIRect* dst) const
+    {
+        SkASSERT(dst);
+        dst->set(SkScalarFloor(fLeft), SkScalarFloor(fTop), SkScalarCeil(fRight), SkScalarCeil(fBottom));
+    }
+
+    /** Swap top/bottom or left/right if there are flipped.
+        This can be called if the edges are computed separately,
+        and may have crossed over each other.
+        When this returns, left <= right && top <= bottom
+    */
+    void sort();
+};
+
+#endif
+
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h
new file mode 100644
index 0000000..adb59dd
--- /dev/null
+++ b/include/core/SkRefCnt.h
@@ -0,0 +1,134 @@
+/*
+ * 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 SkRefCnt_DEFINED
+#define SkRefCnt_DEFINED
+
+#include "SkThread.h"
+
+/** \class SkRefCnt
+
+    SkRefCnt is the base class for objects that may be shared by multiple
+    objects. When a new owner wants a reference, it calls ref(). When an owner
+    wants to release its reference, it calls unref(). When the shared object's
+    reference count goes to zero as the result of an unref() call, its (virtual)
+    destructor is called. It is an error for the destructor to be called
+    explicitly (or via the object going out of scope on the stack or calling
+    delete) if getRefCnt() > 1.
+*/
+class SkRefCnt : SkNoncopyable {
+public:
+    /** Default construct, initializing the reference count to 1.
+    */
+    SkRefCnt() : fRefCnt(1) {}
+
+    /**  Destruct, asserting that the reference count is 1.
+    */
+    virtual ~SkRefCnt() { SkASSERT(fRefCnt == 1); }
+
+    /** Return the reference count.
+    */
+    int32_t getRefCnt() const { return fRefCnt; }
+
+    /** Increment the reference count. Must be balanced by a call to unref().
+    */
+    void ref() const {
+        SkASSERT(fRefCnt > 0);
+        sk_atomic_inc(&fRefCnt);
+    }
+
+    /** Decrement the reference count. If the reference count is 1 before the
+        decrement, then call delete on the object. Note that if this is the
+        case, then the object needs to have been allocated via new, and not on
+        the stack.
+    */
+    void unref() const {
+        SkASSERT(fRefCnt > 0);
+        if (sk_atomic_dec(&fRefCnt) == 1) {
+            fRefCnt = 1;    // so our destructor won't complain
+            SkDELETE(this);
+        }
+    }
+    
+    /** Helper version of ref(), that first checks to see if this is not null.
+        If this is null, then do nothing.
+    */
+    void safeRef() const {
+        if (this) {
+            this->ref();
+        }
+    }
+
+    /** Helper version of unref(), that first checks to see if this is not null.
+        If this is null, then do nothing.
+    */
+    void safeUnref() const {
+        if (this) {
+            this->unref();
+        }
+    }
+
+private:
+    mutable int32_t fRefCnt;
+};
+
+/** \class SkAutoUnref
+
+    SkAutoUnref is a stack-helper class that will automatically call unref() on
+    the object it points to when the SkAutoUnref object goes out of scope.
+    If obj is null, do nothing.
+*/
+class SkAutoUnref : SkNoncopyable {
+public:
+    SkAutoUnref(SkRefCnt* obj) : fObj(obj) {}
+    ~SkAutoUnref();
+
+    SkRefCnt*   get() const { return fObj; }
+
+    /** If the hosted object is null, do nothing and return false, else call
+        ref() on it and return true
+    */
+    bool        ref();
+
+    /** If the hosted object is null, do nothing and return false, else call
+        unref() on it, set its reference to null, and return true
+    */
+    bool        unref();
+
+    /** If the hosted object is null, do nothing and return NULL, else call
+        unref() on it, set its reference to null, and return the object
+    */
+    SkRefCnt*   detach();
+
+private:
+    SkRefCnt*   fObj;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
+    null in on each side of the assignment, and ensuring that ref() is called
+    before unref(), in case the two pointers point to the same object.
+*/
+#define SkRefCnt_SafeAssign(dst, src)   \
+    do {                                \
+        if (src) src->ref();            \
+        if (dst) dst->unref();          \
+        dst = src;                      \
+    } while (0)
+
+#endif
+
diff --git a/include/core/SkRegion.h b/include/core/SkRegion.h
new file mode 100644
index 0000000..8b15a89
--- /dev/null
+++ b/include/core/SkRegion.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2005 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 SkRegion_DEFINED
+#define SkRegion_DEFINED
+
+#include "SkRect.h"
+
+class SkPath;
+class SkRgnBuilder;
+
+namespace android {
+    class Region;
+}
+
+#define SkRegion_gEmptyRunHeadPtr   ((SkRegion::RunHead*)-1)
+#define SkRegion_gRectRunHeadPtr    0
+
+/** \class SkRegion
+
+    The SkRegion class encapsulates the geometric region used to specify
+    clipping areas for drawing.
+*/
+class SkRegion {
+public:
+    typedef int32_t RunType;
+    enum {
+        kRunTypeSentinel = 0x7FFFFFFF
+    };
+    
+    SkRegion();
+    SkRegion(const SkRegion&);
+    explicit SkRegion(const SkIRect&);
+    ~SkRegion();
+
+    SkRegion& operator=(const SkRegion&);
+    
+    friend int operator==(const SkRegion& a, const SkRegion& b);
+    friend int operator!=(const SkRegion& a, const SkRegion& b) {
+        return !(a == b);
+    }
+    
+    /** Replace this region with the specified region, and return true if the
+        resulting region is non-empty.
+    */
+    bool set(const SkRegion& src) {
+        SkASSERT(&src);
+        *this = src;
+        return !this->isEmpty();
+    }
+
+    /** Swap the contents of this and the specified region. This operation
+        is gauarenteed to never fail.
+    */
+    void    swap(SkRegion&);
+
+    /** Return true if this region is empty */
+    bool    isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }
+    /** Return true if this region is a single, non-empty rectangle */
+    bool    isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }
+    /** Return true if this region consists of more than 1 rectangular area */
+    bool    isComplex() const { return !this->isEmpty() && !this->isRect(); }
+    /** Return the bounds of this region. If the region is empty, returns an
+        empty rectangle.
+    */
+    const SkIRect& getBounds() const { return fBounds; }
+
+    /** Returns true if the region is non-empty, and if so, sets the specified
+        path to the boundary(s) of the region.
+    */
+    bool getBoundaryPath(SkPath* path) const;
+
+    /** Set the region to be empty, and return false, since the resulting
+        region is empty
+    */
+    bool    setEmpty();
+
+    /** If rect is non-empty, set this region to that rectangle and return true,
+        otherwise set this region to empty and return false.
+    */
+    bool    setRect(const SkIRect&);
+
+    /** If left < right and top < bottom, set this region to that rectangle and
+        return true, otherwise set this region to empty and return false.
+    */
+    bool    setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+    /** Set this region to the specified region, and return true if it is
+        non-empty. */
+    bool    setRegion(const SkRegion&);
+
+    /** Set this region to the area described by the path, clipped.
+        Return true if the resulting region is non-empty.
+        This produces a region that is identical to the pixels that would be
+        drawn by the path (with no antialiasing) with the specified clip.
+    */
+    bool    setPath(const SkPath&, const SkRegion& clip);
+    
+    /** Returns true if the specified rectangle has a non-empty intersection
+        with this region.
+    */
+    bool    intersects(const SkIRect&) const;
+    
+    /** Returns true if the specified region has a non-empty intersection
+        with this region.
+    */
+    bool    intersects(const SkRegion&) const;
+
+    /** Return true if the specified x,y coordinate is inside the region.
+    */
+    bool    contains(int32_t x, int32_t y) const;
+
+    /** Return true if the specified rectangle is completely inside the region.
+        This works for simple (rectangular) and complex regions, and always
+        returns the correct result. Note: if either this region or the rectangle
+        is empty, contains() returns false.
+    */
+    bool    contains(const SkIRect&) const;
+
+    /** Return true if the specified region is completely inside the region.
+        This works for simple (rectangular) and complex regions, and always
+        returns the correct result. Note: if either region is empty, contains()
+        returns false.
+    */
+    bool    contains(const SkRegion&) const;
+
+    /** Return true if this region is a single rectangle (not complex) and the
+        specified rectangle is contained by this region. Returning false is not
+        a guarantee that the rectangle is not contained by this region, but
+        return true is a guarantee that the rectangle is contained by this region.
+    */
+    bool quickContains(const SkIRect& r) const {
+        return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
+    }
+
+    /** Return true if this region is a single rectangle (not complex) and the
+        specified rectangle is contained by this region. Returning false is not
+        a guarantee that the rectangle is not contained by this region, but
+        return true is a guarantee that the rectangle is contained by this
+        region.
+    */
+    bool quickContains(int32_t left, int32_t top, int32_t right,
+                       int32_t bottom) const {
+        SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
+        
+        return left < right && top < bottom &&
+               fRunHead == SkRegion_gRectRunHeadPtr &&  // this->isRect()
+               /* fBounds.contains(left, top, right, bottom); */
+               fBounds.fLeft <= left && fBounds.fTop <= top &&
+               fBounds.fRight >= right && fBounds.fBottom >= bottom;
+    }
+    
+    /** Return true if this region is empty, or if the specified rectangle does
+        not intersect the region. Returning false is not a guarantee that they
+        intersect, but returning true is a guarantee that they do not.
+    */
+    bool quickReject(const SkIRect& rect) const
+    {
+        return this->isEmpty() || rect.isEmpty() ||
+                !SkIRect::Intersects(fBounds, rect);
+    }
+
+    /** Return true if this region, or rgn, is empty, or if their bounds do not
+        intersect. Returning false is not a guarantee that they intersect, but
+        returning true is a guarantee that they do not.
+    */
+    bool quickReject(const SkRegion& rgn) const {
+        return this->isEmpty() || rgn.isEmpty() ||
+               !SkIRect::Intersects(fBounds, rgn.fBounds);
+    }
+
+    /** Translate the region by the specified (dx, dy) amount.
+    */
+    void translate(int dx, int dy) { this->translate(dx, dy, this); }
+
+    /** Translate the region by the specified (dx, dy) amount, writing the
+        resulting region into dst. Note: it is legal to pass this region as the
+        dst parameter, effectively translating the region in place. If dst is
+        null, nothing happens.
+    */
+    void translate(int dx, int dy, SkRegion* dst) const;
+
+    /** The logical operations that can be performed when combining two regions.
+    */
+    enum Op {
+        kDifference_Op, //!< subtract the op region from the first region
+        kIntersect_Op,  //!< intersect the two regions
+        kUnion_Op,      //!< union (inclusive-or) the two regions
+        kXOR_Op,        //!< exclusive-or the two regions
+        /** subtract the first region from the op region */
+        kReverseDifference_Op,
+        kReplace_Op     //!< replace the dst region with the op region
+    };
+    
+    /** Set this region to the result of applying the Op to this region and the
+        specified rectangle: this = (this op rect).
+        Return true if the resulting region is non-empty.
+        */
+    bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); }
+    
+    /** Set this region to the result of applying the Op to this region and the
+        specified rectangle: this = (this op rect).
+        Return true if the resulting region is non-empty.
+    */
+    bool op(int left, int top, int right, int bottom, Op op) {
+        SkIRect rect;
+        rect.set(left, top, right, bottom);
+        return this->op(*this, rect, op);
+    }
+    
+    /** Set this region to the result of applying the Op to this region and the
+        specified region: this = (this op rgn).
+        Return true if the resulting region is non-empty.
+    */
+    bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
+    /** Set this region to the result of applying the Op to the specified
+        rectangle and region: this = (rect op rgn).
+        Return true if the resulting region is non-empty.
+    */
+    bool op(const SkIRect& rect, const SkRegion& rgn, Op);
+    /** Set this region to the result of applying the Op to the specified
+        region and rectangle: this = (rgn op rect).
+        Return true if the resulting region is non-empty.
+    */
+    bool op(const SkRegion& rgn, const SkIRect& rect, Op);
+    /** Set this region to the result of applying the Op to the specified
+        regions: this = (rgna op rgnb).
+        Return true if the resulting region is non-empty.
+    */
+    bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
+
+    /** Returns the sequence of rectangles, sorted in Y and X, that make up
+        this region.
+    */
+    class Iterator {
+    public:
+        Iterator() : fRgn(NULL), fDone(true) {}
+        Iterator(const SkRegion&);
+        // if we have a region, reset to it and return true, else return false
+        bool rewind();
+        // reset the iterator, using the new region
+        void reset(const SkRegion&);
+        bool done() { return fDone; }
+        void next();
+        const SkIRect& rect() const { return fRect; }
+
+    private:
+        const SkRegion* fRgn;
+        const RunType*  fRuns;
+        SkIRect         fRect;
+        bool            fDone;
+    };
+
+    /** Returns the sequence of rectangles, sorted in Y and X, that make up
+        this region intersected with the specified clip rectangle.
+    */
+    class Cliperator {
+    public:
+        Cliperator(const SkRegion&, const SkIRect& clip);
+        bool            done() { return fDone; }
+        void            next();
+        const SkIRect& rect() const { return fRect; }
+
+    private:
+        Iterator    fIter;
+        SkIRect     fClip;
+        SkIRect     fRect;
+        bool        fDone;
+    };
+
+    /** Returns the sequence of runs that make up this region for the specified
+        Y scanline, clipped to the specified left and right X values.
+    */
+    class Spanerator {
+    public:
+        Spanerator(const SkRegion&, int y, int left, int right);
+        bool    next(int* left, int* right);
+
+    private:
+        const SkRegion::RunType* fRuns;
+        int     fLeft, fRight;
+        bool    fDone;
+    };
+
+    /** Write the region to the buffer, and return the number of bytes written.
+        If buffer is NULL, it still returns the number of bytes.
+    */
+    uint32_t flatten(void* buffer) const;
+    /** Initialized the region from the buffer, returning the number
+        of bytes actually read.
+    */
+    uint32_t unflatten(const void* buffer);
+    
+    SkDEBUGCODE(void dump() const;)
+    SkDEBUGCODE(void validate() const;)
+    SkDEBUGCODE(static void UnitTest();)
+
+    // expose this to allow for regression test on complex regions
+    SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)
+
+private:
+    enum {
+        kOpCount = kReplace_Op + 1
+    };
+
+    enum {
+        kRectRegionRuns = 6 // need to store a region of a rect [T B L R S S]        
+    };
+
+    friend class android::Region;    // needed for marshalling efficiently
+    void allocateRuns(int count); // allocate space for count runs
+
+    struct RunHead;
+
+    SkIRect     fBounds;
+    RunHead*    fRunHead;
+
+    void            freeRuns();
+    const RunType*  getRuns(RunType tmpStorage[], int* count) const;
+    bool            setRuns(RunType runs[], int count);
+
+    int count_runtype_values(int* itop, int* ibot) const;
+    
+    static void BuildRectRuns(const SkIRect& bounds,
+                              RunType runs[kRectRegionRuns]);
+    // returns true if runs are just a rect
+    static bool ComputeRunBounds(const RunType runs[], int count,
+                                 SkIRect* bounds);
+
+    friend struct RunHead;
+    friend class Iterator;
+    friend class Spanerator;
+    friend class SkRgnBuilder;
+    friend class SkFlatRegion;
+};
+
+
+#endif
+
diff --git a/include/core/SkScalar.h b/include/core/SkScalar.h
new file mode 100644
index 0000000..86341eb
--- /dev/null
+++ b/include/core/SkScalar.h
@@ -0,0 +1,254 @@
+/*
+ * 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 SkScalar_DEFINED
+#define SkScalar_DEFINED
+
+#include "SkFixed.h"
+
+/** \file SkScalar.h
+
+    Types and macros for the data type SkScalar. This is the fractional numeric type
+    that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented
+    either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written
+    to allow the calling code to manipulate SkScalar values without knowing which representation
+    is in effect.
+*/
+
+#ifdef SK_SCALAR_IS_FLOAT
+    #include "SkFloatingPoint.h"
+
+    /** SkScalar is our type for fractional values and coordinates. Depending on
+        compile configurations, it is either represented as an IEEE float, or
+        as a 16.16 fixed point integer.
+    */
+    typedef float   SkScalar;
+    extern const uint32_t gIEEENotANumber;
+    extern const uint32_t gIEEEInfinity;
+
+    /** SK_Scalar1 is defined to be 1.0 represented as an SkScalar
+    */
+    #define SK_Scalar1              (1.0f)
+    /** SK_Scalar1 is defined to be 1/2 represented as an SkScalar
+    */
+    #define SK_ScalarHalf           (0.5f)
+    /** SK_ScalarInfinity is defined to be infinity as an SkScalar
+    */
+    #define SK_ScalarInfinity           (*(const float*)&gIEEEInfinity)
+    /** SK_ScalarMax is defined to be the largest value representable as an SkScalar
+    */
+    #define SK_ScalarMax            (3.4028235e+38f)
+    /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar
+    */
+    #define SK_ScalarMin            (1.1754944e-38f)
+    /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar
+    */
+    #define SK_ScalarNaN      (*(const float*)(const void*)&gIEEENotANumber)
+    /** SkScalarIsNaN(n) returns true if argument is not a number
+    */
+    static inline bool SkScalarIsNaN(float x) { return x != x; }
+    /** SkIntToScalar(n) returns its integer argument as an SkScalar
+    */
+    #define SkIntToScalar(n)        ((float)(n))
+    /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar
+    */
+    #define SkFixedToScalar(x)      SkFixedToFloat(x)
+    /** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed
+    */
+    #define SkScalarToFixed(x)      SkFloatToFixed(x)
+
+    #define SkScalarToFloat(n)      (n)
+    #define SkFloatToScalar(n)      (n)
+
+    #define SkScalarToDouble(n)      (double)(n)
+    #define SkDoubleToScalar(n)      (float)(n)
+
+    /** SkScalarFraction(x) returns the signed fractional part of the argument
+    */
+    #define SkScalarFraction(x)     sk_float_mod(x, 1.0f)
+    /** Rounds the SkScalar to the nearest integer value
+    */
+    #define SkScalarRound(x)        sk_float_round2int(x)
+    /** Returns the smallest integer that is >= the specified SkScalar
+    */
+    #define SkScalarCeil(x)         sk_float_ceil2int(x)
+    /** Returns the largest integer that is <= the specified SkScalar
+    */
+    #define SkScalarFloor(x)        sk_float_floor2int(x)
+    /** Returns the absolute value of the specified SkScalar
+    */
+    #define SkScalarAbs(x)          sk_float_abs(x)
+    /** Returns the value pinned between 0 and max inclusive
+    */
+    inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {
+        return x < 0 ? 0 : x > max ? max : x;
+    }
+    /** Returns the value pinned between min and max inclusive
+    */
+    inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {
+        return x < min ? min : x > max ? max : x;
+    }
+    /** Returns the specified SkScalar squared (x*x)
+    */
+    inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
+    /** Returns the product of two SkScalars
+    */
+    #define SkScalarMul(a, b)       ((float)(a) * (b))
+    /** Returns the product of two SkScalars plus a third SkScalar
+    */
+    #define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c))
+    /** Returns the product of a SkScalar and an int rounded to the nearest integer value
+    */
+    #define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b))
+    /** Returns the product of a SkScalar and an int promoted to the next larger int
+    */
+    #define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b))
+    /** Returns the product of a SkScalar and an int truncated to the next smaller int
+    */
+    #define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b))
+    /** Returns the quotient of two SkScalars (a/b)
+    */
+    #define SkScalarDiv(a, b)       ((float)(a) / (b))
+    /** Returns the mod of two SkScalars (a mod b)
+    */
+    #define SkScalarMod(x,y)        sk_float_mod(x,y)
+    /** Returns the product of the first two arguments, divided by the third argument
+    */
+    #define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c))
+    /** Returns the multiplicative inverse of the SkScalar (1/x)
+    */
+    #define SkScalarInvert(x)       (SK_Scalar1 / (x))
+    #define SkScalarFastInvert(x)   (SK_Scalar1 / (x))
+    /** Returns the square root of the SkScalar
+    */
+    #define SkScalarSqrt(x)         sk_float_sqrt(x)
+    /** Returns the average of two SkScalars (a+b)/2
+    */
+    #define SkScalarAve(a, b)       (((a) + (b)) * 0.5f)
+    /** Returns the geometric mean of two SkScalars
+    */
+    #define SkScalarMean(a, b)      sk_float_sqrt((float)(a) * (b))
+    /** Returns one half of the specified SkScalar
+    */
+    #define SkScalarHalf(a)         ((a) * 0.5f)
+
+    #define SK_ScalarSqrt2          1.41421356f
+    #define SK_ScalarPI             3.14159265f
+    #define SK_ScalarTanPIOver8     0.414213562f
+    #define SK_ScalarRoot2Over2     0.707106781f
+
+    #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
+    float SkScalarSinCos(SkScalar radians, SkScalar* cosValue);
+    #define SkScalarSin(radians)    (float)sk_float_sin(radians)
+    #define SkScalarCos(radians)    (float)sk_float_cos(radians)
+    #define SkScalarTan(radians)    (float)sk_float_tan(radians)
+    #define SkScalarASin(val)   (float)sk_float_asin(val)
+    #define SkScalarACos(val)   (float)sk_float_acos(val)
+    #define SkScalarATan2(y, x) (float)sk_float_atan2(y,x)
+    #define SkScalarExp(x)  (float)sk_float_exp(x)
+    #define SkScalarLog(x)  (float)sk_float_log(x)
+
+    inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }
+    inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }
+
+#else
+    typedef SkFixed SkScalar;
+
+    #define SK_Scalar1              SK_Fixed1
+    #define SK_ScalarHalf           SK_FixedHalf
+    #define SK_ScalarInfinity   SK_FixedMax
+    #define SK_ScalarMax            SK_FixedMax
+    #define SK_ScalarMin            SK_FixedMin
+    #define SK_ScalarNaN            SK_FixedNaN
+    #define SkScalarIsNaN(x)        ((x) == SK_FixedNaN)
+    #define SkIntToScalar(n)        SkIntToFixed(n)
+    #define SkFixedToScalar(x)      (x)
+    #define SkScalarToFixed(x)      (x)
+    #ifdef SK_CAN_USE_FLOAT
+        #define SkScalarToFloat(n)  SkFixedToFloat(n)
+        #define SkFloatToScalar(n)  SkFloatToFixed(n)
+
+        #define SkScalarToDouble(n) SkFixedToDouble(n)
+        #define SkDoubleToScalar(n) SkDoubleToFixed(n)
+    #endif
+    #define SkScalarFraction(x)     SkFixedFraction(x)
+    #define SkScalarRound(x)        SkFixedRound(x)
+    #define SkScalarCeil(x)         SkFixedCeil(x)
+    #define SkScalarFloor(x)        SkFixedFloor(x)
+    #define SkScalarAbs(x)          SkFixedAbs(x)
+    #define SkScalarClampMax(x, max) SkClampMax(x, max)
+    #define SkScalarPin(x, min, max) SkPin32(x, min, max)
+    #define SkScalarSquare(x)       SkFixedSquare(x)
+    #define SkScalarMul(a, b)       SkFixedMul(a, b)
+    #define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c)
+    #define SkScalarMulRound(a, b)  SkFixedMulCommon(a, b, SK_FixedHalf)
+    #define SkScalarMulCeil(a, b)   SkFixedMulCommon(a, b, SK_Fixed1 - 1)
+    #define SkScalarMulFloor(a, b)  SkFixedMulCommon(a, b, 0)
+    #define SkScalarDiv(a, b)       SkFixedDiv(a, b)
+    #define SkScalarMod(a, b)       SkFixedMod(a, b)
+    #define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c)
+    #define SkScalarInvert(x)       SkFixedInvert(x)
+    #define SkScalarFastInvert(x)   SkFixedFastInvert(x)
+    #define SkScalarSqrt(x)         SkFixedSqrt(x)
+    #define SkScalarAve(a, b)       SkFixedAve(a, b)
+    #define SkScalarMean(a, b)      SkFixedMean(a, b)
+    #define SkScalarHalf(a)         ((a) >> 1)
+
+    #define SK_ScalarSqrt2          SK_FixedSqrt2
+    #define SK_ScalarPI             SK_FixedPI
+    #define SK_ScalarTanPIOver8     SK_FixedTanPIOver8
+    #define SK_ScalarRoot2Over2     SK_FixedRoot2Over2
+
+    #define SkDegreesToRadians(degrees)     SkFractMul(degrees, SK_FractPIOver180)
+    #define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr)
+    #define SkScalarSin(radians)    SkFixedSin(radians)
+    #define SkScalarCos(radians)    SkFixedCos(radians)
+    #define SkScalarTan(val)        SkFixedTan(val)
+    #define SkScalarASin(val)       SkFixedASin(val)
+    #define SkScalarACos(val)       SkFixedACos(val)
+    #define SkScalarATan2(y, x)     SkFixedATan2(y,x)
+    #define SkScalarExp(x)          SkFixedExp(x)
+    #define SkScalarLog(x)          SkFixedLog(x)
+
+    #define SkMaxScalar(a, b)       SkMax32(a, b)
+    #define SkMinScalar(a, b)       SkMin32(a, b)
+#endif
+
+#define SK_ScalarNearlyZero         (SK_Scalar1 / (1 << 12))
+
+/*  <= is slower than < for floats, so we use < for our tolerance test
+*/
+
+inline bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero)
+{
+    SkASSERT(tolerance > 0);
+    return SkScalarAbs(x) < tolerance;
+}
+
+/** Linearly interpolate between A and B, based on t.
+    If t is 0, return A
+    If t is 1, return B
+    else interpolate.
+    t must be [0..SK_Scalar1]
+*/
+inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t)
+{
+    SkASSERT(t >= 0 && t <= SK_Scalar1);
+    return A + SkScalarMul(B - A, t);
+}
+
+#endif
+
diff --git a/include/core/SkScalarCompare.h b/include/core/SkScalarCompare.h
new file mode 100644
index 0000000..fee554c
--- /dev/null
+++ b/include/core/SkScalarCompare.h
@@ -0,0 +1,34 @@
+/*
+ * 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 SkScalarCompare_DEFINED
+#define SkScalarCompare_DEFINED
+
+#include "SkFloatBits.h"
+#include "SkRect.h"
+
+#ifdef SK_SCALAR_SLOW_COMPARES
+    typedef int32_t SkScalarCompareType;
+    typedef SkIRect SkRectCompareType;
+    #define SkScalarToCompareType(x)    SkScalarAs2sCompliment(x)
+#else
+    typedef SkScalar SkScalarCompareType;
+    typedef SkRect SkRectCompareType;
+    #define SkScalarToCompareType(x)    (x)
+#endif
+
+#endif
+
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
new file mode 100644
index 0000000..ec2cd0d
--- /dev/null
+++ b/include/core/SkScalerContext.h
@@ -0,0 +1,219 @@
+/*
+ * 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 SkScalerContext_DEFINED
+#define SkScalerContext_DEFINED
+
+#include "SkMask.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+
+class SkDescriptor;
+class SkMaskFilter;
+class SkPathEffect;
+class SkRasterizer;
+
+// needs to be != to any valid SkMask::Format
+#define MASK_FORMAT_JUST_ADVANCE    (0xFF)
+
+struct SkGlyph {
+    void*       fImage;
+    SkPath*     fPath;
+    SkFixed     fAdvanceX, fAdvanceY;
+
+    uint32_t    fID;
+    uint16_t    fWidth, fHeight;
+    int16_t     fTop, fLeft;
+
+    uint8_t     fMaskFormat;
+    int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
+    
+    unsigned rowBytes() const {
+        unsigned rb = fWidth;
+        if (SkMask::kBW_Format == fMaskFormat) {
+            rb = (rb + 7) >> 3;
+        } else {
+            rb = SkAlign4(rb);
+        }
+        return rb;
+    }
+    
+    bool isJustAdvance() const {
+        return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
+    }
+    
+    bool isFullMetrics() const {
+        return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
+    }
+    
+    uint16_t getGlyphID() const {
+        return ID2Code(fID);
+    }
+
+    unsigned getGlyphID(unsigned baseGlyphCount) const {
+        unsigned code = ID2Code(fID);
+        SkASSERT(code >= baseGlyphCount);
+        return code - baseGlyphCount;
+    }
+    
+    unsigned getSubX() const {
+        return ID2SubX(fID);
+    }
+    
+    SkFixed getSubXFixed() const {
+        return SubToFixed(ID2SubX(fID));
+    }
+    
+    SkFixed getSubYFixed() const {
+        return SubToFixed(ID2SubY(fID));
+    }
+    
+    size_t computeImageSize() const;
+    
+    enum {
+        kSubBits = 2,
+        kSubMask = ((1 << kSubBits) - 1),
+        kSubShift = 24, // must be large enough for glyphs and unichars
+        kCodeMask = ((1 << kSubShift) - 1),
+        // relative offsets for X and Y subpixel bits
+        kSubShiftX = kSubBits,
+        kSubShiftY = 0
+    };
+
+    static unsigned ID2Code(uint32_t id) {
+        return id & kCodeMask;
+    }
+    
+    static unsigned ID2SubX(uint32_t id) {
+        return id >> (kSubShift + kSubShiftX);
+    }
+    
+    static unsigned ID2SubY(uint32_t id) {
+        return (id >> (kSubShift + kSubShiftY)) & kSubMask;
+    }
+    
+    static unsigned FixedToSub(SkFixed n) {
+        return (n >> (16 - kSubBits)) & kSubMask;
+    }
+    
+    static SkFixed SubToFixed(unsigned sub) {
+        SkASSERT(sub <= kSubMask);
+        return sub << (16 - kSubBits);
+    }
+    
+    static uint32_t MakeID(unsigned code) {
+        return code;
+    }
+    
+    static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
+        SkASSERT(code <= kCodeMask);
+        x = FixedToSub(x);
+        y = FixedToSub(y);
+        return (x << (kSubShift + kSubShiftX)) |
+               (y << (kSubShift + kSubShiftY)) |
+               code;
+    }
+    
+    void toMask(SkMask* mask) const;
+};
+
+class SkScalerContext {
+public:
+    enum Hints {
+        kNo_Hints,
+        kSubpixel_Hints,
+        kNormal_Hints
+    };
+    enum Flags {
+        kFrameAndFill_Flag  = 0x01,
+        kDevKernText_Flag   = 0x02,
+        kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags
+        kGammaForWhite_Flag = 0x08  // illegal to set both Gamma flags
+    };
+    struct Rec {
+        uint32_t    fFontID;
+        SkScalar    fTextSize, fPreScaleX, fPreSkewX;
+        SkScalar    fPost2x2[2][2];
+        SkScalar    fFrameWidth, fMiterLimit;
+        uint8_t     fHints;
+        uint8_t     fMaskFormat;
+        uint8_t     fStrokeJoin;
+        uint8_t     fFlags;
+        
+        void    getMatrixFrom2x2(SkMatrix*) const;
+        void    getLocalMatrix(SkMatrix*) const;
+        void    getSingleMatrix(SkMatrix*) const;
+    };
+
+    SkScalerContext(const SkDescriptor* desc);
+    virtual ~SkScalerContext();
+
+    void setBaseGlyphCount(unsigned baseGlyphCount) {
+        fBaseGlyphCount = baseGlyphCount;
+    }
+
+    uint16_t    charToGlyphID(SkUnichar uni);
+
+    unsigned    getGlyphCount() const { return this->generateGlyphCount(); }
+    void        getAdvance(SkGlyph*);
+    void        getMetrics(SkGlyph*);
+    void        getImage(const SkGlyph&);
+    void        getPath(const SkGlyph&, SkPath*);
+    void        getFontMetrics(SkPaint::FontMetrics* mX,
+                               SkPaint::FontMetrics* mY);
+
+    static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
+    static SkScalerContext* Create(const SkDescriptor*);
+
+protected:
+    Rec         fRec;
+    unsigned    fBaseGlyphCount;
+
+    virtual unsigned generateGlyphCount() const = 0;
+    virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
+    virtual void generateAdvance(SkGlyph*) = 0;
+    virtual void generateMetrics(SkGlyph*) = 0;
+    virtual void generateImage(const SkGlyph&) = 0;
+    virtual void generatePath(const SkGlyph&, SkPath*) = 0;
+    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
+                                     SkPaint::FontMetrics* mY) = 0;
+
+private:
+    SkPathEffect*   fPathEffect;
+    SkMaskFilter*   fMaskFilter;
+    SkRasterizer*   fRasterizer;
+    SkScalar        fDevFrameWidth;
+
+    void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
+                         SkPath* devPath, SkMatrix* fillToDevMatrix);
+
+    mutable SkScalerContext* fAuxScalerContext;
+
+    SkScalerContext* getGlyphContext(const SkGlyph& glyph) const;
+    
+    // return loaded fAuxScalerContext or NULL
+    SkScalerContext* loadAuxContext() const;
+};
+
+#define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
+#define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
+#define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
+#define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
+
+#endif
+
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
new file mode 100644
index 0000000..7c13e3d
--- /dev/null
+++ b/include/core/SkShader.h
@@ -0,0 +1,184 @@
+/*
+ * 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 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
+    };
+
+    /** 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();
+    
+    /** Optional methods for shaders that can pretend to be a bitmap/texture
+        to play along with opengl. Default just returns false and ignores
+        the out parameters.
+    */
+    virtual bool asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
+                           TileMode xy[2]);
+
+    //////////////////////////////////////////////////////////////////////////
+    //  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
+
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
new file mode 100644
index 0000000..26ef43f
--- /dev/null
+++ b/include/core/SkStream.h
@@ -0,0 +1,315 @@
+/*
+ * 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 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();
+
+    static void UnitTest();
+};
+
+class 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    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);
+
+    static void UnitTest();
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include "SkString.h"
+
+struct SkFILE;
+
+/** A stream that reads from a FILE*, which is opened in the constructor and
+    closed in the destructor
+ */
+class 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);
+    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:
+    const void* fSrc;
+    size_t fSize, fOffset;
+    SkBool8 fWeOwnTheData;
+};
+
+/** \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 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 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() { return fBytesWritten; }
+
+    // copy what has been written to the stream into dst
+    void    copyTo(void* dst) const;
+    /*  return a cache of the flattened data returned by copyTo().
+        This copy is only valid until the next call to write().
+        The memory is managed by the stream class.
+    */
+    const char* getStream() const;
+
+    // same as getStream, but additionally detach the flattened datat
+    const char* detach();
+    
+    // reset the stream to its original state
+    void reset();
+    void padToAlign4();
+private:
+    struct Block;
+    Block*  fHead;
+    Block*  fTail;
+    size_t  fBytesWritten;
+    mutable char*   fCopyToCache;
+};
+
+
+class SkDebugWStream : public SkWStream {
+public:
+    // overrides
+    virtual bool write(const void* buffer, size_t size);
+    virtual void newline();
+};
+
+// for now
+typedef SkFILEStream SkURLStream;
+
+#endif
+
diff --git a/include/core/SkString.h b/include/core/SkString.h
new file mode 100644
index 0000000..743b093
--- /dev/null
+++ b/include/core/SkString.h
@@ -0,0 +1,170 @@
+/*
+ * 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 SkStrAppendScalar_MaxSize  11
+char*   SkStrAppendScalar(char buffer[], SkScalar);
+
+/** \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);
+    explicit    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(); }
+
+    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&);
+
+    char*   writable_str();
+
+    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    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    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    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);
+
+    /** Swap contents between this and other. This function is guaranteed
+        to never fail or throw.
+    */
+    void    swap(SkString& other);
+
+  /** @cond UNIT_TEST */
+    SkDEBUGCODE(static void UnitTest();)
+  /** @endcond */
+    
+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
+
diff --git a/include/core/SkStroke.h b/include/core/SkStroke.h
new file mode 100644
index 0000000..b593b69
--- /dev/null
+++ b/include/core/SkStroke.h
@@ -0,0 +1,71 @@
+/*
+ * 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
+
diff --git a/include/core/SkTDArray.h b/include/core/SkTDArray.h
new file mode 100644
index 0000000..4d2d7f7
--- /dev/null
+++ b/include/core/SkTDArray.h
@@ -0,0 +1,293 @@
+/*
+ * 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 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);
+    }
+
+    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();
+    }
+    
+#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
+
diff --git a/include/core/SkTDStack.h b/include/core/SkTDStack.h
new file mode 100644
index 0000000..5bc10ee
--- /dev/null
+++ b/include/core/SkTDStack.h
@@ -0,0 +1,120 @@
+/*
+ * 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; }
+
+    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
+
diff --git a/include/core/SkTDict.h b/include/core/SkTDict.h
new file mode 100644
index 0000000..0b92779
--- /dev/null
+++ b/include/core/SkTDict.h
@@ -0,0 +1,169 @@
+/*
+ * 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
+
diff --git a/include/core/SkTSearch.h b/include/core/SkTSearch.h
new file mode 100644
index 0000000..f29e6f5
--- /dev/null
+++ b/include/core/SkTSearch.h
@@ -0,0 +1,167 @@
+/*
+ * 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);
+}
+
+SkDEBUGCODE(void SkQSort_UnitTest();)
+
+#endif
+
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
new file mode 100644
index 0000000..27ebd41
--- /dev/null
+++ b/include/core/SkTemplates.h
@@ -0,0 +1,217 @@
+/*
+ * 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 SkTemplates_DEFINED
+#define SkTemplates_DEFINED
+
+#include "SkTypes.h"
+
+/** \file SkTemplates.h
+
+    This file contains light-weight template classes for type-safe and exception-safe
+    resource management.
+*/
+
+/** \class SkAutoTCallVProc
+
+    Call a function when this goes out of scope. The template uses two
+    parameters, the object, and a function that is to be called in the destructor.
+    If detach() is called, the object reference is set to null. If the object
+    reference is null when the destructor is called, we do not call the
+    function.
+*/
+template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
+public:
+    SkAutoTCallVProc(T* obj): fObj(obj) {}
+    ~SkAutoTCallVProc() { if (fObj) P(fObj); }
+    T* detach() { T* obj = fObj; fObj = NULL; return obj; }
+private:
+    T* fObj;
+};
+
+/** \class SkAutoTCallIProc
+
+Call a function when this goes out of scope. The template uses two
+parameters, the object, and a function that is to be called in the destructor.
+If detach() is called, the object reference is set to null. If the object
+reference is null when the destructor is called, we do not call the
+function.
+*/
+template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
+public:
+    SkAutoTCallIProc(T* obj): fObj(obj) {}
+    ~SkAutoTCallIProc() { if (fObj) P(fObj); }
+    T* detach() { T* obj = fObj; fObj = NULL; return obj; }
+private:
+    T* fObj;
+};
+
+template <typename T> class SkAutoTDelete : SkNoncopyable {
+public:
+    SkAutoTDelete(T* obj) : fObj(obj) {}
+    ~SkAutoTDelete() { delete fObj; }
+
+    T*      get() const { return fObj; }
+    void    free() { delete fObj; fObj = NULL; }
+    T*      detach() { T* obj = fObj; fObj = NULL; return obj; }
+
+private:
+    T*  fObj;
+};
+
+template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
+public:
+    SkAutoTDeleteArray(T array[]) : fArray(array) {}
+    ~SkAutoTDeleteArray() { delete[] fArray; }
+
+    T*      get() const { return fArray; }
+    void    free() { delete[] fArray; fArray = NULL; }
+    T*      detach() { T* array = fArray; fArray = NULL; return array; }
+
+private:
+    T*  fArray;
+};
+
+/** Allocate an array of T elements, and free the array in the destructor
+ */
+template <typename T> class SkAutoTArray : SkNoncopyable {
+public:
+    /** Allocate count number of T elements
+     */
+    SkAutoTArray(size_t count) {
+        fArray = NULL;
+        if (count) {
+            fArray = new T[count];
+        }
+        SkDEBUGCODE(fCount = count;)
+    }
+
+    ~SkAutoTArray() {
+        delete[] fArray;
+    }
+
+    /** Return the array of T elements. Will be NULL if count == 0
+     */
+    T* get() const { return fArray; }
+    
+    /** Return the nth element in the array
+     */
+    T&  operator[](int index) const {
+        SkASSERT((unsigned)index < fCount);
+        return fArray[index];
+    }
+
+private:
+    T*  fArray;
+    SkDEBUGCODE(size_t fCount;)
+};
+
+/** Wraps SkAutoTArray, with room for up to N elements preallocated
+ */
+template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
+public:
+    /** Allocate count number of T elements
+     */
+    SkAutoSTArray(size_t count) {
+        if (count > N) {
+            fArray = new T[count];
+        } else if (count) {
+            fArray = new (fStorage) T[count];
+        } else {
+            fArray = NULL;
+        }
+        fCount = count;
+    }
+    
+    ~SkAutoSTArray() {
+        if (fCount > N) {
+            delete[] fArray;
+        } else {
+            T* start = fArray;
+            T* iter = start + fCount;
+            while (iter > start) {
+                (--iter)->~T();
+            }
+        }
+    }
+    
+    /** Return the number of T elements in the array
+     */
+    size_t count() const { return fCount; }
+    
+    /** Return the array of T elements. Will be NULL if count == 0
+     */
+    T* get() const { return fArray; }
+    
+    /** Return the nth element in the array
+     */
+    T&  operator[](int index) const {
+        SkASSERT((unsigned)index < fCount);
+        return fArray[index];
+    }
+    
+private:
+    size_t  fCount;
+    T*      fArray;
+    // since we come right after fArray, fStorage should be properly aligned
+    char    fStorage[N * sizeof(T)];
+};
+
+/** Allocate a temp array on the stack/heap.
+    Does NOT call any constructors/destructors on T (i.e. T must be POD)
+*/
+template <typename T> class SkAutoTMalloc : SkNoncopyable {
+public:
+    SkAutoTMalloc(size_t count)
+    {
+        fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+    }
+    ~SkAutoTMalloc()
+    {
+        sk_free(fPtr);
+    }
+    T* get() const { return fPtr; }
+
+private:
+    T*  fPtr;
+};
+
+template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
+public:
+    SkAutoSTMalloc(size_t count)
+    {
+        if (count <= N)
+            fPtr = fTStorage;
+        else
+            fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+    }
+    ~SkAutoSTMalloc()
+    {
+        if (fPtr != fTStorage)
+            sk_free(fPtr);
+    }
+    T* get() const { return fPtr; }
+
+private:
+    T*          fPtr;
+    union {
+        uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
+        T           fTStorage[1];   // do NOT want to invoke T::T()
+    };
+};
+
+#endif
+
diff --git a/include/core/SkThread.h b/include/core/SkThread.h
new file mode 100644
index 0000000..637492d
--- /dev/null
+++ b/include/core/SkThread.h
@@ -0,0 +1,68 @@
+/*
+ * 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 SkThread_DEFINED
+#define SkThread_DEFINED
+
+#include "SkTypes.h"
+#include "SkThread_platform.h"
+
+/****** SkThread_platform needs to define the following...
+
+int32_t sk_atomic_inc(int32_t*);
+int32_t sk_atomic_dec(int32_t*);
+
+class SkMutex {
+public:
+    SkMutex();
+    ~SkMutex();
+
+    void    acquire();
+    void    release();
+};
+
+****************/
+
+class SkAutoMutexAcquire : SkNoncopyable {
+public:
+    explicit SkAutoMutexAcquire(SkMutex& mutex) : fMutex(&mutex)
+    {
+        SkASSERT(fMutex != NULL);
+        mutex.acquire();
+    }
+    /** If the mutex has not been release, release it now.
+    */
+    ~SkAutoMutexAcquire()
+    {
+        if (fMutex)
+            fMutex->release();
+    }
+    /** If the mutex has not been release, release it now.
+    */
+    void release()
+    {
+        if (fMutex)
+        {
+            fMutex->release();
+            fMutex = NULL;
+        }
+    }
+        
+private:
+    SkMutex* fMutex;
+};
+
+#endif
diff --git a/include/core/SkThread_platform.h b/include/core/SkThread_platform.h
new file mode 100644
index 0000000..825b737
--- /dev/null
+++ b/include/core/SkThread_platform.h
@@ -0,0 +1,71 @@
+/*
+ * 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 SkThread_platform_DEFINED
+#define SkThread_platform_DEFINED
+
+#ifdef ANDROID
+
+#include <utils/threads.h>
+#include <utils/Atomic.h>
+
+#define sk_atomic_inc(addr)     android_atomic_inc(addr)
+#define sk_atomic_dec(addr)     android_atomic_dec(addr)
+
+class SkMutex : android::Mutex {
+public:
+    // if isGlobal is true, then ignore any errors in the platform-specific
+    // destructor
+    SkMutex(bool isGlobal = true) {}
+    ~SkMutex() {}
+
+    void    acquire() { this->lock(); }
+    void    release() { this->unlock(); }
+};
+
+#else
+
+/** Implemented by the porting layer, this function adds 1 to the int specified
+    by the address (in a thread-safe manner), and returns the previous value.
+*/
+int32_t sk_atomic_inc(int32_t* addr);
+/** Implemented by the porting layer, this function subtracts 1 to the int
+    specified by the address (in a thread-safe manner), and returns the previous
+    value.
+*/
+int32_t sk_atomic_dec(int32_t* addr);
+
+class SkMutex {
+public:
+    // if isGlobal is true, then ignore any errors in the platform-specific
+    // destructor
+    SkMutex(bool isGlobal = true);
+    ~SkMutex();
+
+    void    acquire();
+    void    release();
+
+private:
+    bool fIsGlobal;
+    enum {
+        kStorageIntCount = 12
+    };
+    uint32_t    fStorage[kStorageIntCount];
+};
+
+#endif
+
+#endif
diff --git a/include/core/SkTime.h b/include/core/SkTime.h
new file mode 100644
index 0000000..9ee7110
--- /dev/null
+++ b/include/core/SkTime.h
@@ -0,0 +1,72 @@
+/*
+ * 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 SkTime_DEFINED
+#define SkTime_DEFINED
+
+#include "SkTypes.h"
+
+/** \class SkTime
+    Platform-implemented utilities to return time of day, and millisecond counter.
+*/
+class SkTime {
+public:
+    struct DateTime {
+        uint16_t fYear;          //!< e.g. 2005
+        uint8_t  fMonth;         //!< 1..12
+        uint8_t  fDayOfWeek;     //!< 0..6, 0==Sunday
+        uint8_t  fDay;           //!< 1..31
+        uint8_t  fHour;          //!< 0..23
+        uint8_t  fMinute;        //!< 0..59
+        uint8_t  fSecond;        //!< 0..59
+    };
+    static void GetDateTime(DateTime*);
+
+    static SkMSec GetMSecs();
+};
+
+#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN32)
+    extern SkMSec gForceTickCount;
+#endif
+
+#define SK_TIME_FACTOR      1
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkAutoTime {
+public:
+    // The label is not deep-copied, so its address must remain valid for the
+    // lifetime of this object
+    SkAutoTime(const char* label = NULL, SkMSec minToDump = 0) : fLabel(label)
+    {
+        fNow = SkTime::GetMSecs();
+        fMinToDump = minToDump;
+    }
+    ~SkAutoTime()
+    {
+        SkMSec dur = SkTime::GetMSecs() - fNow;
+        if (dur >= fMinToDump) {
+            SkDebugf("%s %d\n", fLabel ? fLabel : "", dur);
+        }
+    }
+private:
+    const char* fLabel;
+    SkMSec      fNow;
+    SkMSec      fMinToDump;
+};
+
+#endif
+
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
new file mode 100644
index 0000000..546edca
--- /dev/null
+++ b/include/core/SkTypeface.h
@@ -0,0 +1,131 @@
+/*
+ * 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 SkTypeface_DEFINED
+#define SkTypeface_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkStream;
+class SkWStream;
+
+/** \class SkTypeface
+
+    The SkTypeface class specifies the typeface and intrinsic style of a font.
+    This is used in the paint, along with optionally algorithmic settings like
+    textSize, textSkewX, textScaleX, kFakeBoldText_Mask, to specify
+    how text appears when drawn (and measured).
+
+    Typeface objects are immutable, and so they can be shred between threads.
+    To enable this, Typeface inherits from the thread-safe version of SkRefCnt.
+*/
+class SkTypeface : public SkRefCnt {
+public:
+    /** Style specifies the intrinsic style attributes of a given typeface
+    */
+    enum Style {
+        kNormal = 0,
+        kBold   = 0x01,
+        kItalic = 0x02,
+
+        // helpers
+        kBoldItalic = 0x03
+    };
+
+    /** Returns the typeface's intrinsic style attributes
+    */
+    Style style() const { return fStyle; }
+    
+    /** DEPRECATED */
+    Style getStyle() const { return this->style(); }
+
+    /** Returns true if getStyle() has the kBold bit set.
+    */
+    bool isBold() const { return (fStyle & kBold) != 0; }
+
+    /** Returns true if getStyle() has the kItalic bit set.
+    */
+    bool isItalic() const { return (fStyle & kItalic) != 0; }
+    
+    uint32_t uniqueID() const { return fUniqueID; }
+
+    /** Return the uniqueID for the specified typeface. If the face is null,
+        resolve it to the default font and return its uniqueID.
+    */
+    static uint32_t UniqueID(const SkTypeface* face);
+
+    /** Return a new reference to the typeface that most closely matches the
+        requested familyName and style. Pass null as the familyName to return
+        the default font for the requested style. Will never return null
+        
+        @param familyName  May be NULL. The name of the font family.
+        @param style       The style (normal, bold, italic) of the typeface.
+        @return reference to the closest-matching typeface. Call must call
+                unref() when they are done.
+    */
+    static SkTypeface* Create(const char familyName[], Style style = kNormal);
+
+    /** Return a new reference to the typeface that most closely matches the
+        requested typeface and specified Style. Use this call if you want to
+        pick a new style from the same family of the existing typeface.
+        If family is NULL, this selects from the default font's family.
+        
+        @param family  May be NULL. The name of the existing type face.
+        @param s       The style (normal, bold, italic) of the type face.
+        @return reference to the closest-matching typeface. Call must call
+                unref() when they are done.
+    */
+    static SkTypeface* CreateFromTypeface(const SkTypeface* family, Style s);
+
+    /** Returns true if the two typefaces reference the same underlying font,
+        even if one is null (which maps to the default font).
+    */
+    static bool Equal(const SkTypeface* facea, const SkTypeface* faceb);
+    
+    /** Returns a 32bit hash value for the typeface. Takes care of mapping null
+        to the default typeface.
+    */
+    static uint32_t Hash(const SkTypeface* face);
+
+    /** Return a new typeface given a file. If the file does not exist, or is
+        not a valid font file, returns null.
+    */
+    static SkTypeface* CreateFromFile(const char path[]);
+    
+    /** Return a new typeface given a stream. If the stream is
+        not a valid font file, returns null. Ownership of the stream is
+        transferred, so the caller must not reference it again.
+    */
+    static SkTypeface* CreateFromStream(SkStream* stream);
+
+    // Serialization
+    void serialize(SkWStream*) const;
+    static SkTypeface* Deserialize(SkStream*);
+
+protected:
+    /** uniqueID must be unique (please!) and non-zero
+    */
+    SkTypeface(Style style, uint32_t uniqueID)
+        : fUniqueID(uniqueID), fStyle(style) {}
+
+private:
+    uint32_t    fUniqueID;
+    Style       fStyle;
+    
+    typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
new file mode 100644
index 0000000..0554c73
--- /dev/null
+++ b/include/core/SkTypes.h
@@ -0,0 +1,377 @@
+/*
+ * 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 SkTypes_DEFINED
+#define SkTypes_DEFINED
+
+#include "SkPreConfig.h"
+#include "SkUserConfig.h"
+#include "SkPostConfig.h"
+
+#ifndef SK_IGNORE_STDINT_DOT_H
+    #include <stdint.h>
+#endif
+
+#include <stdio.h>
+
+/** \file SkTypes.h
+*/
+
+/*
+    memory wrappers to be implemented by the porting layer (platform)
+*/
+
+/** Called internally if we run out of memory. The platform implementation must
+    not return, but should either throw an exception or otherwise exit.
+*/
+extern void  sk_out_of_memory(void);
+/** Called internally if we hit an unrecoverable error.
+    The platform implementation must not return, but should either throw
+    an exception or otherwise exit.
+*/
+extern void  sk_throw(void);
+
+enum {
+    SK_MALLOC_TEMP  = 0x01, //!< hint to sk_malloc that the requested memory will be freed in the scope of the stack frame
+    SK_MALLOC_THROW = 0x02  //!< instructs sk_malloc to call sk_throw if the memory cannot be allocated.
+};
+/** Return a block of memory (at least 4-byte aligned) of at least the
+    specified size. If the requested memory cannot be returned, either
+    return null (if SK_MALLOC_TEMP bit is clear) or call sk_throw()
+    (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free().
+*/
+extern void* sk_malloc_flags(size_t size, unsigned flags);
+/** Same as sk_malloc(), but hard coded to pass SK_MALLOC_THROW as the flag
+*/
+extern void* sk_malloc_throw(size_t size);
+/** Same as standard realloc(), but this one never returns null on failure. It will throw
+    an exception if it fails.
+*/
+extern void* sk_realloc_throw(void* buffer, size_t size);
+/** Free memory returned by sk_malloc(). It is safe to pass null.
+*/
+extern void  sk_free(void*);
+
+///////////////////////////////////////////////////////////////////////
+
+#define SK_INIT_TO_AVOID_WARNING    = 0
+
+#ifndef SkDebugf
+    void SkDebugf(const char format[], ...);
+#endif
+
+#ifdef SK_DEBUG
+    #define SkASSERT(cond)              SK_DEBUGBREAK(cond)
+    #define SkDEBUGCODE(code)           code
+    #define SkDECLAREPARAM(type, var)   , type var
+    #define SkPARAM(var)                , var
+//  #define SkDEBUGF(args       )       SkDebugf##args
+    #define SkDEBUGF(args       )       SkDebugf args
+    #define SkAssertResult(cond)        SkASSERT(cond)
+#else
+    #define SkASSERT(cond)
+    #define SkDEBUGCODE(code)
+    #define SkDEBUGF(args)
+    #define SkDECLAREPARAM(type, var)
+    #define SkPARAM(var)
+
+    // unlike SkASSERT, this guy executes its condition in the non-debug build
+    #define SkAssertResult(cond)        cond
+#endif
+
+///////////////////////////////////////////////////////////////////////
+
+/** Fast type for signed 8 bits. Use for parameter passing and local variables, not for storage
+*/
+typedef int         S8CPU;
+/** Fast type for unsigned 8 bits. Use for parameter passing and local variables, not for storage
+*/
+typedef int         S16CPU;
+/** Fast type for signed 16 bits. Use for parameter passing and local variables, not for storage
+*/
+typedef unsigned    U8CPU;
+/** Fast type for unsigned 16 bits. Use for parameter passing and local variables, not for storage
+*/
+typedef unsigned    U16CPU;
+
+/** Meant to be faster than bool (doesn't promise to be 0 or 1, just 0 or non-zero
+*/
+typedef int         SkBool;
+/** Meant to be a small version of bool, for storage purposes. Will be 0 or 1
+*/
+typedef uint8_t     SkBool8;
+
+#ifdef SK_DEBUG
+    int8_t      SkToS8(long);
+    uint8_t     SkToU8(size_t);
+    int16_t     SkToS16(long);
+    uint16_t    SkToU16(size_t);
+    int32_t     SkToS32(long);
+    uint32_t    SkToU32(size_t);
+#else
+    #define SkToS8(x)   ((int8_t)(x))
+    #define SkToU8(x)   ((uint8_t)(x))
+    #define SkToS16(x)  ((int16_t)(x))
+    #define SkToU16(x)  ((uint16_t)(x))
+    #define SkToS32(x)  ((int32_t)(x))
+    #define SkToU32(x)  ((uint32_t)(x))
+#endif
+
+/** Returns 0 or 1 based on the condition
+*/
+#define SkToBool(cond)  ((cond) != 0)
+
+#define SK_MaxS16   32767
+#define SK_MinS16   -32767
+#define SK_MaxU16   0xFFFF
+#define SK_MinU16   0
+#define SK_MaxS32   0x7FFFFFFF
+#define SK_MinS32   0x80000001
+#define SK_MaxU32   0xFFFFFFFF
+#define SK_MinU32   0
+#define SK_NaN32    0x80000000
+
+#ifndef SK_OFFSETOF
+    #define SK_OFFSETOF(type, field)    ((char*)&(((type*)1)->field) - (char*)1)
+#endif
+
+/** Returns the number of entries in an array (not a pointer)
+*/
+#define SK_ARRAY_COUNT(array)       (sizeof(array) / sizeof(array[0]))
+
+/** Returns x rounded up to a multiple of 2
+*/
+#define SkAlign2(x)     (((x) + 1) >> 1 << 1)
+/** Returns x rounded up to a multiple of 4
+*/
+#define SkAlign4(x)     (((x) + 3) >> 2 << 2)
+
+typedef uint32_t SkFourByteTag;
+#define SkSetFourByteTag(a, b, c, d)    (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+
+/** 32 bit integer to hold a unicode value
+*/
+typedef int32_t SkUnichar;
+/** 32 bit value to hold a millisecond count
+*/
+typedef uint32_t SkMSec;
+/** 1 second measured in milliseconds
+*/
+#define SK_MSec1 1000
+/** maximum representable milliseconds
+*/
+#define SK_MSecMax 0x7FFFFFFF
+/** Returns a < b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0
+*/
+#define SkMSec_LT(a, b)     ((int32_t)(a) - (int32_t)(b) < 0)
+/** Returns a <= b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0
+*/
+#define SkMSec_LE(a, b)     ((int32_t)(a) - (int32_t)(b) <= 0)
+
+
+/****************************************************************************
+    The rest of these only build with C++
+*/
+#ifdef __cplusplus
+
+/** Faster than SkToBool for integral conditions. Returns 0 or 1
+*/
+inline int Sk32ToBool(uint32_t n)
+{
+    return (n | (0-n)) >> 31;
+}
+
+template <typename T> inline void SkTSwap(T& a, T& b)
+{
+    T c(a);
+    a = b;
+    b = c;
+}
+
+inline int32_t SkAbs32(int32_t value)
+{
+#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
+    if (value < 0)
+        value = -value;
+    return value;
+#else
+    int32_t mask = value >> 31;
+    return (value ^ mask) - mask;
+#endif
+}
+
+inline int32_t SkMax32(int32_t a, int32_t b)
+{
+    if (a < b)
+        a = b;
+    return a;
+}
+
+inline int32_t SkMin32(int32_t a, int32_t b)
+{
+    if (a > b)
+        a = b;
+    return a;
+}
+
+inline int32_t SkSign32(int32_t a)
+{
+    return (a >> 31) | ((unsigned) -a >> 31);
+}
+
+inline int32_t SkFastMin32(int32_t value, int32_t max)
+{
+#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
+    if (value > max)
+        value = max;
+    return value;
+#else
+    int diff = max - value;
+    // clear diff if it is negative (clear if value > max)
+    diff &= (diff >> 31);
+    return value + diff;
+#endif
+}
+
+/** Returns signed 32 bit value pinned between min and max, inclusively
+*/
+inline int32_t SkPin32(int32_t value, int32_t min, int32_t max)
+{
+#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
+    if (value < min)
+        value = min;
+    if (value > max)
+        value = max;
+#else
+    if (value < min)
+        value = min;
+    else if (value > max)
+        value = max;
+#endif
+    return value;
+}
+
+inline uint32_t SkSetClearShift(uint32_t bits, bool cond, unsigned shift)
+{
+    SkASSERT((int)cond == 0 || (int)cond == 1);
+    return (bits & ~(1 << shift)) | ((int)cond << shift);
+}
+
+inline uint32_t SkSetClearMask(uint32_t bits, bool cond, uint32_t mask)
+{
+    return cond ? bits | mask : bits & ~mask;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/** \class SkNoncopyable
+
+SkNoncopyable is the base class for objects that may do not want to
+be copied. It hides its copy-constructor and its assignment-operator.
+*/
+class SkNoncopyable {
+public:
+    SkNoncopyable() {}
+    
+private:
+    SkNoncopyable(const SkNoncopyable&);
+    SkNoncopyable& operator=(const SkNoncopyable&);
+};
+
+class SkAutoFree : SkNoncopyable {
+public:
+    SkAutoFree() : fPtr(NULL) {}
+    explicit SkAutoFree(void* ptr) : fPtr(ptr) {}
+    ~SkAutoFree() { sk_free(fPtr); }
+    
+    /** Return the currently allocate buffer, or null
+    */
+    void* get() const { return fPtr; }
+
+    /** Assign a new ptr allocated with sk_malloc (or null), and return the
+        previous ptr. Note it is the caller's responsibility to sk_free the
+        returned ptr.
+    */
+    void* set(void* ptr) {
+        void* prev = fPtr;
+        fPtr = ptr;
+        return prev;
+    }
+    
+    /** Transfer ownership of the current ptr to the caller, setting the
+        internal reference to null. Note the caller is reponsible for calling
+        sk_free on the returned address.
+    */
+    void* detach() { return this->set(NULL); }
+
+    /** Free the current buffer, and set the internal reference to NULL. Same
+        as calling sk_free(detach())
+    */
+    void free() {
+        sk_free(fPtr);
+        fPtr = NULL;
+    }
+
+private:
+    void* fPtr;
+    // illegal
+    SkAutoFree(const SkAutoFree&);
+    SkAutoFree& operator=(const SkAutoFree&);
+};
+
+class SkAutoMalloc : public SkAutoFree {
+public:
+    explicit SkAutoMalloc(size_t size)
+        : SkAutoFree(sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP)) {}
+
+    SkAutoMalloc(size_t size, unsigned flags)
+        : SkAutoFree(sk_malloc_flags(size, flags)) {}
+    SkAutoMalloc() {}
+
+    void* alloc(size_t size,
+                unsigned flags = (SK_MALLOC_THROW | SK_MALLOC_TEMP)) {
+        sk_free(set(sk_malloc_flags(size, flags)));
+        return get();
+    }
+};
+
+template <size_t kSize> class SkAutoSMalloc : SkNoncopyable {
+public:
+    explicit SkAutoSMalloc(size_t size)
+    {
+        if (size <= kSize)
+            fPtr = fStorage;
+        else
+            fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP);
+    }
+    ~SkAutoSMalloc()
+    {
+        if (fPtr != (void*)fStorage)
+            sk_free(fPtr);
+    }
+    void* get() const { return fPtr; }
+private:
+    void*       fPtr;
+    uint32_t    fStorage[(kSize + 3) >> 2];
+    // illegal
+    SkAutoSMalloc(const SkAutoSMalloc&);
+    SkAutoSMalloc& operator=(const SkAutoSMalloc&);
+};
+
+#endif /* C++ */
+
+#endif
+
diff --git a/include/core/SkUnPreMultiply.h b/include/core/SkUnPreMultiply.h
new file mode 100644
index 0000000..4bdb980
--- /dev/null
+++ b/include/core/SkUnPreMultiply.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+
+#ifndef SkUnPreMultiply_DEFINED
+#define SkUnPreMultiply_DEFINED
+
+#include "SkColor.h"
+
+class SkUnPreMultiply {
+public:
+    typedef uint32_t Scale;
+    
+    // index this table with alpha [0..255]
+    static const Scale* GetScaleTable() {
+        return gTable;
+    }
+
+    static Scale GetScale(U8CPU alpha) {
+        SkASSERT(alpha <= 255);
+        return gTable[alpha];
+    }
+    
+    /** Usage:
+     
+        const Scale* table = SkUnPreMultiply::GetScaleTable();
+     
+        for (...) {
+            unsigned a = ...
+            SkUnPreMultiply::Scale scale = table[a];
+     
+            red = SkUnPreMultiply::ApplyScale(scale, red);
+            ...
+            // now red is unpremultiplied
+        }
+    */
+    static U8CPU ApplyScale(Scale scale, U8CPU component) {
+        SkASSERT(component <= 255);
+        return (scale * component + (1 << 23)) >> 24;
+    }
+    
+    static SkColor PMColorToColor(SkPMColor c);
+    
+private:
+    static const uint32_t gTable[256];
+};
+
+#endif
diff --git a/include/core/SkUnitMapper.h b/include/core/SkUnitMapper.h
new file mode 100644
index 0000000..5d1ea35
--- /dev/null
+++ b/include/core/SkUnitMapper.h
@@ -0,0 +1,38 @@
+/*
+ * 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 SkUnitMapper_DEFINED
+#define SkUnitMapper_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+
+#include "SkFlattenable.h"
+
+class SkUnitMapper : public SkFlattenable {
+public:
+    SkUnitMapper() {}
+
+    /** Given a value in [0..0xFFFF], return a value in the same range.
+    */
+    virtual uint16_t mapUnit16(uint16_t x) = 0;
+    
+protected:
+    SkUnitMapper(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
+};
+
+#endif
+
diff --git a/include/core/SkUserConfig.h b/include/core/SkUserConfig.h
new file mode 100644
index 0000000..85cda1c
--- /dev/null
+++ b/include/core/SkUserConfig.h
@@ -0,0 +1,104 @@
+/*
+ * 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 SkUserConfig_DEFINED
+#define SkUserConfig_DEFINED
+
+// for floats
+#ifdef SK_SCALAR_IS_FIXED
+#undef  SK_SCALAR_IS_FIXED
+#endif
+#define SK_SCALAR_IS_FLOAT
+
+// remove the x if you want to force us into SK_DEBUG mode
+#ifdef SK_RELEASE
+    #undef SK_RELEASE
+    #define SK_DEBUG
+#endif
+
+// remove the x if you want to force us into SK_RELEASE mode
+#ifdef SK_DEBUGx
+    #undef SK_DEBUG
+    #define SK_RELEASE
+#endif
+
+#ifdef ANDROID
+    #include <utils/misc.h>
+    #include <assert.h>
+
+    #define SK_CRASH() *(int *)(uintptr_t)0 = 0
+//    #define SK_CRASH() assert(0)
+
+#if 0
+    // force fixed
+    #define SK_SCALAR_IS_FIXED
+    #undef  SK_SCALAR_IS_FLOAT
+#else
+    // force floats
+    #ifdef SK_SCALAR_IS_FIXED
+        #undef  SK_SCALAR_IS_FIXED
+    #endif
+    #define SK_SCALAR_IS_FLOAT
+#endif
+
+    #define SK_CAN_USE_FLOAT
+    #define SK_SOFTWARE_FLOAT
+    #define SkLONGLONG int64_t
+
+    // replace some sw float routines (floor, ceil, etc.)
+    #define SK_USE_FLOATBITS
+
+    #if __BYTE_ORDER == __BIG_ENDIAN
+        #define SK_CPU_BENDIAN
+        #undef  SK_CPU_LENDIAN
+    #else
+        #define SK_CPU_LENDIAN
+        #undef  SK_CPU_BENDIAN
+    #endif
+
+    // define SkDebugf to record file/line
+    #define SkDebugf(...) Android_SkDebugf(__FILE__, __LINE__, \
+                                           __FUNCTION__, __VA_ARGS__)
+    void Android_SkDebugf(const char* file, int line, 
+                          const char* function, const char* format, ...);
+#endif
+
+/*  This file is included before all other headers, except for SkPreConfig.h.
+    That file uses various heuristics to make a "best guess" at settings for
+    the following build defines.
+
+    However, in this file you can override any of those decisions by either
+    defining new symbols, or #undef symbols that were already set.
+*/
+
+// experimental for now
+#define SK_SUPPORT_MIPMAP
+
+#ifdef SK_DEBUG
+    #define SK_SUPPORT_UNITTEST
+    /* Define SK_SIMULATE_FAILED_MALLOC to have
+     * sk_malloc throw an exception. Use this to
+     * detect unhandled memory leaks. */
+    //#define SK_SIMULATE_FAILED_MALLOC
+    //#define SK_FIND_MEMORY_LEAKS
+#endif
+
+#ifdef SK_BUILD_FOR_BREW
+    #include "SkBrewUserConfig.h"
+#endif
+
+#endif
+
diff --git a/include/core/SkUtils.h b/include/core/SkUtils.h
new file mode 100644
index 0000000..f3e3341
--- /dev/null
+++ b/include/core/SkUtils.h
@@ -0,0 +1,140 @@
+/*
+ * 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 SkUtils_DEFINED
+#define SkUtils_DEFINED
+
+#include "SkTypes.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+/** Similar to memset(), but it assigns a 16bit value into the buffer.
+    @param buffer   The memory to have value copied into it
+    @param value    The 16bit value to be copied into buffer
+    @param count    The number of times value should be copied into the buffer.
+*/
+void sk_memset16_portable(uint16_t dst[], uint16_t value, int count);
+
+/** Similar to memset(), but it assigns a 32bit value into the buffer.
+    @param buffer   The memory to have value copied into it
+    @param value    The 32bit value to be copied into buffer
+    @param count    The number of times value should be copied into the buffer.
+*/
+void sk_memset32_portable(uint32_t dst[], uint32_t value, int count);
+
+#ifdef ANDROID
+    #include "cutils/memory.h"
+    
+    #define sk_memset16(dst, value, count)    android_memset16(dst, value, (count) << 1)
+    #define sk_memset32(dst, value, count)    android_memset32(dst, value, (count) << 2)
+#endif
+
+#ifndef sk_memset16
+    #define sk_memset16(dst, value, count)  sk_memset16_portable(dst, value, count)
+#endif
+
+#ifndef sk_memset32
+    #define sk_memset32(dst, value, count)  sk_memset32_portable(dst, value, count)
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////
+
+#define kMaxBytesInUTF8Sequence     4
+
+#ifdef SK_DEBUG
+    int SkUTF8_LeadByteToCount(unsigned c);
+#else
+    #define SkUTF8_LeadByteToCount(c)   ((((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1)
+#endif
+
+inline int SkUTF8_CountUTF8Bytes(const char utf8[])
+{
+    SkASSERT(utf8);
+    return SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
+}
+
+int         SkUTF8_CountUnichars(const char utf8[]);
+int         SkUTF8_CountUnichars(const char utf8[], size_t byteLength);
+SkUnichar   SkUTF8_ToUnichar(const char utf8[]);
+SkUnichar   SkUTF8_NextUnichar(const char**);
+SkUnichar   SkUTF8_PrevUnichar(const char**);
+
+/** Return the number of bytes need to convert a unichar
+    into a utf8 sequence. Will be 1..kMaxBytesInUTF8Sequence,
+    or 0 if uni is illegal.
+*/
+size_t      SkUTF8_FromUnichar(SkUnichar uni, char utf8[] = NULL);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define SkUTF16_IsHighSurrogate(c)  (((c) & 0xFC00) == 0xD800)
+#define SkUTF16_IsLowSurrogate(c)   (((c) & 0xFC00) == 0xDC00)
+
+int SkUTF16_CountUnichars(const uint16_t utf16[]);
+int SkUTF16_CountUnichars(const uint16_t utf16[],
+                                  int numberOf16BitValues);
+// returns the current unichar and then moves past it (*p++)
+SkUnichar SkUTF16_NextUnichar(const uint16_t**);
+// this guy backs up to the previus unichar value, and returns it (*--p)
+SkUnichar SkUTF16_PrevUnichar(const uint16_t**);
+size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t utf16[] = NULL);
+
+size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
+                           char utf8[] = NULL);
+
+class SkUtils {
+public:
+#ifdef SK_DEBUG
+    static void UnitTest();
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkAutoTrace {
+public:
+    /** NOTE: label contents are not copied, just the ptr is
+        retained, so DON'T DELETE IT.
+    */
+    SkAutoTrace(const char label[]) : fLabel(label) {
+        SkDebugf("--- trace: %s Enter\n", fLabel);
+    }
+    ~SkAutoTrace() {
+        SkDebugf("--- trace: %s Leave\n", fLabel);
+    }
+private:
+    const char* fLabel;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkAutoMemoryUsageProbe {
+public:
+    /** Record memory usage in constructor, and dump the result
+        (delta and current total) in the destructor, with the optional
+        label. NOTE: label contents are not copied, just the ptr is
+        retained, so DON'T DELETE IT.
+    */
+    SkAutoMemoryUsageProbe(const char label[]);
+    ~SkAutoMemoryUsageProbe();
+private:
+    const char* fLabel;
+    size_t      fBytesAllocated;
+};
+
+#endif
+
diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h
new file mode 100644
index 0000000..aeeb37d
--- /dev/null
+++ b/include/core/SkWriter32.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkWriter32_DEFINED
+#define SkWriter32_DEFINED
+
+#include "SkTypes.h"
+
+#include "SkScalar.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+
+class SkStream;
+class SkWStream;
+
+class SkWriter32 : SkNoncopyable {
+public:
+    SkWriter32(size_t minSize) {
+        fMinSize = minSize;
+        fSize = 0;
+        fHead = fTail = NULL;
+    }
+    ~SkWriter32();
+
+    bool writeBool(bool value) {
+        this->writeInt(value);
+        return value;
+    }
+    
+    void writeInt(int32_t value) {
+        *(int32_t*)this->reserve(sizeof(value)) = value;
+    }
+    
+    void write8(int32_t value) {
+        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
+    }
+    
+    void write16(int32_t value) {
+        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
+    }
+    
+    void write32(int32_t value) {
+        *(int32_t*)this->reserve(sizeof(value)) = value;
+    }
+    
+    void writeScalar(SkScalar value) {
+        *(SkScalar*)this->reserve(sizeof(value)) = value;
+    }
+    
+    void writePoint(const SkPoint& pt) {
+        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
+    }
+    
+    void writeRect(const SkRect& rect) {
+        *(SkRect*)this->reserve(sizeof(rect)) = rect;
+    }
+    
+    // write count bytes (must be a multiple of 4)
+    void writeMul4(const void* values, size_t size) {
+        SkASSERT(SkAlign4(size) == size);
+        // if we could query how much is avail in the current block, we might
+        // copy that much, and then alloc the rest. That would reduce the waste
+        // in the current block
+        memcpy(this->reserve(size), values, size);
+    }
+    
+    void writePad(const void* src, size_t size);
+    
+    // return the current offset (will always be a multiple of 4)
+    uint32_t  size() const { return fSize; }
+    void      reset();
+    uint32_t* reserve(size_t size); // size MUST be multiple of 4
+    
+    // return the address of the 4byte int at the specified offset (which must
+    // be a multiple of 4. This does not allocate any new space, so the returned
+    // address is only valid for 1 int.
+    uint32_t* peek32(size_t offset);
+    
+    // copy into a single buffer (allocated by caller). Must be at least size()
+    void flatten(void* dst) const;
+    
+    // read from the stream, and write up to length bytes. Return the actual
+    // number of bytes written.
+    size_t readFromStream(SkStream*, size_t length);
+    
+    bool writeToStream(SkWStream*);
+
+private:
+    size_t      fMinSize;
+    uint32_t    fSize;
+    
+    struct Block;
+    Block*  fHead;
+    Block*  fTail;
+    
+    Block* newBlock(size_t bytes);
+};
+
+#endif
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
new file mode 100644
index 0000000..f7e6510
--- /dev/null
+++ b/include/core/SkXfermode.h
@@ -0,0 +1,115 @@
+/*
+ * 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 SkXfermode_DEFINED
+#define SkXfermode_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkColor.h"
+
+/** \class SkXfermode
+
+    SkXfermode is the base class for objects that are called to implement custom
+    "transfer-modes" in the drawing pipeline. The static function Create(Modes)
+    can be called to return an instance of any of the predefined subclasses as
+    specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
+    then objects drawn with that paint have the xfermode applied.
+*/
+class SkXfermode : public SkFlattenable {
+public:
+    SkXfermode() {}
+
+    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
+                          const SkAlpha aa[]);
+    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    
+    enum Coeff {
+        kZero_Coeff,
+        kOne_Coeff,
+        kSC_Coeff,
+        kISC_Coeff,
+        kDC_Coeff,
+        kIDC_Coeff,
+        kSA_Coeff,
+        kISA_Coeff,
+        kDA_Coeff,
+        kIDA_Coeff,
+        
+        kCoeffCount
+    };
+    virtual bool asCoeff(Coeff* src, Coeff* dst);
+
+protected:
+    SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
+    
+    /** The default implementation of xfer32/xfer16/xferA8 in turn call this
+        method, 1 color at a time (upscaled to a SkPMColor). The default
+        implmentation of this method just returns dst. If performance is
+        important, your subclass should override xfer32/xfer16/xferA8 directly.
+        
+        This method will not be called directly by the client, so it need not
+        be implemented if your subclass has overridden xfer32/xfer16/xferA8
+    */
+    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst);
+
+private:
+    typedef SkFlattenable INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** \class SkProcXfermode
+
+    SkProcXfermode is a xfermode that applies the specified proc to its colors.
+    This class is not exported to java.
+*/
+class SkProcXfermode : public SkXfermode {
+public:
+    SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
+
+    // overrides from SkXfermode
+    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
+                          const SkAlpha aa[]);
+    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+
+    // overrides from SkFlattenable
+    virtual Factory getFactory() { return CreateProc; }
+    virtual void    flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkProcXfermode(SkFlattenableReadBuffer&);
+
+private:
+    SkXfermodeProc  fProc;
+    
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkProcXfermode, (buffer)); }
+
+    typedef SkXfermode INHERITED;
+};
+
+#endif
+
diff --git a/include/effects/Sk1DPathEffect.h b/include/effects/Sk1DPathEffect.h
new file mode 100644
index 0000000..db01055
--- /dev/null
+++ b/include/effects/Sk1DPathEffect.h
@@ -0,0 +1,93 @@
+/*
+ * 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 Sk1DPathEffect_DEFINED
+#define Sk1DPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+#include "SkPath.h"
+
+class SkPathMeasure;
+
+//  This class is not exported to java.
+class Sk1DPathEffect : public SkPathEffect {
+public:
+    //  override from SkPathEffect
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+protected:
+    /** Called at the start of each contour, returns the initial offset
+        into that contour.
+    */
+    virtual SkScalar begin(SkScalar contourLength) = 0;
+    /** Called with the current distance along the path, with the current matrix
+        for the point/tangent at the specified distance.
+        Return the distance to travel for the next call. If return <= 0, then that
+        contour is done.
+    */
+    virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) = 0;
+
+private:
+    typedef SkPathEffect INHERITED;
+};
+
+class SkPath1DPathEffect : public Sk1DPathEffect {
+public:
+    enum Style {
+        kTranslate_Style,   // translate the shape to each position
+        kRotate_Style,      // rotate the shape about its center
+        kMorph_Style,       // transform each point, and turn lines into curves
+        
+        kStyleCount
+    };
+    
+    /** Dash by replicating the specified path.
+        @param path The path to replicate (dash)
+        @param advance The space between instances of path
+        @param phase distance (mod advance) along path for its initial position
+        @param style how to transform path at each point (based on the current
+                     position and tangent)
+    */
+    SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style);
+
+    // override from SkPathEffect
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+protected:
+    SkPath1DPathEffect(SkFlattenableReadBuffer& buffer);
+
+    // overrides from Sk1DPathEffect
+    virtual SkScalar begin(SkScalar contourLength);
+    virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&);
+    // overrides from SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory() { return CreateProc; }
+    
+private:
+    SkPath      fPath;          // copied from constructor
+    SkScalar    fAdvance;       // copied from constructor
+    SkScalar    fInitialOffset; // computed from phase
+    Style       fStyle;         // copied from constructor
+    
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkPath1DPathEffect, (buffer));
+    }
+
+    typedef Sk1DPathEffect INHERITED;
+};
+
+
+#endif
diff --git a/include/effects/Sk2DPathEffect.h b/include/effects/Sk2DPathEffect.h
new file mode 100644
index 0000000..6e54d0a
--- /dev/null
+++ b/include/effects/Sk2DPathEffect.h
@@ -0,0 +1,73 @@
+/*
+ * 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 Sk2DPathEffect_DEFINED
+#define Sk2DPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+#include "SkMatrix.h"
+
+//  This class is not exported to java.
+class Sk2DPathEffect : public SkPathEffect {
+public:
+    Sk2DPathEffect(const SkMatrix& mat);
+
+    // overrides
+    //  This method is not exported to java.
+    virtual bool    filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+    // overrides from SkFlattenable
+    //  This method is not exported to java.
+    virtual void    flatten(SkFlattenableWriteBuffer&);
+    
+    //  This method is not exported to java.
+       virtual Factory getFactory();
+
+protected:
+    /** New virtual, to be overridden by subclasses.
+        This is called once from filterPath, and provides the
+        uv parameter bounds for the path. Subsequent calls to
+        next() will receive u and v values within these bounds,
+        and then a call to end() will signal the end of processing.
+    */
+    virtual void begin(const SkIRect& uvBounds, SkPath* dst);
+    virtual void next(const SkPoint& loc, int u, int v, SkPath* dst);
+    virtual void end(SkPath* dst);
+
+    /** Low-level virtual called per span of locations in the u-direction.
+        The default implementation calls next() repeatedly with each
+        location.
+    */
+    virtual void nextSpan(int u, int v, int ucount, SkPath* dst);
+
+    const SkMatrix& getMatrix() const { return fMatrix; }
+
+    // protected so that subclasses can call this during unflattening
+    Sk2DPathEffect(SkFlattenableReadBuffer&);
+
+private:
+    SkMatrix    fMatrix, fInverse;
+    // illegal
+    Sk2DPathEffect(const Sk2DPathEffect&);
+    Sk2DPathEffect& operator=(const Sk2DPathEffect&);
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+
+    friend class Sk2DPathEffectBlitter;
+    typedef SkPathEffect INHERITED;
+};
+
+#endif
diff --git a/include/effects/SkAvoidXfermode.h b/include/effects/SkAvoidXfermode.h
new file mode 100644
index 0000000..32bc049
--- /dev/null
+++ b/include/effects/SkAvoidXfermode.h
@@ -0,0 +1,73 @@
+/*
+ * 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 SkAvoidXfermode_DEFINED
+#define SkAvoidXfermode_DEFINED
+
+#include "SkXfermode.h"
+
+/** \class SkAvoidXfermode
+
+    This xfermode will draw the src everywhere except on top of the specified
+    color.
+*/
+class SkAvoidXfermode : public SkXfermode {
+public:
+    enum Mode {
+        kAvoidColor_Mode,   //!< draw everywhere except on the opColor
+        kTargetColor_Mode   //!< draw only on top of the opColor
+    };
+
+    /** This xfermode will draw the src everywhere except on top of the opColor
+        or, depending on the Mode, draw only on top of the opColor.
+        @param opColor  the color to avoid (or to target depending on Mode).
+                        note: the alpha in opColor is ignored
+        @param tolerance    How closely we compare a pixel to the opColor.
+                            0 - only operate if exact match
+                            255 - maximum gradation (blending) based on how
+                            similar the pixel is to our opColor (max tolerance)
+        @param mode If we should avoid or target the opColor
+    */
+    SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode);
+
+    // overrides from SkXfermode
+    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+    virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
+                          const SkAlpha aa[]);
+    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]);
+
+    // overrides from SkFlattenable
+    virtual Factory getFactory();
+    virtual void flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkAvoidXfermode(SkFlattenableReadBuffer&);
+
+private:
+    SkColor     fOpColor;
+    uint32_t    fDistMul;   // x.14
+    Mode        fMode;
+    
+    static SkFlattenable* Create(SkFlattenableReadBuffer&);
+    
+    typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/include/effects/SkBlurDrawLooper.h b/include/effects/SkBlurDrawLooper.h
new file mode 100644
index 0000000..028b2eb
--- /dev/null
+++ b/include/effects/SkBlurDrawLooper.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkBlurDrawLooper_DEFINED
+#define SkBlurDrawLooper_DEFINED
+
+#include "SkDrawLooper.h"
+#include "SkColor.h"
+
+class SkMaskFilter;
+
+/** \class SkBlurDrawLooper
+    This class draws a shadow of the object (possibly offset), and then draws
+    the original object in its original position.
+    should there be an option to just draw the shadow/blur layer? webkit?
+*/
+class SkBlurDrawLooper : public SkDrawLooper {
+public:
+    SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color);
+    virtual ~SkBlurDrawLooper();
+
+    // overrides from SkDrawLooper
+    virtual void init(SkCanvas*, SkPaint*);
+    virtual bool next();
+    virtual void restore();
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkBlurDrawLooper, (buffer));
+    }
+
+protected:
+    SkBlurDrawLooper(SkFlattenableReadBuffer&);
+    // overrides from SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory() { return CreateProc; }
+
+private:
+    SkCanvas*       fCanvas;
+    SkPaint*        fPaint;
+    SkMaskFilter*   fBlur;
+    SkScalar        fDx, fDy;
+    SkColor         fBlurColor;
+    SkColor         fSavedColor;    // remember the original
+    int             fSaveCount;
+
+    enum State {
+        kBeforeEdge,
+        kAfterEdge,
+        kDone
+    };
+    State   fState;
+    
+    typedef SkDrawLooper INHERITED;
+};
+
+#endif
diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h
new file mode 100644
index 0000000..b90ea5e
--- /dev/null
+++ b/include/effects/SkBlurMaskFilter.h
@@ -0,0 +1,58 @@
+/*
+ * 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 SkBlurMaskFilter_DEFINED
+#define SkBlurMaskFilter_DEFINED
+
+// we include this since our callers will need to at least be able to ref/unref
+#include "SkMaskFilter.h"
+#include "SkScalar.h"
+
+class SkBlurMaskFilter {
+public:
+    enum BlurStyle {
+        kNormal_BlurStyle,  //!< fuzzy inside and outside
+        kSolid_BlurStyle,   //!< solid inside, fuzzy outside
+        kOuter_BlurStyle,   //!< nothing inside, fuzzy outside
+        kInner_BlurStyle,   //!< fuzzy inside, nothing outside
+
+        kBlurStyleCount
+    };
+
+    /** Create a blur maskfilter.
+        @param radius   The radius to extend the blur from the original mask. Must be > 0.
+        @param style    The BlurStyle to use
+        @return The new blur maskfilter
+    */
+    static SkMaskFilter* Create(SkScalar radius, BlurStyle style);
+
+    /** Create an emboss maskfilter
+        @param direction    array of 3 scalars [x, y, z] specifying the direction of the light source
+        @param ambient      0...1 amount of ambient light
+        @param specular     coefficient for specular highlights (e.g. 8)
+        @param blurRadius   amount to blur before applying lighting (e.g. 3)
+        @return the emboss maskfilter
+    */
+    static SkMaskFilter* CreateEmboss(  const SkScalar direction[3],
+                                        SkScalar ambient, SkScalar specular,
+                                        SkScalar blurRadius);
+
+private:
+    SkBlurMaskFilter(); // can't be instantiated
+};
+
+#endif
+
diff --git a/include/effects/SkColorMatrix.h b/include/effects/SkColorMatrix.h
new file mode 100644
index 0000000..cee5d6e
--- /dev/null
+++ b/include/effects/SkColorMatrix.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkColorMatrix_DEFINED
+#define SkColorMatrix_DEFINED
+
+#include "SkScalar.h"
+
+class SkColorMatrix {
+public:
+    SkScalar    fMat[20];
+    
+    void setIdentity();
+    void setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+                  SkScalar aScale = SK_Scalar1);
+    void preScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+                  SkScalar aScale = SK_Scalar1);
+    void postScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+                   SkScalar aScale = SK_Scalar1);
+
+    enum Axis {
+        kR_Axis = 0,
+        kG_Axis = 1,
+        kB_Axis = 2
+    };
+    void setRotate(Axis, SkScalar degrees);
+    void setSinCos(Axis, SkScalar sine, SkScalar cosine);
+    void preRotate(Axis, SkScalar degrees);
+    void postRotate(Axis, SkScalar degrees);
+
+    void setConcat(const SkColorMatrix& a, const SkColorMatrix& b);
+    void preConcat(const SkColorMatrix& mat) { this->setConcat(*this, mat); }
+    void postConcat(const SkColorMatrix& mat) { this->setConcat(mat, *this); }
+
+    void setSaturation(SkScalar sat);
+    void setRGB2YUV();
+    void setYUV2RGB();
+};
+
+#endif
diff --git a/include/effects/SkColorMatrixFilter.h b/include/effects/SkColorMatrixFilter.h
new file mode 100644
index 0000000..f9194df
--- /dev/null
+++ b/include/effects/SkColorMatrixFilter.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkColorMatrixFilter_DEFINED
+#define SkColorMatrixFilter_DEFINED
+
+#include "SkColorFilter.h"
+#include "SkColorMatrix.h"
+
+class SkColorMatrixFilter : public SkColorFilter {
+public:
+    SkColorMatrixFilter();
+    explicit SkColorMatrixFilter(const SkColorMatrix&);
+    SkColorMatrixFilter(const SkScalar array[20]);
+    
+    void setMatrix(const SkColorMatrix&);
+    void setArray(const SkScalar array[20]);
+    
+    // overrides from SkColorFilter
+    virtual void filterSpan(const SkPMColor src[], int count, SkPMColor[]);
+    virtual void filterSpan16(const uint16_t src[], int count, uint16_t[]);
+    virtual uint32_t getFlags();
+    
+    // overrides for SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& buffer);
+
+    struct State {
+        int32_t fArray[20];
+        int     fShift;
+        int32_t fResult[4];
+    };
+
+protected:
+    // overrides for SkFlattenable
+    virtual Factory getFactory();
+    
+    SkColorMatrixFilter(SkFlattenableReadBuffer& buffer);
+    
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer);
+
+    typedef void (*Proc)(State*, unsigned r, unsigned g, unsigned b,
+                         unsigned a);
+
+    Proc        fProc;
+    State       fState;
+    uint32_t    fFlags;
+    
+    void setup(const SkScalar array[20]);
+    
+    typedef SkColorFilter INHERITED;
+};
+
+#endif
diff --git a/include/effects/SkCornerPathEffect.h b/include/effects/SkCornerPathEffect.h
new file mode 100644
index 0000000..a459478
--- /dev/null
+++ b/include/effects/SkCornerPathEffect.h
@@ -0,0 +1,61 @@
+/*
+ * 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 SkCornerPathEffect_DEFINED
+#define SkCornerPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+
+/** \class SkCornerPathEffect
+
+    SkCornerPathEffect is a subclass of SkPathEffect that can turn sharp corners
+    into various treatments (e.g. rounded corners)
+*/
+class SkCornerPathEffect : public SkPathEffect {
+public:
+    /** radius must be > 0 to have an effect. It specifies the distance from each corner
+        that should be "rounded".
+    */
+    SkCornerPathEffect(SkScalar radius);
+    virtual ~SkCornerPathEffect();
+
+    // overrides for SkPathEffect
+    //  This method is not exported to java.
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+    // overrides for SkFlattenable
+    //  This method is not exported to java.
+    virtual Factory getFactory();
+    //  This method is not exported to java.
+    virtual void flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkCornerPathEffect(SkFlattenableReadBuffer&);
+
+private:
+    SkScalar    fRadius;
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+    
+    // illegal
+    SkCornerPathEffect(const SkCornerPathEffect&);
+    SkCornerPathEffect& operator=(const SkCornerPathEffect&);
+    
+    typedef SkPathEffect INHERITED;
+};
+
+#endif
+
diff --git a/include/effects/SkDashPathEffect.h b/include/effects/SkDashPathEffect.h
new file mode 100644
index 0000000..cc414e3
--- /dev/null
+++ b/include/effects/SkDashPathEffect.h
@@ -0,0 +1,65 @@
+/*
+ * 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 SkDashPathEffect_DEFINED
+#define SkDashPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+
+/** \class SkDashPathEffect
+
+    SkDashPathEffect is a subclass of SkPathEffect that implements dashing
+*/
+class SkDashPathEffect : public SkPathEffect {
+public:
+    /** The intervals array must contain an even number of entries (>=2), with the even
+        indices specifying the "on" intervals, and the odd indices specifying the "off"
+        intervals. phase is an offset into the intervals array (mod the sum of all of the
+        intervals).
+        Note: only affects framed paths
+    */
+    SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase, bool scaleToFit = false);
+    virtual ~SkDashPathEffect();
+
+    // overrides for SkPathEffect
+    //  This method is not exported to java.
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+    // overrides for SkFlattenable
+    //  This method is not exported to java.
+    virtual Factory getFactory();
+    //  This method is not exported to java.
+    virtual void flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkDashPathEffect(SkFlattenableReadBuffer&);
+    
+private:
+    SkScalar*   fIntervals;
+    int32_t     fCount;
+    // computed from phase
+    SkScalar    fInitialDashLength;
+    int32_t     fInitialDashIndex;
+    SkScalar    fIntervalLength;
+    bool        fScaleToFit;
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+
+    typedef SkPathEffect INHERITED;
+};
+
+#endif
+
diff --git a/include/effects/SkDiscretePathEffect.h b/include/effects/SkDiscretePathEffect.h
new file mode 100644
index 0000000..2950950
--- /dev/null
+++ b/include/effects/SkDiscretePathEffect.h
@@ -0,0 +1,56 @@
+/*
+ * 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 SkDiscretePathEffect_DEFINED
+#define SkDiscretePathEffect_DEFINED
+
+#include "SkPathEffect.h"
+
+/** \class SkDiscretePathEffect
+
+    This path effect chops a path into discrete segments, and randomly displaces them.
+*/
+class SkDiscretePathEffect : public SkPathEffect {
+public:
+    /** Break the path into segments of segLength length, and randomly move the endpoints
+        away from the original path by a maximum of deviation.
+        Note: works on filled or framed paths
+    */
+    SkDiscretePathEffect(SkScalar segLength, SkScalar deviation);
+
+    // overrides for SkPathEffect
+    //  This method is not exported to java.
+    virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+    // overrides for SkFlattenable
+    //  This method is not exported to java.
+    virtual Factory getFactory();
+    //  This method is not exported to java.
+    virtual void flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkDiscretePathEffect(SkFlattenableReadBuffer&);
+
+private:
+    SkScalar fSegLength, fPerterb;
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+    
+    typedef SkPathEffect INHERITED;
+};
+
+#endif
+
diff --git a/include/effects/SkDrawExtraPathEffect.h b/include/effects/SkDrawExtraPathEffect.h
new file mode 100644
index 0000000..65e255aa
--- /dev/null
+++ b/include/effects/SkDrawExtraPathEffect.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SK_DRAW_EXTRA_PATH_EFFECT_H
+#define SK_DRAW_EXTRA_PATH_EFFECT_H
+class SkAnimator;
+void InitializeSkExtraPathEffects(SkAnimator* animator);
+#endif
+
diff --git a/include/effects/SkEmbossMaskFilter.h b/include/effects/SkEmbossMaskFilter.h
new file mode 100644
index 0000000..042a2a6
--- /dev/null
+++ b/include/effects/SkEmbossMaskFilter.h
@@ -0,0 +1,63 @@
+/*
+ * 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 SkEmbossMaskFilter_DEFINED
+#define SkEmbossMaskFilter_DEFINED
+
+#include "SkMaskFilter.h"
+
+/** \class SkEmbossMaskFilter
+
+    This mask filter creates a 3D emboss look, by specifying a light and blur amount.
+*/
+class SkEmbossMaskFilter : public SkMaskFilter {
+public:
+    struct Light {
+        SkScalar    fDirection[3];  // x,y,z
+        uint16_t    fPad;
+        uint8_t     fAmbient;
+        uint8_t     fSpecular;      // exponent, 4.4 right now
+    };
+
+    SkEmbossMaskFilter(const Light& light, SkScalar blurRadius);
+
+    // overrides from SkMaskFilter
+    //  This method is not exported to java.
+    virtual SkMask::Format getFormat();
+    //  This method is not exported to java.
+    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin);
+
+    // overrides from SkFlattenable
+
+    //  This method is not exported to java.
+    virtual Factory getFactory();
+    //  This method is not exported to java.
+    virtual void flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkEmbossMaskFilter(SkFlattenableReadBuffer&);
+
+private:
+    Light       fLight;
+    SkScalar    fBlurRadius;
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+    
+    typedef SkMaskFilter INHERITED;
+};
+
+#endif
+
diff --git a/include/effects/SkGradientShader.h b/include/effects/SkGradientShader.h
new file mode 100644
index 0000000..9a8696c
--- /dev/null
+++ b/include/effects/SkGradientShader.h
@@ -0,0 +1,97 @@
+/*
+ * 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 SkGradientShader_DEFINED
+#define SkGradientShader_DEFINED
+
+#include "SkShader.h"
+
+class SkUnitMapper;
+
+/** \class SkGradientShader
+
+    SkGradientShader hosts factories for creating subclasses of SkShader that
+    render linear and radial gradients.
+*/
+class SkGradientShader {
+public:
+    /** Returns a shader that generates a linear gradient between the two
+        specified points.
+        <p />
+        CreateLinear returns a shader with a reference count of 1.
+        The caller should decrement the shader's reference count when done with the shader.
+        It is an error for count to be < 2.
+        @param  pts The start and end points for the gradient.
+        @param  colors  The array[count] of colors, to be distributed between the two points
+        @param  pos     May be NULL. array[count] of SkScalars, or NULL, of the relative position of
+                        each corresponding color in the colors array. If this is NULL,
+                        the the colors are distributed evenly between the start and end point.
+                        If this is not null, the values must begin with 0, end with 1.0, and
+                        intermediate values must be strictly increasing.
+        @param  count   Must be >=2. The number of colors (and pos if not NULL) entries. 
+        @param  mode    The tiling mode
+        @param  mapper  May be NULL. Callback to modify the spread of the colors.
+    */
+    static SkShader* CreateLinear(  const SkPoint pts[2],
+                                    const SkColor colors[], const SkScalar pos[], int count,
+                                    SkShader::TileMode mode,
+                                    SkUnitMapper* mapper = NULL);
+
+    /** Returns a shader that generates a radial gradient given the center and radius.
+        <p />
+        CreateRadial returns a shader with a reference count of 1.
+        The caller should decrement the shader's reference count when done with the shader.
+        It is an error for colorCount to be < 2, or for radius to be <= 0.
+        @param  center  The center of the circle for this gradient
+        @param  radius  Must be positive. The radius of the circle for this gradient
+        @param  colors  The array[count] of colors, to be distributed between the center and edge of the circle
+        @param  pos     May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
+                        each corresponding color in the colors array. If this is NULL,
+                        the the colors are distributed evenly between the center and edge of the circle.
+                        If this is not null, the values must begin with 0, end with 1.0, and
+                        intermediate values must be strictly increasing.
+        @param  count   Must be >= 2. The number of colors (and pos if not NULL) entries
+        @param  mode    The tiling mode
+        @param  mapper  May be NULL. Callback to modify the spread of the colors.
+    */
+    static SkShader* CreateRadial(  const SkPoint& center, SkScalar radius,
+                                    const SkColor colors[], const SkScalar pos[], int count,
+                                    SkShader::TileMode mode,
+                                    SkUnitMapper* mapper = NULL);
+
+    /** Returns a shader that generates a sweep gradient given a center.
+        <p />
+        CreateRadial returns a shader with a reference count of 1.
+        The caller should decrement the shader's reference count when done with the shader.
+        It is an error for colorCount to be < 2.
+        @param  cx      The X coordinate of the center of the sweep
+        @param  cx      The Y coordinate of the center of the sweep
+        @param  colors  The array[count] of colors, to be distributed around the center.
+        @param  pos     May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
+                        each corresponding color in the colors array. If this is NULL,
+                        the the colors are distributed evenly between the center and edge of the circle.
+                        If this is not null, the values must begin with 0, end with 1.0, and
+                        intermediate values must be strictly increasing.
+        @param  count   Must be >= 2. The number of colors (and pos if not NULL) entries
+        @param  mapper  May be NULL. Callback to modify the spread of the colors.
+    */
+    static SkShader* CreateSweep(SkScalar cx, SkScalar cy,
+                                 const SkColor colors[], const SkScalar pos[],
+                                 int count, SkUnitMapper* mapper = NULL);
+};
+
+#endif
+
diff --git a/include/effects/SkKernel33MaskFilter.h b/include/effects/SkKernel33MaskFilter.h
new file mode 100644
index 0000000..84136e2
--- /dev/null
+++ b/include/effects/SkKernel33MaskFilter.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkKernel33MaskFilter_DEFINED
+#define SkKernel33MaskFilter_DEFINED
+
+#include "SkMaskFilter.h"
+
+class SkKernel33ProcMaskFilter : public SkMaskFilter {
+public:
+    SkKernel33ProcMaskFilter(unsigned percent256 = 256)
+        : fPercent256(percent256) {}
+
+    virtual uint8_t computeValue(uint8_t* const* srcRows) = 0;
+    
+    // overrides from SkMaskFilter
+    virtual SkMask::Format getFormat();
+    virtual bool filterMask(SkMask*, const SkMask&, const SkMatrix&, SkIPoint*);
+
+    // overrides from SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& wb);
+
+protected:
+    SkKernel33ProcMaskFilter(SkFlattenableReadBuffer& rb);
+
+private:
+    int fPercent256;
+    
+    typedef SkMaskFilter INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkKernel33MaskFilter : public SkKernel33ProcMaskFilter {
+public:
+    SkKernel33MaskFilter(const int coeff[3][3], int shift, int percent256 = 256)
+        : SkKernel33ProcMaskFilter(percent256)
+    {
+        memcpy(fKernel, coeff, 9 * sizeof(int));
+        fShift = shift;
+    }
+    
+    // override from SkKernel33ProcMaskFilter
+    virtual uint8_t computeValue(uint8_t* const* srcRows);
+    
+    // overrides from SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& wb);
+    virtual Factory getFactory();
+    
+private:
+    int fKernel[3][3];
+    int fShift;
+
+    SkKernel33MaskFilter(SkFlattenableReadBuffer& rb);
+    static SkFlattenable* Create(SkFlattenableReadBuffer& rb);
+    
+    typedef SkKernel33ProcMaskFilter INHERITED;
+};
+
+#endif
diff --git a/include/effects/SkLayerDrawLooper.h b/include/effects/SkLayerDrawLooper.h
new file mode 100644
index 0000000..670ac23
--- /dev/null
+++ b/include/effects/SkLayerDrawLooper.h
@@ -0,0 +1,70 @@
+#ifndef SkLayerDrawLooper_DEFINED
+#define SkLayerDrawLooper_DEFINED
+
+#include "SkDrawLooper.h"
+
+struct SkPoint;
+
+class SkLayerDrawLooper : public SkDrawLooper {
+public:
+            SkLayerDrawLooper();
+    virtual ~SkLayerDrawLooper();
+    
+    /** Call for each layer you want to add (from top to bottom).
+        This returns a paint you can modify, but that ptr is only valid until
+        the next call made to this object.
+     */
+    SkPaint* addLayer(SkScalar dx, SkScalar dy);
+    
+    /** Helper for addLayer() which passes (0, 0) for the offset parameters
+     */
+    SkPaint* addLayer() {
+        return this->addLayer(0, 0);
+    }
+    
+    // overrides from SkDrawLooper
+    virtual void init(SkCanvas*, SkPaint*);
+    virtual bool next();
+    virtual void restore();
+
+    // must be public for Registrar :(
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkLayerDrawLooper, (buffer));
+    }
+    
+protected:
+    SkLayerDrawLooper(SkFlattenableReadBuffer&);
+
+    // overrides from SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory() { return CreateProc; }
+    
+private:
+    struct Rec {
+        Rec*    fNext;
+        SkPaint fPaint;
+        SkPoint fOffset;
+        
+        static Rec* Reverse(Rec*);
+    };
+    Rec*    fRecs;
+    int     fCount;
+    
+    struct Iter {
+        SkPaint     fSavedPaint;
+        SkPaint*    fPaint;
+        SkCanvas*   fCanvas;
+        Rec*        fRec;
+    };
+    Iter    fIter;
+    
+    class MyRegistrar : public SkFlattenable::Registrar {
+    public:
+        MyRegistrar();
+    };
+    
+    typedef SkDrawLooper INHERITED;
+};
+
+
+#endif
diff --git a/include/effects/SkLayerRasterizer.h b/include/effects/SkLayerRasterizer.h
new file mode 100644
index 0000000..820f6fc
--- /dev/null
+++ b/include/effects/SkLayerRasterizer.h
@@ -0,0 +1,63 @@
+/*
+ * 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 SkLayerRasterizer_DEFINED
+#define SkLayerRasterizer_DEFINED
+
+#include "SkRasterizer.h"
+#include "SkDeque.h"
+#include "SkScalar.h"
+
+class SkPaint;
+
+class SkLayerRasterizer : public SkRasterizer {
+public:
+            SkLayerRasterizer();
+    virtual ~SkLayerRasterizer();
+    
+    void addLayer(const SkPaint& paint)
+    {
+        this->addLayer(paint, 0, 0);
+    }
+
+	/**	Add a new layer (above any previous layers) to the rasterizer.
+		The layer will extract those fields that affect the mask from
+		the specified paint, but will not retain a reference to the paint
+		object itself, so it may be reused without danger of side-effects.
+	*/
+    void addLayer(const SkPaint& paint, SkScalar dx, SkScalar dy);
+
+    // overrides from SkFlattenable
+    virtual Factory getFactory();
+    virtual void    flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    SkLayerRasterizer(SkFlattenableReadBuffer&);
+
+    // override from SkRasterizer
+    virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix,
+                             const SkIRect* clipBounds,
+                             SkMask* mask, SkMask::CreateMode mode);
+
+private:
+    SkDeque fLayers;
+    
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+
+    typedef SkRasterizer INHERITED;
+};
+
+#endif
diff --git a/include/effects/SkPaintFlagsDrawFilter.h b/include/effects/SkPaintFlagsDrawFilter.h
new file mode 100644
index 0000000..941be24
--- /dev/null
+++ b/include/effects/SkPaintFlagsDrawFilter.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPaintFlagsDrawFilter_DEFINED
+#define SkPaintFlagsDrawFilter_DEFINED
+
+#include "SkDrawFilter.h"
+
+class SkPaintFlagsDrawFilter : public SkDrawFilter {
+public:
+    SkPaintFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags);
+    
+    // overrides
+    virtual bool filter(SkCanvas*, SkPaint*, Type);
+    virtual void restore(SkCanvas*, SkPaint*, Type);
+    
+private:
+    uint32_t    fPrevFlags;     // local cache for filter/restore
+    uint16_t    fClearFlags;    // user specified
+    uint16_t    fSetFlags;      // user specified
+};
+
+#endif
+
diff --git a/include/effects/SkPixelXorXfermode.h b/include/effects/SkPixelXorXfermode.h
new file mode 100644
index 0000000..369e0e5
--- /dev/null
+++ b/include/effects/SkPixelXorXfermode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPixelXorXfermode_DEFINED
+#define SkPixelXorXfermode_DEFINED
+
+#include "SkXfermode.h"
+
+/** SkPixelXorXfermode implements a simple pixel xor (op ^ src ^ dst).
+    This transformation does not follow premultiplied conventions, therefore
+    this proc *always* returns an opaque color (alpha == 255). Thus it is
+    not really usefull for operating on blended colors.
+*/
+class SkPixelXorXfermode : public SkXfermode {
+public:
+    SkPixelXorXfermode(SkColor opColor) : fOpColor(opColor) {}
+
+    // override from SkFlattenable
+    virtual Factory getFactory();
+    virtual void flatten(SkFlattenableWriteBuffer&);
+
+protected:
+    // override from SkXfermode
+    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst);
+
+private:
+    SkColor fOpColor;
+
+    SkPixelXorXfermode(SkFlattenableReadBuffer& rb);
+    // our private factory
+    static SkFlattenable* Create(SkFlattenableReadBuffer&);
+
+    typedef SkXfermode INHERITED;
+};
+
+#endif
+
diff --git a/include/effects/SkTransparentShader.h b/include/effects/SkTransparentShader.h
new file mode 100644
index 0000000..8bc60ff
--- /dev/null
+++ b/include/effects/SkTransparentShader.h
@@ -0,0 +1,55 @@
+/*
+ * 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 SkTransparentShader_DEFINED
+#define SkTransparentShader_DEFINED
+
+#include "SkShader.h"
+
+class SkTransparentShader : public SkShader {
+public:
+    SkTransparentShader() {}
+    virtual uint32_t getFlags();
+    virtual bool    setContext( const SkBitmap& device,
+                                const SkPaint& paint,
+                                const SkMatrix& matrix);
+    virtual void    shadeSpan(int x, int y, SkPMColor[], int count);
+    virtual void    shadeSpan16(int x, int y, uint16_t span[], int count);
+
+    // overrides for SkFlattenable
+    virtual Factory getFactory() { return Create; }
+    virtual void flatten(SkFlattenableWriteBuffer& buffer)
+    {
+        this->INHERITED::flatten(buffer);
+    }
+        
+private:
+    // these are a cache from the call to setContext()
+    const SkBitmap* fDevice;
+    uint8_t         fAlpha;
+
+    SkTransparentShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+    
+    static SkFlattenable* Create(SkFlattenableReadBuffer& buffer)
+    {
+        return SkNEW_ARGS(SkTransparentShader, (buffer));
+    }
+
+    typedef SkShader INHERITED;
+};
+
+#endif
+
diff --git a/include/images/SkFlipPixelRef.h b/include/images/SkFlipPixelRef.h
new file mode 100644
index 0000000..3b4e97a
--- /dev/null
+++ b/include/images/SkFlipPixelRef.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkFlipPixelRef_DEFINED
+#define SkFlipPixelRef_DEFINED
+
+#include "SkBitmap.h"
+#include "SkPageFlipper.h"
+#include "SkPixelRef.h"
+#include "SkThread.h"
+
+class SkRegion;
+
+class SkFlipPixelRef : public SkPixelRef {
+public:
+            SkFlipPixelRef(SkBitmap::Config, int width, int height);
+    virtual ~SkFlipPixelRef();
+    
+    bool isDirty() const { return fFlipper.isDirty(); }
+    const SkRegion& dirtyRgn() const { return fFlipper.dirtyRgn(); }
+
+    void inval() { fFlipper.inval(); }
+    void inval(const SkIRect& rect) { fFlipper.inval(rect); }
+    void inval(const SkRegion& rgn) { fFlipper.inval(rgn); }
+    void inval(const SkRect& r, bool doAA) { fFlipper.inval(r, doAA); }
+
+    const SkRegion& beginUpdate(SkBitmap* device);
+    void endUpdate();
+    
+private:
+    void getFrontBack(const void** front, void** back) const {
+        if (front) {
+            *front = fPage0;
+        }
+        if (back) {
+            *back = fPage1;
+        }
+    }
+
+    void    swapPages();
+
+    // Helper to copy pixels from srcAddr to the dst bitmap, clipped to clip.
+    // srcAddr points to memory with the same config as dst.
+    static void CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
+                                 const void* srcAddr);
+
+    // serialization
+
+public:
+    virtual Factory getFactory() const { return Create; }
+    virtual void flatten(SkFlattenableWriteBuffer&) const;
+    static SkPixelRef* Create(SkFlattenableReadBuffer& buffer);
+    
+protected:
+    virtual void* onLockPixels(SkColorTable**);
+    virtual void onUnlockPixels();
+
+    SkFlipPixelRef(SkFlattenableReadBuffer&);
+
+private:
+    SkMutex         fMutex;
+    SkPageFlipper   fFlipper;
+    
+    void*           fStorage;
+    void*           fPage0; // points into fStorage;
+    void*           fPage1; // points into fStorage;
+    size_t          fSize;  // size of 1 page. fStorage holds 2 pages
+    SkBitmap::Config fConfig;
+
+    typedef SkPixelRef INHERITED;
+};
+
+class SkAutoFlipUpdate : SkNoncopyable {
+public:
+    SkAutoFlipUpdate(SkFlipPixelRef* ref) : fRef(ref) {
+        fDirty = &ref->beginUpdate(&fBitmap);
+    }
+    ~SkAutoFlipUpdate() {
+        if (fRef) {
+            fRef->endUpdate();
+        }
+    }
+    
+    const SkBitmap& bitmap() const { return fBitmap; }
+    const SkRegion& dirty() const { return *fDirty; }
+    
+    // optional. This gets automatically called in the destructor (only once)
+    void endUpdate() {
+        if (fRef) {
+            fRef->endUpdate();
+            fRef = NULL;
+        }
+    }
+
+private:
+    SkFlipPixelRef* fRef;
+    SkBitmap        fBitmap;
+    const SkRegion* fDirty;
+};
+
+#endif
diff --git a/include/images/SkImageDecoder.h b/include/images/SkImageDecoder.h
new file mode 100644
index 0000000..4a18cab
--- /dev/null
+++ b/include/images/SkImageDecoder.h
@@ -0,0 +1,301 @@
+/*
+ * 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 SkImageDecoder_DEFINED
+#define SkImageDecoder_DEFINED
+
+#include "SkBitmap.h"
+#include "SkRefCnt.h"
+
+class SkStream;
+
+/** \class SkImageDecoder
+
+    Base class for decoding compressed images into a SkBitmap
+*/
+class SkImageDecoder {
+public:
+    virtual ~SkImageDecoder();
+    
+    enum Format {
+        kUnknown_Format,
+        kBMP_Format,
+        kGIF_Format,
+        kICO_Format,
+        kJPEG_Format,
+        kPNG_Format,
+        kWBMP_Format,
+        
+        kLastKnownFormat = kWBMP_Format
+    };
+        
+    /** Return the compressed data's format (see Format enum)
+    */
+    virtual Format getFormat() const;
+
+    /** Returns true if the decoder should try to dither the resulting image.
+        The default setting is true.
+    */
+    bool getDitherImage() const { return fDitherImage; }
+    
+    /** Set to true if the the decoder should try to dither the resulting image.
+        The default setting is true.
+    */
+    void setDitherImage(bool dither) { fDitherImage = dither; }
+
+    /** \class Peeker
+    
+        Base class for optional callbacks to retrieve meta/chunk data out of
+        an image as it is being decoded.
+    */
+    class Peeker : public SkRefCnt {
+    public:
+        /** Return true to continue decoding, or false to indicate an error, which
+            will cause the decoder to not return the image.
+        */
+        virtual bool peek(const char tag[], const void* data, size_t length) = 0;
+    };
+
+    Peeker* getPeeker() const { return fPeeker; }
+    Peeker* setPeeker(Peeker*);
+    
+    /** \class Peeker
+    
+        Base class for optional callbacks to retrieve meta/chunk data out of
+        an image as it is being decoded.
+    */
+    class Chooser : public SkRefCnt {
+    public:
+        virtual void begin(int count) {}
+        virtual void inspect(int index, SkBitmap::Config config, int width, int height) {}
+        /** Return the index of the subimage you want, or -1 to choose none of them.
+        */
+        virtual int choose() = 0;
+    };
+
+    Chooser* getChooser() const { return fChooser; }
+    Chooser* setChooser(Chooser*);
+
+    SkBitmap::Allocator* getAllocator() const { return fAllocator; }
+    SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
+
+    // sample-size, if set to > 1, tells the decoder to return a smaller than
+    // original bitmap, sampling 1 pixel for every size pixels. e.g. if sample
+    // size is set to 3, then the returned bitmap will be 1/3 as wide and high,
+    // and will contain 1/9 as many pixels as the original.
+    // Note: this is a hint, and the codec may choose to ignore this, or only
+    // approximate the sample size.
+    int getSampleSize() const { return fSampleSize; }
+    void setSampleSize(int size);
+    
+    /** Reset the sampleSize to its default of 1
+     */
+    void resetSampleSize() { this->setSampleSize(1); }
+
+    /** Decoding is synchronous, but for long decodes, a different thread can
+        call this method safely. This sets a state that the decoders will
+        periodically check, and if they see it changed to cancel, they will
+        cancel. This will result in decode() returning false. However, there is
+        no guarantee that the decoder will see the state change in time, so
+        it is possible that cancelDecode() will be called, but will be ignored
+        and decode() will return true (assuming no other problems were
+        encountered).
+     
+        This state is automatically reset at the beginning of decode().
+     */
+    void cancelDecode() {
+        // now the subclass must query shouldCancelDecode() to be informed
+        // of the request
+        fShouldCancelDecode = true;
+    }
+
+    /** Passed to the decode method. If kDecodeBounds_Mode is passed, then
+        only the bitmap's width/height/config need be set. If kDecodePixels_Mode
+        is passed, then the bitmap must have pixels or a pixelRef.
+    */
+    enum Mode {
+        kDecodeBounds_Mode, //!< only return width/height/config in bitmap
+        kDecodePixels_Mode  //!< return entire bitmap (including pixels)
+    };
+    
+    /** Given a stream, decode it into the specified bitmap.
+        If the decoder can decompress the image, it calls bitmap.setConfig(),
+        and then if the Mode is kDecodePixels_Mode, call allocPixelRef(),
+        which will allocated a pixelRef. To access the pixel memory, the codec
+        needs to call lockPixels/unlockPixels on the
+        bitmap. It can then set the pixels with the decompressed image.
+        If the image cannot be decompressed, return false.
+        
+        note: document use of Allocator, Peeker and Chooser 
+    */
+    bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
+
+    /** Given a stream, this will try to find an appropriate decoder object.
+        If none is found, the method returns NULL.
+    */
+    static SkImageDecoder* Factory(SkStream*);
+    
+    /** Decode the image stored in the specified file, and store the result
+        in bitmap. Return true for success or false on failure.
+
+        If pref is kNo_Config, then the decoder is free to choose the most natural
+        config given the image data. If pref something other than kNo_Config,
+        the decoder will attempt to decode the image into that format, unless
+        there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
+        config does not support that), in which case the decoder will choose a
+        closest match configuration.
+    */
+    static bool DecodeFile(const char file[], SkBitmap* bitmap,
+                             SkBitmap::Config prefConfig, Mode);
+    static bool DecodeFile(const char file[], SkBitmap* bitmap)
+    {
+        return DecodeFile(file, bitmap, SkBitmap::kNo_Config, kDecodePixels_Mode);
+    }
+    /** Decode the image stored in the specified memory buffer, and store the
+        result in bitmap. Return true for success or false on failure.
+
+        If pref is kNo_Config, then the decoder is free to choose the most natural
+        config given the image data. If pref something other than kNo_Config,
+        the decoder will attempt to decode the image into that format, unless
+        there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
+        config does not support that), in which case the decoder will choose a
+        closest match configuration.
+    */
+    static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap,
+                             SkBitmap::Config prefConfig, Mode);
+    static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap)
+    {
+        return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config,
+                            kDecodePixels_Mode);
+    }
+    /** Decode the image stored in the specified SkStream, and store the result
+        in bitmap. Return true for success or false on failure.
+
+        If pref is kNo_Config, then the decoder is free to choose the most
+        natural config given the image data. If pref something other than
+        kNo_Config, the decoder will attempt to decode the image into that
+        format, unless there is a conflict (e.g. the image has per-pixel alpha
+        and the bitmap's config does not support that), in which case the
+        decoder will choose a closest match configuration.
+    */
+    static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
+                             SkBitmap::Config prefConfig, Mode);
+    static bool DecodeStream(SkStream* stream, SkBitmap* bitmap)
+    {
+        return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
+                            kDecodePixels_Mode);
+    }
+    
+    /*  Given a format, return true if there is a currently installed decoder
+        for that format. Since a given build may not include all codecs (to save
+        code-size), this may return false.
+    */
+    static bool SupportsFormat(Format);
+
+    /** Return the default config for the running device.
+        Currently this used as a suggestion to image decoders that need to guess
+        what config they should decode into.
+        Default is kNo_Config, but this can be changed with SetDeviceConfig()
+    */
+    static SkBitmap::Config GetDeviceConfig();
+    /** Set the default config for the running device.
+        Currently this used as a suggestion to image decoders that need to guess
+        what config they should decode into.
+        Default is kNo_Config.
+        This can be queried with GetDeviceConfig()
+    */
+    static void SetDeviceConfig(SkBitmap::Config);
+
+  /** @cond UNIT_TEST */
+    SkDEBUGCODE(static void UnitTest();)
+  /** @endcond */
+
+protected:
+    // must be overridden in subclasses. This guy is called by decode(...)
+    virtual bool onDecode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref,
+                          Mode) = 0;
+
+    /** Can be queried from within onDecode, to see if the user (possibly in
+        a different thread) has requested the decode to cancel. If this returns
+        true, your onDecode() should stop and return false.
+        Each subclass needs to decide how often it can query this, to balance
+        responsiveness with performance.
+     
+        Calling this outside of onDecode() may return undefined values.
+     */
+
+public:
+    bool shouldCancelDecode() const { return fShouldCancelDecode; }
+
+protected:    
+    SkImageDecoder();
+
+    // helper function for decoders to handle the (common) case where there is only
+    // once choice available in the image file.
+    bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const;
+
+    /*  Helper for subclasses. Call this to allocate the pixel memory given the bitmap's
+        width/height/rowbytes/config. Returns true on success. This method handles checking
+        for an optional Allocator.
+    */
+    bool allocPixelRef(SkBitmap*, SkColorTable*) const;
+
+private:
+    Peeker*                 fPeeker;
+    Chooser*                fChooser;
+    SkBitmap::Allocator*    fAllocator;
+    int                     fSampleSize;
+    bool                    fDitherImage;
+    mutable bool            fShouldCancelDecode;
+
+    // illegal
+    SkImageDecoder(const SkImageDecoder&);
+    SkImageDecoder& operator=(const SkImageDecoder&);
+};
+
+#ifdef SK_SUPPORT_IMAGE_ENCODE
+
+class SkWStream;
+
+class SkImageEncoder {
+public:
+    enum Type {
+        kJPEG_Type,
+        kPNG_Type
+    };
+    static SkImageEncoder* Create(Type);
+
+    virtual ~SkImageEncoder();
+    
+    /*  Quality ranges from 0..100 */
+
+    bool encodeFile(const char file[], const SkBitmap&, int quality = 80);
+    bool encodeStream(SkWStream*, const SkBitmap&, int quality = 80);
+
+    static bool EncodeFile(const char file[], const SkBitmap&, Type,
+                           int quality = 80);
+    static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
+                           int quality = 80);
+
+protected:
+    virtual bool onEncode(SkWStream*, const SkBitmap&, int quality) = 0;
+};
+
+#endif /* SK_SUPPORT_IMAGE_ENCODE */
+
+///////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/include/images/SkImageRef.h b/include/images/SkImageRef.h
new file mode 100644
index 0000000..e94b7d4
--- /dev/null
+++ b/include/images/SkImageRef.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkImageRef_DEFINED
+#define SkImageRef_DEFINED
+
+#include "SkPixelRef.h"
+#include "SkBitmap.h"
+#include "SkImageDecoder.h"
+#include "SkString.h"
+
+class SkImageRefPool;
+class SkStream;
+
+// define this to enable dumping whenever we add/remove/purge an imageref
+//#define DUMP_IMAGEREF_LIFECYCLE
+
+class SkImageRef : public SkPixelRef {
+public:
+    /** Create a new imageref from a stream. NOTE: the stream is not copied, but
+        since it may be accessed from another thread, the caller must ensure
+        that this imageref is the only owner of the stream. i.e. - sole
+        ownership of the stream object is transferred to this imageref object.
+    
+        @param stream The stream containing the encoded image data. Ownership
+                      of this stream is transferred to the imageref, and
+                      therefore the stream's ownercount must be 1.
+        @param config The preferred config of the decoded bitmap.
+        @param sampleSize Requested sampleSize for decoding. Defaults to 1.
+    */
+    SkImageRef(SkStream*, SkBitmap::Config config, int sampleSize = 1);
+    virtual ~SkImageRef();
+    
+    /** Return true if the image can be decoded. If so, and bitmap is non-null,
+        call its setConfig() with the corresponding values, but explicitly will
+        not set its pixels or colortable. Use SkPixelRef::lockPixels() for that.
+     
+        If there has been an error decoding the bitmap, this will return false
+        and ignore the bitmap parameter.
+    */
+    bool getInfo(SkBitmap* bm);
+
+    // overrides
+    virtual void flatten(SkFlattenableWriteBuffer&) const;
+
+protected:
+    /** Override if you want to install a custom allocator.
+        When this is called we will have already acquired the mutex!
+    */
+    virtual bool onDecode(SkImageDecoder* codec, SkStream*, SkBitmap*,
+                          SkBitmap::Config, SkImageDecoder::Mode);
+
+    /*  Overrides from SkPixelRef
+        When these are called, we will have already acquired the mutex!
+     */
+
+    virtual void* onLockPixels(SkColorTable**);
+    // override this in your subclass to clean up when we're unlocking pixels
+    virtual void onUnlockPixels();
+    
+    SkImageRef(SkFlattenableReadBuffer&);
+
+    SkBitmap fBitmap;
+
+private:    
+    SkStream* setStream(SkStream*);
+    // called with mutex already held. returns true if the bitmap is in the
+    // requested state (or further, i.e. has pixels)
+    bool prepareBitmap(SkImageDecoder::Mode);
+
+    SkStream*           fStream;
+    SkBitmap::Config    fConfig;
+    int                 fSampleSize;
+    bool                fErrorInDecoding;
+    
+    friend class SkImageRefPool;
+    
+    SkImageRef*  fPrev, *fNext;    
+    size_t ramUsed() const;
+    
+    typedef SkPixelRef INHERITED;
+};
+
+#endif
diff --git a/include/images/SkImageRef_GlobalPool.h b/include/images/SkImageRef_GlobalPool.h
new file mode 100644
index 0000000..a9d4dce
--- /dev/null
+++ b/include/images/SkImageRef_GlobalPool.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkImageRef_GlobalPool_DEFINED
+#define SkImageRef_GlobalPool_DEFINED
+
+#include "SkImageRef.h"
+
+class SkImageRef_GlobalPool : public SkImageRef {
+public:
+    // if pool is null, use the global pool
+    SkImageRef_GlobalPool(SkStream*, SkBitmap::Config, int sampleSize = 1);
+    virtual ~SkImageRef_GlobalPool();
+    
+    // overrides
+    virtual Factory getFactory() const {
+        return Create;
+    }
+    static SkPixelRef* Create(SkFlattenableReadBuffer&);
+
+    // API to control the global pool
+
+    /** Return the amount specified as the budget for the cache (in bytes).
+     */
+    static size_t GetRAMBudget();
+    
+    /** Set a new budget value for the cache.
+     */
+    static void SetRAMBudget(size_t);
+    
+    /** Return how much ram is currently in use by the global cache.
+     */
+    static size_t GetRAMUsed();
+    
+    /** Free up (approximately) enough such that the amount used by the cache
+     is <= the specified amount. Since some images may be "in use", the
+     amount actually freed may not always result in a ram usage value <=
+     to the requested amount. In addition, because of the
+     chunky nature of the cache, the resulting usage may be < the requested
+     amount.
+     */
+    static void SetRAMUsed(size_t usageInBytes);
+    
+    static void DumpPool();
+
+protected:
+    virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
+                          SkBitmap* bitmap, SkBitmap::Config config,
+                          SkImageDecoder::Mode mode);
+    
+    virtual void onUnlockPixels();
+    
+    SkImageRef_GlobalPool(SkFlattenableReadBuffer&);
+
+private:
+    typedef SkImageRef INHERITED;
+};
+
+#endif
diff --git a/include/images/SkMovie.h b/include/images/SkMovie.h
new file mode 100644
index 0000000..45962a5
--- /dev/null
+++ b/include/images/SkMovie.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkMovie_DEFINED
+#define SkMovie_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkCanvas.h"
+
+class SkStream;
+
+class SkMovie : public SkRefCnt {
+public:
+    /** Try to create a movie from the stream. If the stream format is not
+        supported, return NULL.
+    */
+    static SkMovie* DecodeStream(SkStream*);
+    /** Try to create a movie from the specified file path. If the file is not
+        found, or the format is not supported, return NULL. If a movie is
+        returned, the stream may be retained by the movie (via ref()) until
+        the movie is finished with it (by calling unref()).
+    */
+    static SkMovie* DecodeFile(const char path[]);
+    /** Try to create a movie from the specified memory.
+        If the format is not supported, return NULL. If a movie is returned,
+        the data will have been read or copied, and so the caller may free
+        it.
+    */
+    static SkMovie* DecodeMemory(const void* data, size_t length);
+
+    SkMSec  duration();
+    int     width();
+    int     height();
+    int     isOpaque();
+    
+    /** Specify the time code (between 0...duration) to sample a bitmap
+        from the movie. Returns true if this time code generated a different
+        bitmap/frame from the previous state (i.e. true means you need to
+        redraw).
+    */
+    bool setTime(SkMSec);
+
+    // return the right bitmap for the current time code
+    const SkBitmap& bitmap();
+    
+protected:
+    struct Info {
+        SkMSec  fDuration;
+        int     fWidth;
+        int     fHeight;
+        bool    fIsOpaque;
+    };
+
+    virtual bool onGetInfo(Info*) = 0;
+    virtual bool onSetTime(SkMSec) = 0;
+    virtual bool onGetBitmap(SkBitmap*) = 0;
+
+    // visible for subclasses
+    SkMovie();
+
+private:
+    Info        fInfo;
+    SkMSec      fCurrTime;
+    SkBitmap    fBitmap;
+    bool        fNeedBitmap;
+    
+    void ensureInfo();
+};
+
+#endif
diff --git a/include/images/SkPageFlipper.h b/include/images/SkPageFlipper.h
new file mode 100644
index 0000000..0d791ee
--- /dev/null
+++ b/include/images/SkPageFlipper.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPageFlipper_DEFINED
+#define SkPageFlipper_DEFINED
+
+#include "SkRegion.h"
+
+/** SkPageFlipper manages alternating inval/dirty regions for a rectangular area
+    (like a bitmap). You call inval() to accumulate inval areas, and then when
+    you're ready to "flip" pages (i.e. draw into the one you've been
+    invalidating) you call update, which swaps the inval regions, and returns
+    two things to you: 1) the final inval region to be drawn into, and 2) the
+    region of pixels that should be copied from the "front" page onto the one
+    you're about to draw into. This copyBits region will be disjoint from the
+    inval region, so both need to be handled.
+ */
+class SkPageFlipper {
+public:
+    SkPageFlipper();
+    SkPageFlipper(int width, int height);
+    
+    int width() const { return fWidth; }
+    int height() const { return fHeight; }
+
+    void resize(int width, int height);
+
+    bool isDirty() const { return !fDirty1->isEmpty(); }
+    const SkRegion& dirtyRgn() const { return *fDirty1; }
+
+    void inval();
+    void inval(const SkIRect&);
+    void inval(const SkRegion&);
+    void inval(const SkRect&, bool antialias);
+
+    /** When you're ready to write to the back page, call update. The returned
+        region is the invalidate are that needs to be drawn to. The copyBits
+        region (provided by the caller) is the area that should be copied from
+        the front page to the back page (will not intersect with the returned
+        inval region.
+     
+        Once this is called, the two internal regions are swapped, so the *new*
+        back inval region is ready to receive new inval calls.
+     */
+    const SkRegion& update(SkRegion* copyBits);
+
+private:
+    SkRegion*   fDirty0;
+    SkRegion*   fDirty1;
+    SkRegion    fDirty0Storage;
+    SkRegion    fDirty1Storage;
+    int         fWidth;
+    int         fHeight;
+};
+
+#endif
+
diff --git a/include/ports/SkOSFile.h b/include/ports/SkOSFile.h
new file mode 100644
index 0000000..de8090c
--- /dev/null
+++ b/include/ports/SkOSFile.h
@@ -0,0 +1,85 @@
+/*
+ * 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 SkOSFile_DEFINED
+#define SkOSFile_DEFINED
+
+#include "SkString.h"
+
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
+    #include <dirent.h>
+#endif
+
+struct SkFILE;
+
+enum SkFILE_Flags {
+    kRead_SkFILE_Flag   = 0x01,
+    kWrite_SkFILE_Flag  = 0x02
+};
+
+SkFILE* sk_fopen(const char path[], SkFILE_Flags);
+void    sk_fclose(SkFILE*);
+
+size_t  sk_fgetsize(SkFILE*);
+/** Return true if the file could seek back to the beginning
+*/
+bool    sk_frewind(SkFILE*);
+
+size_t  sk_fread(void* buffer, size_t byteCount, SkFILE*);
+size_t  sk_fwrite(const void* buffer, size_t byteCount, SkFILE*);
+void    sk_fflush(SkFILE*);
+
+int     sk_fseek( SkFILE*, size_t, int );
+size_t  sk_ftell( SkFILE* );
+
+class SkOSFile {
+public:
+    class Iter {
+    public:
+        Iter();
+        Iter(const char path[], const char suffix[] = NULL);
+        ~Iter();
+
+        void reset(const char path[], const char suffix[] = NULL);
+        bool next(SkString* name, bool getDir = false);
+
+    private:
+#ifdef SK_BUILD_FOR_WIN
+        HANDLE      fHandle;
+        uint16_t*   fPath16;
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
+        DIR*        fDIR;
+        SkString    fPath, fSuffix;
+#endif
+    };
+};
+
+class SkUTF16_Str {
+public:
+    SkUTF16_Str(const char src[]);
+    ~SkUTF16_Str()
+    {
+        sk_free(fStr);
+    }
+    const uint16_t* get() const { return fStr; }
+
+private:
+    uint16_t*   fStr;
+};
+
+#endif
+
diff --git a/include/ports/SkStream_Win.h b/include/ports/SkStream_Win.h
new file mode 100644
index 0000000..1b17450
--- /dev/null
+++ b/include/ports/SkStream_Win.h
@@ -0,0 +1,53 @@
+/*
+ * 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
+
diff --git a/include/svg/SkSVGAttribute.h b/include/svg/SkSVGAttribute.h
new file mode 100644
index 0000000..810d11c
--- /dev/null
+++ b/include/svg/SkSVGAttribute.h
@@ -0,0 +1,49 @@
+/*
+ * 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 SkSVGAttribute_DEFINED
+#define SkSVGAttribute_DEFINED
+
+#include "SkTypes.h"
+
+struct SkSVGAttribute {
+    const char* fName;
+#ifdef SK_DEBUG
+    size_t fOffset;
+#endif
+};
+
+#ifndef SK_OFFSETOF
+#define SK_OFFSETOF(a, b) (((size_t) (&(((a*) 1)->b)))-1)
+#endif
+
+#ifdef SK_DEBUG
+#define SVG_ATTRIBUTE(attr) { #attr, SK_OFFSETOF(BASE_CLASS, f_##attr) }
+#define SVG_LITERAL_ATTRIBUTE(svgAttr, cAttr) { #svgAttr, SK_OFFSETOF(BASE_CLASS, cAttr) }
+#else
+#define SVG_ATTRIBUTE(attr) { #attr }
+#define SVG_LITERAL_ATTRIBUTE(svgAttr, cAttr) { #svgAttr }
+#endif
+
+#define SVG_ADD_ATTRIBUTE(attr) \
+    if (f_##attr.size() > 0) \
+        parser._addAttributeLen(#attr, f_##attr.c_str(), f_##attr.size())
+
+#define SVG_ADD_ATTRIBUTE_ALIAS(attr, alias) \
+    if (f_##alias.size() > 0) \
+        parser._addAttributeLen(#attr, f_##alias.c_str(), f_##alias.size())
+
+#endif // SkSVGAttribute_DEFINED
diff --git a/include/svg/SkSVGBase.h b/include/svg/SkSVGBase.h
new file mode 100644
index 0000000..4d24aed
--- /dev/null
+++ b/include/svg/SkSVGBase.h
@@ -0,0 +1,33 @@
+/*
+ * 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 SkSVGBase_DEFINED
+#define SkSVGBase_DEFINED
+
+#include "SkSVGAttribute.h"
+
+class SkSVGParser;
+
+class SkSVGBase {
+public:
+    virtual ~SkSVGBase();
+    virtual void addAttribute(SkSVGParser& parser, int attrIndex, 
+        const char* attrValue, size_t attrLength);
+    virtual int getAttributes(const SkSVGAttribute** attrPtr) = 0;
+};
+
+#endif // SkSVGBase_DEFINEDes(const SkSVGAttribute** attrPtr) = 0;
+
diff --git a/include/svg/SkSVGPaintState.h b/include/svg/SkSVGPaintState.h
new file mode 100644
index 0000000..f3f74e1
--- /dev/null
+++ b/include/svg/SkSVGPaintState.h
@@ -0,0 +1,96 @@
+/*
+ * 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 SkSVGPaintState_DEFINED
+#define SkSVGPaintState_DEFINED
+
+#include "SkSVGBase.h"
+#include "SkString.h"
+
+class SkSVGPaint : public SkSVGBase {
+public:
+    enum Field {
+        kInitial = -1,
+        kClipPath,
+        kClipRule,
+        kEnableBackground,
+        kFill,
+        kFillRule,
+        kFilter,
+        kFontFamily,
+        kFontSize,
+        kLetterSpacing,
+        kMask,
+        kOpacity,
+        kStopColor,
+        kStopOpacity,
+        kStroke,
+        kStroke_Dasharray,
+        kStroke_Linecap,
+        kStroke_Linejoin,
+        kStroke_Miterlimit,
+        kStroke_Width,
+        kStyle,
+        kTransform,
+        kTerminal
+    };
+
+    SkSVGPaint();
+    virtual void addAttribute(SkSVGParser& parser, int attrIndex, 
+        const char* attrValue, size_t attrLength);
+    bool flush(SkSVGParser& , bool isFlushable, bool isDef);
+    virtual int getAttributes(const SkSVGAttribute** attrPtr); 
+    static void Push(SkSVGPaint** head, SkSVGPaint* add);
+    static void Pop(SkSVGPaint** head);
+    SkString* operator[](int index);
+    SkString fInitial;
+    SkString f_clipPath;
+    SkString f_clipRule;
+    SkString f_enableBackground;
+    SkString f_fill;
+    SkString f_fillRule;
+    SkString f_filter;
+    SkString f_fontFamily;
+    SkString f_fontSize;
+    SkString f_letterSpacing;
+    SkString f_mask;
+    SkString f_opacity;
+    SkString f_stopColor;
+    SkString f_stopOpacity;
+    SkString f_stroke;
+    SkString f_strokeDasharray;
+    SkString f_strokeLinecap;
+    SkString f_strokeLinejoin;
+    SkString f_strokeMiterlimit;
+    SkString f_strokeWidth;
+    SkString f_style; // unused, but allows array access to the rest
+    SkString f_transform;
+#ifdef SK_DEBUG
+    SkString fTerminal;
+#endif
+    SkString fTransformID;
+    static SkSVGAttribute gAttributes[];
+    static const int kAttributesSize;
+private:
+    void setSave(SkSVGParser& );
+    bool writeChangedAttributes(SkSVGParser& , SkSVGPaint& , bool* changed);
+    bool writeChangedElements(SkSVGParser& , SkSVGPaint& , bool* changed);
+    SkSVGPaint* fNext;
+    friend class SkSVGParser;
+    typedef SkSVGPaint BASE_CLASS;
+};
+
+#endif // SkSVGPaintState_DEFINED
diff --git a/include/svg/SkSVGParser.h b/include/svg/SkSVGParser.h
new file mode 100644
index 0000000..86ae4c2
--- /dev/null
+++ b/include/svg/SkSVGParser.h
@@ -0,0 +1,81 @@
+/*
+ * 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 SkSVGParser_DEFINED
+#define SkSVGParser_DEFINED
+
+#include "SkMatrix.h"
+#include "SkTDict.h"
+#include "SkTDStack.h"
+#include "SkSVGPaintState.h"
+#include "SkSVGTypes.h"
+#include "SkStream.h"
+#include "SkString.h"
+#include "SkXMLParser.h"
+#include "SkXMLWriter.h"
+
+class SkSVGBase;
+class SkSVGElement;
+
+class SkSVGParser : public SkXMLParser {
+public:
+    SkSVGParser();
+    virtual ~SkSVGParser();
+    void _addAttribute(const char* attrName, const char* attrValue) {
+        fXMLWriter.addAttribute(attrName, attrValue); }
+    void _addAttribute(const char* attrName, SkString& attrValue) {
+        fXMLWriter.addAttribute(attrName, attrValue.c_str()); }
+    void _addAttributeLen(const char* attrName, const char* attrValue, size_t len) {
+        fXMLWriter.addAttributeLen(attrName, attrValue, len); }
+    void _endElement() { fXMLWriter.endElement(); }
+    int findAttribute(SkSVGBase* , const char* attrValue, size_t len, bool isPaint);
+    const char* getFinal();
+    SkTDict<SkSVGElement*>& getIDs() { return fIDs; }
+    SkString& getPaintLast(SkSVGPaint::Field field);
+    void _startElement(const char name[]) { fXMLWriter.startElement(name); }
+    void translate(SkSVGElement*, bool isDef);
+    void translateMatrix(SkString& , SkString* id);
+    static void ConvertToArray(SkString& vals);
+protected:
+    virtual bool onAddAttribute(const char name[], const char value[]);
+    bool onAddAttributeLen(const char name[], const char value[], size_t len);
+    virtual bool onEndElement(const char elem[]);
+    virtual bool onStartElement(const char elem[]);
+    bool onStartElementLen(const char elem[], size_t len);
+    virtual bool onText(const char text[], int len);
+private:
+    bool isStrokeAndFill(SkSVGPaint** stroke, SkSVGPaint** fill);
+    static SkSVGElement* CreateElement(SkSVGTypes type, SkSVGElement* parent);
+    static void Delete(SkTDArray<SkSVGElement*>& fChildren);
+    static SkSVGTypes GetType(const char name[], size_t len);
+    SkSVGPaint* fHead;
+    SkSVGPaint fEmptyPaint; 
+    SkSVGPaint fLastFlush;
+    SkString fLastColor;
+    SkMatrix fLastTransform;
+    SkTDArray<SkSVGElement*> fChildren;
+    SkTDict<SkSVGElement*> fIDs;
+    SkTDArray<SkSVGElement*> fParents;
+    SkDynamicMemoryWStream fStream;
+    SkXMLStreamWriter fXMLWriter;
+    SkSVGElement*   fCurrElement;
+    SkBool8 fInSVG;
+    SkBool8 fSuppressPaint;
+    friend class SkSVGPaint;
+    friend class SkSVGGradient;
+};
+
+#endif // SkSVGParser_DEFINED
diff --git a/include/svg/SkSVGTypes.h b/include/svg/SkSVGTypes.h
new file mode 100644
index 0000000..38d63ce
--- /dev/null
+++ b/include/svg/SkSVGTypes.h
@@ -0,0 +1,46 @@
+/*
+ * 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 SkSVGTypes_DEFINED
+#define SkSVGTypes_DEFINED
+
+enum SkSVGTypes {
+    SkSVGType_Circle,
+    SkSVGType_ClipPath,
+    SkSVGType_Defs,
+    SkSVGType_Ellipse,
+    SkSVGType_FeColorMatrix,
+    SkSVGType_Filter,
+    SkSVGType_G,
+    SkSVGType_Image,
+    SkSVGType_Line,
+    SkSVGType_LinearGradient,
+    SkSVGType_Mask,
+    SkSVGType_Metadata,
+    SkSVGType_Path,
+    SkSVGType_Polygon,
+    SkSVGType_Polyline,
+    SkSVGType_RadialGradient,
+    SkSVGType_Rect,
+    SkSVGType_SVG,
+    SkSVGType_Stop,
+    SkSVGType_Symbol,
+    SkSVGType_Text,
+    SkSVGType_Tspan,
+    SkSVGType_Use
+};
+
+#endif // SkSVGTypes_DEFINED
diff --git a/include/utils/SkCamera.h b/include/utils/SkCamera.h
new file mode 100644
index 0000000..8bbcabf
--- /dev/null
+++ b/include/utils/SkCamera.h
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+
+
+//  Inspired by Rob Johnson's most excellent QuickDraw GX sample code
+
+#ifndef SkCamera_DEFINED
+#define SkCamera_DEFINED
+
+#include "Sk64.h"
+#include "SkMatrix.h"
+
+class SkCanvas;
+
+#ifdef SK_SCALAR_IS_FIXED
+    typedef SkFract SkUnitScalar;
+    #define SK_UnitScalar1          SK_Fract1
+    #define SkUnitScalarMul(a, b)   SkFractMul(a, b)
+    #define SkUnitScalarDiv(a, b)   SkFractDiv(a, b)
+#else
+    typedef float   SkUnitScalar;
+    #define SK_UnitScalar1          SK_Scalar1
+    #define SkUnitScalarMul(a, b)   SkScalarMul(a, b)
+    #define SkUnitScalarDiv(a, b)   SkScalarDiv(a, b)
+#endif
+
+struct SkUnit3D {
+    SkUnitScalar    fX, fY, fZ;
+
+    void set(SkUnitScalar x, SkUnitScalar y, SkUnitScalar z)
+    {
+        fX = x; fY = y; fZ = z;
+    }
+    static SkUnitScalar Dot(const SkUnit3D&, const SkUnit3D&);
+    static void Cross(const SkUnit3D&, const SkUnit3D&, SkUnit3D* cross);
+};
+
+struct SkPoint3D {
+    SkScalar    fX, fY, fZ;
+
+    void set(SkScalar x, SkScalar y, SkScalar z)
+    {
+        fX = x; fY = y; fZ = z;
+    }
+    SkScalar    normalize(SkUnit3D*) const;
+};
+typedef SkPoint3D SkVector3D;
+
+struct SkMatrix3D {
+    SkScalar    fMat[3][4];
+    
+    void reset();
+
+    void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0)
+    {
+        SkASSERT((unsigned)row < 3);
+        fMat[row][0] = a;
+        fMat[row][1] = b;
+        fMat[row][2] = c;
+        fMat[row][3] = d;
+    }
+
+    void setRotateX(SkScalar deg);
+    void setRotateY(SkScalar deg);
+    void setRotateZ(SkScalar deg);
+    void setTranslate(SkScalar x, SkScalar y, SkScalar z);
+    
+    void preRotateX(SkScalar deg);
+    void preRotateY(SkScalar deg);
+    void preRotateZ(SkScalar deg);
+    void preTranslate(SkScalar x, SkScalar y, SkScalar z);
+
+    void setConcat(const SkMatrix3D& a, const SkMatrix3D& b);
+    void mapPoint(const SkPoint3D& src, SkPoint3D* dst) const;
+    void mapVector(const SkVector3D& src, SkVector3D* dst) const;
+
+    void mapPoint(SkPoint3D* v) const
+    {
+        this->mapPoint(*v, v);
+    }
+    void mapVector(SkVector3D* v) const
+    {
+        this->mapVector(*v, v);
+    }
+};
+
+class SkPatch3D {
+public:
+    SkPatch3D();
+
+    void    reset();
+    void    transform(const SkMatrix3D&, SkPatch3D* dst = NULL) const;
+
+    // dot a unit vector with the patch's normal
+    SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const;
+    SkScalar dotWith(const SkVector3D& v) const
+    {
+        return this->dotWith(v.fX, v.fY, v.fZ);
+    }
+
+    // depreicated, but still here for animator (for now)
+    void rotate(SkScalar x, SkScalar y, SkScalar z) {}
+    void rotateDegrees(SkScalar x, SkScalar y, SkScalar z) {}
+
+private:
+public: // make public for SkDraw3D for now
+    SkVector3D  fU, fV;
+    SkPoint3D   fOrigin;
+    
+    friend class SkCamera3D;
+};
+
+class SkCamera3D {
+public:
+    SkCamera3D();
+
+    void reset();
+    void update();
+    void patchToMatrix(const SkPatch3D&, SkMatrix* matrix) const;
+
+    SkPoint3D   fLocation;
+    SkPoint3D   fAxis;
+    SkPoint3D   fZenith;
+    SkPoint3D   fObserver;
+
+private:
+    mutable SkMatrix    fOrientation;
+    mutable bool        fNeedToUpdate;
+
+    void doUpdate() const;
+};
+
+class Sk3DView : SkNoncopyable {
+public:
+    Sk3DView();
+    ~Sk3DView();
+
+    void save();
+    void restore();
+
+    void translate(SkScalar x, SkScalar y, SkScalar z);
+    void rotateX(SkScalar deg);
+    void rotateY(SkScalar deg);
+    void rotateZ(SkScalar deg);
+
+    void getMatrix(SkMatrix*) const;
+    void applyToCanvas(SkCanvas*) const;
+
+    SkScalar dotWithNormal(SkScalar dx, SkScalar dy, SkScalar dz) const;
+    
+private:
+    struct Rec {
+        Rec*        fNext;
+        SkMatrix3D  fMatrix;
+    };
+    Rec*        fRec;
+    Rec         fInitialRec;
+    SkCamera3D  fCamera;
+};
+
+#endif
+
diff --git a/include/utils/SkCullPoints.h b/include/utils/SkCullPoints.h
new file mode 100644
index 0000000..cee64e2
--- /dev/null
+++ b/include/utils/SkCullPoints.h
@@ -0,0 +1,75 @@
+/*
+ * 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 SkCullPoints_DEFINED
+#define SkCullPoints_DEFINED
+
+#include "SkRect.h"
+
+class SkCullPoints {
+public:
+    SkCullPoints();
+    SkCullPoints(const SkIRect& r);
+    
+    void    reset(const SkIRect& r);
+    
+    /** Start a contour at (x,y). Follow this with call(s) to lineTo(...)
+    */
+    void    moveTo(int x, int y);
+    
+    enum LineToResult {
+        kNo_Result,             //!< line segment was completely clipped out
+        kLineTo_Result,         //!< path.lineTo(pts[1]);
+        kMoveToLineTo_Result    //!< path.moveTo(pts[0]); path.lineTo(pts[1]);
+    };
+    /** Connect a line to the previous call to lineTo (or moveTo).
+    */
+    LineToResult lineTo(int x, int y, SkIPoint pts[2]);
+
+private:
+    SkIRect      fR;             // the caller's rectangle
+    SkIPoint     fAsQuad[4];     // cache of fR as 4 points
+    SkIPoint     fPrevPt;        // private state
+    LineToResult fPrevResult;   // private state
+    
+    bool sect_test(int x0, int y0, int x1, int y1) const;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+class SkPath;
+
+/** \class SkCullPointsPath
+
+    Similar to SkCullPoints, but this class handles the return values
+    from lineTo, and automatically builds a SkPath with the result(s).
+*/
+class SkCullPointsPath {
+public:
+    SkCullPointsPath();
+    SkCullPointsPath(const SkIRect& r, SkPath* dst);
+
+    void reset(const SkIRect& r, SkPath* dst);
+    
+    void    moveTo(int x, int y);
+    void    lineTo(int x, int y);
+
+private:
+    SkCullPoints    fCP;
+    SkPath*         fPath;
+};
+
+#endif
diff --git a/include/utils/SkDumpCanvas.h b/include/utils/SkDumpCanvas.h
new file mode 100644
index 0000000..b919627
--- /dev/null
+++ b/include/utils/SkDumpCanvas.h
@@ -0,0 +1,139 @@
+#ifndef SkDumpCanvas_DEFINED
+#define SkDumpCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+/** This class overrides all the draw methods on SkCanvas, and formats them
+    as text, and then sends that to a Dumper helper object.
+ 
+    Typical use might be to dump a display list to a log file to see what is
+    being drawn.
+ */
+class SkDumpCanvas : public SkCanvas {
+public:
+    class Dumper;
+
+    explicit SkDumpCanvas(Dumper* = 0);
+    virtual ~SkDumpCanvas();
+    
+    enum Verb {
+        kNULL_Verb,
+
+        kSave_Verb,
+        kRestore_Verb,
+        
+        kMatrix_Verb,
+        
+        kClip_Verb,
+        
+        kDrawPaint_Verb,
+        kDrawPoints_Verb,
+        kDrawRect_Verb,
+        kDrawPath_Verb,
+        kDrawBitmap_Verb,
+        kDrawText_Verb,
+        kDrawPicture_Verb,
+        kDrawVertices_Verb
+    };
+    
+    /** Subclasses of this are installed on the DumpCanvas, and then called for
+        each drawing command.
+     */
+    class Dumper : public SkRefCnt {
+    public:
+        virtual void dump(SkDumpCanvas*, SkDumpCanvas::Verb, const char str[],
+                          const SkPaint*) = 0;
+    };
+        
+    Dumper* getDumper() const { return fDumper; }
+    void    setDumper(Dumper*);
+    
+    // overrides from SkCanvas
+
+    virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
+    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+                          SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+    virtual void restore();
+
+    virtual bool translate(SkScalar dx, SkScalar dy);
+    virtual bool scale(SkScalar sx, SkScalar sy);
+    virtual bool rotate(SkScalar degrees);
+    virtual bool skew(SkScalar sx, SkScalar sy);
+    virtual bool concat(const SkMatrix& matrix);
+    virtual void setMatrix(const SkMatrix& matrix);
+    
+    virtual bool clipRect(const SkRect& rect,
+                          SkRegion::Op op = SkRegion::kIntersect_Op);
+    virtual bool clipPath(const SkPath& path,
+                          SkRegion::Op op = SkRegion::kIntersect_Op);
+    virtual bool clipRegion(const SkRegion& deviceRgn,
+                            SkRegion::Op op = SkRegion::kIntersect_Op);
+
+    virtual void drawPaint(const SkPaint& paint);
+    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                            const SkPaint& paint);
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint);
+    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+                            const SkPaint* paint = NULL);
+    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+                                const SkRect& dst, const SkPaint* paint = NULL);
+    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+                                  const SkPaint* paint = NULL);
+    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+                            const SkPaint* paint = NULL);
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint);
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint);
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint);
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint);
+    virtual void drawPicture(SkPicture& picture);
+    virtual void drawVertices(VertexMode vmode, int vertexCount,
+                              const SkPoint vertices[], const SkPoint texs[],
+                              const SkColor colors[], SkXfermode* xmode,
+                              const uint16_t indices[], int indexCount,
+                              const SkPaint& paint);
+
+private:
+    Dumper* fDumper;
+    
+    void dump(Verb, const SkPaint*, const char format[], ...);
+
+    typedef SkCanvas INHERITED;
+};
+
+/** Formats the draw commands, and send them to a function-pointer provided
+    by the caller.
+ */
+class SkFormatDumper : public SkDumpCanvas::Dumper {
+public:
+    SkFormatDumper(void (*)(const char text[], void* refcon), void* refcon);
+    
+    // override from baseclass that does the formatting, and in turn calls
+    // the function pointer that was passed to the constructor
+    virtual void dump(SkDumpCanvas*, SkDumpCanvas::Verb, const char str[],
+                      const SkPaint*);
+    
+private:
+    void (*fProc)(const char*, void*);
+    void* fRefcon;
+    
+    typedef SkDumpCanvas::Dumper INHERITED;
+};
+
+/** Subclass of Dumper that dumps the drawing command to SkDebugf
+ */
+class SkDebugfDumper : public SkFormatDumper {
+public:
+    SkDebugfDumper();
+
+private:
+    typedef SkFormatDumper INHERITED;
+};
+
+#endif
diff --git a/include/utils/SkGLCanvas.h b/include/utils/SkGLCanvas.h
new file mode 100644
index 0000000..40fc52d
--- /dev/null
+++ b/include/utils/SkGLCanvas.h
@@ -0,0 +1,80 @@
+/*
+ * 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 SkGLCanvas_DEFINED
+#define SkGLCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+#ifdef SK_BUILD_FOR_MAC
+    #include <OpenGL/gl.h>
+#elif defined(ANDROID)
+    #include <GLES/gl.h>
+#endif
+
+class SkGLDevice;
+class SkGLClipIter;
+
+class SkGLCanvas : public SkCanvas {
+public:
+    // notice, we do NOT allow the SkCanvas(bitmap) constructor, since that
+    // does not create a SkGLDevice, which we require
+    SkGLCanvas();
+    virtual ~SkGLCanvas();
+
+    // overrides from SkCanvas
+
+    virtual bool getViewport(SkIPoint*) const;
+    virtual bool setViewport(int width, int height);
+
+    virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
+                                   bool isOpaque, bool isForLayer);
+
+    // settings for the global texture cache
+
+    static size_t GetTextureCacheMaxCount();
+    static void SetTextureCacheMaxCount(size_t count);
+
+    static size_t GetTextureCacheMaxSize();
+    static void SetTextureCacheMaxSize(size_t size);
+
+    /** Call glDeleteTextures for all textures (including those for text)
+        This should be called while the gl-context is still valid. Its purpose
+        is to free up gl resources. Note that if a bitmap or text is drawn after
+        this call, new caches will be created.
+    */
+    static void DeleteAllTextures();
+
+    /** Forget all textures without calling delete (including those for text).
+        This should be called if the gl-context has changed, and the texture
+        IDs that have been cached are no longer valid.
+    */
+    static void AbandonAllTextures();
+
+private:
+    SkIPoint fViewportSize;
+
+    // need to disallow this guy
+    virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap) {
+        sk_throw();
+        return NULL;
+    }
+
+    typedef SkCanvas INHERITED;
+};
+
+#endif
+
diff --git a/include/utils/SkInterpolator.h b/include/utils/SkInterpolator.h
new file mode 100644
index 0000000..c03eb23
--- /dev/null
+++ b/include/utils/SkInterpolator.h
@@ -0,0 +1,139 @@
+/*
+ * 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 SkInterpolator_DEFINED
+#define SkInterpolator_DEFINED
+
+#include "SkScalar.h"
+
+class SkInterpolatorBase : SkNoncopyable {
+public:
+    enum Result {
+        kNormal_Result,
+        kFreezeStart_Result,
+        kFreezeEnd_Result
+    };
+protected:
+    SkInterpolatorBase();
+    ~SkInterpolatorBase();
+public:
+    void    reset(int elemCount, int frameCount);
+
+    /** Return the start and end time for this interpolator.
+        If there are no key frames, return false.
+        @param startTime If not null, returns the time (in milliseconds) of the
+                         first keyframe. If there are no keyframes, this param
+                         is ignored (left unchanged).
+        @param endTime If not null, returns the time (in milliseconds) of the
+                       last keyframe. If there are no keyframes, this parameter
+                       is ignored (left unchanged).
+        @return True if there are key frames, or false if there are none.
+    */
+    bool    getDuration(SkMSec* startTime, SkMSec* endTime) const;
+
+
+    /** Set the whether the repeat is mirrored.
+        @param mirror If true, the odd repeats interpolate from the last key
+                      frame and the first.
+    */
+    void setMirror(bool mirror) {
+        fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror);
+    }
+
+    /** Set the repeat count. The repeat count may be fractional.
+        @param repeatCount Multiplies the total time by this scalar.
+    */
+    void    setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; }
+
+    /** Set the whether the repeat is mirrored.
+        @param reset If true, the odd repeats interpolate from the last key
+                     frame and the first.
+    */
+    void setReset(bool reset) {
+        fFlags = SkToU8((fFlags & ~kReset) | (int)reset);
+    }
+
+    Result  timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const;
+
+protected:
+    enum Flags {
+        kMirror = 1,
+        kReset = 2,
+        kHasBlend = 4
+    };
+    static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime,
+                             SkMSec nextTime, const SkScalar blend[4] = NULL);
+    int16_t fFrameCount;
+    uint8_t fElemCount;
+    uint8_t fFlags;
+    SkScalar fRepeat;
+    struct SkTimeCode {
+        SkMSec  fTime;
+        SkScalar fBlend[4];
+    };
+    SkTimeCode* fTimes;     // pointer into fStorage
+    void* fStorage;
+#ifdef SK_DEBUG
+    SkTimeCode(* fTimesArray)[10];
+#endif
+};
+
+class SkInterpolator : public SkInterpolatorBase {
+public:
+    SkInterpolator();
+    SkInterpolator(int elemCount, int frameCount);
+    void    reset(int elemCount, int frameCount);
+
+    /** Add or replace a key frame, copying the values[] data into the
+        interpolator.
+        @param index    The index of this frame (frames must be ordered by time)
+        @param time The millisecond time for this frame
+        @param values   The array of values [elemCount] for this frame. The data
+                        is copied into the interpolator.
+        @param blend    A positive scalar specifying how to blend between this
+                        and the next key frame. [0...1) is a cubic lag/log/lag
+                        blend (slow to change at the beginning and end)
+                        1 is a linear blend (default)
+    */
+    bool setKeyFrame(int index, SkMSec time, const SkScalar values[],
+                     const SkScalar blend[4] = NULL);
+
+    /** Return the computed values given the specified time. Return whether
+        those values are the result of pinning to either the first
+        (kFreezeStart) or last (kFreezeEnd), or from interpolated the two
+        nearest key values (kNormal).
+        @param time The time to sample (in milliseconds)
+        @param (may be null) where to write the computed values.
+    */
+    Result timeToValues(SkMSec time, SkScalar values[] = NULL) const;
+
+    SkDEBUGCODE(static void UnitTest();)
+private:
+    SkScalar* fValues;  // pointer into fStorage
+#ifdef SK_DEBUG
+    SkScalar(* fScalarsArray)[10];
+#endif
+    typedef SkInterpolatorBase INHERITED;
+};
+
+/** Given all the parameters are [0...1], apply the cubic specified by (0,0)
+    (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1].
+*/
+SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,
+                           SkScalar cx, SkScalar cy);
+
+#endif
+
diff --git a/include/utils/SkNinePatch.h b/include/utils/SkNinePatch.h
new file mode 100644
index 0000000..a655621
--- /dev/null
+++ b/include/utils/SkNinePatch.h
@@ -0,0 +1,40 @@
+/*
+ * 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 SkNinePatch_DEFINED
+#define SkNinePatch_DEFINED
+
+#include "SkRect.h"
+#include "SkRegion.h"
+
+class SkBitmap;
+class SkCanvas;
+class SkPaint;
+
+class SkNinePatch {
+public:
+    static void DrawNine(SkCanvas* canvas, const SkRect& dst,
+                     const SkBitmap& bitmap, const SkIRect& margins,
+                     const SkPaint* paint = NULL);
+    
+    static void DrawMesh(SkCanvas* canvas, const SkRect& dst,
+                         const SkBitmap& bitmap,
+                         const int32_t xDivs[], int numXDivs,
+                         const int32_t yDivs[], int numYDivs,
+                         const SkPaint* paint = NULL);
+};
+
+#endif
diff --git a/include/utils/SkParse.h b/include/utils/SkParse.h
new file mode 100644
index 0000000..57d040c
--- /dev/null
+++ b/include/utils/SkParse.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkParse_DEFINED
+#define SkParse_DEFINED
+
+#include "SkColor.h"
+#include "SkMath.h"
+
+class SkParse {
+public:
+    static int Count(const char str[]); // number of scalars or int values
+    static int Count(const char str[], char separator);
+    static const char* FindColor(const char str[], SkColor* value);
+    static const char* FindHex(const char str[], uint32_t* value);
+    static const char* FindMSec(const char str[], SkMSec* value);
+    static const char* FindNamedColor(const char str[], size_t len, SkColor* color);
+    static const char* FindS32(const char str[], int32_t* value);
+    static const char* FindScalar(const char str[], SkScalar* value);
+    static const char* FindScalars(const char str[], SkScalar value[], int count);
+
+    static bool FindBool(const char str[], bool* value);
+    // return the index of str in list[], or -1 if not found
+    static int  FindList(const char str[], const char list[]);
+#ifdef SK_SUPPORT_UNITTEST
+    static void TestColor();
+    static void UnitTest();
+#endif
+};
+
+#endif
+
diff --git a/include/utils/SkParsePaint.h b/include/utils/SkParsePaint.h
new file mode 100644
index 0000000..d23cd92
--- /dev/null
+++ b/include/utils/SkParsePaint.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkParsePaint_DEFINED
+#define SkParsePaint_DEFINED
+
+#include "SkPaint.h"
+#include "SkDOM.h"
+
+/** "color"             color
+    "opacity"           scalar  [0..1]
+    "stroke-width"      scalar  (0...inf)
+    "text-size"         scalar  (0..inf)
+    "is-stroke"         bool
+    "is-antialias"      bool
+    "is-lineartext"     bool
+*/
+void SkPaint_Inflate(SkPaint*, const SkDOM&, const SkDOM::Node*);
+
+#endif
+
diff --git a/include/utils/SkProxyCanvas.h b/include/utils/SkProxyCanvas.h
new file mode 100644
index 0000000..1bc411a
--- /dev/null
+++ b/include/utils/SkProxyCanvas.h
@@ -0,0 +1,90 @@
+#ifndef SkProxyCanvas_DEFINED
+#define SkProxyCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+/** This class overrides all virtual methods on SkCanvas, and redirects them
+    to a "proxy", another SkCanvas instance. It can be the basis for
+    intercepting (and possibly modifying) calls to a canvas.
+ 
+    There must be a proxy installed before the proxycanvas can be used (i.e.
+    before its virtual methods can be called).
+ */
+class SkProxyCanvas : public SkCanvas {
+public:
+    SkProxyCanvas() : fProxy(NULL) {}
+    SkProxyCanvas(SkCanvas* proxy);
+    virtual ~SkProxyCanvas();
+    
+    SkCanvas*   getProxy() const { return fProxy; }
+    void        setProxy(SkCanvas* proxy);
+    
+    // overrides from SkCanvas
+
+    virtual bool getViewport(SkIPoint* size) const;
+    virtual bool setViewport(int x, int y);
+    
+    virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
+
+    virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
+    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+                          SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+    virtual void restore();
+
+    virtual bool translate(SkScalar dx, SkScalar dy);
+    virtual bool scale(SkScalar sx, SkScalar sy);
+    virtual bool rotate(SkScalar degrees);
+    virtual bool skew(SkScalar sx, SkScalar sy);
+    virtual bool concat(const SkMatrix& matrix);
+    virtual void setMatrix(const SkMatrix& matrix);
+    
+    virtual bool clipRect(const SkRect& rect,
+                          SkRegion::Op op = SkRegion::kIntersect_Op);
+    virtual bool clipPath(const SkPath& path,
+                          SkRegion::Op op = SkRegion::kIntersect_Op);
+    virtual bool clipRegion(const SkRegion& deviceRgn,
+                            SkRegion::Op op = SkRegion::kIntersect_Op);
+
+    virtual void drawPaint(const SkPaint& paint);
+    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                            const SkPaint& paint);
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint);
+    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+                            const SkPaint* paint = NULL);
+    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+                                const SkRect& dst, const SkPaint* paint = NULL);
+    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+                                  const SkPaint* paint = NULL);
+    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+                            const SkPaint* paint = NULL);
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint);
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint);
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint);
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint);
+    virtual void drawPicture(SkPicture& picture);
+    virtual void drawVertices(VertexMode vmode, int vertexCount,
+                              const SkPoint vertices[], const SkPoint texs[],
+                              const SkColor colors[], SkXfermode* xmode,
+                              const uint16_t indices[], int indexCount,
+                              const SkPaint& paint);
+    
+    virtual SkBounder* setBounder(SkBounder* bounder);
+    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
+
+    virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
+                                   bool isOpaque, bool isForLayer);
+
+private:
+    SkCanvas*   fProxy;
+    
+    typedef SkCanvas INHERITED;
+};
+
+#endif
diff --git a/include/utils/SkTextBox.h b/include/utils/SkTextBox.h
new file mode 100644
index 0000000..2c34448
--- /dev/null
+++ b/include/utils/SkTextBox.h
@@ -0,0 +1,77 @@
+/*
+ * 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 SkTextBox_DEFINED
+#define SkTextBox_DEFINED
+
+#include "SkCanvas.h"
+
+/** \class SkTextBox
+
+    SkTextBox is a helper class for drawing 1 or more lines of text
+    within a rectangle. The textbox is positioned and clipped by its Frame.
+    The Margin rectangle controls where the text is drawn relative to
+    the Frame. Line-breaks occur inside the Margin rectangle.
+
+    Spacing is a linear equation used to compute the distance between lines
+    of text. Spacing consists of two scalars: mul and add, and the spacing
+    between lines is computed as: spacing = paint.getTextSize() * mul + add
+*/
+class SkTextBox {
+public:
+    SkTextBox();
+
+    enum Mode {
+        kOneLine_Mode,
+        kLineBreak_Mode,
+
+        kModeCount
+    };
+    Mode    getMode() const { return (Mode)fMode; }
+    void    setMode(Mode);
+
+    enum SpacingAlign {
+        kStart_SpacingAlign,
+        kCenter_SpacingAlign,
+        kEnd_SpacingAlign,
+
+        kSpacingAlignCount
+    };
+    SpacingAlign    getSpacingAlign() const { return (SpacingAlign)fSpacingAlign; }
+    void            setSpacingAlign(SpacingAlign);
+
+    void    getBox(SkRect*) const;
+    void    setBox(const SkRect&);
+    void    setBox(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+    void    getSpacing(SkScalar* mul, SkScalar* add) const;
+    void    setSpacing(SkScalar mul, SkScalar add);
+
+    void    draw(SkCanvas*, const char text[], size_t len, const SkPaint&);
+
+private:
+    SkRect      fBox;
+    SkScalar    fSpacingMul, fSpacingAdd;
+    uint8_t     fMode, fSpacingAlign;
+};
+
+class SkTextLineBreaker {
+public:
+    static int CountLines(const char text[], size_t len, const SkPaint&, SkScalar width);
+};
+
+#endif
+
diff --git a/include/utils/SkUnitMappers.h b/include/utils/SkUnitMappers.h
new file mode 100644
index 0000000..51708b6
--- /dev/null
+++ b/include/utils/SkUnitMappers.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkUnitMappers_DEFINED
+#define SkUnitMappers_DEFINED
+
+#include "SkUnitMapper.h"
+
+/** This discretizes the range [0...1) into N discret values.
+*/
+class SkDiscreteMapper : public SkUnitMapper {
+public:
+    SkDiscreteMapper(int segments);
+    // override from SkUnitMapper
+    virtual uint16_t mapUnit16(uint16_t x);
+
+protected:
+    SkDiscreteMapper(SkFlattenableReadBuffer& );
+    // overrides from SkFlattenable
+    virtual void flatten(SkFlattenableWriteBuffer& );
+    virtual Factory getFactory();
+private:
+    int     fSegments;
+    SkFract fScale;    // computed from fSegments
+
+    static SkFlattenable* Create(SkFlattenableReadBuffer& buffer);
+    
+    typedef SkUnitMapper INHERITED;
+};
+
+/** This returns cos(x), to simulate lighting a sphere, where 0 maps to the
+    center of the sphere, and 1 maps to the edge.
+*/
+class SkCosineMapper : public SkUnitMapper {
+public:
+    SkCosineMapper() {}
+    // override from SkUnitMapper
+    virtual uint16_t mapUnit16(uint16_t x);
+
+protected:
+    SkCosineMapper(SkFlattenableReadBuffer&);
+    // overrides from SkFlattenable
+    virtual Factory getFactory();
+
+private:
+    static SkFlattenable* Create(SkFlattenableReadBuffer&);
+
+    typedef SkUnitMapper INHERITED;
+};
+
+#endif
+
diff --git a/include/views/SkApplication.h b/include/views/SkApplication.h
new file mode 100644
index 0000000..4c4a4fb
--- /dev/null
+++ b/include/views/SkApplication.h
@@ -0,0 +1,26 @@
+/*
+ * 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 SkApplication_DEFINED
+#define SkApplication_DEFINED
+
+class SkOSWindow;
+
+extern SkOSWindow* create_sk_window(void* hwnd);
+extern void application_init();
+extern void application_term();
+
+#endif // SkApplication_DEFINED
diff --git a/include/views/SkBGViewArtist.h b/include/views/SkBGViewArtist.h
new file mode 100644
index 0000000..1bca42f
--- /dev/null
+++ b/include/views/SkBGViewArtist.h
@@ -0,0 +1,41 @@
+/*
+ * 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 SkBGViewArtist_DEFINED
+#define SkBGViewArtist_DEFINED
+
+#include "SkView.h"
+#include "SkPaint.h"
+
+class SkBGViewArtist : public SkView::Artist {
+public:
+            SkBGViewArtist(SkColor c = SK_ColorWHITE);
+    virtual ~SkBGViewArtist();
+
+    const SkPaint&  paint() const { return fPaint; }
+    SkPaint&        paint() { return fPaint; }
+
+protected:
+    // overrides
+    virtual void onDraw(SkView*, SkCanvas*);
+    virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+    SkPaint fPaint;
+};
+
+#endif
+
diff --git a/include/views/SkBorderView.h b/include/views/SkBorderView.h
new file mode 100644
index 0000000..94ccc1f
--- /dev/null
+++ b/include/views/SkBorderView.h
@@ -0,0 +1,48 @@
+/*
+ * 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 SkBorderView_DEFINED
+#define SkBorderView_DEFINED
+
+#include "SkView.h"
+#include "SkWidgetViews.h"
+#include "SkAnimator.h"
+
+class SkBorderView : public SkWidgetView {
+public:
+    SkBorderView();
+    ~SkBorderView();
+    void setSkin(const char skin[]);
+    SkScalar getLeft() const { return fLeft; }
+    SkScalar getRight() const { return fRight; }
+    SkScalar getTop() const { return fTop; }
+    SkScalar getBottom() const { return fBottom; }
+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;
+    SkScalar fLeft, fRight, fTop, fBottom;  //margin on each side
+    SkRect fMargin;
+
+    typedef SkWidgetView INHERITED;
+};
+
+#endif
+
diff --git a/include/views/SkEvent.h b/include/views/SkEvent.h
new file mode 100644
index 0000000..2b43f34
--- /dev/null
+++ b/include/views/SkEvent.h
@@ -0,0 +1,244 @@
+/*
+ * 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 SkEvent_DEFINED
+#define SkEvent_DEFINED
+
+#include "SkDOM.h"
+#include "SkMetaData.h"
+#include "SkString.h"
+
+//class SkOSWindow;
+
+/** Unique 32bit id used to identify an instance of SkEventSink. When events are
+    posted, they are posted to a specific sinkID. When it is time to dispatch the
+    event, the sinkID is used to find the specific SkEventSink object. If it is found,
+    its doEvent() method is called with the event.
+*/
+typedef uint32_t SkEventSinkID;
+
+/** \class SkEvent
+
+    SkEvents are used to communicate type-safe information to SkEventSinks.
+    SkEventSinks (including SkViews) each have a unique ID, which is stored
+    in an event. This ID is used to target the event once it has been "posted".
+*/
+class SkEvent {
+public:
+    /** Default construct, creating an empty event.
+    */
+    SkEvent();
+    /** Construct a new event with the specified type.
+    */
+    explicit SkEvent(const SkString& type);
+    /** Construct a new event with the specified type.
+    */
+    explicit SkEvent(const char type[]);
+    /** Construct a new event by copying the fields from the src event.
+    */
+    SkEvent(const SkEvent& src);
+    ~SkEvent();
+
+//  /** Return the event's type (will never be null) */
+//  const char* getType() const;
+    /** Copy the event's type into the specified SkString parameter */
+    void    getType(SkString* str) const;
+    /** Returns true if the event's type matches exactly the specified type (case sensitive) */
+    bool    isType(const SkString& str) const;
+    /** Returns true if the event's type matches exactly the specified type (case sensitive) */
+    bool    isType(const char type[], size_t len = 0) const;
+    /** Set the event's type to the specified string.
+        In XML, use the "type" attribute.
+    */
+    void    setType(const SkString&);
+    /** Set the event's type to the specified string.
+        In XML, use the "type" attribute.
+    */
+    void    setType(const char type[], size_t len = 0);
+
+    /** Return the event's unnamed 32bit field. Default value is 0 */
+    uint32_t getFast32() const { return f32; }
+    /** Set the event's unnamed 32bit field. In XML, use
+        the subelement <data fast32=... />
+    */
+    void    setFast32(uint32_t x) { f32 = x; }
+
+    /** Return true if the event contains the named 32bit field, and return the field
+        in value (if value is non-null). If there is no matching named field, return false
+        and ignore the value parameter.
+    */
+    bool    findS32(const char name[], int32_t* value = NULL) const { return fMeta.findS32(name, value); }
+    /** Return true if the event contains the named SkScalar field, and return the field
+        in value (if value is non-null). If there is no matching named field, return false
+        and ignore the value parameter.
+    */
+    bool    findScalar(const char name[], SkScalar* value = NULL) const { return fMeta.findScalar(name, value); }
+    /** Return true if the event contains the named SkScalar field, and return the fields
+        in value[] (if value is non-null), and return the number of SkScalars in count (if count is non-null).
+        If there is no matching named field, return false and ignore the value and count parameters.
+    */
+    const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const { return fMeta.findScalars(name, count, values); }
+    /** Return the value of the named string field, or if no matching named field exists, return null.
+    */
+    const char* findString(const char name[]) const { return fMeta.findString(name); }
+    /** Return true if the event contains the named pointer field, and return the field
+        in value (if value is non-null). If there is no matching named field, return false
+        and ignore the value parameter.
+    */
+    bool    findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); }
+    bool    findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); }
+
+    /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */
+    bool    hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); }
+    /** Returns true if ethe event contains the named SkScalar field, and if it equals the specified value */
+    bool    hasScalar(const char name[], SkScalar value) const { return fMeta.hasScalar(name, value); }
+    /** Returns true if ethe event contains the named string field, and if it equals (using strcmp) the specified value */
+    bool    hasString(const char name[], const char value[]) const { return fMeta.hasString(name, value); }
+    /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */
+    bool    hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); }
+    bool    hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); }
+
+    /** Add/replace the named 32bit field to the event. In XML use the subelement <data name=... s32=... /> */
+    void    setS32(const char name[], int32_t value) { fMeta.setS32(name, value); }
+    /** Add/replace the named SkScalar field to the event. In XML use the subelement <data name=... scalar=... /> */
+    void    setScalar(const char name[], SkScalar value) { fMeta.setScalar(name, value); }
+    /** Add/replace the named SkScalar[] field to the event. */
+    SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL) { return fMeta.setScalars(name, count, values); }
+    /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */
+    void    setString(const char name[], const SkString& value) { fMeta.setString(name, value.c_str()); }
+    /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */
+    void    setString(const char name[], const char value[]) { fMeta.setString(name, value); }
+    /** Add/replace the named pointer field to the event. There is no XML equivalent for this call */
+    void    setPtr(const char name[], void* value) { fMeta.setPtr(name, value); }
+    void    setBool(const char name[], bool value) { fMeta.setBool(name, value); }
+
+    /** Return the underlying metadata object */
+    SkMetaData&         getMetaData() { return fMeta; }
+    /** Return the underlying metadata object */
+    const SkMetaData&   getMetaData() const { return fMeta; }
+
+    void tron() { SkDEBUGCODE(fDebugTrace = true;) }
+    void troff() { SkDEBUGCODE(fDebugTrace = false;) }
+    bool isDebugTrace() const
+    {
+#ifdef SK_DEBUG
+        return fDebugTrace;
+#else
+        return false;
+#endif
+    }
+
+    /** Call this to initialize the event from the specified XML node */
+    void    inflate(const SkDOM&, const SkDOM::Node*);
+
+    SkDEBUGCODE(void dump(const char title[] = NULL);)
+
+    /** Post the specified event to the event queue, targeting the specified eventsink, with an optional
+        delay. The event must be dynamically allocated for this. It cannot be a global or on the stack.
+        After this call, ownership is transfered to the system, so the caller must not retain
+        the event's ptr. Returns false if the event could not be posted (which means it will have been deleted).
+    */
+    static bool Post(SkEvent* evt, SkEventSinkID targetID, SkMSec delay = 0);
+    /** Post the specified event to the event queue, targeting the specified eventsink, to be delivered on/after the
+        specified millisecond time. The event must be dynamically allocated for this. It cannot be a global or on the stack.
+        After this call, ownership is transfered to the system, so the caller must not retain
+        the event's ptr. Returns false if the event could not be posted (which means it will have been deleted).
+    */
+    static bool PostTime(SkEvent* evt, SkEventSinkID targetID, SkMSec time);
+
+    /** Helper method for calling SkEvent::PostTime(this, ...), where the caller specifies a delay.
+        The real "time" will be computed automatically by sampling the clock and adding its value
+        to delay.
+    */
+    bool post(SkEventSinkID sinkID, SkMSec delay = 0)
+    {
+        return SkEvent::Post(this, sinkID, delay);
+    }
+
+    void postTime(SkEventSinkID sinkID, SkMSec time)
+    {
+        SkEvent::PostTime(this, sinkID, time);
+    }
+
+    ///////////////////////////////////////////////
+    /** Porting layer must call these functions **/
+    ///////////////////////////////////////////////
+
+    /** Global initialization function for the SkEvent system. Should be called exactly
+        once before any other event method is called, and should be called after the
+        call to SkGraphics::Init().
+    */
+    static void     Init();
+    /** Global cleanup function for the SkEvent system. Should be called exactly once after
+        all event methods have been called, and should be called before calling SkGraphics::Term().
+    */
+    static void     Term();
+
+    /** Call this to process one event from the queue. If it returns true, there are more events
+        to process.
+    */
+    static bool     ProcessEvent();
+    /** Call this whenever the requested timer has expired (requested by a call to SetQueueTimer).
+        It will post any delayed events whose time as "expired" onto the event queue.
+        It may also call SignalQueueTimer() and SignalNonEmptyQueue().
+    */
+    static void     ServiceQueueTimer();
+
+    ////////////////////////////////////////////////////
+    /** Porting layer must implement these functions **/
+    ////////////////////////////////////////////////////
+
+    /** Called whenever an SkEvent is posted to an empty queue, so that the OS
+        can be told to later call Dequeue().
+    */
+    static void SignalNonEmptyQueue();
+    /** Called whenever the delay until the next delayed event changes. If zero is
+        passed, then there are no more queued delay events.
+    */
+    static void SignalQueueTimer(SkMSec delay);
+
+#ifndef SK_USE_WXWIDGETS
+#ifdef SK_BUILD_FOR_WIN
+    static bool WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+#elif defined(SK_BUILD_FOR_UNIXx)
+  static uint32_t HandleTimer(uint32_t, void*);
+  static bool WndProc(Display*, Window, XEvent&);
+#endif
+#else
+    // Don't know yet what this will be
+    //static bool CustomEvent();
+#endif
+
+private:
+    SkMetaData      fMeta;
+    mutable char*   fType;  // may be characters with low bit set to know that it is not a pointer
+    uint32_t        f32;
+    SkDEBUGCODE(bool fDebugTrace;)
+
+    // these are for our implementation of the event queue
+    SkEventSinkID   fTargetID;
+    SkMSec          fTime;
+    SkEvent*        fNextEvent; // either in the delay or normal event queue
+    void initialize(const char* type, size_t typeLen);
+
+    static bool Enqueue(SkEvent* evt);
+    static SkMSec EnqueueTime(SkEvent* evt, SkMSec time);
+    static SkEvent* Dequeue(SkEventSinkID* targetID);
+    static bool     QHasEvents();
+};
+
+#endif
+
diff --git a/include/views/SkEventSink.h b/include/views/SkEventSink.h
new file mode 100644
index 0000000..27a6743
--- /dev/null
+++ b/include/views/SkEventSink.h
@@ -0,0 +1,103 @@
+/*
+ * 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 SkEventSink_DEFINED
+#define SkEventSink_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkEvent.h"
+
+struct SkTagList;
+
+/** \class SkEventSink
+
+    SkEventSink is the base class for all objects that receive SkEvents.
+*/
+class SkEventSink : public SkRefCnt {
+public:
+            SkEventSink();
+    virtual ~SkEventSink();
+
+    /** Returns this eventsink's unique ID. Use this to post SkEvents to
+        this eventsink.
+    */
+    SkEventSinkID getSinkID() const { return fID; }
+
+    /** Call this to pass an event to this object for processing. Returns true if the
+        event was handled.
+    */
+    bool doEvent(const SkEvent&);
+    /** Returns true if the sink (or one of its subclasses) understands the event as a query.
+        If so, the sink may modify the event to communicate its "answer".
+    */
+    bool doQuery(SkEvent* query);
+
+    /** Add sinkID to the list of listeners, to receive events from calls to sendToListeners()
+        and postToListeners(). If sinkID already exists in the listener list, no change is made.
+    */
+    void    addListenerID(SkEventSinkID sinkID);
+    /** Copy listeners from one event sink to another, typically from parent to child.
+        @param from the event sink to copy the listeners from
+    */
+    void copyListeners(const SkEventSink& from);
+    /** Remove sinkID from the list of listeners. If sinkID does not appear in the list,
+        no change is made.
+    */
+    void    removeListenerID(SkEventSinkID);
+    /** Returns true if there are 1 or more listeners attached to this eventsink
+    */
+    bool    hasListeners() const;
+    /** Posts a copy of evt to each of the eventsinks in the lisener list.
+    */
+    void    postToListeners(const SkEvent& evt, SkMSec delay = 0);
+
+    enum EventResult {
+        kHandled_EventResult,       //!< the eventsink returned true from its doEvent method
+        kNotHandled_EventResult,    //!< the eventsink returned false from its doEvent method
+        kSinkNotFound_EventResult   //!< no matching eventsink was found for the event's getSink().
+    };
+    /** DoEvent handles searching for an eventsink object that matches the targetID.
+        If one is found, it calls the sink's doEvent method, returning
+        either kHandled_EventResult or kNotHandled_EventResult. If no matching
+        eventsink is found, kSinkNotFound_EventResult is returned.
+    */
+    static EventResult DoEvent(const SkEvent&, SkEventSinkID targetID);
+
+    /** Returns the matching eventsink, or null if not found
+    */
+    static SkEventSink* FindSink(SkEventSinkID);
+
+protected:
+    /** Override this to handle events in your subclass. Be sure to call the inherited version
+        for events that you don't handle.
+    */
+    virtual bool onEvent(const SkEvent&);
+    virtual bool onQuery(SkEvent*);
+
+    SkTagList*  findTagList(U8CPU tag) const;
+    void        addTagList(SkTagList*);
+    void        removeTagList(U8CPU tag);
+
+private:
+    SkEventSinkID   fID;
+    SkTagList*      fTagHead;
+
+    // for our private link-list
+    SkEventSink*    fNextSink;
+};
+
+#endif
+
diff --git a/include/views/SkImageView.h b/include/views/SkImageView.h
new file mode 100644
index 0000000..157abb1
--- /dev/null
+++ b/include/views/SkImageView.h
@@ -0,0 +1,75 @@
+/*
+ * 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 SkImageView_DEFINED
+#define SkImageView_DEFINED
+
+#include "SkView.h"
+#include "SkString.h"
+
+class SkAnimator;
+class SkBitmap;
+struct SkMatrix;
+
+class SkImageView : public SkView {
+public:
+            SkImageView();
+    virtual ~SkImageView();
+
+    void    getUri(SkString*) const;
+    void    setUri(const char []);
+    void    setUri(const SkString&);
+    
+
+    enum ScaleType {
+        kMatrix_ScaleType,
+        kFitXY_ScaleType,
+        kFitStart_ScaleType,
+        kFitCenter_ScaleType,
+        kFitEnd_ScaleType
+    };
+    ScaleType   getScaleType() const { return (ScaleType)fScaleType; }
+    void        setScaleType(ScaleType);
+    
+    bool    getImageMatrix(SkMatrix*) const;
+    void    setImageMatrix(const SkMatrix*);
+
+protected:
+    // overrides
+    virtual bool    onEvent(const SkEvent&);
+    virtual void    onDraw(SkCanvas*);
+    virtual void    onInflate(const SkDOM&, const SkDOMNode*);
+    
+private:
+    SkString    fUri;
+    SkMatrix*   fMatrix;    // null or copy of caller's matrix ,,,,,
+    union {
+        SkAnimator* fAnim;
+        SkBitmap* fBitmap;
+    } fData;
+    uint8_t     fScaleType;
+    SkBool8     fDataIsAnim;    // as opposed to bitmap
+    SkBool8     fUriIsValid;
+    
+    void    onUriChange();
+    bool    getDataBounds(SkRect* bounds);
+    bool    freeData();
+    bool    ensureUriIsLoaded();
+
+    typedef SkView INHERITED;
+};
+
+#endif
diff --git a/include/views/SkKey.h b/include/views/SkKey.h
new file mode 100644
index 0000000..3fd5114
--- /dev/null
+++ b/include/views/SkKey.h
@@ -0,0 +1,63 @@
+/*
+ * 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 SkKey_DEFINED
+#define SkKey_DEFINED
+
+#include "SkTypes.h"
+
+enum SkKey {
+    //reordering these to match android.app.KeyEvent 
+    kNONE_SkKey,    //corresponds to android's UNKNOWN
+    
+    kLeftSoftKey_SkKey,
+    kRightSoftKey_SkKey,
+
+    kHome_SkKey,    //!< the home key - added to match android
+    kBack_SkKey,    //!< (CLR)
+    kSend_SkKey,    //!< the green (talk) key
+    kEnd_SkKey,     //!< the red key
+    
+    k0_SkKey,
+    k1_SkKey,
+    k2_SkKey,
+    k3_SkKey,
+    k4_SkKey,
+    k5_SkKey,
+    k6_SkKey,
+    k7_SkKey,
+    k8_SkKey,
+    k9_SkKey,
+    kStar_SkKey,    //!< the * key
+    kHash_SkKey,    //!< the # key
+
+    kUp_SkKey,
+    kDown_SkKey,
+    kLeft_SkKey,
+    kRight_SkKey,
+
+    kOK_SkKey,      //!< the center key
+
+    kVolUp_SkKey,   //!< volume up - match android
+    kVolDown_SkKey, //!< volume down - same
+    kPower_SkKey,   //!< power button - same
+    kCamera_SkKey,  //!< camera         - same
+
+    kSkKeyCount
+};
+
+#endif
+
diff --git a/include/views/SkMetaData.h b/include/views/SkMetaData.h
new file mode 100644
index 0000000..21739fe
--- /dev/null
+++ b/include/views/SkMetaData.h
@@ -0,0 +1,154 @@
+/*
+ * 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 SkMetaData_DEFINED
+#define SkMetaData_DEFINED
+
+#include "SkScalar.h"
+
+class SkMetaData {
+public:
+    SkMetaData();
+    SkMetaData(const SkMetaData& src);
+    ~SkMetaData();
+
+    SkMetaData& operator=(const SkMetaData& src);
+
+    void    reset();
+
+    bool    findS32(const char name[], int32_t* value = NULL) const;
+    bool    findScalar(const char name[], SkScalar* value = NULL) const;
+    const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const;
+    const char* findString(const char name[]) const;
+    bool    findPtr(const char name[], void** value = NULL) const;
+    bool    findBool(const char name[], bool* value = NULL) const;
+
+    bool    hasS32(const char name[], int32_t value) const
+    {
+        int32_t v;
+        return this->findS32(name, &v) && v == value;
+    }
+    bool    hasScalar(const char name[], SkScalar value) const
+    {
+        SkScalar    v;
+        return this->findScalar(name, &v) && v == value;
+    }
+    bool    hasString(const char name[], const char value[]) const
+    {
+        const char* v = this->findString(name);
+        return  v == NULL && value == NULL ||
+                v != NULL && value != NULL && !strcmp(v, value);
+    }
+    bool    hasPtr(const char name[], void* value) const
+    {
+        void*   v;
+        return this->findPtr(name, &v) && v == value;
+    }
+    bool    hasBool(const char name[], bool value) const
+    {
+        bool    v;
+        return this->findBool(name, &v) && v == value;
+    }
+
+    void    setS32(const char name[], int32_t value);
+    void    setScalar(const char name[], SkScalar value);
+    SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL);
+    void    setString(const char name[], const char value[]);
+    void    setPtr(const char name[], void* value);
+    void    setBool(const char name[], bool value);
+
+    bool    removeS32(const char name[]);
+    bool    removeScalar(const char name[]);
+    bool    removeString(const char name[]);
+    bool    removePtr(const char name[]);
+    bool    removeBool(const char name[]);
+
+    SkDEBUGCODE(static void UnitTest();)
+
+    enum Type {
+        kS32_Type,
+        kScalar_Type,
+        kString_Type,
+        kPtr_Type,
+        kBool_Type,
+
+        kTypeCount
+    };
+
+    struct Rec;
+    class Iter;
+    friend class Iter;
+
+    class Iter {
+    public:
+        Iter() : fRec(NULL) {}
+        Iter(const SkMetaData&);
+
+        /** Reset the iterator, so that calling next() will return the first
+            data element. This is done implicitly in the constructor.
+        */
+        void    reset(const SkMetaData&);
+
+        /** Each time next is called, it returns the name of the next data element,
+            or null when there are no more elements. If non-null is returned, then the
+            element's type is returned (if not null), and the number of data values
+            is returned in count (if not null).
+        */
+        const char* next(Type*, int* count);
+
+    private:
+        Rec* fRec;
+    };
+
+public:
+    struct Rec {
+        Rec*        fNext;
+        uint16_t    fDataCount; // number of elements
+        uint8_t     fDataLen;   // sizeof a single element
+#ifdef SK_DEBUG
+        Type        fType;
+#else
+        uint8_t     fType;
+#endif
+
+#ifdef SK_DEBUG
+        const char* fName;
+        union {
+            int32_t     fS32;
+            SkScalar    fScalar;
+            const char* fString;
+            void*       fPtr;
+            bool        fBool;
+        } fData;
+#endif
+
+        const void* data() const { return (this + 1); }
+        void*       data() { return (this + 1); }
+        const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
+        char*       name() { return (char*)this->data() + fDataLen * fDataCount; }
+
+        static Rec* Alloc(size_t);
+        static void Free(Rec*);
+    };
+    Rec*    fRec;
+
+    const Rec* find(const char name[], Type) const;
+    void* set(const char name[], const void* data, size_t len, Type, int count);
+    bool remove(const char name[], Type);
+};
+
+#endif
+
diff --git a/include/views/SkOSMenu.h b/include/views/SkOSMenu.h
new file mode 100644
index 0000000..433a601
--- /dev/null
+++ b/include/views/SkOSMenu.h
@@ -0,0 +1,55 @@
+/*
+ * 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 SkOSMenu_DEFINED
+#define SkOSMenu_DEFINED
+
+#include "SkEvent.h"
+#include "SkTDArray.h"
+
+class SkOSMenu {
+public:
+    explicit SkOSMenu(const char title[]);
+    ~SkOSMenu();
+
+    const char* getTitle() const { return fTitle; }
+
+    void    appendItem(const char title[], const char eventType[], int32_t eventData);
+
+    // called by SkOSWindow when it receives an OS menu event
+    int         countItems() const;
+    const char* getItem(int index, uint32_t* cmdID) const;
+
+    SkEvent* createEvent(uint32_t os_cmd);
+
+private:
+    const char* fTitle;
+
+    struct Item {
+        const char* fTitle;
+        const char* fEventType;
+        uint32_t    fEventData;
+        uint32_t    fOSCmd; // internal
+    };
+    SkTDArray<Item> fItems;
+
+    // illegal
+    SkOSMenu(const SkOSMenu&);
+    SkOSMenu& operator=(const SkOSMenu&);
+};
+
+#endif
+
diff --git a/include/views/SkOSSound.h b/include/views/SkOSSound.h
new file mode 100644
index 0000000..5d77955
--- /dev/null
+++ b/include/views/SkOSSound.h
@@ -0,0 +1,36 @@
+/*
+ * 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 SkOSSound_DEFINED
+#define SkOSSound_DEFINED
+
+#include "SkTypes.h"
+
+class SkOSSound {
+public:
+    static void Play(const char path[]);
+    static void Pause();
+    static void Resume();
+    static bool TogglePause();  // returns true if we are now playing, or false if we're now paused
+    static void Stop();
+
+    //  volume runs from 0 (silent) to 0xFF (max-volume)
+    static uint8_t GetVolume();
+    static void SetVolume(U8CPU volume);
+};
+
+#endif
+
diff --git a/include/views/SkOSWindow_Mac.h b/include/views/SkOSWindow_Mac.h
new file mode 100644
index 0000000..1f6a1fa
--- /dev/null
+++ b/include/views/SkOSWindow_Mac.h
@@ -0,0 +1,49 @@
+/*
+ * 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 SkOSWindow_Mac_DEFINED
+#define SkOSWindow_Mac_DEFINED
+
+#include "SkWindow.h"
+
+class SkOSWindow : public SkWindow {
+public:
+    SkOSWindow(void* hwnd);
+
+    void*   getHWND() const { return fHWND; }
+    void    updateSize();
+
+    static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+    static pascal OSStatus SkOSWindow::EventHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* userData );
+
+protected:
+    // overrides from SkWindow
+    virtual void onHandleInval(const SkIRect&);
+    // overrides from SkView
+    virtual void onAddMenu(const SkOSMenu*);
+    virtual void onSetTitle(const char[]);
+
+private:
+    void*   fHWND;
+
+    void    doPaint(void* ctx);
+
+    typedef SkWindow INHERITED;
+};
+
+#endif
+
diff --git a/include/views/SkOSWindow_Unix.h b/include/views/SkOSWindow_Unix.h
new file mode 100644
index 0000000..26f51be
--- /dev/null
+++ b/include/views/SkOSWindow_Unix.h
@@ -0,0 +1,60 @@
+/*
+ * 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 SkOSWindow_Unix_DEFINED
+#define SkOSWindow_Unix_DEFINED
+
+#include "SkWindow.h"
+#include <X11/Xlib.h>
+
+struct SkUnixWindow {
+  Display* fDisplay;
+  Window fWin;
+  size_t fOSWin;
+};
+
+class SkOSWindow : public SkWindow {
+public:
+    SkOSWindow(Display* display, Window win);
+
+    void*   getHWND() const { return (void*)fUnixWindow.fWin; }
+  void* getDisplay() const { return (void*)fUnixWindow.fDisplay; }
+  void* getUnixWindow() const { return (void*)&fUnixWindow; }
+  void  setSize(int width, int height);
+    void    updateSize();
+
+    static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+    static bool WndProc(SkUnixWindow* w,  XEvent &e);
+
+protected:
+    // overrides from SkWindow
+    virtual void onHandleInval(const SkIRect&);
+    // overrides from SkView
+    virtual void onAddMenu(const SkOSMenu*);
+
+private:
+    SkUnixWindow  fUnixWindow;
+
+    void    doPaint();
+
+    void*   fMBar;
+
+    typedef SkWindow INHERITED;
+};
+
+#endif
+
diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h
new file mode 100644
index 0000000..6d821db
--- /dev/null
+++ b/include/views/SkOSWindow_Win.h
@@ -0,0 +1,59 @@
+/*
+ * 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 SkOSWindow_Win_DEFINED
+#define SkOSWindow_Win_DEFINED
+
+#include "SkWindow.h"
+
+class SkOSWindow : public SkWindow {
+public:
+    SkOSWindow(void* hwnd);
+
+    void*   getHWND() const { return fHWND; }
+    void    setSize(int width, int height);
+    void    updateSize();
+
+    static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+    static bool WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+    static bool SkOSWindow::QuitOnDeactivate(HWND hWnd);
+
+    enum {
+        SK_WM_SkEvent = WM_APP + 1000,
+        SK_WM_SkTimerID = 0xFFFF    // just need a non-zero value
+    };
+
+protected:
+    virtual bool quitOnDeactivate() { return true; }
+
+    // overrides from SkWindow
+    virtual void onHandleInval(const SkIRect&);
+    // overrides from SkView
+    virtual void onAddMenu(const SkOSMenu*);
+
+private:
+    void*   fHWND;
+
+    void    doPaint(void* ctx);
+
+    HMENU   fMBar;
+
+    typedef SkWindow INHERITED;
+};
+
+#endif
+
diff --git a/include/views/SkOSWindow_wxwidgets.h b/include/views/SkOSWindow_wxwidgets.h
new file mode 100644
index 0000000..c5dfc7c
--- /dev/null
+++ b/include/views/SkOSWindow_wxwidgets.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/*
+ *  SkOSWindow_wxwidgets.h
+ *  wxwidgets
+ *
+ *  Copyright 2005 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef SkOSWindow_wxwidgets_DEFINED
+#define SkOSWindow_wxwidgets_DEFINED
+
+#include "SkWindow.h"
+#include "wx/frame.h"
+
+class SkOSWindow: public SkWindow
+{
+public:
+    SkOSWindow();
+    SkOSWindow(const wxString& title, int x, int y, int width, int height);
+    ~SkOSWindow();
+    
+    wxFrame* getWXFrame() const { return fFrame; }
+    
+    void updateSize();
+    
+protected:
+    virtual void onHandleInval(const SkIRect&);
+    virtual void onAddMenu(const SkOSMenu*);
+    
+private:
+    wxFrame* fFrame;
+    typedef SkWindow INHERITED;
+    
+};
+
+#endifpedef SkWindow INHERITED;
diff --git a/include/views/SkProgressBarView.h b/include/views/SkProgressBarView.h
new file mode 100644
index 0000000..6341fcb
--- /dev/null
+++ b/include/views/SkProgressBarView.h
@@ -0,0 +1,57 @@
+/*
+ * 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 SkProgressBarView_DEFINED
+#define SkProgressBarView_DEFINED
+
+#include "SkView.h"
+#include "SkWidgetViews.h"
+#include "SkAnimator.h"
+
+class SkProgressBarView : public SkWidgetView {
+    public:
+        SkProgressBarView();
+        //SkProgressBarView(int max);
+                
+        //inflate: "sk-progress"
+    
+        void reset();   //reset progress to zero
+        void setProgress(int progress);
+        void changeProgress(int diff);
+        void setMax(int max);
+        
+        int getProgress() const { return fProgress; }
+        int getMax() const { return fMax; }
+    
+    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;
+        int         fProgress;
+        int         fMax;
+        
+        typedef SkWidgetView INHERITED;
+};
+
+
+
+
+#endif
diff --git a/include/views/SkScrollBarView.h b/include/views/SkScrollBarView.h
new file mode 100644
index 0000000..b8a5209
--- /dev/null
+++ b/include/views/SkScrollBarView.h
@@ -0,0 +1,52 @@
+/*
+ * 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
+
diff --git a/include/views/SkStackViewLayout.h b/include/views/SkStackViewLayout.h
new file mode 100644
index 0000000..8000319
--- /dev/null
+++ b/include/views/SkStackViewLayout.h
@@ -0,0 +1,96 @@
+/*
+ * 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
+
diff --git a/include/views/SkSystemEventTypes.h b/include/views/SkSystemEventTypes.h
new file mode 100644
index 0000000..8dfe8be
--- /dev/null
+++ b/include/views/SkSystemEventTypes.h
@@ -0,0 +1,32 @@
+/*
+ * 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
diff --git a/include/views/SkView.h b/include/views/SkView.h
new file mode 100644
index 0000000..d5d89df
--- /dev/null
+++ b/include/views/SkView.h
@@ -0,0 +1,345 @@
+/*
+ * 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 SkView_DEFINED
+#define SkView_DEFINED
+
+#include "SkEventSink.h"
+#include "SkRect.h"
+#include "SkDOM.h"
+#include "SkTDict.h"
+
+class SkCanvas;
+class SkLayerView;
+
+/** \class SkView
+
+    SkView is the base class for screen management. All widgets and controls inherit
+    from SkView.
+*/
+class SkView : public SkEventSink {
+public:
+    enum Flag_Shift {
+        kVisible_Shift,
+        kEnabled_Shift,
+        kFocusable_Shift,
+        kFlexH_Shift,
+        kFlexV_Shift,
+
+        kFlagShiftCount
+    };
+    enum Flag_Mask {
+        kVisible_Mask   = 1 << kVisible_Shift,      //!< set if the view is visible
+        kEnabled_Mask   = 1 << kEnabled_Shift,      //!< set if the view is enabled
+        kFocusable_Mask = 1 << kFocusable_Shift,    //!< set if the view can receive focus
+        kFlexH_Mask     = 1 << kFlexH_Shift,        //!< set if the view's width is stretchable
+        kFlexV_Mask     = 1 << kFlexV_Shift,        //!< set if the view's height is stretchable
+
+        kAllFlagMasks   = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount)
+    };
+
+                SkView(uint32_t flags = 0);
+    virtual     ~SkView();
+
+    /** Return the flags associated with the view
+    */
+    uint32_t    getFlags() const { return fFlags; }
+    /** Set the flags associated with the view
+    */
+    void        setFlags(uint32_t flags);
+
+    /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags
+    */
+    int         isVisible() const { return fFlags & kVisible_Mask; }
+    int         isEnabled() const { return fFlags & kEnabled_Mask; }
+    int         isFocusable() const { return fFlags & kFocusable_Mask; }
+    /** Helper to set/clear the view's kVisible_Mask flag */
+    void        setVisibleP(bool);
+    void        setEnabledP(bool);
+    void        setFocusableP(bool);
+
+    /** Return the view's width */
+    SkScalar    width() const { return fWidth; }
+    /** Return the view's height */
+    SkScalar    height() const { return fHeight; }
+    /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */
+    void        setSize(SkScalar width, SkScalar height);
+    void        setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }
+    void        setWidth(SkScalar width) { this->setSize(width, fHeight); }
+    void        setHeight(SkScalar height) { this->setSize(fWidth, height); }
+    /** Return a rectangle set to [0, 0, width, height] */
+    void        getLocalBounds(SkRect* bounds) const;
+
+    /** Return the view's left edge */
+    SkScalar    locX() const { return fLoc.fX; }
+    /** Return the view's top edge */
+    SkScalar    locY() const { return fLoc.fY; }
+    /** Set the view's left and top edge. This does not affect the view's size */
+    void        setLoc(SkScalar x, SkScalar y);
+    void        setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); }
+    void        setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); }
+    void        setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); }
+    /** Offset (move) the view by the specified dx and dy. This does not affect the view's size */
+    void        offset(SkScalar dx, SkScalar dy);
+
+    /** Call this to have the view draw into the specified canvas. */
+    void        draw(SkCanvas* canvas);
+    /** Call this to invalidate part of all of a view, requesting that the view's
+        draw method be called. The rectangle parameter specifies the part of the view
+        that should be redrawn. If it is null, it specifies the entire view bounds.
+    */
+    void        inval(SkRect* rectOrNull);
+
+    //  Focus management
+
+    SkView* getFocusView() const;
+    bool    hasFocus() const;
+
+    enum FocusDirection {
+        kNext_FocusDirection,
+        kPrev_FocusDirection,
+
+        kFocusDirectionCount
+    };
+    bool    acceptFocus();
+    SkView* moveFocus(FocusDirection);
+
+    //  Click handling
+
+    class Click {
+    public:
+        Click(SkView* target);
+        virtual ~Click();
+
+        const char* getType() const { return fType; }
+        bool        isType(const char type[]) const;
+        void        setType(const char type[]);     // does NOT make a copy of the string
+        void        copyType(const char type[]);    // makes a copy of the string
+
+        enum State {
+            kDown_State,
+            kMoved_State,
+            kUp_State
+        };
+        SkPoint     fOrig, fPrev, fCurr;
+        SkIPoint    fIOrig, fIPrev, fICurr;
+        State       fState;
+    private:
+        SkEventSinkID   fTargetID;
+        char*           fType;
+        bool            fWeOwnTheType;
+
+        void resetType();
+
+        friend class SkView;
+    };
+    Click*  findClickHandler(SkScalar x, SkScalar y);
+
+    static void DoClickDown(Click*, int x, int y);
+    static void DoClickMoved(Click*, int x, int y);
+    static void DoClickUp(Click*, int x, int y);
+
+    /** Send the event to the view's parent, and its parent etc. until one of them
+        returns true from its onEvent call. This view is returned. If no parent handles
+        the event, null is returned.
+    */
+    SkView*     sendEventToParents(const SkEvent&);
+    /** Depricated helper function. Just call event->post(sinkID, delay);
+    */
+    bool    postEvent(SkEvent* evt, SkEventSinkID sinkID, SkMSec delay) { return evt->post(sinkID, delay); }
+
+    //  View hierarchy management
+
+    /** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */
+    SkView*     getParent() const { return fParent; }
+    SkView*     attachChildToFront(SkView* child);
+    /** Attach the child view to this view, and increment the child's reference count. The child view is added
+        such that it will be drawn before all other child views.
+        The child view parameter is returned.
+    */
+    SkView*     attachChildToBack(SkView* child);
+    /** If the view has a parent, detach the view from its parent and decrement the view's reference count.
+        If the parent was the only owner of the view, this will cause the view to be deleted.
+    */
+    void        detachFromParent();
+    /** Attach the child view to this view, and increment the child's reference count. The child view is added
+        such that it will be drawn after all other child views.
+        The child view parameter is returned.
+    */
+    /** Detach all child views from this view. */
+    void        detachAllChildren();
+
+    /** Convert the specified point from global coordinates into view-local coordinates
+    */
+    void        globalToLocal(SkPoint* pt) const { if (pt) this->globalToLocal(pt->fX, pt->fY, pt); }
+    /** Convert the specified x,y from global coordinates into view-local coordinates, returning
+        the answer in the local parameter.
+    */
+    void        globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const;
+
+    /** \class F2BIter
+    
+        Iterator that will return each of this view's children, in
+        front-to-back order (the order used for clicking). The first
+        call to next() returns the front-most child view. When
+        next() returns null, there are no more child views.
+    */
+    class F2BIter {
+    public:
+        F2BIter(const SkView* parent);
+        SkView* next();
+    private:
+        SkView* fFirstChild, *fChild;
+    };
+
+    /** \class B2FIter
+    
+        Iterator that will return each of this view's children, in
+        back-to-front order (the order they are drawn). The first
+        call to next() returns the back-most child view. When
+        next() returns null, there are no more child views.
+    */
+    class B2FIter {
+    public:
+        B2FIter(const SkView* parent);
+        SkView* next();
+    private:
+        SkView* fFirstChild, *fChild;
+    };
+
+    /** \class Artist
+    
+        Install a subclass of this in a view (calling setArtist()), and then the
+        default implementation of that view's onDraw() will invoke this object
+        automatically.
+    */
+    class Artist : public SkRefCnt {
+    public:
+        void draw(SkView*, SkCanvas*);
+        void inflate(const SkDOM&, const SkDOM::Node*);
+    protected:
+        virtual void onDraw(SkView*, SkCanvas*) = 0;
+        virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+    };
+    /** Return the artist attached to this view (or null). The artist's reference
+        count is not affected.
+    */
+    Artist* getArtist() const;
+    /** Attach the specified artist (or null) to the view, replacing any existing
+        artist. If the new artist is not null, its reference count is incremented.
+        The artist parameter is returned.
+    */
+    Artist* setArtist(Artist* artist);
+
+    /** \class Layout
+    
+        Install a subclass of this in a view (calling setLayout()), and then the
+        default implementation of that view's onLayoutChildren() will invoke
+        this object automatically.
+    */
+    class Layout : public SkRefCnt {
+    public:
+        void layoutChildren(SkView* parent);
+        void inflate(const SkDOM&, const SkDOM::Node*);
+    protected:
+        virtual void onLayoutChildren(SkView* parent) = 0;
+        virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+    };
+
+    /** Return the layout attached to this view (or null). The layout's reference
+        count is not affected.
+    */
+    Layout* getLayout() const;
+    /** Attach the specified layout (or null) to the view, replacing any existing
+        layout. If the new layout is not null, its reference count is incremented.
+        The layout parameter is returned.
+    */
+    Layout* setLayout(Layout*, bool invokeLayoutNow = true);
+    /** If a layout is attached to this view, call its layoutChildren() method
+    */
+    void    invokeLayout();
+
+    /** Call this to initialize this view based on the specified XML node
+    */
+    void    inflate(const SkDOM& dom, const SkDOM::Node* node);
+    /** After a view hierarchy is inflated, this may be called with a dictionary
+        containing pairs of <name, view*>, where the name string was the view's
+        "id" attribute when it was inflated.
+
+        This will call the virtual onPostInflate for this view, and the recursively
+        call postInflate on all of the view's children.
+    */
+    void    postInflate(const SkTDict<SkView*>& ids);
+
+    SkDEBUGCODE(void dump(bool recurse) const;)
+
+protected:
+    /** Override this to draw inside the view. Be sure to call the inherited version too */
+    virtual void    onDraw(SkCanvas*);
+    /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */
+    virtual void    onSizeChange();
+    /** Override this if you want to handle an inval request from this view or one of its children.
+        Tyically this is only overridden by the by the "window". If your subclass does handle the
+        request, return true so the request will not continue to propogate to the parent.
+    */
+    virtual bool    handleInval(const SkRect&);
+    virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; }
+    virtual void afterChildren(SkCanvas* orig) {}
+    /** Override this if you might handle the click
+    */
+    virtual Click*  onFindClickHandler(SkScalar x, SkScalar y);
+    /** Override this to track clicks, returning true as long as you want to track
+        the pen/mouse.
+    */
+    virtual bool    onClick(Click*);
+    /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */
+    virtual void    onInflate(const SkDOM& dom, const SkDOM::Node* node);
+    /** Override this if you want to perform post initialization work based on the ID dictionary built
+        during XML parsing. Be sure to call the inherited version too.
+    */
+    virtual void    onPostInflate(const SkTDict<SkView*>&);
+
+public:
+    // default action is to inval the view
+    virtual void    onFocusChange(bool gainFocusP);
+protected:
+
+    // override these if you're acting as a layer/host
+    virtual bool    onGetFocusView(SkView**) const { return false; }
+    virtual bool    onSetFocusView(SkView*) { return false; }
+
+private:
+    SkScalar    fWidth, fHeight;
+    SkPoint     fLoc;
+    SkView*     fParent;
+    SkView*     fFirstChild;
+    SkView*     fNextSibling;
+    SkView*     fPrevSibling;
+    uint8_t     fFlags;
+    uint8_t     fContainsFocus;
+
+    friend class B2FIter;
+    friend class F2BIter;
+    
+    friend class SkLayerView;
+
+    bool    setFocusView(SkView* fvOrNull);
+    SkView* acceptFocus(FocusDirection);
+    void    detachFromParent_NoLayout();
+};
+
+#endif
+
diff --git a/include/views/SkViewInflate.h b/include/views/SkViewInflate.h
new file mode 100644
index 0000000..3ec65a6
--- /dev/null
+++ b/include/views/SkViewInflate.h
@@ -0,0 +1,79 @@
+/*
+ * 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 SkViewInflate_DEFINED
+#define SkViewInflate_DEFINED
+
+#include "SkDOM.h"
+#include "SkTDict.h"
+#include "SkEvent.h"
+
+class SkView;
+
+class SkViewInflate {
+public: 
+            SkViewInflate();
+    virtual ~SkViewInflate();
+
+    /** Return the tree of inflated views. If root is null, create the root element
+        as a view, otherwise assume root is that view, and just "inflate" it.
+
+        Returns null if the tree cannot be built.
+    */
+    SkView* inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root = NULL);
+    SkView* inflate(const char xml[], size_t len, SkView* root = NULL);
+
+    /** Given an id attribute value, return the corresponding view, or null
+        if no match is found.
+    */
+    SkView* findViewByID(const char id[]) const;
+    
+    SkDEBUGCODE(void dump() const;)
+
+protected:
+    /*  Override this in your subclass to handle instantiating views
+        Call the inherited version for nodes you don't recognize.
+
+        Do not call "inflate" on the view, just return it. This will
+        get called automatically after createView returns.
+    */
+    virtual SkView* createView(const SkDOM& dom, const SkDOM::Node* node);
+    /** Base implementation calls view->inflate(dom, node). Subclasses may override this
+        to perform additional initializations to view, either before or after calling
+        the inherited version.
+    */
+    virtual void inflateView(SkView* view, const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+    enum {
+        kMinIDStrAlloc = 64
+    };
+    SkTDict<SkView*> fIDs;
+
+    struct IDStr {
+        SkView* fView;
+        char*   fStr;
+    };
+    SkTDArray<IDStr>    fListenTo, fBroadcastTo;
+    SkChunkAlloc        fStrings;
+
+    void addIDStr(SkTDArray<IDStr>* list, SkView*, const char* str);
+
+    void    rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent);
+};
+
+#endif
+
diff --git a/include/views/SkWidget.h b/include/views/SkWidget.h
new file mode 100644
index 0000000..db85f01
--- /dev/null
+++ b/include/views/SkWidget.h
@@ -0,0 +1,476 @@
+/*
+ * 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 SkWidget_DEFINED
+#define SkWidget_DEFINED
+
+#include "SkView.h"
+#include "SkBitmap.h"
+#include "SkDOM.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+class SkWidget : public SkView {
+public:
+    SkWidget(uint32_t flags = 0) : SkView(flags | kFocusable_Mask | kEnabled_Mask) {}
+
+    /** Call this to post the widget's event to its listeners */
+    void    postWidgetEvent();
+
+    static void Init();
+    static void Term();
+protected:
+    // override to add slots to an event before posting
+    virtual void prepareWidgetEvent(SkEvent*);
+    virtual void onEnabledChange();
+
+    // <event ...> to initialize the event from XML
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+    SkEvent fEvent;
+    typedef SkView INHERITED;
+};
+
+class SkHasLabelWidget : public SkWidget {
+public:
+    SkHasLabelWidget(uint32_t flags = 0) : SkWidget(flags) {}
+
+    size_t  getLabel(SkString* label = NULL) const;
+    size_t  getLabel(char lable[] = NULL) const;
+    void    setLabel(const SkString&);
+    void    setLabel(const char label[]);
+    void    setLabel(const char label[], size_t len);
+
+protected:
+    // called when the label changes
+    virtual void onLabelChange();
+
+    // overrides
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+    SkString    fLabel;
+    typedef SkWidget INHERITED;
+};
+
+class SkButtonWidget : public SkHasLabelWidget {
+public:
+    SkButtonWidget(uint32_t flags = 0) : SkHasLabelWidget(flags), fState(kOff_State) {}
+
+    enum State {
+        kOff_State,     //!< XML: buttonState="off"
+        kOn_State,      //!< XML: buttonState="on"
+        kUnknown_State  //!< XML: buttonState="unknown"
+    };
+    State   getButtonState() const { return fState; }
+    void    setButtonState(State);
+
+protected:
+    /** called when the label changes. default behavior is to inval the widget */
+    virtual void onButtonStateChange();
+
+    // overrides
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+    State   fState;
+    typedef SkHasLabelWidget INHERITED;
+};
+
+class SkPushButtonWidget : public SkButtonWidget {
+public:
+    SkPushButtonWidget(uint32_t flags = 0) : SkButtonWidget(flags) {}
+
+protected:
+    virtual bool onEvent(const SkEvent&);
+    virtual void onDraw(SkCanvas*);
+    virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
+    virtual bool onClick(Click* click);
+
+private:
+    typedef SkButtonWidget INHERITED;
+};
+
+class SkCheckBoxWidget : public SkButtonWidget {
+public:
+    SkCheckBoxWidget(uint32_t flags = 0);
+
+protected:
+    virtual bool onEvent(const SkEvent&);
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+    typedef SkButtonWidget INHERITED;
+};
+
+#include "SkTextBox.h"
+
+class SkStaticTextView : public SkView {
+public:
+            SkStaticTextView(uint32_t flags = 0);
+    virtual ~SkStaticTextView();
+
+    enum Mode {
+        kFixedSize_Mode,
+        kAutoWidth_Mode,
+        kAutoHeight_Mode,
+
+        kModeCount
+    };
+    Mode    getMode() const { return (Mode)fMode; }
+    void    setMode(Mode);
+
+    SkTextBox::SpacingAlign getSpacingAlign() const { return (SkTextBox::SpacingAlign)fSpacingAlign; }
+    void    setSpacingAlign(SkTextBox::SpacingAlign);
+
+    void    getMargin(SkPoint* margin) const;
+    void    setMargin(SkScalar dx, SkScalar dy);
+
+    size_t  getText(SkString* text = NULL) const;
+    size_t  getText(char text[] = NULL) const;
+    void    setText(const SkString&);
+    void    setText(const char text[]);
+    void    setText(const char text[], size_t len);
+
+    void    getPaint(SkPaint*) const;
+    void    setPaint(const SkPaint&);
+
+protected:
+    // overrides
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+    SkPoint     fMargin;
+    SkString    fText;
+    SkPaint     fPaint;
+    uint8_t     fMode;
+    uint8_t     fSpacingAlign;
+
+    void computeSize();
+
+    typedef SkView INHERITED;
+};
+
+class SkBitmapView : public SkView {
+public:
+            SkBitmapView(uint32_t flags = 0);
+    virtual ~SkBitmapView();
+
+    bool    getBitmap(SkBitmap*) const;
+    void    setBitmap(const SkBitmap*, bool viewOwnsPixels);
+    bool    loadBitmapFromFile(const char path[]);
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+    SkBitmap    fBitmap;
+    typedef SkView INHERITED;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class SkShader;
+class SkInterpolator;
+
+class SkWidgetView : public SkView {
+public:
+            SkWidgetView(uint32_t flags = 0);
+    virtual ~SkWidgetView();
+
+    static const char*  GetEventType();
+};
+
+class SkSliderView : public SkWidgetView {
+public:
+    SkSliderView(uint32_t flags = 0);
+
+    uint16_t    getValue() const { return fValue; }
+    uint16_t    getMax() const { return fMax; }
+
+    void    setMax(U16CPU max);
+    void    setValue(U16CPU value);
+
+protected:
+    virtual void    onDraw(SkCanvas*);
+    virtual Click*  onFindClickHandler(SkScalar x, SkScalar y);
+    virtual bool    onClick(Click*);
+
+private:
+    uint16_t fValue, fMax;
+
+    typedef SkWidgetView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class SkHasLabelView : public SkView {
+public:
+    void    getLabel(SkString*) const;
+    void    setLabel(const SkString&);
+    void    setLabel(const char label[]);
+
+protected:
+    SkString    fLabel;
+
+    // called when the label changes
+    virtual void onLabelChange();
+
+    // overrides
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+};
+
+class SkPushButtonView : public SkHasLabelView {
+public:
+    SkPushButtonView(uint32_t flags = 0);
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+};
+
+class SkCheckBoxView : public SkHasLabelView {
+public:
+    SkCheckBoxView(uint32_t flags = 0);
+
+    enum State {
+        kOff_State,
+        kOn_State,
+        kMaybe_State
+    };
+    State   getState() const { return fState; }
+    void    setState(State);
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+    State   fState;
+};
+
+class SkProgressView : public SkView {
+public:
+    SkProgressView(uint32_t flags = 0);
+    virtual ~SkProgressView();
+
+    uint16_t    getValue() const { return fValue; }
+    uint16_t    getMax() const { return fMax; }
+
+    void    setMax(U16CPU max);
+    void    setValue(U16CPU value);
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+    uint16_t    fValue, fMax;
+    SkShader*   fOnShader, *fOffShader;
+    SkInterpolator* fInterp;
+    bool fDoInterp;
+
+    typedef SkView INHERITED;
+};
+
+class SkTextView : public SkView {
+public:
+            SkTextView(uint32_t flags = 0);
+    virtual ~SkTextView();
+
+    enum AnimaDir {
+        kNeutral_AnimDir,
+        kForward_AnimDir,
+        kBackward_AnimDir,
+        kAnimDirCount
+    };
+
+    void    getText(SkString*) const;
+    void    setText(const SkString&, AnimaDir dir = kNeutral_AnimDir);
+    void    setText(const char text[], AnimaDir dir = kNeutral_AnimDir);
+    void    setText(const char text[], size_t len, AnimaDir dir = kNeutral_AnimDir);
+
+    void    getMargin(SkPoint* margin) const;
+    void    setMargin(const SkPoint&);
+
+    SkPaint&    paint() { return fPaint; }
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+    SkString fText;
+    SkPaint  fPaint;
+    SkPoint  fMargin;
+
+    class Interp;
+    Interp* fInterp;
+    bool    fDoInterp;
+    // called by the other setText methods. This guy does not check for !=
+    // before doing the assign, so the caller must check for us
+    void privSetText(const SkString&, AnimaDir dir);
+
+    typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////
+
+class SkEvent;
+
+class SkListSource : public SkEventSink {
+public:
+    virtual int countRows() = 0;
+    virtual void getRow(int index, SkString* left, SkString* right) = 0;
+    virtual SkEvent* getEvent(int index);
+
+    static SkListSource* CreateFromDir(const char path[], const char suffix[],
+                                        const char targetPrefix[]);
+    static SkListSource* CreateFromDOM(const SkDOM& dom, const SkDOM::Node* node);
+};
+
+class SkListView : public SkWidgetView {
+public:
+            SkListView(uint32_t flags = 0);
+    virtual ~SkListView();
+
+    SkScalar    getRowHeight() const { return fRowHeight; }
+    void        setRowHeight(SkScalar);
+
+    /** Return the index of the selected row, or -1 if none
+    */
+    int     getSelection() const { return fCurrIndex; }
+    /** Set the index of the selected row, or -1 for none
+    */
+    void    setSelection(int);
+
+    void    moveSelectionUp();
+    void    moveSelectionDown();
+
+    enum Attr {
+        kBG_Attr,
+        kNormalText_Attr,
+        kHiliteText_Attr,
+        kHiliteCell_Attr,
+        kAttrCount
+    };
+    SkPaint&    paint(Attr);
+
+    SkListSource*   getListSource() const { return fSource; }
+    SkListSource*   setListSource(SkListSource*);
+
+#if 0
+    enum Action {
+        kSelectionChange_Action,
+        kSelectionPicked_Action,
+        kActionCount
+    };
+    /** If event is not null, it is retained by the view, and a copy
+        of the event will be posted to its listeners when the specified
+        action occurs. If event is null, then no event will be posted for
+        the specified action.
+    */
+    void    setActionEvent(Action, SkEvent* event);
+#endif
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onSizeChange();
+    virtual bool onEvent(const SkEvent&);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+    SkPaint         fPaint[kAttrCount];
+    SkListSource*   fSource;
+    SkScalar        fRowHeight;
+    int             fCurrIndex;     // logical index
+    int             fScrollIndex;   // logical index of top-most visible row
+    int             fVisibleRowCount;
+    SkString*       fStrCache;
+
+    void    dirtyStrCache();
+    void    ensureStrCache(int visibleCount);
+
+    int     logicalToVisualIndex(int index) const { return index - fScrollIndex; }
+    void    invalSelection();
+    bool    getRowRect(int index, SkRect*) const;
+    void    ensureSelectionIsVisible();
+
+    typedef SkWidgetView INHERITED;
+};
+
+//////////////////////////////////////////////////////////
+
+class SkGridView : public SkWidgetView {
+public:
+            SkGridView(uint32_t flags = 0);
+    virtual ~SkGridView();
+
+    void    getCellSize(SkPoint*) const;
+    void    setCellSize(SkScalar x, SkScalar y);
+
+    /** Return the index of the selected item, or -1 if none
+    */
+    int     getSelection() const { return fCurrIndex; }
+    /** Set the index of the selected row, or -1 for none
+    */
+    void    setSelection(int);
+
+    void    moveSelectionUp();
+    void    moveSelectionDown();
+
+    enum Attr {
+        kBG_Attr,
+        kHiliteCell_Attr,
+        kAttrCount
+    };
+    SkPaint&    paint(Attr);
+
+    SkListSource*   getListSource() const { return fSource; }
+    SkListSource*   setListSource(SkListSource*);
+
+protected:
+    virtual void onDraw(SkCanvas*);
+    virtual void onSizeChange();
+    virtual bool onEvent(const SkEvent&);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+    SkView*         fScrollBar;
+    SkPaint         fPaint[kAttrCount];
+    SkListSource*   fSource;
+    int             fCurrIndex;     // logical index
+
+    SkPoint         fCellSize;
+    SkIPoint        fVisibleCount;
+
+    int     logicalToVisualIndex(int index) const { return index; }
+    void    invalSelection();
+    bool    getCellRect(int index, SkRect*) const;
+    void    ensureSelectionIsVisible();
+
+    typedef SkWidgetView INHERITED;
+};
+
+#endif
+
diff --git a/include/views/SkWidgetViews.h b/include/views/SkWidgetViews.h
new file mode 100644
index 0000000..4dd8866
--- /dev/null
+++ b/include/views/SkWidgetViews.h
@@ -0,0 +1,310 @@
+/*
+ * 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 SkWidgetViews_DEFINED
+#define SkWidgetViews_DEFINED
+
+#include "SkView.h"
+
+
+enum SkWidgetEnum {
+    kBorder_WidgetEnum,         //!< <sk-border>
+    kButton_WidgetEnum,         //!< <sk-button>
+    kImage_WidgetEnum,          //!< <sk-image>
+    kList_WidgetEnum,           //!< <sk-list>
+    kProgress_WidgetEnum,       //!< <sk-progress>
+    kScroll_WidgetEnum,         //!< <sk-scroll>
+    kText_WidgetEnum,           //!< <sk-text>
+    
+    kWidgetEnumCount
+};
+
+//determines which skin to use
+enum SkinEnum {
+    kBorder_SkinEnum,
+    kButton_SkinEnum,
+    kProgress_SkinEnum,
+    kScroll_SkinEnum,
+    kStaticText_SkinEnum,
+    
+    kSkinEnumCount
+};
+
+#include "SkAnimator.h"
+//used for inflates
+const char* get_skin_enum_path(SkinEnum se);
+void init_skin_anim(const char path[], SkAnimator* anim);
+void init_skin_anim(SkinEnum se, SkAnimator* anim);
+void init_skin_paint(SkinEnum se, SkPaint* paint);
+void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint);
+
+/** Given an enum value, return an instance of the specified widget.
+    If the enum is out of range, returns null
+*/
+SkView* SkWidgetFactory(SkWidgetEnum);
+/** Given the inflate/element name of a widget, return an instance of
+    the specified widget, or null if name does not match any known
+    widget type.
+*/
+SkView* SkWidgetFactory(const char name[]);
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkWidgetView : public SkView {
+public:
+    SkWidgetView();
+
+    const char* getLabel() const;
+    void        getLabel(SkString* label) const;
+
+    void        setLabel(const char[]);
+    void        setLabel(const char[], size_t len);
+    void        setLabel(const SkString&);
+
+    SkEvent&        event() { return fEvent; }
+    const SkEvent&  event() const { return fEvent; }
+
+    /** Returns true if the widget can post its event to its listeners.
+    */
+    bool    postWidgetEvent();
+    
+    /** Returns the sinkID of the widgetview that posted the event, or 0
+    */
+    static SkEventSinkID GetWidgetEventSinkID(const SkEvent&);
+
+protected:
+    /** called when the label changes. override in subclasses. default action invals the view's bounds.
+        called with the old and new labels, before the label has actually changed.
+    */
+    virtual void onLabelChange(const char oldLabel[], const char newLabel[]);
+    /** called before posting the event to our listeners. Override to add slots to the event
+        before posting. Return true to proceed with posting, or false to not post the event to any
+        listener. Note: the event passed in may not be the same as calling this->event().
+        Be sure to call your INHERITED method as well, so that all classes in the hierarchy get a shot
+        at modifying the event (and possibly returning false to abort).
+    */
+    virtual bool onPrepareWidgetEvent(SkEvent* evt);
+
+    // overrides
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+    
+private:
+    SkString    fLabel;
+    SkEvent     fEvent;
+    
+    typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkButtonView : public SkWidgetView {
+public:
+    // inflate: "sk-button"
+    
+protected:
+    // overrides
+    virtual bool onEvent(const SkEvent&);
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkCheckButtonView : public SkWidgetView {
+public:
+    SkCheckButtonView();
+
+    // inflate: "sk-checkbutton"
+    
+    enum CheckState {
+        kOff_CheckState,        //!< inflate: check-state="off"
+        kOn_CheckState,         //!< inflate: check-state="on"
+        kUnknown_CheckState     //!< inflate: check-state="unknown"
+    };
+    CheckState  getCheckState() const { return (CheckState)fCheckState; }
+    void        setCheckState(CheckState);
+
+    /** use this to extract the CheckState from an event (i.e. one that as posted
+        by a SkCheckButtonView). Returns true if the proper slot was present in the event,
+        and sets state to that value. If no proper slot is found, returns false and does not
+        modify state.
+    */
+    static bool GetWidgetEventCheckState(const SkEvent&, CheckState* state);
+
+protected:
+    // called when the check-state is about to change, but before it actually has
+    virtual void onCheckStateChange(CheckState oldState, CheckState newState);
+
+    // overrides
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+    virtual bool onPrepareWidgetEvent(SkEvent* evt);
+    
+private:
+    uint8_t  fCheckState;
+    
+    typedef SkWidgetView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+#include "SkTextBox.h"
+
+class SkStaticTextView : public SkView {
+public:
+            SkStaticTextView();
+    virtual ~SkStaticTextView();
+
+    enum Mode {
+        kFixedSize_Mode,
+        kAutoWidth_Mode,
+        kAutoHeight_Mode,
+
+        kModeCount
+    };
+    Mode    getMode() const { return (Mode)fMode; }
+    void    setMode(Mode);
+
+    SkTextBox::SpacingAlign getSpacingAlign() const { return (SkTextBox::SpacingAlign)fSpacingAlign; }
+    void    setSpacingAlign(SkTextBox::SpacingAlign);
+
+    void    getMargin(SkPoint* margin) const;
+    void    setMargin(SkScalar dx, SkScalar dy);
+
+    size_t  getText(SkString* text = NULL) const;
+    size_t  getText(char text[] = NULL) const;
+    void    setText(const SkString&);
+    void    setText(const char text[]);
+    void    setText(const char text[], size_t len);
+
+    void    getPaint(SkPaint*) const;
+    void    setPaint(const SkPaint&);
+
+protected:
+    // overrides
+    virtual void onDraw(SkCanvas*);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+    SkPoint     fMargin;
+    SkString    fText;
+    SkPaint     fPaint;
+    uint8_t     fMode;
+    uint8_t     fSpacingAlign;
+
+    void computeSize();
+
+    typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkAnimator;
+class SkListSource;
+class SkScrollBarView;
+
+class SkListView : public SkWidgetView {
+public:
+            SkListView();
+    virtual ~SkListView();
+
+    bool    hasScrollBar() const { return fScrollBar != NULL; }
+    void    setHasScrollBar(bool);
+    
+    /** Return the number of visible rows
+    */
+    int     getVisibleRowCount() const { return fVisibleRowCount; }
+    /** Return the index of the selected row, or -1 if none
+    */
+    int     getSelection() const { return fCurrIndex; }
+    /** Set the index of the selected row, or -1 for none
+    */
+    void    setSelection(int);
+    /** If possible, move the selection up and return true,
+        else do nothing and return false
+        If nothing is selected, select the last item (unless there are no items).
+    */
+    bool    moveSelectionUp();
+    /** If possible, move the selection down and return true,
+        else do nothing and return false.
+        If nothing is selected, select the first item (unless there are no items).
+    */
+    bool    moveSelectionDown();
+
+    SkListSource*   getListSource() const { return fSource; }
+    SkListSource*   setListSource(SkListSource*);
+
+    /** Call this in your event handler. If the specified event is from a SkListView,
+        then it returns the index of the selected item in this list, otherwise it
+        returns -1
+    */
+    static int GetWidgetEventListIndex(const SkEvent&);
+
+protected:
+    // overrides
+    virtual void onDraw(SkCanvas*);
+    virtual void onSizeChange();
+    virtual bool onEvent(const SkEvent&);
+    virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+    virtual bool onPrepareWidgetEvent(SkEvent*);
+
+private:
+    enum DirtyFlags {
+        kAnimCount_DirtyFlag    = 0x01,
+        kAnimContent_DirtyFlag  = 0x02
+    };
+    void    dirtyCache(unsigned dirtyFlags);
+    bool    ensureCache();
+
+    int     logicalToVisualIndex(int index) const { return index - fScrollIndex; }
+    void    invalSelection();
+    SkScalar getContentWidth() const;
+    bool    getRowRect(int index, SkRect*) const;
+    void    ensureSelectionIsVisible();
+    void    ensureVisibleRowCount();
+
+    struct BindingRec;
+
+    enum Heights {
+        kNormal_Height,
+        kSelected_Height
+    };
+    SkListSource*   fSource;
+    SkScrollBarView*    fScrollBar;
+    SkAnimator*     fAnims;
+    BindingRec*     fBindings;
+    SkString        fSkinName;
+    SkScalar        fHeights[2];
+    int16_t         fScrollIndex, fCurrIndex;
+    uint16_t        fVisibleRowCount, fBindingCount;
+    SkBool8         fAnimContentDirty;
+    SkBool8         fAnimFocusDirty;
+
+    typedef SkWidgetView INHERITED;
+};
+
+class SkListSource : public SkRefCnt {
+public:
+    virtual int countFields();
+    virtual void getFieldName(int index, SkString* field);
+    /** Return the index of the named field, or -1 if not found */
+    virtual int findFieldIndex(const char field[]);
+
+    virtual int countRecords();
+    virtual void getRecord(int rowIndex, int fieldIndex, SkString* data);
+
+    virtual bool prepareWidgetEvent(SkEvent*, int rowIndex);
+    
+    static SkListSource* Factory(const char name[]);
+};
+
+#endif
diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h
new file mode 100644
index 0000000..96262ee
--- /dev/null
+++ b/include/views/SkWindow.h
@@ -0,0 +1,102 @@
+/*
+ * 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 SkWindow_DEFINED
+#define SkWindow_DEFINED
+
+#include "SkView.h"
+#include "SkBitmap.h"
+#include "SkRegion.h"
+#include "SkEvent.h"
+#include "SkKey.h"
+#include "SkTDArray.h"
+
+#ifdef SK_BUILD_FOR_WINCEx
+    #define SHOW_FPS
+#endif
+//#define USE_GX_SCREEN
+
+class SkOSMenu;
+
+class SkWindow : public SkView {
+public:
+            SkWindow();
+    virtual ~SkWindow();
+
+    const SkBitmap& getBitmap() const { return fBitmap; }
+
+    void    setConfig(SkBitmap::Config);
+    void    resize(int width, int height, SkBitmap::Config config = SkBitmap::kNo_Config);
+    void    eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+    void    eraseRGB(U8CPU r, U8CPU g, U8CPU b);
+
+    bool    isDirty() const { return !fDirtyRgn.isEmpty(); }
+    bool    update(SkIRect* updateArea);
+    bool    handleClick(int x, int y, Click::State);
+    bool    handleChar(SkUnichar);
+    bool    handleKey(SkKey);
+    bool    handleKeyUp(SkKey);
+    bool    handleMenu(uint32_t os_cmd);
+
+    void    addMenu(SkOSMenu*);
+    void    setTitle(const char title[]);
+
+protected:
+    virtual bool onEvent(const SkEvent&);
+
+    // called if part of our bitmap is invalidated
+    virtual void onHandleInval(const SkIRect&);
+    virtual bool onHandleChar(SkUnichar);
+    virtual bool onHandleKey(SkKey);
+    virtual bool onHandleKeyUp(SkKey);
+    virtual void onAddMenu(const SkOSMenu*) {}
+    virtual void onSetTitle(const char title[]) {}
+
+    // overrides from SkView
+    virtual bool handleInval(const SkRect&);
+    virtual bool onGetFocusView(SkView** focus) const;
+    virtual bool onSetFocusView(SkView* focus);
+
+private:
+    SkBitmap::Config    fConfig;
+    SkBitmap    fBitmap;
+    SkRegion    fDirtyRgn;
+    Click*      fClick; // to track clicks
+
+    SkTDArray<SkOSMenu*>    fMenus;
+
+    SkView* fFocusView;
+    bool    fWaitingOnInval;
+
+    typedef SkView INHERITED;
+};
+
+///////////////////////////////////////////////////////////
+
+#ifndef SK_USE_WXWIDGETS
+#ifdef SK_BUILD_FOR_MAC
+    #include "SkOSWindow_Mac.h"
+#elif defined(SK_BUILD_FOR_WIN)
+    #include "SkOSWindow_Win.h"
+#elif defined(SK_BUILD_FOR_UNIXx)
+  #include "SkOSWindow_Unix.h"
+#endif
+#else
+  #include "SkOSWindow_wxwidgets.h"
+#endif
+
+#endif
+
diff --git a/include/xml/SkBML_WXMLParser.h b/include/xml/SkBML_WXMLParser.h
new file mode 100644
index 0000000..faa127d
--- /dev/null
+++ b/include/xml/SkBML_WXMLParser.h
@@ -0,0 +1,54 @@
+/*
+ * 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 SkBML_WXMLParser_DEFINED
+#define SkBML_WXMLParser_DEFINED
+
+#include "SkString.h"
+#include "SkXMLParser.h"
+
+class SkStream;
+class SkWStream;
+
+class BML_WXMLParser : public SkXMLParser {
+public:
+    BML_WXMLParser(SkWStream& writer);
+    virtual ~BML_WXMLParser();
+    static void Write(SkStream& s, const char filename[]);
+  
+  /** @cond UNIT_TEST */
+  SkDEBUGCODE(static void UnitTest();)
+  /** @endcond */  
+private:
+    virtual bool onAddAttribute(const char name[], const char value[]);
+    virtual bool onEndElement(const char name[]);
+    virtual bool onStartElement(const char name[]);
+    BML_WXMLParser& operator=(const BML_WXMLParser& src);
+#ifdef SK_DEBUG
+    int fElemsCount, fElemsReused;
+    int fAttrsCount, fNamesReused, fValuesReused;
+#endif
+    SkWStream&  fWriter;
+    char*       fElems[256];
+    char*       fAttrNames[256];
+    char*       fAttrValues[256];
+
+    // important that these are U8, so we get automatic wrap-around
+    U8  fNextElem, fNextAttrName, fNextAttrValue;
+};
+
+#endif // SkBML_WXMLParser_DEFINED
+
diff --git a/include/xml/SkBML_XMLParser.h b/include/xml/SkBML_XMLParser.h
new file mode 100644
index 0000000..f056bca
--- /dev/null
+++ b/include/xml/SkBML_XMLParser.h
@@ -0,0 +1,39 @@
+/*
+ * 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 SkBML_XMLParser_DEFINED
+#define SkBML_XMLParser_DEFINED
+
+class SkStream;
+class SkWStream;
+class SkXMLParser;
+class SkXMLWriter;
+
+class BML_XMLParser {
+public:
+    /** Read the byte XML stream and write the decompressed XML.
+    */
+    static void Read(SkStream& s, SkXMLWriter& writer);
+    /** Read the byte XML stream and write the decompressed XML into a writable stream.
+    */
+    static void Read(SkStream& s, SkWStream& output);
+    /** Read the byte XML stream and write the decompressed XML into an XML parser.
+    */
+    static void Read(SkStream& s, SkXMLParser& output);
+};
+
+#endif // SkBML_XMLParser_DEFINED
+
diff --git a/include/xml/SkDOM.h b/include/xml/SkDOM.h
new file mode 100644
index 0000000..74e2492
--- /dev/null
+++ b/include/xml/SkDOM.h
@@ -0,0 +1,100 @@
+/*
+ * 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 SkDOM_DEFINED
+#define SkDOM_DEFINED
+
+#include "SkChunkAlloc.h"
+#include "SkMath.h"
+#include "SkScalar.h"
+#include "SkTemplates.h"
+
+struct SkDOMNode;
+struct SkDOMAttr;
+
+class SkDOM {
+public:
+    SkDOM();
+    ~SkDOM();
+
+    typedef SkDOMNode Node;
+    typedef SkDOMAttr Attr;
+
+    /** Returns null on failure
+    */
+    const Node* build(const char doc[], size_t len);
+    const Node* copy(const SkDOM& dom, const Node* node);
+
+    const Node* getRootNode() const;
+
+    enum Type {
+        kElement_Type,
+        kText_Type
+    };
+    Type    getType(const Node*) const;
+
+    const char* getName(const Node*) const;
+    const Node* getFirstChild(const Node*, const char elem[] = NULL) const;
+    const Node* getNextSibling(const Node*, const char elem[] = NULL) const;
+
+    const char* findAttr(const Node*, const char attrName[]) const;
+    const Attr* getFirstAttr(const Node*) const;
+    const Attr* getNextAttr(const Node*, const Attr*) const;
+    const char* getAttrName(const Node*, const Attr*) const;
+    const char* getAttrValue(const Node*, const Attr*) const;
+    
+    // helpers for walking children
+    int countChildren(const Node* node, const char elem[] = NULL) const;
+
+    // helpers for calling SkParse
+    bool findS32(const Node*, const char name[], int32_t* value) const;
+    bool findScalars(const Node*, const char name[], SkScalar value[], int count) const;
+    bool findHex(const Node*, const char name[], uint32_t* value) const;
+    bool findBool(const Node*, const char name[], bool*) const;
+    int  findList(const Node*, const char name[], const char list[]) const;
+
+    bool findScalar(const Node* node, const char name[], SkScalar value[]) const
+    {
+        return this->findScalars(node, name, value, 1);
+    }
+
+    bool hasAttr(const Node*, const char name[], const char value[]) const;
+    bool hasS32(const Node*, const char name[], int32_t value) const;
+    bool hasScalar(const Node*, const char name[], SkScalar value) const;
+    bool hasHex(const Node*, const char name[], uint32_t value) const;
+    bool hasBool(const Node*, const char name[], bool value) const;
+
+    class AttrIter {
+    public:
+        AttrIter(const class SkDOM&, const Node*);
+        const char* next(const char** value);
+    private:
+        const Attr* fAttr;
+        const Attr* fStop;
+    };
+
+    SkDEBUGCODE(void dump(const Node* node = NULL, int tabLevel = 0) const;)
+    SkDEBUGCODE(static void UnitTest();)
+
+private:
+    SkChunkAlloc    fAlloc;
+    Node*           fRoot;
+    friend class AttrIter;
+    friend class SkDOMParser;
+};
+
+#endif
+
diff --git a/include/xml/SkJS.h b/include/xml/SkJS.h
new file mode 100644
index 0000000..fe76352
--- /dev/null
+++ b/include/xml/SkJS.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include "SkTypes.h"
+#include "SkWindow.h"
+
+extern "C" {
+    typedef long JSWord;
+    typedef JSWord jsword;
+    typedef jsword  jsval;
+    typedef struct JSRuntime JSRuntime;
+    typedef struct JSContext JSContext;
+    typedef struct JSObject JSObject;
+}
+
+class SkString;
+
+class SkJS : public SkOSWindow {
+public:
+    SkJS(void* hwnd);
+    ~SkJS();
+    SkBool EvaluateScript(const char* script, jsval* rVal);
+    SkBool ValueToString(jsval value, SkString* string);
+#ifdef SK_DEBUG
+    static void Test(void* hwnd);
+#endif
+protected:
+    void InitializeDisplayables(const SkBitmap& , JSContext *, JSObject *, JSObject *);
+    void DisposeDisplayables();
+    JSRuntime *fRuntime;
+    JSContext *fContext;
+    JSObject *fGlobal;
+};
+
diff --git a/include/xml/SkXMLParser.h b/include/xml/SkXMLParser.h
new file mode 100644
index 0000000..ddad273
--- /dev/null
+++ b/include/xml/SkXMLParser.h
@@ -0,0 +1,161 @@
+/*
+ * 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 SkXMLParser_DEFINED
+#define SkXMLParser_DEFINED
+
+#include "SkMath.h"
+#include "SkString.h"
+
+class SkStream;
+
+class SkDOM;
+struct SkDOMNode;
+
+class SkXMLParserError {
+public:
+    enum ErrorCode {
+        kNoError,
+        kEmptyFile,
+        kUnknownElement,
+        kUnknownAttributeName,
+        kErrorInAttributeValue,
+        kDuplicateIDs,
+        kUnknownError
+    };
+
+    SkXMLParserError();
+    virtual ~SkXMLParserError();
+    ErrorCode getErrorCode() const { return fCode; }
+    virtual void getErrorString(SkString* str) const;
+    int getLineNumber() const { return fLineNumber; }
+    int getNativeCode() const { return fNativeCode; }
+    bool hasError() const { return fCode != kNoError || fNativeCode != -1; }
+    bool hasNoun() const { return fNoun.size() > 0; }
+    void reset();
+    void setCode(ErrorCode code) { fCode = code; }
+    void setNoun(const SkString& str) { fNoun.set(str); }
+    void setNoun(const char* ch)  { fNoun.set(ch); }
+    void setNoun(const char* ch, size_t len) { fNoun.set(ch, len); }
+protected:
+    ErrorCode fCode;
+private:
+    int fLineNumber;
+    int fNativeCode;
+    SkString fNoun;
+    friend class SkXMLParser;
+};
+
+class SkXMLParser {
+public:
+            SkXMLParser(SkXMLParserError* parserError = NULL);
+    virtual ~SkXMLParser();
+
+    /** Returns true for success
+    */
+    bool parse(const char doc[], size_t len);
+    bool parse(SkStream& docStream);
+    bool parse(const SkDOM&, const SkDOMNode*);
+
+    static void GetNativeErrorString(int nativeErrorCode, SkString* str);
+
+protected:
+    // override in subclasses; return true to stop parsing
+    virtual bool onStartElement(const char elem[]);
+    virtual bool onAddAttribute(const char name[], const char value[]);
+    virtual bool onEndElement(const char elem[]);
+    virtual bool onText(const char text[], int len);
+
+public:
+    // public for ported implementation, not meant for clients to call
+    virtual bool startElement(const char elem[]);
+    virtual bool addAttribute(const char name[], const char value[]);
+    virtual bool endElement(const char elem[]);
+    virtual bool text(const char text[], int len); 
+    void* fParser;
+protected:
+    SkXMLParserError* fError;
+private:
+    void reportError(void* parser);
+};
+
+class SkXMLPullParser {
+public:
+            SkXMLPullParser();
+    explicit SkXMLPullParser(SkStream*);
+    virtual ~SkXMLPullParser();
+
+    SkStream*   getStream() const { return fStream; }
+    SkStream*   setStream(SkStream* stream);
+
+    enum EventType {
+        ERROR = -1,
+        START_DOCUMENT,
+        END_DOCUMENT,
+        START_TAG,
+        END_TAG,
+        TEXT,
+        CDSECT,
+        ENTITY_REF,
+        IGNORABLE_WHITESPACE,
+        PROCESSING_INSTRUCTION,
+        COMMENT,
+        DOCDECL
+    };
+
+    EventType   nextToken();
+    EventType   getEventType() const { return fCurr.fEventType; }
+
+    struct AttrInfo {
+        const char* fName;
+        const char* fValue;
+    };
+    
+    int         getDepth() const { return fDepth; }
+    const char* getName();
+    int         getAttributeCount();
+    void        getAttributeInfo(int, AttrInfo*);
+    const char* getText();
+    bool        isWhitespace();
+    
+protected:
+    virtual bool onEntityReplacement(const char name[],
+                                     SkString* replacement);
+
+public:
+    struct Curr {
+        EventType   fEventType;
+        const char* fName;
+        AttrInfo*   fAttrInfos;
+        int         fAttrInfoCount;
+        bool        fIsWhitespace;
+    };
+
+private:
+    // implemented in the porting layer
+    bool        onInit();   // return false on failure
+    EventType   onNextToken();
+    void        onExit();
+    
+    SkStream*   fStream;
+    Curr        fCurr;
+    int         fDepth;
+    
+    struct Impl;
+    Impl*   fImpl;
+};
+
+#endif
diff --git a/include/xml/SkXMLWriter.h b/include/xml/SkXMLWriter.h
new file mode 100644
index 0000000..742e7f1
--- /dev/null
+++ b/include/xml/SkXMLWriter.h
@@ -0,0 +1,93 @@
+/*
+ * 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 SkXMLWriter_DEFINED
+#define SkXMLWriter_DEFINED
+
+#include "SkTDArray.h"
+#include "SkString.h"
+#include "SkDOM.h"
+
+class SkWStream;
+class SkXMLParser;
+
+class SkXMLWriter {
+public:
+            SkXMLWriter(bool doEscapeMarkup = true);
+    virtual ~SkXMLWriter();
+
+    void    addS32Attribute(const char name[], int32_t value);
+    void    addAttribute(const char name[], const char value[]);
+    void    addAttributeLen(const char name[], const char value[], size_t length);
+    void    addHexAttribute(const char name[], uint32_t value, int minDigits = 0);
+    void    addScalarAttribute(const char name[], SkScalar value);
+    void    endElement() { this->onEndElement(); }
+    void    startElement(const char elem[]);
+    void    startElementLen(const char elem[], size_t length);
+    void    writeDOM(const SkDOM&, const SkDOM::Node*, bool skipRoot);
+    void    flush();
+    virtual void writeHeader();
+
+protected:
+    virtual void onStartElementLen(const char elem[], size_t length) = 0;
+    virtual void onAddAttributeLen(const char name[], const char value[], size_t length) = 0;
+    virtual void onEndElement() = 0;
+
+    struct Elem {
+        SkString    fName;
+        bool        fHasChildren;
+    };
+    void doEnd(Elem* elem);
+    bool doStart(const char name[], size_t length);
+    Elem* getEnd();
+    const char* getHeader();
+    SkTDArray<Elem*> fElems;
+
+private:
+    bool fDoEscapeMarkup;
+    // illegal
+    SkXMLWriter& operator=(const SkXMLWriter&);
+};
+
+class SkXMLStreamWriter : public SkXMLWriter {
+public:
+    SkXMLStreamWriter(SkWStream*);
+    virtual ~SkXMLStreamWriter();
+    virtual void    writeHeader();
+    SkDEBUGCODE(static void UnitTest();)
+protected:
+    virtual void onStartElementLen(const char elem[], size_t length);
+    virtual void onEndElement();
+    virtual void onAddAttributeLen(const char name[], const char value[], size_t length);
+private:
+    SkWStream&      fStream;
+};
+
+class SkXMLParserWriter : public SkXMLWriter {
+public:
+    SkXMLParserWriter(SkXMLParser*);
+    virtual ~SkXMLParserWriter();
+protected:
+    virtual void onStartElementLen(const char elem[], size_t length);
+    virtual void onEndElement();
+    virtual void onAddAttributeLen(const char name[], const char value[], size_t length);
+private:
+    SkXMLParser&        fParser;
+};
+
+
+#endif
+