Canvas.cpp revision 47c0d4eaa926d979c5ea366934750526c20af8ff
14f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
24f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Copyright (C) 2006-2007 The Android Open Source Project
34f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
44f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
54f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * you may not use this file except in compliance with the License.
64f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * You may obtain a copy of the License at
74f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
84f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
94f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * See the License for the specific language governing permissions and
144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * limitations under the License.
154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "jni.h"
184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "GraphicsJNI.h"
194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkCanvas.h"
224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkDevice.h"
234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkGLCanvas.h"
244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkGraphics.h"
254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkImageRef_GlobalPool.h"
264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkPorterDuff.h"
274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkShader.h"
284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "SkTemplates.h"
294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define TIME_DRAWx
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
32e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)static uint32_t get_thread_msec() {
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if defined(HAVE_POSIX_CLOCKS)
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct timespec tm;
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
386310a8261c922533a692fb3e74ece2da98d4bafaColin Cross    return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
393899e9fc01cf608f19f716749c54cc5c4d17e766Colin Cross#else
40ed8a7d84428ec945c48b6b53dc5a3a18fabaf683Colin Cross    struct timeval tv;
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    gettimeofday(&tv, NULL);
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectnamespace android {
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectclass SkCanvasGlue {
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectpublic:
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void finalizer(JNIEnv* env, jobject clazz, SkCanvas* canvas) {
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->unref();
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
55008abac082f1c098d402f944d9287dce67ffce0aMike Chan
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static SkCanvas* initRaster(JNIEnv* env, jobject, SkBitmap* bitmap) {
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return bitmap ? new SkCanvas(*bitmap) : new SkCanvas;
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static SkCanvas* initGL(JNIEnv* env, jobject) {
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return new SkGLCanvas;
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void freeCaches(JNIEnv* env, jobject) {
65008abac082f1c098d402f944d9287dce67ffce0aMike Chan        // these are called in no particular order
664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkGLCanvas::DeleteAllTextures();
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkImageRef_GlobalPool::SetRAMUsed(0);
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkGraphics::SetFontCacheUsed(0);
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /*
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Currently we cannot support transparency in GL-based canvas' at
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            the view level. Therefore we cannot base our answer on the device's
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            bitmap, but need to hard-code the answer. If we relax this
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            limitation in views, we can simplify the following code as well.
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            Use the getViewport() call to find out if we're gl-based...
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        */
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (canvas->getViewport(NULL)) {
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return true;
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // normal technique, rely on the device's bitmap for the answer
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->getDevice()->accessBitmap(false).isOpaque();
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int getWidth(JNIEnv* env, jobject jcanvas) {
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->getDevice()->accessBitmap(false).width();
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int getHeight(JNIEnv* env, jobject jcanvas) {
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->getDevice()->accessBitmap(false).height();
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void setViewport(JNIEnv* env, jobject, SkCanvas* canvas,
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                            int width, int height) {
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->setViewport(width, height);
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas,
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                          SkBitmap* bitmap) {
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->setBitmapDevice(*bitmap);
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int saveAll(JNIEnv* env, jobject jcanvas) {
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int save(JNIEnv* env, jobject jcanvas, SkCanvas::SaveFlags flags) {
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int saveLayer(JNIEnv* env, jobject, SkCanvas* canvas, jobject bounds,
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         SkPaint* paint, int flags) {
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect* bounds_ = NULL;
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect  storage;
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (bounds != NULL) {
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            bounds_ = &storage;
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->saveLayer(bounds_, paint, (SkCanvas::SaveFlags)flags);
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
133f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int saveLayer4F(JNIEnv* env, jobject, SkCanvas* canvas,
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           jfloat l, jfloat t, jfloat r, jfloat b,
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           SkPaint* paint, int flags) {
137e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)        SkRect bounds;
138e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)        bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
139e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)                   SkFloatToScalar(b));
140e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)        return canvas->saveLayer(&bounds, paint, (SkCanvas::SaveFlags)flags);
141e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)    }
142e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)
143e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)    static int saveLayerAlpha(JNIEnv* env, jobject, SkCanvas* canvas,
144e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)                              jobject bounds, int alpha, int flags) {
145e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)        SkRect* bounds_ = NULL;
146e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)        SkRect  storage;
147e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)        if (bounds != NULL) {
148e7cb137f32fbc7caf97b80fac152b4bd3ac242cdJay Freeman (saurik)            GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            bounds_ = &storage;
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->saveLayerAlpha(bounds_, alpha,
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                      (SkCanvas::SaveFlags)flags);
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int saveLayerAlpha4F(JNIEnv* env, jobject, SkCanvas* canvas,
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                jfloat l, jfloat t, jfloat r, jfloat b,
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                int alpha, int flags) {
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect  bounds;
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                   SkFloatToScalar(b));
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->saveLayerAlpha(&bounds, alpha,
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                      (SkCanvas::SaveFlags)flags);
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void restore(JNIEnv* env, jobject jcanvas) {
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            doThrowISE(env, "Underflow in restore");
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->restore();
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static int getSaveCount(JNIEnv* env, jobject jcanvas) {
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void restoreToCount(JNIEnv* env, jobject jcanvas, int restoreCount) {
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (restoreCount < 1) {
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            doThrowIAE(env, "Underflow in restoreToCount");
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->restoreToCount(restoreCount);
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
19135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
19235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar dx_ = SkFloatToScalar(dx);
19335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar dy_ = SkFloatToScalar(dy);
19435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
19535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
19635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
19735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
19835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
19935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar sx_ = SkFloatToScalar(sx);
20035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar sy_ = SkFloatToScalar(sy);
20135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
20235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
20335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
20435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
20535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
20635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar degrees_ = SkFloatToScalar(degrees);
20735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
20835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
21135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
21235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar sx_ = SkFloatToScalar(sx);
21335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkScalar sy_ = SkFloatToScalar(sy);
21435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
21535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
21635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
21735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    static void concat(JNIEnv* env, jobject, SkCanvas* canvas,
21835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                       const SkMatrix* matrix) {
21935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        canvas->concat(*matrix);
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void setMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                          const SkMatrix* matrix) {
2246310a8261c922533a692fb3e74ece2da98d4bafaColin Cross        if (NULL == matrix) {
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            canvas->resetMatrix();
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            canvas->setMatrix(*matrix);
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  jfloat top, jfloat right, jfloat bottom) {
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect  r;
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        r.set(SkFloatToScalar(left), SkFloatToScalar(top),
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project              SkFloatToScalar(right), SkFloatToScalar(bottom));
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return c->clipRect(r);
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  jint top, jint right, jint bottom) {
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect  r;
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        r.set(SkIntToScalar(left), SkIntToScalar(top),
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project              SkIntToScalar(right), SkIntToScalar(bottom));
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, rectf);
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect tmp;
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, jcanvas);
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_ZERO(env, rect);
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect tmp;
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean clipRect(JNIEnv* env, jobject, SkCanvas* canvas,
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                             float left, float top, float right, float bottom,
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                             int op) {
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect rect;
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                 SkFloatToScalar(right), SkFloatToScalar(bottom));
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->clipRect(rect, (SkRegion::Op)op);
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean clipPath(JNIEnv* env, jobject, SkCanvas* canvas,
276e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                             SkPath* path, int op) {
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->clipPath(*path, (SkRegion::Op)op);
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
280cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    static jboolean clipRegion(JNIEnv* env, jobject, SkCanvas* canvas,
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                               SkRegion* deviceRgn, int op) {
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return canvas->clipRegion(*deviceRgn, (SkRegion::Op)op);
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void setDrawFilter(JNIEnv* env, jobject, SkCanvas* canvas,
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                              SkDrawFilter* filter) {
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->setDrawFilter(filter);
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
290cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas,
291cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross                                        jobject rect, int edgetype) {
292cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        SkRect rect_;
293cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
294cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype);
295cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    }
296cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas,
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                       SkPath* path, int edgetype) {
299e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype);
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
301e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
302e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas,
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                       jfloat left, jfloat top, jfloat right,
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                       jfloat bottom, int edgetype) {
305e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        SkRect r;
306e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        r.set(SkFloatToScalar(left), SkFloatToScalar(top),
307e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)              SkFloatToScalar(right), SkFloatToScalar(bottom));
308e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype);
309e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
310e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
311cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas,
312cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross                        jint r, jint g, jint b) {
313e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        canvas->drawARGB(0xFF, r, g, b);
314e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
315e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
316e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    static void drawARGB(JNIEnv* env, jobject, SkCanvas* canvas,
317e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                         jint a, jint r, jint g, jint b) {
318e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        canvas->drawARGB(a, r, g, b);
319e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
320e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
321e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    static void drawColor__I(JNIEnv* env, jobject, SkCanvas* canvas,
322e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                             jint color) {
323e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        canvas->drawColor(color);
324e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
325e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas,
327e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                              jint color, SkPorterDuff::Mode mode) {
328e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
329e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
330e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
331e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas,
332e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                          SkPaint* paint) {
333e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        canvas->drawPaint(*paint);
334e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
335e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
336e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
337e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                         jint offset, jint count, jobject jpaint,
338e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)                         SkCanvas::PointMode mode) {
339e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        NPE_CHECK_RETURN_VOID(env, jcanvas);
340e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        NPE_CHECK_RETURN_VOID(env, jptsArray);
341e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        NPE_CHECK_RETURN_VOID(env, jpaint);
342e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
343e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
344e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
345e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        AutoJavaFloatArray autoPts(env, jptsArray);
346e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        float* floats = autoPts.ptr();
347e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        const int length = autoPts.length();
348e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
349e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        if ((offset | count) < 0 || offset + count > length) {
350e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)            doThrowAIOOBE(env);
351e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)            return;
352e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        }
353e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
354e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        // now convert the floats into SkPoints
355e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        count >>= 1;    // now it is the number of points
356e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        SkAutoSTMalloc<32, SkPoint> storage(count);
357e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        SkPoint* pts = storage.get();
358e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        const float* src = floats + offset;
359cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        for (int i = 0; i < count; i++) {
360cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross            pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
361e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)            src += 2;
362e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        }
363e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)        canvas->drawPoints(mode, count, pts, paint);
364e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)    }
365e520d036165b36cf5c4cb305f9cec7d183977b61Jay Freeman (saurik)
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           jint offset, jint count, jobject jpaint) {
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                 SkCanvas::kPoints_PointMode);
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           jint offset, jint count, jobject jpaint) {
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                 SkCanvas::kLines_PointMode);
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawPoint(JNIEnv* env, jobject jcanvas, float x, float y,
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                          jobject jpaint) {
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jcanvas);
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NPE_CHECK_RETURN_VOID(env, jpaint);
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawLine__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    jfloat startX, jfloat startY, jfloat stopX,
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    jfloat stopY, SkPaint* paint) {
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         SkFloatToScalar(stopX), SkFloatToScalar(stopY),
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         *paint);
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawRect__RectFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                     jobject rect, SkPaint* paint) {
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect rect_;
399f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawRect(rect_, *paint);
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawRect__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    jfloat left, jfloat top, jfloat right,
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    jfloat bottom, SkPaint* paint) {
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkScalar left_ = SkFloatToScalar(left);
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkScalar top_ = SkFloatToScalar(top);
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkScalar right_ = SkFloatToScalar(right);
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkScalar bottom_ = SkFloatToScalar(bottom);
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawOval(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         SkPaint* paint) {
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect oval;
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        GraphicsJNI::jrectf_to_rect(env, joval, &oval);
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawOval(oval, *paint);
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
420f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    static void drawCircle(JNIEnv* env, jobject, SkCanvas* canvas, jfloat cx,
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           jfloat cy, jfloat radius, SkPaint* paint) {
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           SkFloatToScalar(radius), *paint);
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawArc(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
42711e1c42df69b15c938aa1b7570e4370e6ab15a86Jay Freeman (saurik)                        jfloat startAngle, jfloat sweepAngle,
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        jboolean useCenter, SkPaint* paint) {
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkRect oval;
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        GraphicsJNI::jrectf_to_rect(env, joval, &oval);
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawArc(oval, SkFloatToScalar(startAngle),
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        SkFloatToScalar(sweepAngle), useCenter, *paint);
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawRoundRect(JNIEnv* env, jobject, SkCanvas* canvas,
43635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                              jobject jrect, jfloat rx, jfloat ry,
43735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                              SkPaint* paint) {
43835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        SkRect rect;
43935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
44035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
44135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                              *paint);
44235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
44335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
44435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    static void drawPath(JNIEnv* env, jobject, SkCanvas* canvas, SkPath* path,
44535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                         SkPaint* paint) {
44635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        canvas->drawPath(*path, *paint);
44735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
44835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
44935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                            SkPicture* picture) {
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkASSERT(canvas);
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkASSERT(picture);
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#ifdef TIME_DRAW
4557c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
4567c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat#endif
4577c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        canvas->drawPicture(*picture);
4587c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat#ifdef TIME_DRAW
4597c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        LOGD("---- picture playback %d ms\n", get_thread_msec() - now);
4607c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat#endif
4617c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    }
4627c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4637c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
4647c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                                          SkCanvas* canvas, SkBitmap* bitmap,
4657c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                                          jfloat left, jfloat top,
4667c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                                          SkPaint* paint,
4677c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                                          jboolean autoScale, jfloat densityScale) {
4687c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        SkScalar left_ = SkFloatToScalar(left);
4697c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        SkScalar top_ = SkFloatToScalar(top);
4707c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4717c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        if (!autoScale || densityScale <= 0.0f) {
4727c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            canvas->drawBitmap(*bitmap, left_, top_, paint);
4734833d9f4986d6dafacff841beb3bf93172c84bdcTom Zhu        } else {
4747c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            canvas->save();
4757c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            SkScalar canvasScale = GraphicsJNI::getCanvasDensityScale(env, jcanvas);
4767c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            SkScalar scale = canvasScale / SkFloatToScalar(densityScale);
4777c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            canvas->scale(scale, scale);
4787c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4797c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            SkPaint filteredPaint;
4807c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            if (paint) {
4817c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                filteredPaint = *paint;
4827c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            }
4837c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            filteredPaint.setFilterBitmap(true);
4847c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4857c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
4867c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4877c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            canvas->restore();
4887c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        }
4897c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    }
4907c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4917c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
4927c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                        jobject srcIRect, const SkRect& dst, SkPaint* paint) {
4937c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        SkIRect    src, *srcPtr = NULL;
4947c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
4957c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        if (NULL != srcIRect) {
4967c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
4977c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat            srcPtr = &src;
4987c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        }
4997c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
5007c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    }
5017c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
5027c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas,
5037c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                             SkBitmap* bitmap, jobject srcIRect,
5047c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                             jobject dstRectF, SkPaint* paint) {
5057c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        SkRect      dst;
5067c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
5077c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint);
5087c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    }
5097c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat
5107c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas,
5117c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                             SkBitmap* bitmap, jobject srcIRect,
5127c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat                             jobject dstRect, SkPaint* paint) {
5137c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        SkRect      dst;
5147c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
5157c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat        doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint);
5167c44fe5925b6dd51166f73d30de0a2f22d66373eSan Mehat    }
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas,
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                jintArray jcolors, int offset, int stride,
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                jfloat x, jfloat y, int width, int height,
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                jboolean hasAlpha, SkPaint* paint)
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkBitmap    bitmap;
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         SkBitmap::kRGB_565_Config, width, height);
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!bitmap.allocPixels()) {
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    0, 0, width, height, bitmap)) {
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           paint);
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawBitmapMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                 const SkBitmap* bitmap, const SkMatrix* matrix,
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                 const SkPaint* paint) {
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static void drawBitmapMesh(JNIEnv* env, jobject, SkCanvas* canvas,
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                          const SkBitmap* bitmap, int meshWidth, int meshHeight,
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                          jfloatArray jverts, int vertIndex, jintArray jcolors,
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                          int colorIndex, const SkPaint* paint) {
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int ptCount = (meshWidth + 1) * (meshHeight + 1);
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int indexCount = meshWidth * meshHeight * 6;
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AutoJavaFloatArray  vertA(env, jverts, vertIndex + (ptCount << 1));
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AutoJavaIntArray    colorA(env, jcolors, colorIndex + ptCount);
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /*  Our temp storage holds 2 or 3 arrays.
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            texture points [ptCount * sizeof(SkPoint)]
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                copy to convert from float to fixed
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            indices [ptCount * sizeof(uint16_t)]
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        */
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#ifdef SK_SCALAR_IS_FIXED
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        storageSize += ptCount * sizeof(SkPoint);  // storage for verts
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        storageSize += indexCount * sizeof(uint16_t);  // indices[]
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkAutoMalloc storage(storageSize);
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkPoint* texs = (SkPoint*)storage.get();
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SkPoint* verts;
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        uint16_t* indices;
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#ifdef SK_SCALAR_IS_FLOAT
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        verts = (SkPoint*)(vertA.ptr() + vertIndex);
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        indices = (uint16_t*)(texs + ptCount);
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#else
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        verts = texs + ptCount;
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        indices = (uint16_t*)(verts + ptCount);
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // convert floats to fixed
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const float* src = vertA.ptr() + vertIndex;
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            for (int i = 0; i < ptCount; i++) {
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                src += 2;
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
586cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        }
587cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross#endif
588cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross
589cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        // cons up texture coordinates and indices
590cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        {
591cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross            const SkScalar w = SkIntToScalar(bitmap->width());
592cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross            const SkScalar h = SkIntToScalar(bitmap->height());
593cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross            const SkScalar dx = w / meshWidth;
594            const SkScalar dy = h / meshHeight;
595
596            SkPoint* texsPtr = texs;
597            SkScalar y = 0;
598            for (int i = 0; i <= meshHeight; i++) {
599                if (i == meshHeight) {
600                    y = h;  // to ensure numerically we hit h exactly
601                }
602                SkScalar x = 0;
603                for (int j = 0; j < meshWidth; j++) {
604                    texsPtr->set(x, y);
605                    texsPtr += 1;
606                    x += dx;
607                }
608                texsPtr->set(w, y);
609                texsPtr += 1;
610                y += dy;
611            }
612            SkASSERT(texsPtr - texs == ptCount);
613        }
614
615        // cons up indices
616        {
617            uint16_t* indexPtr = indices;
618            int index = 0;
619            for (int i = 0; i < meshHeight; i++) {
620                for (int j = 0; j < meshWidth; j++) {
621                    // lower-left triangle
622                    *indexPtr++ = index;
623                    *indexPtr++ = index + meshWidth + 1;
624                    *indexPtr++ = index + meshWidth + 2;
625                    // upper-right triangle
626                    *indexPtr++ = index;
627                    *indexPtr++ = index + meshWidth + 2;
628                    *indexPtr++ = index + 1;
629                    // bump to the next cell
630                    index += 1;
631                }
632                // bump to the next row
633                index += 1;
634            }
635            SkASSERT(indexPtr - indices == indexCount);
636            SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
637        }
638
639        // double-check that we have legal indices
640#ifdef SK_DEBUG
641        {
642            for (int i = 0; i < indexCount; i++) {
643                SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
644            }
645        }
646#endif
647
648        // cons-up a shader for the bitmap
649        SkPaint tmpPaint;
650        if (paint) {
651            tmpPaint = *paint;
652        }
653        SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
654                        SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
655        tmpPaint.setShader(shader)->safeUnref();
656
657        canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
658                             texs, (const SkColor*)colorA.ptr(), NULL, indices,
659                             indexCount, tmpPaint);
660    }
661
662    static void drawVertices(JNIEnv* env, jobject, SkCanvas* canvas,
663                             SkCanvas::VertexMode mode, int vertexCount,
664                             jfloatArray jverts, int vertIndex,
665                             jfloatArray jtexs, int texIndex,
666                             jintArray jcolors, int colorIndex,
667                             jshortArray jindices, int indexIndex,
668                             int indexCount, const SkPaint* paint) {
669
670        AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
671        AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
672        AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
673        AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
674
675        const int ptCount = vertexCount >> 1;
676
677        SkPoint* verts;
678        SkPoint* texs = NULL;
679#ifdef SK_SCALAR_IS_FLOAT
680        verts = (SkPoint*)(vertA.ptr() + vertIndex);
681        if (jtexs != NULL) {
682            texs = (SkPoint*)(texA.ptr() + texIndex);
683        }
684#else
685        int count = ptCount;    // for verts
686        if (jtexs != NULL) {
687            count += ptCount;   // += for texs
688        }
689        SkAutoMalloc storage(count * sizeof(SkPoint));
690        verts = (SkPoint*)storage.get();
691        const float* src = vertA.ptr() + vertIndex;
692        for (int i = 0; i < ptCount; i++) {
693            verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
694            src += 2;
695        }
696        if (jtexs != NULL) {
697            texs = verts + ptCount;
698            src = texA.ptr() + texIndex;
699            for (int i = 0; i < ptCount; i++) {
700                texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
701                src += 2;
702            }
703        }
704#endif
705
706        const SkColor* colors = NULL;
707        const uint16_t* indices = NULL;
708        if (jcolors != NULL) {
709            colors = (const SkColor*)(colorA.ptr() + colorIndex);
710        }
711        if (jindices != NULL) {
712            indices = (const uint16_t*)(indexA.ptr() + indexIndex);
713        }
714
715        canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
716                             indices, indexCount, *paint);
717    }
718
719    static void drawText___CIIFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
720                                      jcharArray text, int index, int count,
721                                      jfloat x, jfloat y, SkPaint* paint) {
722        jchar* textArray = env->GetCharArrayElements(text, NULL);
723        jsize textCount = env->GetArrayLength(text);
724        SkScalar x_ = SkFloatToScalar(x);
725        SkScalar y_ = SkFloatToScalar(y);
726        canvas->drawText(textArray + index, count << 1, x_, y_, *paint);
727        env->ReleaseCharArrayElements(text, textArray, 0);
728    }
729
730    static void drawText__StringIIFFPaint(JNIEnv* env, jobject,
731                            SkCanvas* canvas, jstring text, int start, int end,
732                                          jfloat x, jfloat y, SkPaint* paint) {
733        const void* text_ = env->GetStringChars(text, NULL);
734        SkScalar x_ = SkFloatToScalar(x);
735        SkScalar y_ = SkFloatToScalar(y);
736        canvas->drawText((const uint16_t*)text_ + start, (end - start) << 1,
737                         x_, y_, *paint);
738        env->ReleaseStringChars(text, (const jchar*) text_);
739    }
740
741    static void drawString(JNIEnv* env, jobject canvas, jstring text,
742                           jfloat x, jfloat y, jobject paint) {
743        NPE_CHECK_RETURN_VOID(env, canvas);
744        NPE_CHECK_RETURN_VOID(env, paint);
745        NPE_CHECK_RETURN_VOID(env, text);
746        size_t count = env->GetStringLength(text);
747        if (0 == count) {
748            return;
749        }
750        const jchar* text_ = env->GetStringChars(text, NULL);
751        SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
752        c->drawText(text_, count << 1, SkFloatToScalar(x), SkFloatToScalar(y),
753                    *GraphicsJNI::getNativePaint(env, paint));
754        env->ReleaseStringChars(text, text_);
755    }
756
757    static void drawPosText___CII_FPaint(JNIEnv* env, jobject, SkCanvas* canvas,
758                                         jcharArray text, int index, int count,
759                                         jfloatArray pos, SkPaint* paint) {
760        jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
761        jsize textCount = text ? env->GetArrayLength(text) : NULL;
762        float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
763        int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
764        SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
765        int indx;
766        for (indx = 0; indx < posCount; indx++) {
767            posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
768            posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
769        }
770        canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
771        if (text) {
772            env->ReleaseCharArrayElements(text, textArray, 0);
773        }
774        if (pos) {
775            env->ReleaseFloatArrayElements(pos, posArray, 0);
776        }
777        delete[] posPtr;
778    }
779
780    static void drawPosText__String_FPaint(JNIEnv* env, jobject,
781                                           SkCanvas* canvas, jstring text,
782                                           jfloatArray pos, SkPaint* paint) {
783        const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
784        int byteLength = text ? env->GetStringLength(text) : 0;
785        float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
786        int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
787        SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
788
789        for (int indx = 0; indx < posCount; indx++) {
790            posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
791            posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
792        }
793        canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
794        if (text) {
795            env->ReleaseStringChars(text, (const jchar*) text_);
796        }
797        if (pos) {
798            env->ReleaseFloatArrayElements(pos, posArray, 0);
799        }
800        delete[] posPtr;
801    }
802
803    static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
804                        SkCanvas* canvas, jcharArray text, int index, int count,
805                SkPath* path, jfloat hOffset, jfloat vOffset, SkPaint* paint) {
806
807        jchar* textArray = env->GetCharArrayElements(text, NULL);
808        canvas->drawTextOnPathHV(textArray + index, count << 1, *path,
809                    SkFloatToScalar(hOffset), SkFloatToScalar(vOffset), *paint);
810        env->ReleaseCharArrayElements(text, textArray, 0);
811    }
812
813    static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
814                            SkCanvas* canvas, jstring text, SkPath* path,
815                            jfloat hOffset, jfloat vOffset, SkPaint* paint) {
816        const jchar* text_ = env->GetStringChars(text, NULL);
817        int byteLength = env->GetStringLength(text) << 1;
818        canvas->drawTextOnPathHV(text_, byteLength, *path,
819                    SkFloatToScalar(hOffset), SkFloatToScalar(vOffset), *paint);
820        env->ReleaseStringChars(text, text_);
821    }
822
823    static bool getClipBounds(JNIEnv* env, jobject, SkCanvas* canvas,
824                              jobject bounds) {
825        SkRect   r;
826        SkIRect ir;
827        bool     result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
828
829        r.round(&ir);
830        (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
831        return result;
832    }
833
834    static void getCTM(JNIEnv* env, jobject, SkCanvas* canvas,
835                       SkMatrix* matrix) {
836        *matrix = canvas->getTotalMatrix();
837    }
838};
839
840///////////////////////////////////////////////////////////////////////////////
841
842static JNINativeMethod gCanvasMethods[] = {
843    {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
844    {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster},
845    {"initGL","()I", (void*) SkCanvasGlue::initGL},
846    {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
847    {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
848    {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
849    {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
850    {"nativeSetViewport", "(III)V", (void*) SkCanvasGlue::setViewport},
851    {"save","()I", (void*) SkCanvasGlue::saveAll},
852    {"save","(I)I", (void*) SkCanvasGlue::save},
853    {"native_saveLayer","(ILandroid/graphics/RectF;II)I",
854        (void*) SkCanvasGlue::saveLayer},
855    {"native_saveLayer","(IFFFFII)I", (void*) SkCanvasGlue::saveLayer4F},
856    {"native_saveLayerAlpha","(ILandroid/graphics/RectF;II)I",
857        (void*) SkCanvasGlue::saveLayerAlpha},
858    {"native_saveLayerAlpha","(IFFFFII)I",
859        (void*) SkCanvasGlue::saveLayerAlpha4F},
860    {"restore","()V", (void*) SkCanvasGlue::restore},
861    {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
862    {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
863    {"translate","(FF)V", (void*) SkCanvasGlue::translate},
864    {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
865    {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
866    {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
867    {"native_concat","(II)V", (void*) SkCanvasGlue::concat},
868    {"native_setMatrix","(II)V", (void*) SkCanvasGlue::setMatrix},
869    {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
870    {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
871    {"clipRect","(Landroid/graphics/RectF;)Z",
872        (void*) SkCanvasGlue::clipRect_RectF},
873    {"clipRect","(Landroid/graphics/Rect;)Z",
874        (void*) SkCanvasGlue::clipRect_Rect},
875    {"native_clipRect","(IFFFFI)Z", (void*) SkCanvasGlue::clipRect},
876    {"native_clipPath","(III)Z", (void*) SkCanvasGlue::clipPath},
877    {"native_clipRegion","(III)Z", (void*) SkCanvasGlue::clipRegion},
878    {"nativeSetDrawFilter", "(II)V", (void*) SkCanvasGlue::setDrawFilter},
879    {"native_getClipBounds","(ILandroid/graphics/Rect;)Z",
880        (void*) SkCanvasGlue::getClipBounds},
881    {"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM},
882    {"native_quickReject","(ILandroid/graphics/RectF;I)Z",
883        (void*) SkCanvasGlue::quickReject__RectFI},
884    {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI},
885    {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI},
886    {"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB},
887    {"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB},
888    {"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I},
889    {"native_drawColor","(III)V", (void*) SkCanvasGlue::drawColor__II},
890    {"native_drawPaint","(II)V", (void*) SkCanvasGlue::drawPaint},
891    {"drawPoint", "(FFLandroid/graphics/Paint;)V",
892    (void*) SkCanvasGlue::drawPoint},
893    {"drawPoints", "([FIILandroid/graphics/Paint;)V",
894        (void*) SkCanvasGlue::drawPoints},
895    {"drawLines", "([FIILandroid/graphics/Paint;)V",
896        (void*) SkCanvasGlue::drawLines},
897    {"native_drawLine","(IFFFFI)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
898    {"native_drawRect","(ILandroid/graphics/RectF;I)V",
899        (void*) SkCanvasGlue::drawRect__RectFPaint},
900    {"native_drawRect","(IFFFFI)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
901    {"native_drawOval","(ILandroid/graphics/RectF;I)V",
902        (void*) SkCanvasGlue::drawOval},
903    {"native_drawCircle","(IFFFI)V", (void*) SkCanvasGlue::drawCircle},
904    {"native_drawArc","(ILandroid/graphics/RectF;FFZI)V",
905        (void*) SkCanvasGlue::drawArc},
906    {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
907        (void*) SkCanvasGlue::drawRoundRect},
908    {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
909    {"native_drawBitmap","(IIFFIZF)V",
910        (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
911    {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;I)V",
912        (void*) SkCanvasGlue::drawBitmapRF},
913    {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;I)V",
914        (void*) SkCanvasGlue::drawBitmapRR},
915    {"native_drawBitmap", "(I[IIIFFIIZI)V",
916    (void*)SkCanvasGlue::drawBitmapArray},
917
918    {"nativeDrawBitmapMatrix", "(IIII)V",
919        (void*)SkCanvasGlue::drawBitmapMatrix},
920    {"nativeDrawBitmapMesh", "(IIII[FI[III)V",
921        (void*)SkCanvasGlue::drawBitmapMesh},
922    {"nativeDrawVertices", "(III[FI[FI[II[SIII)V",
923        (void*)SkCanvasGlue::drawVertices},
924    {"native_drawText","(I[CIIFFI)V",
925        (void*) SkCanvasGlue::drawText___CIIFFPaint},
926    {"native_drawText","(ILjava/lang/String;IIFFI)V",
927        (void*) SkCanvasGlue::drawText__StringIIFFPaint},
928    {"drawText","(Ljava/lang/String;FFLandroid/graphics/Paint;)V",
929        (void*) SkCanvasGlue::drawString},
930    {"native_drawPosText","(I[CII[FI)V",
931        (void*) SkCanvasGlue::drawPosText___CII_FPaint},
932    {"native_drawPosText","(ILjava/lang/String;[FI)V",
933        (void*) SkCanvasGlue::drawPosText__String_FPaint},
934    {"native_drawTextOnPath","(I[CIIIFFI)V",
935        (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
936    {"native_drawTextOnPath","(ILjava/lang/String;IFFI)V",
937        (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
938    {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
939
940    {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
941};
942
943#include <android_runtime/AndroidRuntime.h>
944
945#define REG(env, name, array) \
946    result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
947                                                    SK_ARRAY_COUNT(array));  \
948    if (result < 0) return result
949
950int register_android_graphics_Canvas(JNIEnv* env) {
951    int result;
952
953    REG(env, "android/graphics/Canvas", gCanvasMethods);
954
955    return result;
956}
957
958}
959