OLD | NEW |
| (Empty) |
1 /* | |
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 "SkPaint.h" | |
12 #include "SkPathEffect.h" | |
13 #include "SkShader.h" | |
14 #include "SkTLazy.h" | |
15 | |
16 namespace { | |
17 | |
18 /** Discard SkShaders not exposed by the Android Java API. */ | |
19 | |
20 void CheckShader(SkPaint* paint) { | |
21 SkShader* shader = paint->getShader(); | |
22 if (!shader) { | |
23 return; | |
24 } | |
25 | |
26 if (shader->isABitmap()) { | |
27 return; | |
28 } | |
29 if (shader->asACompose(nullptr)) { | |
30 return; | |
31 } | |
32 SkShader::GradientType gtype = shader->asAGradient(nullptr); | |
33 if (gtype == SkShader::kLinear_GradientType || | |
34 gtype == SkShader::kRadial_GradientType || | |
35 gtype == SkShader::kSweep_GradientType) { | |
36 return; | |
37 } | |
38 paint->setShader(nullptr); | |
39 } | |
40 | |
41 void 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(nullptr); | |
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(nullptr); | |
74 } | |
75 } | |
76 | |
77 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | |
78 SkPathEffect* pe = paint->getPathEffect(); | |
79 if (pe && !pe->exposedInAndroidJavaAPI()) { | |
80 paint->setPathEffect(nullptr); | |
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(nullptr); | |
88 paint->setLooper(nullptr); | |
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 | |
106 SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { } | |
107 | |
108 void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget;
} | |
109 | |
110 void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) { | |
111 FILTER(paint); | |
112 fProxyTarget->drawPaint(filteredPaint); | |
113 } | |
114 void 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 } | |
121 void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) { | |
122 FILTER(paint); | |
123 fProxyTarget->drawOval(r, filteredPaint); | |
124 } | |
125 void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { | |
126 FILTER(paint); | |
127 fProxyTarget->drawRect(r, filteredPaint); | |
128 } | |
129 void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) { | |
130 FILTER(paint); | |
131 fProxyTarget->drawRRect(r, filteredPaint); | |
132 } | |
133 void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { | |
134 FILTER(paint); | |
135 fProxyTarget->drawPath(path, filteredPaint); | |
136 } | |
137 void 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 } | |
144 void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap, | |
145 const SkRect* src, | |
146 const SkRect& dst, | |
147 const SkPaint* paint, | |
148 SkCanvas::SrcRectConstraint c
onstraint) { | |
149 FILTER_PTR(paint); | |
150 fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constra
int); | |
151 } | |
152 void 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 } | |
159 void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode, | |
160 int vertexCount, | |
161 const SkPoint vertices[], | |
162 const SkPoint texs[], const SkColor colors[], SkXfermode* xM
ode, | |
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 | |
170 void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer, | |
171 const SkRRect& inner, | |
172 const SkPaint& paint) { | |
173 FILTER(paint); | |
174 fProxyTarget->drawDRRect(outer, inner, filteredPaint); | |
175 } | |
176 | |
177 void 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 } | |
185 void 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 } | |
192 void 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 } | |
200 void 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 } | |
208 void 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 | |
216 void 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 | |
226 void 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 | |
234 void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image, | |
235 const SkRect* in, | |
236 const SkRect& out, | |
237 const SkPaint* paint, | |
238 SrcRectConstraint constraint) { | |
239 FILTER_PTR(paint); | |
240 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint
); | |
241 } | |
242 | |
243 void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture, | |
244 const SkMatrix* matrix, | |
245 const SkPaint* paint) { | |
246 FILTER_PTR(paint); | |
247 fProxyTarget->drawPicture(picture, matrix, filteredPaint); | |
248 } | |
249 | |
250 void 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 | |
263 void 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 | |
272 void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* ma
trix) { | |
273 fProxyTarget->drawDrawable(drawable, matrix); | |
274 } | |
275 | |
276 SkISize SkAndroidSDKCanvas::getBaseLayerSize() const { | |
277 return fProxyTarget->getBaseLayerSize(); | |
278 } | |
279 bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const { | |
280 return fProxyTarget->getClipBounds(rect); | |
281 } | |
282 bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const { | |
283 return fProxyTarget->getClipDeviceBounds(rect); | |
284 } | |
285 | |
286 bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(
); } | |
287 bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect();
} | |
288 | |
289 SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info, | |
290 const SkSurfaceProps& props
) { | |
291 return fProxyTarget->newSurface(info, &props); | |
292 } | |
293 | |
294 bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) { | |
295 SkASSERT(pmap); | |
296 SkImageInfo info; | |
297 size_t rowBytes; | |
298 const void* addr = fProxyTarget->peekPixels(&info, &rowBytes); | |
299 if (addr) { | |
300 pmap->reset(info, addr, rowBytes); | |
301 return true; | |
302 } | |
303 return false; | |
304 } | |
305 | |
306 bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) { | |
307 SkASSERT(pmap); | |
308 SkImageInfo info; | |
309 size_t rowBytes; | |
310 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, null
ptr); | |
311 if (addr) { | |
312 pmap->reset(info, addr, rowBytes); | |
313 return true; | |
314 } | |
315 return false; | |
316 } | |
317 | |
318 void SkAndroidSDKCanvas::willSave() { | |
319 fProxyTarget->save(); | |
320 } | |
321 | |
322 SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveL
ayerRec& rec) { | |
323 fProxyTarget->saveLayer(rec); | |
324 return SkCanvas::kNoLayer_SaveLayerStrategy; | |
325 } | |
326 | |
327 void SkAndroidSDKCanvas::willRestore() { | |
328 fProxyTarget->restore(); | |
329 } | |
330 | |
331 void SkAndroidSDKCanvas::didRestore() { } | |
332 | |
333 void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) { | |
334 fProxyTarget->concat(m); | |
335 } | |
336 | |
337 void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) { | |
338 fProxyTarget->setMatrix(m); | |
339 } | |
340 | |
341 void SkAndroidSDKCanvas::onClipRect(const SkRect& rect, | |
342 SkRegion::Op op, | |
343 ClipEdgeStyle style) { | |
344 fProxyTarget->clipRect(rect, op, style); | |
345 } | |
346 | |
347 void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect, | |
348 SkRegion::Op op, | |
349 ClipEdgeStyle style) { | |
350 fProxyTarget->clipRRect(rrect, op, style); | |
351 } | |
352 | |
353 void SkAndroidSDKCanvas::onClipPath(const SkPath& path, | |
354 SkRegion::Op op, | |
355 ClipEdgeStyle style) { | |
356 fProxyTarget->clipPath(path, op, style); | |
357 } | |
358 | |
359 void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) { | |
360 fProxyTarget->clipRegion(region, op); | |
361 } | |
362 | |
363 void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); } | |
364 | |
365 | |
OLD | NEW |