Add asAGradient shader extraction API.
Store initial gradient parameters. Add compile asserts in GPU code for BitmapType ordering. Review URL: http://codereview.appspot.com/4178063 git-svn-id: http://skia.googlecode.com/svn/trunk@845 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
7d7ca79c3e
commit
d3ae77965e
@ -51,6 +51,9 @@ public:
|
||||
SkMatrix* outMatrix,
|
||||
TileMode xy[2],
|
||||
SkScalar* twoPointRadialParams);
|
||||
|
||||
virtual GradientType asAGradient(GradientInfo* info) const;
|
||||
|
||||
protected:
|
||||
SkColorShader(SkFlattenableReadBuffer& );
|
||||
virtual void flatten(SkFlattenableWriteBuffer& );
|
||||
|
@ -163,7 +163,7 @@ public:
|
||||
// to (0,0) as bitmap x coord, where angle = 0 is
|
||||
// bitmap left edge of bitmap = 2pi is the
|
||||
// right edge. Bitmap is 1 pixel tall. No extras
|
||||
kTwoPointRadial_BitmapType
|
||||
kTwoPointRadial_BitmapType,
|
||||
//<! Matrix transforms to space where (0,0) is
|
||||
// the center of the starting circle. The second
|
||||
// circle will be centered (x, 0) where x may be
|
||||
@ -176,7 +176,8 @@ public:
|
||||
// space
|
||||
// 2: the second radius minus the first radius
|
||||
// in pre-transformed space.
|
||||
|
||||
|
||||
kLast_BitmapType = kTwoPointRadial_BitmapType
|
||||
};
|
||||
/** Optional methods for shaders that can pretend to be a bitmap/texture
|
||||
to play along with opengl. Default just returns kNone_BitmapType and
|
||||
@ -196,6 +197,59 @@ public:
|
||||
virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
|
||||
TileMode xy[2], SkScalar* twoPointRadialParams);
|
||||
|
||||
/**
|
||||
* If the shader subclass can be represented as a gradient, asAGradient
|
||||
* returns the matching GradientType enum (or kNone_GradientType if it
|
||||
* cannot). Also, if info is not null, asAGradient populates info with
|
||||
* the relevant (see below) parameters for the gradient. fColorCount
|
||||
* is both an input and output parameter. On input, it indicates how
|
||||
* many entries in fColors and fColorOffsets can be used, if they are
|
||||
* non-NULL. After asAGradient has run, fColorCount indicates how
|
||||
* many color-offset pairs there are in the gradient. If there is
|
||||
* insufficient space to store all of the color-offset pairs, fColors
|
||||
* and fColorOffsets will not be altered. fColorOffsets specifies
|
||||
* where on the range of 0 to 1 to transition to the given color.
|
||||
* The meaning of fPoint and fRadius is dependant on the type of gradient.
|
||||
*
|
||||
* None:
|
||||
* info is ignored.
|
||||
* Color:
|
||||
* fColorOffsets[0] is meaningless.
|
||||
* Linear:
|
||||
* fPoint[0] and fPoint[1] are the end-points of the gradient
|
||||
* Radial:
|
||||
* fPoint[0] and fRadius[0] are the center and radius
|
||||
* Radial2:
|
||||
* fPoint[0] and fRadius[0] are the center and radius of the 1st circle
|
||||
* fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
|
||||
* Sweep:
|
||||
* fPoint[0] is the center of the sweep.
|
||||
*/
|
||||
|
||||
enum GradientType {
|
||||
kNone_GradientType,
|
||||
kColor_GradientType,
|
||||
kLinear_GradientType,
|
||||
kRadial_GradientType,
|
||||
kRadial2_GradientType,
|
||||
kSweep_GradientType,
|
||||
kLast_GradientType = kSweep_GradientType
|
||||
};
|
||||
|
||||
struct GradientInfo {
|
||||
int fColorCount; //!< In-out parameter, specifies passed size
|
||||
// of fColors/fColorOffsets on input, and
|
||||
// actual number of colors/offsets on
|
||||
// output.
|
||||
SkColor* fColors; //!< The colors in the gradient.
|
||||
SkScalar* fColorOffsets; //!< The unit offset for color transitions.
|
||||
SkPoint fPoint[2]; //!< Type specific, see above.
|
||||
SkScalar fRadius[2]; //!< Type specific, see above.
|
||||
TileMode fTileMode; //!< The tile mode used.
|
||||
};
|
||||
|
||||
virtual GradientType asAGradient(GradientInfo* info) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Factory methods for stock shaders
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
#include "SkScalar.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkMallocPixelRef.h"
|
||||
@ -196,11 +197,15 @@ SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
|
||||
SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
|
||||
TileMode*, SkScalar*) {
|
||||
return kNone_BitmapType;
|
||||
}
|
||||
|
||||
SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
|
||||
return kNone_GradientType;
|
||||
}
|
||||
|
||||
SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
|
||||
TileMode tmx, TileMode tmy) {
|
||||
return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
|
||||
@ -258,20 +263,18 @@ bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
|
||||
return false;
|
||||
}
|
||||
|
||||
SkColor c;
|
||||
unsigned a;
|
||||
|
||||
|
||||
if (fInheritColor) {
|
||||
c = paint.getColor();
|
||||
a = SkColorGetA(c);
|
||||
fColor = paint.getColor();
|
||||
a = SkColorGetA(fColor);
|
||||
} else {
|
||||
c = fColor;
|
||||
a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
|
||||
a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha()));
|
||||
}
|
||||
|
||||
unsigned r = SkColorGetR(c);
|
||||
unsigned g = SkColorGetG(c);
|
||||
unsigned b = SkColorGetB(c);
|
||||
unsigned r = SkColorGetR(fColor);
|
||||
unsigned g = SkColorGetG(fColor);
|
||||
unsigned b = SkColorGetB(fColor);
|
||||
|
||||
// we want this before we apply any alpha
|
||||
fColor16 = SkPack888ToRGB16(r, g, b);
|
||||
@ -331,3 +334,13 @@ SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix
|
||||
return kDefault_BitmapType;
|
||||
}
|
||||
|
||||
SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
|
||||
if (info) {
|
||||
if (info->fColors && info->fColorCount >= 1) {
|
||||
info->fColors[0] = fColor;
|
||||
}
|
||||
info->fColorCount = 1;
|
||||
info->fTileMode = SkShader::kRepeat_TileMode;
|
||||
}
|
||||
return kColor_GradientType;
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ protected:
|
||||
SkMallocPixelRef* fCache32PixelRef;
|
||||
|
||||
void commonAsABitmap(SkBitmap*);
|
||||
void commonAsAGradient(GradientInfo*) const;
|
||||
|
||||
private:
|
||||
enum {
|
||||
@ -687,6 +688,28 @@ void Gradient_Shader::commonAsABitmap(SkBitmap* bitmap) {
|
||||
}
|
||||
}
|
||||
|
||||
void Gradient_Shader::commonAsAGradient(GradientInfo* info) const {
|
||||
if (info) {
|
||||
if (info->fColorCount >= fColorCount) {
|
||||
if (info->fColors) {
|
||||
memcpy(info->fColors, fOrigColors,
|
||||
fColorCount * sizeof(SkColor));
|
||||
}
|
||||
if (info->fColorOffsets) {
|
||||
if (fColorCount == 2) {
|
||||
info->fColorOffsets[0] = 0;
|
||||
info->fColorOffsets[1] = SK_Scalar1;
|
||||
} else if (fColorCount > 2) {
|
||||
for (int i = 0; i < fColorCount; i++)
|
||||
info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
info->fColorCount = fColorCount;
|
||||
info->fTileMode = fTileMode;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void pts_to_unit_matrix(const SkPoint pts[2], SkMatrix* matrix) {
|
||||
@ -707,7 +730,9 @@ public:
|
||||
Linear_Gradient(const SkPoint pts[2],
|
||||
const SkColor colors[], const SkScalar pos[], int colorCount,
|
||||
SkShader::TileMode mode, SkUnitMapper* mapper)
|
||||
: Gradient_Shader(colors, pos, colorCount, mode, mapper)
|
||||
: Gradient_Shader(colors, pos, colorCount, mode, mapper),
|
||||
fStart(pts[0]),
|
||||
fEnd(pts[1])
|
||||
{
|
||||
pts_to_unit_matrix(pts, &fPtsToUnit);
|
||||
}
|
||||
@ -717,17 +742,32 @@ public:
|
||||
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
|
||||
virtual BitmapType asABitmap(SkBitmap*, SkMatrix*,
|
||||
TileMode*, SkScalar* twoPointRadialParams);
|
||||
virtual GradientType asAGradient(GradientInfo* info) const;
|
||||
|
||||
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
||||
return SkNEW_ARGS(Linear_Gradient, (buffer));
|
||||
}
|
||||
|
||||
virtual void flatten(SkFlattenableWriteBuffer& buffer) {
|
||||
this->INHERITED::flatten(buffer);
|
||||
buffer.writeScalar(fStart.fX);
|
||||
buffer.writeScalar(fStart.fY);
|
||||
buffer.writeScalar(fEnd.fX);
|
||||
buffer.writeScalar(fEnd.fY);
|
||||
}
|
||||
|
||||
protected:
|
||||
Linear_Gradient(SkFlattenableReadBuffer& buffer) : Gradient_Shader(buffer) {}
|
||||
Linear_Gradient(SkFlattenableReadBuffer& buffer)
|
||||
: Gradient_Shader(buffer),
|
||||
fStart(SkPoint::Make(buffer.readScalar(), buffer.readScalar())),
|
||||
fEnd(SkPoint::Make(buffer.readScalar(), buffer.readScalar())) {
|
||||
}
|
||||
virtual Factory getFactory() { return CreateProc; }
|
||||
|
||||
private:
|
||||
typedef Gradient_Shader INHERITED;
|
||||
const SkPoint fStart;
|
||||
const SkPoint fEnd;
|
||||
};
|
||||
|
||||
bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
|
||||
@ -850,6 +890,15 @@ SkShader::BitmapType Linear_Gradient::asABitmap(SkBitmap* bitmap,
|
||||
return kDefault_BitmapType;
|
||||
}
|
||||
|
||||
SkShader::GradientType Linear_Gradient::asAGradient(GradientInfo* info) const {
|
||||
if (info) {
|
||||
commonAsAGradient(info);
|
||||
info->fPoint[0] = fStart;
|
||||
info->fPoint[1] = fEnd;
|
||||
}
|
||||
return kLinear_GradientType;
|
||||
}
|
||||
|
||||
static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
|
||||
int count) {
|
||||
if (reinterpret_cast<uintptr_t>(dst) & 2) {
|
||||
@ -989,7 +1038,9 @@ public:
|
||||
Radial_Gradient(const SkPoint& center, SkScalar radius,
|
||||
const SkColor colors[], const SkScalar pos[], int colorCount,
|
||||
SkShader::TileMode mode, SkUnitMapper* mapper)
|
||||
: Gradient_Shader(colors, pos, colorCount, mode, mapper)
|
||||
: Gradient_Shader(colors, pos, colorCount, mode, mapper),
|
||||
fCenter(center),
|
||||
fRadius(radius)
|
||||
{
|
||||
// make sure our table is insync with our current #define for kSQRT_TABLE_SIZE
|
||||
SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE);
|
||||
@ -1199,17 +1250,38 @@ public:
|
||||
}
|
||||
return kRadial_BitmapType;
|
||||
}
|
||||
virtual GradientType asAGradient(GradientInfo* info) const {
|
||||
if (info) {
|
||||
commonAsAGradient(info);
|
||||
info->fPoint[0] = fCenter;
|
||||
info->fRadius[0] = fRadius;
|
||||
}
|
||||
return kRadial_GradientType;
|
||||
}
|
||||
|
||||
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
||||
return SkNEW_ARGS(Radial_Gradient, (buffer));
|
||||
}
|
||||
|
||||
virtual void flatten(SkFlattenableWriteBuffer& buffer) {
|
||||
this->INHERITED::flatten(buffer);
|
||||
buffer.writeScalar(fCenter.fX);
|
||||
buffer.writeScalar(fCenter.fY);
|
||||
buffer.writeScalar(fRadius);
|
||||
}
|
||||
|
||||
protected:
|
||||
Radial_Gradient(SkFlattenableReadBuffer& buffer) : Gradient_Shader(buffer) {};
|
||||
Radial_Gradient(SkFlattenableReadBuffer& buffer)
|
||||
: Gradient_Shader(buffer),
|
||||
fCenter(SkPoint::Make(buffer.readScalar(), buffer.readScalar())),
|
||||
fRadius(buffer.readScalar()) {
|
||||
}
|
||||
virtual Factory getFactory() { return CreateProc; }
|
||||
|
||||
private:
|
||||
typedef Gradient_Shader INHERITED;
|
||||
const SkPoint fCenter;
|
||||
const SkScalar fRadius;
|
||||
};
|
||||
|
||||
/* Two-point radial gradients are specified by two circles, each with a center
|
||||
@ -1305,20 +1377,12 @@ public:
|
||||
const SkColor colors[], const SkScalar pos[],
|
||||
int colorCount, SkShader::TileMode mode,
|
||||
SkUnitMapper* mapper)
|
||||
: Gradient_Shader(colors, pos, colorCount, mode, mapper)
|
||||
{
|
||||
fDiff = start - end;
|
||||
fDiffRadius = endRadius - startRadius;
|
||||
SkScalar inv = SkScalarInvert(fDiffRadius);
|
||||
fDiff.fX = SkScalarMul(fDiff.fX, inv);
|
||||
fDiff.fY = SkScalarMul(fDiff.fY, inv);
|
||||
fStartRadius = SkScalarMul(startRadius, inv);
|
||||
fSr2D2 = SkScalarSquare(fStartRadius);
|
||||
fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
|
||||
fOneOverTwoA = SkScalarInvert(fA * 2);
|
||||
|
||||
fPtsToUnit.setTranslate(-start.fX, -start.fY);
|
||||
fPtsToUnit.postScale(inv, inv);
|
||||
: Gradient_Shader(colors, pos, colorCount, mode, mapper),
|
||||
fCenter1(start),
|
||||
fCenter2(end),
|
||||
fRadius1(startRadius),
|
||||
fRadius2(endRadius) {
|
||||
init();
|
||||
}
|
||||
|
||||
virtual BitmapType asABitmap(SkBitmap* bitmap,
|
||||
@ -1351,6 +1415,17 @@ public:
|
||||
return kTwoPointRadial_BitmapType;
|
||||
}
|
||||
|
||||
virtual GradientType asAGradient(GradientInfo* info) const {
|
||||
if (info) {
|
||||
commonAsAGradient(info);
|
||||
info->fPoint[0] = fCenter1;
|
||||
info->fPoint[1] = fCenter2;
|
||||
info->fRadius[0] = fRadius1;
|
||||
info->fRadius[1] = fRadius2;
|
||||
}
|
||||
return kRadial2_GradientType;
|
||||
}
|
||||
|
||||
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
|
||||
{
|
||||
SkASSERT(count > 0);
|
||||
@ -1468,32 +1543,48 @@ public:
|
||||
|
||||
virtual void flatten(SkFlattenableWriteBuffer& buffer) {
|
||||
this->INHERITED::flatten(buffer);
|
||||
buffer.writeScalar(fDiff.fX);
|
||||
buffer.writeScalar(fDiff.fY);
|
||||
buffer.writeScalar(fStartRadius);
|
||||
buffer.writeScalar(fDiffRadius);
|
||||
buffer.writeScalar(fSr2D2);
|
||||
buffer.writeScalar(fA);
|
||||
buffer.writeScalar(fOneOverTwoA);
|
||||
buffer.writeScalar(fCenter1.fX);
|
||||
buffer.writeScalar(fCenter1.fY);
|
||||
buffer.writeScalar(fCenter2.fX);
|
||||
buffer.writeScalar(fCenter2.fY);
|
||||
buffer.writeScalar(fRadius1);
|
||||
buffer.writeScalar(fRadius2);
|
||||
}
|
||||
|
||||
protected:
|
||||
Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
|
||||
: Gradient_Shader(buffer) {
|
||||
fDiff.fX = buffer.readScalar();
|
||||
fDiff.fY = buffer.readScalar();
|
||||
fStartRadius = buffer.readScalar();
|
||||
fDiffRadius = buffer.readScalar();
|
||||
fSr2D2 = buffer.readScalar();
|
||||
fA = buffer.readScalar();
|
||||
fOneOverTwoA = buffer.readScalar();
|
||||
: Gradient_Shader(buffer),
|
||||
fCenter1(SkPoint::Make(buffer.readScalar(), buffer.readScalar())),
|
||||
fCenter2(SkPoint::Make(buffer.readScalar(), buffer.readScalar())),
|
||||
fRadius1(buffer.readScalar()),
|
||||
fRadius2(buffer.readScalar()) {
|
||||
init();
|
||||
};
|
||||
virtual Factory getFactory() { return CreateProc; }
|
||||
|
||||
private:
|
||||
typedef Gradient_Shader INHERITED;
|
||||
const SkPoint fCenter1;
|
||||
const SkPoint fCenter2;
|
||||
const SkScalar fRadius1;
|
||||
const SkScalar fRadius2;
|
||||
SkPoint fDiff;
|
||||
SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
|
||||
|
||||
void init() {
|
||||
fDiff = fCenter1 - fCenter2;
|
||||
fDiffRadius = fRadius2 - fRadius1;
|
||||
SkScalar inv = SkScalarInvert(fDiffRadius);
|
||||
fDiff.fX = SkScalarMul(fDiff.fX, inv);
|
||||
fDiff.fY = SkScalarMul(fDiff.fY, inv);
|
||||
fStartRadius = SkScalarMul(fRadius1, inv);
|
||||
fSr2D2 = SkScalarSquare(fStartRadius);
|
||||
fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
|
||||
fOneOverTwoA = SkScalarInvert(fA * 2);
|
||||
|
||||
fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
|
||||
fPtsToUnit.postScale(inv, inv);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -1502,7 +1593,8 @@ class Sweep_Gradient : public Gradient_Shader {
|
||||
public:
|
||||
Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
|
||||
const SkScalar pos[], int count, SkUnitMapper* mapper)
|
||||
: Gradient_Shader(colors, pos, count, SkShader::kClamp_TileMode, mapper)
|
||||
: Gradient_Shader(colors, pos, count, SkShader::kClamp_TileMode, mapper),
|
||||
fCenter(SkPoint::Make(cx, cy))
|
||||
{
|
||||
fPtsToUnit.setTranslate(-cx, -cy);
|
||||
}
|
||||
@ -1526,16 +1618,35 @@ public:
|
||||
return kSweep_BitmapType;
|
||||
}
|
||||
|
||||
virtual GradientType asAGradient(GradientInfo* info) const {
|
||||
if (info) {
|
||||
commonAsAGradient(info);
|
||||
info->fPoint[0] = fCenter;
|
||||
}
|
||||
return kSweep_GradientType;
|
||||
}
|
||||
|
||||
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
||||
return SkNEW_ARGS(Sweep_Gradient, (buffer));
|
||||
}
|
||||
|
||||
virtual void flatten(SkFlattenableWriteBuffer& buffer) {
|
||||
this->INHERITED::flatten(buffer);
|
||||
buffer.writeScalar(fCenter.fX);
|
||||
buffer.writeScalar(fCenter.fY);
|
||||
}
|
||||
|
||||
protected:
|
||||
Sweep_Gradient(SkFlattenableReadBuffer& buffer) : Gradient_Shader(buffer) {}
|
||||
Sweep_Gradient(SkFlattenableReadBuffer& buffer)
|
||||
: Gradient_Shader(buffer),
|
||||
fCenter(SkPoint::Make(buffer.readScalar(), buffer.readScalar())) {
|
||||
}
|
||||
|
||||
virtual Factory getFactory() { return CreateProc; }
|
||||
|
||||
private:
|
||||
typedef Gradient_Shader INHERITED;
|
||||
const SkPoint fCenter;
|
||||
};
|
||||
|
||||
#ifdef COMPUTE_SWEEP_TABLE
|
||||
|
@ -325,7 +325,13 @@ bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// must be in SkShader::BitmapTypeOrder
|
||||
SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
|
||||
SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
|
||||
SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
|
||||
SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
|
||||
SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
|
||||
shader_type_mismatch);
|
||||
SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 4, shader_type_mismatch);
|
||||
|
||||
static const GrSamplerState::SampleMode sk_bmp_type_to_sample_mode[] = {
|
||||
(GrSamplerState::SampleMode) -1, // kNone_BitmapType
|
||||
|
Loading…
Reference in New Issue
Block a user