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