// 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
// 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
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
SkMallocPixelRef* fCache32PixelRef;
void commonAsABitmap(SkBitmap*);
+ void commonAsAGradient(GradientInfo*) const;
private:
enum {
}
}
+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) {
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);
}
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,
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) {
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);
}
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
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,
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);
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);
+ }
};
///////////////////////////////////////////////////////////////////////////////
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);
}
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