aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/image')
-rw-r--r--src/image/SkImageShader.cpp109
-rw-r--r--src/image/SkImageShader.h7
2 files changed, 108 insertions, 8 deletions
diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp
index 12caa7a3d2..a486f71dfd 100644
--- a/src/image/SkImageShader.cpp
+++ b/src/image/SkImageShader.cpp
@@ -7,6 +7,9 @@
#include "SkBitmapProcShader.h"
#include "SkBitmapProvider.h"
+#include "SkColorShader.h"
+#include "SkColorTable.h"
+#include "SkEmptyShader.h"
#include "SkImage_Base.h"
#include "SkImageShader.h"
#include "SkReadBuffer.h"
@@ -43,11 +46,11 @@ bool SkImageShader::isOpaque() const {
}
size_t SkImageShader::onContextSize(const ContextRec& rec) const {
- return SkBitmapProcShader::ContextSize(rec, SkBitmapProvider(fImage).info());
+ return SkBitmapProcLegacyShader::ContextSize(rec, SkBitmapProvider(fImage).info());
}
SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const {
- return SkBitmapProcShader::MakeContext(*this, fTileModeX, fTileModeY,
+ return SkBitmapProcLegacyShader::MakeContext(*this, fTileModeX, fTileModeY,
SkBitmapProvider(fImage), rec, storage);
}
@@ -81,12 +84,76 @@ bool SkImageShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode xy[]
return true;
}
+static bool bitmap_is_too_big(int w, int h) {
+ // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
+ // communicates between its matrix-proc and its sampler-proc. Until we can
+ // widen that, we have to reject bitmaps that are larger.
+ //
+ static const int kMaxSize = 65535;
+
+ return w > kMaxSize || h > kMaxSize;
+}
+
+// returns true and set color if the bitmap can be drawn as a single color
+// (for efficiency)
+static bool can_use_color_shader(const SkImage* image, SkColor* color) {
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ // HWUI does not support color shaders (see b/22390304)
+ return false;
+#endif
+
+ if (1 != image->width() || 1 != image->height()) {
+ return false;
+ }
+
+ SkPixmap pmap;
+ if (!image->peekPixels(&pmap)) {
+ return false;
+ }
+
+ switch (pmap.colorType()) {
+ case kN32_SkColorType:
+ *color = SkUnPreMultiply::PMColorToColor(*pmap.addr32(0, 0));
+ return true;
+ case kRGB_565_SkColorType:
+ *color = SkPixel16ToColor(*pmap.addr16(0, 0));
+ return true;
+ case kIndex_8_SkColorType: {
+ const SkColorTable& ctable = *pmap.ctable();
+ *color = SkUnPreMultiply::PMColorToColor(ctable[*pmap.addr8(0, 0)]);
+ return true;
+ }
+ default: // just skip the other configs for now
+ break;
+ }
+ return false;
+}
+
sk_sp<SkShader> SkImageShader::Make(const SkImage* image, TileMode tx, TileMode ty,
- const SkMatrix* localMatrix) {
- if (!image) {
- return nullptr;
+ const SkMatrix* localMatrix,
+ SkTBlitterAllocator* allocator) {
+ SkShader* shader;
+ SkColor color;
+ if (!image || bitmap_is_too_big(image->width(), image->height())) {
+ if (nullptr == allocator) {
+ shader = new SkEmptyShader;
+ } else {
+ shader = allocator->createT<SkEmptyShader>();
+ }
+ } else if (can_use_color_shader(image, &color)) {
+ if (nullptr == allocator) {
+ shader = new SkColorShader(color);
+ } else {
+ shader = allocator->createT<SkColorShader>(color);
+ }
+ } else {
+ if (nullptr == allocator) {
+ shader = new SkImageShader(image, tx, ty, localMatrix);
+ } else {
+ shader = allocator->createT<SkImageShader>(image, tx, ty, localMatrix);
+ }
}
- return sk_sp<SkShader>(new SkImageShader(image, tx, ty, localMatrix));
+ return sk_sp<SkShader>(shader);
}
#ifndef SK_IGNORE_TO_STRING
@@ -161,3 +228,33 @@ sk_sp<GrFragmentProcessor> SkImageShader::asFragmentProcessor(const AsFPArgs& ar
}
#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+#include "SkImagePriv.h"
+
+sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
+ SkShader::TileMode tmy, const SkMatrix* localMatrix,
+ SkTBlitterAllocator* allocator) {
+ ForceCopyMode mode = allocator ? kNever_ForceCopyMode : kNo_ForceCopyMode;
+ return SkImageShader::Make(SkMakeImageFromRasterBitmap(src, mode).get(),
+ tmx, tmy, localMatrix, allocator);
+}
+
+static sk_sp<SkFlattenable> SkBitmapProcShader_CreateProc(SkReadBuffer& buffer) {
+ SkMatrix lm;
+ buffer.readMatrix(&lm);
+ SkBitmap bm;
+ if (!buffer.readBitmap(&bm)) {
+ return nullptr;
+ }
+ bm.setImmutable();
+ SkShader::TileMode mx = (SkShader::TileMode)buffer.readUInt();
+ SkShader::TileMode my = (SkShader::TileMode)buffer.readUInt();
+ return SkShader::MakeBitmapShader(bm, mx, my, &lm);
+}
+
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShader)
+SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageShader)
+SkFlattenable::Register("SkBitmapProcShader", SkBitmapProcShader_CreateProc, kSkShader_Type);
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
+
diff --git a/src/image/SkImageShader.h b/src/image/SkImageShader.h
index 160de7ac9c..e9911e6c25 100644
--- a/src/image/SkImageShader.h
+++ b/src/image/SkImageShader.h
@@ -10,11 +10,12 @@
#include "SkImage.h"
#include "SkShader.h"
+#include "SkBitmapProcShader.h"
class SkImageShader : public SkShader {
public:
static sk_sp<SkShader> Make(const SkImage*, TileMode tx, TileMode ty,
- const SkMatrix* localMatrix);
+ const SkMatrix* localMatrix, SkTBlitterAllocator* = nullptr);
bool isOpaque() const override;
@@ -25,6 +26,8 @@ public:
sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
#endif
+ SkImageShader(const SkImage*, TileMode tx, TileMode ty, const SkMatrix* localMatrix);
+
protected:
void flatten(SkWriteBuffer&) const override;
size_t onContextSize(const ContextRec&) const override;
@@ -37,7 +40,7 @@ protected:
const TileMode fTileModeY;
private:
- SkImageShader(const SkImage*, TileMode tx, TileMode ty, const SkMatrix* localMatrix);
+ friend class SkShader;
typedef SkShader INHERITED;
};