blob: e0a13f915bdef3116ef2f212eb5c17d4445f2c5a [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
32void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
33 const SkPaint* paint) {
scroggo@google.com7def5e12013-05-31 14:00:10 +000034 as_IB(this)->onDraw(canvas, x, y, paint);
reed@google.comf6627b72012-07-27 18:02:50 +000035}
junov@chromium.orgda904742013-05-01 22:38:16 +000036
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000037void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
38 const SkPaint* paint) {
39 as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
40}
41
reed@google.com4f7c6152014-02-06 14:11:56 +000042const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
43 SkImageInfo infoStorage;
44 size_t rowBytesStorage;
45 if (NULL == info) {
46 info = &infoStorage;
47 }
48 if (NULL == rowBytes) {
49 rowBytes = &rowBytesStorage;
50 }
51 return as_IB(this)->onPeekPixels(info, rowBytes);
52}
53
54bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
55 if (NULL == bitmap) {
56 return false;
57 }
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000058
reed@google.com4f7c6152014-02-06 14:11:56 +000059 SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
60
61 // trim against the bitmap, if its already been allocated
62 if (bitmap->pixelRef()) {
63 bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
64 bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
65 if (bounds.isEmpty()) {
66 return false;
67 }
68 }
69
70 if (subset && !bounds.intersect(*subset)) {
71 // perhaps we could return true + empty-bitmap?
72 return false;
73 }
74 return as_IB(this)->onReadPixels(bitmap, bounds);
75}
76
junov@chromium.orgda904742013-05-01 22:38:16 +000077GrTexture* SkImage::getTexture() {
scroggo@google.com7def5e12013-05-31 14:00:10 +000078 return as_IB(this)->onGetTexture();
79}
80
81SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
82 SkBitmap bm;
83 if (as_IB(this)->getROPixels(&bm)) {
84 return SkImageEncoder::EncodeData(bm, type, quality);
85 }
86 return NULL;
junov@chromium.orgda904742013-05-01 22:38:16 +000087}
reed@google.com4f7c6152014-02-06 14:11:56 +000088
89///////////////////////////////////////////////////////////////////////////////
90
91static bool raster_canvas_supports(const SkImageInfo& info) {
92 switch (info.fColorType) {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000093 case kN32_SkColorType:
reed@google.com4f7c6152014-02-06 14:11:56 +000094 return kUnpremul_SkAlphaType != info.fAlphaType;
95 case kRGB_565_SkColorType:
96 return true;
97 case kAlpha_8_SkColorType:
98 return true;
99 default:
100 break;
101 }
102 return false;
103}
104
105bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
reed@google.com4f7c6152014-02-06 14:11:56 +0000106 if (bitmap->pixelRef()) {
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000107 const SkImageInfo info = bitmap->info();
108 if (kUnknown_SkColorType == info.colorType()) {
reed@google.com4f7c6152014-02-06 14:11:56 +0000109 return false;
110 }
111 if (!raster_canvas_supports(info)) {
112 return false;
113 }
114 } else {
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000115 const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
reed@google.com4f7c6152014-02-06 14:11:56 +0000116 SkBitmap tmp;
117 if (!tmp.allocPixels(info)) {
118 return false;
119 }
120 *bitmap = tmp;
121 }
122
123 SkRect srcR, dstR;
124 srcR.set(subset);
125 dstR = srcR;
126 dstR.offset(-dstR.left(), -dstR.top());
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000127
reed@google.com4f7c6152014-02-06 14:11:56 +0000128 SkCanvas canvas(*bitmap);
129
130 SkPaint paint;
131 paint.setXfermodeMode(SkXfermode::kClear_Mode);
132 canvas.drawRect(dstR, paint);
133
134 const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
135 return true;
136}