blob: f701d1233692f572e4c5bcd331ef48d416fee3e6 [file] [log] [blame]
Mike Klein841101d2017-03-10 09:55:51 -05001/*
2 * Copyright 2017 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
Mike Klein49f33b82017-03-13 09:56:34 -07008#include "SkColorFilter.h"
Mike Klein841101d2017-03-10 09:55:51 -05009#include "SkColorSpaceXformCanvas.h"
Matt Sarettcdc651d2017-03-30 12:41:48 -040010#include "SkColorSpaceXformer.h"
Mike Kleind492db92017-03-15 09:56:47 -070011#include "SkGradientShader.h"
Matt Sarett6de13102017-03-14 14:10:48 -040012#include "SkImage_Base.h"
Matt Sarette6844832017-04-03 10:35:42 -040013#include "SkImagePriv.h"
Mike Klein841101d2017-03-10 09:55:51 -050014#include "SkMakeUnique.h"
15#include "SkNoDrawCanvas.h"
16#include "SkSurface.h"
Mike Klein841101d2017-03-10 09:55:51 -050017
18class SkColorSpaceXformCanvas : public SkNoDrawCanvas {
19public:
Matt Sarette6844832017-04-03 10:35:42 -040020 SkColorSpaceXformCanvas(SkCanvas* target, sk_sp<SkColorSpace> targetCS,
Matt Sarettcdc651d2017-03-30 12:41:48 -040021 std::unique_ptr<SkColorSpaceXformer> xformer)
Mike Klein841101d2017-03-10 09:55:51 -050022 : SkNoDrawCanvas(SkIRect::MakeSize(target->getBaseLayerSize()))
23 , fTarget(target)
Matt Sarette6844832017-04-03 10:35:42 -040024 , fTargetCS(targetCS)
Matt Sarettcdc651d2017-03-30 12:41:48 -040025 , fXformer(std::move(xformer))
Matt Sarett9969e772017-03-30 17:23:48 -040026 {
27 // Set the matrix and clip to match |fTarget|. Otherwise, we'll answer queries for
28 // bounds/matrix differently than |fTarget| would.
Mike Klein2f245be2017-03-30 18:30:50 -040029 SkCanvas::onClipRect(SkRect::Make(fTarget->getDeviceClipBounds()),
Matt Sarett9969e772017-03-30 17:23:48 -040030 SkClipOp::kIntersect, kHard_ClipEdgeStyle);
31 SkCanvas::setMatrix(fTarget->getTotalMatrix());
32 }
Mike Klein49f33b82017-03-13 09:56:34 -070033
Matt Saretta88a6462017-03-23 10:45:04 -040034 SkImageInfo onImageInfo() const override {
35 return fTarget->imageInfo();
36 }
37
Mike Klein841101d2017-03-10 09:55:51 -050038 void onDrawPaint(const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040039 fTarget->drawPaint(fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050040 }
41
42 void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040043 fTarget->drawRect(rect, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050044 }
45 void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040046 fTarget->drawOval(oval, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050047 }
48 void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040049 fTarget->drawRRect(rrect, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050050 }
51 void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040052 fTarget->drawDRRect(outer, inner, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050053 }
54 void onDrawPath(const SkPath& path, const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040055 fTarget->drawPath(path, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050056 }
57 void onDrawArc(const SkRect& oval, SkScalar start, SkScalar sweep, bool useCenter,
58 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040059 fTarget->drawArc(oval, start, sweep, useCenter, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050060 }
61 void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040062 fTarget->drawRegion(region, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050063 }
64 void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
65 SkBlendMode mode, const SkPaint& paint) override {
Mike Klein49f33b82017-03-13 09:56:34 -070066 SkColor xformed[4];
67 if (colors) {
Matt Sarettcdc651d2017-03-30 12:41:48 -040068 fXformer->apply(xformed, colors, 4);
Mike Klein49f33b82017-03-13 09:56:34 -070069 colors = xformed;
70 }
71
Matt Sarettcdc651d2017-03-30 12:41:48 -040072 fTarget->drawPatch(cubics, colors, texs, mode, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050073 }
74 void onDrawPoints(PointMode mode, size_t count, const SkPoint* pts,
75 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040076 fTarget->drawPoints(mode, count, pts, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050077 }
Mike Reedfed9cfd2017-03-17 12:09:04 -040078 void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
79 const SkPaint& paint) override {
80 sk_sp<SkVertices> copy;
81 if (vertices->hasColors()) {
82 int count = vertices->vertexCount();
83 SkSTArray<8, SkColor> xformed(count);
Matt Sarettcdc651d2017-03-30 12:41:48 -040084 fXformer->apply(xformed.begin(), vertices->colors(), count);
Mike Reedfed9cfd2017-03-17 12:09:04 -040085 copy = SkVertices::MakeCopy(vertices->mode(), count, vertices->positions(),
86 vertices->texCoords(), xformed.begin(),
87 vertices->indexCount(), vertices->indices());
88 vertices = copy.get();
Mike Klein49f33b82017-03-13 09:56:34 -070089 }
90
Matt Sarettcdc651d2017-03-30 12:41:48 -040091 fTarget->drawVertices(vertices, mode, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050092 }
93
94 void onDrawText(const void* ptr, size_t len,
95 SkScalar x, SkScalar y,
96 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -040097 fTarget->drawText(ptr, len, x, y, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -050098 }
99 void onDrawPosText(const void* ptr, size_t len,
100 const SkPoint* xys,
101 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400102 fTarget->drawPosText(ptr, len, xys, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500103 }
104 void onDrawPosTextH(const void* ptr, size_t len,
105 const SkScalar* xs, SkScalar y,
106 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400107 fTarget->drawPosTextH(ptr, len, xs, y, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500108 }
109 void onDrawTextOnPath(const void* ptr, size_t len,
110 const SkPath& path, const SkMatrix* matrix,
111 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400112 fTarget->drawTextOnPath(ptr, len, path, matrix, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500113 }
114 void onDrawTextRSXform(const void* ptr, size_t len,
115 const SkRSXform* xforms, const SkRect* cull,
116 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400117 fTarget->drawTextRSXform(ptr, len, xforms, cull, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500118 }
119 void onDrawTextBlob(const SkTextBlob* blob,
120 SkScalar x, SkScalar y,
121 const SkPaint& paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400122 fTarget->drawTextBlob(blob, x, y, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500123 }
124
125 void onDrawImage(const SkImage* img,
126 SkScalar l, SkScalar t,
127 const SkPaint* paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400128 fTarget->drawImage(fXformer->apply(img).get(),
Mike Klein841101d2017-03-10 09:55:51 -0500129 l, t,
Matt Sarettcdc651d2017-03-30 12:41:48 -0400130 fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500131 }
132 void onDrawImageRect(const SkImage* img,
133 const SkRect* src, const SkRect& dst,
134 const SkPaint* paint, SrcRectConstraint constraint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400135 fTarget->drawImageRect(fXformer->apply(img).get(),
Matt Sarette6844832017-04-03 10:35:42 -0400136 src ? *src : SkRect::MakeIWH(img->width(), img->height()), dst,
Matt Sarettcdc651d2017-03-30 12:41:48 -0400137 fXformer->apply(paint), constraint);
Mike Klein841101d2017-03-10 09:55:51 -0500138 }
139 void onDrawImageNine(const SkImage* img,
140 const SkIRect& center, const SkRect& dst,
141 const SkPaint* paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400142 fTarget->drawImageNine(fXformer->apply(img).get(),
Mike Klein841101d2017-03-10 09:55:51 -0500143 center, dst,
Matt Sarettcdc651d2017-03-30 12:41:48 -0400144 fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500145 }
146 void onDrawImageLattice(const SkImage* img,
147 const Lattice& lattice, const SkRect& dst,
148 const SkPaint* paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400149 fTarget->drawImageLattice(fXformer->apply(img).get(),
Mike Klein841101d2017-03-10 09:55:51 -0500150 lattice, dst,
Matt Sarettcdc651d2017-03-30 12:41:48 -0400151 fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500152 }
153 void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex,
154 const SkColor* colors, int count, SkBlendMode mode,
155 const SkRect* cull, const SkPaint* paint) override {
Mike Kleind492db92017-03-15 09:56:47 -0700156 SkSTArray<8, SkColor> xformed;
Mike Klein49f33b82017-03-13 09:56:34 -0700157 if (colors) {
158 xformed.reset(count);
Matt Sarettcdc651d2017-03-30 12:41:48 -0400159 fXformer->apply(xformed.begin(), colors, count);
Mike Klein49f33b82017-03-13 09:56:34 -0700160 colors = xformed.begin();
161 }
162
Matt Sarettcdc651d2017-03-30 12:41:48 -0400163 fTarget->drawAtlas(fXformer->apply(atlas).get(), xforms, tex, colors, count, mode, cull,
164 fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500165 }
166
167 void onDrawBitmap(const SkBitmap& bitmap,
168 SkScalar l, SkScalar t,
169 const SkPaint* paint) override {
Matt Sarette6844832017-04-03 10:35:42 -0400170 if (this->skipXform(bitmap)) {
171 return fTarget->drawBitmap(bitmap, l, t, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500172 }
Matt Sarette6844832017-04-03 10:35:42 -0400173
174 fTarget->drawImage(fXformer->apply(bitmap).get(), l, t, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500175 }
176 void onDrawBitmapRect(const SkBitmap& bitmap,
177 const SkRect* src, const SkRect& dst,
178 const SkPaint* paint, SrcRectConstraint constraint) override {
Matt Sarette6844832017-04-03 10:35:42 -0400179 if (this->skipXform(bitmap)) {
180 return fTarget->drawBitmapRect(bitmap,
181 src ? *src : SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst,
182 fXformer->apply(paint), constraint);
Mike Klein841101d2017-03-10 09:55:51 -0500183 }
Matt Sarette6844832017-04-03 10:35:42 -0400184
185 fTarget->drawImageRect(fXformer->apply(bitmap).get(),
186 src ? *src : SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst,
187 fXformer->apply(paint), constraint);
Mike Klein841101d2017-03-10 09:55:51 -0500188 }
189 void onDrawBitmapNine(const SkBitmap& bitmap,
190 const SkIRect& center, const SkRect& dst,
191 const SkPaint* paint) override {
Matt Sarette6844832017-04-03 10:35:42 -0400192 if (this->skipXform(bitmap)) {
193 return fTarget->drawBitmapNine(bitmap, center, dst, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500194 }
Matt Sarette6844832017-04-03 10:35:42 -0400195
196 fTarget->drawImageNine(fXformer->apply(bitmap).get(), center, dst, fXformer->apply(paint));
197
Mike Klein841101d2017-03-10 09:55:51 -0500198 }
199 void onDrawBitmapLattice(const SkBitmap& bitmap,
200 const Lattice& lattice, const SkRect& dst,
201 const SkPaint* paint) override {
Matt Sarette6844832017-04-03 10:35:42 -0400202 if (this->skipXform(bitmap)) {
203 return fTarget->drawBitmapLattice(bitmap, lattice, dst, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500204 }
Matt Sarette6844832017-04-03 10:35:42 -0400205
206
207 fTarget->drawImageLattice(fXformer->apply(bitmap).get(), lattice, dst,
208 fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500209 }
210
211 // TODO: May not be ideal to unfurl pictures.
212 void onDrawPicture(const SkPicture* pic,
213 const SkMatrix* matrix,
214 const SkPaint* paint) override {
Matt Sarettcdc651d2017-03-30 12:41:48 -0400215 SkCanvas::onDrawPicture(pic, matrix, fXformer->apply(paint));
Mike Klein841101d2017-03-10 09:55:51 -0500216 }
217 void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
Mike Klein841101d2017-03-10 09:55:51 -0500218 SkCanvas::onDrawDrawable(drawable, matrix);
219 }
220
221 SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
Mike Klein841101d2017-03-10 09:55:51 -0500222 fTarget->saveLayer({
223 rec.fBounds,
Matt Sarettcdc651d2017-03-30 12:41:48 -0400224 fXformer->apply(rec.fPaint),
Mike Klein841101d2017-03-10 09:55:51 -0500225 rec.fBackdrop, // TODO: this is an image filter
226 rec.fSaveLayerFlags,
227 });
228 return kNoLayer_SaveLayerStrategy;
229 }
230
231 // Everything from here on should be uninteresting strictly proxied state-change calls.
232 void willSave() override { fTarget->save(); }
233 void willRestore() override { fTarget->restore(); }
234
235 void didConcat (const SkMatrix& m) override { fTarget->concat (m); }
236 void didSetMatrix(const SkMatrix& m) override { fTarget->setMatrix(m); }
237
238 void onClipRect(const SkRect& clip, SkClipOp op, ClipEdgeStyle style) override {
Mike Klein1683f782017-03-20 22:47:33 -0400239 SkCanvas::onClipRect(clip, op, style);
Mike Klein841101d2017-03-10 09:55:51 -0500240 fTarget->clipRect(clip, op, style);
241 }
242 void onClipRRect(const SkRRect& clip, SkClipOp op, ClipEdgeStyle style) override {
Mike Klein1683f782017-03-20 22:47:33 -0400243 SkCanvas::onClipRRect(clip, op, style);
Mike Klein841101d2017-03-10 09:55:51 -0500244 fTarget->clipRRect(clip, op, style);
245 }
246 void onClipPath(const SkPath& clip, SkClipOp op, ClipEdgeStyle style) override {
Mike Klein1683f782017-03-20 22:47:33 -0400247 SkCanvas::onClipPath(clip, op, style);
Mike Klein841101d2017-03-10 09:55:51 -0500248 fTarget->clipPath(clip, op, style);
249 }
250 void onClipRegion(const SkRegion& clip, SkClipOp op) override {
Mike Klein1683f782017-03-20 22:47:33 -0400251 SkCanvas::onClipRegion(clip, op);
Mike Klein841101d2017-03-10 09:55:51 -0500252 fTarget->clipRegion(clip, op);
253 }
254
255 void onDrawAnnotation(const SkRect& rect, const char* key, SkData* val) override {
256 fTarget->drawAnnotation(rect, key, val);
257 }
258
259 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) override {
260 return fTarget->makeSurface(info, &props);
261 }
262
Matt Sarettb48df272017-03-30 16:10:45 -0400263 SkISize getBaseLayerSize() const override { return fTarget->getBaseLayerSize(); }
264 SkRect onGetLocalClipBounds() const override { return fTarget->getLocalClipBounds(); }
265 SkIRect onGetDeviceClipBounds() const override { return fTarget->getDeviceClipBounds(); }
266 bool isClipEmpty() const override { return fTarget->isClipEmpty(); }
267 bool isClipRect() const override { return fTarget->isClipRect(); }
268 bool onPeekPixels(SkPixmap* pixmap) override { return fTarget->peekPixels(pixmap); }
269 bool onAccessTopLayerPixels(SkPixmap* pixmap) override {
270 SkImageInfo info;
271 size_t rowBytes;
272 SkIPoint* origin = nullptr;
273 void* addr = fTarget->accessTopLayerPixels(&info, &rowBytes, origin);
274 if (addr) {
275 *pixmap = SkPixmap(info, addr, rowBytes);
276 return true;
277 }
278 return false;
279 }
280
281 bool onGetProps(SkSurfaceProps* props) const override { return fTarget->getProps(props); }
282 void onFlush() override { return fTarget->flush(); }
283
Mike Klein841101d2017-03-10 09:55:51 -0500284private:
Matt Sarette6844832017-04-03 10:35:42 -0400285 bool skipXform(const SkBitmap& bitmap) {
286 return (!bitmap.colorSpace() && fTargetCS->isSRGB()) ||
287 (SkColorSpace::Equals(bitmap.colorSpace(), fTargetCS.get())) ||
288 (kAlpha_8_SkColorType == bitmap.colorType());
289 }
290
Matt Sarettcdc651d2017-03-30 12:41:48 -0400291 SkCanvas* fTarget;
Matt Sarette6844832017-04-03 10:35:42 -0400292 sk_sp<SkColorSpace> fTargetCS;
Matt Sarettcdc651d2017-03-30 12:41:48 -0400293 std::unique_ptr<SkColorSpaceXformer> fXformer;
Mike Klein841101d2017-03-10 09:55:51 -0500294};
295
296std::unique_ptr<SkCanvas> SkCreateColorSpaceXformCanvas(SkCanvas* target,
297 sk_sp<SkColorSpace> targetCS) {
Matt Sarette6844832017-04-03 10:35:42 -0400298 std::unique_ptr<SkColorSpaceXformer> xformer = SkColorSpaceXformer::Make(targetCS);
Matt Sarettcdc651d2017-03-30 12:41:48 -0400299 if (!xformer) {
300 return nullptr;
301 }
302
Matt Sarette6844832017-04-03 10:35:42 -0400303 return skstd::make_unique<SkColorSpaceXformCanvas>(target, std::move(targetCS),
304 std::move(xformer));
Mike Klein841101d2017-03-10 09:55:51 -0500305}