blob: 1deb97cbc67cb603574c505e6d57567f5b1d1b6c [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
reedf5822822015-08-19 11:46:38 -070026 if (shader->isABitmap()) {
tomhudsonf7edcde2015-03-23 12:51:20 -070027 return;
28 }
halcanary96fcdcc2015-08-27 07:41:13 -070029 if (shader->asACompose(nullptr)) {
tomhudsonf7edcde2015-03-23 12:51:20 -070030 return;
31 }
halcanary96fcdcc2015-08-27 07:41:13 -070032 SkShader::GradientType gtype = shader->asAGradient(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070033 if (gtype == SkShader::kLinear_GradientType ||
34 gtype == SkShader::kRadial_GradientType ||
35 gtype == SkShader::kSweep_GradientType) {
36 return;
37 }
halcanary96fcdcc2015-08-27 07:41:13 -070038 paint->setShader(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070039}
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) {
halcanary96fcdcc2015-08-27 07:41:13 -070051 paint->setXfermode(nullptr);
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(
71 SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode));
72 } 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}
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);
reede47829b2015-08-06 10:02:53 -0700150 fProxyTarget->legacy_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}
tomhudsonf7edcde2015-03-23 12:51:20 -0700159void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
160 int vertexCount,
161 const SkPoint vertices[],
162 const SkPoint texs[], const SkColor colors[], SkXfermode* xMode,
163 const uint16_t indices[], int indexCount,
164 const SkPaint& paint) {
165 FILTER(paint);
166 fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
167 xMode, indices, indexCount, filteredPaint);
168}
169
170void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
171 const SkRRect& inner,
172 const SkPaint& paint) {
173 FILTER(paint);
174 fProxyTarget->drawDRRect(outer, inner, filteredPaint);
175}
176
177void SkAndroidSDKCanvas::onDrawText(const void* text,
178 size_t byteLength,
179 SkScalar x,
180 SkScalar y,
181 const SkPaint& paint) {
182 FILTER(paint);
183 fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
184}
185void SkAndroidSDKCanvas::onDrawPosText(const void* text,
186 size_t byteLength,
187 const SkPoint pos[],
188 const SkPaint& paint) {
189 FILTER(paint);
190 fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
191}
192void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
193 size_t byteLength,
194 const SkScalar xpos[],
195 SkScalar constY,
196 const SkPaint& paint) {
197 FILTER(paint);
198 fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
199}
200void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
201 size_t byteLength,
202 const SkPath& path,
203 const SkMatrix* matrix,
204 const SkPaint& paint) {
205 FILTER(paint);
206 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
207}
208void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
209 SkScalar x,
210 SkScalar y,
211 const SkPaint& paint) {
212 FILTER(paint);
213 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
214}
215
216void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
217 const SkColor colors[4],
218 const SkPoint texCoords[4],
219 SkXfermode* xmode,
220 const SkPaint& paint) {
221 FILTER(paint);
222 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
223}
224
225
226void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
227 SkScalar x,
228 SkScalar y,
229 const SkPaint* paint) {
230 FILTER_PTR(paint);
231 fProxyTarget->drawImage(image, x, y, filteredPaint);
232}
233
234void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700235 const SkRect* in,
236 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400237 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700238 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700239 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700240 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700241}
242
243void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
tomhudson45863342015-10-01 08:02:22 -0700244 const SkMatrix* matrix,
245 const SkPaint* paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700246 FILTER_PTR(paint);
247 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
248}
249
tomhudson45863342015-10-01 08:02:22 -0700250void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
251 const SkRSXform xform[],
252 const SkRect tex[],
253 const SkColor colors[],
254 int count,
255 SkXfermode::Mode mode,
256 const SkRect* cullRect,
257 const SkPaint* paint) {
258 FILTER_PTR(paint);
259 fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
260 filteredPaint);
261}
262
263void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
264 const SkIRect& center,
265 const SkRect& dst,
266 const SkPaint* paint) {
267 FILTER_PTR(paint);
268 fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
269}
270
271
reeda8db7282015-07-07 10:22:31 -0700272void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
273 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700274}
275
276SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
277 return fProxyTarget->getBaseLayerSize();
278}
279bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
280 return fProxyTarget->getClipBounds(rect);
281}
282bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
283 return fProxyTarget->getClipDeviceBounds(rect);
284}
285
286bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
287bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
288
289SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
290 const SkSurfaceProps& props) {
291 return fProxyTarget->newSurface(info, &props);
292}
293
tomhudsonb97e9092015-05-26 14:12:24 -0700294bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
reed6ceeebd2016-03-09 14:26:26 -0800295 return fProxyTarget->peekPixels(pmap);
tomhudsonf7edcde2015-03-23 12:51:20 -0700296}
297
tomhudsonb97e9092015-05-26 14:12:24 -0700298bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
299 SkASSERT(pmap);
300 SkImageInfo info;
301 size_t rowBytes;
halcanary96fcdcc2015-08-27 07:41:13 -0700302 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
tomhudsonb97e9092015-05-26 14:12:24 -0700303 if (addr) {
304 pmap->reset(info, addr, rowBytes);
305 return true;
306 }
307 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700308}
309
tomhudson05e4aba2015-04-08 06:52:58 -0700310void SkAndroidSDKCanvas::willSave() {
311 fProxyTarget->save();
312}
313
reeda2b6fdd2015-12-18 07:38:26 -0800314SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
315 fProxyTarget->saveLayer(rec);
tomhudson05e4aba2015-04-08 06:52:58 -0700316 return SkCanvas::kNoLayer_SaveLayerStrategy;
317}
318
319void SkAndroidSDKCanvas::willRestore() {
320 fProxyTarget->restore();
321}
322
tomhudsonf7edcde2015-03-23 12:51:20 -0700323void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700324
tomhudsonf7edcde2015-03-23 12:51:20 -0700325void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
326 fProxyTarget->concat(m);
327}
tomhudson05e4aba2015-04-08 06:52:58 -0700328
329void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
330 fProxyTarget->setMatrix(m);
331}
tomhudsonf7edcde2015-03-23 12:51:20 -0700332
333void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
334 SkRegion::Op op,
335 ClipEdgeStyle style) {
336 fProxyTarget->clipRect(rect, op, style);
337}
338
339void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
340 SkRegion::Op op,
341 ClipEdgeStyle style) {
342 fProxyTarget->clipRRect(rrect, op, style);
343}
344
345void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
346 SkRegion::Op op,
347 ClipEdgeStyle style) {
348 fProxyTarget->clipPath(path, op, style);
349}
350
351void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
352 fProxyTarget->clipRegion(region, op);
353}
354
355void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
356
357