• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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