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