blob: 26baaf2954d16eed0f02d5a40fcc3187315b1241 [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,
146 DrawBitmapRectFlags flags) {
147 FILTER_PTR(paint);
148 fProxyTarget->drawBitmapRectToRect(bitmap, src, dst, filteredPaint, flags);
149}
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,
240 const SkRect* in,
241 const SkRect& out,
242 const SkPaint* paint) {
243 FILTER_PTR(paint);
244 fProxyTarget->drawImageRect(image, in, out, filteredPaint);
245}
246
247void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
248 const SkMatrix* matrix,
249 const SkPaint* paint) {
250 FILTER_PTR(paint);
251 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
252}
253
reeda8db7282015-07-07 10:22:31 -0700254void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
255 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700256}
257
258SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
259 return fProxyTarget->getBaseLayerSize();
260}
261bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
262 return fProxyTarget->getClipBounds(rect);
263}
264bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
265 return fProxyTarget->getClipDeviceBounds(rect);
266}
267
268bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
269bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
270
271SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
272 const SkSurfaceProps& props) {
273 return fProxyTarget->newSurface(info, &props);
274}
275
tomhudsonb97e9092015-05-26 14:12:24 -0700276bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
277 SkASSERT(pmap);
278 SkImageInfo info;
279 size_t rowBytes;
280 const void* addr = fProxyTarget->peekPixels(&info, &rowBytes);
281 if (addr) {
282 pmap->reset(info, addr, rowBytes);
283 return true;
284 }
285 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700286}
287
tomhudsonb97e9092015-05-26 14:12:24 -0700288bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
289 SkASSERT(pmap);
290 SkImageInfo info;
291 size_t rowBytes;
292 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, NULL);
293 if (addr) {
294 pmap->reset(info, addr, rowBytes);
295 return true;
296 }
297 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700298}
299
tomhudson05e4aba2015-04-08 06:52:58 -0700300void SkAndroidSDKCanvas::willSave() {
301 fProxyTarget->save();
302}
303
304SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::willSaveLayer(const SkRect* rect,
305 const SkPaint* paint,
306 SaveFlags flags) {
307 fProxyTarget->saveLayer(rect, paint, flags);
308 return SkCanvas::kNoLayer_SaveLayerStrategy;
309}
310
311void SkAndroidSDKCanvas::willRestore() {
312 fProxyTarget->restore();
313}
314
tomhudsonf7edcde2015-03-23 12:51:20 -0700315void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700316
tomhudsonf7edcde2015-03-23 12:51:20 -0700317void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
318 fProxyTarget->concat(m);
319}
tomhudson05e4aba2015-04-08 06:52:58 -0700320
321void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
322 fProxyTarget->setMatrix(m);
323}
tomhudsonf7edcde2015-03-23 12:51:20 -0700324
325void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
326 SkRegion::Op op,
327 ClipEdgeStyle style) {
328 fProxyTarget->clipRect(rect, op, style);
329}
330
331void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
332 SkRegion::Op op,
333 ClipEdgeStyle style) {
334 fProxyTarget->clipRRect(rrect, op, style);
335}
336
337void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
338 SkRegion::Op op,
339 ClipEdgeStyle style) {
340 fProxyTarget->clipPath(path, op, style);
341}
342
343void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
344 fProxyTarget->clipRegion(region, op);
345}
346
347void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
348
349