aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkColorShader.h8
-rw-r--r--include/core/SkShader.h10
-rw-r--r--samplecode/SampleTestGL.cpp16
-rw-r--r--src/core/SkBitmapProcShader.cpp11
-rw-r--r--src/core/SkBlitter.cpp7
-rw-r--r--src/core/SkBlitter_RGB16.cpp28
-rw-r--r--src/core/SkCoreBlitters.h6
-rw-r--r--src/core/SkShader.cpp11
-rw-r--r--src/effects/SkGradientShader.cpp14
-rw-r--r--xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj4
10 files changed, 96 insertions, 19 deletions
diff --git a/include/core/SkColorShader.h b/include/core/SkColorShader.h
index f9c3dc33d2..7c5f941c0a 100644
--- a/include/core/SkColorShader.h
+++ b/include/core/SkColorShader.h
@@ -29,14 +29,15 @@ public:
/** Create a ColorShader that will inherit its color from the Paint
at draw time.
*/
- SkColorShader() : fInheritColor(true) {}
+ SkColorShader() : fFlags(0), fInheritColor(true) {}
+
/** Create a ColorShader that ignores the color in the paint, and uses the
specified color. Note: like all shaders, at draw time the paint's alpha
will be respected, and is applied to the specified color.
*/
- SkColorShader(SkColor c) : fColor(c), fInheritColor(false) {}
+ SkColorShader(SkColor c) : fColor(c), fFlags(0), fInheritColor(false) {}
- virtual uint32_t getFlags();
+ virtual uint32_t getFlags() { return fFlags; }
virtual uint8_t getSpan16Alpha() const;
virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix);
@@ -54,6 +55,7 @@ private:
}
SkColor fColor; // ignored if fInheritColor is true
SkPMColor fPMColor; // cached after setContext()
+ uint32_t fFlags; // cached after setContext()
uint16_t fColor16; // cached after setContext()
SkBool8 fInheritColor;
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index 7c13e3d3e8..8fac8cbb08 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -63,14 +63,22 @@ public:
enum Flags {
//!< set if all of the colors will be opaque
kOpaqueAlpha_Flag = 0x01,
+
//! set if this shader's shadeSpan16() method can be called
kHasSpan16_Flag = 0x02,
+
/** Set this bit if the shader's native data type is instrinsically 16
bit, meaning that calling the 32bit shadeSpan() entry point will
mean the the impl has to up-sample 16bit data into 32bit. Used as a
a means of clearing a dither request if the it will have no effect
*/
- kIntrinsicly16_Flag = 0x04
+ kIntrinsicly16_Flag = 0x04,
+
+ /** set (after setContext) if the spans only vary in X (const in Y).
+ e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
+ that varies from left-to-right
+ */
+ kConstInY_Flag = 0x08
};
/** Called sometimes before drawing with this shader.
diff --git a/samplecode/SampleTestGL.cpp b/samplecode/SampleTestGL.cpp
index c12eb7ccac..210d7799e1 100644
--- a/samplecode/SampleTestGL.cpp
+++ b/samplecode/SampleTestGL.cpp
@@ -9,6 +9,19 @@
#include "SkShader.h"
#include "SkUtils.h"
+static void show_ramp(SkCanvas* canvas, const SkRect& r) {
+ SkPoint pts[] = { r.fLeft, 0, r.fRight, 0 };
+ SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2,
+ SkShader::kRepeat_TileMode);
+ SkPaint p;
+ p.setShader(s)->unref();
+ canvas->drawRect(r, p);
+ canvas->translate(r.width() + SkIntToScalar(8), 0);
+ p.setDither(true);
+ canvas->drawRect(r, p);
+}
+
class TestGLView : public SkView {
public:
TestGLView() {
@@ -49,6 +62,9 @@ protected:
canvas->translate(r.width() + SkIntToScalar(20), 0);
paint.setStrokeWidth(SkIntToScalar(5));
canvas->drawRect(r, paint);
+
+ canvas->translate(r.width() * 10/9, 0);
+ show_ramp(canvas, r);
}
private:
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 8ba57c4ae3..2302e0f048 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -67,6 +67,11 @@ void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
buffer.write8(fState.fTileModeY);
}
+static bool only_scale_and_translate(const SkMatrix& matrix) {
+ unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
+ return (matrix.getType() & ~mask) == 0;
+}
+
bool SkBitmapProcShader::setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) {
@@ -117,6 +122,12 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
default:
break;
}
+
+ // if we're only 1-pixel heigh, and we don't rotate, then we can claim this
+ if (1 == fState.fBitmap->height() &&
+ only_scale_and_translate(this->getTotalInverse())) {
+ fFlags |= kConstInY_Flag;
+ }
return true;
}
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 25303ac6b8..a38b46e99a 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -977,17 +977,16 @@ const uint32_t gMask_00FF00FF = 0xFF00FF;
//////////////////////////////////////////////////////////////////////////////////////////////////////
SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
- : INHERITED(device)
-{
+ : INHERITED(device) {
fShader = paint.getShader();
SkASSERT(fShader);
fShader->ref();
fShader->beginSession();
+ fShaderFlags = fShader->getFlags();
}
-SkShaderBlitter::~SkShaderBlitter()
-{
+SkShaderBlitter::~SkShaderBlitter() {
fShader->endSession();
fShader->unref();
}
diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp
index b253662da3..40eceeca5c 100644
--- a/src/core/SkBlitter_RGB16.cpp
+++ b/src/core/SkBlitter_RGB16.cpp
@@ -483,7 +483,7 @@ void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
const SkPaint& paint)
: SkRGB16_Shader_Blitter(device, paint) {
- SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags()));
+ SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
}
void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
@@ -569,7 +569,7 @@ SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
// compute SkBlitRow::Procs
unsigned flags = 0;
- uint32_t shaderFlags = fShader->getFlags();
+ uint32_t shaderFlags = fShaderFlags;
// shaders take care of global alpha, so we never set it in SkBlitRow
if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
flags |= SkBlitRow::kSrcPixelAlpha_Flag;
@@ -597,6 +597,30 @@ void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
}
+void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
+ SkShader* shader = fShader;
+ SkBlitRow::Proc proc = fOpaqueProc;
+ SkPMColor* buffer = fBuffer;
+ uint16_t* dst = fDevice.getAddr16(x, y);
+ size_t dstRB = fDevice.rowBytes();
+
+ if (fShaderFlags & SkShader::kConstInY_Flag) {
+ shader->shadeSpan(x, y, buffer, width);
+ do {
+ proc(dst, buffer, width, 0xFF, x, y);
+ y += 1;
+ dst = (uint16_t*)((char*)dst + dstRB);
+ } while (--height);
+ } else {
+ do {
+ shader->shadeSpan(x, y, buffer, width);
+ proc(dst, buffer, width, 0xFF, x, y);
+ y += 1;
+ dst = (uint16_t*)((char*)dst + dstRB);
+ } while (--height);
+ }
+}
+
static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
int count = 0;
for (;;) {
diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h
index 5b3497e089..8f9cfc36f9 100644
--- a/src/core/SkCoreBlitters.h
+++ b/src/core/SkCoreBlitters.h
@@ -38,7 +38,8 @@ public:
virtual ~SkShaderBlitter();
protected:
- SkShader* fShader;
+ uint32_t fShaderFlags;
+ SkShader* fShader;
private:
// illegal
@@ -192,7 +193,8 @@ public:
virtual ~SkRGB16_Shader_Blitter();
virtual void blitH(int x, int y, int width);
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
-
+ virtual void blitRect(int x, int y, int width, int height);
+
protected:
SkPMColor* fBuffer;
SkBlitRow::Proc fOpaqueProc;
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index dd9c8590b8..5567914530 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -210,6 +210,7 @@ SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
#include "SkUtils.h"
SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
+ fFlags = 0; // computed in setContext
fInheritColor = b.readU8();
if (fInheritColor) {
return;
@@ -226,11 +227,6 @@ void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
buffer.write32(fColor);
}
-uint32_t SkColorShader::getFlags() {
- return (SkGetPackedA32(fPMColor) == 255 ? kOpaqueAlpha_Flag : 0) |
- kHasSpan16_Flag;
-}
-
uint8_t SkColorShader::getSpan16Alpha() const {
return SkGetPackedA32(fPMColor);
}
@@ -267,6 +263,11 @@ bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
}
fPMColor = SkPackARGB32(a, r, g, b);
+ fFlags = kHasSpan16_Flag | kConstInY_Flag;
+ if (SkGetPackedA32(fPMColor) == 255) {
+ fFlags |= kOpaqueAlpha_Flag;
+ }
+
return true;
}
diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp
index 87d70c23b0..e1a92ba3bf 100644
--- a/src/effects/SkGradientShader.cpp
+++ b/src/effects/SkGradientShader.cpp
@@ -620,6 +620,7 @@ public:
}
}
+ virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*);
@@ -646,6 +647,19 @@ private:
typedef Gradient_Shader INHERITED;
};
+bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
+ const SkMatrix& matrix) {
+ if (!this->INHERITED::setContext(device, paint, matrix)) {
+ return false;
+ }
+
+ unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
+ if ((fDstToIndex.getType() & ~mask) == 0) {
+ fFlags |= SkShader::kConstInY_Flag;
+ }
+ return true;
+}
+
// Return true if fx, fx+dx, fx+2*dx, ... is always in range
static inline bool no_need_for_clamp(int fx, int dx, int count)
{
diff --git a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
index d3679c4824..c67031436d 100644
--- a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
+++ b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
@@ -71,7 +71,7 @@
00A728270FD43D0400D5051F /* SampleMovie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F6760FCCCB01002BD8B4 /* SampleMovie.cpp */; };
00A7282F0FD43D3700D5051F /* SkMovie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A7282D0FD43D3700D5051F /* SkMovie.cpp */; };
00A7295D0FD8397600D5051F /* SampleAll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F6740FCCCB01002BD8B4 /* SampleAll.cpp */; };
- 00A729650FD93ED600D5051F /* SampleTestGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A729630FD93ED600D5051F /* SampleTestGL.cpp */; };
+ 00AF77B00FE2EA2D007F9650 /* SampleTestGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A729630FD93ED600D5051F /* SampleTestGL.cpp */; };
00C55DA10F8552DC000CAC09 /* SampleGradients.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C55DA00F8552DC000CAC09 /* SampleGradients.cpp */; };
00FF39140FC6ED2C00915187 /* SampleEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FF39130FC6ED2C00915187 /* SampleEffects.cpp */; };
0156F80407C56A3000C6122B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0156F80307C56A3000C6122B /* Foundation.framework */; };
@@ -569,8 +569,8 @@
00A728270FD43D0400D5051F /* SampleMovie.cpp in Sources */,
00A7282F0FD43D3700D5051F /* SkMovie.cpp in Sources */,
00A7295D0FD8397600D5051F /* SampleAll.cpp in Sources */,
- 00A729650FD93ED600D5051F /* SampleTestGL.cpp in Sources */,
000A99820FD97526007E45BD /* SampleArc.cpp in Sources */,
+ 00AF77B00FE2EA2D007F9650 /* SampleTestGL.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};