grab from latest android

git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2008-12-17 15:59:43 +00:00
parent 2559c62907
commit 8a1c16ff38
667 changed files with 139836 additions and 0 deletions

View File

@ -0,0 +1,60 @@
#include "SkMatrix.h"
static void computeOuterProduct(SkScalar op[4],
const SkPoint pts0[3], const SkPoint& ave0,
const SkPoint pts1[3], const SkPoint& ave1) {
bzero(op, 4 * sizeof(op[0]));
for (int i = 0; i < 3; i++) {
SkScalar x0 = pts0[i].fX - ave0.fX;
SkScalar y0 = pts0[i].fY - ave0.fY;
SkScalar x1 = pts1[i].fX - ave1.fX;
SkScalar y1 = pts1[i].fY - ave1.fY;
op[0] += SkScalarMul(x0, x1);
op[1] += SkScalarMul(x0, y1);
op[2] += SkScalarMul(y0, x1);
op[3] += SkScalarMul(y0, y1);
}
}
static SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
return SkScalarMul(ax, bx) + SkScalarMul(ay, by);
}
bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) {
const SkPoint& srcAve = src[0];
const SkPoint& dstAve = dst[0];
SkScalar srcOP[4], dstOP[4];
computeOuterProduct(srcOP, src, srcAve, src, srcAve);
computeOuterProduct(dstOP, src, srcAve, dst, dstAve);
SkScalar det = SkScalarMul(srcOP[0], srcOP[3]) - SkScalarMul(srcOP[1], srcOP[2]);
// need SkScalarNearlyZeroSquared for this (to match Chrome's fix)
if (SkScalarNearlyZero(det)) {
return false;
}
SkScalar invDet = SkScalarInvert(det);
// now compute invDet * [srcOP]T * [dstOP]
// scale and transpose
const SkScalar srcOP0 = SkScalarMul( srcOP[3], invDet);
const SkScalar srcOP1 = SkScalarMul(-srcOP[1], invDet);
const SkScalar srcOP2 = SkScalarMul(-srcOP[2], invDet);
const SkScalar srcOP3 = SkScalarMul( srcOP[0], invDet);
matrix->reset();
matrix->setScaleX(dot(srcOP0, srcOP1, dstOP[0], dstOP[2]));
matrix->setSkewX( dot(srcOP2, srcOP3, dstOP[0], dstOP[2]));
matrix->setSkewY (dot(srcOP0, srcOP1, dstOP[1], dstOP[3]));
matrix->setScaleY(dot(srcOP2, srcOP3, dstOP[1], dstOP[3]));
matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY,
matrix->getScaleX(), matrix->getSkewX()));
matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY,
matrix->getSkewY(), matrix->getScaleY()));
return true;
}

View File

