blob: 41536b1b8995709a0075d3271d2918db2dfa29e0 [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"
11#include "SkPathEffect.h"
12#include "SkShader.h"
13
14namespace {
15
16/** Discard SkShaders not exposed by the Android Java API. */
17
18void CheckShader(SkPaint* paint) {
19 SkShader* shader = paint->getShader();
20 if (!shader) {
21 return;
22 }
23
24 if (shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
25 return;
26 }
27 if (shader->asACompose(NULL)) {
28 return;
29 }
30 SkShader::GradientType gtype = shader->asAGradient(NULL);
31 if (gtype == SkShader::kLinear_GradientType ||
32 gtype == SkShader::kRadial_GradientType ||
33 gtype == SkShader::kSweep_GradientType) {
34 return;
35 }
36 paint->setShader(NULL);
37}
38
39void Filter(SkPaint* paint) {
40
41 uint32_t flags = paint->getFlags();
42 flags &= ~SkPaint::kLCDRenderText_Flag;
43 paint->setFlags(flags);
44
45 // Android doesn't support Xfermodes above kLighten_Mode
46 SkXfermode::Mode mode;
47 SkXfermode::AsMode(paint->getXfermode(), &mode);
48 if (mode > SkXfermode::kLighten_Mode) {
49 paint->setXfermode(NULL);
50 }
51
52 // Force bilinear scaling or none
53 if (paint->getFilterQuality() != kNone_SkFilterQuality) {
54 paint->setFilterQuality(kLow_SkFilterQuality);
55 }
56
57 CheckShader(paint);
58
59 // Android SDK only supports mode & matrix color filters
60 // (and, again, no modes above kLighten_Mode).
61 SkColorFilter* cf = paint->getColorFilter();
62 if (cf) {
63 SkColor color;
64 SkXfermode::Mode mode;
65 SkScalar srcColorMatrix[20];
66 bool isMode = cf->asColorMode(&color, &mode);
67 if (isMode && mode > SkXfermode::kLighten_Mode) {
68 paint->setColorFilter(
69 SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode));
70 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
71 paint->setColorFilter(NULL);
72 }
73 }
74
75#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
76 SkPathEffect* pe = paint->getPathEffect();
77 if (pe && !pe->exposedInAndroidJavaAPI()) {
78 paint->setPathEffect(NULL);
79 }
80#endif
81
82 // TODO: Android doesn't support all the flags that can be passed to
83 // blur filters; we need plumbing to get them out.
84
85 paint->setImageFilter(NULL);
86 paint->setLooper(NULL);
87};
88
89} // namespace
90
91#define FILTER(p) \
92 SkPaint filteredPaint(p); \
93 Filter(&filteredPaint);
94
95#define FILTER_PTR(p) \
96 SkTLazy<SkPaint> lazyPaint; \
97 SkPaint* filteredPaint = (SkPaint*) p; \
98 if (p) { \
99 filteredPaint = lazyPaint.set(*p); \
100 Filter(filteredPaint); \
101 }
102
103
104SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(NULL) { }
105
106void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }
107
108void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
109 FILTER(paint);
110 fProxyTarget->drawPaint(filteredPaint);
111}
112void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
113 size_t count,
114 const SkPoint pts[],
115 const SkPaint& paint) {
116 FILTER(paint);
117 fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
118}
119void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
120 FILTER(paint);
121 fProxyTarget->drawOval(r, filteredPaint);
122}
123void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
124 FILTER(paint);
125 fProxyTarget->drawRect(r, filteredPaint);
126}
127void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
128 FILTER(paint);
129 fProxyTarget->drawRRect(r, filteredPaint);
130}
131void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
132 FILTER(paint);
133 fProxyTarget->drawPath(path, filteredPaint);
134}
135void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
136 SkScalar left,
137 SkScalar top,
138 const SkPaint* paint) {
139 FILTER_PTR(paint);
140 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
141}
142void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
143 const SkRect* src,
144 const SkRect& dst,
145 const SkPaint* paint,
scroggoaa80e422015-07-31 14:29:26 -0700146 SkCanvas::SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700147 FILTER_PTR(paint);
scroggoaa80e422015-07-31 14:29:26 -0700148 fProxyTarget->drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700149}
150void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
151 const SkIRect& center,
152 const SkRect& dst,
153 const SkPaint* paint) {
154 FILTER_PTR(paint);
155 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
156}
157void SkAndroidSDKCanvas::onDrawSprite(const SkBitmap& bitmap,
158 int left,
159 int top,
160 const SkPaint* paint) {
161 FILTER_PTR(paint);
162 fProxyTarget->drawSprite(bitmap, left, top, filteredPaint);
163}
164void 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,
206 size_t byteLength,
207 const SkPath& path,
208 const SkMatrix* matrix,
209 const SkPaint& paint) {
210 FILTER(paint);
211 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
212}
213void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
214 SkScalar x,
215 SkScalar y,
216 const SkPaint& paint) {
217 FILTER(paint);
218 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
219}
220
221void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
222 const SkColor colors[4],
223 const SkPoint texCoords[4],
224 SkXfermode* xmode,
225 const SkPaint& paint) {
226 FILTER(paint);
227 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
228}
229
230
231void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
232 SkScalar x,
233 SkScalar y,
234 const SkPaint* paint) {
235 FILTER_PTR(paint);
236 fProxyTarget->drawImage(image, x, y, filteredPaint);
237}
238
239void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700240 const SkRect* in,
241 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400242 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700243 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700244 FILTER_PTR(paint);
djsollend8ea6b42015-08-03 06:03:06 -0700245 fProxyTarget->drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700246}
247
248void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
249 const SkMatrix* matrix,
250 const SkPaint* paint) {
251 FILTER_PTR(paint);
252 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
253}
254
reeda8db7282015-07-07 10:22:31 -0700255void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
256 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700257}
258
259SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
260 return fProxyTarget->getBaseLayerSize();
261}
262bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
263 return fProxyTarget->getClipBounds(rect);
264}
265bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
266 return fProxyTarget->getClipDeviceBounds(rect);
267}
268
269bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
270bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
271
272SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
273 const SkSurfaceProps& props) {
274 return fProxyTarget->newSurface(info, &props);
275}
276
tomhudsonb97e9092015-05-26 14:12:24 -0700277bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
278 SkASSERT(pmap);
279 SkImageInfo info;
280 size_t rowBytes;
281 const void* addr = fProxyTarget->peekPixels(&info, &rowBytes);
282 if (addr) {
283 pmap->reset(info, addr, rowBytes);
284 return true;
285 }
286 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700287}
288
tomhudsonb97e9092015-05-26 14:12:24 -0700289bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
290 SkASSERT(pmap);
291 SkImageInfo info;
292 size_t rowBytes;
293 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, NULL);
294 if (addr) {
295 pmap->reset(info, addr, rowBytes);
296 return true;
297 }
298 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700299}
300
tomhudson05e4aba2015-04-08 06:52:58 -0700301void SkAndroidSDKCanvas::willSave() {
302 fProxyTarget->save();
303}
304
305SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::willSaveLayer(const SkRect* rect,
306 const SkPaint* paint,
307 SaveFlags flags) {
308 fProxyTarget->saveLayer(rect, paint, flags);
309 return SkCanvas::kNoLayer_SaveLayerStrategy;
310}
311
312void SkAndroidSDKCanvas::willRestore() {
313 fProxyTarget->restore();
314}
315
tomhudsonf7edcde2015-03-23 12:51:20 -0700316void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700317
tomhudsonf7edcde2015-03-23 12:51:20 -0700318void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
319 fProxyTarget->concat(m);
320}
tomhudson05e4aba2015-04-08 06:52:58 -0700321
322void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
323 fProxyTarget->setMatrix(m);
324}
tomhudsonf7edcde2015-03-23 12:51:20 -0700325
326void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
327 SkRegion::Op op,
328 ClipEdgeStyle style) {
329 fProxyTarget->clipRect(rect, op, style);
330}
331
332void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
333 SkRegion::Op op,
334 ClipEdgeStyle style) {
335 fProxyTarget->clipRRect(rrect, op, style);
336}
337
338void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
339 SkRegion::Op op,
340 ClipEdgeStyle style) {
341 fProxyTarget->clipPath(path, op, style);
342}
343
344void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
345 fProxyTarget->clipRegion(region, op);
346}
347
348void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
349
350