1165d1422625c7f0f6522e8e5951afad806c32ea
[platform/upstream/libSkiaSharp.git] / src / image / SkImage_Raster.cpp
1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkImage_Base.h"
9 #include "SkBitmap.h"
10 #include "SkCanvas.h"
11 #include "SkData.h"
12 #include "SkImageGenerator.h"
13 #include "SkImagePriv.h"
14 #include "SkPixelRef.h"
15 #include "SkSurface.h"
16
17 class SkImage_Raster : public SkImage_Base {
18 public:
19     static bool ValidArgs(const Info& info, size_t rowBytes) {
20         const int maxDimension = SK_MaxS32 >> 2;
21         const size_t kMaxPixelByteSize = SK_MaxS32;
22
23         if (info.width() <= 0 || info.height() <= 0) {
24             return false;
25         }
26         if (info.width() > maxDimension || info.height() > maxDimension) {
27             return false;
28         }
29         if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
30             return false;
31         }
32         if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
33             return false;
34         }
35
36         if (kUnknown_SkColorType == info.colorType()) {
37             return false;
38         }
39
40         // TODO: check colorspace
41
42         if (rowBytes < SkImageMinRowBytes(info)) {
43             return false;
44         }
45
46         int64_t size = (int64_t)info.height() * rowBytes;
47         if (size > (int64_t)kMaxPixelByteSize) {
48             return false;
49         }
50         return true;
51     }
52
53     SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, const SkSurfaceProps*);
54     virtual ~SkImage_Raster();
55
56     void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) const SK_OVERRIDE;
57     void onDrawRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) const SK_OVERRIDE;
58     SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const SK_OVERRIDE;
59     bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const SK_OVERRIDE;
60     const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
61     bool getROPixels(SkBitmap*) const SK_OVERRIDE;
62
63     // exposed for SkSurface_Raster via SkNewImageFromPixelRef
64     SkImage_Raster(const SkImageInfo&, SkPixelRef*, const SkIPoint& pixelRefOrigin, size_t rowBytes,
65                    const SkSurfaceProps*);
66
67     SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
68
69     virtual SkShader* onNewShader(SkShader::TileMode,
70                                   SkShader::TileMode,
71                                   const SkMatrix* localMatrix) const SK_OVERRIDE;
72
73     bool isOpaque() const SK_OVERRIDE;
74
75     SkImage_Raster(const SkBitmap& bm, const SkSurfaceProps* props)
76         : INHERITED(bm.width(), bm.height(), props)
77         , fBitmap(bm) {}
78
79 private:
80     SkImage_Raster() : INHERITED(0, 0, NULL) {}
81
82     SkBitmap    fBitmap;
83
84     typedef SkImage_Base INHERITED;
85 };
86
87 ///////////////////////////////////////////////////////////////////////////////
88
89 static void release_data(void* addr, void* context) {
90     SkData* data = static_cast<SkData*>(context);
91     data->unref();
92 }
93
94 SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes,
95                                const SkSurfaceProps* props)
96     : INHERITED(info.width(), info.height(), props)
97 {
98     data->ref();
99     void* addr = const_cast<void*>(data->data());
100     SkColorTable* ctable = NULL;
101
102     fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
103     fBitmap.setImmutable();
104     fBitmap.lockPixels();
105 }
106
107 SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, const SkIPoint& pixelRefOrigin,
108                                size_t rowBytes,  const SkSurfaceProps* props)
109     : INHERITED(info.width(), info.height(), props)
110 {
111     fBitmap.setInfo(info, rowBytes);
112     fBitmap.setPixelRef(pr, pixelRefOrigin);
113     fBitmap.lockPixels();
114 }
115
116 SkImage_Raster::~SkImage_Raster() {}
117
118 SkShader* SkImage_Raster::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY,
119                                       const SkMatrix* localMatrix) const {
120     return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix);
121 }
122
123 void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
124     SkBitmap shallowCopy(fBitmap);
125     canvas->drawBitmap(shallowCopy, x, y, paint);
126 }
127
128 void SkImage_Raster::onDrawRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
129                                       const SkPaint* paint) const {
130     SkBitmap shallowCopy(fBitmap);
131     canvas->drawBitmapRectToRect(shallowCopy, src, dst, paint);
132 }
133
134 SkSurface* SkImage_Raster::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
135     return SkSurface::NewRaster(info, &props);
136 }
137
138 bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
139                                   int srcX, int srcY) const {
140     SkBitmap shallowCopy(fBitmap);
141     return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
142 }
143
144 const void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr, size_t* rowBytesPtr) const {
145     const SkImageInfo info = fBitmap.info();
146     if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
147         return NULL;
148     }
149     *infoPtr = info;
150     *rowBytesPtr = fBitmap.rowBytes();
151     return fBitmap.getPixels();
152 }
153
154 bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
155     *dst = fBitmap;
156     return true;
157 }
158
159 ///////////////////////////////////////////////////////////////////////////////
160
161 SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
162     if (!SkImage_Raster::ValidArgs(info, rowBytes) || !pixels) {
163         return NULL;
164     }
165
166     // Here we actually make a copy of the caller's pixel data
167     SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.height() * rowBytes));
168     return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
169 }
170
171
172 SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
173     if (!SkImage_Raster::ValidArgs(info, rowBytes) || !data) {
174         return NULL;
175     }
176
177     // did they give us enough data?
178     size_t size = info.height() * rowBytes;
179     if (data->size() < size) {
180         return NULL;
181     }
182
183     return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
184 }
185
186 SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
187     SkBitmap bitmap;
188     if (!SkInstallDiscardablePixelRef(generator, &bitmap)) {
189         return NULL;
190     }
191     if (0 == bitmap.width() || 0 == bitmap.height()) {
192         return NULL;
193     }
194
195     return SkNEW_ARGS(SkImage_Raster, (bitmap, NULL));
196 }
197
198 SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
199                                 const SkIPoint& pixelRefOrigin, size_t rowBytes,
200                                 const SkSurfaceProps* props) {
201     if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
202         return NULL;
203     }
204     return SkNEW_ARGS(SkImage_Raster, (info, pr, pixelRefOrigin, rowBytes, props));
205 }
206
207 SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef,
208                               const SkSurfaceProps* props) {
209     if (!SkImage_Raster::ValidArgs(bm.info(), bm.rowBytes())) {
210         return NULL;
211     }
212
213     SkImage* image = NULL;
214     if (canSharePixelRef || bm.isImmutable()) {
215         image = SkNEW_ARGS(SkImage_Raster, (bm, props));
216     } else {
217         bm.lockPixels();
218         if (bm.getPixels()) {
219             image = SkImage::NewRasterCopy(bm.info(), bm.getPixels(), bm.rowBytes());
220         }
221         bm.unlockPixels();
222
223         // we don't expose props to NewRasterCopy (need a private vers) so post-init it here
224         if (image && props) {
225             as_IB(image)->initWithProps(*props);
226         }
227     }
228     return image;
229 }
230
231 const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
232     return ((const SkImage_Raster*)image)->getPixelRef();
233 }
234
235 bool SkImage_Raster::isOpaque() const {
236     return fBitmap.isOpaque();
237 }
238