blob: 887d416dfb174a3f301a1faf9eba7a75314b06aa [file] [log] [blame]
tomhudsonf7edcde2015-03-23 12:51:20 -07001/*
2 * Copyright 2015 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 "SkAndroidSDKCanvas.h"
9
10#include "SkColorFilter.h"
reed7b380d02016-03-21 13:25:16 -070011#include "SkDrawLooper.h"
Mike Reed37d1b492016-11-03 13:12:30 -040012#include "SkImageFilter.h"
bungemand3ebb482015-08-05 13:57:49 -070013#include "SkPaint.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070014#include "SkPathEffect.h"
15#include "SkShader.h"
reede8f30622016-03-23 18:59:25 -070016#include "SkSurface.h"
bungemand3ebb482015-08-05 13:57:49 -070017#include "SkTLazy.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070018
19namespace {
20
21/** Discard SkShaders not exposed by the Android Java API. */
22
23void CheckShader(SkPaint* paint) {
24 SkShader* shader = paint->getShader();
25 if (!shader) {
26 return;
27 }
28
fmalita2766cc52016-10-06 14:37:23 -070029 if (shader->isAImage()) {
tomhudsonf7edcde2015-03-23 12:51:20 -070030 return;
31 }
halcanary96fcdcc2015-08-27 07:41:13 -070032 if (shader->asACompose(nullptr)) {
tomhudsonf7edcde2015-03-23 12:51:20 -070033 return;
34 }
halcanary96fcdcc2015-08-27 07:41:13 -070035 SkShader::GradientType gtype = shader->asAGradient(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070036 if (gtype == SkShader::kLinear_GradientType ||
37 gtype == SkShader::kRadial_GradientType ||
38 gtype == SkShader::kSweep_GradientType) {
39 return;
40 }
halcanary96fcdcc2015-08-27 07:41:13 -070041 paint->setShader(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070042}
43
44void Filter(SkPaint* paint) {
45
46 uint32_t flags = paint->getFlags();
47 flags &= ~SkPaint::kLCDRenderText_Flag;
48 paint->setFlags(flags);
49
fmalita2766cc52016-10-06 14:37:23 -070050 // Android doesn't support blend modes above kLighten_Mode
51 if (paint->getBlendMode() > SkBlendMode::kLighten) {
52 paint->setBlendMode(SkBlendMode::kSrcOver);
tomhudsonf7edcde2015-03-23 12:51:20 -070053 }
54
55 // Force bilinear scaling or none
56 if (paint->getFilterQuality() != kNone_SkFilterQuality) {
57 paint->setFilterQuality(kLow_SkFilterQuality);
58 }
59
60 CheckShader(paint);
61
62 // Android SDK only supports mode & matrix color filters
63 // (and, again, no modes above kLighten_Mode).
64 SkColorFilter* cf = paint->getColorFilter();
65 if (cf) {
66 SkColor color;
reed70295ea2016-10-31 05:27:57 -070067 SK_XFERMODE_MODE_PARAM mode;
tomhudsonf7edcde2015-03-23 12:51:20 -070068 SkScalar srcColorMatrix[20];
69 bool isMode = cf->asColorMode(&color, &mode);
reed70295ea2016-10-31 05:27:57 -070070 if (isMode && (int)mode > (int)SkBlendMode::kLighten) {
tomhudsonf7edcde2015-03-23 12:51:20 -070071 paint->setColorFilter(
reed70295ea2016-10-31 05:27:57 -070072 SkColorFilter::MakeModeFilter(color, SkBlendMode::kSrcOver));
tomhudsonf7edcde2015-03-23 12:51:20 -070073 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -070074 paint->setColorFilter(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070075 }
76 }
77
78#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
79 SkPathEffect* pe = paint->getPathEffect();
80 if (pe && !pe->exposedInAndroidJavaAPI()) {
halcanary96fcdcc2015-08-27 07:41:13 -070081 paint->setPathEffect(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070082 }
83#endif
84
85 // TODO: Android doesn't support all the flags that can be passed to
86 // blur filters; we need plumbing to get them out.
87
halcanary96fcdcc2015-08-27 07:41:13 -070088 paint->setImageFilter(nullptr);
89 paint->setLooper(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070090};
91
92} // namespace
93
94#define FILTER(p) \
95 SkPaint filteredPaint(p); \
96 Filter(&filteredPaint);
97
98#define FILTER_PTR(p) \
99 SkTLazy<SkPaint> lazyPaint; \
100 SkPaint* filteredPaint = (SkPaint*) p; \
101 if (p) { \
102 filteredPaint = lazyPaint.set(*p); \
103 Filter(filteredPaint); \
104 }
105
106
halcanary96fcdcc2015-08-27 07:41:13 -0700107SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { }
tomhudsonf7edcde2015-03-23 12:51:20 -0700108
109void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }
110
111void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
112 FILTER(paint);
113 fProxyTarget->drawPaint(filteredPaint);
114}
115void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
116 size_t count,
117 const SkPoint pts[],
118 const SkPaint& paint) {
119 FILTER(paint);
120 fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
121}
122void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
123 FILTER(paint);
124 fProxyTarget->drawOval(r, filteredPaint);
125}
bsalomonac3aa242016-08-19 11:25:19 -0700126void SkAndroidSDKCanvas::onDrawArc(const SkRect& r, SkScalar startAngle, SkScalar sweepAngle,
127 bool useCenter, const SkPaint& paint) {
128 FILTER(paint);
129 fProxyTarget->drawArc(r, startAngle, sweepAngle, useCenter, filteredPaint);
130}
tomhudsonf7edcde2015-03-23 12:51:20 -0700131void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
132 FILTER(paint);
133 fProxyTarget->drawRect(r, filteredPaint);
134}
135void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
136 FILTER(paint);
137 fProxyTarget->drawRRect(r, filteredPaint);
138}
139void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
140 FILTER(paint);
141 fProxyTarget->drawPath(path, filteredPaint);
142}
143void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
144 SkScalar left,
145 SkScalar top,
146 const SkPaint* paint) {
147 FILTER_PTR(paint);
148 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
149}
150void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
151 const SkRect* src,
152 const SkRect& dst,
153 const SkPaint* paint,
scroggoaa80e422015-07-31 14:29:26 -0700154 SkCanvas::SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700155 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700156 fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700157}
158void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
159 const SkIRect& center,
160 const SkRect& dst,
161 const SkPaint* paint) {
162 FILTER_PTR(paint);
163 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
164}
tomhudsonf7edcde2015-03-23 12:51:20 -0700165void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
166 int vertexCount,
167 const SkPoint vertices[],
reed70295ea2016-10-31 05:27:57 -0700168 const SkPoint texs[], const SkColor colors[], SK_XFERMODE_PARAM xMode,
tomhudsonf7edcde2015-03-23 12:51:20 -0700169 const uint16_t indices[], int indexCount,
170 const SkPaint& paint) {
171 FILTER(paint);
172 fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
173 xMode, indices, indexCount, filteredPaint);
174}
175
176void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
177 const SkRRect& inner,
178 const SkPaint& paint) {
179 FILTER(paint);
180 fProxyTarget->drawDRRect(outer, inner, filteredPaint);
181}
182
183void SkAndroidSDKCanvas::onDrawText(const void* text,
184 size_t byteLength,
185 SkScalar x,
186 SkScalar y,
187 const SkPaint& paint) {
188 FILTER(paint);
189 fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
190}
191void SkAndroidSDKCanvas::onDrawPosText(const void* text,
192 size_t byteLength,
193 const SkPoint pos[],
194 const SkPaint& paint) {
195 FILTER(paint);
196 fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
197}
198void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
199 size_t byteLength,
200 const SkScalar xpos[],
201 SkScalar constY,
202 const SkPaint& paint) {
203 FILTER(paint);
204 fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
205}
206void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
reed45561a02016-07-07 12:47:17 -0700207 size_t byteLength,
208 const SkPath& path,
209 const SkMatrix* matrix,
210 const SkPaint& paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700211 FILTER(paint);
212 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
213}
reed45561a02016-07-07 12:47:17 -0700214void SkAndroidSDKCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
215 const SkRSXform xform[], const SkRect* cull,
216 const SkPaint& paint) {
217 FILTER(paint);
218 fProxyTarget->drawTextRSXform(text, byteLength, xform, cull, filteredPaint);
219}
tomhudsonf7edcde2015-03-23 12:51:20 -0700220void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
221 SkScalar x,
222 SkScalar y,
223 const SkPaint& paint) {
224 FILTER(paint);
225 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
226}
227
228void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
229 const SkColor colors[4],
230 const SkPoint texCoords[4],
reed70295ea2016-10-31 05:27:57 -0700231 SK_XFERMODE_PARAM xmode,
tomhudsonf7edcde2015-03-23 12:51:20 -0700232 const SkPaint& paint) {
233 FILTER(paint);
234 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
235}
236
237
238void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
239 SkScalar x,
240 SkScalar y,
241 const SkPaint* paint) {
242 FILTER_PTR(paint);
243 fProxyTarget->drawImage(image, x, y, filteredPaint);
244}
245
246void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700247 const SkRect* in,
248 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400249 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700250 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700251 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700252 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700253}
254
255void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
tomhudson45863342015-10-01 08:02:22 -0700256 const SkMatrix* matrix,
257 const SkPaint* paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700258 FILTER_PTR(paint);
259 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
260}
261
tomhudson45863342015-10-01 08:02:22 -0700262void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
263 const SkRSXform xform[],
264 const SkRect tex[],
265 const SkColor colors[],
266 int count,
reed70295ea2016-10-31 05:27:57 -0700267 SK_XFERMODE_MODE_PARAM mode,
tomhudson45863342015-10-01 08:02:22 -0700268 const SkRect* cullRect,
269 const SkPaint* paint) {
270 FILTER_PTR(paint);
271 fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
272 filteredPaint);
273}
274
275void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
276 const SkIRect& center,
277 const SkRect& dst,
278 const SkPaint* paint) {
279 FILTER_PTR(paint);
280 fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
281}
282
283
reeda8db7282015-07-07 10:22:31 -0700284void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
285 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700286}
287
288SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
289 return fProxyTarget->getBaseLayerSize();
290}
291bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
292 return fProxyTarget->getClipBounds(rect);
293}
294bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
295 return fProxyTarget->getClipDeviceBounds(rect);
296}
297
298bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
299bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
300
reede8f30622016-03-23 18:59:25 -0700301sk_sp<SkSurface> SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
302 const SkSurfaceProps& props) {
303 return fProxyTarget->makeSurface(info, &props);
tomhudsonf7edcde2015-03-23 12:51:20 -0700304}
305
tomhudsonb97e9092015-05-26 14:12:24 -0700306bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
reed6ceeebd2016-03-09 14:26:26 -0800307 return fProxyTarget->peekPixels(pmap);
tomhudsonf7edcde2015-03-23 12:51:20 -0700308}
309
tomhudsonb97e9092015-05-26 14:12:24 -0700310bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
311 SkASSERT(pmap);
312 SkImageInfo info;
halcanary9d524f22016-03-29 09:03:52 -0700313 size_t rowBytes;
halcanary96fcdcc2015-08-27 07:41:13 -0700314 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
tomhudsonb97e9092015-05-26 14:12:24 -0700315 if (addr) {
316 pmap->reset(info, addr, rowBytes);
317 return true;
318 }
319 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700320}
321
tomhudson05e4aba2015-04-08 06:52:58 -0700322void SkAndroidSDKCanvas::willSave() {
323 fProxyTarget->save();
324}
325
reeda2b6fdd2015-12-18 07:38:26 -0800326SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
327 fProxyTarget->saveLayer(rec);
tomhudson05e4aba2015-04-08 06:52:58 -0700328 return SkCanvas::kNoLayer_SaveLayerStrategy;
329}
330
331void SkAndroidSDKCanvas::willRestore() {
332 fProxyTarget->restore();
333}
334
tomhudsonf7edcde2015-03-23 12:51:20 -0700335void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700336
tomhudsonf7edcde2015-03-23 12:51:20 -0700337void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
338 fProxyTarget->concat(m);
339}
tomhudson05e4aba2015-04-08 06:52:58 -0700340
341void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
342 fProxyTarget->setMatrix(m);
343}
tomhudsonf7edcde2015-03-23 12:51:20 -0700344
345void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
fmalita2766cc52016-10-06 14:37:23 -0700346 ClipOp op,
tomhudsonf7edcde2015-03-23 12:51:20 -0700347 ClipEdgeStyle style) {
348 fProxyTarget->clipRect(rect, op, style);
349}
350
351void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
fmalita2766cc52016-10-06 14:37:23 -0700352 ClipOp op,
tomhudsonf7edcde2015-03-23 12:51:20 -0700353 ClipEdgeStyle style) {
354 fProxyTarget->clipRRect(rrect, op, style);
355}
356
357void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
fmalita2766cc52016-10-06 14:37:23 -0700358 ClipOp op,
tomhudsonf7edcde2015-03-23 12:51:20 -0700359 ClipEdgeStyle style) {
360 fProxyTarget->clipPath(path, op, style);
361}
362
fmalita2766cc52016-10-06 14:37:23 -0700363void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, ClipOp op) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700364 fProxyTarget->clipRegion(region, op);
365}
366
367void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }