blob: 35b1581fdab2df6175120e9cc9991cab1f19336e [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"
bungemand3ebb482015-08-05 13:57:49 -070015#include "SkTLazy.h"
tomhudsonf7edcde2015-03-23 12:51:20 -070016
17namespace {
18
19/** Discard SkShaders not exposed by the Android Java API. */
20
21void CheckShader(SkPaint* paint) {
22 SkShader* shader = paint->getShader();
23 if (!shader) {
24 return;
25 }
26
reedf5822822015-08-19 11:46:38 -070027 if (shader->isABitmap()) {
tomhudsonf7edcde2015-03-23 12:51:20 -070028 return;
29 }
halcanary96fcdcc2015-08-27 07:41:13 -070030 if (shader->asACompose(nullptr)) {
tomhudsonf7edcde2015-03-23 12:51:20 -070031 return;
32 }
halcanary96fcdcc2015-08-27 07:41:13 -070033 SkShader::GradientType gtype = shader->asAGradient(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070034 if (gtype == SkShader::kLinear_GradientType ||
35 gtype == SkShader::kRadial_GradientType ||
36 gtype == SkShader::kSweep_GradientType) {
37 return;
38 }
halcanary96fcdcc2015-08-27 07:41:13 -070039 paint->setShader(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070040}
41
42void Filter(SkPaint* paint) {
43
44 uint32_t flags = paint->getFlags();
45 flags &= ~SkPaint::kLCDRenderText_Flag;
46 paint->setFlags(flags);
47
48 // Android doesn't support Xfermodes above kLighten_Mode
49 SkXfermode::Mode mode;
50 SkXfermode::AsMode(paint->getXfermode(), &mode);
51 if (mode > SkXfermode::kLighten_Mode) {
halcanary96fcdcc2015-08-27 07:41:13 -070052 paint->setXfermode(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070053 }
54
55 // Force bilinear scaling or none
56 if (paint->getFilterQuality() != kNone_SkFilterQuality) {
57 paint->setFilterQuality(kLow_SkFilterQuality);
58 }
59
60 CheckShader(paint);
61
62 // Android SDK only supports mode & matrix color filters
63 // (and, again, no modes above kLighten_Mode).
64 SkColorFilter* cf = paint->getColorFilter();
65 if (cf) {
66 SkColor color;
67 SkXfermode::Mode mode;
68 SkScalar srcColorMatrix[20];
69 bool isMode = cf->asColorMode(&color, &mode);
70 if (isMode && mode > SkXfermode::kLighten_Mode) {
71 paint->setColorFilter(
72 SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode));
73 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -070074 paint->setColorFilter(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070075 }
76 }
77
78#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
79 SkPathEffect* pe = paint->getPathEffect();
80 if (pe && !pe->exposedInAndroidJavaAPI()) {
halcanary96fcdcc2015-08-27 07:41:13 -070081 paint->setPathEffect(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070082 }
83#endif
84
85 // TODO: Android doesn't support all the flags that can be passed to
86 // blur filters; we need plumbing to get them out.
87
halcanary96fcdcc2015-08-27 07:41:13 -070088 paint->setImageFilter(nullptr);
89 paint->setLooper(nullptr);
tomhudsonf7edcde2015-03-23 12:51:20 -070090};
91
92} // namespace
93
94#define FILTER(p) \
95 SkPaint filteredPaint(p); \
96 Filter(&filteredPaint);
97
98#define FILTER_PTR(p) \
99 SkTLazy<SkPaint> lazyPaint; \
100 SkPaint* filteredPaint = (SkPaint*) p; \
101 if (p) { \
102 filteredPaint = lazyPaint.set(*p); \
103 Filter(filteredPaint); \
104 }
105
106
halcanary96fcdcc2015-08-27 07:41:13 -0700107SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { }
tomhudsonf7edcde2015-03-23 12:51:20 -0700108
109void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }
110
111void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
112 FILTER(paint);
113 fProxyTarget->drawPaint(filteredPaint);
114}
115void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
116 size_t count,
117 const SkPoint pts[],
118 const SkPaint& paint) {
119 FILTER(paint);
120 fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
121}
122void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
123 FILTER(paint);
124 fProxyTarget->drawOval(r, filteredPaint);
125}
126void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
127 FILTER(paint);
128 fProxyTarget->drawRect(r, filteredPaint);
129}
130void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
131 FILTER(paint);
132 fProxyTarget->drawRRect(r, filteredPaint);
133}
134void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
135 FILTER(paint);
136 fProxyTarget->drawPath(path, filteredPaint);
137}
138void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
139 SkScalar left,
140 SkScalar top,
141 const SkPaint* paint) {
142 FILTER_PTR(paint);
143 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
144}
145void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
146 const SkRect* src,
147 const SkRect& dst,
148 const SkPaint* paint,
scroggoaa80e422015-07-31 14:29:26 -0700149 SkCanvas::SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700150 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700151 fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700152}
153void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
154 const SkIRect& center,
155 const SkRect& dst,
156 const SkPaint* paint) {
157 FILTER_PTR(paint);
158 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
159}
tomhudsonf7edcde2015-03-23 12:51:20 -0700160void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
161 int vertexCount,
162 const SkPoint vertices[],
163 const SkPoint texs[], const SkColor colors[], SkXfermode* xMode,
164 const uint16_t indices[], int indexCount,
165 const SkPaint& paint) {
166 FILTER(paint);
167 fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
168 xMode, indices, indexCount, filteredPaint);
169}
170
171void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
172 const SkRRect& inner,
173 const SkPaint& paint) {
174 FILTER(paint);
175 fProxyTarget->drawDRRect(outer, inner, filteredPaint);
176}
177
178void SkAndroidSDKCanvas::onDrawText(const void* text,
179 size_t byteLength,
180 SkScalar x,
181 SkScalar y,
182 const SkPaint& paint) {
183 FILTER(paint);
184 fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
185}
186void SkAndroidSDKCanvas::onDrawPosText(const void* text,
187 size_t byteLength,
188 const SkPoint pos[],
189 const SkPaint& paint) {
190 FILTER(paint);
191 fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
192}
193void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
194 size_t byteLength,
195 const SkScalar xpos[],
196 SkScalar constY,
197 const SkPaint& paint) {
198 FILTER(paint);
199 fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
200}
201void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
202 size_t byteLength,
203 const SkPath& path,
204 const SkMatrix* matrix,
205 const SkPaint& paint) {
206 FILTER(paint);
207 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
208}
209void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
210 SkScalar x,
211 SkScalar y,
212 const SkPaint& paint) {
213 FILTER(paint);
214 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
215}
216
217void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
218 const SkColor colors[4],
219 const SkPoint texCoords[4],
220 SkXfermode* xmode,
221 const SkPaint& paint) {
222 FILTER(paint);
223 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
224}
225
226
227void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
228 SkScalar x,
229 SkScalar y,
230 const SkPaint* paint) {
231 FILTER_PTR(paint);
232 fProxyTarget->drawImage(image, x, y, filteredPaint);
233}
234
235void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
djsollend8ea6b42015-08-03 06:03:06 -0700236 const SkRect* in,
237 const SkRect& out,
Derek Sollenberger849a6202015-08-03 11:41:53 -0400238 const SkPaint* paint,
djsollend8ea6b42015-08-03 06:03:06 -0700239 SrcRectConstraint constraint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700240 FILTER_PTR(paint);
reede47829b2015-08-06 10:02:53 -0700241 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
tomhudsonf7edcde2015-03-23 12:51:20 -0700242}
243
244void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
tomhudson45863342015-10-01 08:02:22 -0700245 const SkMatrix* matrix,
246 const SkPaint* paint) {
tomhudsonf7edcde2015-03-23 12:51:20 -0700247 FILTER_PTR(paint);
248 fProxyTarget->drawPicture(picture, matrix, filteredPaint);
249}
250
tomhudson45863342015-10-01 08:02:22 -0700251void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
252 const SkRSXform xform[],
253 const SkRect tex[],
254 const SkColor colors[],
255 int count,
256 SkXfermode::Mode mode,
257 const SkRect* cullRect,
258 const SkPaint* paint) {
259 FILTER_PTR(paint);
260 fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
261 filteredPaint);
262}
263
264void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
265 const SkIRect& center,
266 const SkRect& dst,
267 const SkPaint* paint) {
268 FILTER_PTR(paint);
269 fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
270}
271
272
reeda8db7282015-07-07 10:22:31 -0700273void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
274 fProxyTarget->drawDrawable(drawable, matrix);
tomhudsonf7edcde2015-03-23 12:51:20 -0700275}
276
277SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
278 return fProxyTarget->getBaseLayerSize();
279}
280bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
281 return fProxyTarget->getClipBounds(rect);
282}
283bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
284 return fProxyTarget->getClipDeviceBounds(rect);
285}
286
287bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
288bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
289
290SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
291 const SkSurfaceProps& props) {
292 return fProxyTarget->newSurface(info, &props);
293}
294
tomhudsonb97e9092015-05-26 14:12:24 -0700295bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
reed6ceeebd2016-03-09 14:26:26 -0800296 return fProxyTarget->peekPixels(pmap);
tomhudsonf7edcde2015-03-23 12:51:20 -0700297}
298
tomhudsonb97e9092015-05-26 14:12:24 -0700299bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
300 SkASSERT(pmap);
301 SkImageInfo info;
302 size_t rowBytes;
halcanary96fcdcc2015-08-27 07:41:13 -0700303 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
tomhudsonb97e9092015-05-26 14:12:24 -0700304 if (addr) {
305 pmap->reset(info, addr, rowBytes);
306 return true;
307 }
308 return false;
tomhudsonf7edcde2015-03-23 12:51:20 -0700309}
310
tomhudson05e4aba2015-04-08 06:52:58 -0700311void SkAndroidSDKCanvas::willSave() {
312 fProxyTarget->save();
313}
314
reeda2b6fdd2015-12-18 07:38:26 -0800315SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
316 fProxyTarget->saveLayer(rec);
tomhudson05e4aba2015-04-08 06:52:58 -0700317 return SkCanvas::kNoLayer_SaveLayerStrategy;
318}
319
320void SkAndroidSDKCanvas::willRestore() {
321 fProxyTarget->restore();
322}
323
tomhudsonf7edcde2015-03-23 12:51:20 -0700324void SkAndroidSDKCanvas::didRestore() { }
tomhudson05e4aba2015-04-08 06:52:58 -0700325
tomhudsonf7edcde2015-03-23 12:51:20 -0700326void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
327 fProxyTarget->concat(m);
328}
tomhudson05e4aba2015-04-08 06:52:58 -0700329
330void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
331 fProxyTarget->setMatrix(m);
332}
tomhudsonf7edcde2015-03-23 12:51:20 -0700333
334void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
335 SkRegion::Op op,
336 ClipEdgeStyle style) {
337 fProxyTarget->clipRect(rect, op, style);
338}
339
340void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
341 SkRegion::Op op,
342 ClipEdgeStyle style) {
343 fProxyTarget->clipRRect(rrect, op, style);
344}
345
346void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
347 SkRegion::Op op,
348 ClipEdgeStyle style) {
349 fProxyTarget->clipPath(path, op, style);
350}
351
352void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
353 fProxyTarget->clipRegion(region, op);
354}
355
356void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
357
358