• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkPathEffect.h"
12 #include "SkShader.h"
13 
14 namespace {
15 
16 /** Discard SkShaders not exposed by the Android Java API. */
17 
CheckShader(SkPaint * paint)18 void CheckShader(SkPaint* paint) {
19     SkShader* shader = paint->getShader();
20     if (!shader) {
21         return;
22     }
23 
24     if (shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
25         return;
26     }
27     if (shader->asACompose(NULL)) {
28         return;
29     }
30     SkShader::GradientType gtype = shader->asAGradient(NULL);
31     if (gtype == SkShader::kLinear_GradientType ||
32         gtype == SkShader::kRadial_GradientType ||
33         gtype == SkShader::kSweep_GradientType) {
34         return;
35     }
36     paint->setShader(NULL);
37 }
38 
Filter(SkPaint * paint)39 void Filter(SkPaint* paint) {
40 
41     uint32_t flags = paint->getFlags();
42     flags &= ~SkPaint::kLCDRenderText_Flag;
43     paint->setFlags(flags);
44 
45     // Android doesn't support Xfermodes above kLighten_Mode
46     SkXfermode::Mode mode;
47     SkXfermode::AsMode(paint->getXfermode(), &mode);
48     if (mode > SkXfermode::kLighten_Mode) {
49         paint->setXfermode(NULL);
50     }
51 
52     // Force bilinear scaling or none
53     if (paint->getFilterQuality() != kNone_SkFilterQuality) {
54         paint->setFilterQuality(kLow_SkFilterQuality);
55     }
56 
57     CheckShader(paint);
58 
59     // Android SDK only supports mode & matrix color filters
60     // (and, again, no modes above kLighten_Mode).
61     SkColorFilter* cf = paint->getColorFilter();
62     if (cf) {
63         SkColor color;
64         SkXfermode::Mode mode;
65         SkScalar srcColorMatrix[20];
66         bool isMode = cf->asColorMode(&color, &mode);
67         if (isMode && mode > SkXfermode::kLighten_Mode) {
68             paint->setColorFilter(
69                 SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode));
70         } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
71             paint->setColorFilter(NULL);
72         }
73     }
74 
75 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
76     SkPathEffect* pe = paint->getPathEffect();
77     if (pe && !pe->exposedInAndroidJavaAPI()) {
78         paint->setPathEffect(NULL);
79     }
80 #endif
81 
82     // TODO: Android doesn't support all the flags that can be passed to
83     // blur filters; we need plumbing to get them out.
84 
85     paint->setImageFilter(NULL);
86     paint->setLooper(NULL);
87 };
88 
89 }  // namespace
90 
91 #define FILTER(p)             \
92     SkPaint filteredPaint(p); \
93     Filter(&filteredPaint);
94 
95 #define FILTER_PTR(p)                          \
96     SkTLazy<SkPaint> lazyPaint;                \
97     SkPaint* filteredPaint = (SkPaint*) p;     \
98     if (p) {                                   \
99         filteredPaint = lazyPaint.set(*p);     \
100         Filter(filteredPaint);                 \
101     }
102 
103 
SkAndroidSDKCanvas()104 SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(NULL) { }
105 
reset(SkCanvas * newTarget)106 void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }
107 
onDrawPaint(const SkPaint & paint)108 void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
109     FILTER(paint);
110     fProxyTarget->drawPaint(filteredPaint);
111 }
onDrawPoints(PointMode pMode,size_t count,const SkPoint pts[],const SkPaint & paint)112 void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
113                                                size_t count,
114                                                const SkPoint pts[],
115                                                const SkPaint& paint) {
116     FILTER(paint);
117     fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
118 }
onDrawOval(const SkRect & r,const SkPaint & paint)119 void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
120     FILTER(paint);
121     fProxyTarget->drawOval(r, filteredPaint);
122 }
onDrawRect(const SkRect & r,const SkPaint & paint)123 void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
124     FILTER(paint);
125     fProxyTarget->drawRect(r, filteredPaint);
126 }
onDrawRRect(const SkRRect & r,const SkPaint & paint)127 void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
128     FILTER(paint);
129     fProxyTarget->drawRRect(r, filteredPaint);
130 }
onDrawPath(const SkPath & path,const SkPaint & paint)131 void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
132     FILTER(paint);
133     fProxyTarget->drawPath(path, filteredPaint);
134 }
onDrawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)135 void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
136                                                SkScalar left,
137                                                SkScalar top,
138                                                const SkPaint* paint) {
139     FILTER_PTR(paint);
140     fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
141 }
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)142 void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
143                                                    const SkRect* src,
144                                                    const SkRect& dst,
145                                                    const SkPaint* paint,
146                                                    DrawBitmapRectFlags flags) {
147     FILTER_PTR(paint);
148     fProxyTarget->drawBitmapRectToRect(bitmap, src, dst, filteredPaint, flags);
149 }
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)150 void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
151                                                    const SkIRect& center,
152                                                    const SkRect& dst,
153                                                    const SkPaint* paint) {
154     FILTER_PTR(paint);
155     fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
156 }
onDrawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint)157 void SkAndroidSDKCanvas::onDrawSprite(const SkBitmap& bitmap,
158                                                int left,
159                                                int top,
160                                                const SkPaint* paint) {
161     FILTER_PTR(paint);
162     fProxyTarget->drawSprite(bitmap, left, top, filteredPaint);
163 }
onDrawVertices(VertexMode vMode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode * xMode,const uint16_t indices[],int indexCount,const SkPaint & paint)164 void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
165                                                  int vertexCount,
166                                                  const SkPoint vertices[],
167                     const SkPoint texs[], const SkColor colors[], SkXfermode* xMode,
168                     const uint16_t indices[], int indexCount,
169                     const SkPaint& paint) {
170     FILTER(paint);
171     fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
172                                xMode, indices, indexCount, filteredPaint);
173 }
174 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)175 void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
176                                                const SkRRect& inner,
177                                                const SkPaint& paint) {
178     FILTER(paint);
179     fProxyTarget->drawDRRect(outer, inner, filteredPaint);
180 }
181 
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)182 void SkAndroidSDKCanvas::onDrawText(const void* text,
183                                              size_t byteLength,
184                                              SkScalar x,
185                                              SkScalar y,
186                                              const SkPaint& paint) {
187     FILTER(paint);
188     fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
189 }
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)190 void SkAndroidSDKCanvas::onDrawPosText(const void* text,
191                                                 size_t byteLength,
192                                                 const SkPoint pos[],
193                                                 const SkPaint& paint) {
194     FILTER(paint);
195     fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
196 }
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)197 void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
198                                                  size_t byteLength,
199                                                  const SkScalar xpos[],
200                                                  SkScalar constY,
201                                                  const SkPaint& paint) {
202     FILTER(paint);
203     fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
204 }
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)205 void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
206                                                    size_t byteLength,
207                                                    const SkPath& path,
208                                                    const SkMatrix* matrix,
209                                                    const SkPaint& paint) {
210     FILTER(paint);
211     fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
212 }
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)213 void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
214                                                  SkScalar x,
215                                                  SkScalar y,
216                                                  const SkPaint& paint) {
217     FILTER(paint);
218     fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
219 }
220 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)221 void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
222                                               const SkColor colors[4],
223                                               const SkPoint texCoords[4],
224                                               SkXfermode* xmode,
225                                               const SkPaint& paint) {
226     FILTER(paint);
227     fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
228 }
229 
230 
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)231 void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
232                                               SkScalar x,
233                                               SkScalar y,
234                                               const SkPaint* paint) {
235     FILTER_PTR(paint);
236     fProxyTarget->drawImage(image, x, y, filteredPaint);
237 }
238 
onDrawImageRect(const SkImage * image,const SkRect * in,const SkRect & out,const SkPaint * paint)239 void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
240                                                   const SkRect* in,
241                                                   const SkRect& out,
242                                                   const SkPaint* paint) {
243     FILTER_PTR(paint);
244     fProxyTarget->drawImageRect(image, in, out, filteredPaint);
245 }
246 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)247 void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
248                                                 const SkMatrix* matrix,
249                                                 const SkPaint* paint) {
250     FILTER_PTR(paint);
251     fProxyTarget->drawPicture(picture, matrix, filteredPaint);
252 }
253 
onDrawDrawable(SkDrawable * drawable)254 void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable) {
255     fProxyTarget->drawDrawable(drawable);
256 }
257 
getBaseLayerSize() const258 SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
259     return fProxyTarget->getBaseLayerSize();
260 }
getClipBounds(SkRect * rect) const261 bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
262     return fProxyTarget->getClipBounds(rect);
263 }
getClipDeviceBounds(SkIRect * rect) const264 bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
265     return fProxyTarget->getClipDeviceBounds(rect);
266 }
267 
isClipEmpty() const268 bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
isClipRect() const269 bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }
270 
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)271 SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
272                                                      const SkSurfaceProps& props) {
273     return fProxyTarget->newSurface(info, &props);
274 }
275 
onPeekPixels(SkImageInfo * info,size_t * data)276 const void* SkAndroidSDKCanvas::onPeekPixels(SkImageInfo* info, size_t* data) {
277     return fProxyTarget->peekPixels(info, data);
278 }
279 
onAccessTopLayerPixels(SkImageInfo * info,size_t * data)280 void* SkAndroidSDKCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* data) {
281     return fProxyTarget->accessTopLayerPixels(info, data);
282 }
283 
willSave()284 void SkAndroidSDKCanvas::willSave() {
285     fProxyTarget->save();
286 }
287 
willSaveLayer(const SkRect * rect,const SkPaint * paint,SaveFlags flags)288 SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::willSaveLayer(const SkRect* rect,
289                                                               const SkPaint* paint,
290                                                               SaveFlags flags) {
291     fProxyTarget->saveLayer(rect, paint, flags);
292     return SkCanvas::kNoLayer_SaveLayerStrategy;
293 }
294 
willRestore()295 void SkAndroidSDKCanvas::willRestore() {
296     fProxyTarget->restore();
297 }
298 
didRestore()299 void SkAndroidSDKCanvas::didRestore() { }
300 
didConcat(const SkMatrix & m)301 void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
302     fProxyTarget->concat(m);
303 }
304 
didSetMatrix(const SkMatrix & m)305 void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
306     fProxyTarget->setMatrix(m);
307 }
308 
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle style)309 void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
310                                              SkRegion::Op op,
311                                              ClipEdgeStyle style) {
312     fProxyTarget->clipRect(rect, op, style);
313 }
314 
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle style)315 void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
316                                               SkRegion::Op op,
317                                               ClipEdgeStyle style) {
318     fProxyTarget->clipRRect(rrect, op, style);
319 }
320 
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle style)321 void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
322                                              SkRegion::Op op,
323                                              ClipEdgeStyle style) {
324     fProxyTarget->clipPath(path, op, style);
325 }
326 
onClipRegion(const SkRegion & region,SkRegion::Op op)327 void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
328     fProxyTarget->clipRegion(region, op);
329 }
330 
onDiscard()331 void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
332 
333 
334