aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/image
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-27 21:10:42 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-27 21:10:42 +0000
commit889b09edfeb5f461ca283dfd08ee6b23560a7859 (patch)
tree4c1c5a9edb63f938bbaec013c7ea6854a7669eeb /src/image
parent2092c40a0d0a89a91cc4b6bb2b1b992fd4f02cd7 (diff)
check-point for surface experiment
git-svn-id: http://skia.googlecode.com/svn/trunk@4819 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/image')
-rw-r--r--src/image/SkImage.cpp97
-rw-r--r--src/image/SkImagePriv.cpp109
-rw-r--r--src/image/SkImagePriv.h27
-rw-r--r--src/image/SkSurface.cpp173
4 files changed, 336 insertions, 70 deletions
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 0573a83836..4d96b9ffff 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -1,5 +1,5 @@
#include "SkImage.h"
-
+#include "SkImagePriv.h"
#include "SkBitmap.h"
///////////////////////////////////////////////////////////////////////////////
@@ -20,70 +20,6 @@ static SkImage_Base* asIB(SkImage* image) {
///////////////////////////////////////////////////////////////////////////////
-static SkBitmap::Config InfoToConfig(const SkImage::Info& info, bool* isOpaque) {
- switch (info.fColorType) {
- case SkImage::kAlpha_8_ColorType:
- switch (info.fAlphaType) {
- case SkImage::kIgnore_AlphaType:
- // makes no sense
- return SkBitmap::kNo_Config;
-
- case SkImage::kOpaque_AlphaType:
- *isOpaque = true;
- return SkBitmap::kA8_Config;
-
- case SkImage::kPremul_AlphaType:
- case SkImage::kUnpremul_AlphaType:
- *isOpaque = false;
- return SkBitmap::kA8_Config;
- }
- break;
-
- case SkImage::kRGB_565_ColorType:
- // we ignore fAlpahType, though some would not make sense
- *isOpaque = true;
- return SkBitmap::kRGB_565_Config;
-
- case SkImage::kRGBA_8888_ColorType:
- case SkImage::kBGRA_8888_ColorType:
- // not supported yet
- return SkBitmap::kNo_Config;
-
- case SkImage::kPMColor_ColorType:
- switch (info.fAlphaType) {
- case SkImage::kIgnore_AlphaType:
- case SkImage::kUnpremul_AlphaType:
- // not supported yet
- return SkBitmap::kNo_Config;
- case SkImage::kOpaque_AlphaType:
- *isOpaque = true;
- return SkBitmap::kARGB_8888_Config;
- case SkImage::kPremul_AlphaType:
- *isOpaque = false;
- return SkBitmap::kARGB_8888_Config;
- }
- break;
- }
- SkASSERT(!"how did we get here");
- return SkBitmap::kNo_Config;
-}
-
-static int BytesPerPixel(SkImage::ColorType ct) {
- static const uint8_t gColorTypeBytesPerPixel[] = {
- 1, // kAlpha_8_ColorType
- 2, // kRGB_565_ColorType
- 4, // kRGBA_8888_ColorType
- 4, // kBGRA_8888_ColorType
- 4, // kPMColor_ColorType
- };
-
- SkASSERT((size_t)ct < SK_ARRAY_COUNT(gColorTypeBytesPerPixel));
- return gColorTypeBytesPerPixel[ct];
-}
-
-static size_t ComputeMinRowBytes(const SkImage::Info& info) {
- return info.fWidth * BytesPerPixel(info.fColorType);
-}
class SkImage_Raster : public SkImage_Base {
public:
@@ -105,13 +41,13 @@ public:
}
bool isOpaque;
- if (InfoToConfig(info, &isOpaque) == SkBitmap::kNo_Config) {
+ if (SkImageInfoToBitmapConfig(info, &isOpaque) == SkBitmap::kNo_Config) {
return false;
}
// TODO: check colorspace
- if (rowBytes < ComputeMinRowBytes(info)) {
+ if (rowBytes < SkImageMinRowBytes(info)) {
return false;
}
@@ -129,6 +65,9 @@ public:
virtual const SkBitmap* asABitmap() SK_OVERRIDE;
+ // exposed for SkSurface_Raster via SkNewImageFromPixelRef
+ SkImage_Raster(const SkImage::Info&, SkPixelRef*, size_t rowBytes);
+
private:
SkImage_Raster() : INHERITED(0, 0) {}
@@ -137,6 +76,11 @@ private:
typedef SkImage_Base INHERITED;
};
+SkImage* SkNewImageFromPixelRef(const SkImage::Info& info, SkPixelRef* pr,
+ size_t rowBytes) {
+ return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes));
+}
+
///////////////////////////////////////////////////////////////////////////////
#include "SkData.h"
@@ -154,14 +98,27 @@ SkImage* SkImage_Raster::NewEmpty() {
SkImage_Raster::SkImage_Raster(const Info& info, SkColorSpace* cs,
SkData* data, size_t rowBytes)
+: INHERITED(info.fWidth, info.fHeight) {
+ bool isOpaque;
+ SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
+
+ fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes);
+ fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
+ fBitmap.setIsOpaque(isOpaque);
+ fBitmap.setImmutable();
+}
+
+SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
: INHERITED(info.fWidth, info.fHeight) {
+ SkASSERT(pr->isImmutable());
+
bool isOpaque;
- SkBitmap::Config config = InfoToConfig(info, &isOpaque);
+ SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes);
- fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
+ fBitmap.setPixelRef(pr);
fBitmap.setIsOpaque(isOpaque);
- fBitmap.setImmutable(); // Yea baby!
+ fBitmap.setImmutable();
}
SkImage_Raster::~SkImage_Raster() {}
diff --git a/src/image/SkImagePriv.cpp b/src/image/SkImagePriv.cpp
new file mode 100644
index 0000000000..d0c56fd2ef
--- /dev/null
+++ b/src/image/SkImagePriv.cpp
@@ -0,0 +1,109 @@
+#include "SkImagePriv.h"
+
+SkBitmap::Config SkImageInfoToBitmapConfig(const SkImage::Info& info,
+ bool* isOpaque) {
+ switch (info.fColorType) {
+ case SkImage::kAlpha_8_ColorType:
+ switch (info.fAlphaType) {
+ case SkImage::kIgnore_AlphaType:
+ // makes no sense
+ return SkBitmap::kNo_Config;
+
+ case SkImage::kOpaque_AlphaType:
+ *isOpaque = true;
+ return SkBitmap::kA8_Config;
+
+ case SkImage::kPremul_AlphaType:
+ case SkImage::kUnpremul_AlphaType:
+ *isOpaque = false;
+ return SkBitmap::kA8_Config;
+ }
+ break;
+
+ case SkImage::kRGB_565_ColorType:
+ // we ignore fAlpahType, though some would not make sense
+ *isOpaque = true;
+ return SkBitmap::kRGB_565_Config;
+
+ case SkImage::kRGBA_8888_ColorType:
+ case SkImage::kBGRA_8888_ColorType:
+ // not supported yet
+ return SkBitmap::kNo_Config;
+
+ case SkImage::kPMColor_ColorType:
+ switch (info.fAlphaType) {
+ case SkImage::kIgnore_AlphaType:
+ case SkImage::kUnpremul_AlphaType:
+ // not supported yet
+ return SkBitmap::kNo_Config;
+ case SkImage::kOpaque_AlphaType:
+ *isOpaque = true;
+ return SkBitmap::kARGB_8888_Config;
+ case SkImage::kPremul_AlphaType:
+ *isOpaque = false;
+ return SkBitmap::kARGB_8888_Config;
+ }
+ break;
+ }
+ SkASSERT(!"how did we get here");
+ return SkBitmap::kNo_Config;
+}
+
+int SkImageBytesPerPixel(SkImage::ColorType ct) {
+ static const uint8_t gColorTypeBytesPerPixel[] = {
+ 1, // kAlpha_8_ColorType
+ 2, // kRGB_565_ColorType
+ 4, // kRGBA_8888_ColorType
+ 4, // kBGRA_8888_ColorType
+ 4, // kPMColor_ColorType
+ };
+
+ SkASSERT((size_t)ct < SK_ARRAY_COUNT(gColorTypeBytesPerPixel));
+ return gColorTypeBytesPerPixel[ct];
+}
+
+bool SkBitmapToImageInfo(const SkBitmap& bm, SkImage::Info* info) {
+ switch (bm.config()) {
+ case SkBitmap::kA8_Config:
+ info->fColorType = SkImage::kAlpha_8_ColorType;
+ break;
+
+ case SkBitmap::kRGB_565_Config:
+ info->fColorType = SkImage::kRGB_565_ColorType;
+ break;
+
+ case SkBitmap::kARGB_8888_Config:
+ info->fColorType = SkImage::kPMColor_ColorType;
+ break;
+
+ default:
+ return false;
+ }
+
+ info->fWidth = bm.width();
+ info->fHeight = bm.height();
+ info->fAlphaType = bm.isOpaque() ? SkImage::kOpaque_AlphaType :
+ SkImage::kPremul_AlphaType;
+ return true;
+}
+
+SkImage* SkNewImageFromBitmap(const SkBitmap& bm) {
+ SkImage::Info info;
+ if (!SkBitmapToImageInfo(bm, &info)) {
+ return NULL;
+ }
+
+ SkImage* image = NULL;
+ if (bm.isImmutable()) {
+ image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes());
+ } else {
+ bm.lockPixels();
+ if (NULL == bm.getPixels()) {
+ image = SkImage::NewRasterCopy(info, NULL, bm.getPixels(),
+ bm.rowBytes());
+ }
+ bm.unlockPixels();
+ }
+ return image;
+}
+
diff --git a/src/image/SkImagePriv.h b/src/image/SkImagePriv.h
new file mode 100644
index 0000000000..1c732c3b9f
--- /dev/null
+++ b/src/image/SkImagePriv.h
@@ -0,0 +1,27 @@
+
+#ifndef SkImagePriv_DEFINED
+#define SkImagePriv_DEFINED
+
+#include "SkBitmap.h"
+#include "SkImage.h"
+
+extern SkBitmap::Config SkImageInfoToBitmapConfig(const SkImage::Info&,
+ bool* isOpaque);
+
+extern int SkImageBytesPerPixel(SkImage::ColorType);
+
+extern bool SkBitmapToImageInfo(const SkBitmap&, SkImage::Info*);
+extern SkImage* SkNewImageFromPixelRef(const SkImage::Info&, SkPixelRef*,
+ size_t rowBytes);
+
+/**
+ * Examines the bitmap to decide if it can share the existing pixelRef, or
+ * if it needs to make a deep-copy of the pixels
+ */
+extern SkImage* SkNewImageFromBitmap(const SkBitmap&);
+
+static inline size_t SkImageMinRowBytes(const SkImage::Info& info) {
+ return info.fWidth * SkImageBytesPerPixel(info.fColorType);
+}
+
+#endif
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
new file mode 100644
index 0000000000..2a9e33a8e2
--- /dev/null
+++ b/src/image/SkSurface.cpp
@@ -0,0 +1,173 @@
+#include "SkSurface.h"
+#include "SkImagePriv.h"
+#include "SkCanvas.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkSurface_Base : public SkSurface {
+public:
+ SkSurface_Base(int width, int height) : INHERITED(width, height) {}
+
+ virtual SkCanvas* onNewCanvas() = 0;
+ virtual SkSurface* onNewSurface(const SkImage::Info&, SkColorSpace*) = 0;
+ virtual SkImage* onNewImageShapshot() = 0;
+
+ /**
+ * Default implementation:
+ *
+ * image = this->newImageSnapshot();
+ * if (image) {
+ * image->draw(canvas, ...);
+ * image->unref();
+ * }
+ */
+ virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+
+private:
+ typedef SkSurface INHERITED;
+};
+
+void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ SkImage* image = this->newImageShapshot();
+ if (image) {
+ image->draw(canvas, x, y, paint);
+ image->unref();
+ }
+}
+
+static SkSurface_Base* asSB(SkSurface* surface) {
+ return static_cast<SkSurface_Base*>(surface);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
+ SkASSERT(width >= 0);
+ SkASSERT(height >= 0);
+ fGenerationID = 0;
+}
+
+SkCanvas* SkSurface::newCanvas() {
+ return asSB(this)->onNewCanvas();
+}
+
+SkSurface* SkSurface::newSurface(const SkImage::Info& info, SkColorSpace* cs) {
+ return asSB(this)->onNewSurface(info, cs);
+}
+
+SkImage* SkSurface::newImageShapshot() {
+ return asSB(this)->onNewImageShapshot();
+}
+
+void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ return asSB(this)->onDraw(canvas, x, y, paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkSurface_Raster : public SkSurface {
+public:
+ static bool Valid(const SkImage::Info&, SkColorSpace*, size_t rb);
+
+ SkSurface_Raster(const SkImage::Info&, SkColorSpace*, void*, size_t rb);
+
+ virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
+ virtual SkSurface* onNewSurface(const SkImage::Info&, SkColorSpace*) SK_OVERRIDE;
+ virtual SkImage* onNewImageShapshot() SK_OVERRIDE;
+ virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
+ const SkPaint*) SK_OVERRIDE;
+
+private:
+ SkBitmap fBitmap;
+
+ typedef SkSurface INHERITED;
+};
+
+bool SkSurface_Raster::Valid(const SkImage::Info& info, SkColorSpace* cs,
+ size_t rowBytes) {
+ static size_t kMaxTotalSize = (1 << 31) - 1;
+
+ bool isOpaque;
+ SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
+
+ int shift = 0;
+ switch (config) {
+ case SkBitmap::kA8_Config:
+ shift = 0;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ shift = 1;
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ shift = 2;
+ break;
+ default:
+ return false;
+ }
+
+ // TODO: examine colorspace
+
+ uint64_t minRB = (uint64_t)info.fWidth << shift;
+ if (minRB > rowBytes) {
+ return false;
+ }
+
+ size_t alignedRowBytes = rowBytes >> shift << shift;
+ if (alignedRowBytes != rowBytes) {
+ return false;
+ }
+
+ uint64_t size = (uint64_t)info.fHeight * rowBytes;
+ if (size > kMaxTotalSize) {
+ return false;
+ }
+
+ return true;
+}
+
+SkSurface_Raster::SkSurface_Raster(const SkImage::Info& info, SkColorSpace* cs,
+ void* pixels, size_t rb)
+ : INHERITED(info.fWidth, info.fHeight) {
+ bool isOpaque;
+ SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
+
+ fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
+ fBitmap.setPixels(pixels);
+ fBitmap.setIsOpaque(isOpaque);
+}
+
+SkCanvas* SkSurface_Raster::onNewCanvas() {
+ return SkNEW_ARGS(SkCanvas, (fBitmap));
+}
+
+SkSurface* SkSurface_Raster::onNewSurface(const SkImage::Info& info,
+ SkColorSpace* cs) {
+ return SkSurface::NewRaster(info, cs);
+}
+
+SkImage* SkSurface_Raster::onNewImageShapshot() {
+ return SkNewImageFromBitmap(fBitmap);
+}
+
+void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ canvas->drawBitmap(fBitmap, x, y, paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkSurface* SkSurface::NewRasterDirect(const SkImage::Info& info,
+ SkColorSpace* cs,
+ void* pixels, size_t rowBytes) {
+ if (!SkSurface_Raster::Valid(info, cs, rowBytes)) {
+ return NULL;
+ }
+ if (NULL == pixels) {
+ return NULL;
+ }
+
+ return SkNEW_ARGS(SkSurface_Raster, (info, cs, pixels, rowBytes));
+}
+