@ -0,0 +1,90 @@
#include "SkMatrix.h"
#ifdef SK_SCALAR_IS_FIXED
typedef int64_t SkDScalar;
static SkScalar SkDScalar_toScalar(SkDScalar value) {
SkDScalar result = (value + (1 << 15)) >> 16;
int top = result >> 31;
SkASSERT(top == 0 || top == -1);
return (SkScalar)result;
}
static SkScalar div(SkDScalar numer, SkDScalar denom) {
denom >>= 16;
return numer / denom;
}
#else
typedef double SkDScalar;
static SkScalar SkDScalar_toScalar(SkDScalar value) {
return static_cast<float>(value);
}
static SkScalar div(SkDScalar numer, SkDScalar denom) {
return static_cast<float>(numer / denom);
}
#endif
static SkDScalar SkDScalar_setMul(SkScalar a, SkScalar b) {
return (SkDScalar)a * b;
}
static void computeOuterProduct(SkScalar op[4],
const SkPoint pts0[3], const SkPoint& ave0,
const SkPoint pts1[3], const SkPoint& ave1) {
bzero(op, 4 * sizeof(op[0]));
for (int i = 0; i < 3; i++) {
SkScalar x0 = pts0[i].fX - ave0.fX;
SkScalar y0 = pts0[i].fY - ave0.fY;
SkScalar x1 = pts1[i].fX - ave1.fX;
SkScalar y1 = pts1[i].fY - ave1.fY;
op[0] += SkScalarMul(x0, x1);
op[1] += SkScalarMul(x0, y1);
op[2] += SkScalarMul(y0, x1);
op[3] += SkScalarMul(y0, y1);
}
}
static SkDScalar ddot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
return SkDScalar_setMul(ax, bx) + SkDScalar_setMul(ay, by);
}
static SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
return SkDScalar_toScalar(ddot(ax, ay, bx, by));
}
bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) {
const SkPoint& srcAve = src[0];
const SkPoint& dstAve = dst[0];
SkScalar srcOP[4], dstOP[4];
computeOuterProduct(srcOP, src, srcAve, src, srcAve);
computeOuterProduct(dstOP, src, srcAve, dst, dstAve);
SkDScalar det = SkDScalar_setMul(srcOP[0], srcOP[3]) -
SkDScalar_setMul(srcOP[1], srcOP[2]);
SkDScalar M[4];
const SkScalar srcOP0 = srcOP[3];
const SkScalar srcOP1 = -srcOP[1];
const SkScalar srcOP2 = -srcOP[2];
const SkScalar srcOP3 = srcOP[0];
M[0] = ddot(srcOP0, srcOP1, dstOP[0], dstOP[2]);
M[1] = ddot(srcOP2, srcOP3, dstOP[0], dstOP[2]);
M[2] = ddot(srcOP0, srcOP1, dstOP[1], dstOP[3]);
M[3] = ddot(srcOP2, srcOP3, dstOP[1], dstOP[3]);
matrix->reset();
matrix->setScaleX(div(M[0], det));
matrix->setSkewX( div(M[1], det));
matrix->setSkewY (div(M[2], det));
matrix->setScaleY(div(M[3], det));
matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY,
matrix->getScaleX(), matrix->getSkewX()));
matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY,
matrix->getSkewY(), matrix->getScaleY()));
return true;
}

View File

@ -0,0 +1,65 @@
#include "SkMatrix.h"
typedef int64_t SkDScalar;
static SkScalar SkDScalar_toScalar(SkDScalar value) {
SkDScalar result = (value + (1 << 15)) >> 16;
int top = result >> 31;
SkASSERT(top == 0 || top == -1);
return (SkScalar)result;
}
static SkDScalar SkDScalar_setMul(SkScalar a, SkScalar b) {
return (SkDScalar)a * b;
}
static void computeOuterProduct(SkMatrix* matrix,
const SkPoint pts0[3], const SkPoint& ave0,
const SkPoint pts1[3], const SkPoint& ave1) {
SkDScalar tmp[4];
bzero(tmp, sizeof(tmp));
for (int i = 0; i < 3; i++) {
SkScalar x0 = pts0[i].fX - ave0.fX;
SkScalar y0 = pts0[i].fY - ave0.fY;
SkScalar x1 = pts1[i].fX - ave1.fX;
SkScalar y1 = pts1[i].fY - ave1.fY;
tmp[0] += SkDScalar_setMul(x0, x1);
tmp[1] += SkDScalar_setMul(x0, y1);
tmp[2] += SkDScalar_setMul(y0, x1);
tmp[3] += SkDScalar_setMul(y0, y1);
}
matrix->reset();
matrix->setScaleX(SkDScalar_toScalar(tmp[0]));
matrix->setSkewY( SkDScalar_toScalar(tmp[1]));
matrix->setSkewX( SkDScalar_toScalar(tmp[2]));
matrix->setScaleY(SkDScalar_toScalar(tmp[3]));
}
static SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
return SkDScalar_toScalar(SkDScalar_setMul(ax, bx) +
SkDScalar_setMul(ay, by));
}
bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) {
const SkPoint& srcAve = src[0];
const SkPoint& dstAve = dst[0];
SkMatrix srcOP, dstOP;
computeOuterProduct(&srcOP, src, srcAve, src, srcAve);
if (!srcOP.invert(&srcOP)) {
return false;
}
computeOuterProduct(&dstOP, src, srcAve, dst, dstAve);
matrix->setConcat(dstOP, srcOP);
matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY,
matrix->getScaleX(), matrix->getSkewX()));
matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY,
matrix->getSkewY(), matrix->getScaleY()));
return true;
}

