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 "SkBitmap.h"
9 #include "SkCanvas.h"
10 #include "SkImagePriv.h"
11 #include "SkImage_Base.h"
12
as_IB(SkImage * image)13 static SkImage_Base* as_IB(SkImage* image) {
14 return static_cast<SkImage_Base*>(image);
15 }
16
as_IB(const SkImage * image)17 static const SkImage_Base* as_IB(const SkImage* image) {
18 return static_cast<const SkImage_Base*>(image);
19 }
20
NextUniqueID()21 uint32_t SkImage::NextUniqueID() {
22 static int32_t gUniqueID;
23
24 // never return 0;
25 uint32_t id;
26 do {
27 id = sk_atomic_inc(&gUniqueID) + 1;
28 } while (0 == id);
29 return id;
30 }
31
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const32 void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
33 as_IB(this)->onDraw(canvas, x, y, paint);
34 }
35
draw(SkCanvas * canvas,const SkRect * src,const SkRect & dst,const SkPaint * paint) const36 void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
37 const SkPaint* paint) const {
38 as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
39 }
40
peekPixels(SkImageInfo * info,size_t * rowBytes) const41 const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
42 SkImageInfo infoStorage;
43 size_t rowBytesStorage;
44 if (NULL == info) {
45 info = &infoStorage;
46 }
47 if (NULL == rowBytes) {
48 rowBytes = &rowBytesStorage;
49 }
50 return as_IB(this)->onPeekPixels(info, rowBytes);
51 }
52
readPixels(SkBitmap * bitmap,const SkIRect * subset) const53 bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
54 if (NULL == bitmap) {
55 return false;
56 }
57
58 SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
59
60 // trim against the bitmap, if its already been allocated
61 if (bitmap->pixelRef()) {
62 bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
63 bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
64 if (bounds.isEmpty()) {
65 return false;
66 }
67 }
68
69 if (subset && !bounds.intersect(*subset)) {
70 // perhaps we could return true + empty-bitmap?
71 return false;
72 }
73 return as_IB(this)->onReadPixels(bitmap, bounds);
74 }
75
getTexture()76 GrTexture* SkImage::getTexture() {
77 return as_IB(this)->onGetTexture();
78 }
79
newShader(SkShader::TileMode tileX,SkShader::TileMode tileY,const SkMatrix * localMatrix) const80 SkShader* SkImage::newShader(SkShader::TileMode tileX,
81 SkShader::TileMode tileY,
82 const SkMatrix* localMatrix) const {
83 return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
84 }
85
encode(SkImageEncoder::Type type,int quality) const86 SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
87 SkBitmap bm;
88 if (as_IB(this)->getROPixels(&bm)) {
89 return SkImageEncoder::EncodeData(bm, type, quality);
90 }
91 return NULL;
92 }
93
94 ///////////////////////////////////////////////////////////////////////////////
95
raster_canvas_supports(const SkImageInfo & info)96 static bool raster_canvas_supports(const SkImageInfo& info) {
97 switch (info.colorType()) {
98 case kN32_SkColorType:
99 return kUnpremul_SkAlphaType != info.alphaType();
100 case kRGB_565_SkColorType:
101 return true;
102 case kAlpha_8_SkColorType:
103 return true;
104 default:
105 break;
106 }
107 return false;
108 }
109
onReadPixels(SkBitmap * bitmap,const SkIRect & subset) const110 bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
111 if (bitmap->pixelRef()) {
112 const SkImageInfo info = bitmap->info();
113 if (kUnknown_SkColorType == info.colorType()) {
114 return false;
115 }
116 if (!raster_canvas_supports(info)) {
117 return false;
118 }
119 } else {
120 SkBitmap tmp;
121 if (!tmp.tryAllocN32Pixels(subset.width(), subset.height())) {
122 return false;
123 }
124 *bitmap = tmp;
125 }
126
127 SkRect srcR, dstR;
128 srcR.set(subset);
129 dstR = srcR;
130 dstR.offset(-dstR.left(), -dstR.top());
131
132 SkCanvas canvas(*bitmap);
133
134 SkPaint paint;
135 paint.setXfermodeMode(SkXfermode::kClear_Mode);
136 canvas.drawRect(dstR, paint);
137
138 const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
139 return true;
140 }
141