blob: 35fff1f24234b8a32cf6029efc07f65b1d08d7c7 [file] [log] [blame]
reed@google.com6997ebb2012-07-30 19:50:31 +00001/*
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
reed@google.comf6627b72012-07-27 18:02:50 +00008#include "SkBitmap.h"
mike@reedtribe.org70e35902012-07-29 20:38:16 +00009#include "SkCanvas.h"
reed5965c8a2015-01-07 18:04:45 -080010#include "SkImageGenerator.h"
scroggo@google.com7def5e12013-05-31 14:00:10 +000011#include "SkImagePriv.h"
12#include "SkImage_Base.h"
reed96472de2014-12-10 09:53:42 -080013#include "SkReadPixelsRec.h"
reedf8d18742015-01-02 20:45:37 -080014#include "SkString.h"
reed4af267b2014-11-21 08:46:37 -080015#include "SkSurface.h"
scroggo@google.com7def5e12013-05-31 14:00:10 +000016
reed@google.comf6627b72012-07-27 18:02:50 +000017uint32_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
reed8572fc02014-08-11 13:03:55 -070028void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
scroggo@google.com7def5e12013-05-31 14:00:10 +000029 as_IB(this)->onDraw(canvas, x, y, paint);
reed@google.comf6627b72012-07-27 18:02:50 +000030}
junov@chromium.orgda904742013-05-01 22:38:16 +000031
piotaixr5ceff912014-09-26 07:36:26 -070032void SkImage::drawRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
reed8572fc02014-08-11 13:03:55 -070033 const SkPaint* paint) const {
piotaixr5ceff912014-09-26 07:36:26 -070034 as_IB(this)->onDrawRect(canvas, src, dst, paint);
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000035}
36
reed@google.com4f7c6152014-02-06 14:11:56 +000037const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
38 SkImageInfo infoStorage;
39 size_t rowBytesStorage;
40 if (NULL == info) {
41 info = &infoStorage;
42 }
43 if (NULL == rowBytes) {
44 rowBytes = &rowBytesStorage;
45 }
46 return as_IB(this)->onPeekPixels(info, rowBytes);
47}
48
reed96472de2014-12-10 09:53:42 -080049bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
50 int srcX, int srcY) const {
51 SkReadPixelsRec rec(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
52 if (!rec.trim(this->width(), this->height())) {
reed@google.com4f7c6152014-02-06 14:11:56 +000053 return false;
54 }
reed96472de2014-12-10 09:53:42 -080055 return as_IB(this)->onReadPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
reed@google.com4f7c6152014-02-06 14:11:56 +000056}
57
junov@chromium.orgda904742013-05-01 22:38:16 +000058GrTexture* SkImage::getTexture() {
scroggo@google.com7def5e12013-05-31 14:00:10 +000059 return as_IB(this)->onGetTexture();
60}
61
piotaixr76d5b472014-07-22 15:02:05 -070062SkShader* SkImage::newShader(SkShader::TileMode tileX,
63 SkShader::TileMode tileY,
64 const SkMatrix* localMatrix) const {
65 return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
piotaixrcef04f82014-07-14 07:48:04 -070066}
67
scroggo@google.com7def5e12013-05-31 14:00:10 +000068SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
69 SkBitmap bm;
70 if (as_IB(this)->getROPixels(&bm)) {
71 return SkImageEncoder::EncodeData(bm, type, quality);
72 }
73 return NULL;
junov@chromium.orgda904742013-05-01 22:38:16 +000074}
reed@google.com4f7c6152014-02-06 14:11:56 +000075
reed5965c8a2015-01-07 18:04:45 -080076SkImage* SkImage::NewFromData(SkData* data) {
77 if (NULL == data) {
78 return NULL;
79 }
80 SkImageGenerator* generator = SkImageGenerator::NewFromData(data);
81 return generator ? SkImage::NewFromGenerator(generator) : NULL;
82}
83
reed4af267b2014-11-21 08:46:37 -080084SkSurface* SkImage::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) const {
85 if (NULL == props) {
86 props = &as_IB(this)->props();
87 }
88 return as_IB(this)->onNewSurface(info, *props);
89}
90
reedf8d18742015-01-02 20:45:37 -080091const char* SkImage::toString(SkString* str) const {
92 str->appendf("image: (id:%d (%d, %d) %s)", this->uniqueID(), this->width(), this->height(),
93 this->isOpaque() ? "opaque" : "");
94 return str->c_str();
95}
96
reedf803da12015-01-23 05:58:07 -080097SkImage* SkImage::newImage(int newWidth, int newHeight, const SkIRect* subset,
98 SkFilterQuality quality) const {
99 if (newWidth <= 0 || newHeight <= 0) {
100 return NULL;
101 }
102
103 const SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
104
105 if (subset) {
106 if (!bounds.contains(*subset)) {
107 return NULL;
108 }
109 if (bounds == *subset) {
110 subset = NULL; // and fall through to check below
111 }
112 }
113
114 if (NULL == subset && this->width() == newWidth && this->height() == newHeight) {
115 return SkRef(const_cast<SkImage*>(this));
116 }
117
118 return as_IB(this)->onNewImage(newWidth, newHeight, subset, quality);
119}
120
reed96a857e2015-01-25 10:33:58 -0800121void SkImage::preroll() const {
122 as_IB(this)->onPreroll();
123}
124
reed@google.com4f7c6152014-02-06 14:11:56 +0000125///////////////////////////////////////////////////////////////////////////////
126
127static bool raster_canvas_supports(const SkImageInfo& info) {
reede5ea5002014-09-03 11:54:58 -0700128 switch (info.colorType()) {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000129 case kN32_SkColorType:
reede5ea5002014-09-03 11:54:58 -0700130 return kUnpremul_SkAlphaType != info.alphaType();
reed@google.com4f7c6152014-02-06 14:11:56 +0000131 case kRGB_565_SkColorType:
132 return true;
133 case kAlpha_8_SkColorType:
134 return true;
135 default:
136 break;
137 }
138 return false;
139}
140
reed96472de2014-12-10 09:53:42 -0800141bool SkImage_Base::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
142 int srcX, int srcY) const {
143 if (!raster_canvas_supports(dstInfo)) {
144 return false;
reed@google.com4f7c6152014-02-06 14:11:56 +0000145 }
146
reed96472de2014-12-10 09:53:42 -0800147 SkBitmap bm;
148 bm.installPixels(dstInfo, dstPixels, dstRowBytes);
149 SkCanvas canvas(bm);
reed@google.com4f7c6152014-02-06 14:11:56 +0000150
151 SkPaint paint;
reed96472de2014-12-10 09:53:42 -0800152 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
153 canvas.drawImage(this, -SkIntToScalar(srcX), -SkIntToScalar(srcY), &paint);
reed@google.com4f7c6152014-02-06 14:11:56 +0000154
reed@google.com4f7c6152014-02-06 14:11:56 +0000155 return true;
156}
reedf803da12015-01-23 05:58:07 -0800157
158SkImage* SkImage_Base::onNewImage(int newWidth, int newHeight, const SkIRect* subset,
159 SkFilterQuality quality) const {
160 const bool opaque = this->isOpaque();
161 const SkImageInfo info = SkImageInfo::Make(newWidth, newHeight, kN32_SkColorType,
162 opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
163 SkAutoTUnref<SkSurface> surface(this->newSurface(info, NULL));
164 if (!surface.get()) {
165 return NULL;
166 }
167
168 SkRect src;
169 if (subset) {
170 src.set(*subset);
171 } else {
172 src = SkRect::MakeIWH(this->width(), this->height());
173 }
174
175 surface->getCanvas()->scale(newWidth / src.width(), newHeight / src.height());
176 surface->getCanvas()->translate(-src.x(), -src.y());
177
178 SkPaint paint;
179 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
180 paint.setFilterQuality(quality);
181 surface->getCanvas()->drawImage(this, 0, 0, &paint);
182 return surface->newImageSnapshot();
183}
184
185