android_view_GLES20Canvas.cpp revision f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640
1/* 2 * Copyright (C) 2010 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 <nativehelper/JNIHelp.h> 19#include <android_runtime/AndroidRuntime.h> 20 21#include <SkBitmap.h> 22#include <SkCanvas.h> 23#include <SkMatrix.h> 24#include <SkPaint.h> 25#include <SkXfermode.h> 26 27#include <OpenGLRenderer.h> 28#include <Rect.h> 29#include <ui/Rect.h> 30 31namespace android { 32 33using namespace uirenderer; 34 35// ---------------------------------------------------------------------------- 36// Java APIs 37// ---------------------------------------------------------------------------- 38 39static struct { 40 jclass clazz; 41 jmethodID set; 42} gRectClassInfo; 43 44// ---------------------------------------------------------------------------- 45// Constructors 46// ---------------------------------------------------------------------------- 47 48static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject canvas) { 49 return new OpenGLRenderer; 50} 51 52static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject canvas, 53 OpenGLRenderer* renderer) { 54 delete renderer; 55} 56 57// ---------------------------------------------------------------------------- 58// Setup 59// ---------------------------------------------------------------------------- 60 61static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject canvas, 62 OpenGLRenderer* renderer, jint width, jint height) { 63 renderer->setViewport(width, height); 64} 65 66static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject canvas, 67 OpenGLRenderer* renderer) { 68 renderer->prepare(); 69} 70 71// ---------------------------------------------------------------------------- 72// State 73// ---------------------------------------------------------------------------- 74 75static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, 76 jint flags) { 77 return renderer->save(flags); 78} 79 80static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject canvas, 81 OpenGLRenderer* renderer) { 82 return renderer->getSaveCount(); 83} 84 85static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject canvas, 86 OpenGLRenderer* renderer) { 87 renderer->restore(); 88} 89 90static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject canvas, 91 OpenGLRenderer* renderer, jint saveCount) { 92 renderer->restoreToCount(saveCount); 93} 94 95// ---------------------------------------------------------------------------- 96// Layers 97// ---------------------------------------------------------------------------- 98 99static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject canvas, 100 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 101 SkPaint* paint, jint saveFlags) { 102 return renderer->saveLayer(left, top, right, bottom, paint, saveFlags); 103} 104 105static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject canvas, 106 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 107 jint alpha, jint saveFlags) { 108 return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); 109} 110 111// ---------------------------------------------------------------------------- 112// Clipping 113// ---------------------------------------------------------------------------- 114 115static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject canvas, 116 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 117 SkCanvas::EdgeType edge) { 118 return renderer->quickReject(left, top, right, bottom); 119} 120 121static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject canvas, 122 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) { 123 return renderer->clipRect(left, top, right, bottom); 124} 125 126static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject canvas, 127 OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom) { 128 return renderer->clipRect(float(left), float(top), float(right), float(bottom)); 129} 130 131static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject canvas, 132 OpenGLRenderer* renderer, jobject rect) { 133 const android::uirenderer::Rect& bounds(renderer->getClipBounds()); 134 135 env->CallVoidMethod(rect, gRectClassInfo.set, 136 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom)); 137 138 return !bounds.isEmpty(); 139} 140 141// ---------------------------------------------------------------------------- 142// Transforms 143// ---------------------------------------------------------------------------- 144 145static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject canvas, 146 OpenGLRenderer* renderer, jfloat dx, jfloat dy) { 147 renderer->translate(dx, dy); 148} 149 150static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject canvas, 151 OpenGLRenderer* renderer, jfloat degrees) { 152 renderer->rotate(degrees); 153} 154 155static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject canvas, 156 OpenGLRenderer* renderer, jfloat sx, jfloat sy) { 157 renderer->scale(sx, sy); 158} 159 160static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject canvas, 161 OpenGLRenderer* renderer, SkMatrix* matrix) { 162 renderer->setMatrix(matrix); 163} 164 165static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject canvas, 166 OpenGLRenderer* renderer, SkMatrix* matrix) { 167 renderer->getMatrix(matrix); 168} 169 170static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject canvas, 171 OpenGLRenderer* renderer, SkMatrix* matrix) { 172 renderer->concatMatrix(matrix); 173} 174 175// ---------------------------------------------------------------------------- 176// Drawing 177// ---------------------------------------------------------------------------- 178 179static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject canvas, 180 OpenGLRenderer* renderer, SkBitmap* bitmap, float left, float top, 181 SkPaint* paint, jint bitmapDensity, jint canvasDensity,jint screenDensity) { 182 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { 183 renderer->drawBitmap(bitmap, left, top, paint); 184 } else { 185 renderer->save(0); 186 const float scale = canvasDensity / float(bitmapDensity); 187 renderer->translate(left, top); 188 renderer->scale(scale, scale); 189 renderer->drawBitmap(bitmap, left, top, paint); 190 renderer->restore(); 191 } 192} 193 194static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject canvas, 195 OpenGLRenderer* renderer, SkBitmap* bitmap, 196 float srcLeft, float srcTop, float srcRight, float srcBottom, 197 float dstLeft, float dstTop, float dstRight, float dstBottom, 198 SkPaint* paint, jint bitmapDensity, jint canvasDensity, jint screenDensity) { 199 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { 200 renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 201 dstLeft, dstTop, dstRight, dstBottom, paint); 202 } else { 203 // TODO: implement 204 } 205} 206 207static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject canvas, 208 OpenGLRenderer* renderer, SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint, 209 jint bitmapDensity, jint canvasDensity,jint screenDensity) { 210 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { 211 renderer->drawBitmap(bitmap, matrix, paint); 212 } else { 213 // TODO: implement 214 } 215} 216 217static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject canvas, 218 OpenGLRenderer* renderer, jint color, SkXfermode::Mode mode) { 219 renderer->drawColor(color, mode); 220} 221 222static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject canvas, 223 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 224 SkPaint* paint) { 225 renderer->drawRect(left, top, right, bottom, paint); 226} 227 228// ---------------------------------------------------------------------------- 229// JNI Glue 230// ---------------------------------------------------------------------------- 231 232const char* const kClassPathName = "android/view/GLES20Canvas"; 233 234static JNINativeMethod gMethods[] = { 235 { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer }, 236 { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer }, 237 { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport }, 238 { "nPrepare", "(I)V", (void*) android_view_GLES20Canvas_prepare }, 239 240 { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save }, 241 { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore }, 242 { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount }, 243 { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount }, 244 245 { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer }, 246 { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha }, 247 248 { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject }, 249 { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Canvas_clipRectF }, 250 { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Canvas_clipRect }, 251 252 { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate }, 253 { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate }, 254 { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale }, 255 256 { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix }, 257 { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix }, 258 { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix }, 259 260 { "nDrawBitmap", "(IIFFIIII)V", (void*) android_view_GLES20Canvas_drawBitmap }, 261 { "nDrawBitmap", "(IIFFFFFFFFIIII)V", (void*) android_view_GLES20Canvas_drawBitmapRect }, 262 { "nDrawBitmap", "(IIIIIII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix }, 263 { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor }, 264 { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, 265 266 { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z", 267 (void*) android_view_GLES20Canvas_getClipBounds }, 268}; 269 270#define FIND_CLASS(var, className) \ 271 var = env->FindClass(className); \ 272 LOG_FATAL_IF(! var, "Unable to find class " className); \ 273 var = jclass(env->NewGlobalRef(var)); 274 275#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 276 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 277 LOG_FATAL_IF(! var, "Unable to find method " methodName); 278 279int register_android_view_GLES20Canvas(JNIEnv* env) { 280 FIND_CLASS(gRectClassInfo.clazz, "android/graphics/Rect"); 281 GET_METHOD_ID(gRectClassInfo.set, gRectClassInfo.clazz, "set", "(IIII)V"); 282 283 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 284} 285 286}; 287