| Index: include/core/SkShader.h
|
| diff --git a/include/core/SkShader.h b/include/core/SkShader.h
|
| index 108c6b0829b22ddb764a1aba14417b52f0a4f781..6a25f53101ce5819ef0554f676965bf3401e4358 100644
|
| --- a/include/core/SkShader.h
|
| +++ b/include/core/SkShader.h
|
| @@ -128,59 +128,130 @@ public:
|
| */
|
| virtual bool isOpaque() const { return false; }
|
|
|
| + // Moved to public so it could on a Context object. May not be the right place for it.
|
| + enum MatrixClass {
|
| + kLinear_MatrixClass, // no perspective
|
| + kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each scanline
|
| + kPerspective_MatrixClass // slow perspective, need to mappoints each pixel
|
| + };
|
| +
|
| /**
|
| - * Return the alpha associated with the data returned by shadeSpan16(). If
|
| - * kHasSpan16_Flag is not set, this value is meaningless.
|
| + * Total number of bytes needed to store subclass specific Context information.
|
| + * Each class will override this by including the macro DEFINE_CONTEXT_RETRIEVAL_FUNCTIONS()
|
| + * in its private section, and defining getMySpaceNeededForContext(), which returns the
|
| + * number of bytes required by that specific subclass (not including its parents).
|
| + */
|
| + virtual size_t getTotalSpaceNeededForContext() const { return 0; }
|
| +
|
| + /**
|
| + * Called to get a pointer to subclass-specific information.
|
| */
|
| - virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
|
| + virtual void* getMyContext(Context* c) const = 0;
|
| +
|
| + class Context : public SkNoncopyable {
|
| + public:
|
| + Context(const SkMatrix& totalInverse, uint8_t paintAlpha,
|
| + SkBitmap::Config deviceConfig);
|
| +
|
| + uint8_t getPaintAlpha() const { return fPaintAlpha; }
|
| + SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
|
| + const SkMatrix& getTotalInverse() const { return fTotalInverse; }
|
| + MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
|
| +
|
| + /**
|
| + * Should not be called directly. Instead, the subclass should call getMyContext.
|
| + */
|
| + void* getExtraStorage() {
|
| + SkAssert(fStorageAllocated);
|
| + return fExtraStorage;
|
| + }
|
| +
|
| + void reset(const SkShader& shader) {
|
| + // This can only be called once
|
| + SkAssert(!fStorageAllocated);
|
| + fExtraStorage = fStorage.reset(shader.getTotalSpaceNeededForContext());
|
| + // What should we do if this fails?
|
| + SkASSERT(fExtraStorage != NULL);
|
| + fStorageAllocated = true;
|
| + }
|
| +
|
| + private:
|
| + SkMatrix fTotalInverse;
|
| + uint8_t fPaintAlpha;
|
| + uint8_t fDeviceConfig;
|
| + uint8_t fTotalInverseClass;
|
| + // This size is arbitrary, for now, but probably should be related to the size of the
|
| + // subclasses needed.
|
| + SkAutoSMalloc<1024> fStorage;
|
| + // Should be debugcode
|
| + bool fStorageAllocated;
|
| + // Space for the subclasses' Context information. Will pint to fStorage.
|
| + void* fExtraStorage;
|
| + };
|
|
|
| /**
|
| * Called once before drawing, with the current paint and device matrix.
|
| - * Return true if your shader supports these parameters, or false if not.
|
| - * If false is returned, nothing will be drawn. If true is returned, then
|
| + * Return a new Context object if your shader supports these parameters,
|
| + * or NULL if not. If NULL is returned, nothing will be drawn. On success,
|
| * a balancing call to endContext() will be made before the next call to
|
| * setContext.
|
| - *
|
| - * Subclasses should be sure to call their INHERITED::setContext() if they
|
| - * override this method.
|
| */
|
| - virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
|
| - const SkMatrix& matrix);
|
|
|
| + Context* setContext(const SkBitmap& device, const SkPaint& paint,
|
| + const SkMatrix& matrix);
|
| +
|
| + /**
|
| + * Subclasses should be sure to call their INHERITED::onSetContext() if they
|
| + * override this method.
|
| + */
|
| + virtual bool onSetContext(Context* context, const SkBitmap& device,
|
| + const SkPaint& paint,
|
| + const SkMatrix& matrix) { return true; }
|
| /**
|
| * Assuming setContext returned true, endContext() will be called when
|
| * the draw using the shader has completed. It is an error for setContext
|
| * to be called twice w/o an intervening call to endContext().
|
| *
|
| + * This method will delete the Context object.
|
| + *
|
| * Subclasses should be sure to call their INHERITED::endContext() if they
|
| - * override this method.
|
| + * override this method, after deleting their subclass-specific info.
|
| */
|
| - virtual void endContext();
|
| + virtual void endContext(Context*);
|
|
|
| SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); })
|
|
|
| /**
|
| + * Return the alpha associated with the data returned by shadeSpan16(). If
|
| + * kHasSpan16_Flag is not set, this value is meaningless.
|
| + */
|
| + virtual uint8_t getSpan16Alpha(Context* c) const { return c->getPaintAlpha(); }
|
| +
|
| + /**
|
| * Called for each span of the object being drawn. Your subclass should
|
| * set the appropriate colors (with premultiplied alpha) that correspond
|
| * to the specified device coordinates.
|
| */
|
| - virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
|
| + // FIXME: It may make more sense for Context to be a const ref? (Same for others)
|
| + virtual void shadeSpan(Context* c, int x, int y, SkPMColor[], int count) = 0;
|
|
|
| + // Used by SkBlitter_ARGB32.cpp
|
| typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
|
| + // Will need to pass a Context to this as well.
|
| virtual ShadeProc asAShadeProc(void** ctx);
|
|
|
| /**
|
| * Called only for 16bit devices when getFlags() returns
|
| * kOpaqueAlphaFlag | kHasSpan16_Flag
|
| */
|
| - virtual void shadeSpan16(int x, int y, uint16_t[], int count);
|
| + virtual void shadeSpan16(Context* c, int x, int y, uint16_t[], int count);
|
|
|
| /**
|
| * Similar to shadeSpan, but only returns the alpha-channel for a span.
|
| * The default implementation calls shadeSpan() and then extracts the alpha
|
| * values from the returned colors.
|
| */
|
| - virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
|
| + virtual void shadeSpanAlpha(Context* c, int x, int y, uint8_t alpha[], int count);
|
|
|
| /**
|
| * Helper function that returns true if this shader's shadeSpan16() method
|
| @@ -350,27 +421,13 @@ public:
|
| SK_DEFINE_FLATTENABLE_TYPE(SkShader)
|
|
|
| protected:
|
| - enum MatrixClass {
|
| - kLinear_MatrixClass, // no perspective
|
| - kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each scanline
|
| - kPerspective_MatrixClass // slow perspective, need to mappoints each pixel
|
| - };
|
| static MatrixClass ComputeMatrixClass(const SkMatrix&);
|
|
|
| - // These can be called by your subclass after setContext() has been called
|
| - uint8_t getPaintAlpha() const { return fPaintAlpha; }
|
| - SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
|
| - const SkMatrix& getTotalInverse() const { return fTotalInverse; }
|
| - MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
|
| -
|
| SkShader(SkReadBuffer& );
|
| virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
| private:
|
| + // FIXME: Move onto SkPaint.
|
| SkMatrix fLocalMatrix;
|
| - SkMatrix fTotalInverse;
|
| - uint8_t fPaintAlpha;
|
| - uint8_t fDeviceConfig;
|
| - uint8_t fTotalInverseClass;
|
| SkDEBUGCODE(SkBool8 fInSetContext;)
|
|
|
| static SkShader* CreateBitmapShader(const SkBitmap& src,
|
| @@ -380,4 +437,30 @@ private:
|
| typedef SkFlattenable INHERITED;
|
| };
|
|
|
| +/**
|
| + * Each SkShader subclass must include the following macro in its private
|
| + * section (defined below):
|
| + *
|
| + * DEFINE_CONTEXT_RETRIEVAL_FUNCTIONS()
|
| + *
|
| + * It defines functions for accessing the particular subclass's specific
|
| + * information from the Context. The subclass must also implement the
|
| + * following function:
|
| + *
|
| + * size_t getMySpaceNeededForContext() const;
|
| + *
|
| + * This function will return the number of bytes required to store that
|
| + * subclasses Context information.
|
| + */
|
| +
|
| +#define DEFINE_CONTEXT_RETRIEVAL_FUNCTIONS() \
|
| + virtual size_t getTotalSpaceNeededForContext() const SK_OVERRIDE { \
|
| + return this->INHERITED::getTotalSpaceNeededForContext() \
|
| + + this->getMySpaceNeededForContext(); \
|
| + } \
|
| + virtual void* getMyContext(Context* c) const SK_OVERRIDE { \
|
| + return c->getExtraStorage() + this->INHERITED::getTotalSpaceNeededForContext(); \
|
| + }
|
| +
|
| +
|
| #endif
|
|
|