SkImage.cpp revision 70e359055240d0de93da4ba71bf5833164fb394c
1#include "SkImage.h"
2#include "SkImagePriv.h"
3#include "SkBitmap.h"
4#include "SkCanvas.h"
5
6///////////////////////////////////////////////////////////////////////////////
7
8class SkImage_Base : public SkImage {
9public:
10    SkImage_Base(int width, int height) : INHERITED(width, height) {}
11
12    virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) = 0;
13
14private:
15    typedef SkImage INHERITED;
16};
17
18static SkImage_Base* asIB(SkImage* image) {
19    return static_cast<SkImage_Base*>(image);
20}
21
22///////////////////////////////////////////////////////////////////////////////
23
24
25class SkImage_Raster : public SkImage_Base {
26public:
27    static bool ValidArgs(const Info& info, SkColorSpace* cs, size_t rowBytes) {
28        const int maxDimension = SK_MaxS32 >> 2;
29        const size_t kMaxPixelByteSize = SK_MaxS32;
30
31        if (info.fWidth < 0 || info.fHeight < 0) {
32            return false;
33        }
34        if (info.fWidth > maxDimension || info.fHeight > maxDimension) {
35            return false;
36        }
37        if ((unsigned)info.fColorType > (unsigned)kLastEnum_ColorType) {
38            return false;
39        }
40        if ((unsigned)info.fAlphaType > (unsigned)kLastEnum_AlphaType) {
41            return false;
42        }
43
44        bool isOpaque;
45        if (SkImageInfoToBitmapConfig(info, &isOpaque) == SkBitmap::kNo_Config) {
46            return false;
47        }
48
49        // TODO: check colorspace
50
51        if (rowBytes < SkImageMinRowBytes(info)) {
52            return false;
53        }
54
55        int64_t size = (int64_t)info.fHeight * rowBytes;
56        if (size > kMaxPixelByteSize) {
57            return false;
58        }
59        return true;
60    }
61
62    static SkImage* NewEmpty();
63
64    SkImage_Raster(const SkImage::Info&, SkColorSpace*, SkData*, size_t rb);
65    virtual ~SkImage_Raster();
66
67    virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
68
69    // exposed for SkSurface_Raster via SkNewImageFromPixelRef
70    SkImage_Raster(const SkImage::Info&, SkPixelRef*, size_t rowBytes);
71
72private:
73    SkImage_Raster() : INHERITED(0, 0) {}
74
75    SkBitmap    fBitmap;
76
77    typedef SkImage_Base INHERITED;
78};
79
80SkImage* SkNewImageFromPixelRef(const SkImage::Info& info, SkPixelRef* pr,
81                                size_t rowBytes) {
82    return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes));
83}
84
85///////////////////////////////////////////////////////////////////////////////
86
87#include "SkData.h"
88#include "SkDataPixelRef.h"
89
90SkImage* SkImage_Raster::NewEmpty() {
91    // Returns lazily created singleton
92    static SkImage* gEmpty;
93    if (NULL == gEmpty) {
94        gEmpty = SkNEW(SkImage_Raster);
95    }
96    gEmpty->ref();
97    return gEmpty;
98}
99
100SkImage_Raster::SkImage_Raster(const Info& info, SkColorSpace* cs,
101                               SkData* data, size_t rowBytes)
102: INHERITED(info.fWidth, info.fHeight) {
103    bool isOpaque;
104    SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
105
106    fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes);
107    fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
108    fBitmap.setIsOpaque(isOpaque);
109    fBitmap.setImmutable();
110}
111
112SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
113        : INHERITED(info.fWidth, info.fHeight) {
114    SkASSERT(pr->isImmutable());
115
116    bool isOpaque;
117    SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
118
119    fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes);
120    fBitmap.setPixelRef(pr);
121    fBitmap.setIsOpaque(isOpaque);
122    fBitmap.setImmutable();
123}
124
125SkImage_Raster::~SkImage_Raster() {}
126
127void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
128    canvas->drawBitmap(fBitmap, x, y, paint);
129}
130
131///////////////////////////////////////////////////////////////////////////////
132
133#include "SkPicture.h"
134
135class SkImage_Picture : public SkImage_Base {
136public:
137    SkImage_Picture(SkPicture*);
138    virtual ~SkImage_Picture();
139
140    virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
141
142private:
143    SkPicture*  fPicture;
144
145    typedef SkImage_Base INHERITED;
146};
147
148SkImage_Picture::SkImage_Picture(SkPicture* pict) : INHERITED(pict->width(), pict->height()) {
149    pict->endRecording();
150    pict->ref();
151    fPicture = pict;
152}
153
154SkImage_Picture::~SkImage_Picture() {
155    fPicture->unref();
156}
157
158void SkImage_Picture::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
159                             const SkPaint* paint) {
160    SkImagePrivDrawPicture(canvas, fPicture, x, y, paint);
161}
162
163SkImage* SkNewImageFromPicture(SkPicture* pict) {
164    return SkNEW_ARGS(SkImage_Picture, (pict));
165}
166
167///////////////////////////////////////////////////////////////////////////////
168
169SkImage* SkImage::NewRasterCopy(const SkImage::Info& info, SkColorSpace* cs,
170                                const void* pixels, size_t rowBytes) {
171    if (!SkImage_Raster::ValidArgs(info, cs, rowBytes)) {
172        return NULL;
173    }
174    if (0 == info.fWidth && 0 == info.fHeight) {
175        return SkImage_Raster::NewEmpty();
176    }
177    // check this after empty-check
178    if (NULL == pixels) {
179        return NULL;
180    }
181
182    // Here we actually make a copy of the caller's pixel data
183    SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.fHeight * rowBytes));
184    return SkNEW_ARGS(SkImage_Raster, (info, cs, data, rowBytes));
185}
186
187
188SkImage* SkImage::NewRasterData(const SkImage::Info& info, SkColorSpace* cs,
189                                SkData* pixelData, size_t rowBytes) {
190    if (!SkImage_Raster::ValidArgs(info, cs, rowBytes)) {
191        return NULL;
192    }
193    if (0 == info.fWidth && 0 == info.fHeight) {
194        return SkImage_Raster::NewEmpty();
195    }
196    // check this after empty-check
197    if (NULL == pixelData) {
198        return NULL;
199    }
200
201    // did they give us enough data?
202    size_t size = info.fHeight * rowBytes;
203    if (pixelData->size() < size) {
204        return NULL;
205    }
206
207    SkAutoDataUnref data(pixelData);
208    return SkNEW_ARGS(SkImage_Raster, (info, cs, data, rowBytes));
209}
210
211///////////////////////////////////////////////////////////////////////////////
212
213#include "SkCanvas.h"
214
215uint32_t SkImage::NextUniqueID() {
216    static int32_t gUniqueID;
217
218    // never return 0;
219    uint32_t id;
220    do {
221        id = sk_atomic_inc(&gUniqueID) + 1;
222    } while (0 == id);
223    return id;
224}
225
226void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
227                   const SkPaint* paint) {
228    asIB(this)->onDraw(canvas, x, y, paint);
229}
230
231