1 /*
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
8 #include "SkColorFilter.h"
9 #include "SkColorSpaceXformCanvas.h"
10 #include "SkColorSpaceXformer.h"
11 #include "SkGradientShader.h"
12 #include "SkImage_Base.h"
13 #include "SkImagePriv.h"
14 #include "SkMakeUnique.h"
15 #include "SkNoDrawCanvas.h"
16 #include "SkSurface.h"
17 #include "SkTLazy.h"
18
19 namespace {
20 struct MaybePaint {
21 SkTLazy<SkPaint> fStorage;
22 const SkPaint* fPaint = nullptr;
MaybePaint__anone5180b580111::MaybePaint23 MaybePaint(const SkPaint* p, SkColorSpaceXformer* xformer) {
24 if (p) { fPaint = fStorage.set(xformer->apply(*p)); }
25 }
operator const SkPaint*__anone5180b580111::MaybePaint26 operator const SkPaint*() const { return fPaint; }
27 };
28 };
29
30 class SkColorSpaceXformCanvas : public SkNoDrawCanvas {
31 public:
SkColorSpaceXformCanvas(SkCanvas * target,sk_sp<SkColorSpace> targetCS,std::unique_ptr<SkColorSpaceXformer> xformer)32 SkColorSpaceXformCanvas(SkCanvas* target, sk_sp<SkColorSpace> targetCS,
33 std::unique_ptr<SkColorSpaceXformer> xformer)
34 : SkNoDrawCanvas(SkIRect::MakeSize(target->getBaseLayerSize()))
35 , fTarget(target)
36 , fTargetCS(targetCS)
37 , fXformer(std::move(xformer))
38 {
39 // Set the matrix and clip to match |fTarget|. Otherwise, we'll answer queries for
40 // bounds/matrix differently than |fTarget| would.
41 SkCanvas::onClipRect(SkRect::MakeFromIRect(fTarget->getDeviceClipBounds()),
42 SkClipOp::kIntersect, kHard_ClipEdgeStyle);
43 SkCanvas::setMatrix(fTarget->getTotalMatrix());
44 }
45
onImageInfo() const46 SkImageInfo onImageInfo() const override {
47 return fTarget->imageInfo();
48 }
49
onDrawPaint(const SkPaint & paint)50 void onDrawPaint(const SkPaint& paint) override {
51 fTarget->drawPaint(fXformer->apply(paint));
52 }
53
onDrawRect(const SkRect & rect,const SkPaint & paint)54 void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
55 fTarget->drawRect(rect, fXformer->apply(paint));
56 }
onDrawOval(const SkRect & oval,const SkPaint & paint)57 void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
58 fTarget->drawOval(oval, fXformer->apply(paint));
59 }
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)60 void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
61 fTarget->drawRRect(rrect, fXformer->apply(paint));
62 }
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)63 void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
64 fTarget->drawDRRect(outer, inner, fXformer->apply(paint));
65 }
onDrawPath(const SkPath & path,const SkPaint & paint)66 void onDrawPath(const SkPath& path, const SkPaint& paint) override {
67 fTarget->drawPath(path, fXformer->apply(paint));
68 }
onDrawArc(const SkRect & oval,SkScalar start,SkScalar sweep,bool useCenter,const SkPaint & paint)69 void onDrawArc(const SkRect& oval, SkScalar start, SkScalar sweep, bool useCenter,
70 const SkPaint& paint) override {
71 fTarget->drawArc(oval, start, sweep, useCenter, fXformer->apply(paint));
72 }
onDrawRegion(const SkRegion & region,const SkPaint & paint)73 void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
74 fTarget->drawRegion(region, fXformer->apply(paint));
75 }
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texs[4],SkBlendMode mode,const SkPaint & paint)76 void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
77 SkBlendMode mode, const SkPaint& paint) override {
78 SkColor xformed[4];
79 if (colors) {
80 fXformer->apply(xformed, colors, 4);
81 colors = xformed;
82 }
83
84 fTarget->drawPatch(cubics, colors, texs, mode, fXformer->apply(paint));
85 }
onDrawPoints(PointMode mode,size_t count,const SkPoint * pts,const SkPaint & paint)86 void onDrawPoints(PointMode mode, size_t count, const SkPoint* pts,
87 const SkPaint& paint) override {
88 fTarget->drawPoints(mode, count, pts, fXformer->apply(paint));
89 }
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode mode,const SkPaint & paint)90 void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
91 const SkPaint& paint) override {
92 sk_sp<SkVertices> copy;
93 if (vertices->hasColors()) {
94 int count = vertices->vertexCount();
95 SkSTArray<8, SkColor> xformed(count);
96 fXformer->apply(xformed.begin(), vertices->colors(), count);
97 copy = SkVertices::MakeCopy(vertices->mode(), count, vertices->positions(),
98 vertices->texCoords(), xformed.begin(),
99 vertices->indexCount(), vertices->indices());
100 vertices = copy.get();
101 }
102
103 fTarget->drawVertices(vertices, mode, fXformer->apply(paint));
104 }
105
onDrawText(const void * ptr,size_t len,SkScalar x,SkScalar y,const SkPaint & paint)106 void onDrawText(const void* ptr, size_t len,
107 SkScalar x, SkScalar y,
108 const SkPaint& paint) override {
109 fTarget->drawText(ptr, len, x, y, fXformer->apply(paint));
110 }
onDrawPosText(const void * ptr,size_t len,const SkPoint * xys,const SkPaint & paint)111 void onDrawPosText(const void* ptr, size_t len,
112 const SkPoint* xys,
113 const SkPaint& paint) override {
114 fTarget->drawPosText(ptr, len, xys, fXformer->apply(paint));
115 }
onDrawPosTextH(const void * ptr,size_t len,const SkScalar * xs,SkScalar y,const SkPaint & paint)116 void onDrawPosTextH(const void* ptr, size_t len,
117 const SkScalar* xs, SkScalar y,
118 const SkPaint& paint) override {
119 fTarget->drawPosTextH(ptr, len, xs, y, fXformer->apply(paint));
120 }
onDrawTextOnPath(const void * ptr,size_t len,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)121 void onDrawTextOnPath(const void* ptr, size_t len,
122 const SkPath& path, const SkMatrix* matrix,
123 const SkPaint& paint) override {
124 fTarget->drawTextOnPath(ptr, len, path, matrix, fXformer->apply(paint));
125 }
onDrawTextRSXform(const void * ptr,size_t len,const SkRSXform * xforms,const SkRect * cull,const SkPaint & paint)126 void onDrawTextRSXform(const void* ptr, size_t len,
127 const SkRSXform* xforms, const SkRect* cull,
128 const SkPaint& paint) override {
129 fTarget->drawTextRSXform(ptr, len, xforms, cull, fXformer->apply(paint));
130 }
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)131 void onDrawTextBlob(const SkTextBlob* blob,
132 SkScalar x, SkScalar y,
133 const SkPaint& paint) override {
134 fTarget->drawTextBlob(blob, x, y, fXformer->apply(paint));
135 }
136
onDrawImage(const SkImage * img,SkScalar l,SkScalar t,const SkPaint * paint)137 void onDrawImage(const SkImage* img,
138 SkScalar l, SkScalar t,
139 const SkPaint* paint) override {
140 fTarget->drawImage(fXformer->apply(img).get(), l, t, MaybePaint(paint, fXformer.get()));
141 }
onDrawImageRect(const SkImage * img,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)142 void onDrawImageRect(const SkImage* img,
143 const SkRect* src, const SkRect& dst,
144 const SkPaint* paint, SrcRectConstraint constraint) override {
145 fTarget->drawImageRect(fXformer->apply(img).get(),
146 src ? *src : SkRect::MakeIWH(img->width(), img->height()), dst,
147 MaybePaint(paint, fXformer.get()), constraint);
148 }
onDrawImageNine(const SkImage * img,const SkIRect & center,const SkRect & dst,const SkPaint * paint)149 void onDrawImageNine(const SkImage* img,
150 const SkIRect& center, const SkRect& dst,
151 const SkPaint* paint) override {
152 fTarget->drawImageNine(fXformer->apply(img).get(), center, dst,
153 MaybePaint(paint, fXformer.get()));
154 }
onDrawImageLattice(const SkImage * img,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)155 void onDrawImageLattice(const SkImage* img,
156 const Lattice& lattice, const SkRect& dst,
157 const SkPaint* paint) override {
158 fTarget->drawImageLattice(fXformer->apply(img).get(), lattice, dst,
159 MaybePaint(paint, fXformer.get()));
160 }
onDrawAtlas(const SkImage * atlas,const SkRSXform * xforms,const SkRect * tex,const SkColor * colors,int count,SkBlendMode mode,const SkRect * cull,const SkPaint * paint)161 void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex,
162 const SkColor* colors, int count, SkBlendMode mode,
163 const SkRect* cull, const SkPaint* paint) override {
164 SkSTArray<8, SkColor> xformed;
165 if (colors) {
166 xformed.reset(count);
167 fXformer->apply(xformed.begin(), colors, count);
168 colors = xformed.begin();
169 }
170 fTarget->drawAtlas(fXformer->apply(atlas).get(), xforms, tex, colors, count, mode, cull,
171 MaybePaint(paint, fXformer.get()));
172 }
173
onDrawBitmap(const SkBitmap & bitmap,SkScalar l,SkScalar t,const SkPaint * paint)174 void onDrawBitmap(const SkBitmap& bitmap,
175 SkScalar l, SkScalar t,
176 const SkPaint* paint) override {
177 if (this->skipXform(bitmap)) {
178 return fTarget->drawBitmap(bitmap, l, t, MaybePaint(paint, fXformer.get()));
179 }
180
181 fTarget->drawImage(fXformer->apply(bitmap).get(), l, t, MaybePaint(paint, fXformer.get()));
182 }
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)183 void onDrawBitmapRect(const SkBitmap& bitmap,
184 const SkRect* src, const SkRect& dst,
185 const SkPaint* paint, SrcRectConstraint constraint) override {
186 if (this->skipXform(bitmap)) {
187 return fTarget->drawBitmapRect(bitmap,
188 src ? *src : SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst,
189 MaybePaint(paint, fXformer.get()), constraint);
190 }
191
192 fTarget->drawImageRect(fXformer->apply(bitmap).get(),
193 src ? *src : SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst,
194 MaybePaint(paint, fXformer.get()), constraint);
195 }
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)196 void onDrawBitmapNine(const SkBitmap& bitmap,
197 const SkIRect& center, const SkRect& dst,
198 const SkPaint* paint) override {
199 if (this->skipXform(bitmap)) {
200 return fTarget->drawBitmapNine(bitmap, center, dst, MaybePaint(paint, fXformer.get()));
201 }
202
203 fTarget->drawImageNine(fXformer->apply(bitmap).get(), center, dst,
204 MaybePaint(paint, fXformer.get()));
205
206 }
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)207 void onDrawBitmapLattice(const SkBitmap& bitmap,
208 const Lattice& lattice, const SkRect& dst,
209 const SkPaint* paint) override {
210 if (this->skipXform(bitmap)) {
211 return fTarget->drawBitmapLattice(bitmap, lattice, dst,
212 MaybePaint(paint, fXformer.get()));
213 }
214
215
216 fTarget->drawImageLattice(fXformer->apply(bitmap).get(), lattice, dst,
217 MaybePaint(paint, fXformer.get()));
218 }
219
220 // TODO: May not be ideal to unfurl pictures.
onDrawPicture(const SkPicture * pic,const SkMatrix * matrix,const SkPaint * paint)221 void onDrawPicture(const SkPicture* pic,
222 const SkMatrix* matrix,
223 const SkPaint* paint) override {
224 SkCanvas::onDrawPicture(pic, matrix, MaybePaint(paint, fXformer.get()));
225 }
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)226 void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
227 SkCanvas::onDrawDrawable(drawable, matrix);
228 }
229
getSaveLayerStrategy(const SaveLayerRec & rec)230 SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
231 fTarget->saveLayer({
232 rec.fBounds,
233 MaybePaint(rec.fPaint, fXformer.get()),
234 rec.fBackdrop, // TODO: this is an image filter
235 rec.fSaveLayerFlags,
236 });
237 return kNoLayer_SaveLayerStrategy;
238 }
239
240 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
setDrawFilter(SkDrawFilter * filter)241 SkDrawFilter* setDrawFilter(SkDrawFilter* filter) override {
242 SkCanvas::setDrawFilter(filter);
243 return fTarget->setDrawFilter(filter);
244 }
245 #endif
246
247 // Everything from here on should be uninteresting strictly proxied state-change calls.
willSave()248 void willSave() override { fTarget->save(); }
willRestore()249 void willRestore() override { fTarget->restore(); }
250
didConcat(const SkMatrix & m)251 void didConcat (const SkMatrix& m) override { fTarget->concat (m); }
didSetMatrix(const SkMatrix & m)252 void didSetMatrix(const SkMatrix& m) override { fTarget->setMatrix(m); }
253
onClipRect(const SkRect & clip,SkClipOp op,ClipEdgeStyle style)254 void onClipRect(const SkRect& clip, SkClipOp op, ClipEdgeStyle style) override {
255 SkCanvas::onClipRect(clip, op, style);
256 fTarget->clipRect(clip, op, style);
257 }
onClipRRect(const SkRRect & clip,SkClipOp op,ClipEdgeStyle style)258 void onClipRRect(const SkRRect& clip, SkClipOp op, ClipEdgeStyle style) override {
259 SkCanvas::onClipRRect(clip, op, style);
260 fTarget->clipRRect(clip, op, style);
261 }
onClipPath(const SkPath & clip,SkClipOp op,ClipEdgeStyle style)262 void onClipPath(const SkPath& clip, SkClipOp op, ClipEdgeStyle style) override {
263 SkCanvas::onClipPath(clip, op, style);
264 fTarget->clipPath(clip, op, style);
265 }
onClipRegion(const SkRegion & clip,SkClipOp op)266 void onClipRegion(const SkRegion& clip, SkClipOp op) override {
267 SkCanvas::onClipRegion(clip, op);
268 fTarget->clipRegion(clip, op);
269 }
270
onDrawAnnotation(const SkRect & rect,const char * key,SkData * val)271 void onDrawAnnotation(const SkRect& rect, const char* key, SkData* val) override {
272 fTarget->drawAnnotation(rect, key, val);
273 }
274
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)275 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) override {
276 return fTarget->makeSurface(info, &props);
277 }
278
getBaseLayerSize() const279 SkISize getBaseLayerSize() const override { return fTarget->getBaseLayerSize(); }
onGetLocalClipBounds() const280 SkRect onGetLocalClipBounds() const override { return fTarget->getLocalClipBounds(); }
onGetDeviceClipBounds() const281 SkIRect onGetDeviceClipBounds() const override { return fTarget->getDeviceClipBounds(); }
isClipEmpty() const282 bool isClipEmpty() const override { return fTarget->isClipEmpty(); }
isClipRect() const283 bool isClipRect() const override { return fTarget->isClipRect(); }
onPeekPixels(SkPixmap * pixmap)284 bool onPeekPixels(SkPixmap* pixmap) override { return fTarget->peekPixels(pixmap); }
onAccessTopLayerPixels(SkPixmap * pixmap)285 bool onAccessTopLayerPixels(SkPixmap* pixmap) override {
286 SkImageInfo info;
287 size_t rowBytes;
288 SkIPoint* origin = nullptr;
289 void* addr = fTarget->accessTopLayerPixels(&info, &rowBytes, origin);
290 if (addr) {
291 *pixmap = SkPixmap(info, addr, rowBytes);
292 return true;
293 }
294 return false;
295 }
296
onGetProps(SkSurfaceProps * props) const297 bool onGetProps(SkSurfaceProps* props) const override { return fTarget->getProps(props); }
onFlush()298 void onFlush() override { return fTarget->flush(); }
299
300 private:
skipXform(const SkBitmap & bitmap)301 bool skipXform(const SkBitmap& bitmap) {
302 return (!bitmap.colorSpace() && fTargetCS->isSRGB()) ||
303 (SkColorSpace::Equals(bitmap.colorSpace(), fTargetCS.get())) ||
304 (kAlpha_8_SkColorType == bitmap.colorType());
305 }
306
307 SkCanvas* fTarget;
308 sk_sp<SkColorSpace> fTargetCS;
309 std::unique_ptr<SkColorSpaceXformer> fXformer;
310 };
311
SkCreateColorSpaceXformCanvas(SkCanvas * target,sk_sp<SkColorSpace> targetCS)312 std::unique_ptr<SkCanvas> SkCreateColorSpaceXformCanvas(SkCanvas* target,
313 sk_sp<SkColorSpace> targetCS) {
314 std::unique_ptr<SkColorSpaceXformer> xformer = SkColorSpaceXformer::Make(targetCS);
315 if (!xformer) {
316 return nullptr;
317 }
318
319 return skstd::make_unique<SkColorSpaceXformCanvas>(target, std::move(targetCS),
320 std::move(xformer));
321 }
322