зеркало из https://github.com/mozilla/moz-skia.git
Add flipped gradient branch to two point conical gradient
BUG=skia: Committed: http://code.google.com/p/skia/source/detail?r=14235 R=bsalomon@google.com Author: egdaniel@google.com Review URL: https://codereview.chromium.org/227623004 git-svn-id: http://skia.googlecode.com/svn/trunk@14271 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
f7927dd607
Коммит
44d83c1e81
|
@ -56,3 +56,15 @@ image-surface
|
|||
aaclip
|
||||
composeshader
|
||||
peekpixels
|
||||
|
||||
# egdaniel https://codereview.chromium.org/227623004/
|
||||
# This change will cause change two point conical gradients to change pixels values
|
||||
# but without any real perceptual differences.
|
||||
gradients
|
||||
gradients_view_perspective
|
||||
gradients_local_perspective
|
||||
gradients_no_texture
|
||||
twopointconical
|
||||
lightingcolorfilter
|
||||
radial_gradient2
|
||||
gradient_dirty_laundry
|
||||
|
|
|
@ -323,13 +323,14 @@ protected:
|
|||
// V21: add pushCull, popCull
|
||||
// V22: SK_PICT_FACTORY_TAG's size is now the chunk size in bytes
|
||||
// V23: SkPaint::FilterLevel became a real enum
|
||||
// V24: SkTwoPointConicalGradient now has fFlipped flag for gradient flipping
|
||||
|
||||
// Note: If the picture version needs to be increased then please follow the
|
||||
// steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw
|
||||
|
||||
// Only SKPs within the min/current picture version range (inclusive) can be read.
|
||||
static const uint32_t MIN_PICTURE_VERSION = 19;
|
||||
static const uint32_t CURRENT_PICTURE_VERSION = 23;
|
||||
static const uint32_t CURRENT_PICTURE_VERSION = 24;
|
||||
|
||||
mutable uint32_t fUniqueID;
|
||||
|
||||
|
|
|
@ -118,12 +118,13 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
|
|||
SkFixed dp = SK_Fixed1 / (desc.fCount - 1);
|
||||
SkFixed p = dp;
|
||||
SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp
|
||||
for (int i = 1; i < desc.fCount; i++) {
|
||||
for (int i = 1; i < desc.fCount - 1; i++) {
|
||||
recs->fPos = p;
|
||||
recs->fScale = scale;
|
||||
recs += 1;
|
||||
p += dp;
|
||||
}
|
||||
recs->fPos = SK_Fixed1;
|
||||
}
|
||||
}
|
||||
this->initCommon();
|
||||
|
@ -237,6 +238,30 @@ SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor
|
|||
return kTexture_GpuColorType;
|
||||
}
|
||||
|
||||
void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
|
||||
SkColor* colorSrc, Rec* recSrc,
|
||||
int count) {
|
||||
SkAutoSTArray<8, SkColor> colorsTemp(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int offset = count - i - 1;
|
||||
colorsTemp[i] = colorSrc[offset];
|
||||
}
|
||||
if (count > 2) {
|
||||
SkAutoSTArray<8, Rec> recsTemp(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int offset = count - i - 1;
|
||||
recsTemp[i].fPos = SK_Fixed1 - recSrc[offset].fPos;
|
||||
recsTemp[i].fScale = recSrc[offset].fScale;
|
||||
}
|
||||
memcpy(recDst, recsTemp.get(), count * sizeof(Rec));
|
||||
}
|
||||
memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
|
||||
}
|
||||
|
||||
void SkGradientShaderBase::flipGradientColors() {
|
||||
FlipGradientColors(fOrigColors, fRecs, fOrigColors, fRecs, fColorCount);
|
||||
}
|
||||
|
||||
bool SkGradientShaderBase::isOpaque() const {
|
||||
return fColorsAreOpaque;
|
||||
}
|
||||
|
@ -643,11 +668,23 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
|
|||
}
|
||||
}
|
||||
|
||||
void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
|
||||
void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad) const {
|
||||
if (info) {
|
||||
if (info->fColorCount >= fColorCount) {
|
||||
SkColor* colorLoc;
|
||||
Rec* recLoc;
|
||||
if (flipGrad && (info->fColors || info->fColorOffsets)) {
|
||||
SkAutoSTArray<8, SkColor> colorStorage(fColorCount);
|
||||
SkAutoSTArray<8, Rec> recStorage(fColorCount);
|
||||
colorLoc = colorStorage.get();
|
||||
recLoc = recStorage.get();
|
||||
FlipGradientColors(colorLoc, recLoc, fOrigColors, fRecs, fColorCount);
|
||||
} else {
|
||||
colorLoc = fOrigColors;
|
||||
recLoc = fRecs;
|
||||
}
|
||||
if (info->fColors) {
|
||||
memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor));
|
||||
memcpy(info->fColors, colorLoc, fColorCount * sizeof(SkColor));
|
||||
}
|
||||
if (info->fColorOffsets) {
|
||||
if (fColorCount == 2) {
|
||||
|
@ -655,7 +692,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
|
|||
info->fColorOffsets[1] = SK_Scalar1;
|
||||
} else if (fColorCount > 2) {
|
||||
for (int i = 0; i < fColorCount; ++i) {
|
||||
info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
|
||||
info->fColorOffsets[i] = SkFixedToScalar(recLoc[i].fPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -801,12 +838,36 @@ SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
|
|||
if (start == end && startRadius == endRadius) {
|
||||
return SkNEW(SkEmptyShader);
|
||||
}
|
||||
|
||||
EXPAND_1_COLOR(colorCount);
|
||||
|
||||
bool flipGradient = startRadius > endRadius;
|
||||
|
||||
SkGradientShaderBase::Descriptor desc;
|
||||
|
||||
if (!flipGradient) {
|
||||
desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
|
||||
return SkNEW_ARGS(SkTwoPointConicalGradient,
|
||||
(start, startRadius, end, endRadius, desc));
|
||||
(start, startRadius, end, endRadius, flipGradient, desc));
|
||||
} else {
|
||||
SkAutoSTArray<8, SkColor> colorsNew(colorCount);
|
||||
SkAutoSTArray<8, SkScalar> posNew(colorCount);
|
||||
for (int i = 0; i < colorCount; ++i) {
|
||||
colorsNew[i] = colors[colorCount - i - 1];
|
||||
}
|
||||
|
||||
if (pos) {
|
||||
for (int i = 0; i < colorCount; ++i) {
|
||||
posNew[i] = 1 - pos[colorCount - i - 1];
|
||||
}
|
||||
desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, mapper, flags);
|
||||
} else {
|
||||
desc_init(&desc, colorsNew.get(), NULL, colorCount, mode, mapper, flags);
|
||||
}
|
||||
|
||||
return SkNEW_ARGS(SkTwoPointConicalGradient,
|
||||
(end, endRadius, start, startRadius, flipGradient, desc));
|
||||
}
|
||||
}
|
||||
|
||||
SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
|
||||
|
|
|
@ -166,7 +166,23 @@ protected:
|
|||
const uint16_t* getCache16() const;
|
||||
const SkPMColor* getCache32() const;
|
||||
|
||||
void commonAsAGradient(GradientInfo*) const;
|
||||
void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
|
||||
|
||||
/*
|
||||
* Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
|
||||
* Count is the number of colors in the gradient
|
||||
* It will then flip all the color and rec information and return in their respective Dst
|
||||
* pointers. It is assumed that space has already been allocated for the Dst pointers.
|
||||
* The rec src and dst are only assumed to be valid if count > 2
|
||||
*/
|
||||
static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
|
||||
SkColor* colorSrc, Rec* recSrc,
|
||||
int count);
|
||||
|
||||
// V23_COMPATIBILITY_CODE
|
||||
// Used for 2-pt conical gradients since we sort start/end cirlces by radius
|
||||
// Assumes space has already been allocated for fOrigColors
|
||||
void flipGradientColors();
|
||||
|
||||
private:
|
||||
enum {
|
||||
|
|
|
@ -20,7 +20,7 @@ static int valid_divide(float numer, float denom, float* ratio) {
|
|||
|
||||
// Return the number of distinct real roots, and write them into roots[] in
|
||||
// ascending order
|
||||
static int find_quad_roots(float A, float B, float C, float roots[2]) {
|
||||
static int find_quad_roots(float A, float B, float C, float roots[2], bool descendingOrder = false) {
|
||||
SkASSERT(roots);
|
||||
|
||||
if (A == 0) {
|
||||
|
@ -54,6 +54,9 @@ static int find_quad_roots(float A, float B, float C, float roots[2]) {
|
|||
float r1 = C / Q;
|
||||
roots[0] = r0 < r1 ? r0 : r1;
|
||||
roots[1] = r0 > r1 ? r0 : r1;
|
||||
if (descendingOrder) {
|
||||
SkTSwap(roots[0], roots[1]);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -64,7 +67,8 @@ static float lerp(float x, float dx, float t) {
|
|||
static float sqr(float x) { return x * x; }
|
||||
|
||||
void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
|
||||
const SkPoint& center1, SkScalar rad1) {
|
||||
const SkPoint& center1, SkScalar rad1,
|
||||
bool flipped) {
|
||||
fCenterX = SkScalarToFloat(center0.fX);
|
||||
fCenterY = SkScalarToFloat(center0.fY);
|
||||
fDCenterX = SkScalarToFloat(center1.fX) - fCenterX;
|
||||
|
@ -75,6 +79,8 @@ void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
|
|||
fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
|
||||
fRadius2 = sqr(fRadius);
|
||||
fRDR = fRadius * fDRadius;
|
||||
|
||||
fFlipped = flipped;
|
||||
}
|
||||
|
||||
void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) {
|
||||
|
@ -90,7 +96,7 @@ SkFixed TwoPtRadial::nextT() {
|
|||
float roots[2];
|
||||
|
||||
float C = sqr(fRelX) + sqr(fRelY) - fRadius2;
|
||||
int countRoots = find_quad_roots(fA, fB, C, roots);
|
||||
int countRoots = find_quad_roots(fA, fB, C, roots, fFlipped);
|
||||
|
||||
fRelX += fIncX;
|
||||
fRelY += fIncY;
|
||||
|
@ -169,7 +175,7 @@ static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
|
|||
}
|
||||
|
||||
void SkTwoPointConicalGradient::init() {
|
||||
fRec.init(fCenter1, fRadius1, fCenter2, fRadius2);
|
||||
fRec.init(fCenter1, fRadius1, fCenter2, fRadius2, fFlippedGrad);
|
||||
fPtsToUnit.reset();
|
||||
}
|
||||
|
||||
|
@ -178,12 +184,13 @@ void SkTwoPointConicalGradient::init() {
|
|||
SkTwoPointConicalGradient::SkTwoPointConicalGradient(
|
||||
const SkPoint& start, SkScalar startRadius,
|
||||
const SkPoint& end, SkScalar endRadius,
|
||||
const Descriptor& desc)
|
||||
bool flippedGrad, const Descriptor& desc)
|
||||
: SkGradientShaderBase(desc),
|
||||
fCenter1(start),
|
||||
fCenter2(end),
|
||||
fRadius1(startRadius),
|
||||
fRadius2(endRadius) {
|
||||
fRadius2(endRadius),
|
||||
fFlippedGrad(flippedGrad) {
|
||||
// this is degenerate, and should be caught by our caller
|
||||
SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2);
|
||||
this->init();
|
||||
|
@ -299,14 +306,19 @@ SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
|
|||
return kTwoPointConical_BitmapType;
|
||||
}
|
||||
|
||||
// Returns the original non-sorted version of the gradient
|
||||
SkShader::GradientType SkTwoPointConicalGradient::asAGradient(
|
||||
GradientInfo* info) const {
|
||||
if (info) {
|
||||
commonAsAGradient(info);
|
||||
commonAsAGradient(info, fFlippedGrad);
|
||||
info->fPoint[0] = fCenter1;
|
||||
info->fPoint[1] = fCenter2;
|
||||
info->fRadius[0] = fRadius1;
|
||||
info->fRadius[1] = fRadius2;
|
||||
if (fFlippedGrad) {
|
||||
SkTSwap(info->fPoint[0], info->fPoint[1]);
|
||||
SkTSwap(info->fRadius[0], info->fRadius[1]);
|
||||
}
|
||||
}
|
||||
return kConical_GradientType;
|
||||
}
|
||||
|
@ -318,6 +330,20 @@ SkTwoPointConicalGradient::SkTwoPointConicalGradient(
|
|||
fCenter2(buffer.readPoint()),
|
||||
fRadius1(buffer.readScalar()),
|
||||
fRadius2(buffer.readScalar()) {
|
||||
if (buffer.pictureVersion() >= 24 || 0 == buffer.pictureVersion()) {
|
||||
fFlippedGrad = buffer.readBool();
|
||||
} else {
|
||||
// V23_COMPATIBILITY_CODE
|
||||
// Sort gradient by radius size for old pictures
|
||||
if (fRadius2 < fRadius1) {
|
||||
SkTSwap(fCenter1, fCenter2);
|
||||
SkTSwap(fRadius1, fRadius2);
|
||||
this->flipGradientColors();
|
||||
fFlippedGrad = true;
|
||||
} else {
|
||||
fFlippedGrad = false;
|
||||
}
|
||||
}
|
||||
this->init();
|
||||
};
|
||||
|
||||
|
@ -328,6 +354,7 @@ void SkTwoPointConicalGradient::flatten(
|
|||
buffer.writePoint(fCenter2);
|
||||
buffer.writeScalar(fRadius1);
|
||||
buffer.writeScalar(fRadius2);
|
||||
buffer.writeBool(fFlippedGrad);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
|
|
@ -23,9 +23,11 @@ struct TwoPtRadial {
|
|||
float fA;
|
||||
float fRadius2;
|
||||
float fRDR;
|
||||
bool fFlipped;
|
||||
|
||||
void init(const SkPoint& center0, SkScalar rad0,
|
||||
const SkPoint& center1, SkScalar rad1);
|
||||
const SkPoint& center1, SkScalar rad1,
|
||||
bool flipped);
|
||||
|
||||
// used by setup and nextT
|
||||
float fRelX, fRelY, fIncX, fIncY;
|
||||
|
@ -47,7 +49,7 @@ class SkTwoPointConicalGradient : public SkGradientShaderBase {
|
|||
public:
|
||||
SkTwoPointConicalGradient(const SkPoint& start, SkScalar startRadius,
|
||||
const SkPoint& end, SkScalar endRadius,
|
||||
const Descriptor&);
|
||||
bool flippedGrad, const Descriptor&);
|
||||
|
||||
virtual void shadeSpan(int x, int y, SkPMColor* dstCParam,
|
||||
int count) SK_OVERRIDE;
|
||||
|
@ -68,6 +70,7 @@ public:
|
|||
const SkPoint& getStartCenter() const { return fCenter1; }
|
||||
const SkPoint& getEndCenter() const { return fCenter2; }
|
||||
SkScalar getEndRadius() const { return fRadius2; }
|
||||
bool isFlippedGrad() const { return fFlippedGrad; }
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTwoPointConicalGradient)
|
||||
|
@ -77,11 +80,13 @@ protected:
|
|||
virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
SkPoint fCenter1;
|
||||
SkPoint fCenter2;
|
||||
SkScalar fRadius1;
|
||||
SkScalar fRadius2;
|
||||
bool fFlippedGrad;
|
||||
|
||||
typedef SkGradientShaderBase INHERITED;
|
||||
const SkPoint fCenter1;
|
||||
const SkPoint fCenter2;
|
||||
const SkScalar fRadius1;
|
||||
const SkScalar fRadius2;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
|
||||
// The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
|
||||
bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(fCenterX1); }
|
||||
bool isFlipped() const { return fIsFlipped; }
|
||||
SkScalar center() const { return fCenterX1; }
|
||||
SkScalar diffRadius() const { return fDiffRadius; }
|
||||
SkScalar radius() const { return fRadius0; }
|
||||
|
@ -68,7 +69,8 @@ private:
|
|||
return (INHERITED::onIsEqual(sBase) &&
|
||||
this->fCenterX1 == s.fCenterX1 &&
|
||||
this->fRadius0 == s.fRadius0 &&
|
||||
this->fDiffRadius == s.fDiffRadius);
|
||||
this->fDiffRadius == s.fDiffRadius &&
|
||||
this->fIsFlipped == s.fIsFlipped);
|
||||
}
|
||||
|
||||
Default2PtConicalEffect(GrContext* ctx,
|
||||
|
@ -78,7 +80,8 @@ private:
|
|||
: INHERITED(ctx, shader, matrix, tm),
|
||||
fCenterX1(shader.getCenterX1()),
|
||||
fRadius0(shader.getStartRadius()),
|
||||
fDiffRadius(shader.getDiffRadius()) {
|
||||
fDiffRadius(shader.getDiffRadius()),
|
||||
fIsFlipped(shader.isFlippedGrad()) {
|
||||
// We pass the linear part of the quadratic as a varying.
|
||||
// float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
|
||||
fBTransform = this->getCoordTransform();
|
||||
|
@ -103,6 +106,7 @@ private:
|
|||
SkScalar fCenterX1;
|
||||
SkScalar fRadius0;
|
||||
SkScalar fDiffRadius;
|
||||
bool fIsFlipped;
|
||||
|
||||
// @}
|
||||
|
||||
|
@ -132,6 +136,7 @@ protected:
|
|||
const char* fFSVaryingName;
|
||||
|
||||
bool fIsDegenerate;
|
||||
bool fIsFlipped;
|
||||
|
||||
// @{
|
||||
/// Values last uploaded as uniforms
|
||||
|
@ -194,6 +199,7 @@ GLDefault2PtConicalEffect::GLDefault2PtConicalEffect(const GrBackendEffectFactor
|
|||
|
||||
const Default2PtConicalEffect& data = drawEffect.castEffect<Default2PtConicalEffect>();
|
||||
fIsDegenerate = data.isDegenerate();
|
||||
fIsFlipped = data.isFlipped();
|
||||
}
|
||||
|
||||
void GLDefault2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
|
||||
|
@ -281,9 +287,14 @@ void GLDefault2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
|
|||
// Note: If there are two roots that both generate radius(t) > 0, the
|
||||
// Canvas spec says to choose the larger t.
|
||||
|
||||
// so we'll look at the larger one first:
|
||||
// so we'll look at the larger one first (or smaller if flipped):
|
||||
if (!fIsFlipped) {
|
||||
builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(),
|
||||
r0Name.c_str(), r1Name.c_str());
|
||||
} else {
|
||||
builder->fsCodeAppendf("\t\tfloat %s = min(%s, %s);\n", tName.c_str(),
|
||||
r0Name.c_str(), r1Name.c_str());
|
||||
}
|
||||
|
||||
// if r(t) > 0, then we're done; t will be our x coordinate
|
||||
builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
|
||||
|
@ -294,8 +305,13 @@ void GLDefault2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
|
|||
|
||||
// otherwise, if r(t) for the larger root was <= 0, try the other root
|
||||
builder->fsCodeAppend("\t\t} else {\n");
|
||||
if (!fIsFlipped) {
|
||||
builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(),
|
||||
r0Name.c_str(), r1Name.c_str());
|
||||
} else {
|
||||
builder->fsCodeAppendf("\t\t\t%s = max(%s, %s);\n", tName.c_str(),
|
||||
r0Name.c_str(), r1Name.c_str());
|
||||
}
|
||||
|
||||
// if r(t) > 0 for the smaller root, then t will be our x coordinate
|
||||
builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n",
|
||||
|
@ -330,6 +346,7 @@ void GLDefault2PtConicalEffect::setData(const GrGLUniformManager& uman,
|
|||
INHERITED::setData(uman, drawEffect);
|
||||
const Default2PtConicalEffect& data = drawEffect.castEffect<Default2PtConicalEffect>();
|
||||
SkASSERT(data.isDegenerate() == fIsDegenerate);
|
||||
SkASSERT(data.isFlipped() == fIsFlipped);
|
||||
SkScalar centerX1 = data.center();
|
||||
SkScalar radius0 = data.radius();
|
||||
SkScalar diffRadius = data.diffRadius();
|
||||
|
@ -365,12 +382,16 @@ GrGLEffect::EffectKey GLDefault2PtConicalEffect::GenKey(const GrDrawEffect& draw
|
|||
const GrGLCaps&) {
|
||||
enum {
|
||||
kIsDegenerate = 1 << kBaseKeyBitCnt,
|
||||
kIsFlipped = 1 << (kBaseKeyBitCnt + 1),
|
||||
};
|
||||
|
||||
EffectKey key = GenBaseGradientKey(drawEffect);
|
||||
if (drawEffect.castEffect<Default2PtConicalEffect>().isDegenerate()) {
|
||||
key |= kIsDegenerate;
|
||||
}
|
||||
if (drawEffect.castEffect<Default2PtConicalEffect>().isFlipped()) {
|
||||
key |= kIsFlipped;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче