diff options
Diffstat (limited to 'include')
58 files changed, 4550 insertions, 107 deletions
diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h index aa2e6cf..c56d8cf 100644 --- a/include/config/SkUserConfig.h +++ b/include/config/SkUserConfig.h @@ -54,7 +54,7 @@ /* Somewhat independent of how SkScalar is implemented, Skia also wants to know if it can use floats at all. Naturally, if SK_SCALAR_IS_FLOAT is defined, - then so muse SK_CAN_USE_FLOAT, but if scalars are fixed, SK_CAN_USE_FLOAT + SK_CAN_USE_FLOAT must be too; but if scalars are fixed, SK_CAN_USE_FLOAT can go either way. */ //#define SK_CAN_USE_FLOAT @@ -151,4 +151,3 @@ #endif #endif - diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h index ae0b974..6e8da76 100644 --- a/include/core/SkClipStack.h +++ b/include/core/SkClipStack.h @@ -43,6 +43,7 @@ public: struct Clip { friend bool operator==(const Clip& a, const Clip& b); + friend bool operator!=(const Clip& a, const Clip& b); const SkRect* fRect; // if non-null, this is a rect clip const SkPath* fPath; // if non-null, this is a path clip SkRegion::Op fOp; diff --git a/include/core/SkColorPriv.h b/include/core/SkColorPriv.h index f9e02a2..6fa9df3 100644 --- a/include/core/SkColorPriv.h +++ b/include/core/SkColorPriv.h @@ -155,31 +155,13 @@ static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[], #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) diff --git a/include/core/SkComposeShader.h b/include/core/SkComposeShader.h index 0b198f6..ea37549 100644 --- a/include/core/SkComposeShader.h +++ b/include/core/SkComposeShader.h @@ -27,7 +27,7 @@ class SkXfermode; This subclass of shader returns the coposition of two other shaders, combined by a xfermode. */ -class SkComposeShader : public SkShader { +class SK_API 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 diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index 46bcf1a..d9a4fde 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -155,31 +155,6 @@ public: virtual void setMatrixClip(const SkMatrix&, const SkRegion&, const SkClipStack&); - /** - * Observer interface for listening to the calls to - * SkDevice::setMatrixClip(...). Users of SkDevice instances should - * implement matrixClipChanged(...) to receive notifications. - */ - class SkMatrixClipObserver : public SkRefCnt { - public: - virtual void matrixClipChanged(const SkMatrix&, const SkRegion&, - const SkClipStack&) = 0; - }; - - /** Assign the clip observer. Note that an extra reference is added to the - * observer, and removed at SkDevice construction, or re-assignment of a - * different observer. - */ - void setMatrixClipObserver(SkMatrixClipObserver* observer); - - /** Return the device's associated SkMatrixClipObserver, or NULL. - * If non-null is returned, the reference count of the object is not - * modified. - */ - SkMatrixClipObserver* getMatrixClipObserver() const { - return fMatrixClipObserver; - } - /** Called when this device gains focus (i.e becomes the current device for drawing). */ @@ -306,8 +281,6 @@ private: SkIPoint fOrigin; SkMetaData* fMetaData; - SkMatrixClipObserver* fMatrixClipObserver; - SkDeviceFactory* fCachedDeviceFactory; }; diff --git a/include/core/SkMath.h b/include/core/SkMath.h index 3e72904..efe378a 100644 --- a/include/core/SkMath.h +++ b/include/core/SkMath.h @@ -115,7 +115,7 @@ static inline unsigned SkClampUMax(unsigned value, unsigned max) { /////////////////////////////////////////////////////////////////////////////// -#if defined(__arm__) && !defined(__thumb__) +#if defined(__arm__) #define SkCLZ(x) __builtin_clz(x) #endif diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h index 7c77902..480e077 100644 --- a/include/core/SkMatrix.h +++ b/include/core/SkMatrix.h @@ -438,6 +438,7 @@ public: */ bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const; +#ifdef SK_SCALAR_IS_FIXED friend bool operator==(const SkMatrix& a, const SkMatrix& b) { return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) == 0; } @@ -445,6 +446,12 @@ public: friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) != 0; } +#else + friend bool operator==(const SkMatrix& a, const SkMatrix& b); + friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { + return !(a == b); + } +#endif enum { // flatten/unflatten will never return a value larger than this @@ -488,7 +495,12 @@ private: kRectStaysRect_Mask = 0x10, kUnknown_Mask = 0x80, - + + kORableMasks = kTranslate_Mask | + kScale_Mask | + kAffine_Mask | + kPerspective_Mask, + kAllMasks = kTranslate_Mask | kScale_Mask | kAffine_Mask | @@ -506,7 +518,12 @@ private: SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask); fTypeMask = SkToU8(mask); } - + + void orTypeMask(int mask) { + SkASSERT((mask & kORableMasks) == mask); + fTypeMask = SkToU8(fTypeMask | mask); + } + void clearTypeMask(int mask) { // only allow a valid mask SkASSERT((mask & kAllMasks) == mask); diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 18dcd11..7120d3f 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -88,9 +88,10 @@ public: /** 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() - */ + /** + * Toggle between inverse and normal filltypes. This reverse the return + * value of isInverseFillType() + */ void toggleInverseFillType() { fFillType ^= 2; GEN_ID_INC; @@ -103,14 +104,33 @@ public: }; /** - * Return the path's convexity, as stored in the path. + * Return the path's convexity, as stored in the path. If it is currently + * unknown, and the computeIfUnknown bool is true, then this will first + * call ComputeConvexity() and then return that (cached) value. + */ + Convexity getConvexity() const { + if (kUnknown_Convexity == fConvexity) { + fConvexity = (uint8_t)ComputeConvexity(*this); + } + return (Convexity)fConvexity; + } + + /** + * Return the currently cached value for convexity, even if that is set to + * kUnknown_Convexity. Note: getConvexity() will automatically call + * ComputeConvexity and cache its return value if the current setting is + * kUnknown. */ - Convexity getConvexity() const { return (Convexity)fConvexity; } + Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; } /** * Store a convexity setting in the path. There is no automatic check to * see if this value actually agress with the return value from * ComputeConvexity(). + * + * Note: even if this is set to a "known" value, if the path is later + * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be + * reset to kUnknown_Convexity. */ void setConvexity(Convexity); @@ -118,9 +138,11 @@ public: * Compute the convexity of the specified path. This does not look at the * value stored in the path, but computes it directly from the path's data. * + * This never returns kUnknown_Convexity. + * * If there is more than one contour, this returns kConcave_Convexity. - * If the contour is degenerate (i.e. all segements are colinear, - * then this returns kUnknown_Convexity. + * If the contour is degenerate (e.g. there are fewer than 3 non-degenerate + * segments), then this returns kConvex_Convexity. * The contour is treated as if it were closed, even if there is no kClose * verb. */ @@ -635,7 +657,7 @@ private: mutable SkRect fBounds; mutable uint8_t fBoundsIsDirty; uint8_t fFillType; - uint8_t fConvexity; + mutable uint8_t fConvexity; #ifdef ANDROID uint32_t fGenerationID; #endif diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h index 57cc368..23ce02b 100644 --- a/include/core/SkPostConfig.h +++ b/include/core/SkPostConfig.h @@ -132,6 +132,25 @@ #endif #endif +/* + * We check to see if the SHIFT value has already been defined. + * 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 + // stdlib macros #if 0 diff --git a/include/core/SkPreConfig.h b/include/core/SkPreConfig.h index 8d47d46..6ec73ce 100644 --- a/include/core/SkPreConfig.h +++ b/include/core/SkPreConfig.h @@ -41,14 +41,16 @@ #define SK_BUILD_FOR_UNIX #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR #define SK_BUILD_FOR_IOS - #elif defined(ANDROID_NDK) - #define SK_BUILD_FOR_ANDROID_NDK - #elif defined(ANROID) - #define SK_BUILD_FOR_ANDROID #else #define SK_BUILD_FOR_MAC #endif + #if defined(ANDROID) + #define SK_BUILD_FOR_ANDROID + #endif + #if defined(ANDROID_NDK) + #define SK_BUILD_FOR_ANDROID_NDK + #endif #endif ////////////////////////////////////////////////////////////////////// diff --git a/include/core/SkReader32.h b/include/core/SkReader32.h index 03a34c7..654ebd5 100644 --- a/include/core/SkReader32.h +++ b/include/core/SkReader32.h @@ -101,7 +101,14 @@ public: uint16_t readU16() { return (uint16_t)this->readInt(); } int32_t readS32() { return this->readInt(); } uint32_t readU32() { return this->readInt(); } - + + /** + * Read the length of a string written by SkWriter32::writeString() + * (if len is not NULL) and return the null-ternimated address of the + * string. + */ + const char* readString(size_t* len = NULL); + private: // these are always 4-byte aligned const char* fCurr; // current position within buffer diff --git a/include/core/SkRect.h b/include/core/SkRect.h index 550c5d1..19ee12a 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -290,7 +290,7 @@ struct SK_API SkIRect { void sort(); static const SkIRect& EmptyIRect() { - static const SkIRect gEmpty = {0,0,0,0}; + static const SkIRect gEmpty = { 0, 0, 0, 0 }; return gEmpty; } }; diff --git a/include/core/SkScalar.h b/include/core/SkScalar.h index ebe621b..5dbf684 100644 --- a/include/core/SkScalar.h +++ b/include/core/SkScalar.h @@ -66,9 +66,47 @@ int exponent = bits << 1 >> 24; return exponent != 0xFF; } +#ifdef SK_DEBUG + /** SkIntToScalar(n) returns its integer argument as an SkScalar + * + * If we're compiling in DEBUG mode, and can thus afford some extra runtime + * cycles, check to make sure that the parameter passed in has not already + * been converted to SkScalar. (A double conversion like this is harmless + * for SK_SCALAR_IS_FLOAT, but for SK_SCALAR_IS_FIXED this causes trouble.) + * + * Note that we need all of these method signatures to properly handle the + * various types that we pass into SkIntToScalar() to date: + * int, size_t, U8CPU, etc., even though what we really mean is "anything + * but a float". + */ + static inline float SkIntToScalar(signed int param) { + return (float)param; + } + static inline float SkIntToScalar(unsigned int param) { + return (float)param; + } + static inline float SkIntToScalar(signed long param) { + return (float)param; + } + static inline float SkIntToScalar(unsigned long param) { + return (float)param; + } + static inline float SkIntToScalar(float param) { + /* If the parameter passed into SkIntToScalar is a float, + * one of two things has happened: + * 1. the parameter was an SkScalar (which is typedef'd to float) + * 2. the parameter was a float instead of an int + * + * Either way, it's not good. + */ + SkASSERT(!"looks like you passed an SkScalar into SkIntToScalar"); + return (float)0; + } +#else // not SK_DEBUG /** SkIntToScalar(n) returns its integer argument as an SkScalar */ #define SkIntToScalar(n) ((float)(n)) +#endif // not SK_DEBUG /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar */ #define SkFixedToScalar(x) SkFixedToFloat(x) @@ -282,4 +320,3 @@ SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[], const SkScalar values[], int length); #endif - diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h index 55dfcef..3f818a3 100644 --- a/include/core/SkScalerContext.h +++ b/include/core/SkScalerContext.h @@ -179,6 +179,9 @@ public: kEmbolden_Flag = 0x80, kSubpixelPositioning_Flag = 0x100, kAutohinting_Flag = 0x200, + // these should only ever be set if fMaskFormat is LCD + kLCD_Vertical_Flag = 0x400, // else Horizontal + kLCD_BGROrder_Flag = 0x800, // else RGB order }; private: enum { diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h index 8e133c2..c8ebb6a 100644 --- a/include/core/SkWriter32.h +++ b/include/core/SkWriter32.h @@ -100,7 +100,22 @@ public: } void writePad(const void* src, size_t size); - + + /** + * Writes a string to the writer, which can be retrieved with + * SkReader32::readString(). + * The length can be specified, or if -1 is passed, it will be computed by + * calling strlen(). The length must be < 0xFFFF + */ + void writeString(const char* str, size_t len = (size_t)-1); + + /** + * Computes the size (aligned to multiple of 4) need to write the string + * in a call to writeString(). If the length is not specified, it will be + * computed by calling strlen(). + */ + static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); + // return the current offset (will always be a multiple of 4) uint32_t size() const { return fSize; } void reset(); diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h index 4d46bb9..6ab9d6d 100644 --- a/include/core/SkXfermode.h +++ b/include/core/SkXfermode.h @@ -103,11 +103,15 @@ public: kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] - // these modes are defined in the SVG Compositing standard + // all remaining modes are defined in the SVG Compositing standard // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/ kPlus_Mode, - kMultiply_Mode, - kScreen_Mode, + kMultiply_Mode, + + // all above modes can be expressed as pair of src/dst Coeffs + kCoeffModesCnt, + + kScreen_Mode = kCoeffModesCnt, kOverlay_Mode, kDarken_Mode, kLighten_Mode, diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h index 15def87..601da09 100644 --- a/include/gpu/SkGpuDevice.h +++ b/include/gpu/SkGpuDevice.h @@ -163,17 +163,26 @@ private: // doesn't set the texture/sampler/matrix state // caller needs to null out GrPaint's texture if // non-textured drawing is desired. + // Set constantColor to true if a constant color + // will be used. This is an optimization, and can + // always be set to false. constantColor should + // never be true if justAlpha is true. bool skPaint2GrPaintNoShader(const SkPaint& skPaint, bool justAlpha, - GrPaint* grPaint); + GrPaint* grPaint, + bool constantColor); // uses the SkShader to setup paint, act used to // hold lock on cached texture and free it when // destroyed. + // If there is no shader, constantColor will + // be passed to skPaint2GrPaintNoShader. Otherwise + // it is ignored. bool skPaint2GrPaintShader(const SkPaint& skPaint, SkAutoCachedTexture* act, const SkMatrix& ctm, - GrPaint* grPaint); + GrPaint* grPaint, + bool constantColor); SkDrawProcs* initDrawForText(GrTextContext*); bool bindDeviceAsTexture(GrPaint* paint); diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h index 75099b2..65565c9 100644 --- a/include/gpu/SkGr.h +++ b/include/gpu/SkGr.h @@ -24,8 +24,8 @@ #include "GrConfig.h" #include "GrContext.h" #include "GrFontScaler.h" -#include "GrPathIter.h" #include "GrClipIterator.h" +#include "GrPath.h" // skia headers #include "SkBitmap.h" @@ -130,29 +130,6 @@ public: //////////////////////////////////////////////////////////////////////////////// // Classes -class SkGrPathIter : public GrPathIter { -public: - SkGrPathIter() { fPath = NULL; } - SkGrPathIter(const SkPath& path) { reset(path); } - virtual GrPathCmd next(GrPoint pts[]); - virtual GrPathCmd next(); - virtual void rewind(); - virtual GrConvexHint convexHint() const; - virtual bool getConservativeBounds(GrRect* rect) const; - - void reset(const SkPath& path) { - fPath = &path; - fIter.setPath(path, false); - } -private: - -#if !SK_SCALAR_IS_GR_SCALAR - SkPoint fPoints[4]; -#endif - SkPath::Iter fIter; - const SkPath* fPath; -}; - class SkGrClipIterator : public GrClipIterator { public: SkGrClipIterator() { fClipStack = NULL; fCurr = NULL; } @@ -176,9 +153,8 @@ public: } } - virtual GrPathIter* getPathIter() { - fPathIter.reset(*fCurr->fPath); - return &fPathIter; + virtual const GrPath* getPath() { + return fCurr->fPath; } virtual GrPathFill getPathFill() const; @@ -186,7 +162,6 @@ public: private: const SkClipStack* fClipStack; SkClipStack::B2FIter fIter; - SkGrPathIter fPathIter; // SkClipStack's auto advances on each get // so we store the current pos here. const SkClipStack::B2FIter::Clip* fCurr; @@ -218,7 +193,7 @@ public: rect->fBottom = GrIntToScalar(r.fBottom); } - virtual GrPathIter* getPathIter() { + virtual const GrPath* getPath() { SkASSERT(0); return NULL; } diff --git a/include/pdf/SkPDFCatalog.h b/include/pdf/SkPDFCatalog.h new file mode 100644 index 0000000..e02ffa1 --- /dev/null +++ b/include/pdf/SkPDFCatalog.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFCatalog_DEFINED +#define SkPDFCatalog_DEFINED + +#include <sys/types.h> + +#include "SkPDFTypes.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" + +/** \class SkPDFCatalog + + The PDF catalog manages object numbers and file offsets. It is used + to create the PDF cross reference table. +*/ +class SK_API SkPDFCatalog { +public: + /** Create a PDF catalog. + */ + SkPDFCatalog(); + ~SkPDFCatalog(); + + /** Add the passed object to the catalog. Refs obj. + * @param obj The object to add. + * @param onFirstPage Is the object on the first page. + * @return The obj argument is returned. + */ + SkPDFObject* addObject(SkPDFObject* obj, bool onFirstPage); + + /** Inform the catalog of the object's position in the final stream. + * The object should already have been added to the catalog. Returns + * the object's size. + * @param obj The object to add. + * @param offset The byte offset in the output stream of this object. + */ + size_t setFileOffset(SkPDFObject* obj, size_t offset); + + /** Output the object number for the passed object. + * @param obj The object of interest. + * @param stream The writable output stream to send the output to. + */ + void emitObjectNumber(SkWStream* stream, SkPDFObject* obj); + + /** Return the number of bytes that would be emitted for the passed + * object's object number. + * @param obj The object of interest + */ + size_t getObjectNumberSize(SkPDFObject* obj); + + /** Output the cross reference table for objects in the catalog. + * Returns the total number of objects. + * @param stream The writable output stream to send the output to. + * @param firstPage If true, include first page objects only, otherwise + * include all objects not on the first page. + */ + int32_t emitXrefTable(SkWStream* stream, bool firstPage); + +private: + struct Rec { + Rec(SkPDFObject* object, bool onFirstPage) + : fObject(object), + fFileOffset(0), + fObjNumAssigned(false), + fOnFirstPage(onFirstPage) { + } + SkPDFObject* fObject; + off_t fFileOffset; + bool fObjNumAssigned; + bool fOnFirstPage; + }; + + // TODO(vandebo) Make this a hash if it's a performance problem. + SkTDArray<struct Rec> fCatalog; + + // Number of objects on the first page. + uint32_t fFirstPageCount; + // Next object number to assign (on page > 1). + uint32_t fNextObjNum; + // Next object number to assign on the first page. + uint32_t fNextFirstPageObjNum; + + int findObjectIndex(SkPDFObject* obj) const; + + int assignObjNum(SkPDFObject* obj); +}; + +#endif diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h new file mode 100644 index 0000000..6e4d8db --- /dev/null +++ b/include/pdf/SkPDFDevice.h @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFDevice_DEFINED +#define SkPDFDevice_DEFINED + +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkPaint.h" +#include "SkPath.h" +#include "SkRefCnt.h" +#include "SkStream.h" +#include "SkTScopedPtr.h" + +class SkPDFArray; +class SkPDFDevice; +class SkPDFDict; +class SkPDFFont; +class SkPDFFormXObject; +class SkPDFGraphicState; +class SkPDFObject; +class SkPDFShader; +class SkPDFStream; + +// Private classes. +struct ContentEntry; +struct GraphicStateEntry; + +class SkPDFDeviceFactory : public SkDeviceFactory { +public: + virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width, + int height, bool isOpaque, bool isForLayer); +}; + +/** \class SkPDFDevice + + The drawing context for the PDF backend. +*/ +class SkPDFDevice : public SkDevice { +public: + /** Create a PDF drawing context with the given width and height. + * 72 points/in means letter paper is 612x792. + * @param pageSize Page size in points. + * @param contentSize The content size of the page in points. This will be + * combined with the initial transform to determine the drawing area + * (as reported by the width and height methods). Anything outside + * of the drawing area will be clipped. + * @param initialTransform The initial transform to apply to the page. + * This may be useful to, for example, move the origin in and + * over a bit to account for a margin, scale the canvas, + * or apply a rotation. Note1: the SkPDFDevice also applies + * a scale+translate transform to move the origin from the + * bottom left (PDF default) to the top left. Note2: drawDevice + * (used by layer restore) draws the device after this initial + * transform is applied, so the PDF device factory does an + * inverse scale+translate to accommodate the one that SkPDFDevice + * always does. + */ + // TODO(vandebo) The sizes should be SkSize and not SkISize. + SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize, + const SkMatrix& initialTransform); + SK_API virtual ~SkPDFDevice(); + + virtual uint32_t getDeviceCapabilities() { return kVector_Capability; } + + virtual void clear(SkColor color); + + virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { + return false; + } + + /** 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& origpath, + const SkPaint& paint, const SkMatrix* prePathMatrix, + bool pathIsMutable); + virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, + const SkIRect* srcRectOrNull, + 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&); + + // PDF specific methods. + + /** Returns a reference to the resource dictionary for this device. + */ + SK_API const SkRefPtr<SkPDFDict>& getResourceDict(); + + /** Get the list of resources (PDF objects) used on this page. + * @param resourceList A list to append the resources to. + */ + SK_API void getResources(SkTDArray<SkPDFObject*>* resourceList) const; + + /** Get the fonts used on this device. + */ + SK_API const SkTDArray<SkPDFFont*>& getFontResources() const; + + /** Returns the media box for this device. + */ + SK_API SkRefPtr<SkPDFArray> getMediaBox() const; + + /** Returns a SkStream with the page contents. The caller is responsible + for a reference to the returned value. + */ + SK_API SkStream* content() const; + + SK_API const SkMatrix& initialTransform() const { + return fInitialTransform; + } + +protected: + // override + virtual SkDeviceFactory* onNewDeviceFactory(); + +private: + friend class SkPDFDeviceFactory; + // TODO(vandebo) push most of SkPDFDevice's state into a core object in + // order to get the right access levels without using friend. + friend class ScopedContentEntry; + + SkISize fPageSize; + SkISize fContentSize; + SkMatrix fInitialTransform; + SkClipStack fExistingClipStack; + SkRegion fExistingClipRegion; + SkRefPtr<SkPDFDict> fResourceDict; + + SkTDArray<SkPDFGraphicState*> fGraphicStateResources; + SkTDArray<SkPDFObject*> fXObjectResources; + SkTDArray<SkPDFFont*> fFontResources; + SkTDArray<SkPDFShader*> fShaderResources; + + SkTScopedPtr<ContentEntry> fContentEntries; + ContentEntry* fLastContentEntry; + + // For use by the DeviceFactory. + SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack, + const SkRegion& existingClipRegion); + + void init(); + void cleanUp(); + void createFormXObjectFromDevice(SkRefPtr<SkPDFFormXObject>* xobject); + + // Clear the passed clip from all existing content entries. + void clearClipFromContent(const SkClipStack* clipStack, + const SkRegion& clipRegion); + void drawFormXObjectWithClip(SkPDFFormXObject* form, + const SkClipStack* clipStack, + const SkRegion& clipRegion, + bool invertClip); + + // If the paint or clip is such that we shouldn't draw anything, this + // returns NULL and does not create a content entry. + // setUpContentEntry and finishContentEntry can be used directly, but + // the preferred method is to use the ScopedContentEntry helper class. + ContentEntry* setUpContentEntry(const SkClipStack* clipStack, + const SkRegion& clipRegion, + const SkMatrix& matrix, + const SkPaint& paint, + bool hasText, + SkRefPtr<SkPDFFormXObject>* dst); + void finishContentEntry(SkXfermode::Mode xfermode, + SkPDFFormXObject* dst); + bool isContentEmpty(); + + void populateGraphicStateEntryFromPaint(const SkMatrix& matrix, + const SkClipStack& clipStack, + const SkRegion& clipRegion, + const SkPaint& paint, + bool hasText, + GraphicStateEntry* entry); + int addGraphicStateResource(SkPDFGraphicState* gs); + + void updateFont(const SkPaint& paint, uint16_t glyphID, + ContentEntry* contentEntry); + int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID); + + void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry); + void internalDrawBitmap(const SkMatrix& matrix, + const SkClipStack* clipStack, + const SkRegion& clipRegion, + const SkBitmap& bitmap, + const SkIRect* srcRect, + const SkPaint& paint); + + // Disable the default copy and assign implementation. + SkPDFDevice(const SkPDFDevice&); + void operator=(const SkPDFDevice&); +}; + +#endif diff --git a/include/pdf/SkPDFDocument.h b/include/pdf/SkPDFDocument.h new file mode 100644 index 0000000..0a76ea2 --- /dev/null +++ b/include/pdf/SkPDFDocument.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFDocument_DEFINED +#define SkPDFDocument_DEFINED + +#include "SkPDFCatalog.h" +#include "SkPDFTypes.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" + +class SkPDFDevice; +class SkPDFPage; +class SkWSteam; + +/** \class SkPDFDocument + + A SkPDFDocument assembles pages together and generates the final PDF file. +*/ +class SkPDFDocument { +public: + /** Create a PDF document. + */ + SK_API SkPDFDocument(); + SK_API ~SkPDFDocument(); + + /** Output the PDF to the passed stream. + * @param stream The writable output stream to send the PDF to. + */ + SK_API bool emitPDF(SkWStream* stream); + + /** Append the passed pdf device to the document as a new page. Returns + * true if successful. Will fail if the document has already been emitted. + * + * @param pdfDevice The page to add to this document. + */ + SK_API bool appendPage(const SkRefPtr<SkPDFDevice>& pdfDevice); + + /** Get the list of pages in this document. + */ + SK_API const SkTDArray<SkPDFPage*>& getPages(); + +private: + SkPDFCatalog fCatalog; + int64_t fXRefFileOffset; + + SkTDArray<SkPDFPage*> fPages; + SkTDArray<SkPDFDict*> fPageTree; + SkRefPtr<SkPDFDict> fDocCatalog; + SkTDArray<SkPDFObject*> fPageResources; + int fSecondPageFirstResourceIndex; + + SkRefPtr<SkPDFDict> fTrailerDict; + + /** Output the PDF header to the passed stream. + * @param stream The writable output stream to send the header to. + */ + void emitHeader(SkWStream* stream); + + /** Get the size of the header. + */ + size_t headerSize(); + + /** Output the PDF footer to the passed stream. + * @param stream The writable output stream to send the footer to. + * @param objCount The number of objects in the PDF. + */ + void emitFooter(SkWStream* stream, int64_t objCount); +}; + +#endif diff --git a/include/pdf/SkPDFFont.h b/include/pdf/SkPDFFont.h new file mode 100644 index 0000000..93a72f1 --- /dev/null +++ b/include/pdf/SkPDFFont.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFFont_DEFINED +#define SkPDFFont_DEFINED + +#include "SkAdvancedTypefaceMetrics.h" +#include "SkPDFTypes.h" +#include "SkTDArray.h" +#include "SkThread.h" + +class SkPaint; + +/** \class SkPDFFont + A PDF Object class representing a font. The font may have resources + attached to it in order to embed the font. SkPDFFonts are canonicalized + so that resource deduplication will only include one copy of a font. + This class uses the same pattern as SkPDFGraphicState, a static weak + reference to each instantiated class. +*/ +class SkPDFFont : public SkPDFDict { +public: + SK_API virtual ~SkPDFFont(); + + SK_API virtual void getResources(SkTDArray<SkPDFObject*>* resourceList); + + /** Returns the typeface represented by this class. Returns NULL for the + * default typeface. + */ + SK_API SkTypeface* typeface(); + + /** Returns the font type represented in this font. For Type0 fonts, + * returns the type of the decendant font. + */ + SK_API SkAdvancedTypefaceMetrics::FontType getType(); + + /** Return true if this font has an encoding for the passed glyph id. + */ + SK_API bool hasGlyph(uint16_t glyphID); + + /** Returns true if this font encoding supports glyph IDs above 255. + */ + SK_API bool multiByteGlyphs(); + + /** Convert (in place) the input glyph IDs into the font encoding. If the + * font has more glyphs than can be encoded (like a type 1 font with more + * than 255 glyphs) this method only converts up to the first out of range + * glyph ID. + * @param glyphIDs The input text as glyph IDs. + * @param numGlyphs The number of input glyphs. + * @return Returns the number of glyphs consumed. + */ + SK_API size_t glyphsToPDFFontEncoding(uint16_t* glyphIDs, size_t numGlyphs); + + /** Get the font resource for the passed typeface and glyphID. The + * reference count of the object is incremented and it is the caller's + * responsibility to unreference it when done. This is needed to + * accommodate the weak reference pattern used when the returned object + * is new and has no other references. + * @param typeface The typeface to find. + * @param glyphID Specify which section of a large font is of interest. + */ + SK_API static SkPDFFont* getFontResource(SkTypeface* typeface, + uint16_t glyphID); + +private: + SkRefPtr<SkTypeface> fTypeface; + SkAdvancedTypefaceMetrics::FontType fType; +#ifdef SK_DEBUG + bool fDescendant; +#endif + bool fMultiByteGlyphs; + + // The glyph IDs accessible with this font. For Type1 (non CID) fonts, + // this will be a subset if the font has more than 255 glyphs. + uint16_t fFirstGlyphID; + uint16_t fLastGlyphID; + // The font info is only kept around after construction for large + // Type1 (non CID) fonts that need multiple "fonts" to access all glyphs. + SkRefPtr<SkAdvancedTypefaceMetrics> fFontInfo; + SkTDArray<SkPDFObject*> fResources; + SkRefPtr<SkPDFDict> fDescriptor; + + class FontRec { + public: + SkPDFFont* fFont; + uint32_t fFontID; + uint16_t fGlyphID; + + // A fGlyphID of 0 with no fFont always matches. + bool operator==(const FontRec& b) const; + FontRec(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID); + }; + + // This should be made a hash table if performance is a problem. + static SkTDArray<FontRec>& canonicalFonts(); + static SkMutex& canonicalFontsMutex(); + + /** Construct a new font dictionary and support objects. + * @param fontInfo Information about the to create. + * @param typeface The typeface for the font. + * @param glyphID The glyph ID the caller is interested in. This + * is important only for Type1 fonts, which have + * more than 255 glyphs. + * @param descendantFont If this is the descendant (true) or root + * (Type 0 font - false) font dictionary. Only True + * Type and CID encoded fonts will use a true value. + * @param fontDescriptor If the font descriptor has already have generated + * for this font, pass it in here, otherwise pass + * NULL. + */ + SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo, SkTypeface* typeface, + uint16_t glyphID, bool descendantFont, SkPDFDict* fontDescriptor); + + void populateType0Font(); + void populateCIDFont(); + bool populateType1Font(int16_t glyphID); + + /** Populate the PDF font dictionary as Type3 font which includes glyph + * descriptions with instructions for painting the glyphs. This function + * doesn't use any fields from SkAdvancedTypefaceMetrics (fFontInfo). Font + * information including glyph paths are queried from the platform + * dependent SkGlyphCache. + */ + void populateType3Font(int16_t glyphID); + bool addFontDescriptor(int16_t defaultWidth); + void populateToUnicodeTable(); + void addWidthInfoFromRange(int16_t defaultWidth, + const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry); + /** Set fFirstGlyphID and fLastGlyphID to span at most 255 glyphs, + * including the passed glyphID. + */ + void adjustGlyphRangeForSingleByteEncoding(int16_t glyphID); + + static bool find(uint32_t fontID, uint16_t glyphID, int* index); +}; + +#endif diff --git a/include/pdf/SkPDFFormXObject.h b/include/pdf/SkPDFFormXObject.h new file mode 100644 index 0000000..41719f0 --- /dev/null +++ b/include/pdf/SkPDFFormXObject.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFFormXObject_DEFINED +#define SkPDFFormXObject_DEFINED + +#include "SkPDFStream.h" +#include "SkPDFTypes.h" +#include "SkRefCnt.h" +#include "SkString.h" + +class SkMatrix; +class SkPDFDevice; +class SkPDFCatalog; + +/** \class SkPDFFormXObject + + A form XObject; a self contained description of graphics objects. A form + XObject is basically a page object with slightly different syntax, that + can be drawn onto a page. +*/ + +// The caller could keep track of the form XObjects it creates and +// canonicalize them, but the Skia API doesn't provide enough context to +// automatically do it (trivially). +class SkPDFFormXObject : public SkPDFObject { +public: + /** Create a PDF form XObject. Entries for the dictionary entries are + * automatically added. + * @param device The set of graphical elements on this form. + */ + explicit SkPDFFormXObject(SkPDFDevice* device); + virtual ~SkPDFFormXObject(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + virtual void getResources(SkTDArray<SkPDFObject*>* resourceList); + + /** Add the value to the stream dictionary with the given key. Refs value. + * @param key The key for this dictionary entry. + * @param value The value for this dictionary entry. + * @return The value argument is returned. + */ + SkPDFObject* insert(SkPDFName* key, SkPDFObject* value); + + /** Add the value to the stream dictionary with the given key. Refs value. + * @param key The text of the key for this dictionary entry. + * @param value The value for this dictionary entry. + * @return The value argument is returned. + */ + SkPDFObject* insert(const char key[], SkPDFObject* value); + +private: + SkRefPtr<SkPDFStream> fStream; + SkTDArray<SkPDFObject*> fResources; +}; + +#endif diff --git a/include/pdf/SkPDFGraphicState.h b/include/pdf/SkPDFGraphicState.h new file mode 100644 index 0000000..49809a4 --- /dev/null +++ b/include/pdf/SkPDFGraphicState.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFGraphicState_DEFINED +#define SkPDFGraphicState_DEFINED + +#include "SkPaint.h" +#include "SkPDFTypes.h" +#include "SkTemplates.h" +#include "SkThread.h" + +class SkPDFFormXObject; + +/** \class SkPDFGraphicState + SkPaint objects roughly correspond to graphic state dictionaries that can + be installed. So that a given dictionary is only output to the pdf file + once, we want to canonicalize them. Static methods in this class manage + a weakly referenced set of SkPDFGraphicState objects: when the last + reference to a SkPDFGraphicState is removed, it removes itself from the + static set of objects. + +*/ +class SkPDFGraphicState : public SkPDFDict { +public: + virtual ~SkPDFGraphicState(); + + virtual void getResources(SkTDArray<SkPDFObject*>* resourceList); + + // Override emitObject and getOutputSize so that we can populate + // the dictionary on demand. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + + /** Get the graphic state for the passed SkPaint. The reference count of + * the object is incremented and it is the caller's responsibility to + * unreference it when done. This is needed to accommodate the weak + * reference pattern used when the returned object is new and has no + * other references. + * @param paint The SkPaint to emulate. + */ + static SkPDFGraphicState* getGraphicStateForPaint(const SkPaint& paint); + + /** Make a graphic state that only sets the passed soft mask. The + * reference count of the object is incremented and it is the caller's + * responsibility to unreference it when done. + * @param sMask The form xobject to use as a soft mask. + * @param invert Indicates if the alpha of the sMask should be inverted. + */ + static SkPDFGraphicState* getSMaskGraphicState(SkPDFFormXObject* sMask, + bool invert); + + /** Get a graphic state that only unsets the soft mask. The reference + * count of the object is incremented and it is the caller's responsibility + * to unreference it when done. This is needed to accommodate the weak + * reference pattern used when the returned object is new and has no + * other references. + */ + static SkPDFGraphicState* getNoSMaskGraphicState(); + +private: + const SkPaint fPaint; + SkTDArray<SkPDFObject*> fResources; + bool fPopulated; + bool fSMask; + + class GSCanonicalEntry { + public: + SkPDFGraphicState* fGraphicState; + const SkPaint* fPaint; + + bool operator==(const GSCanonicalEntry& b) const; + explicit GSCanonicalEntry(SkPDFGraphicState* gs) + : fGraphicState(gs), + fPaint(&gs->fPaint) {} + explicit GSCanonicalEntry(const SkPaint* paint) : fPaint(paint) {} + }; + + // This should be made a hash table if performance is a problem. + static SkTDArray<GSCanonicalEntry>& canonicalPaints(); + static SkMutex& canonicalPaintsMutex(); + + SkPDFGraphicState(); + explicit SkPDFGraphicState(const SkPaint& paint); + + void populateDict(); + + static SkPDFObject* GetInvertFunction(); + + static int find(const SkPaint& paint); +}; + +#endif diff --git a/include/pdf/SkPDFImage.h b/include/pdf/SkPDFImage.h new file mode 100644 index 0000000..945ff9e --- /dev/null +++ b/include/pdf/SkPDFImage.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFImage_DEFINED +#define SkPDFImage_DEFINED + +#include "SkPDFStream.h" +#include "SkPDFTypes.h" +#include "SkRefCnt.h" + +class SkBitmap; +class SkPaint; +class SkPDFCatalog; +struct SkIRect; + +/** \class SkPDFImage + + An image XObject. +*/ + +// We could play the same trick here as is done in SkPDFGraphicState, storing +// a copy of the Bitmap object (not the pixels), the pixel generation number, +// and settings used from the paint to canonicalize image objects. +class SkPDFImage : public SkPDFObject { +public: + /** Create a new Image XObject to represent the passed bitmap. + * @param bitmap The image to encode. + * @param srcRect The rectangle to cut out of bitmap. + * @param paint Used to calculate alpha, masks, etc. + * @return The image XObject or NUll if there is nothing to draw for + * the given parameters. + */ + static SkPDFImage* CreateImage(const SkBitmap& bitmap, + const SkIRect& srcRect, + const SkPaint& paint); + + virtual ~SkPDFImage(); + + /** Add a Soft Mask (alpha or shape channel) to the image. Refs mask. + * @param mask A gray scale image representing the mask. + * @return The mask argument is returned. + */ + SkPDFImage* addSMask(SkPDFImage* mask); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + virtual void getResources(SkTDArray<SkPDFObject*>* resourceList); + +private: + SkRefPtr<SkPDFStream> fStream; + SkTDArray<SkPDFObject*> fResources; + + /** Create a PDF image XObject. Entries for the image properties are + * automatically added to the stream dictionary. + * @param imageData The final raw bits representing the image. + * @param bitmap The image parameters to use (Config, etc). + * @param srcRect The clipping applied to bitmap before generating + * imageData. + * @param alpha Is this the alpha channel of the bitmap. + * @param paint Used to calculate alpha, masks, etc. + */ + SkPDFImage(SkStream* imageData, const SkBitmap& bitmap, + const SkIRect& srcRect, bool alpha, const SkPaint& paint); + + /** Add the value to the stream dictionary with the given key. Refs value. + * @param key The key for this dictionary entry. + * @param value The value for this dictionary entry. + * @return The value argument is returned. + */ + SkPDFObject* insert(SkPDFName* key, SkPDFObject* value); + + /** Add the value to the stream dictionary with the given key. Refs value. + * @param key The text of the key for this dictionary entry. + * @param value The value for this dictionary entry. + * @return The value argument is returned. + */ + SkPDFObject* insert(const char key[], SkPDFObject* value); +}; + +#endif diff --git a/include/pdf/SkPDFPage.h b/include/pdf/SkPDFPage.h new file mode 100644 index 0000000..0e30028 --- /dev/null +++ b/include/pdf/SkPDFPage.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFPage_DEFINED +#define SkPDFPage_DEFINED + +#include "SkPDFTypes.h" +#include "SkPDFStream.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" + +class SkPDFCatalog; +class SkPDFDevice; +class SkWStream; + +/** \class SkPDFPage + + A SkPDFPage contains meta information about a page, is used in the page + tree and points to the content of the page. +*/ +class SkPDFPage : public SkPDFDict { +public: + /** Create a PDF page with the passed PDF device. The device need not + * have content on it yet. + * @param content The page content. + */ + explicit SkPDFPage(const SkRefPtr<SkPDFDevice>& content); + ~SkPDFPage(); + + /** Before a page and its contents can be sized and emitted, it must + * be finalized. No changes to the PDFDevice will be honored after + * finalizePage has been called. This function adds the page content + * to the passed catalog, so it must be called for each document + * that the page is part of. + * @param catalog The catalog to add page content objects to. + * @param firstPage Indicate if this is the first page of a document. + * @param resourceObjects The resource objects used on the page are added + * to this array. This gives the caller a chance + * to deduplicate resources across pages. + */ + void finalizePage(SkPDFCatalog* catalog, bool firstPage, + SkTDArray<SkPDFObject*>* resourceObjects); + + /** Determine the size of the page content and store to the catalog + * the offsets of all nonresource-indirect objects that make up the page + * content. This must be called before emitPage(), but after finalizePage. + * @param catalog The catalog to add the object offsets to. + * @param fileOffset The file offset where the page content will be + * emitted. + */ + off_t getPageSize(SkPDFCatalog* catalog, off_t fileOffset); + + /** Output the page content to the passed stream. + * @param stream The writable output stream to send the content to. + * @param catalog The active object catalog. + */ + void emitPage(SkWStream* stream, SkPDFCatalog* catalog); + + /** Generate a page tree for the passed vector of pages. New objects are + * added to the catalog. The pageTree vector is populated with all of + * the 'Pages' dictionaries as well as the 'Page' objects. Page trees + * have both parent and children links, creating reference cycles, so + * it must be torn down explicitly. The first page is not added to + * the pageTree dictionary array so the caller can handle it specially. + * @param pages The ordered vector of page objects. + * @param catalog The catalog to add new objects into. + * @param pageTree An output vector with all of the internal and leaf + * nodes of the pageTree. + * @param rootNode An output parameter set to the root node. + */ + static void generatePageTree(const SkTDArray<SkPDFPage*>& pages, + SkPDFCatalog* catalog, + SkTDArray<SkPDFDict*>* pageTree, + SkPDFDict** rootNode); + + /** Get the fonts used on this page. + */ + SK_API const SkTDArray<SkPDFFont*>& getFontResources() const; + +private: + // Multiple pages may reference the content. + SkRefPtr<SkPDFDevice> fDevice; + + // Once the content is finalized, put it into a stream for output. + SkRefPtr<SkPDFStream> fContentStream; +}; + +#endif diff --git a/include/pdf/SkPDFShader.h b/include/pdf/SkPDFShader.h new file mode 100644 index 0000000..17f7f03 --- /dev/null +++ b/include/pdf/SkPDFShader.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFShader_DEFINED +#define SkPDFShader_DEFINED + +#include "SkPDFStream.h" +#include "SkPDFTypes.h" +#include "SkMatrix.h" +#include "SkRefCnt.h" +#include "SkShader.h" + +class SkObjRef; +class SkPDFCatalog; + +/** \class SkPDFShader + + In PDF parlance, this is a pattern, used in place of a color when the + pattern color space is selected. +*/ + +class SkPDFShader : public SkPDFObject { +public: + virtual ~SkPDFShader(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + virtual void getResources(SkTDArray<SkPDFObject*>* resourceList); + + /** Get the PDF shader for the passed SkShader. If the SkShader is + * invalid in some way, returns NULL. The reference count of + * the object is incremented and it is the caller's responsibility to + * unreference it when done. This is needed to accommodate the weak + * reference pattern used when the returned object is new and has no + * other references. + * @param shader The SkShader to emulate. + * @param matrix The current transform. (PDF shaders are absolutely + * positioned, relative to where the page is drawn.) + * @param surfceBBox The bounding box of the drawing surface (with matrix + * already applied). + */ + static SkPDFShader* getPDFShader(const SkShader& shader, + const SkMatrix& matrix, + const SkIRect& surfaceBBox); + +private: + class State { + public: + SkShader::GradientType fType; + SkShader::GradientInfo fInfo; + SkAutoFree fColorData; + SkMatrix fCanvasTransform; + SkMatrix fShaderTransform; + SkIRect fBBox; + + SkBitmap fImage; + uint32_t fPixelGeneration; + SkShader::TileMode fImageTileModes[2]; + + explicit State(const SkShader& shader, const SkMatrix& canvasTransform, + const SkIRect& bbox); + bool operator==(const State& b) const; + }; + + SkRefPtr<SkPDFDict> fContent; + SkTDArray<SkPDFObject*> fResources; + SkAutoTDelete<const State> fState; + + class ShaderCanonicalEntry { + public: + SkPDFShader* fPDFShader; + const State* fState; + + bool operator==(const ShaderCanonicalEntry& b) const { + return fPDFShader == b.fPDFShader || *fState == *b.fState; + } + ShaderCanonicalEntry(SkPDFShader* pdfShader, const State* state) + : fPDFShader(pdfShader), + fState(state) { + } + }; + // This should be made a hash table if performance is a problem. + static SkTDArray<ShaderCanonicalEntry>& canonicalShaders(); + static SkMutex& canonicalShadersMutex(); + + static SkPDFObject* rangeObject(); + + SkPDFShader(State* state); + + void doFunctionShader(); + void doImageShader(); + SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); +}; + +#endif diff --git a/include/pdf/SkPDFStream.h b/include/pdf/SkPDFStream.h new file mode 100644 index 0000000..a975ad6 --- /dev/null +++ b/include/pdf/SkPDFStream.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFStream_DEFINED +#define SkPDFStream_DEFINED + +#include "SkPDFTypes.h" +#include "SkRefCnt.h" +#include "SkStream.h" +#include "SkTemplates.h" + +class SkPDFCatalog; + +/** \class SkPDFStream + + A stream object in a PDF. Note, all streams must be indirect objects (via + SkObjRef). +*/ +class SkPDFStream : public SkPDFDict { +public: + /** Create a PDF stream. A Length entry is automatically added to the + * stream dictionary. + * @param stream The data part of the stream. + */ + explicit SkPDFStream(SkStream* stream); + virtual ~SkPDFStream(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + +private: + size_t fLength; + // Only one of the two streams will be valid. + SkRefPtr<SkStream> fPlainData; + SkDynamicMemoryWStream fCompressedData; + + typedef SkPDFDict INHERITED; +}; + +#endif diff --git a/include/pdf/SkPDFTypes.h b/include/pdf/SkPDFTypes.h new file mode 100644 index 0000000..6b5146a --- /dev/null +++ b/include/pdf/SkPDFTypes.h @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFTypes_DEFINED +#define SkPDFTypes_DEFINED + +#include "SkRefCnt.h" +#include "SkScalar.h" +#include "SkString.h" +#include "SkTDArray.h" +#include "SkTypes.h" + +class SkPDFCatalog; +class SkWStream; + +/** \class SkPDFObject + + A PDF Object is the base class for primitive elements in a PDF file. A + common subtype is used to ease the use of indirect object references, + which are common in the PDF format. +*/ +class SkPDFObject : public SkRefCnt { +public: + /** Create a PDF object. + */ + SkPDFObject(); + virtual ~SkPDFObject(); + + /** Subclasses must implement this method to print the object to the + * PDF file. + * @param catalog The object catalog to use. + * @param indirect If true, output an object identifier with the object. + * @param stream The writable output stream to send the output to. + */ + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect) = 0; + + /** Return the size (number of bytes) of this object in the final output + * file. Compound objects or objects that are computationally intensive + * to output should override this method. + * @param catalog The object catalog to use. + * @param indirect If true, output an object identifier with the object. + */ + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + + /** If this object explicitly depends on other objects, add them to the + * end of the list. This only applies to higher level object, where + * the depenency is explicit and introduced by the class. i.e. an + * SkPDFImage added to an SkPDFDevice, but not an SkPDFObjRef added to + * an SkPDFArray. + * @param resourceList The list to append dependant resources to. + */ + virtual void getResources(SkTDArray<SkPDFObject*>* resourceList); + + /** Helper function to output an indirect object. + * @param catalog The object catalog to use. + * @param stream The writable output stream to send the output to. + */ + void emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog); + + /** Helper function to find the size of an indirect object. + * @param catalog The object catalog to use. + */ + size_t getIndirectOutputSize(SkPDFCatalog* catalog); +}; + +/** \class SkPDFObjRef + + An indirect reference to a PDF object. +*/ +class SkPDFObjRef : public SkPDFObject { +public: + /** Create a reference to an existing SkPDFObject. + * @param obj The object to reference. + */ + explicit SkPDFObjRef(SkPDFObject* obj); + virtual ~SkPDFObjRef(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + +private: + SkRefPtr<SkPDFObject> fObj; +}; + +/** \class SkPDFInt + + An integer object in a PDF. +*/ +class SkPDFInt : public SkPDFObject { +public: + /** Create a PDF integer (usually for indirect reference purposes). + * @param value An integer value between 2^31 - 1 and -2^31. + */ + explicit SkPDFInt(int32_t value); + virtual ~SkPDFInt(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + +private: + int32_t fValue; +}; + +/** \class SkPDFBool + + An boolean value in a PDF. +*/ +class SkPDFBool : public SkPDFObject { +public: + /** Create a PDF boolean. + * @param value true or false. + */ + explicit SkPDFBool(bool value); + virtual ~SkPDFBool(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + +private: + bool fValue; +}; + +/** \class SkPDFScalar + + A real number object in a PDF. +*/ +class SkPDFScalar : public SkPDFObject { +public: + /** Create a PDF real number. + * @param value A real value. + */ + explicit SkPDFScalar(SkScalar value); + virtual ~SkPDFScalar(); + + static void Append(SkScalar value, SkWStream* stream); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + +private: + SkScalar fValue; +}; + +/** \class SkPDFString + + A string object in a PDF. +*/ +class SkPDFString : public SkPDFObject { +public: + /** Create a PDF string. Maximum length (in bytes) is 65,535. + * @param value A string value. + */ + explicit SkPDFString(const char value[]); + explicit SkPDFString(const SkString& value); + + /** Create a PDF string. Maximum length (in bytes) is 65,535. + * @param value A string value. + * @param len The length of value. + * @param wideChars Indicates if the top byte in value is significant and + * should be encoded (true) or not (false). + */ + SkPDFString(const uint16_t* value, size_t len, bool wideChars); + virtual ~SkPDFString(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + + static SkString formatString(const char* input, size_t len); + static SkString formatString(const uint16_t* input, size_t len, + bool wideChars); +private: + static const size_t kMaxLen = 65535; + + const SkString fValue; + + static SkString doFormatString(const void* input, size_t len, + bool wideInput, bool wideOutput); +}; + +/** \class SkPDFName + + A name object in a PDF. +*/ +class SkPDFName : public SkPDFObject { +public: + /** Create a PDF name object. Maximum length is 127 bytes. + * @param value The name. + */ + explicit SkPDFName(const char name[]); + explicit SkPDFName(const SkString& name); + virtual ~SkPDFName(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + +private: + static const size_t kMaxLen = 127; + + const SkString fValue; + + static SkString formatName(const SkString& input); +}; + +/** \class SkPDFArray + + An array object in a PDF. +*/ +class SkPDFArray : public SkPDFObject { +public: + /** Create a PDF array. Maximum length is 8191. + */ + SkPDFArray(); + virtual ~SkPDFArray(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + + /** The size of the array. + */ + int size() { return fValue.count(); } + + /** Preallocate space for the given number of entries. + * @param length The number of array slots to preallocate. + */ + void reserve(int length); + + /** Returns the object at the given offset in the array. + * @param index The index into the array to retrieve. + */ + SkPDFObject* getAt(int index) { return fValue[index]; } + + /** Set the object at the given offset in the array. Ref's value. + * @param index The index into the array to set. + * @param value The value to add to the array. + * @return The value argument is returned. + */ + SkPDFObject* setAt(int index, SkPDFObject* value); + + /** Append the object to the end of the array and increments its ref count. + * @param value The value to add to the array. + * @return The value argument is returned. + */ + SkPDFObject* append(SkPDFObject* value); + +private: + static const int kMaxLen = 8191; + SkTDArray<SkPDFObject*> fValue; +}; + +/** \class SkPDFDict + + A dictionary object in a PDF. +*/ +class SkPDFDict : public SkPDFObject { +public: + /** Create a PDF dictionary. Maximum number of entries is 4095. + */ + SkPDFDict(); + + /** Create a PDF dictionary with a Type entry. + * @param type The value of the Type entry. + */ + explicit SkPDFDict(const char type[]); + + virtual ~SkPDFDict(); + + // The SkPDFObject interface. + virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, + bool indirect); + virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); + + /** The size of the dictionary. + */ + int size() { return fValue.count(); } + + /** Add the value to the dictionary with the given key. Refs value. + * @param key The key for this dictionary entry. + * @param value The value for this dictionary entry. + * @return The value argument is returned. + */ + SkPDFObject* insert(SkPDFName* key, SkPDFObject* value); + + /** Add the value to the dictionary with the given key. Refs value. The + * method will create the SkPDFName object. + * @param key The text of the key for this dictionary entry. + * @param value The value for this dictionary entry. + * @return The value argument is returned. + */ + SkPDFObject* insert(const char key[], SkPDFObject* value); + + /** Remove all entries from the dictionary. + */ + void clear(); + +private: + static const int kMaxLen = 4095; + + struct Rec { + SkPDFName* key; + SkPDFObject* value; + }; + + SkTDArray<struct Rec> fValue; +}; + +#endif diff --git a/include/pdf/SkPDFUtils.h b/include/pdf/SkPDFUtils.h new file mode 100644 index 0000000..50da28c --- /dev/null +++ b/include/pdf/SkPDFUtils.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFUtils_DEFINED +#define SkPDFUtils_DEFINED + +#include "SkPath.h" + +class SkMatrix; +class SkPath; +class SkPDFArray; +struct SkRect; + +#if 0 +#define PRINT_NOT_IMPL(str) fprintf(stderr, str) +#else +#define PRINT_NOT_IMPL(str) +#endif + +#define NOT_IMPLEMENTED(condition, assert) \ + do { \ + if (condition) { \ + PRINT_NOT_IMPL("NOT_IMPLEMENTED: " #condition "\n"); \ + SkDEBUGCODE(SkASSERT(!assert);) \ + } \ + } while(0) + +class SkPDFUtils { +public: + static SkPDFArray* MatrixToArray(const SkMatrix& matrix); + static void AppendTransform(const SkMatrix& matrix, SkWStream* content); + + static void MoveTo(SkScalar x, SkScalar y, SkWStream* content); + static void AppendLine(SkScalar x, SkScalar y, SkWStream* content); + static void AppendCubic(SkScalar ctl1X, SkScalar ctl1Y, + SkScalar ctl2X, SkScalar ctl2Y, + SkScalar dstX, SkScalar dstY, SkWStream* content); + static void AppendRectangle(const SkRect& rect, SkWStream* content); + static void EmitPath(const SkPath& path, SkWStream* content); + static void ClosePath(SkWStream* content); + static void PaintPath(SkPaint::Style style, SkPath::FillType fill, + SkWStream* content); + static void StrokePath(SkWStream* content); + static void DrawFormXObject(int objectIndex, SkWStream* content); + static void ApplyGraphicState(int objectIndex, SkWStream* content); +}; + +#endif diff --git a/include/pipe/SkGPipe.h b/include/pipe/SkGPipe.h new file mode 100644 index 0000000..897766f --- /dev/null +++ b/include/pipe/SkGPipe.h @@ -0,0 +1,96 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkGPipe_DEFINED +#define SkGPipe_DEFINED + +#include "SkWriter32.h" +#include "SkFlattenable.h" + +class SkCanvas; + +class SkGPipeReader { +public: + SkGPipeReader(SkCanvas* target); + ~SkGPipeReader(); + + enum Status { + kDone_Status, //!< no more data expected from reader + kEOF_Status, //!< need more data from reader + kError_Status //!< encountered error + }; + + // data must be 4-byte aligned + // length must be a multiple of 4 + Status playback(const void* data, size_t length, size_t* bytesRead = NULL); + +private: + SkCanvas* fCanvas; + class SkGPipeState* fState; +}; + +/////////////////////////////////////////////////////////////////////////////// + +class SkGPipeController { +public: + /** + * Called periodically by the writer, to get a working buffer of RAM to + * write into. The actual size of the block is also returned, and must be + * actual >= minRequest. If NULL is returned, then actual is ignored and + * writing will stop. + * + * The returned block must be 4-byte aligned, and actual must be a + * multiple of 4. + * minRequest will always be a multiple of 4. + */ + virtual void* requestBlock(size_t minRequest, size_t* actual) = 0; + + /** + * This is called each time some atomic portion of the data has been + * written to the block (most recently returned by requestBlock()). + * If bytes == 0, then the writer has finished. + * + * bytes will always be a multiple of 4. + */ + virtual void notifyWritten(size_t bytes) = 0; +}; + +class SkGPipeWriter { +public: + SkGPipeWriter(); + ~SkGPipeWriter(); + + bool isRecording() const { return NULL != fCanvas; } + + enum Flags { + kCrossProcess_Flag = 1 << 0, + }; + + SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0); + + // called in destructor, but can be called sooner once you know there + // should be no more drawing calls made into the recording canvas. + void endRecording(); + +private: + class SkGPipeCanvas* fCanvas; + SkGPipeController* fController; + SkFactorySet fFactorySet; + SkWriter32 fWriter; +}; + +#endif diff --git a/include/utils/SkEGLContext.h b/include/utils/SkEGLContext.h index 4b17be1..ced31a5 100644 --- a/include/utils/SkEGLContext.h +++ b/include/utils/SkEGLContext.h @@ -1,20 +1,53 @@ #ifndef SkEGLContext_DEFINED #define SkEGLContext_DEFINED -#include "SkTypes.h" +#if defined(SK_MESA) + #include "GL/osmesa.h" +#elif defined(SK_BUILD_FOR_MAC) + #include <AGL/agl.h> +#elif defined(SK_BUILD_FOR_ANDROID) + #include "GLES2/gl2.h" + #include "EGL/egl.h" +#elif defined(SK_BUILD_FOR_UNIX) + #include <X11/Xlib.h> + #include <GL/glx.h> +#elif defined(SK_BUILD_FOR_WIN32) + #include <Windows.h> + #include <GL/GL.h> +#else + +#endif /** * Create an offscreen opengl context */ class SkEGLContext { public: - SkEGLContext(); - ~SkEGLContext(); + SkEGLContext(); + ~SkEGLContext(); - bool init(int width, int height); + bool init(const int width, const int height); private: - void* fContext; +#if defined(SK_MESA) + OSMesaContext context; + GLfloat *image; +#elif defined(SK_BUILD_FOR_MAC) + AGLContext context; +#elif defined(SK_BUILD_FOR_ANDROID) + +#elif defined(SK_BUILD_FOR_UNIX) + GLXContext context; + Display *display; + Pixmap pixmap; + GLXPixmap glxPixmap; +#elif defined(SK_BUILD_FOR_WIN32) + HWND fWindow; + HDC fDeviceContext; + HGLRC fGlRenderContext; +#else + +#endif }; #endif diff --git a/include/utils/android/AndroidKeyToSkKey.h b/include/utils/android/AndroidKeyToSkKey.h new file mode 100644 index 0000000..7b0a035 --- /dev/null +++ b/include/utils/android/AndroidKeyToSkKey.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011 Skia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_TO_SKIA_KEYCODES_H +#define _ANDROID_TO_SKIA_KEYCODES_H + +#include "keycodes.h" +#include "SkKey.h" + +// Convert an Android keycode to an SkKey. This is an incomplete list, only +// including keys used by the sample app. +SkKey AndroidKeycodeToSkKey(int keycode) { + switch (keycode) { + case AKEYCODE_DPAD_LEFT: + return kLeft_SkKey; + case AKEYCODE_DPAD_RIGHT: + return kRight_SkKey; + case AKEYCODE_DPAD_UP: + return kUp_SkKey; + case AKEYCODE_DPAD_DOWN: + return kDown_SkKey; + default: + return kNONE_SkKey; + } +} + +#endif diff --git a/include/utils/unix/XkeysToSkKeys.h b/include/utils/unix/XkeysToSkKeys.h index 3d41a22..1852d99 100644 --- a/include/utils/unix/XkeysToSkKeys.h +++ b/include/utils/unix/XkeysToSkKeys.h @@ -8,6 +8,14 @@ SkKey XKeyToSkKey(KeySym keysym) { switch (keysym) { + case XK_BackSpace: + return kBack_SkKey; + case XK_Return: + return kOK_SkKey; + case XK_Home: + return kHome_SkKey; + case XK_End: + return kEnd_SkKey; case XK_Right: return kRight_SkKey; case XK_Left: diff --git a/include/views/SkApplication.h b/include/views/SkApplication.h new file mode 100644 index 0000000..4c4a4fb --- /dev/null +++ b/include/views/SkApplication.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkApplication_DEFINED +#define SkApplication_DEFINED + +class SkOSWindow; + +extern SkOSWindow* create_sk_window(void* hwnd); +extern void application_init(); +extern void application_term(); + +#endif // SkApplication_DEFINED diff --git a/include/views/SkBGViewArtist.h b/include/views/SkBGViewArtist.h new file mode 100644 index 0000000..1bca42f --- /dev/null +++ b/include/views/SkBGViewArtist.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkBGViewArtist_DEFINED +#define SkBGViewArtist_DEFINED + +#include "SkView.h" +#include "SkPaint.h" + +class SkBGViewArtist : public SkView::Artist { +public: + SkBGViewArtist(SkColor c = SK_ColorWHITE); + virtual ~SkBGViewArtist(); + + const SkPaint& paint() const { return fPaint; } + SkPaint& paint() { return fPaint; } + +protected: + // overrides + virtual void onDraw(SkView*, SkCanvas*); + virtual void onInflate(const SkDOM&, const SkDOM::Node*); + +private: + SkPaint fPaint; +}; + +#endif + diff --git a/include/views/SkBorderView.h b/include/views/SkBorderView.h new file mode 100644 index 0000000..94ccc1f --- /dev/null +++ b/include/views/SkBorderView.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkBorderView_DEFINED +#define SkBorderView_DEFINED + +#include "SkView.h" +#include "SkWidgetViews.h" +#include "SkAnimator.h" + +class SkBorderView : public SkWidgetView { +public: + SkBorderView(); + ~SkBorderView(); + void setSkin(const char skin[]); + SkScalar getLeft() const { return fLeft; } + SkScalar getRight() const { return fRight; } + SkScalar getTop() const { return fTop; } + SkScalar getBottom() const { return fBottom; } +protected: + //overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + virtual void onSizeChange(); + virtual void onDraw(SkCanvas* canvas); + virtual bool onEvent(const SkEvent& evt); +private: + SkAnimator fAnim; + SkScalar fLeft, fRight, fTop, fBottom; //margin on each side + SkRect fMargin; + + typedef SkWidgetView INHERITED; +}; + +#endif + diff --git a/include/views/SkEvent.h b/include/views/SkEvent.h new file mode 100644 index 0000000..f6719d6 --- /dev/null +++ b/include/views/SkEvent.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkEvent_DEFINED +#define SkEvent_DEFINED + +#include "SkDOM.h" +#include "SkMetaData.h" +#include "SkString.h" + +/** Unique 32bit id used to identify an instance of SkEventSink. When events are + posted, they are posted to a specific sinkID. When it is time to dispatch the + event, the sinkID is used to find the specific SkEventSink object. If it is found, + its doEvent() method is called with the event. +*/ +typedef uint32_t SkEventSinkID; + +/** \class SkEvent + + SkEvents are used to communicate type-safe information to SkEventSinks. + SkEventSinks (including SkViews) each have a unique ID, which is stored + in an event. This ID is used to target the event once it has been "posted". +*/ +class SkEvent { +public: + /** Default construct, creating an empty event. + */ + SkEvent(); + /** Construct a new event with the specified type. + */ + explicit SkEvent(const SkString& type); + /** Construct a new event with the specified type. + */ + explicit SkEvent(const char type[]); + /** Construct a new event by copying the fields from the src event. + */ + SkEvent(const SkEvent& src); + ~SkEvent(); + +// /** Return the event's type (will never be null) */ +// const char* getType() const; + /** Copy the event's type into the specified SkString parameter */ + void getType(SkString* str) const; + /** Returns true if the event's type matches exactly the specified type (case sensitive) */ + bool isType(const SkString& str) const; + /** Returns true if the event's type matches exactly the specified type (case sensitive) */ + bool isType(const char type[], size_t len = 0) const; + /** Set the event's type to the specified string. + In XML, use the "type" attribute. + */ + void setType(const SkString&); + /** Set the event's type to the specified string. + In XML, use the "type" attribute. + */ + void setType(const char type[], size_t len = 0); + + /** Return the event's unnamed 32bit field. Default value is 0 */ + uint32_t getFast32() const { return f32; } + /** Set the event's unnamed 32bit field. In XML, use + the subelement <data fast32=... /> + */ + void setFast32(uint32_t x) { f32 = x; } + + /** Return true if the event contains the named 32bit field, and return the field + in value (if value is non-null). If there is no matching named field, return false + and ignore the value parameter. + */ + bool findS32(const char name[], int32_t* value = NULL) const { return fMeta.findS32(name, value); } + /** Return true if the event contains the named SkScalar field, and return the field + in value (if value is non-null). If there is no matching named field, return false + and ignore the value parameter. + */ + bool findScalar(const char name[], SkScalar* value = NULL) const { return fMeta.findScalar(name, value); } + /** Return true if the event contains the named SkScalar field, and return the fields + in value[] (if value is non-null), and return the number of SkScalars in count (if count is non-null). + If there is no matching named field, return false and ignore the value and count parameters. + */ + const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const { return fMeta.findScalars(name, count, values); } + /** Return the value of the named string field, or if no matching named field exists, return null. + */ + const char* findString(const char name[]) const { return fMeta.findString(name); } + /** Return true if the event contains the named pointer field, and return the field + in value (if value is non-null). If there is no matching named field, return false + and ignore the value parameter. + */ + bool findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); } + bool findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); } + const void* findData(const char name[], size_t* byteCount = NULL) const { + return fMeta.findData(name, byteCount); + } + + /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */ + bool hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); } + /** Returns true if ethe event contains the named SkScalar field, and if it equals the specified value */ + bool hasScalar(const char name[], SkScalar value) const { return fMeta.hasScalar(name, value); } + /** Returns true if ethe event contains the named string field, and if it equals (using strcmp) the specified value */ + bool hasString(const char name[], const char value[]) const { return fMeta.hasString(name, value); } + /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */ + bool hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); } + bool hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); } + bool hasData(const char name[], const void* data, size_t byteCount) const { + return fMeta.hasData(name, data, byteCount); + } + + /** Add/replace the named 32bit field to the event. In XML use the subelement <data name=... s32=... /> */ + void setS32(const char name[], int32_t value) { fMeta.setS32(name, value); } + /** Add/replace the named SkScalar field to the event. In XML use the subelement <data name=... scalar=... /> */ + void setScalar(const char name[], SkScalar value) { fMeta.setScalar(name, value); } + /** Add/replace the named SkScalar[] field to the event. */ + SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL) { return fMeta.setScalars(name, count, values); } + /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */ + void setString(const char name[], const SkString& value) { fMeta.setString(name, value.c_str()); } + /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */ + void setString(const char name[], const char value[]) { fMeta.setString(name, value); } + /** Add/replace the named pointer field to the event. There is no XML equivalent for this call */ + void setPtr(const char name[], void* value) { fMeta.setPtr(name, value); } + void setBool(const char name[], bool value) { fMeta.setBool(name, value); } + void setData(const char name[], const void* data, size_t byteCount) { + fMeta.setData(name, data, byteCount); + } + + /** Return the underlying metadata object */ + SkMetaData& getMetaData() { return fMeta; } + /** Return the underlying metadata object */ + const SkMetaData& getMetaData() const { return fMeta; } + + void tron() { SkDEBUGCODE(fDebugTrace = true;) } + void troff() { SkDEBUGCODE(fDebugTrace = false;) } + bool isDebugTrace() const + { +#ifdef SK_DEBUG + return fDebugTrace; +#else + return false; +#endif + } + + /** Call this to initialize the event from the specified XML node */ + void inflate(const SkDOM&, const SkDOM::Node*); + + SkDEBUGCODE(void dump(const char title[] = NULL);) + + /** Post the specified event to the event queue, targeting the specified eventsink, with an optional + delay. The event must be dynamically allocated for this. It cannot be a global or on the stack. + After this call, ownership is transfered to the system, so the caller must not retain + the event's ptr. Returns false if the event could not be posted (which means it will have been deleted). + */ + static bool Post(SkEvent* evt, SkEventSinkID targetID, SkMSec delay = 0); + /** Post the specified event to the event queue, targeting the specified eventsink, to be delivered on/after the + specified millisecond time. The event must be dynamically allocated for this. It cannot be a global or on the stack. + After this call, ownership is transfered to the system, so the caller must not retain + the event's ptr. Returns false if the event could not be posted (which means it will have been deleted). + */ + static bool PostTime(SkEvent* evt, SkEventSinkID targetID, SkMSec time); + + /** Helper method for calling SkEvent::PostTime(this, ...), where the caller specifies a delay. + The real "time" will be computed automatically by sampling the clock and adding its value + to delay. + */ + bool post(SkEventSinkID sinkID, SkMSec delay = 0) + { + return SkEvent::Post(this, sinkID, delay); + } + + void postTime(SkEventSinkID sinkID, SkMSec time) + { + SkEvent::PostTime(this, sinkID, time); + } + + /////////////////////////////////////////////// + /** Porting layer must call these functions **/ + /////////////////////////////////////////////// + + /** Global initialization function for the SkEvent system. Should be called exactly + once before any other event method is called, and should be called after the + call to SkGraphics::Init(). + */ + static void Init(); + /** Global cleanup function for the SkEvent system. Should be called exactly once after + all event methods have been called, and should be called before calling SkGraphics::Term(). + */ + static void Term(); + + /** Call this to process one event from the queue. If it returns true, there are more events + to process. + */ + static bool ProcessEvent(); + /** Call this whenever the requested timer has expired (requested by a call to SetQueueTimer). + It will post any delayed events whose time as "expired" onto the event queue. + It may also call SignalQueueTimer() and SignalNonEmptyQueue(). + */ + static void ServiceQueueTimer(); + + /** Return the number of queued events. note that this value may be obsolete + upon return, since another thread may have called ProcessEvent() or + Post() after the count was made. + */ + static int CountEventsOnQueue(); + + //////////////////////////////////////////////////// + /** Porting layer must implement these functions **/ + //////////////////////////////////////////////////// + + /** Called whenever an SkEvent is posted to an empty queue, so that the OS + can be told to later call Dequeue(). + */ + static void SignalNonEmptyQueue(); + /** Called whenever the delay until the next delayed event changes. If zero is + passed, then there are no more queued delay events. + */ + static void SignalQueueTimer(SkMSec delay); + +#ifndef SK_USE_WXWIDGETS +#ifdef SK_BUILD_FOR_WIN + static bool WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +#elif defined(SK_BUILD_FOR_UNIXx) + static uint32_t HandleTimer(uint32_t, void*); + static bool WndProc(Display*, Window, XEvent&); +#endif +#else + // Don't know yet what this will be + //static bool CustomEvent(); +#endif + +private: + SkMetaData fMeta; + mutable char* fType; // may be characters with low bit set to know that it is not a pointer + uint32_t f32; + SkDEBUGCODE(bool fDebugTrace;) + + // these are for our implementation of the event queue + SkEventSinkID fTargetID; + SkMSec fTime; + SkEvent* fNextEvent; // either in the delay or normal event queue + void initialize(const char* type, size_t typeLen); + + static bool Enqueue(SkEvent* evt); + static SkMSec EnqueueTime(SkEvent* evt, SkMSec time); + static SkEvent* Dequeue(SkEventSinkID* targetID); + static bool QHasEvents(); +}; + +#endif + diff --git a/include/views/SkEventSink.h b/include/views/SkEventSink.h new file mode 100644 index 0000000..27a6743 --- /dev/null +++ b/include/views/SkEventSink.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkEventSink_DEFINED +#define SkEventSink_DEFINED + +#include "SkRefCnt.h" +#include "SkEvent.h" + +struct SkTagList; + +/** \class SkEventSink + + SkEventSink is the base class for all objects that receive SkEvents. +*/ +class SkEventSink : public SkRefCnt { +public: + SkEventSink(); + virtual ~SkEventSink(); + + /** Returns this eventsink's unique ID. Use this to post SkEvents to + this eventsink. + */ + SkEventSinkID getSinkID() const { return fID; } + + /** Call this to pass an event to this object for processing. Returns true if the + event was handled. + */ + bool doEvent(const SkEvent&); + /** Returns true if the sink (or one of its subclasses) understands the event as a query. + If so, the sink may modify the event to communicate its "answer". + */ + bool doQuery(SkEvent* query); + + /** Add sinkID to the list of listeners, to receive events from calls to sendToListeners() + and postToListeners(). If sinkID already exists in the listener list, no change is made. + */ + void addListenerID(SkEventSinkID sinkID); + /** Copy listeners from one event sink to another, typically from parent to child. + @param from the event sink to copy the listeners from + */ + void copyListeners(const SkEventSink& from); + /** Remove sinkID from the list of listeners. If sinkID does not appear in the list, + no change is made. + */ + void removeListenerID(SkEventSinkID); + /** Returns true if there are 1 or more listeners attached to this eventsink + */ + bool hasListeners() const; + /** Posts a copy of evt to each of the eventsinks in the lisener list. + */ + void postToListeners(const SkEvent& evt, SkMSec delay = 0); + + enum EventResult { + kHandled_EventResult, //!< the eventsink returned true from its doEvent method + kNotHandled_EventResult, //!< the eventsink returned false from its doEvent method + kSinkNotFound_EventResult //!< no matching eventsink was found for the event's getSink(). + }; + /** DoEvent handles searching for an eventsink object that matches the targetID. + If one is found, it calls the sink's doEvent method, returning + either kHandled_EventResult or kNotHandled_EventResult. If no matching + eventsink is found, kSinkNotFound_EventResult is returned. + */ + static EventResult DoEvent(const SkEvent&, SkEventSinkID targetID); + + /** Returns the matching eventsink, or null if not found + */ + static SkEventSink* FindSink(SkEventSinkID); + +protected: + /** Override this to handle events in your subclass. Be sure to call the inherited version + for events that you don't handle. + */ + virtual bool onEvent(const SkEvent&); + virtual bool onQuery(SkEvent*); + + SkTagList* findTagList(U8CPU tag) const; + void addTagList(SkTagList*); + void removeTagList(U8CPU tag); + +private: + SkEventSinkID fID; + SkTagList* fTagHead; + + // for our private link-list + SkEventSink* fNextSink; +}; + +#endif + diff --git a/include/views/SkImageView.h b/include/views/SkImageView.h new file mode 100644 index 0000000..57215c9 --- /dev/null +++ b/include/views/SkImageView.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkImageView_DEFINED +#define SkImageView_DEFINED + +#include "SkView.h" +#include "SkString.h" + +class SkAnimator; +class SkBitmap; +class SkMatrix; + +class SkImageView : public SkView { +public: + SkImageView(); + virtual ~SkImageView(); + + void getUri(SkString*) const; + void setUri(const char []); + void setUri(const SkString&); + + + enum ScaleType { + kMatrix_ScaleType, + kFitXY_ScaleType, + kFitStart_ScaleType, + kFitCenter_ScaleType, + kFitEnd_ScaleType + }; + ScaleType getScaleType() const { return (ScaleType)fScaleType; } + void setScaleType(ScaleType); + + bool getImageMatrix(SkMatrix*) const; + void setImageMatrix(const SkMatrix*); + +protected: + // overrides + virtual bool onEvent(const SkEvent&); + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM&, const SkDOMNode*); + +private: + SkString fUri; + SkMatrix* fMatrix; // null or copy of caller's matrix ,,,,, + union { + SkAnimator* fAnim; + SkBitmap* fBitmap; + } fData; + uint8_t fScaleType; + SkBool8 fDataIsAnim; // as opposed to bitmap + SkBool8 fUriIsValid; + + void onUriChange(); + bool getDataBounds(SkRect* bounds); + bool freeData(); + bool ensureUriIsLoaded(); + + typedef SkView INHERITED; +}; + +#endif diff --git a/include/views/SkKey.h b/include/views/SkKey.h new file mode 100644 index 0000000..3fd5114 --- /dev/null +++ b/include/views/SkKey.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkKey_DEFINED +#define SkKey_DEFINED + +#include "SkTypes.h" + +enum SkKey { + //reordering these to match android.app.KeyEvent + kNONE_SkKey, //corresponds to android's UNKNOWN + + kLeftSoftKey_SkKey, + kRightSoftKey_SkKey, + + kHome_SkKey, //!< the home key - added to match android + kBack_SkKey, //!< (CLR) + kSend_SkKey, //!< the green (talk) key + kEnd_SkKey, //!< the red key + + k0_SkKey, + k1_SkKey, + k2_SkKey, + k3_SkKey, + k4_SkKey, + k5_SkKey, + k6_SkKey, + k7_SkKey, + k8_SkKey, + k9_SkKey, + kStar_SkKey, //!< the * key + kHash_SkKey, //!< the # key + + kUp_SkKey, + kDown_SkKey, + kLeft_SkKey, + kRight_SkKey, + + kOK_SkKey, //!< the center key + + kVolUp_SkKey, //!< volume up - match android + kVolDown_SkKey, //!< volume down - same + kPower_SkKey, //!< power button - same + kCamera_SkKey, //!< camera - same + + kSkKeyCount +}; + +#endif + diff --git a/include/views/SkOSMenu.h b/include/views/SkOSMenu.h new file mode 100644 index 0000000..433a601 --- /dev/null +++ b/include/views/SkOSMenu.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkOSMenu_DEFINED +#define SkOSMenu_DEFINED + +#include "SkEvent.h" +#include "SkTDArray.h" + +class SkOSMenu { +public: + explicit SkOSMenu(const char title[]); + ~SkOSMenu(); + + const char* getTitle() const { return fTitle; } + + void appendItem(const char title[], const char eventType[], int32_t eventData); + + // called by SkOSWindow when it receives an OS menu event + int countItems() const; + const char* getItem(int index, uint32_t* cmdID) const; + + SkEvent* createEvent(uint32_t os_cmd); + +private: + const char* fTitle; + + struct Item { + const char* fTitle; + const char* fEventType; + uint32_t fEventData; + uint32_t fOSCmd; // internal + }; + SkTDArray<Item> fItems; + + // illegal + SkOSMenu(const SkOSMenu&); + SkOSMenu& operator=(const SkOSMenu&); +}; + +#endif + diff --git a/include/views/SkOSWindow_Android.h b/include/views/SkOSWindow_Android.h new file mode 100644 index 0000000..38a4cf8 --- /dev/null +++ b/include/views/SkOSWindow_Android.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 Skia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkOSWindow_Android_DEFINED +#define SkOSWindow_Android_DEFINED + +#include "SkWindow.h" +#include "SkEvent.h" + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void*) {} + ~SkOSWindow() {} + bool attachGL() { return false; } + void detachGL() {} + void presentGL() {} + +protected: + // overrides from SkWindow + virtual void onHandleInval(const SkIRect&); + virtual void onSetTitle(const char title[]); + +private: + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/views/SkOSWindow_Mac.h b/include/views/SkOSWindow_Mac.h new file mode 100644 index 0000000..232a202 --- /dev/null +++ b/include/views/SkOSWindow_Mac.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkOSWindow_Mac_DEFINED +#define SkOSWindow_Mac_DEFINED + +#include <Carbon/Carbon.h> +#include "SkWindow.h" + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void* hwnd); + + void* getHWND() const { return fHWND; } + void* getHVIEW() const { return fHVIEW; } + void updateSize(); + + static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + static OSStatus EventHandler(EventHandlerCallRef inHandler, + EventRef inEvent, void* userData); + + void doPaint(void* ctx); + + + bool attachGL(); + void detachGL(); + void presentGL(); + +protected: + // overrides from SkEventSink + virtual bool onEvent(const SkEvent& evt); + // overrides from SkWindow + virtual void onHandleInval(const SkIRect&); + // overrides from SkView + virtual void onAddMenu(const SkOSMenu*); + virtual void onSetTitle(const char[]); + + +private: + void* fHWND; + void* fHVIEW; + void* fAGLCtx; + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/views/SkOSWindow_SDL.h b/include/views/SkOSWindow_SDL.h new file mode 100644 index 0000000..0ff24f3 --- /dev/null +++ b/include/views/SkOSWindow_SDL.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkOSWindow_SDL_DEFINED +#define SkOSWindow_SDL_DEFINED + +#include "SDL.h" +#include "SkWindow.h" + +class SkGLCanvas; + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void* screen); + virtual ~SkOSWindow(); + + static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + void handleSDLEvent(const SDL_Event& event); + +protected: + // overrides from SkWindow + virtual void onHandleInval(const SkIRect&); + // overrides from SkView + virtual void onAddMenu(const SkOSMenu*); + virtual void onSetTitle(const char[]); + +private: + SDL_Surface* fScreen; + SDL_Surface* fSurface; + SkGLCanvas* fGLCanvas; + + void doDraw(); + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/views/SkOSWindow_Unix.h b/include/views/SkOSWindow_Unix.h new file mode 100644 index 0000000..803ca13 --- /dev/null +++ b/include/views/SkOSWindow_Unix.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkOSWindow_Unix_DEFINED +#define SkOSWindow_Unix_DEFINED + +#include "SkWindow.h" +#include <X11/Xlib.h> +#include <GL/glx.h> + +class SkBitmap; +class SkEvent; + +struct SkUnixWindow { + Display* fDisplay; + Window fWin; + size_t fOSWin; + GC fGc; + GLXContext fGLContext; + bool fGLCreated; +}; + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void*); + ~SkOSWindow(); + + void* getHWND() const { return (void*)fUnixWindow.fWin; } + void* getDisplay() const { return (void*)fUnixWindow.fDisplay; } + void* getUnixWindow() const { return (void*)&fUnixWindow; } + void loop(); + void post_linuxevent(); + bool attachGL(); + void detachGL(); + void presentGL(); + + //static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + //static bool WndProc(SkUnixWindow* w, XEvent &e); + +protected: + // overrides from SkWindow + virtual bool onEvent(const SkEvent&); + virtual void onHandleInval(const SkIRect&); + virtual bool onHandleChar(SkUnichar); + virtual bool onHandleKey(SkKey); + virtual bool onHandleKeyUp(SkKey); + virtual void onSetTitle(const char title[]); + +private: + SkUnixWindow fUnixWindow; + bool fGLAttached; + bool fRestart; + + // Needed for GL + XVisualInfo* fVi; + + void doPaint(); + void restartLoop(); + void mapWindowAndWait(); + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h new file mode 100644 index 0000000..4b3e916 --- /dev/null +++ b/include/views/SkOSWindow_Win.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkOSWindow_Win_DEFINED +#define SkOSWindow_Win_DEFINED + +#include "SkWindow.h" + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void* hwnd); + virtual ~SkOSWindow(); + + void* getHWND() const { return fHWND; } + void setSize(int width, int height); + void updateSize(); + + static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + bool attachGL(); + void detachGL(); + void presentGL(); + + bool attachD3D9(); + void detachD3D9(); + void presentD3D9(); + + void* d3d9Device() { return fD3D9Device; } + + bool wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + static bool QuitOnDeactivate(HWND hWnd); + + enum { + SK_WM_SkEvent = WM_APP + 1000, + SK_WM_SkTimerID = 0xFFFF // just need a non-zero value + }; + +protected: + virtual bool quitOnDeactivate() { return true; } + + // overrides from SkWindow + virtual void onHandleInval(const SkIRect&); + // overrides from SkView + virtual void onAddMenu(const SkOSMenu*); + + virtual void onSetTitle(const char title[]); + +private: + void* fHWND; + + void doPaint(void* ctx); + + void* fHGLRC; + + bool fGLAttached; + + void* fD3D9Device; + bool fD3D9Attached; + + HMENU fMBar; + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/views/SkOSWindow_wxwidgets.h b/include/views/SkOSWindow_wxwidgets.h new file mode 100644 index 0000000..c5dfc7c --- /dev/null +++ b/include/views/SkOSWindow_wxwidgets.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SkOSWindow_wxwidgets.h + * wxwidgets + * + * Copyright 2005 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef SkOSWindow_wxwidgets_DEFINED +#define SkOSWindow_wxwidgets_DEFINED + +#include "SkWindow.h" +#include "wx/frame.h" + +class SkOSWindow: public SkWindow +{ +public: + SkOSWindow(); + SkOSWindow(const wxString& title, int x, int y, int width, int height); + ~SkOSWindow(); + + wxFrame* getWXFrame() const { return fFrame; } + + void updateSize(); + +protected: + virtual void onHandleInval(const SkIRect&); + virtual void onAddMenu(const SkOSMenu*); + +private: + wxFrame* fFrame; + typedef SkWindow INHERITED; + +}; + +#endifpedef SkWindow INHERITED; diff --git a/include/views/SkProgressBarView.h b/include/views/SkProgressBarView.h new file mode 100644 index 0000000..6341fcb --- /dev/null +++ b/include/views/SkProgressBarView.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkProgressBarView_DEFINED +#define SkProgressBarView_DEFINED + +#include "SkView.h" +#include "SkWidgetViews.h" +#include "SkAnimator.h" + +class SkProgressBarView : public SkWidgetView { + public: + SkProgressBarView(); + //SkProgressBarView(int max); + + //inflate: "sk-progress" + + void reset(); //reset progress to zero + void setProgress(int progress); + void changeProgress(int diff); + void setMax(int max); + + int getProgress() const { return fProgress; } + int getMax() const { return fMax; } + + protected: + //overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + virtual void onSizeChange(); + virtual void onDraw(SkCanvas* canvas); + virtual bool onEvent(const SkEvent& evt); + + private: + SkAnimator fAnim; + int fProgress; + int fMax; + + typedef SkWidgetView INHERITED; +}; + + + + +#endif diff --git a/include/views/SkScrollBarView.h b/include/views/SkScrollBarView.h new file mode 100644 index 0000000..b8a5209 --- /dev/null +++ b/include/views/SkScrollBarView.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkScrollBarView_DEFINED +#define SkScrollBarView_DEFINED + +#include "SkView.h" +#include "SkWidgetViews.h" +#include "SkAnimator.h" + +class SkScrollBarView : public SkWidgetView { +public: + SkScrollBarView(); + + unsigned getStart() const { return fStartPoint; } + unsigned getShown() const { return fShownLength; } + unsigned getTotal() const { return fTotalLength; } + + void setStart(unsigned start); + void setShown(unsigned shown); + void setTotal(unsigned total); + +protected: + //overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + virtual void onSizeChange(); + virtual void onDraw(SkCanvas* canvas); + virtual bool onEvent(const SkEvent& evt); + +private: + SkAnimator fAnim; + unsigned fTotalLength, fStartPoint, fShownLength; + + void adjust(); + + typedef SkWidgetView INHERITED; +}; +#endif + diff --git a/include/views/SkStackViewLayout.h b/include/views/SkStackViewLayout.h new file mode 100644 index 0000000..8000319 --- /dev/null +++ b/include/views/SkStackViewLayout.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkStackViewLayout_DEFINED +#define SkStackViewLayout_DEFINED + +#include "SkView.h" + +class SkStackViewLayout : public SkView::Layout { +public: + SkStackViewLayout(); + + enum Orient { + kHorizontal_Orient, + kVertical_Orient, + + kOrientCount + }; + Orient getOrient() const { return (Orient)fOrient; } + void setOrient(Orient); + + void getMargin(SkRect*) const; + void setMargin(const SkRect&); + + SkScalar getSpacer() const { return fSpacer; } + void setSpacer(SkScalar); + + /** Controls the posititioning in the same direction as the orientation + */ + enum Pack { + kStart_Pack, + kCenter_Pack, + kEnd_Pack, + + kPackCount + }; + Pack getPack() const { return (Pack)fPack; } + void setPack(Pack); + + /** Controls the posititioning at right angles to the orientation + */ + enum Align { + kStart_Align, + kCenter_Align, + kEnd_Align, + kStretch_Align, + + kAlignCount + }; + Align getAlign() const { return (Align)fAlign; } + void setAlign(Align); + + bool getRound() const { return SkToBool(fRound); } + void setRound(bool); + +protected: + virtual void onLayoutChildren(SkView* parent); + virtual void onInflate(const SkDOM&, const SkDOM::Node*); + +private: + SkRect fMargin; + SkScalar fSpacer; + uint8_t fOrient, fPack, fAlign, fRound; +}; + +class SkFillViewLayout : public SkView::Layout { +public: + SkFillViewLayout(); + void getMargin(SkRect*) const; + void setMargin(const SkRect&); + +protected: + // overrides; + virtual void onLayoutChildren(SkView* parent); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + SkRect fMargin; + typedef SkView::Layout INHERITED; +}; + +#endif + diff --git a/include/views/SkSystemEventTypes.h b/include/views/SkSystemEventTypes.h new file mode 100644 index 0000000..8dfe8be --- /dev/null +++ b/include/views/SkSystemEventTypes.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkSystemEventTypes_DEFINED +#define SkSystemEventTypes_DEFINED + +/* + The goal of these strings is two-fold: + 1) make funny strings (containing at least one char < 32) to avoid colliding with "user" strings + 2) keep them <= 4 bytes, so we can avoid an allocation in SkEvent::setType() +*/ +#define SK_EventType_Delay "\xd" "lay" +#define SK_EventType_Inval "nv" "\xa" "l" +#define SK_EventType_Key "key" "\x1" +#define SK_EventType_OnEnd "on" "\xe" "n" +#define SK_EventType_Unichar "\xc" "har" +#define SK_EventType_KeyUp "key" "\xf" + +#endif diff --git a/include/views/SkTouchGesture.h b/include/views/SkTouchGesture.h new file mode 100644 index 0000000..79d4e28 --- /dev/null +++ b/include/views/SkTouchGesture.h @@ -0,0 +1,72 @@ +#ifndef SkTouchGesture_DEFINED +#define SkTouchGesture_DEFINED + +#include "SkTDArray.h" +#include "SkMatrix.h" + +struct SkFlingState { + SkFlingState() : fActive(false) {} + + bool isActive() const { return fActive; } + void stop() { fActive = false; } + + void reset(float sx, float sy); + bool evaluateMatrix(SkMatrix* matrix); + +private: + SkPoint fDirection; + SkScalar fSpeed0; + double fTime0; + bool fActive; +}; + +class SkTouchGesture { +public: + SkTouchGesture(); + ~SkTouchGesture(); + + void touchBegin(void* owner, float x, float y); + void touchMoved(void* owner, float x, float y); + void touchEnd(void* owner); + void reset(); + + bool isActive() { return fFlinger.isActive(); } + void stop() { fFlinger.stop(); } + + const SkMatrix& localM(); + const SkMatrix& globalM() const { return fGlobalM; } + +private: + enum State { + kEmpty_State, + kTranslate_State, + kZoom_State, + }; + + struct Rec { + void* fOwner; + float fStartX, fStartY; + float fPrevX, fPrevY; + float fLastX, fLastY; + SkMSec fPrevT, fLastT; + }; + SkTDArray<Rec> fTouches; + + State fState; + SkMatrix fLocalM, fGlobalM; + SkFlingState fFlinger; + SkMSec fLastUpT; + SkPoint fLastUpP; + + + void flushLocalM(); + int findRec(void* owner) const; + void appendNewRec(void* owner, float x, float y); + float computePinch(const Rec&, const Rec&); + float limitTotalZoom(float scale) const; + bool handleDblTap(float, float); +}; + +#endif + + diff --git a/include/views/SkView.h b/include/views/SkView.h new file mode 100644 index 0000000..d3633db --- /dev/null +++ b/include/views/SkView.h @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkView_DEFINED +#define SkView_DEFINED + +#include "SkEventSink.h" +#include "SkRect.h" +#include "SkDOM.h" +#include "SkTDict.h" + +class SkCanvas; +class SkLayerView; + +/** \class SkView + + SkView is the base class for screen management. All widgets and controls inherit + from SkView. +*/ +class SkView : public SkEventSink { +public: + enum Flag_Shift { + kVisible_Shift, + kEnabled_Shift, + kFocusable_Shift, + kFlexH_Shift, + kFlexV_Shift, + kNoClip_Shift, + + kFlagShiftCount + }; + enum Flag_Mask { + kVisible_Mask = 1 << kVisible_Shift, //!< set if the view is visible + kEnabled_Mask = 1 << kEnabled_Shift, //!< set if the view is enabled + kFocusable_Mask = 1 << kFocusable_Shift, //!< set if the view can receive focus + kFlexH_Mask = 1 << kFlexH_Shift, //!< set if the view's width is stretchable + kFlexV_Mask = 1 << kFlexV_Shift, //!< set if the view's height is stretchable + kNoClip_Mask = 1 << kNoClip_Shift, //!< set if the view is not clipped to its bounds + + kAllFlagMasks = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount) + }; + + SkView(uint32_t flags = 0); + virtual ~SkView(); + + /** Return the flags associated with the view + */ + uint32_t getFlags() const { return fFlags; } + /** Set the flags associated with the view + */ + void setFlags(uint32_t flags); + + /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags + */ + int isVisible() const { return fFlags & kVisible_Mask; } + int isEnabled() const { return fFlags & kEnabled_Mask; } + int isFocusable() const { return fFlags & kFocusable_Mask; } + int isClipToBounds() const { return !(fFlags & kNoClip_Mask); } + /** Helper to set/clear the view's kVisible_Mask flag */ + void setVisibleP(bool); + void setEnabledP(bool); + void setFocusableP(bool); + void setClipToBounds(bool); + + /** Return the view's width */ + SkScalar width() const { return fWidth; } + /** Return the view's height */ + SkScalar height() const { return fHeight; } + /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */ + void setSize(SkScalar width, SkScalar height); + void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); } + void setWidth(SkScalar width) { this->setSize(width, fHeight); } + void setHeight(SkScalar height) { this->setSize(fWidth, height); } + /** Return a rectangle set to [0, 0, width, height] */ + void getLocalBounds(SkRect* bounds) const; + + /** Return the view's left edge */ + SkScalar locX() const { return fLoc.fX; } + /** Return the view's top edge */ + SkScalar locY() const { return fLoc.fY; } + /** Set the view's left and top edge. This does not affect the view's size */ + void setLoc(SkScalar x, SkScalar y); + void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); } + void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); } + void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); } + /** Offset (move) the view by the specified dx and dy. This does not affect the view's size */ + void offset(SkScalar dx, SkScalar dy); + + /** Call this to have the view draw into the specified canvas. */ + virtual void draw(SkCanvas* canvas); + + /** Call this to invalidate part of all of a view, requesting that the view's + draw method be called. The rectangle parameter specifies the part of the view + that should be redrawn. If it is null, it specifies the entire view bounds. + */ + void inval(SkRect* rectOrNull); + + // Focus management + + SkView* getFocusView() const; + bool hasFocus() const; + + enum FocusDirection { + kNext_FocusDirection, + kPrev_FocusDirection, + + kFocusDirectionCount + }; + bool acceptFocus(); + SkView* moveFocus(FocusDirection); + + // Click handling + + class Click { + public: + Click(SkView* target); + virtual ~Click(); + + const char* getType() const { return fType; } + bool isType(const char type[]) const; + void setType(const char type[]); // does NOT make a copy of the string + void copyType(const char type[]); // makes a copy of the string + + enum State { + kDown_State, + kMoved_State, + kUp_State + }; + SkPoint fOrig, fPrev, fCurr; + SkIPoint fIOrig, fIPrev, fICurr; + State fState; + private: + SkEventSinkID fTargetID; + char* fType; + bool fWeOwnTheType; + + void resetType(); + + friend class SkView; + }; + Click* findClickHandler(SkScalar x, SkScalar y); + + static void DoClickDown(Click*, int x, int y); + static void DoClickMoved(Click*, int x, int y); + static void DoClickUp(Click*, int x, int y); + + /** Send the event to the view's parent, and its parent etc. until one of them + returns true from its onEvent call. This view is returned. If no parent handles + the event, null is returned. + */ + SkView* sendEventToParents(const SkEvent&); + /** Send the query to the view's parent, and its parent etc. until one of them + returns true from its onQuery call. This view is returned. If no parent handles + the query, null is returned. + */ + SkView* sendQueryToParents(SkEvent*); + + /** Depricated helper function. Just call event->post(sinkID, delay); + */ + bool postEvent(SkEvent* evt, SkEventSinkID sinkID, SkMSec delay) { return evt->post(sinkID, delay); } + + // View hierarchy management + + /** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */ + SkView* getParent() const { return fParent; } + SkView* attachChildToFront(SkView* child); + /** Attach the child view to this view, and increment the child's reference count. The child view is added + such that it will be drawn before all other child views. + The child view parameter is returned. + */ + SkView* attachChildToBack(SkView* child); + /** If the view has a parent, detach the view from its parent and decrement the view's reference count. + If the parent was the only owner of the view, this will cause the view to be deleted. + */ + void detachFromParent(); + /** Attach the child view to this view, and increment the child's reference count. The child view is added + such that it will be drawn after all other child views. + The child view parameter is returned. + */ + /** Detach all child views from this view. */ + void detachAllChildren(); + + /** Convert the specified point from global coordinates into view-local coordinates + */ + void globalToLocal(SkPoint* pt) const { if (pt) this->globalToLocal(pt->fX, pt->fY, pt); } + /** Convert the specified x,y from global coordinates into view-local coordinates, returning + the answer in the local parameter. + */ + void globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const; + + /** \class F2BIter + + Iterator that will return each of this view's children, in + front-to-back order (the order used for clicking). The first + call to next() returns the front-most child view. When + next() returns null, there are no more child views. + */ + class F2BIter { + public: + F2BIter(const SkView* parent); + SkView* next(); + private: + SkView* fFirstChild, *fChild; + }; + + /** \class B2FIter + + Iterator that will return each of this view's children, in + back-to-front order (the order they are drawn). The first + call to next() returns the back-most child view. When + next() returns null, there are no more child views. + */ + class B2FIter { + public: + B2FIter(const SkView* parent); + SkView* next(); + private: + SkView* fFirstChild, *fChild; + }; + + /** \class Artist + + Install a subclass of this in a view (calling setArtist()), and then the + default implementation of that view's onDraw() will invoke this object + automatically. + */ + class Artist : public SkRefCnt { + public: + void draw(SkView*, SkCanvas*); + void inflate(const SkDOM&, const SkDOM::Node*); + protected: + virtual void onDraw(SkView*, SkCanvas*) = 0; + virtual void onInflate(const SkDOM&, const SkDOM::Node*); + }; + /** Return the artist attached to this view (or null). The artist's reference + count is not affected. + */ + Artist* getArtist() const; + /** Attach the specified artist (or null) to the view, replacing any existing + artist. If the new artist is not null, its reference count is incremented. + The artist parameter is returned. + */ + Artist* setArtist(Artist* artist); + + /** \class Layout + + Install a subclass of this in a view (calling setLayout()), and then the + default implementation of that view's onLayoutChildren() will invoke + this object automatically. + */ + class Layout : public SkRefCnt { + public: + void layoutChildren(SkView* parent); + void inflate(const SkDOM&, const SkDOM::Node*); + protected: + virtual void onLayoutChildren(SkView* parent) = 0; + virtual void onInflate(const SkDOM&, const SkDOM::Node*); + }; + + /** Return the layout attached to this view (or null). The layout's reference + count is not affected. + */ + Layout* getLayout() const; + /** Attach the specified layout (or null) to the view, replacing any existing + layout. If the new layout is not null, its reference count is incremented. + The layout parameter is returned. + */ + Layout* setLayout(Layout*, bool invokeLayoutNow = true); + /** If a layout is attached to this view, call its layoutChildren() method + */ + void invokeLayout(); + + /** Call this to initialize this view based on the specified XML node + */ + void inflate(const SkDOM& dom, const SkDOM::Node* node); + /** After a view hierarchy is inflated, this may be called with a dictionary + containing pairs of <name, view*>, where the name string was the view's + "id" attribute when it was inflated. + + This will call the virtual onPostInflate for this view, and the recursively + call postInflate on all of the view's children. + */ + void postInflate(const SkTDict<SkView*>& ids); + + SkDEBUGCODE(void dump(bool recurse) const;) + +protected: + /** Override this to draw inside the view. Be sure to call the inherited version too */ + virtual void onDraw(SkCanvas*); + /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */ + virtual void onSizeChange(); + /** Override this if you want to handle an inval request from this view or one of its children. + Tyically this is only overridden by the by the "window". If your subclass does handle the + request, return true so the request will not continue to propogate to the parent. + */ + virtual bool handleInval(const SkRect*); + //! called once before all of the children are drawn (or clipped/translated) + virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; } + //! called once after all of the children are drawn (or clipped/translated) + virtual void afterChildren(SkCanvas* orig) {} + + //! called right before this child's onDraw is called + virtual void beforeChild(SkView* child, SkCanvas* canvas) {} + //! called right after this child's onDraw is called + virtual void afterChild(SkView* child, SkCanvas* canvas) {} + + /** Override this if you might handle the click + */ + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + /** Override this to decide if your children are targets for a click. + The default returns true, in which case your children views will be + candidates for onFindClickHandler. Returning false wil skip the children + and just call your onFindClickHandler. + */ + virtual bool onSendClickToChildren(SkScalar x, SkScalar y); + /** Override this to track clicks, returning true as long as you want to track + the pen/mouse. + */ + virtual bool onClick(Click*); + /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */ + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + /** Override this if you want to perform post initialization work based on the ID dictionary built + during XML parsing. Be sure to call the inherited version too. + */ + virtual void onPostInflate(const SkTDict<SkView*>&); + +public: + // default action is to inval the view + virtual void onFocusChange(bool gainFocusP); +protected: + + // override these if you're acting as a layer/host + virtual bool onGetFocusView(SkView**) const { return false; } + virtual bool onSetFocusView(SkView*) { return false; } + +private: + SkScalar fWidth, fHeight; + SkPoint fLoc; + SkView* fParent; + SkView* fFirstChild; + SkView* fNextSibling; + SkView* fPrevSibling; + uint8_t fFlags; + uint8_t fContainsFocus; + + friend class B2FIter; + friend class F2BIter; + + friend class SkLayerView; + + bool setFocusView(SkView* fvOrNull); + SkView* acceptFocus(FocusDirection); + void detachFromParent_NoLayout(); +}; + +#endif + diff --git a/include/views/SkViewInflate.h b/include/views/SkViewInflate.h new file mode 100644 index 0000000..3ec65a6 --- /dev/null +++ b/include/views/SkViewInflate.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkViewInflate_DEFINED +#define SkViewInflate_DEFINED + +#include "SkDOM.h" +#include "SkTDict.h" +#include "SkEvent.h" + +class SkView; + +class SkViewInflate { +public: + SkViewInflate(); + virtual ~SkViewInflate(); + + /** Return the tree of inflated views. If root is null, create the root element + as a view, otherwise assume root is that view, and just "inflate" it. + + Returns null if the tree cannot be built. + */ + SkView* inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root = NULL); + SkView* inflate(const char xml[], size_t len, SkView* root = NULL); + + /** Given an id attribute value, return the corresponding view, or null + if no match is found. + */ + SkView* findViewByID(const char id[]) const; + + SkDEBUGCODE(void dump() const;) + +protected: + /* Override this in your subclass to handle instantiating views + Call the inherited version for nodes you don't recognize. + + Do not call "inflate" on the view, just return it. This will + get called automatically after createView returns. + */ + virtual SkView* createView(const SkDOM& dom, const SkDOM::Node* node); + /** Base implementation calls view->inflate(dom, node). Subclasses may override this + to perform additional initializations to view, either before or after calling + the inherited version. + */ + virtual void inflateView(SkView* view, const SkDOM& dom, const SkDOM::Node* node); + +private: + enum { + kMinIDStrAlloc = 64 + }; + SkTDict<SkView*> fIDs; + + struct IDStr { + SkView* fView; + char* fStr; + }; + SkTDArray<IDStr> fListenTo, fBroadcastTo; + SkChunkAlloc fStrings; + + void addIDStr(SkTDArray<IDStr>* list, SkView*, const char* str); + + void rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent); +}; + +#endif + diff --git a/include/views/SkWidget.h b/include/views/SkWidget.h new file mode 100644 index 0000000..db85f01 --- /dev/null +++ b/include/views/SkWidget.h @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkWidget_DEFINED +#define SkWidget_DEFINED + +#include "SkView.h" +#include "SkBitmap.h" +#include "SkDOM.h" +#include "SkPaint.h" +#include "SkString.h" +#include "SkTDArray.h" + +////////////////////////////////////////////////////////////////////////////// + +class SkWidget : public SkView { +public: + SkWidget(uint32_t flags = 0) : SkView(flags | kFocusable_Mask | kEnabled_Mask) {} + + /** Call this to post the widget's event to its listeners */ + void postWidgetEvent(); + + static void Init(); + static void Term(); +protected: + // override to add slots to an event before posting + virtual void prepareWidgetEvent(SkEvent*); + virtual void onEnabledChange(); + + // <event ...> to initialize the event from XML + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + SkEvent fEvent; + typedef SkView INHERITED; +}; + +class SkHasLabelWidget : public SkWidget { +public: + SkHasLabelWidget(uint32_t flags = 0) : SkWidget(flags) {} + + size_t getLabel(SkString* label = NULL) const; + size_t getLabel(char lable[] = NULL) const; + void setLabel(const SkString&); + void setLabel(const char label[]); + void setLabel(const char label[], size_t len); + +protected: + // called when the label changes + virtual void onLabelChange(); + + // overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + SkString fLabel; + typedef SkWidget INHERITED; +}; + +class SkButtonWidget : public SkHasLabelWidget { +public: + SkButtonWidget(uint32_t flags = 0) : SkHasLabelWidget(flags), fState(kOff_State) {} + + enum State { + kOff_State, //!< XML: buttonState="off" + kOn_State, //!< XML: buttonState="on" + kUnknown_State //!< XML: buttonState="unknown" + }; + State getButtonState() const { return fState; } + void setButtonState(State); + +protected: + /** called when the label changes. default behavior is to inval the widget */ + virtual void onButtonStateChange(); + + // overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + State fState; + typedef SkHasLabelWidget INHERITED; +}; + +class SkPushButtonWidget : public SkButtonWidget { +public: + SkPushButtonWidget(uint32_t flags = 0) : SkButtonWidget(flags) {} + +protected: + virtual bool onEvent(const SkEvent&); + virtual void onDraw(SkCanvas*); + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + virtual bool onClick(Click* click); + +private: + typedef SkButtonWidget INHERITED; +}; + +class SkCheckBoxWidget : public SkButtonWidget { +public: + SkCheckBoxWidget(uint32_t flags = 0); + +protected: + virtual bool onEvent(const SkEvent&); + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + typedef SkButtonWidget INHERITED; +}; + +#include "SkTextBox.h" + +class SkStaticTextView : public SkView { +public: + SkStaticTextView(uint32_t flags = 0); + virtual ~SkStaticTextView(); + + enum Mode { + kFixedSize_Mode, + kAutoWidth_Mode, + kAutoHeight_Mode, + + kModeCount + }; + Mode getMode() const { return (Mode)fMode; } + void setMode(Mode); + + SkTextBox::SpacingAlign getSpacingAlign() const { return (SkTextBox::SpacingAlign)fSpacingAlign; } + void setSpacingAlign(SkTextBox::SpacingAlign); + + void getMargin(SkPoint* margin) const; + void setMargin(SkScalar dx, SkScalar dy); + + size_t getText(SkString* text = NULL) const; + size_t getText(char text[] = NULL) const; + void setText(const SkString&); + void setText(const char text[]); + void setText(const char text[], size_t len); + + void getPaint(SkPaint*) const; + void setPaint(const SkPaint&); + +protected: + // overrides + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + SkPoint fMargin; + SkString fText; + SkPaint fPaint; + uint8_t fMode; + uint8_t fSpacingAlign; + + void computeSize(); + + typedef SkView INHERITED; +}; + +class SkBitmapView : public SkView { +public: + SkBitmapView(uint32_t flags = 0); + virtual ~SkBitmapView(); + + bool getBitmap(SkBitmap*) const; + void setBitmap(const SkBitmap*, bool viewOwnsPixels); + bool loadBitmapFromFile(const char path[]); + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM&, const SkDOM::Node*); + +private: + SkBitmap fBitmap; + typedef SkView INHERITED; +}; + +///////////////////////////////////////////////////////////////////////////// + +class SkShader; +class SkInterpolator; + +class SkWidgetView : public SkView { +public: + SkWidgetView(uint32_t flags = 0); + virtual ~SkWidgetView(); + + static const char* GetEventType(); +}; + +class SkSliderView : public SkWidgetView { +public: + SkSliderView(uint32_t flags = 0); + + uint16_t getValue() const { return fValue; } + uint16_t getMax() const { return fMax; } + + void setMax(U16CPU max); + void setValue(U16CPU value); + +protected: + virtual void onDraw(SkCanvas*); + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + virtual bool onClick(Click*); + +private: + uint16_t fValue, fMax; + + typedef SkWidgetView INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +class SkHasLabelView : public SkView { +public: + void getLabel(SkString*) const; + void setLabel(const SkString&); + void setLabel(const char label[]); + +protected: + SkString fLabel; + + // called when the label changes + virtual void onLabelChange(); + + // overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); +}; + +class SkPushButtonView : public SkHasLabelView { +public: + SkPushButtonView(uint32_t flags = 0); + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); +}; + +class SkCheckBoxView : public SkHasLabelView { +public: + SkCheckBoxView(uint32_t flags = 0); + + enum State { + kOff_State, + kOn_State, + kMaybe_State + }; + State getState() const { return fState; } + void setState(State); + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + State fState; +}; + +class SkProgressView : public SkView { +public: + SkProgressView(uint32_t flags = 0); + virtual ~SkProgressView(); + + uint16_t getValue() const { return fValue; } + uint16_t getMax() const { return fMax; } + + void setMax(U16CPU max); + void setValue(U16CPU value); + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + uint16_t fValue, fMax; + SkShader* fOnShader, *fOffShader; + SkInterpolator* fInterp; + bool fDoInterp; + + typedef SkView INHERITED; +}; + +class SkTextView : public SkView { +public: + SkTextView(uint32_t flags = 0); + virtual ~SkTextView(); + + enum AnimaDir { + kNeutral_AnimDir, + kForward_AnimDir, + kBackward_AnimDir, + kAnimDirCount + }; + + void getText(SkString*) const; + void setText(const SkString&, AnimaDir dir = kNeutral_AnimDir); + void setText(const char text[], AnimaDir dir = kNeutral_AnimDir); + void setText(const char text[], size_t len, AnimaDir dir = kNeutral_AnimDir); + + void getMargin(SkPoint* margin) const; + void setMargin(const SkPoint&); + + SkPaint& paint() { return fPaint; } + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + SkString fText; + SkPaint fPaint; + SkPoint fMargin; + + class Interp; + Interp* fInterp; + bool fDoInterp; + // called by the other setText methods. This guy does not check for != + // before doing the assign, so the caller must check for us + void privSetText(const SkString&, AnimaDir dir); + + typedef SkView INHERITED; +}; + +////////////////////////////////////////////////////////// + +class SkEvent; + +class SkListSource : public SkEventSink { +public: + virtual int countRows() = 0; + virtual void getRow(int index, SkString* left, SkString* right) = 0; + virtual SkEvent* getEvent(int index); + + static SkListSource* CreateFromDir(const char path[], const char suffix[], + const char targetPrefix[]); + static SkListSource* CreateFromDOM(const SkDOM& dom, const SkDOM::Node* node); +}; + +class SkListView : public SkWidgetView { +public: + SkListView(uint32_t flags = 0); + virtual ~SkListView(); + + SkScalar getRowHeight() const { return fRowHeight; } + void setRowHeight(SkScalar); + + /** Return the index of the selected row, or -1 if none + */ + int getSelection() const { return fCurrIndex; } + /** Set the index of the selected row, or -1 for none + */ + void setSelection(int); + + void moveSelectionUp(); + void moveSelectionDown(); + + enum Attr { + kBG_Attr, + kNormalText_Attr, + kHiliteText_Attr, + kHiliteCell_Attr, + kAttrCount + }; + SkPaint& paint(Attr); + + SkListSource* getListSource() const { return fSource; } + SkListSource* setListSource(SkListSource*); + +#if 0 + enum Action { + kSelectionChange_Action, + kSelectionPicked_Action, + kActionCount + }; + /** If event is not null, it is retained by the view, and a copy + of the event will be posted to its listeners when the specified + action occurs. If event is null, then no event will be posted for + the specified action. + */ + void setActionEvent(Action, SkEvent* event); +#endif + +protected: + virtual void onDraw(SkCanvas*); + virtual void onSizeChange(); + virtual bool onEvent(const SkEvent&); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + SkPaint fPaint[kAttrCount]; + SkListSource* fSource; + SkScalar fRowHeight; + int fCurrIndex; // logical index + int fScrollIndex; // logical index of top-most visible row + int fVisibleRowCount; + SkString* fStrCache; + + void dirtyStrCache(); + void ensureStrCache(int visibleCount); + + int logicalToVisualIndex(int index) const { return index - fScrollIndex; } + void invalSelection(); + bool getRowRect(int index, SkRect*) const; + void ensureSelectionIsVisible(); + + typedef SkWidgetView INHERITED; +}; + +////////////////////////////////////////////////////////// + +class SkGridView : public SkWidgetView { +public: + SkGridView(uint32_t flags = 0); + virtual ~SkGridView(); + + void getCellSize(SkPoint*) const; + void setCellSize(SkScalar x, SkScalar y); + + /** Return the index of the selected item, or -1 if none + */ + int getSelection() const { return fCurrIndex; } + /** Set the index of the selected row, or -1 for none + */ + void setSelection(int); + + void moveSelectionUp(); + void moveSelectionDown(); + + enum Attr { + kBG_Attr, + kHiliteCell_Attr, + kAttrCount + }; + SkPaint& paint(Attr); + + SkListSource* getListSource() const { return fSource; } + SkListSource* setListSource(SkListSource*); + +protected: + virtual void onDraw(SkCanvas*); + virtual void onSizeChange(); + virtual bool onEvent(const SkEvent&); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + SkView* fScrollBar; + SkPaint fPaint[kAttrCount]; + SkListSource* fSource; + int fCurrIndex; // logical index + + SkPoint fCellSize; + SkIPoint fVisibleCount; + + int logicalToVisualIndex(int index) const { return index; } + void invalSelection(); + bool getCellRect(int index, SkRect*) const; + void ensureSelectionIsVisible(); + + typedef SkWidgetView INHERITED; +}; + +#endif + diff --git a/include/views/SkWidgetViews.h b/include/views/SkWidgetViews.h new file mode 100644 index 0000000..9b3a816 --- /dev/null +++ b/include/views/SkWidgetViews.h @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkWidgetViews_DEFINED +#define SkWidgetViews_DEFINED + +#include "SkView.h" + + +enum SkWidgetEnum { + kBorder_WidgetEnum, //!< <sk-border> + kButton_WidgetEnum, //!< <sk-button> + kImage_WidgetEnum, //!< <sk-image> + kList_WidgetEnum, //!< <sk-list> + kProgress_WidgetEnum, //!< <sk-progress> + kScroll_WidgetEnum, //!< <sk-scroll> + kText_WidgetEnum, //!< <sk-text> + + kWidgetEnumCount +}; + +//determines which skin to use +enum SkinEnum { + kBorder_SkinEnum, + kButton_SkinEnum, + kProgress_SkinEnum, + kScroll_SkinEnum, + kStaticText_SkinEnum, + + kSkinEnumCount +}; + +#include "SkAnimator.h" +//used for inflates +const char* get_skin_enum_path(SkinEnum se); +void init_skin_anim(const char path[], SkAnimator* anim); +void init_skin_anim(SkinEnum se, SkAnimator* anim); +void init_skin_paint(SkinEnum se, SkPaint* paint); +void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint); + +/** Given an enum value, return an instance of the specified widget. + If the enum is out of range, returns null +*/ +SkView* SkWidgetFactory(SkWidgetEnum); +/** Given the inflate/element name of a widget, return an instance of + the specified widget, or null if name does not match any known + widget type. +*/ +SkView* SkWidgetFactory(const char name[]); + +//////////////////////////////////////////////////////////////////////////////////////////////// + +class SkWidgetView : public SkView { +public: + SkWidgetView(); + + const char* getLabel() const; + void getLabel(SkString* label) const; + + void setLabel(const char[]); + void setLabel(const char[], size_t len); + void setLabel(const SkString&); + + SkEvent& event() { return fEvent; } + const SkEvent& event() const { return fEvent; } + + /** Returns true if the widget can post its event to its listeners. + */ + bool postWidgetEvent(); + + /** Returns the sinkID of the widgetview that posted the event, or 0 + */ + static SkEventSinkID GetWidgetEventSinkID(const SkEvent&); + +protected: + /** called when the label changes. override in subclasses. default action invals the view's bounds. + called with the old and new labels, before the label has actually changed. + */ + virtual void onLabelChange(const char oldLabel[], const char newLabel[]); + /** called before posting the event to our listeners. Override to add slots to the event + before posting. Return true to proceed with posting, or false to not post the event to any + listener. Note: the event passed in may not be the same as calling this->event(). + Be sure to call your INHERITED method as well, so that all classes in the hierarchy get a shot + at modifying the event (and possibly returning false to abort). + */ + virtual bool onPrepareWidgetEvent(SkEvent* evt); + + // overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + SkString fLabel; + SkEvent fEvent; + + typedef SkView INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +class SkButtonView : public SkWidgetView { +public: + // inflate: "sk-button" + +protected: + // overrides + virtual bool onEvent(const SkEvent&); +private: + typedef SkWidgetView INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +class SkCheckButtonView : public SkWidgetView { +public: + SkCheckButtonView(); + + // inflate: "sk-checkbutton" + + enum CheckState { + kOff_CheckState, //!< inflate: check-state="off" + kOn_CheckState, //!< inflate: check-state="on" + kUnknown_CheckState //!< inflate: check-state="unknown" + }; + CheckState getCheckState() const { return (CheckState)fCheckState; } + void setCheckState(CheckState); + + /** use this to extract the CheckState from an event (i.e. one that as posted + by a SkCheckButtonView). Returns true if the proper slot was present in the event, + and sets state to that value. If no proper slot is found, returns false and does not + modify state. + */ + static bool GetWidgetEventCheckState(const SkEvent&, CheckState* state); + +protected: + // called when the check-state is about to change, but before it actually has + virtual void onCheckStateChange(CheckState oldState, CheckState newState); + + // overrides + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + virtual bool onPrepareWidgetEvent(SkEvent* evt); + +private: + uint8_t fCheckState; + + typedef SkWidgetView INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// +#include "SkTextBox.h" + +class SkStaticTextView : public SkView { +public: + SkStaticTextView(); + virtual ~SkStaticTextView(); + + enum Mode { + kFixedSize_Mode, + kAutoWidth_Mode, + kAutoHeight_Mode, + + kModeCount + }; + Mode getMode() const { return (Mode)fMode; } + void setMode(Mode); + + SkTextBox::SpacingAlign getSpacingAlign() const { return (SkTextBox::SpacingAlign)fSpacingAlign; } + void setSpacingAlign(SkTextBox::SpacingAlign); + + void getMargin(SkPoint* margin) const; + void setMargin(SkScalar dx, SkScalar dy); + + size_t getText(SkString* text = NULL) const; + size_t getText(char text[] = NULL) const; + void setText(const SkString&); + void setText(const char text[]); + void setText(const char text[], size_t len); + + void getPaint(SkPaint*) const; + void setPaint(const SkPaint&); + +protected: + // overrides + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); + +private: + SkPoint fMargin; + SkString fText; + SkPaint fPaint; + uint8_t fMode; + uint8_t fSpacingAlign; + + void computeSize(); + + typedef SkView INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +class SkAnimator; +class SkListSource; +class SkScrollBarView; + +class SkListView : public SkWidgetView { +public: + SkListView(); + virtual ~SkListView(); + + bool hasScrollBar() const { return fScrollBar != NULL; } + void setHasScrollBar(bool); + + /** Return the number of visible rows + */ + int getVisibleRowCount() const { return fVisibleRowCount; } + /** Return the index of the selected row, or -1 if none + */ + int getSelection() const { return fCurrIndex; } + /** Set the index of the selected row, or -1 for none + */ + void setSelection(int); + /** If possible, move the selection up and return true, + else do nothing and return false + If nothing is selected, select the last item (unless there are no items). + */ + bool moveSelectionUp(); + /** If possible, move the selection down and return true, + else do nothing and return false. + If nothing is selected, select the first item (unless there are no items). + */ + bool moveSelectionDown(); + + SkListSource* getListSource() const { return fSource; } + SkListSource* setListSource(SkListSource*); + + /** Call this in your event handler. If the specified event is from a SkListView, + then it returns the index of the selected item in this list, otherwise it + returns -1 + */ + static int GetWidgetEventListIndex(const SkEvent&); + +protected: + // overrides + virtual void onDraw(SkCanvas*); + virtual void onSizeChange(); + virtual bool onEvent(const SkEvent&); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + virtual bool onPrepareWidgetEvent(SkEvent*); + +private: + enum DirtyFlags { + kAnimCount_DirtyFlag = 0x01, + kAnimContent_DirtyFlag = 0x02 + }; + void dirtyCache(unsigned dirtyFlags); + bool ensureCache(); + + int logicalToVisualIndex(int index) const { return index - fScrollIndex; } + void invalSelection(); + SkScalar getContentWidth() const; + bool getRowRect(int index, SkRect*) const; + void ensureSelectionIsVisible(); + void ensureVisibleRowCount(); + + struct BindingRec; + + enum Heights { + kNormal_Height, + kSelected_Height + }; + SkListSource* fSource; + SkScrollBarView* fScrollBar; + SkAnimator* fAnims; + BindingRec* fBindings; + SkString fSkinName; + SkScalar fHeights[2]; + int16_t fScrollIndex, fCurrIndex; + uint16_t fVisibleRowCount, fBindingCount; + SkBool8 fAnimContentDirty; + SkBool8 fAnimFocusDirty; + + typedef SkWidgetView INHERITED; +}; + +class SkListSource : public SkRefCnt { +public: + virtual int countFields(); + virtual void getFieldName(int index, SkString* field); + /** Return the index of the named field, or -1 if not found */ + virtual int findFieldIndex(const char field[]); + + virtual int countRecords(); + virtual void getRecord(int rowIndex, int fieldIndex, SkString* data); + + virtual bool prepareWidgetEvent(SkEvent*, int rowIndex); + + static SkListSource* Factory(const char name[]); +}; + +#endif diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h new file mode 100644 index 0000000..fd4ce0a --- /dev/null +++ b/include/views/SkWindow.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkWindow_DEFINED +#define SkWindow_DEFINED + +#include "SkView.h" +#include "SkBitmap.h" +#include "SkMatrix.h" +#include "SkRegion.h" +#include "SkEvent.h" +#include "SkKey.h" +#include "SkTDArray.h" + +#ifdef SK_BUILD_FOR_WINCEx + #define SHOW_FPS +#endif +//#define USE_GX_SCREEN + +class SkCanvas; + +class SkOSMenu; + +class SkWindow : public SkView { +public: + SkWindow(); + virtual ~SkWindow(); + + const SkBitmap& getBitmap() const { return fBitmap; } + + void setConfig(SkBitmap::Config); + void resize(int width, int height, SkBitmap::Config config = SkBitmap::kNo_Config); + void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b); + void eraseRGB(U8CPU r, U8CPU g, U8CPU b); + + bool isDirty() const { return !fDirtyRgn.isEmpty(); } + bool update(SkIRect* updateArea, SkCanvas* = NULL); + // does not call through to onHandleInval(), but does force the fDirtyRgn + // to be wide open. Call before update() to ensure we redraw everything. + void forceInvalAll(); + // return the bounds of the dirty/inval rgn, or [0,0,0,0] if none + const SkIRect& getDirtyBounds() const { return fDirtyRgn.getBounds(); } + + bool handleClick(int x, int y, Click::State); + bool handleChar(SkUnichar); + bool handleKey(SkKey); + bool handleKeyUp(SkKey); + bool handleMenu(uint32_t os_cmd); + + void addMenu(SkOSMenu*); + + const char* getTitle() const { return fTitle.c_str(); } + void setTitle(const char title[]); + + const SkMatrix& getMatrix() const { return fMatrix; } + void setMatrix(const SkMatrix&); + void preConcat(const SkMatrix&); + void postConcat(const SkMatrix&); + +protected: + virtual bool onEvent(const SkEvent&); + virtual bool onDispatchClick(int x, int y, Click::State); + // called if part of our bitmap is invalidated + virtual void onHandleInval(const SkIRect&); + virtual bool onHandleChar(SkUnichar); + virtual bool onHandleKey(SkKey); + virtual bool onHandleKeyUp(SkKey); + virtual void onAddMenu(const SkOSMenu*) {} + virtual void onSetTitle(const char title[]) {} + + // overrides from SkView + virtual bool handleInval(const SkRect*); + virtual bool onGetFocusView(SkView** focus) const; + virtual bool onSetFocusView(SkView* focus); + +private: + SkBitmap::Config fConfig; + SkBitmap fBitmap; + SkRegion fDirtyRgn; + Click* fClick; // to track clicks + + SkTDArray<SkOSMenu*> fMenus; + + SkView* fFocusView; + bool fWaitingOnInval; + + SkString fTitle; + SkMatrix fMatrix; + + typedef SkView INHERITED; +}; + +/////////////////////////////////////////////////////////// + +#ifdef SK_USE_WXWIDGETS + #include "SkOSWindow_wxwidgets.h" +#elif defined(SK_BUILD_FOR_MAC) + #include "SkOSWindow_Mac.h" +#elif defined(SK_BUILD_FOR_WIN) + #include "SkOSWindow_Win.h" +#elif defined(ANDROID) + #include "SkOSWindow_Android.h" +#elif defined(SK_BUILD_FOR_UNIX) + #include "SkOSWindow_Unix.h" +#elif defined(SK_BUILD_FOR_SDL) + #include "SkOSWindow_SDL.h" +#elif defined(SK_BUILD_FOR_IOS) + #include "SkOSWindow_iOS.h" +#endif + +#endif + |