blob: 44ceccb15c7cb69970109a575308b68e9dc692f1 [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
reedf5822822015-08-19 11:46:38 -070028 if (shader->isABitmap()) {
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
49 // Android doesn't support Xfermodes above kLighten_Mode
50 SkXfermode::Mode mode;
51 SkXfermode::AsMode(paint->getXfermode(), &mode);
52 if (mode > SkXfermode::kLighten_Mode) {
halcanary96fcdcc2015-08-27 07:41:13 -070053 paint->setXfermode(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070054 }
55
56 // Force bilinear scaling or none
57 if (paint->getFilterQuality() != kNone_SkFilterQuality) {
58 paint->setFilterQuality(kLow_SkFilterQuality);
59 }
60
61 CheckShader(paint);
62
63 // Android SDK only supports mode & matrix color filters
64 // (and, again, no modes above kLighten_Mode).
65 SkColorFilter* cf = paint->getColorFilter();
66 if (cf) {
67 SkColor color;
68 SkXfermode::Mode mode;
69 SkScalar srcColorMatrix[20];
70 bool isMode = cf->asColorMode(&color, &mode);
71 if (isMode && mode > SkXfermode::kLighten_Mode) {
72 paint->setColorFilter(
reedd053ce92016-03-22 10:17:23 -070073 SkColorFilter::MakeModeFilter(color, SkXfermode::kSrcOver_Mode));
tomhudsonf7edcde2015-03-23 12:51:20 -070074 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -070075 paint->setColorFilter(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070076 }
77 }
78
79#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
80 SkPathEffect* pe = paint->getPathEffect();
81 if (pe && !pe->exposedInAndroidJavaAPI()) {
halcanary96fcdcc2015-08-27 07:41:13 -070082 paint->setPathEffect(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070083 }
84#endif
85
86 // TODO: Android doesn't support all the flags that can be passed to
87 // blur filters; we need plumbing to get them out.
88
halcanary96fcdcc2015-08-27 07:41:13 -070089 paint->setImageFilter(nullptr);
90 paint->setLooper(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070091};
92
93} // namespace
94
95#define FILTER(p) \
96 SkPaint filteredPaint(p); \
97 Filter(&filteredPaint);
98
99#define FILTER_PTR(p) \
100 SkTLazy<SkPaint> lazyPaint; \
101 SkPaint* filteredPaint = (SkPaint*) p; \
102 if (p) { \
103 filteredPaint = lazyPaint.set(*p); \
104 Filter(filteredPaint); \
105 }
106
107
halcanary96fcdcc2015-08-27 07:41:13 -0700108SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { }
tomhudsonf7edcde2015-03-23 12:51:20 -0700109
110void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }
111
112void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
113 FILTER(paint);
114 fProxyTarget->drawPaint(filteredPaint);
115}
116void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
117 size_t count,
118 const SkPoint pts[],
119 const SkPaint& paint) {
120 FILTER(paint);
121 fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
122}
123void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
124 FILTER(paint);
125 fProxyTarget->drawOval(r, filteredPaint);
126}
bsalomonac3aa242016-08-19 11:25:19 -0700127void SkAndroidSDKCanvas::onDrawArc(const SkRect& r, SkScalar startAngle, SkScalar sweepAngle,
128 bool useCenter, const SkPaint& paint) {
129 FILTER(paint);
130 fProxyTarget->drawArc(r, startAngle, sweepAngle, useCenter, filteredPaint);
131}
tomhudsonf7edcde2015-03-23 12:51:20 -0700132void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
133 FILTER(paint);
134 fProxyTarget->drawRect(r, filteredPaint);
135}
136void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
137 FILTER(paint);
138 fProxyTarget->drawRRect(r, filteredPaint);
139}
140void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
141 FILTER(paint);
142 fProxyTarget->drawPath(path, filteredPaint);
143}
144void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
145 SkScalar left,
146 SkScalar top,
147 const SkPaint* paint) {
148 FILTER_PTR(paint);
149 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
150}
151void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
152 const SkRect* src,
153 const SkRect& dst,
154 const SkPaint* paint,
scroggoaa80e422015-07-31 14:29:26 -0700155 SkCanvas::SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700156 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700157 fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700158}
159void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
160 const SkIRect& center,
161 const SkRect& dst,
162 const SkPaint* paint) {
163 FILTER_PTR(paint);
164 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
165}
tomhudsonf7edcde2015-03-23 12:51:20 -0700166void 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,
reed45561a02016-07-07 12:47:17 -0700208 size_t byteLength,
209 const SkPath& path,
210 const SkMatrix* matrix,
211 const SkPaint& paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700212 FILTER(paint);
213 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
214}
reed45561a02016-07-07 12:47:17 -0700215void SkAndroidSDKCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
216 const SkRSXform xform[], const SkRect* cull,
217 const SkPaint& paint) {
218 FILTER(paint);
219 fProxyTarget->drawTextRSXform(text, byteLength, xform, cull, filteredPaint);
220}
tomhudsonf7edcde2015-03-23 12:51:20 -0700221void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
222 SkScalar x,
223 SkScalar y,
224 const SkPaint& paint) {
225 FILTER(paint);
226 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
227}
228
229void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
230 const SkColor colors[4],
231 const SkPoint texCoords[4],
232 SkXfermode* xmode,
233 const SkPaint& paint) {
234 FILTER(paint);
235 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
236}
237
238
239void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
240 SkScalar x,
241 SkScalar y,
242 const SkPaint* paint) {
243 FILTER_PTR(paint);
244 fProxyTarget->drawImage(image, x, y, filteredPaint);
245}
246
247void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700248 const SkRect* in,
249 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400250 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700251 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700252 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700253 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700254}
255
256void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
tomhudson45863342015-10-01 08:02:22 -0700257 const SkMatrix* matrix,
258 const SkPaint* paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700259 FILTER_PTR(paint);
260 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
261}
262
tomhudson45863342015-10-01 08:02:22 -0700263void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
264 const SkRSXform xform[],
265 const SkRect tex[],
266 const SkColor colors[],
267 int count,
268 SkXfermode::Mode mode,
269 const SkRect* cullRect,
270 const SkPaint* paint) {
271 FILTER_PTR(paint);
272 fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
273 filteredPaint);
274}
275
276void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
277 const SkIRect& center,
278 const SkRect& dst,
279 const SkPaint* paint) {
280 FILTER_PTR(paint);
281 fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
282}
283
284
reeda8db7282015-07-07 10:22:31 -0700285void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
286 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700287}
288
289SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
290 return fProxyTarget->getBaseLayerSize();
291}
292bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
293 return fProxyTarget->getClipBounds(rect);
294}
295bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
296 return fProxyTarget->getClipDeviceBounds(rect);
297}
298
299bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
300bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
301
reede8f30622016-03-23 18:59:25 -0700302sk_sp<SkSurface> SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
303 const SkSurfaceProps& props) {
304 return fProxyTarget->makeSurface(info, &props);
tomhudsonf7edcde2015-03-23 12:51:20 -0700305}
306
tomhudsonb97e9092015-05-26 14:12:24 -0700307bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
reed6ceeebd2016-03-09 14:26:26 -0800308 return fProxyTarget->peekPixels(pmap);
tomhudsonf7edcde2015-03-23 12:51:20 -0700309}
310
tomhudsonb97e9092015-05-26 14:12:24 -0700311bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
312 SkASSERT(pmap);
313 SkImageInfo info;
halcanary9d524f22016-03-29 09:03:52 -0700314 size_t rowBytes;
halcanary96fcdcc2015-08-27 07:41:13 -0700315 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
tomhudsonb97e9092015-05-26 14:12:24 -0700316 if (addr) {
317 pmap->reset(info, addr, rowBytes);
318 return true;
319 }
320 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700321}
322
tomhudson05e4aba2015-04-08 06:52:58 -0700323void SkAndroidSDKCanvas::willSave() {
324 fProxyTarget->save();
325}
326
reeda2b6fdd2015-12-18 07:38:26 -0800327SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
328 fProxyTarget->saveLayer(rec);
tomhudson05e4aba2015-04-08 06:52:58 -0700329 return SkCanvas::kNoLayer_SaveLayerStrategy;
330}
331
332void SkAndroidSDKCanvas::willRestore() {
333 fProxyTarget->restore();
334}
335
tomhudsonf7edcde2015-03-23 12:51:20 -0700336void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700337
tomhudsonf7edcde2015-03-23 12:51:20 -0700338void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
339 fProxyTarget->concat(m);
340}
tomhudson05e4aba2015-04-08 06:52:58 -0700341
342void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
343 fProxyTarget->setMatrix(m);
344}
tomhudsonf7edcde2015-03-23 12:51:20 -0700345
346void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
347 SkRegion::Op op,
348 ClipEdgeStyle style) {
349 fProxyTarget->clipRect(rect, op, style);
350}
351
352void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
353 SkRegion::Op op,
354 ClipEdgeStyle style) {
355 fProxyTarget->clipRRect(rrect, op, style);
356}
357
358void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
359 SkRegion::Op op,
360 ClipEdgeStyle style) {
361 fProxyTarget->clipPath(path, op, style);
362}
363
364void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
365 fProxyTarget->clipRegion(region, op);
366}
367
368void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }