blob: 795b8420e6e8cbdff7e3a8d635f79f1902ddc742 [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"
scroggo@google.com7def5e12013-05-31 14:00:10 +000010#include "SkImagePriv.h"
11#include "SkImage_Base.h"
reed@google.comf6627b72012-07-27 18:02:50 +000012
scroggo@google.com7def5e12013-05-31 14:00:10 +000013static SkImage_Base* as_IB(SkImage* image) {
reed@google.comf6627b72012-07-27 18:02:50 +000014 return static_cast<SkImage_Base*>(image);
15}
16
scroggo@google.com7def5e12013-05-31 14:00:10 +000017static const SkImage_Base* as_IB(const SkImage* image) {
18 return static_cast<const SkImage_Base*>(image);
19}
20
reed@google.comf6627b72012-07-27 18:02:50 +000021uint32_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
reed8572fc02014-08-11 13:03:55 -070032void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
scroggo@google.com7def5e12013-05-31 14:00:10 +000033 as_IB(this)->onDraw(canvas, x, y, paint);
reed@google.comf6627b72012-07-27 18:02:50 +000034}
junov@chromium.orgda904742013-05-01 22:38:16 +000035
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000036void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
reed8572fc02014-08-11 13:03:55 -070037 const SkPaint* paint) const {
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000038 as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
39}
40
reed@google.com4f7c6152014-02-06 14:11:56 +000041const 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
53bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
54 if (NULL == bitmap) {
55 return false;
56 }
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000057
reed@google.com4f7c6152014-02-06 14:11:56 +000058 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
junov@chromium.orgda904742013-05-01 22:38:16 +000076GrTexture* SkImage::getTexture() {
scroggo@google.com7def5e12013-05-31 14:00:10 +000077 return as_IB(this)->onGetTexture();
78}
79
piotaixr76d5b472014-07-22 15:02:05 -070080SkShader* SkImage::newShader(SkShader::TileMode tileX,
81 SkShader::TileMode tileY,
82 const SkMatrix* localMatrix) const {
83 return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
piotaixrcef04f82014-07-14 07:48:04 -070084}
85
scroggo@google.com7def5e12013-05-31 14:00:10 +000086SkData* 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;
junov@chromium.orgda904742013-05-01 22:38:16 +000092}
reed@google.com4f7c6152014-02-06 14:11:56 +000093
94///////////////////////////////////////////////////////////////////////////////
95
96static bool raster_canvas_supports(const SkImageInfo& info) {
97 switch (info.fColorType) {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000098 case kN32_SkColorType:
reed@google.com4f7c6152014-02-06 14:11:56 +000099 return kUnpremul_SkAlphaType != info.fAlphaType;
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
110bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
reed@google.com4f7c6152014-02-06 14:11:56 +0000111 if (bitmap->pixelRef()) {
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000112 const SkImageInfo info = bitmap->info();
113 if (kUnknown_SkColorType == info.colorType()) {
reed@google.com4f7c6152014-02-06 14:11:56 +0000114 return false;
115 }
116 if (!raster_canvas_supports(info)) {
117 return false;
118 }
119 } else {
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000120 const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
reed@google.com4f7c6152014-02-06 14:11:56 +0000121 SkBitmap tmp;
122 if (!tmp.allocPixels(info)) {
123 return false;
124 }
125 *bitmap = tmp;
126 }
127
128 SkRect srcR, dstR;
129 srcR.set(subset);
130 dstR = srcR;
131 dstR.offset(-dstR.left(), -dstR.top());
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000132
reed@google.com4f7c6152014-02-06 14:11:56 +0000133 SkCanvas canvas(*bitmap);
134
135 SkPaint paint;
136 paint.setXfermodeMode(SkXfermode::kClear_Mode);
137 canvas.drawRect(dstR, paint);
138
139 const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
140 return true;
141}