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 "SkMallocPixelRef.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.fWidth < 0 || info.fHeight < 0) {
22            return false;
23        }
24        if (info.fWidth > maxDimension || info.fHeight > maxDimension) {
25            return false;
26        }
27        if ((unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType) {
28            return false;
29        }
30        if ((unsigned)info.fAlphaType > (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.fHeight * 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*) SK_OVERRIDE;
57    virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) SK_OVERRIDE;
58    virtual bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE;
59    virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
60    virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
61
62    // exposed for SkSurface_Raster via SkNewImageFromPixelRef
63    SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes);
64
65    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
66
67private:
68    SkImage_Raster() : INHERITED(0, 0) {}
69
70    SkBitmap    fBitmap;
71
72    typedef SkImage_Base INHERITED;
73};
74
75///////////////////////////////////////////////////////////////////////////////
76
77SkImage* SkImage_Raster::NewEmpty() {
78    // Returns lazily created singleton
79    static SkImage* gEmpty;
80    if (NULL == gEmpty) {
81        gEmpty = SkNEW(SkImage_Raster);
82    }
83    gEmpty->ref();
84    return gEmpty;
85}
86
87static void release_data(void* addr, void* context) {
88    SkData* data = static_cast<SkData*>(context);
89    data->unref();
90}
91
92SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
93    : INHERITED(info.fWidth, info.fHeight)
94{
95    data->ref();
96    void* addr = const_cast<void*>(data->data());
97    SkColorTable* ctable = NULL;
98
99    fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
100    fBitmap.setImmutable();
101    fBitmap.lockPixels();
102}
103
104SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
105    : INHERITED(info.fWidth, info.fHeight)
106{
107    fBitmap.setInfo(info, rowBytes);
108    fBitmap.setPixelRef(pr);
109    fBitmap.lockPixels();
110}
111
112SkImage_Raster::~SkImage_Raster() {}
113
114void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
115    canvas->drawBitmap(fBitmap, x, y, paint);
116}
117
118void SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src,
119                                      const SkRect& dst, const SkPaint* paint) {
120    canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
121}
122
123bool SkImage_Raster::onReadPixels(SkBitmap* dst, const SkIRect& subset) const {
124    if (dst->pixelRef()) {
125        return this->INHERITED::onReadPixels(dst, subset);
126    } else {
127        SkBitmap src;
128        if (!fBitmap.extractSubset(&src, subset)) {
129            return false;
130        }
131        return src.copyTo(dst, src.colorType());
132    }
133}
134
135const void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr,
136                                         size_t* rowBytesPtr) const {
137    const SkImageInfo info = fBitmap.info();
138    if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
139        return NULL;
140    }
141    *infoPtr = info;
142    *rowBytesPtr = fBitmap.rowBytes();
143    return fBitmap.getPixels();
144}
145
146bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
147    *dst = fBitmap;
148    return true;
149}
150
151///////////////////////////////////////////////////////////////////////////////
152
153SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
154    if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
155        return NULL;
156    }
157    if (0 == info.fWidth && 0 == info.fHeight) {
158        return SkImage_Raster::NewEmpty();
159    }
160    // check this after empty-check
161    if (NULL == pixels) {
162        return NULL;
163    }
164
165    // Here we actually make a copy of the caller's pixel data
166    SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.fHeight * rowBytes));
167    return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
168}
169
170
171SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
172    if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
173        return NULL;
174    }
175    if (0 == info.fWidth && 0 == info.fHeight) {
176        return SkImage_Raster::NewEmpty();
177    }
178    // check this after empty-check
179    if (NULL == data) {
180        return NULL;
181    }
182
183    // did they give us enough data?
184    size_t size = info.fHeight * rowBytes;
185    if (data->size() < size) {
186        return NULL;
187    }
188
189    return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
190}
191
192SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
193                                size_t rowBytes) {
194    return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes));
195}
196
197SkPixelRef* SkBitmapImageGetPixelRef(SkImage* image) {
198    return ((SkImage_Raster*)image)->getPixelRef();
199}
200