blob: 50447fc1e964ade4fe65bf42930e4e462c5ce735 [file] [log] [blame]
robertphillipsb6c65e92016-02-04 10:52:42 -08001/*
2 * Copyright 2016 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 "SkCanvas.h"
9#include "SkSpecialImage.h"
10#include "SkSpecialSurface.h"
11
12///////////////////////////////////////////////////////////////////////////////
13class SkSpecialImage_Base : public SkSpecialImage {
14public:
15 SkSpecialImage_Base(const SkIRect& subset) : INHERITED(subset) { }
16 virtual ~SkSpecialImage_Base() { }
17
18 virtual void onDraw(SkCanvas*, int x, int y, const SkPaint*) const = 0;
19
20 virtual bool onPeekPixels(SkPixmap*) const { return false; }
21
22 virtual GrTexture* onPeekTexture() const { return nullptr; }
23
24 virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; }
25
26private:
27 typedef SkSpecialImage INHERITED;
28};
29
30///////////////////////////////////////////////////////////////////////////////
31static inline const SkSpecialImage_Base* as_IB(const SkSpecialImage* image) {
32 return static_cast<const SkSpecialImage_Base*>(image);
33}
34
35void SkSpecialImage::draw(SkCanvas* canvas, int x, int y, const SkPaint* paint) const {
36 return as_IB(this)->onDraw(canvas, x, y, paint);
37}
38
39bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
40 return as_IB(this)->onPeekPixels(pixmap);
41}
42
43GrTexture* SkSpecialImage::peekTexture() const {
44 return as_IB(this)->onPeekTexture();
45}
46
47SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const {
48 return as_IB(this)->onNewSurface(info);
49}
50
51///////////////////////////////////////////////////////////////////////////////
52#include "SkImage.h"
53#if SK_SUPPORT_GPU
54#include "SkGr.h"
55#include "SkGrPriv.h"
56#endif
57
58class SkSpecialImage_Image : public SkSpecialImage_Base {
59public:
60 SkSpecialImage_Image(const SkIRect& subset, const SkImage* image)
61 : INHERITED(subset)
62 , fImage(SkRef(image)) {
63 }
64
65 ~SkSpecialImage_Image() override { }
66
67 void onDraw(SkCanvas* canvas, int x, int y, const SkPaint* paint) const override {
68 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
69
70 canvas->drawImageRect(fImage, this->subset(),
71 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
72 }
73
74 bool onPeekPixels(SkPixmap* pixmap) const override {
75 return fImage->peekPixels(pixmap);
76 }
77
78 GrTexture* onPeekTexture() const override { return fImage->getTexture(); }
79
80 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
81#if SK_SUPPORT_GPU
82 GrTexture* texture = fImage->getTexture();
83 if (texture) {
84 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
85 desc.fFlags = kRenderTarget_GrSurfaceFlag;
86
87 return SkSpecialSurface::NewRenderTarget(texture->getContext(), desc);
88 }
89#endif
90 return SkSpecialSurface::NewRaster(info, nullptr);
91 }
92
93private:
94 SkAutoTUnref<const SkImage> fImage;
95
96 typedef SkSpecialImage_Base INHERITED;
97};
98
99#ifdef SK_DEBUG
100static bool rect_fits(const SkIRect& rect, int width, int height) {
101 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
102 rect.fRight >= 0 && rect.fRight <= width &&
103 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
104 rect.fBottom >= 0 && rect.fBottom <= height;
105}
106#endif
107
108SkSpecialImage* SkSpecialImage::NewFromImage(const SkIRect& subset, const SkImage* image) {
109 SkASSERT(rect_fits(subset, image->width(), image->height()));
110 return new SkSpecialImage_Image(subset, image);
111}
112
113///////////////////////////////////////////////////////////////////////////////
114#include "SkBitmap.h"
115#include "SkImageInfo.h"
116#include "SkPixelRef.h"
117
118class SkSpecialImage_Raster : public SkSpecialImage_Base {
119public:
120 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm)
121 : INHERITED(subset)
122 , fBitmap(bm) {
123 if (bm.pixelRef()->isPreLocked()) {
124 // we only preemptively lock if there is no chance of triggering something expensive
125 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
126 fBitmap.lockPixels();
127 }
128 }
129
130 ~SkSpecialImage_Raster() override { }
131
132 void onDraw(SkCanvas* canvas, int x, int y, const SkPaint* paint) const override {
133 SkRect dst = SkRect::MakeXYWH(x, y,
134 this->subset().width(), this->subset().height());
135
136 canvas->drawBitmapRect(fBitmap, this->subset(),
137 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
138 }
139
140 bool onPeekPixels(SkPixmap* pixmap) const override {
141 const SkImageInfo info = fBitmap.info();
142 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
143 return false;
144 }
145 const void* pixels = fBitmap.getPixels();
146 if (pixels) {
147 if (pixmap) {
148 pixmap->reset(info, pixels, fBitmap.rowBytes());
149 }
150 return true;
151 }
152 return false;
153 }
154
155 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
156 return SkSpecialSurface::NewRaster(info, nullptr);
157 }
158
159private:
160 SkBitmap fBitmap;
161
162 typedef SkSpecialImage_Base INHERITED;
163};
164
165SkSpecialImage* SkSpecialImage::NewFromRaster(const SkIRect& subset, const SkBitmap& bm) {
166 SkASSERT(nullptr == bm.getTexture());
167 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
168 return new SkSpecialImage_Raster(subset, bm);
169}
170
171#if SK_SUPPORT_GPU
172///////////////////////////////////////////////////////////////////////////////
173#include "GrTexture.h"
174
175class SkSpecialImage_Gpu : public SkSpecialImage_Base {
176public:
177 SkSpecialImage_Gpu(const SkIRect& subset, GrTexture* tex)
178 : INHERITED(subset)
179 , fTexture(SkRef(tex)) {
180 }
181
182 ~SkSpecialImage_Gpu() override { }
183
184 void onDraw(SkCanvas* canvas, int x, int y, const SkPaint* paint) const override {
185 SkRect dst = SkRect::MakeXYWH(x, y,
186 this->subset().width(), this->subset().height());
187
188 SkBitmap bm;
189
190 static const bool kUnknownOpacity = false;
191 GrWrapTextureInBitmap(fTexture,
192 fTexture->width(), fTexture->height(), kUnknownOpacity, &bm);
193
194 canvas->drawBitmapRect(bm, this->subset(),
195 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
196 }
197
198 GrTexture* onPeekTexture() const override { return fTexture; }
199
200 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
201 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
202 desc.fFlags = kRenderTarget_GrSurfaceFlag;
203
204 return SkSpecialSurface::NewRenderTarget(fTexture->getContext(), desc);
205 }
206
207private:
208 SkAutoTUnref<GrTexture> fTexture;
209
210 typedef SkSpecialImage_Base INHERITED;
211};
212
213SkSpecialImage* SkSpecialImage::NewFromGpu(const SkIRect& subset, GrTexture* tex) {
214 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
215 return new SkSpecialImage_Gpu(subset, tex);
216}
217
218#else
219
220SkSpecialImage* SkSpecialImage::NewFromGpu(const SkIRect& subset, GrTexture* tex) {
221 return nullptr;
222}
223
224#endif