View File

@ -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

View File

@ -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

245
include/core/Sk64.h Normal file
View File

@ -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

684
include/core/SkBitmap.h Normal file
View File

@ -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

72
include/core/SkBounder.h Normal file
View File

@ -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

141
include/core/SkBuffer.h Normal file
View File

@ -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

794
include/core/SkCanvas.h Normal file
View File

@ -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

View File

@ -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

155
include/core/SkColor.h Normal file
View File

@ -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

View File

@ -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

657
include/core/SkColorPriv.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

74
include/core/SkDeque.h Normal file
View File

@ -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

187
include/core/SkDescriptor.h Normal file
View File

@ -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

142
include/core/SkDevice.h Normal file
View File

@ -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

205
include/core/SkDither.h Normal file
View File

@ -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

124
include/core/SkDraw.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

98
include/core/SkEndian.h Normal file
View File

@ -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

67
include/core/SkFDot6.h Normal file
View File

@ -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

253
include/core/SkFixed.h Normal file
View File

@ -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

View File

@ -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

150
include/core/SkFloatBits.h Normal file
View File

@ -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

View File

@ -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

122
include/core/SkFontHost.h Normal file
View File

@ -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

67
include/core/SkGlobals.h Normal file
View File

@ -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

46
include/core/SkGraphics.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

86
include/core/SkMask.h Normal file
View File

@ -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

100
include/core/SkMaskFilter.h Normal file
View File

@ -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

230
include/core/SkMath.h Normal file
View File

@ -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

479
include/core/SkMatrix.h Normal file
View File

@ -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

86
include/core/SkPackBits.h Normal file
View File

@ -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

814
include/core/SkPaint.h Normal file
View File

@ -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

588
include/core/SkPath.h Normal file
View File

@ -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

144
include/core/SkPathEffect.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

124
include/core/SkPicture.h Normal file
View File

@ -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

158
include/core/SkPixelRef.h Normal file
View File

@ -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

288
include/core/SkPoint.h Normal file
View File

@ -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

View File

@ -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

216
include/core/SkPostConfig.h Normal file
View File

@ -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

110
include/core/SkPreConfig.h Normal file
View File

@ -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

View File

@ -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

110
include/core/SkRandom.h Normal file
View File

@ -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

View File

@ -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

115
include/core/SkReader32.h Normal file
View File

@ -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

435
include/core/SkRect.h Normal file
View File

@ -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

134
include/core/SkRefCnt.h Normal file
View File

@ -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

352
include/core/SkRegion.h Normal file
View File

@ -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

254
include/core/SkScalar.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

184
include/core/SkShader.h Normal file
View File

@ -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

315
include/core/SkStream.h Normal file
View File

@ -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

170
include/core/SkString.h Normal file
View File

@ -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

71
include/core/SkStroke.h Normal file
View File

@ -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

293
include/core/SkTDArray.h Normal file
View File

@ -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

120
include/core/SkTDStack.h Normal file
View File

@ -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

169
include/core/SkTDict.h Normal file
View File

@ -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

167
include/core/SkTSearch.h Normal file
View File

@ -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

217
include/core/SkTemplates.h Normal file
View File

@ -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

68
include/core/SkThread.h Normal file
View File

@ -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

View File

@ -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

72
include/core/SkTime.h Normal file
View File

@ -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

131
include/core/SkTypeface.h Normal file
View File

@ -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

377
include/core/SkTypes.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

104
include/core/SkUserConfig.h Normal file
View File

@ -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

140
include/core/SkUtils.h Normal file
View File

@ -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

112
include/core/SkWriter32.h Normal file
View File

@ -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

115
include/core/SkXfermode.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More