blob: a6393d2d33e4eedbb8edf39800579c530eb180ea [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"
bungemand3ebb482015-08-05 13:57:49 -070011#include "SkPaint.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070012#include "SkPathEffect.h"
13#include "SkShader.h"
bungemand3ebb482015-08-05 13:57:49 -070014#include "SkTLazy.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070015
16namespace {
17
18/** Discard SkShaders not exposed by the Android Java API. */
19
20void CheckShader(SkPaint* paint) {
21 SkShader* shader = paint->getShader();
22 if (!shader) {
23 return;
24 }
25
26 if (shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
27 return;
28 }
29 if (shader->asACompose(NULL)) {
30 return;
31 }
32 SkShader::GradientType gtype = shader->asAGradient(NULL);
33 if (gtype == SkShader::kLinear_GradientType ||
34 gtype == SkShader::kRadial_GradientType ||
35 gtype == SkShader::kSweep_GradientType) {
36 return;
37 }
38 paint->setShader(NULL);
39}
40
41void Filter(SkPaint* paint) {
42
43 uint32_t flags = paint->getFlags();
44 flags &= ~SkPaint::kLCDRenderText_Flag;
45 paint->setFlags(flags);
46
47 // Android doesn't support Xfermodes above kLighten_Mode
48 SkXfermode::Mode mode;
49 SkXfermode::AsMode(paint->getXfermode(), &mode);
50 if (mode > SkXfermode::kLighten_Mode) {
51 paint->setXfermode(NULL);
52 }
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(
71 SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode));
72 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
73 paint->setColorFilter(NULL);
74 }
75 }
76
77#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
78 SkPathEffect* pe = paint->getPathEffect();
79 if (pe && !pe->exposedInAndroidJavaAPI()) {
80 paint->setPathEffect(NULL);
81 }
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
87 paint->setImageFilter(NULL);
88 paint->setLooper(NULL);
89};
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
106SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(NULL) { }
107
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}
125void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
126 FILTER(paint);
127 fProxyTarget->drawRect(r, filteredPaint);
128}
129void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
130 FILTER(paint);
131 fProxyTarget->drawRRect(r, filteredPaint);
132}
133void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
134 FILTER(paint);
135 fProxyTarget->drawPath(path, filteredPaint);
136}
137void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
138 SkScalar left,
139 SkScalar top,
140 const SkPaint* paint) {
141 FILTER_PTR(paint);
142 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
143}
144void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
145 const SkRect* src,
146 const SkRect& dst,
147 const SkPaint* paint,
scroggoaa80e422015-07-31 14:29:26 -0700148 SkCanvas::SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700149 FILTER_PTR(paint);
scroggoaa80e422015-07-31 14:29:26 -0700150 fProxyTarget->drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700151}
152void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
153 const SkIRect& center,
154 const SkRect& dst,
155 const SkPaint* paint) {
156 FILTER_PTR(paint);
157 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
158}
159void SkAndroidSDKCanvas::onDrawSprite(const SkBitmap& bitmap,
160 int left,
161 int top,
162 const SkPaint* paint) {
163 FILTER_PTR(paint);
164 fProxyTarget->drawSprite(bitmap, left, top, filteredPaint);
165}
166void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
167 int vertexCount,
168 const SkPoint vertices[],
169 const SkPoint texs[], const SkColor colors[], SkXfermode* xMode,
170 const uint16_t indices[], int indexCount,
171 const SkPaint& paint) {
172 FILTER(paint);
173 fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
174 xMode, indices, indexCount, filteredPaint);
175}
176
177void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
178 const SkRRect& inner,
179 const SkPaint& paint) {
180 FILTER(paint);
181 fProxyTarget->drawDRRect(outer, inner, filteredPaint);
182}
183
184void SkAndroidSDKCanvas::onDrawText(const void* text,
185 size_t byteLength,
186 SkScalar x,
187 SkScalar y,
188 const SkPaint& paint) {
189 FILTER(paint);
190 fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
191}
192void SkAndroidSDKCanvas::onDrawPosText(const void* text,
193 size_t byteLength,
194 const SkPoint pos[],
195 const SkPaint& paint) {
196 FILTER(paint);
197 fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
198}
199void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
200 size_t byteLength,
201 const SkScalar xpos[],
202 SkScalar constY,
203 const SkPaint& paint) {
204 FILTER(paint);
205 fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
206}
207void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
208 size_t byteLength,
209 const SkPath& path,
210 const SkMatrix* matrix,
211 const SkPaint& paint) {
212 FILTER(paint);
213 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
214}
215void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
216 SkScalar x,
217 SkScalar y,
218 const SkPaint& paint) {
219 FILTER(paint);
220 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
221}
222
223void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
224 const SkColor colors[4],
225 const SkPoint texCoords[4],
226 SkXfermode* xmode,
227 const SkPaint& paint) {
228 FILTER(paint);
229 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
230}
231
232
233void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
234 SkScalar x,
235 SkScalar y,
236 const SkPaint* paint) {
237 FILTER_PTR(paint);
238 fProxyTarget->drawImage(image, x, y, filteredPaint);
239}
240
241void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700242 const SkRect* in,
243 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400244 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700245 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700246 FILTER_PTR(paint);
djsollend8ea6b42015-08-03 06:03:06 -0700247 fProxyTarget->drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700248}
249
250void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
251 const SkMatrix* matrix,
252 const SkPaint* paint) {
253 FILTER_PTR(paint);
254 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
255}
256
reeda8db7282015-07-07 10:22:31 -0700257void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
258 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700259}
260
261SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
262 return fProxyTarget->getBaseLayerSize();
263}
264bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
265 return fProxyTarget->getClipBounds(rect);
266}
267bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
268 return fProxyTarget->getClipDeviceBounds(rect);
269}
270
271bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
272bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
273
274SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
275 const SkSurfaceProps& props) {
276 return fProxyTarget->newSurface(info, &props);
277}
278
tomhudsonb97e9092015-05-26 14:12:24 -0700279bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
280 SkASSERT(pmap);
281 SkImageInfo info;
282 size_t rowBytes;
283 const void* addr = fProxyTarget->peekPixels(&info, &rowBytes);
284 if (addr) {
285 pmap->reset(info, addr, rowBytes);
286 return true;
287 }
288 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700289}
290
tomhudsonb97e9092015-05-26 14:12:24 -0700291bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
292 SkASSERT(pmap);
293 SkImageInfo info;
294 size_t rowBytes;
295 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, NULL);
296 if (addr) {
297 pmap->reset(info, addr, rowBytes);
298 return true;
299 }
300 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700301}
302
tomhudson05e4aba2015-04-08 06:52:58 -0700303void SkAndroidSDKCanvas::willSave() {
304 fProxyTarget->save();
305}
306
307SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::willSaveLayer(const SkRect* rect,
308 const SkPaint* paint,
309 SaveFlags flags) {
310 fProxyTarget->saveLayer(rect, paint, flags);
311 return SkCanvas::kNoLayer_SaveLayerStrategy;
312}
313
314void SkAndroidSDKCanvas::willRestore() {
315 fProxyTarget->restore();
316}
317
tomhudsonf7edcde2015-03-23 12:51:20 -0700318void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700319
tomhudsonf7edcde2015-03-23 12:51:20 -0700320void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
321 fProxyTarget->concat(m);
322}
tomhudson05e4aba2015-04-08 06:52:58 -0700323
324void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
325 fProxyTarget->setMatrix(m);
326}
tomhudsonf7edcde2015-03-23 12:51:20 -0700327
328void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
329 SkRegion::Op op,
330 ClipEdgeStyle style) {
331 fProxyTarget->clipRect(rect, op, style);
332}
333
334void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
335 SkRegion::Op op,
336 ClipEdgeStyle style) {
337 fProxyTarget->clipRRect(rrect, op, style);
338}
339
340void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
341 SkRegion::Op op,
342 ClipEdgeStyle style) {
343 fProxyTarget->clipPath(path, op, style);
344}
345
346void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
347 fProxyTarget->clipRegion(region, op);
348}
349
350void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
351
352