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 "SkImagePriv.h"
10#include "SkBitmap.h"
11#include "SkCanvas.h"
12#include "SkData.h"
13#include "SkDecodingImageGenerator.h"
14
15class SkImage_Raster : public SkImage_Base {
16public:
17    static bool ValidArgs(const Info& info, size_t rowBytes) {
18        const int maxDimension = SK_MaxS32 >> 2;
19        const size_t kMaxPixelByteSize = SK_MaxS32;
20
21        if (info.width() < 0 || info.height() < 0) {
22            return false;
23        }
24        if (info.width() > maxDimension || info.height() > maxDimension) {
25            return false;
26        }
27        if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
28            return false;
29        }
30        if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
31            return false;
32        }
33
34        if (kUnknown_SkColorType == info.colorType()) {
35            return false;
36        }
37
38        // TODO: check colorspace
39
40        if (rowBytes < SkImageMinRowBytes(info)) {
41            return false;
42        }
43
44        int64_t size = (int64_t)info.height() * rowBytes;
45        if (size > (int64_t)kMaxPixelByteSize) {
46            return false;
47        }
48        return true;
49    }
50
51    static SkImage* NewEmpty();
52
53    SkImage_Raster(const SkImageInfo&, SkData*, size_t rb);
54    virtual ~SkImage_Raster();
55
56    virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) const SK_OVERRIDE;
57    virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&,
58                                  const SkPaint*) const SK_OVERRIDE;
59    virtual bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE;
60    virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
61    virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
62
63    // exposed for SkSurface_Raster via SkNewImageFromPixelRef
64    SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes);
65
66    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
67
68    virtual SkShader* onNewShader(SkShader::TileMode,
69                                  SkShader::TileMode,
70                                  const SkMatrix* localMatrix) const SK_OVERRIDE;
71
72    virtual bool isOpaque() const SK_OVERRIDE;
73
74    SkImage_Raster(const SkBitmap& bm)
75        : INHERITED(bm.width(), bm.height())
76        , fBitmap(bm) {}
77
78private:
79    SkImage_Raster() : INHERITED(0, 0) {}
80
81    SkBitmap    fBitmap;
82
83    typedef SkImage_Base INHERITED;
84};
85
86///////////////////////////////////////////////////////////////////////////////
87
88SkImage* SkImage_Raster::NewEmpty() {
89    // Returns lazily created singleton
90    static SkImage* gEmpty;
91    if (NULL == gEmpty) {
92        gEmpty = SkNEW(SkImage_Raster);
93    }
94    gEmpty->ref();
95    return gEmpty;
96}
97
98static void release_data(void* addr, void* context) {
99    SkData* data = static_cast<SkData*>(context);
100    data->unref();
101}
102
103SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
104    : INHERITED(info.width(), info.height())
105{
106    data->ref();
107    void* addr = const_cast<void*>(data->data());
108    SkColorTable* ctable = NULL;
109
110    fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
111    fBitmap.setImmutable();
112    fBitmap.lockPixels();
113}
114
115SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
116    : INHERITED(info.width(), info.height())
117{
118    fBitmap.setInfo(info, rowBytes);
119    fBitmap.setPixelRef(pr);
120    fBitmap.lockPixels();
121}
122
123SkImage_Raster::~SkImage_Raster() {}
124
125SkShader* SkImage_Raster::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY,
126                                      const SkMatrix* localMatrix) const {
127    return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix);
128}
129
130void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
131    canvas->drawBitmap(fBitmap, x, y, paint);
132}
133
134void SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
135                                      const SkPaint* paint) const {
136    canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
137}
138
139bool SkImage_Raster::onReadPixels(SkBitmap* dst, const SkIRect& subset) const {
140    if (dst->pixelRef()) {
141        return this->INHERITED::onReadPixels(dst, subset);
142    } else {
143        SkBitmap src;
144        if (!fBitmap.extractSubset(&src, subset)) {
145            return false;
146        }
147        return src.copyTo(dst, src.colorType());
148    }
149}
150
151const void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr, size_t* rowBytesPtr) const {
152    const SkImageInfo info = fBitmap.info();
153    if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
154        return NULL;
155    }
156    *infoPtr = info;
157    *rowBytesPtr = fBitmap.rowBytes();
158    return fBitmap.getPixels();
159}
160
161bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
162    *dst = fBitmap;
163    return true;
164}
165
166///////////////////////////////////////////////////////////////////////////////
167
168SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
169    if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
170        return NULL;
171    }
172    if (0 == info.width() && 0 == info.height()) {
173        return SkImage_Raster::NewEmpty();
174    }
175    // check this after empty-check
176    if (NULL == pixels) {
177        return NULL;
178    }
179
180    // Here we actually make a copy of the caller's pixel data
181    SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.height() * rowBytes));
182    return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
183}
184
185
186SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
187    if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
188        return NULL;
189    }
190    if (0 == info.width() && 0 == info.height()) {
191        return SkImage_Raster::NewEmpty();
192    }
193    // check this after empty-check
194    if (NULL == data) {
195        return NULL;
196    }
197
198    // did they give us enough data?
199    size_t size = info.height() * rowBytes;
200    if (data->size() < size) {
201        return NULL;
202    }
203
204    return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
205}
206
207SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
208    SkBitmap bitmap;
209    if (!SkInstallDiscardablePixelRef(generator, &bitmap)) {
210        return NULL;
211    }
212    return SkNEW_ARGS(SkImage_Raster, (bitmap));
213}
214
215SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
216                                size_t rowBytes) {
217    return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes));
218}
219
220SkPixelRef* SkBitmapImageGetPixelRef(SkImage* image) {
221    return ((SkImage_Raster*)image)->getPixelRef();
222}
223
224bool SkImage_Raster::isOpaque() const {
225    return fBitmap.isOpaque();
226}
227