blob: f205ac49ca7070970c1b4edc3f9016a54b57a205 [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"
bungemand3ebb482015-08-05 13:57:49 -070012#include "SkPaint.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070013#include "SkPathEffect.h"
14#include "SkShader.h"
reede8f30622016-03-23 18:59:25 -070015#include "SkSurface.h"
bungemand3ebb482015-08-05 13:57:49 -070016#include "SkTLazy.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070017
18namespace {
19
20/** Discard SkShaders not exposed by the Android Java API. */
21
22void CheckShader(SkPaint* paint) {
23 SkShader* shader = paint->getShader();
24 if (!shader) {
25 return;
26 }
27
fmalita2766cc52016-10-06 14:37:23 -070028 if (shader->isAImage()) {
tomhudsonf7edcde2015-03-23 12:51:20 -070029 return;
30 }
halcanary96fcdcc2015-08-27 07:41:13 -070031 if (shader->asACompose(nullptr)) {
tomhudsonf7edcde2015-03-23 12:51:20 -070032 return;
33 }
halcanary96fcdcc2015-08-27 07:41:13 -070034 SkShader::GradientType gtype = shader->asAGradient(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070035 if (gtype == SkShader::kLinear_GradientType ||
36 gtype == SkShader::kRadial_GradientType ||
37 gtype == SkShader::kSweep_GradientType) {
38 return;
39 }
halcanary96fcdcc2015-08-27 07:41:13 -070040 paint->setShader(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070041}
42
43void Filter(SkPaint* paint) {
44
45 uint32_t flags = paint->getFlags();
46 flags &= ~SkPaint::kLCDRenderText_Flag;
47 paint->setFlags(flags);
48
fmalita2766cc52016-10-06 14:37:23 -070049 // Android doesn't support blend modes above kLighten_Mode
50 if (paint->getBlendMode() > SkBlendMode::kLighten) {
51 paint->setBlendMode(SkBlendMode::kSrcOver);
tomhudsonf7edcde2015-03-23 12:51:20 -070052 }
53
54 // Force bilinear scaling or none
55 if (paint->getFilterQuality() != kNone_SkFilterQuality) {
56 paint->setFilterQuality(kLow_SkFilterQuality);
57 }
58
59 CheckShader(paint);
60
61 // Android SDK only supports mode & matrix color filters
62 // (and, again, no modes above kLighten_Mode).
63 SkColorFilter* cf = paint->getColorFilter();
64 if (cf) {
65 SkColor color;
66 SkXfermode::Mode mode;
67 SkScalar srcColorMatrix[20];
68 bool isMode = cf->asColorMode(&color, &mode);
69 if (isMode && mode > SkXfermode::kLighten_Mode) {
70 paint->setColorFilter(
reedd053ce92016-03-22 10:17:23 -070071 SkColorFilter::MakeModeFilter(color, SkXfermode::kSrcOver_Mode));
tomhudsonf7edcde2015-03-23 12:51:20 -070072 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -070073 paint->setColorFilter(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070074 }
75 }
76
77#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
78 SkPathEffect* pe = paint->getPathEffect();
79 if (pe && !pe->exposedInAndroidJavaAPI()) {
halcanary96fcdcc2015-08-27 07:41:13 -070080 paint->setPathEffect(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070081 }
82#endif
83
84 // TODO: Android doesn't support all the flags that can be passed to
85 // blur filters; we need plumbing to get them out.
86
halcanary96fcdcc2015-08-27 07:41:13 -070087 paint->setImageFilter(nullptr);
88 paint->setLooper(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070089};
90
91} // namespace
92
93#define FILTER(p) \
94 SkPaint filteredPaint(p); \
95 Filter(&filteredPaint);
96
97#define FILTER_PTR(p) \
98 SkTLazy<SkPaint> lazyPaint; \
99 SkPaint* filteredPaint = (SkPaint*) p; \
100 if (p) { \
101 filteredPaint = lazyPaint.set(*p); \
102 Filter(filteredPaint); \
103 }
104
105
halcanary96fcdcc2015-08-27 07:41:13 -0700106SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { }
tomhudsonf7edcde2015-03-23 12:51:20 -0700107
108void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }
109
110void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
111 FILTER(paint);
112 fProxyTarget->drawPaint(filteredPaint);
113}
114void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
115 size_t count,
116 const SkPoint pts[],
117 const SkPaint& paint) {
118 FILTER(paint);
119 fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
120}
121void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
122 FILTER(paint);
123 fProxyTarget->drawOval(r, filteredPaint);
124}
bsalomonac3aa242016-08-19 11:25:19 -0700125void SkAndroidSDKCanvas::onDrawArc(const SkRect& r, SkScalar startAngle, SkScalar sweepAngle,
126 bool useCenter, const SkPaint& paint) {
127 FILTER(paint);
128 fProxyTarget->drawArc(r, startAngle, sweepAngle, useCenter, filteredPaint);
129}
tomhudsonf7edcde2015-03-23 12:51:20 -0700130void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
131 FILTER(paint);
132 fProxyTarget->drawRect(r, filteredPaint);
133}
134void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
135 FILTER(paint);
136 fProxyTarget->drawRRect(r, filteredPaint);
137}
138void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
139 FILTER(paint);
140 fProxyTarget->drawPath(path, filteredPaint);
141}
142void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
143 SkScalar left,
144 SkScalar top,
145 const SkPaint* paint) {
146 FILTER_PTR(paint);
147 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
148}
149void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
150 const SkRect* src,
151 const SkRect& dst,
152 const SkPaint* paint,
scroggoaa80e422015-07-31 14:29:26 -0700153 SkCanvas::SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700154 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700155 fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700156}
157void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
158 const SkIRect& center,
159 const SkRect& dst,
160 const SkPaint* paint) {
161 FILTER_PTR(paint);
162 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
163}
tomhudsonf7edcde2015-03-23 12:51:20 -0700164void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
165 int vertexCount,
166 const SkPoint vertices[],
167 const SkPoint texs[], const SkColor colors[], SkXfermode* xMode,
168 const uint16_t indices[], int indexCount,
169 const SkPaint& paint) {
170 FILTER(paint);
171 fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
172 xMode, indices, indexCount, filteredPaint);
173}
174
175void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
176 const SkRRect& inner,
177 const SkPaint& paint) {
178 FILTER(paint);
179 fProxyTarget->drawDRRect(outer, inner, filteredPaint);
180}
181
182void SkAndroidSDKCanvas::onDrawText(const void* text,
183 size_t byteLength,
184 SkScalar x,
185 SkScalar y,
186 const SkPaint& paint) {
187 FILTER(paint);
188 fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
189}
190void SkAndroidSDKCanvas::onDrawPosText(const void* text,
191 size_t byteLength,
192 const SkPoint pos[],
193 const SkPaint& paint) {
194 FILTER(paint);
195 fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
196}
197void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
198 size_t byteLength,
199 const SkScalar xpos[],
200 SkScalar constY,
201 const SkPaint& paint) {
202 FILTER(paint);
203 fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
204}
205void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
reed45561a02016-07-07 12:47:17 -0700206 size_t byteLength,
207 const SkPath& path,
208 const SkMatrix* matrix,
209 const SkPaint& paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700210 FILTER(paint);
211 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
212}
reed45561a02016-07-07 12:47:17 -0700213void SkAndroidSDKCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
214 const SkRSXform xform[], const SkRect* cull,
215 const SkPaint& paint) {
216 FILTER(paint);
217 fProxyTarget->drawTextRSXform(text, byteLength, xform, cull, filteredPaint);
218}
tomhudsonf7edcde2015-03-23 12:51:20 -0700219void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
220 SkScalar x,
221 SkScalar y,
222 const SkPaint& paint) {
223 FILTER(paint);
224 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
225}
226
227void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
228 const SkColor colors[4],
229 const SkPoint texCoords[4],
230 SkXfermode* xmode,
231 const SkPaint& paint) {
232 FILTER(paint);
233 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
234}
235
236
237void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
238 SkScalar x,
239 SkScalar y,
240 const SkPaint* paint) {
241 FILTER_PTR(paint);
242 fProxyTarget->drawImage(image, x, y, filteredPaint);
243}
244
245void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700246 const SkRect* in,
247 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400248 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700249 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700250 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700251 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700252}
253
254void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
tomhudson45863342015-10-01 08:02:22 -0700255 const SkMatrix* matrix,
256 const SkPaint* paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700257 FILTER_PTR(paint);
258 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
259}
260
tomhudson45863342015-10-01 08:02:22 -0700261void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
262 const SkRSXform xform[],
263 const SkRect tex[],
264 const SkColor colors[],
265 int count,
266 SkXfermode::Mode mode,
267 const SkRect* cullRect,
268 const SkPaint* paint) {
269 FILTER_PTR(paint);
270 fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
271 filteredPaint);
272}
273
274void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
275 const SkIRect& center,
276 const SkRect& dst,
277 const SkPaint* paint) {
278 FILTER_PTR(paint);
279 fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
280}
281
282
reeda8db7282015-07-07 10:22:31 -0700283void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
284 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700285}
286
287SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
288 return fProxyTarget->getBaseLayerSize();
289}
290bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
291 return fProxyTarget->getClipBounds(rect);
292}
293bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
294 return fProxyTarget->getClipDeviceBounds(rect);
295}
296
297bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
298bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
299
reede8f30622016-03-23 18:59:25 -0700300sk_sp<SkSurface> SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
301 const SkSurfaceProps& props) {
302 return fProxyTarget->makeSurface(info, &props);
tomhudsonf7edcde2015-03-23 12:51:20 -0700303}
304
tomhudsonb97e9092015-05-26 14:12:24 -0700305bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
reed6ceeebd2016-03-09 14:26:26 -0800306 return fProxyTarget->peekPixels(pmap);
tomhudsonf7edcde2015-03-23 12:51:20 -0700307}
308
tomhudsonb97e9092015-05-26 14:12:24 -0700309bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
310 SkASSERT(pmap);
311 SkImageInfo info;
halcanary9d524f22016-03-29 09:03:52 -0700312 size_t rowBytes;
halcanary96fcdcc2015-08-27 07:41:13 -0700313 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
tomhudsonb97e9092015-05-26 14:12:24 -0700314 if (addr) {
315 pmap->reset(info, addr, rowBytes);
316 return true;
317 }
318 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700319}
320
tomhudson05e4aba2015-04-08 06:52:58 -0700321void SkAndroidSDKCanvas::willSave() {
322 fProxyTarget->save();
323}
324
reeda2b6fdd2015-12-18 07:38:26 -0800325SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
326 fProxyTarget->saveLayer(rec);
tomhudson05e4aba2015-04-08 06:52:58 -0700327 return SkCanvas::kNoLayer_SaveLayerStrategy;
328}
329
330void SkAndroidSDKCanvas::willRestore() {
331 fProxyTarget->restore();
332}
333
tomhudsonf7edcde2015-03-23 12:51:20 -0700334void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700335
tomhudsonf7edcde2015-03-23 12:51:20 -0700336void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
337 fProxyTarget->concat(m);
338}
tomhudson05e4aba2015-04-08 06:52:58 -0700339
340void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
341 fProxyTarget->setMatrix(m);
342}
tomhudsonf7edcde2015-03-23 12:51:20 -0700343
344void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
fmalita2766cc52016-10-06 14:37:23 -0700345 ClipOp op,
tomhudsonf7edcde2015-03-23 12:51:20 -0700346 ClipEdgeStyle style) {
347 fProxyTarget->clipRect(rect, op, style);
348}
349
350void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
fmalita2766cc52016-10-06 14:37:23 -0700351 ClipOp op,
tomhudsonf7edcde2015-03-23 12:51:20 -0700352 ClipEdgeStyle style) {
353 fProxyTarget->clipRRect(rrect, op, style);
354}
355
356void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
fmalita2766cc52016-10-06 14:37:23 -0700357 ClipOp op,
tomhudsonf7edcde2015-03-23 12:51:20 -0700358 ClipEdgeStyle style) {
359 fProxyTarget->clipPath(path, op, style);
360}
361
fmalita2766cc52016-10-06 14:37:23 -0700362void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, ClipOp op) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700363 fProxyTarget->clipRegion(region, op);
364}
365
366void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }