• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "jni.h"
18 #include "GraphicsJNI.h"
19 #include <android_runtime/AndroidRuntime.h>
20 
21 #include "SkCanvas.h"
22 #include "SkDevice.h"
23 #include "SkGLCanvas.h"
24 #include "SkGraphics.h"
25 #include "SkImageRef_GlobalPool.h"
26 #include "SkPorterDuff.h"
27 #include "SkShader.h"
28 #include "SkTemplates.h"
29 
30 #define TIME_DRAWx
31 
get_thread_msec()32 static uint32_t get_thread_msec() {
33 #if defined(HAVE_POSIX_CLOCKS)
34     struct timespec tm;
35 
36     clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
37 
38     return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
39 #else
40     struct timeval tv;
41 
42     gettimeofday(&tv, NULL);
43     return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
44 #endif
45 }
46 
47 namespace android {
48 
49 class SkCanvasGlue {
50 public:
51 
finalizer(JNIEnv * env,jobject clazz,SkCanvas * canvas)52     static void finalizer(JNIEnv* env, jobject clazz, SkCanvas* canvas) {
53         canvas->unref();
54     }
55 
initRaster(JNIEnv * env,jobject,SkBitmap * bitmap)56     static SkCanvas* initRaster(JNIEnv* env, jobject, SkBitmap* bitmap) {
57         return bitmap ? new SkCanvas(*bitmap) : new SkCanvas;
58     }
59 
initGL(JNIEnv * env,jobject)60     static SkCanvas* initGL(JNIEnv* env, jobject) {
61         return new SkGLCanvas;
62     }
63 
freeCaches(JNIEnv * env,jobject)64     static void freeCaches(JNIEnv* env, jobject) {
65         // these are called in no particular order
66         SkGLCanvas::DeleteAllTextures();
67         SkImageRef_GlobalPool::SetRAMUsed(0);
68         SkGraphics::SetFontCacheUsed(0);
69     }
70 
isOpaque(JNIEnv * env,jobject jcanvas)71     static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
72         NPE_CHECK_RETURN_ZERO(env, jcanvas);
73         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
74 
75         /*
76             Currently we cannot support transparency in GL-based canvas' at
77             the view level. Therefore we cannot base our answer on the device's
78             bitmap, but need to hard-code the answer. If we relax this
79             limitation in views, we can simplify the following code as well.
80 
81             Use the getViewport() call to find out if we're gl-based...
82         */
83         if (canvas->getViewport(NULL)) {
84             return true;
85         }
86 
87         // normal technique, rely on the device's bitmap for the answer
88         return canvas->getDevice()->accessBitmap(false).isOpaque();
89     }
90 
getWidth(JNIEnv * env,jobject jcanvas)91     static int getWidth(JNIEnv* env, jobject jcanvas) {
92         NPE_CHECK_RETURN_ZERO(env, jcanvas);
93         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
94         return canvas->getDevice()->accessBitmap(false).width();
95     }
96 
getHeight(JNIEnv * env,jobject jcanvas)97     static int getHeight(JNIEnv* env, jobject jcanvas) {
98         NPE_CHECK_RETURN_ZERO(env, jcanvas);
99         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
100         return canvas->getDevice()->accessBitmap(false).height();
101     }
102 
setViewport(JNIEnv * env,jobject,SkCanvas * canvas,int width,int height)103     static void setViewport(JNIEnv* env, jobject, SkCanvas* canvas,
104                             int width, int height) {
105         canvas->setViewport(width, height);
106     }
107 
setBitmap(JNIEnv * env,jobject,SkCanvas * canvas,SkBitmap * bitmap)108     static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas,
109                           SkBitmap* bitmap) {
110         canvas->setBitmapDevice(*bitmap);
111     }
112 
saveAll(JNIEnv * env,jobject jcanvas)113     static int saveAll(JNIEnv* env, jobject jcanvas) {
114         NPE_CHECK_RETURN_ZERO(env, jcanvas);
115         return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
116     }
117 
save(JNIEnv * env,jobject jcanvas,SkCanvas::SaveFlags flags)118     static int save(JNIEnv* env, jobject jcanvas, SkCanvas::SaveFlags flags) {
119         NPE_CHECK_RETURN_ZERO(env, jcanvas);
120         return GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
121     }
122 
saveLayer(JNIEnv * env,jobject,SkCanvas * canvas,jobject bounds,SkPaint * paint,int flags)123     static int saveLayer(JNIEnv* env, jobject, SkCanvas* canvas, jobject bounds,
124                          SkPaint* paint, int flags) {
125         SkRect* bounds_ = NULL;
126         SkRect  storage;
127         if (bounds != NULL) {
128             GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
129             bounds_ = &storage;
130         }
131         return canvas->saveLayer(bounds_, paint, (SkCanvas::SaveFlags)flags);
132     }
133 
saveLayer4F(JNIEnv * env,jobject,SkCanvas * canvas,jfloat l,jfloat t,jfloat r,jfloat b,SkPaint * paint,int flags)134     static int saveLayer4F(JNIEnv* env, jobject, SkCanvas* canvas,
135                            jfloat l, jfloat t, jfloat r, jfloat b,
136                            SkPaint* paint, int flags) {
137         SkRect bounds;
138         bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
139                    SkFloatToScalar(b));
140         return canvas->saveLayer(&bounds, paint, (SkCanvas::SaveFlags)flags);
141     }
142 
saveLayerAlpha(JNIEnv * env,jobject,SkCanvas * canvas,jobject bounds,int alpha,int flags)143     static int saveLayerAlpha(JNIEnv* env, jobject, SkCanvas* canvas,
144                               jobject bounds, int alpha, int flags) {
145         SkRect* bounds_ = NULL;
146         SkRect  storage;
147         if (bounds != NULL) {
148             GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
149             bounds_ = &storage;
150         }
151         return canvas->saveLayerAlpha(bounds_, alpha,
152                                       (SkCanvas::SaveFlags)flags);
153     }
154 
saveLayerAlpha4F(JNIEnv * env,jobject,SkCanvas * canvas,jfloat l,jfloat t,jfloat r,jfloat b,int alpha,int flags)155     static int saveLayerAlpha4F(JNIEnv* env, jobject, SkCanvas* canvas,
156                                 jfloat l, jfloat t, jfloat r, jfloat b,
157                                 int alpha, int flags) {
158         SkRect  bounds;
159         bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
160                    SkFloatToScalar(b));
161         return canvas->saveLayerAlpha(&bounds, alpha,
162                                       (SkCanvas::SaveFlags)flags);
163     }
164 
restore(JNIEnv * env,jobject jcanvas)165     static void restore(JNIEnv* env, jobject jcanvas) {
166         NPE_CHECK_RETURN_VOID(env, jcanvas);
167         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
168         if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
169             doThrowISE(env, "Underflow in restore");
170             return;
171         }
172         canvas->restore();
173     }
174 
getSaveCount(JNIEnv * env,jobject jcanvas)175     static int getSaveCount(JNIEnv* env, jobject jcanvas) {
176         NPE_CHECK_RETURN_ZERO(env, jcanvas);
177         return GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
178     }
179 
restoreToCount(JNIEnv * env,jobject jcanvas,int restoreCount)180     static void restoreToCount(JNIEnv* env, jobject jcanvas, int restoreCount) {
181         NPE_CHECK_RETURN_VOID(env, jcanvas);
182         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
183         if (restoreCount < 1) {
184             doThrowIAE(env, "Underflow in restoreToCount");
185             return;
186         }
187         canvas->restoreToCount(restoreCount);
188     }
189 
translate(JNIEnv * env,jobject jcanvas,jfloat dx,jfloat dy)190     static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
191         NPE_CHECK_RETURN_VOID(env, jcanvas);
192         SkScalar dx_ = SkFloatToScalar(dx);
193         SkScalar dy_ = SkFloatToScalar(dy);
194         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
195     }
196 
scale__FF(JNIEnv * env,jobject jcanvas,jfloat sx,jfloat sy)197     static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
198         NPE_CHECK_RETURN_VOID(env, jcanvas);
199         SkScalar sx_ = SkFloatToScalar(sx);
200         SkScalar sy_ = SkFloatToScalar(sy);
201         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
202     }
203 
rotate__F(JNIEnv * env,jobject jcanvas,jfloat degrees)204     static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
205         NPE_CHECK_RETURN_VOID(env, jcanvas);
206         SkScalar degrees_ = SkFloatToScalar(degrees);
207         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
208     }
209 
skew__FF(JNIEnv * env,jobject jcanvas,jfloat sx,jfloat sy)210     static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
211         NPE_CHECK_RETURN_VOID(env, jcanvas);
212         SkScalar sx_ = SkFloatToScalar(sx);
213         SkScalar sy_ = SkFloatToScalar(sy);
214         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
215     }
216 
concat(JNIEnv * env,jobject,SkCanvas * canvas,const SkMatrix * matrix)217     static void concat(JNIEnv* env, jobject, SkCanvas* canvas,
218                        const SkMatrix* matrix) {
219         canvas->concat(*matrix);
220     }
221 
setMatrix(JNIEnv * env,jobject,SkCanvas * canvas,const SkMatrix * matrix)222     static void setMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
223                           const SkMatrix* matrix) {
224         if (NULL == matrix) {
225             canvas->resetMatrix();
226         } else {
227             canvas->setMatrix(*matrix);
228         }
229     }
230 
clipRect_FFFF(JNIEnv * env,jobject jcanvas,jfloat left,jfloat top,jfloat right,jfloat bottom)231     static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
232                                   jfloat top, jfloat right, jfloat bottom) {
233         NPE_CHECK_RETURN_ZERO(env, jcanvas);
234         SkRect  r;
235         r.set(SkFloatToScalar(left), SkFloatToScalar(top),
236               SkFloatToScalar(right), SkFloatToScalar(bottom));
237         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
238         return c->clipRect(r);
239     }
240 
clipRect_IIII(JNIEnv * env,jobject jcanvas,jint left,jint top,jint right,jint bottom)241     static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
242                                   jint top, jint right, jint bottom) {
243         NPE_CHECK_RETURN_ZERO(env, jcanvas);
244         SkRect  r;
245         r.set(SkIntToScalar(left), SkIntToScalar(top),
246               SkIntToScalar(right), SkIntToScalar(bottom));
247         return GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
248     }
249 
clipRect_RectF(JNIEnv * env,jobject jcanvas,jobject rectf)250     static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
251         NPE_CHECK_RETURN_ZERO(env, jcanvas);
252         NPE_CHECK_RETURN_ZERO(env, rectf);
253         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
254         SkRect tmp;
255         return c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
256     }
257 
clipRect_Rect(JNIEnv * env,jobject jcanvas,jobject rect)258     static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
259         NPE_CHECK_RETURN_ZERO(env, jcanvas);
260         NPE_CHECK_RETURN_ZERO(env, rect);
261         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
262         SkRect tmp;
263         return c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
264     }
265 
clipRect(JNIEnv * env,jobject,SkCanvas * canvas,float left,float top,float right,float bottom,int op)266     static jboolean clipRect(JNIEnv* env, jobject, SkCanvas* canvas,
267                              float left, float top, float right, float bottom,
268                              int op) {
269         SkRect rect;
270         rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
271                  SkFloatToScalar(right), SkFloatToScalar(bottom));
272         return canvas->clipRect(rect, (SkRegion::Op)op);
273     }
274 
clipPath(JNIEnv * env,jobject,SkCanvas * canvas,SkPath * path,int op)275     static jboolean clipPath(JNIEnv* env, jobject, SkCanvas* canvas,
276                              SkPath* path, int op) {
277         return canvas->clipPath(*path, (SkRegion::Op)op);
278     }
279 
clipRegion(JNIEnv * env,jobject,SkCanvas * canvas,SkRegion * deviceRgn,int op)280     static jboolean clipRegion(JNIEnv* env, jobject, SkCanvas* canvas,
281                                SkRegion* deviceRgn, int op) {
282         return canvas->clipRegion(*deviceRgn, (SkRegion::Op)op);
283     }
284 
setDrawFilter(JNIEnv * env,jobject,SkCanvas * canvas,SkDrawFilter * filter)285     static void setDrawFilter(JNIEnv* env, jobject, SkCanvas* canvas,
286                               SkDrawFilter* filter) {
287         canvas->setDrawFilter(filter);
288     }
289 
quickReject__RectFI(JNIEnv * env,jobject,SkCanvas * canvas,jobject rect,int edgetype)290     static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas,
291                                         jobject rect, int edgetype) {
292         SkRect rect_;
293         GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
294         return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype);
295     }
296 
quickReject__PathI(JNIEnv * env,jobject,SkCanvas * canvas,SkPath * path,int edgetype)297     static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas,
298                                        SkPath* path, int edgetype) {
299         return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype);
300     }
301 
quickReject__FFFFI(JNIEnv * env,jobject,SkCanvas * canvas,jfloat left,jfloat top,jfloat right,jfloat bottom,int edgetype)302     static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas,
303                                        jfloat left, jfloat top, jfloat right,
304                                        jfloat bottom, int edgetype) {
305         SkRect r;
306         r.set(SkFloatToScalar(left), SkFloatToScalar(top),
307               SkFloatToScalar(right), SkFloatToScalar(bottom));
308         return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype);
309     }
310 
drawRGB(JNIEnv * env,jobject,SkCanvas * canvas,jint r,jint g,jint b)311     static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas,
312                         jint r, jint g, jint b) {
313         canvas->drawARGB(0xFF, r, g, b);
314     }
315 
drawARGB(JNIEnv * env,jobject,SkCanvas * canvas,jint a,jint r,jint g,jint b)316     static void drawARGB(JNIEnv* env, jobject, SkCanvas* canvas,
317                          jint a, jint r, jint g, jint b) {
318         canvas->drawARGB(a, r, g, b);
319     }
320 
drawColor__I(JNIEnv * env,jobject,SkCanvas * canvas,jint color)321     static void drawColor__I(JNIEnv* env, jobject, SkCanvas* canvas,
322                              jint color) {
323         canvas->drawColor(color);
324     }
325 
drawColor__II(JNIEnv * env,jobject,SkCanvas * canvas,jint color,SkPorterDuff::Mode mode)326     static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas,
327                               jint color, SkPorterDuff::Mode mode) {
328         canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
329     }
330 
drawPaint(JNIEnv * env,jobject,SkCanvas * canvas,SkPaint * paint)331     static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas,
332                           SkPaint* paint) {
333         canvas->drawPaint(*paint);
334     }
335 
doPoints(JNIEnv * env,jobject jcanvas,jfloatArray jptsArray,jint offset,jint count,jobject jpaint,SkCanvas::PointMode mode)336     static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
337                          jint offset, jint count, jobject jpaint,
338                          SkCanvas::PointMode mode) {
339         NPE_CHECK_RETURN_VOID(env, jcanvas);
340         NPE_CHECK_RETURN_VOID(env, jptsArray);
341         NPE_CHECK_RETURN_VOID(env, jpaint);
342         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
343         const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
344 
345         AutoJavaFloatArray autoPts(env, jptsArray);
346         float* floats = autoPts.ptr();
347         const int length = autoPts.length();
348 
349         if ((offset | count) < 0 || offset + count > length) {
350             doThrowAIOOBE(env);
351             return;
352         }
353 
354         // now convert the floats into SkPoints
355         count >>= 1;    // now it is the number of points
356         SkAutoSTMalloc<32, SkPoint> storage(count);
357         SkPoint* pts = storage.get();
358         const float* src = floats + offset;
359         for (int i = 0; i < count; i++) {
360             pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
361             src += 2;
362         }
363         canvas->drawPoints(mode, count, pts, paint);
364     }
365 
drawPoints(JNIEnv * env,jobject jcanvas,jfloatArray jptsArray,jint offset,jint count,jobject jpaint)366     static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
367                            jint offset, jint count, jobject jpaint) {
368         doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
369                  SkCanvas::kPoints_PointMode);
370     }
371 
drawLines(JNIEnv * env,jobject jcanvas,jfloatArray jptsArray,jint offset,jint count,jobject jpaint)372     static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
373                            jint offset, jint count, jobject jpaint) {
374         doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
375                  SkCanvas::kLines_PointMode);
376     }
377 
drawPoint(JNIEnv * env,jobject jcanvas,float x,float y,jobject jpaint)378     static void drawPoint(JNIEnv* env, jobject jcanvas, float x, float y,
379                           jobject jpaint) {
380         NPE_CHECK_RETURN_VOID(env, jcanvas);
381         NPE_CHECK_RETURN_VOID(env, jpaint);
382         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
383         const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
384 
385         canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
386     }
387 
drawLine__FFFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jfloat startX,jfloat startY,jfloat stopX,jfloat stopY,SkPaint * paint)388     static void drawLine__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
389                                     jfloat startX, jfloat startY, jfloat stopX,
390                                     jfloat stopY, SkPaint* paint) {
391         canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
392                          SkFloatToScalar(stopX), SkFloatToScalar(stopY),
393                          *paint);
394     }
395 
drawRect__RectFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jobject rect,SkPaint * paint)396     static void drawRect__RectFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
397                                      jobject rect, SkPaint* paint) {
398         SkRect rect_;
399         GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
400         canvas->drawRect(rect_, *paint);
401     }
402 
drawRect__FFFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jfloat left,jfloat top,jfloat right,jfloat bottom,SkPaint * paint)403     static void drawRect__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
404                                     jfloat left, jfloat top, jfloat right,
405                                     jfloat bottom, SkPaint* paint) {
406         SkScalar left_ = SkFloatToScalar(left);
407         SkScalar top_ = SkFloatToScalar(top);
408         SkScalar right_ = SkFloatToScalar(right);
409         SkScalar bottom_ = SkFloatToScalar(bottom);
410         canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
411     }
412 
drawOval(JNIEnv * env,jobject,SkCanvas * canvas,jobject joval,SkPaint * paint)413     static void drawOval(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
414                          SkPaint* paint) {
415         SkRect oval;
416         GraphicsJNI::jrectf_to_rect(env, joval, &oval);
417         canvas->drawOval(oval, *paint);
418     }
419 
drawCircle(JNIEnv * env,jobject,SkCanvas * canvas,jfloat cx,jfloat cy,jfloat radius,SkPaint * paint)420     static void drawCircle(JNIEnv* env, jobject, SkCanvas* canvas, jfloat cx,
421                            jfloat cy, jfloat radius, SkPaint* paint) {
422         canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
423                            SkFloatToScalar(radius), *paint);
424     }
425 
drawArc(JNIEnv * env,jobject,SkCanvas * canvas,jobject joval,jfloat startAngle,jfloat sweepAngle,jboolean useCenter,SkPaint * paint)426     static void drawArc(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
427                         jfloat startAngle, jfloat sweepAngle,
428                         jboolean useCenter, SkPaint* paint) {
429         SkRect oval;
430         GraphicsJNI::jrectf_to_rect(env, joval, &oval);
431         canvas->drawArc(oval, SkFloatToScalar(startAngle),
432                         SkFloatToScalar(sweepAngle), useCenter, *paint);
433     }
434 
drawRoundRect(JNIEnv * env,jobject,SkCanvas * canvas,jobject jrect,jfloat rx,jfloat ry,SkPaint * paint)435     static void drawRoundRect(JNIEnv* env, jobject, SkCanvas* canvas,
436                               jobject jrect, jfloat rx, jfloat ry,
437                               SkPaint* paint) {
438         SkRect rect;
439         GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
440         canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
441                               *paint);
442     }
443 
drawPath(JNIEnv * env,jobject,SkCanvas * canvas,SkPath * path,SkPaint * paint)444     static void drawPath(JNIEnv* env, jobject, SkCanvas* canvas, SkPath* path,
445                          SkPaint* paint) {
446         canvas->drawPath(*path, *paint);
447     }
448 
drawPicture(JNIEnv * env,jobject,SkCanvas * canvas,SkPicture * picture)449     static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
450                             SkPicture* picture) {
451         SkASSERT(canvas);
452         SkASSERT(picture);
453 
454 #ifdef TIME_DRAW
455         SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
456 #endif
457         canvas->drawPicture(*picture);
458 #ifdef TIME_DRAW
459         LOGD("---- picture playback %d ms\n", get_thread_msec() - now);
460 #endif
461     }
462 
drawBitmap__BitmapFFPaint(JNIEnv * env,jobject jcanvas,SkCanvas * canvas,SkBitmap * bitmap,jfloat left,jfloat top,SkPaint * paint,jint canvasDensity,jint screenDensity,jint bitmapDensity)463     static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
464                                           SkCanvas* canvas, SkBitmap* bitmap,
465                                           jfloat left, jfloat top,
466                                           SkPaint* paint, jint canvasDensity,
467                                           jint screenDensity, jint bitmapDensity) {
468         SkScalar left_ = SkFloatToScalar(left);
469         SkScalar top_ = SkFloatToScalar(top);
470 
471         if (canvasDensity == bitmapDensity || canvasDensity == 0
472                 || bitmapDensity == 0) {
473             if (screenDensity != 0 && screenDensity != bitmapDensity) {
474                 SkPaint filteredPaint;
475                 if (paint) {
476                     filteredPaint = *paint;
477                 }
478                 filteredPaint.setFilterBitmap(true);
479                 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
480             } else {
481                 canvas->drawBitmap(*bitmap, left_, top_, paint);
482             }
483         } else {
484             canvas->save();
485             SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
486             canvas->translate(left_, top_);
487             canvas->scale(scale, scale);
488 
489             SkPaint filteredPaint;
490             if (paint) {
491                 filteredPaint = *paint;
492             }
493             filteredPaint.setFilterBitmap(true);
494 
495             canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
496 
497             canvas->restore();
498         }
499     }
500 
doDrawBitmap(JNIEnv * env,SkCanvas * canvas,SkBitmap * bitmap,jobject srcIRect,const SkRect & dst,SkPaint * paint,jint screenDensity,jint bitmapDensity)501     static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
502                         jobject srcIRect, const SkRect& dst, SkPaint* paint,
503                         jint screenDensity, jint bitmapDensity) {
504         SkIRect    src, *srcPtr = NULL;
505 
506         if (NULL != srcIRect) {
507             GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
508             srcPtr = &src;
509         }
510 
511         if (screenDensity != 0 && screenDensity != bitmapDensity) {
512             SkPaint filteredPaint;
513             if (paint) {
514                 filteredPaint = *paint;
515             }
516             filteredPaint.setFilterBitmap(true);
517             canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
518         } else {
519             canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
520         }
521     }
522 
drawBitmapRF(JNIEnv * env,jobject,SkCanvas * canvas,SkBitmap * bitmap,jobject srcIRect,jobject dstRectF,SkPaint * paint,jint screenDensity,jint bitmapDensity)523     static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas,
524                              SkBitmap* bitmap, jobject srcIRect,
525                              jobject dstRectF, SkPaint* paint,
526                              jint screenDensity, jint bitmapDensity) {
527         SkRect      dst;
528         GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
529         doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
530                 screenDensity, bitmapDensity);
531     }
532 
drawBitmapRR(JNIEnv * env,jobject,SkCanvas * canvas,SkBitmap * bitmap,jobject srcIRect,jobject dstRect,SkPaint * paint,jint screenDensity,jint bitmapDensity)533     static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas,
534                              SkBitmap* bitmap, jobject srcIRect,
535                              jobject dstRect, SkPaint* paint,
536                              jint screenDensity, jint bitmapDensity) {
537         SkRect      dst;
538         GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
539         doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
540                 screenDensity, bitmapDensity);
541     }
542 
drawBitmapArray(JNIEnv * env,jobject,SkCanvas * canvas,jintArray jcolors,int offset,int stride,jfloat x,jfloat y,int width,int height,jboolean hasAlpha,SkPaint * paint)543     static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas,
544                                 jintArray jcolors, int offset, int stride,
545                                 jfloat x, jfloat y, int width, int height,
546                                 jboolean hasAlpha, SkPaint* paint)
547     {
548         SkBitmap    bitmap;
549 
550         bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
551                          SkBitmap::kRGB_565_Config, width, height);
552         if (!bitmap.allocPixels()) {
553             return;
554         }
555 
556         if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
557                                     0, 0, width, height, bitmap)) {
558             return;
559         }
560 
561         canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
562                            paint);
563     }
564 
drawBitmapMatrix(JNIEnv * env,jobject,SkCanvas * canvas,const SkBitmap * bitmap,const SkMatrix * matrix,const SkPaint * paint)565     static void drawBitmapMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
566                                  const SkBitmap* bitmap, const SkMatrix* matrix,
567                                  const SkPaint* paint) {
568         canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
569     }
570 
drawBitmapMesh(JNIEnv * env,jobject,SkCanvas * canvas,const SkBitmap * bitmap,int meshWidth,int meshHeight,jfloatArray jverts,int vertIndex,jintArray jcolors,int colorIndex,const SkPaint * paint)571     static void drawBitmapMesh(JNIEnv* env, jobject, SkCanvas* canvas,
572                           const SkBitmap* bitmap, int meshWidth, int meshHeight,
573                           jfloatArray jverts, int vertIndex, jintArray jcolors,
574                           int colorIndex, const SkPaint* paint) {
575 
576         const int ptCount = (meshWidth + 1) * (meshHeight + 1);
577         const int indexCount = meshWidth * meshHeight * 6;
578 
579         AutoJavaFloatArray  vertA(env, jverts, vertIndex + (ptCount << 1));
580         AutoJavaIntArray    colorA(env, jcolors, colorIndex + ptCount);
581 
582         /*  Our temp storage holds 2 or 3 arrays.
583             texture points [ptCount * sizeof(SkPoint)]
584             optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
585                 copy to convert from float to fixed
586             indices [ptCount * sizeof(uint16_t)]
587         */
588         ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
589 #ifdef SK_SCALAR_IS_FIXED
590         storageSize += ptCount * sizeof(SkPoint);  // storage for verts
591 #endif
592         storageSize += indexCount * sizeof(uint16_t);  // indices[]
593 
594         SkAutoMalloc storage(storageSize);
595         SkPoint* texs = (SkPoint*)storage.get();
596         SkPoint* verts;
597         uint16_t* indices;
598 #ifdef SK_SCALAR_IS_FLOAT
599         verts = (SkPoint*)(vertA.ptr() + vertIndex);
600         indices = (uint16_t*)(texs + ptCount);
601 #else
602         verts = texs + ptCount;
603         indices = (uint16_t*)(verts + ptCount);
604         // convert floats to fixed
605         {
606             const float* src = vertA.ptr() + vertIndex;
607             for (int i = 0; i < ptCount; i++) {
608                 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
609                 src += 2;
610             }
611         }
612 #endif
613 
614         // cons up texture coordinates and indices
615         {
616             const SkScalar w = SkIntToScalar(bitmap->width());
617             const SkScalar h = SkIntToScalar(bitmap->height());
618             const SkScalar dx = w / meshWidth;
619             const SkScalar dy = h / meshHeight;
620 
621             SkPoint* texsPtr = texs;
622             SkScalar y = 0;
623             for (int i = 0; i <= meshHeight; i++) {
624                 if (i == meshHeight) {
625                     y = h;  // to ensure numerically we hit h exactly
626                 }
627                 SkScalar x = 0;
628                 for (int j = 0; j < meshWidth; j++) {
629                     texsPtr->set(x, y);
630                     texsPtr += 1;
631                     x += dx;
632                 }
633                 texsPtr->set(w, y);
634                 texsPtr += 1;
635                 y += dy;
636             }
637             SkASSERT(texsPtr - texs == ptCount);
638         }
639 
640         // cons up indices
641         {
642             uint16_t* indexPtr = indices;
643             int index = 0;
644             for (int i = 0; i < meshHeight; i++) {
645                 for (int j = 0; j < meshWidth; j++) {
646                     // lower-left triangle
647                     *indexPtr++ = index;
648                     *indexPtr++ = index + meshWidth + 1;
649                     *indexPtr++ = index + meshWidth + 2;
650                     // upper-right triangle
651                     *indexPtr++ = index;
652                     *indexPtr++ = index + meshWidth + 2;
653                     *indexPtr++ = index + 1;
654                     // bump to the next cell
655                     index += 1;
656                 }
657                 // bump to the next row
658                 index += 1;
659             }
660             SkASSERT(indexPtr - indices == indexCount);
661             SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
662         }
663 
664         // double-check that we have legal indices
665 #ifdef SK_DEBUG
666         {
667             for (int i = 0; i < indexCount; i++) {
668                 SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
669             }
670         }
671 #endif
672 
673         // cons-up a shader for the bitmap
674         SkPaint tmpPaint;
675         if (paint) {
676             tmpPaint = *paint;
677         }
678         SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
679                         SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
680         tmpPaint.setShader(shader)->safeUnref();
681 
682         canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
683                              texs, (const SkColor*)colorA.ptr(), NULL, indices,
684                              indexCount, tmpPaint);
685     }
686 
drawVertices(JNIEnv * env,jobject,SkCanvas * canvas,SkCanvas::VertexMode mode,int vertexCount,jfloatArray jverts,int vertIndex,jfloatArray jtexs,int texIndex,jintArray jcolors,int colorIndex,jshortArray jindices,int indexIndex,int indexCount,const SkPaint * paint)687     static void drawVertices(JNIEnv* env, jobject, SkCanvas* canvas,
688                              SkCanvas::VertexMode mode, int vertexCount,
689                              jfloatArray jverts, int vertIndex,
690                              jfloatArray jtexs, int texIndex,
691                              jintArray jcolors, int colorIndex,
692                              jshortArray jindices, int indexIndex,
693                              int indexCount, const SkPaint* paint) {
694 
695         AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
696         AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
697         AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
698         AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
699 
700         const int ptCount = vertexCount >> 1;
701 
702         SkPoint* verts;
703         SkPoint* texs = NULL;
704 #ifdef SK_SCALAR_IS_FLOAT
705         verts = (SkPoint*)(vertA.ptr() + vertIndex);
706         if (jtexs != NULL) {
707             texs = (SkPoint*)(texA.ptr() + texIndex);
708         }
709 #else
710         int count = ptCount;    // for verts
711         if (jtexs != NULL) {
712             count += ptCount;   // += for texs
713         }
714         SkAutoMalloc storage(count * sizeof(SkPoint));
715         verts = (SkPoint*)storage.get();
716         const float* src = vertA.ptr() + vertIndex;
717         for (int i = 0; i < ptCount; i++) {
718             verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
719             src += 2;
720         }
721         if (jtexs != NULL) {
722             texs = verts + ptCount;
723             src = texA.ptr() + texIndex;
724             for (int i = 0; i < ptCount; i++) {
725                 texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
726                 src += 2;
727             }
728         }
729 #endif
730 
731         const SkColor* colors = NULL;
732         const uint16_t* indices = NULL;
733         if (jcolors != NULL) {
734             colors = (const SkColor*)(colorA.ptr() + colorIndex);
735         }
736         if (jindices != NULL) {
737             indices = (const uint16_t*)(indexA.ptr() + indexIndex);
738         }
739 
740         canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
741                              indices, indexCount, *paint);
742     }
743 
drawText___CIIFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,jfloat x,jfloat y,SkPaint * paint)744     static void drawText___CIIFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
745                                       jcharArray text, int index, int count,
746                                       jfloat x, jfloat y, SkPaint* paint) {
747         jchar* textArray = env->GetCharArrayElements(text, NULL);
748         jsize textCount = env->GetArrayLength(text);
749         SkScalar x_ = SkFloatToScalar(x);
750         SkScalar y_ = SkFloatToScalar(y);
751         canvas->drawText(textArray + index, count << 1, x_, y_, *paint);
752         env->ReleaseCharArrayElements(text, textArray, 0);
753     }
754 
drawText__StringIIFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jstring text,int start,int end,jfloat x,jfloat y,SkPaint * paint)755     static void drawText__StringIIFFPaint(JNIEnv* env, jobject,
756                             SkCanvas* canvas, jstring text, int start, int end,
757                                           jfloat x, jfloat y, SkPaint* paint) {
758         const void* text_ = env->GetStringChars(text, NULL);
759         SkScalar x_ = SkFloatToScalar(x);
760         SkScalar y_ = SkFloatToScalar(y);
761         canvas->drawText((const uint16_t*)text_ + start, (end - start) << 1,
762                          x_, y_, *paint);
763         env->ReleaseStringChars(text, (const jchar*) text_);
764     }
765 
drawString(JNIEnv * env,jobject canvas,jstring text,jfloat x,jfloat y,jobject paint)766     static void drawString(JNIEnv* env, jobject canvas, jstring text,
767                            jfloat x, jfloat y, jobject paint) {
768         NPE_CHECK_RETURN_VOID(env, canvas);
769         NPE_CHECK_RETURN_VOID(env, paint);
770         NPE_CHECK_RETURN_VOID(env, text);
771         size_t count = env->GetStringLength(text);
772         if (0 == count) {
773             return;
774         }
775         const jchar* text_ = env->GetStringChars(text, NULL);
776         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
777         c->drawText(text_, count << 1, SkFloatToScalar(x), SkFloatToScalar(y),
778                     *GraphicsJNI::getNativePaint(env, paint));
779         env->ReleaseStringChars(text, text_);
780     }
781 
drawPosText___CII_FPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,jfloatArray pos,SkPaint * paint)782     static void drawPosText___CII_FPaint(JNIEnv* env, jobject, SkCanvas* canvas,
783                                          jcharArray text, int index, int count,
784                                          jfloatArray pos, SkPaint* paint) {
785         jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
786         jsize textCount = text ? env->GetArrayLength(text) : NULL;
787         float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
788         int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
789         SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
790         int indx;
791         for (indx = 0; indx < posCount; indx++) {
792             posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
793             posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
794         }
795         canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
796         if (text) {
797             env->ReleaseCharArrayElements(text, textArray, 0);
798         }
799         if (pos) {
800             env->ReleaseFloatArrayElements(pos, posArray, 0);
801         }
802         delete[] posPtr;
803     }
804 
drawPosText__String_FPaint(JNIEnv * env,jobject,SkCanvas * canvas,jstring text,jfloatArray pos,SkPaint * paint)805     static void drawPosText__String_FPaint(JNIEnv* env, jobject,
806                                            SkCanvas* canvas, jstring text,
807                                            jfloatArray pos, SkPaint* paint) {
808         const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
809         int byteLength = text ? env->GetStringLength(text) : 0;
810         float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
811         int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
812         SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
813 
814         for (int indx = 0; indx < posCount; indx++) {
815             posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
816             posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
817         }
818         canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
819         if (text) {
820             env->ReleaseStringChars(text, (const jchar*) text_);
821         }
822         if (pos) {
823             env->ReleaseFloatArrayElements(pos, posArray, 0);
824         }
825         delete[] posPtr;
826     }
827 
drawTextOnPath___CIIPathFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,SkPath * path,jfloat hOffset,jfloat vOffset,SkPaint * paint)828     static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
829                         SkCanvas* canvas, jcharArray text, int index, int count,
830                 SkPath* path, jfloat hOffset, jfloat vOffset, SkPaint* paint) {
831 
832         jchar* textArray = env->GetCharArrayElements(text, NULL);
833         canvas->drawTextOnPathHV(textArray + index, count << 1, *path,
834                     SkFloatToScalar(hOffset), SkFloatToScalar(vOffset), *paint);
835         env->ReleaseCharArrayElements(text, textArray, 0);
836     }
837 
drawTextOnPath__StringPathFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jstring text,SkPath * path,jfloat hOffset,jfloat vOffset,SkPaint * paint)838     static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
839                             SkCanvas* canvas, jstring text, SkPath* path,
840                             jfloat hOffset, jfloat vOffset, SkPaint* paint) {
841         const jchar* text_ = env->GetStringChars(text, NULL);
842         int byteLength = env->GetStringLength(text) << 1;
843         canvas->drawTextOnPathHV(text_, byteLength, *path,
844                     SkFloatToScalar(hOffset), SkFloatToScalar(vOffset), *paint);
845         env->ReleaseStringChars(text, text_);
846     }
847 
getClipBounds(JNIEnv * env,jobject,SkCanvas * canvas,jobject bounds)848     static bool getClipBounds(JNIEnv* env, jobject, SkCanvas* canvas,
849                               jobject bounds) {
850         SkRect   r;
851         SkIRect ir;
852         bool     result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
853 
854         r.round(&ir);
855         (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
856         return result;
857     }
858 
getCTM(JNIEnv * env,jobject,SkCanvas * canvas,SkMatrix * matrix)859     static void getCTM(JNIEnv* env, jobject, SkCanvas* canvas,
860                        SkMatrix* matrix) {
861         *matrix = canvas->getTotalMatrix();
862     }
863 };
864 
865 ///////////////////////////////////////////////////////////////////////////////
866 
867 static JNINativeMethod gCanvasMethods[] = {
868     {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
869     {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster},
870     {"initGL","()I", (void*) SkCanvasGlue::initGL},
871     {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
872     {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
873     {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
874     {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
875     {"nativeSetViewport", "(III)V", (void*) SkCanvasGlue::setViewport},
876     {"save","()I", (void*) SkCanvasGlue::saveAll},
877     {"save","(I)I", (void*) SkCanvasGlue::save},
878     {"native_saveLayer","(ILandroid/graphics/RectF;II)I",
879         (void*) SkCanvasGlue::saveLayer},
880     {"native_saveLayer","(IFFFFII)I", (void*) SkCanvasGlue::saveLayer4F},
881     {"native_saveLayerAlpha","(ILandroid/graphics/RectF;II)I",
882         (void*) SkCanvasGlue::saveLayerAlpha},
883     {"native_saveLayerAlpha","(IFFFFII)I",
884         (void*) SkCanvasGlue::saveLayerAlpha4F},
885     {"restore","()V", (void*) SkCanvasGlue::restore},
886     {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
887     {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
888     {"translate","(FF)V", (void*) SkCanvasGlue::translate},
889     {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
890     {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
891     {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
892     {"native_concat","(II)V", (void*) SkCanvasGlue::concat},
893     {"native_setMatrix","(II)V", (void*) SkCanvasGlue::setMatrix},
894     {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
895     {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
896     {"clipRect","(Landroid/graphics/RectF;)Z",
897         (void*) SkCanvasGlue::clipRect_RectF},
898     {"clipRect","(Landroid/graphics/Rect;)Z",
899         (void*) SkCanvasGlue::clipRect_Rect},
900     {"native_clipRect","(IFFFFI)Z", (void*) SkCanvasGlue::clipRect},
901     {"native_clipPath","(III)Z", (void*) SkCanvasGlue::clipPath},
902     {"native_clipRegion","(III)Z", (void*) SkCanvasGlue::clipRegion},
903     {"nativeSetDrawFilter", "(II)V", (void*) SkCanvasGlue::setDrawFilter},
904     {"native_getClipBounds","(ILandroid/graphics/Rect;)Z",
905         (void*) SkCanvasGlue::getClipBounds},
906     {"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM},
907     {"native_quickReject","(ILandroid/graphics/RectF;I)Z",
908         (void*) SkCanvasGlue::quickReject__RectFI},
909     {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI},
910     {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI},
911     {"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB},
912     {"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB},
913     {"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I},
914     {"native_drawColor","(III)V", (void*) SkCanvasGlue::drawColor__II},
915     {"native_drawPaint","(II)V", (void*) SkCanvasGlue::drawPaint},
916     {"drawPoint", "(FFLandroid/graphics/Paint;)V",
917     (void*) SkCanvasGlue::drawPoint},
918     {"drawPoints", "([FIILandroid/graphics/Paint;)V",
919         (void*) SkCanvasGlue::drawPoints},
920     {"drawLines", "([FIILandroid/graphics/Paint;)V",
921         (void*) SkCanvasGlue::drawLines},
922     {"native_drawLine","(IFFFFI)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
923     {"native_drawRect","(ILandroid/graphics/RectF;I)V",
924         (void*) SkCanvasGlue::drawRect__RectFPaint},
925     {"native_drawRect","(IFFFFI)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
926     {"native_drawOval","(ILandroid/graphics/RectF;I)V",
927         (void*) SkCanvasGlue::drawOval},
928     {"native_drawCircle","(IFFFI)V", (void*) SkCanvasGlue::drawCircle},
929     {"native_drawArc","(ILandroid/graphics/RectF;FFZI)V",
930         (void*) SkCanvasGlue::drawArc},
931     {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
932         (void*) SkCanvasGlue::drawRoundRect},
933     {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
934     {"native_drawBitmap","(IIFFIIII)V",
935         (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
936     {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V",
937         (void*) SkCanvasGlue::drawBitmapRF},
938     {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V",
939         (void*) SkCanvasGlue::drawBitmapRR},
940     {"native_drawBitmap", "(I[IIIFFIIZI)V",
941     (void*)SkCanvasGlue::drawBitmapArray},
942 
943     {"nativeDrawBitmapMatrix", "(IIII)V",
944         (void*)SkCanvasGlue::drawBitmapMatrix},
945     {"nativeDrawBitmapMesh", "(IIII[FI[III)V",
946         (void*)SkCanvasGlue::drawBitmapMesh},
947     {"nativeDrawVertices", "(III[FI[FI[II[SIII)V",
948         (void*)SkCanvasGlue::drawVertices},
949     {"native_drawText","(I[CIIFFI)V",
950         (void*) SkCanvasGlue::drawText___CIIFFPaint},
951     {"native_drawText","(ILjava/lang/String;IIFFI)V",
952         (void*) SkCanvasGlue::drawText__StringIIFFPaint},
953     {"drawText","(Ljava/lang/String;FFLandroid/graphics/Paint;)V",
954         (void*) SkCanvasGlue::drawString},
955     {"native_drawPosText","(I[CII[FI)V",
956         (void*) SkCanvasGlue::drawPosText___CII_FPaint},
957     {"native_drawPosText","(ILjava/lang/String;[FI)V",
958         (void*) SkCanvasGlue::drawPosText__String_FPaint},
959     {"native_drawTextOnPath","(I[CIIIFFI)V",
960         (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
961     {"native_drawTextOnPath","(ILjava/lang/String;IFFI)V",
962         (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
963     {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
964 
965     {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
966 };
967 
968 #include <android_runtime/AndroidRuntime.h>
969 
970 #define REG(env, name, array) \
971     result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
972                                                     SK_ARRAY_COUNT(array));  \
973     if (result < 0) return result
974 
register_android_graphics_Canvas(JNIEnv * env)975 int register_android_graphics_Canvas(JNIEnv* env) {
976     int result;
977 
978     REG(env, "android/graphics/Canvas", gCanvasMethods);
979 
980     return result;
981 }
982 
983 }
984