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 "SkImageGenerator.h"
11 #include "SkImagePriv.h"
12 #include "SkImage_Base.h"
13 #include "SkReadPixelsRec.h"
14 #include "SkString.h"
15 #include "SkSurface.h"
16
NextUniqueID()17 uint32_t SkImage::NextUniqueID() {
18 static int32_t gUniqueID;
19
20 // never return 0;
21 uint32_t id;
22 do {
23 id = sk_atomic_inc(&gUniqueID) + 1;
24 } while (0 == id);
25 return id;
26 }
27
peekPixels(SkImageInfo * info,size_t * rowBytes) const28 const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
29 SkImageInfo infoStorage;
30 size_t rowBytesStorage;
31 if (NULL == info) {
32 info = &infoStorage;
33 }
34 if (NULL == rowBytes) {
35 rowBytes = &rowBytesStorage;
36 }
37 return as_IB(this)->onPeekPixels(info, rowBytes);
38 }
39
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY) const40 bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
41 int srcX, int srcY) const {
42 SkReadPixelsRec rec(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
43 if (!rec.trim(this->width(), this->height())) {
44 return false;
45 }
46 return as_IB(this)->onReadPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
47 }
48
getTexture() const49 GrTexture* SkImage::getTexture() const {
50 return as_IB(this)->onGetTexture();
51 }
52
newShader(SkShader::TileMode tileX,SkShader::TileMode tileY,const SkMatrix * localMatrix) const53 SkShader* SkImage::newShader(SkShader::TileMode tileX,
54 SkShader::TileMode tileY,
55 const SkMatrix* localMatrix) const {
56 return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
57 }
58
encode(SkImageEncoder::Type type,int quality) const59 SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
60 SkBitmap bm;
61 if (as_IB(this)->getROPixels(&bm)) {
62 return SkImageEncoder::EncodeData(bm, type, quality);
63 }
64 return NULL;
65 }
66
NewFromData(SkData * data)67 SkImage* SkImage::NewFromData(SkData* data) {
68 if (NULL == data) {
69 return NULL;
70 }
71 SkImageGenerator* generator = SkImageGenerator::NewFromData(data);
72 return generator ? SkImage::NewFromGenerator(generator) : NULL;
73 }
74
newSurface(const SkImageInfo & info,const SkSurfaceProps * props) const75 SkSurface* SkImage::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) const {
76 if (NULL == props) {
77 props = &as_IB(this)->props();
78 }
79 return as_IB(this)->onNewSurface(info, *props);
80 }
81
toString(SkString * str) const82 const char* SkImage::toString(SkString* str) const {
83 str->appendf("image: (id:%d (%d, %d) %s)", this->uniqueID(), this->width(), this->height(),
84 this->isOpaque() ? "opaque" : "");
85 return str->c_str();
86 }
87
newImage(int newWidth,int newHeight,const SkIRect * subset,SkFilterQuality quality) const88 SkImage* SkImage::newImage(int newWidth, int newHeight, const SkIRect* subset,
89 SkFilterQuality quality) const {
90 if (newWidth <= 0 || newHeight <= 0) {
91 return NULL;
92 }
93
94 const SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
95
96 if (subset) {
97 if (!bounds.contains(*subset)) {
98 return NULL;
99 }
100 if (bounds == *subset) {
101 subset = NULL; // and fall through to check below
102 }
103 }
104
105 if (NULL == subset && this->width() == newWidth && this->height() == newHeight) {
106 return SkRef(const_cast<SkImage*>(this));
107 }
108
109 return as_IB(this)->onNewImage(newWidth, newHeight, subset, quality);
110 }
111
112 ///////////////////////////////////////////////////////////////////////////////
113
raster_canvas_supports(const SkImageInfo & info)114 static bool raster_canvas_supports(const SkImageInfo& info) {
115 switch (info.colorType()) {
116 case kN32_SkColorType:
117 return kUnpremul_SkAlphaType != info.alphaType();
118 case kRGB_565_SkColorType:
119 return true;
120 case kAlpha_8_SkColorType:
121 return true;
122 default:
123 break;
124 }
125 return false;
126 }
127
onReadPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY) const128 bool SkImage_Base::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
129 int srcX, int srcY) const {
130 if (!raster_canvas_supports(dstInfo)) {
131 return false;
132 }
133
134 SkBitmap bm;
135 bm.installPixels(dstInfo, dstPixels, dstRowBytes);
136 SkCanvas canvas(bm);
137
138 SkPaint paint;
139 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
140 canvas.drawImage(this, -SkIntToScalar(srcX), -SkIntToScalar(srcY), &paint);
141
142 return true;
143 }
144
onNewImage(int newWidth,int newHeight,const SkIRect * subset,SkFilterQuality quality) const145 SkImage* SkImage_Base::onNewImage(int newWidth, int newHeight, const SkIRect* subset,
146 SkFilterQuality quality) const {
147 const bool opaque = this->isOpaque();
148 const SkImageInfo info = SkImageInfo::Make(newWidth, newHeight, kN32_SkColorType,
149 opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
150 SkAutoTUnref<SkSurface> surface(this->newSurface(info, NULL));
151 if (!surface.get()) {
152 return NULL;
153 }
154
155 SkRect src;
156 if (subset) {
157 src.set(*subset);
158 } else {
159 src = SkRect::MakeIWH(this->width(), this->height());
160 }
161
162 surface->getCanvas()->scale(newWidth / src.width(), newHeight / src.height());
163 surface->getCanvas()->translate(-src.x(), -src.y());
164
165 SkPaint paint;
166 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
167 paint.setFilterQuality(quality);
168 surface->getCanvas()->drawImage(this, 0, 0, &paint);
169 return surface->newImageSnapshot();
170 }
171
172 //////////////////////////////////////////////////////////////////////////////////////
173
174 #if !SK_SUPPORT_GPU
175
NewFromTexture(GrContext *,const GrBackendTextureDesc &,SkAlphaType)176 SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
177 return NULL;
178 }
179
NewFromTextureCopy(GrContext *,const GrBackendTextureDesc &,SkAlphaType)180 SkImage* SkImage::NewFromTextureCopy(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
181 return NULL;
182 }
183
184 #endif
185