1 /* libs/android_runtime/android/graphics/Matrix.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "GraphicsJNI.h" 19 #include "Matrix.h" 20 #include "SkMatrix.h" 21 #include "core_jni_helpers.h" 22 23 #include <jni.h> 24 25 namespace android { 26 27 static_assert(sizeof(SkMatrix) == 40, "Unexpected sizeof(SkMatrix), " 28 "update size in Matrix.java#NATIVE_ALLOCATION_SIZE and here"); 29 static_assert(SK_SCALAR_IS_FLOAT, "SK_SCALAR_IS_FLOAT is false, " 30 "only float scalar is supported"); 31 32 class SkMatrixGlue { 33 public: 34 35 // ---------------- Regular JNI ----------------------------- 36 37 static void finalizer(jlong objHandle) { 38 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 39 delete obj; 40 } 41 42 static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) { 43 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&finalizer)); 44 } 45 46 static jlong create(JNIEnv* env, jobject clazz, jlong srcHandle) { 47 const SkMatrix* src = reinterpret_cast<SkMatrix*>(srcHandle); 48 SkMatrix* obj = new SkMatrix(); 49 if (src) 50 *obj = *src; 51 else 52 obj->reset(); 53 return reinterpret_cast<jlong>(obj); 54 } 55 56 // ---------------- @FastNative ----------------------------- 57 58 static void mapPoints(JNIEnv* env, jobject clazz, jlong matrixHandle, 59 jfloatArray dst, jint dstIndex, jfloatArray src, jint srcIndex, 60 jint ptCount, jboolean isPts) { 61 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 62 SkASSERT(ptCount >= 0); 63 AutoJavaFloatArray autoSrc(env, src, srcIndex + (ptCount << 1), 64 kRO_JNIAccess); 65 AutoJavaFloatArray autoDst(env, dst, dstIndex + (ptCount << 1), 66 kRW_JNIAccess); 67 float* srcArray = autoSrc.ptr() + srcIndex; 68 float* dstArray = autoDst.ptr() + dstIndex; 69 if (isPts) 70 matrix->mapPoints((SkPoint*) dstArray, (const SkPoint*) srcArray, 71 ptCount); 72 else 73 matrix->mapVectors((SkVector*) dstArray, (const SkVector*) srcArray, 74 ptCount); 75 } 76 77 static jboolean mapRect__RectFRectF(JNIEnv* env, jobject clazz, 78 jlong matrixHandle, jobjectArray dst, jobject src) { 79 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 80 SkRect dst_, src_; 81 GraphicsJNI::jrectf_to_rect(env, src, &src_); 82 jboolean rectStaysRect = matrix->mapRect(&dst_, src_); 83 GraphicsJNI::rect_to_jrectf(dst_, env, dst); 84 return rectStaysRect ? JNI_TRUE : JNI_FALSE; 85 } 86 87 static jboolean setRectToRect(JNIEnv* env, jobject clazz, 88 jlong matrixHandle, jobject src, jobject dst, jint stfHandle) { 89 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 90 SkMatrix::ScaleToFit stf = static_cast<SkMatrix::ScaleToFit>(stfHandle); 91 SkRect src_; 92 GraphicsJNI::jrectf_to_rect(env, src, &src_); 93 SkRect dst_; 94 GraphicsJNI::jrectf_to_rect(env, dst, &dst_); 95 return matrix->setRectToRect(src_, dst_, stf) ? JNI_TRUE : JNI_FALSE; 96 } 97 98 static jboolean setPolyToPoly(JNIEnv* env, jobject clazz, 99 jlong matrixHandle, jfloatArray jsrc, jint srcIndex, 100 jfloatArray jdst, jint dstIndex, jint ptCount) { 101 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 102 SkASSERT(srcIndex >= 0); 103 SkASSERT(dstIndex >= 0); 104 SkASSERT((unsigned )ptCount <= 4); 105 106 AutoJavaFloatArray autoSrc(env, jsrc, srcIndex + (ptCount << 1), 107 kRO_JNIAccess); 108 AutoJavaFloatArray autoDst(env, jdst, dstIndex + (ptCount << 1), 109 kRW_JNIAccess); 110 float* src = autoSrc.ptr() + srcIndex; 111 float* dst = autoDst.ptr() + dstIndex; 112 bool result; 113 114 result = matrix->setPolyToPoly((const SkPoint*) src, 115 (const SkPoint*) dst, ptCount); 116 return result ? JNI_TRUE : JNI_FALSE; 117 } 118 119 static void getValues(JNIEnv* env, jobject clazz, jlong matrixHandle, 120 jfloatArray values) { 121 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 122 AutoJavaFloatArray autoValues(env, values, 9, kRW_JNIAccess); 123 float* dst = autoValues.ptr(); 124 for (int i = 0; i < 9; i++) { 125 dst[i] = matrix->get(i); 126 } 127 } 128 129 static void setValues(JNIEnv* env, jobject clazz, jlong matrixHandle, 130 jfloatArray values) { 131 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 132 AutoJavaFloatArray autoValues(env, values, 9, kRO_JNIAccess); 133 const float* src = autoValues.ptr(); 134 135 for (int i = 0; i < 9; i++) { 136 matrix->set(i, src[i]); 137 } 138 } 139 140 // ---------------- @CriticalNative ----------------------------- 141 142 static jboolean isIdentity(jlong objHandle) { 143 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 144 return obj->isIdentity() ? JNI_TRUE : JNI_FALSE; 145 } 146 147 static jboolean isAffine(jlong objHandle) { 148 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 149 return obj->asAffine(NULL) ? JNI_TRUE : JNI_FALSE; 150 } 151 152 static jboolean rectStaysRect(jlong objHandle) { 153 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 154 return obj->rectStaysRect() ? JNI_TRUE : JNI_FALSE; 155 } 156 157 static void reset(jlong objHandle) { 158 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 159 obj->reset(); 160 } 161 162 static void set(jlong objHandle, jlong otherHandle) { 163 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 164 SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle); 165 *obj = *other; 166 } 167 168 static void setTranslate(jlong objHandle, jfloat dx, jfloat dy) { 169 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 170 obj->setTranslate(dx, dy); 171 } 172 173 static void setScale__FFFF(jlong objHandle, jfloat sx, jfloat sy, jfloat px, 174 jfloat py) { 175 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 176 obj->setScale(sx, sy, px, py); 177 } 178 179 static void setScale__FF(jlong objHandle, jfloat sx, jfloat sy) { 180 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 181 obj->setScale(sx, sy); 182 } 183 184 static void setRotate__FFF(jlong objHandle, jfloat degrees, jfloat px, 185 jfloat py) { 186 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 187 obj->setRotate(degrees, px, py); 188 } 189 190 static void setRotate__F(jlong objHandle, jfloat degrees) { 191 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 192 obj->setRotate(degrees); 193 } 194 195 static void setSinCos__FFFF(jlong objHandle, jfloat sinValue, 196 jfloat cosValue, jfloat px, jfloat py) { 197 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 198 obj->setSinCos(sinValue, cosValue, px, py); 199 } 200 201 static void setSinCos__FF(jlong objHandle, jfloat sinValue, 202 jfloat cosValue) { 203 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 204 obj->setSinCos(sinValue, cosValue); 205 } 206 207 static void setSkew__FFFF(jlong objHandle, jfloat kx, jfloat ky, jfloat px, 208 jfloat py) { 209 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 210 obj->setSkew(kx, ky, px, py); 211 } 212 213 static void setSkew__FF(jlong objHandle, jfloat kx, jfloat ky) { 214 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 215 obj->setSkew(kx, ky); 216 } 217 218 static void setConcat(jlong objHandle, jlong aHandle, jlong bHandle) { 219 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 220 SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle); 221 SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle); 222 obj->setConcat(*a, *b); 223 } 224 225 static void preTranslate(jlong objHandle, jfloat dx, jfloat dy) { 226 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 227 obj->preTranslate(dx, dy); 228 } 229 230 static void preScale__FFFF(jlong objHandle, jfloat sx, jfloat sy, jfloat px, 231 jfloat py) { 232 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 233 obj->preScale(sx, sy, px, py); 234 } 235 236 static void preScale__FF(jlong objHandle, jfloat sx, jfloat sy) { 237 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 238 obj->preScale(sx, sy); 239 } 240 241 static void preRotate__FFF(jlong objHandle, jfloat degrees, jfloat px, 242 jfloat py) { 243 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 244 obj->preRotate(degrees, px, py); 245 } 246 247 static void preRotate__F(jlong objHandle, jfloat degrees) { 248 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 249 obj->preRotate(degrees); 250 } 251 252 static void preSkew__FFFF(jlong objHandle, jfloat kx, jfloat ky, jfloat px, 253 jfloat py) { 254 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 255 obj->preSkew(kx, ky, px, py); 256 } 257 258 static void preSkew__FF(jlong objHandle, jfloat kx, jfloat ky) { 259 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 260 obj->preSkew(kx, ky); 261 } 262 263 static void preConcat(jlong objHandle, jlong otherHandle) { 264 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 265 SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle); 266 obj->preConcat(*other); 267 } 268 269 static void postTranslate(jlong objHandle, jfloat dx, jfloat dy) { 270 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 271 obj->postTranslate(dx, dy); 272 } 273 274 static void postScale__FFFF(jlong objHandle, jfloat sx, jfloat sy, 275 jfloat px, jfloat py) { 276 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 277 obj->postScale(sx, sy, px, py); 278 } 279 280 static void postScale__FF(jlong objHandle, jfloat sx, jfloat sy) { 281 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 282 obj->postScale(sx, sy); 283 } 284 285 static void postRotate__FFF(jlong objHandle, jfloat degrees, jfloat px, 286 jfloat py) { 287 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 288 obj->postRotate(degrees, px, py); 289 } 290 291 static void postRotate__F(jlong objHandle, jfloat degrees) { 292 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 293 obj->postRotate(degrees); 294 } 295 296 static void postSkew__FFFF(jlong objHandle, jfloat kx, jfloat ky, jfloat px, 297 jfloat py) { 298 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); 299 obj->postSkew(kx, ky, px, py); 300 } 301 302 static void postSkew__FF(jlong matrixHandle, jfloat kx, jfloat ky) { 303 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 304 matrix->postSkew(kx, ky); 305 } 306 307 static void postConcat(jlong matrixHandle, jlong otherHandle) { 308 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 309 SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle); 310 matrix->postConcat(*other); 311 } 312 313 static jboolean invert(jlong matrixHandle, jlong inverseHandle) { 314 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 315 SkMatrix* inverse = reinterpret_cast<SkMatrix*>(inverseHandle); 316 return matrix->invert(inverse); 317 } 318 319 static jfloat mapRadius(jlong matrixHandle, jfloat radius) { 320 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 321 float result; 322 result = SkScalarToFloat(matrix->mapRadius(radius)); 323 return static_cast<jfloat>(result); 324 } 325 326 static jboolean equals(jlong aHandle, jlong bHandle) { 327 const SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle); 328 const SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle); 329 return *a == *b; 330 } 331 }; 332 333 static const JNINativeMethod methods[] = { 334 {"nGetNativeFinalizer", "()J", (void*) SkMatrixGlue::getNativeFinalizer}, 335 {"nCreate","(J)J", (void*) SkMatrixGlue::create}, 336 337 // ------- @FastNative below here --------------- 338 {"nMapPoints","(J[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints}, 339 {"nMapRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;)Z", 340 (void*) SkMatrixGlue::mapRect__RectFRectF}, 341 {"nSetRectToRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", 342 (void*) SkMatrixGlue::setRectToRect}, 343 {"nSetPolyToPoly","(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly}, 344 {"nGetValues","(J[F)V", (void*) SkMatrixGlue::getValues}, 345 {"nSetValues","(J[F)V", (void*) SkMatrixGlue::setValues}, 346 347 // ------- @CriticalNative below here --------------- 348 {"nIsIdentity","(J)Z", (void*) SkMatrixGlue::isIdentity}, 349 {"nIsAffine","(J)Z", (void*) SkMatrixGlue::isAffine}, 350 {"nRectStaysRect","(J)Z", (void*) SkMatrixGlue::rectStaysRect}, 351 {"nReset","(J)V", (void*) SkMatrixGlue::reset}, 352 {"nSet","(JJ)V", (void*) SkMatrixGlue::set}, 353 {"nSetTranslate","(JFF)V", (void*) SkMatrixGlue::setTranslate}, 354 {"nSetScale","(JFFFF)V", (void*) SkMatrixGlue::setScale__FFFF}, 355 {"nSetScale","(JFF)V", (void*) SkMatrixGlue::setScale__FF}, 356 {"nSetRotate","(JFFF)V", (void*) SkMatrixGlue::setRotate__FFF}, 357 {"nSetRotate","(JF)V", (void*) SkMatrixGlue::setRotate__F}, 358 {"nSetSinCos","(JFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF}, 359 {"nSetSinCos","(JFF)V", (void*) SkMatrixGlue::setSinCos__FF}, 360 {"nSetSkew","(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF}, 361 {"nSetSkew","(JFF)V", (void*) SkMatrixGlue::setSkew__FF}, 362 {"nSetConcat","(JJJ)V", (void*) SkMatrixGlue::setConcat}, 363 {"nPreTranslate","(JFF)V", (void*) SkMatrixGlue::preTranslate}, 364 {"nPreScale","(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF}, 365 {"nPreScale","(JFF)V", (void*) SkMatrixGlue::preScale__FF}, 366 {"nPreRotate","(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF}, 367 {"nPreRotate","(JF)V", (void*) SkMatrixGlue::preRotate__F}, 368 {"nPreSkew","(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF}, 369 {"nPreSkew","(JFF)V", (void*) SkMatrixGlue::preSkew__FF}, 370 {"nPreConcat","(JJ)V", (void*) SkMatrixGlue::preConcat}, 371 {"nPostTranslate","(JFF)V", (void*) SkMatrixGlue::postTranslate}, 372 {"nPostScale","(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF}, 373 {"nPostScale","(JFF)V", (void*) SkMatrixGlue::postScale__FF}, 374 {"nPostRotate","(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF}, 375 {"nPostRotate","(JF)V", (void*) SkMatrixGlue::postRotate__F}, 376 {"nPostSkew","(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF}, 377 {"nPostSkew","(JFF)V", (void*) SkMatrixGlue::postSkew__FF}, 378 {"nPostConcat","(JJ)V", (void*) SkMatrixGlue::postConcat}, 379 {"nInvert","(JJ)Z", (void*) SkMatrixGlue::invert}, 380 {"nMapRadius","(JF)F", (void*) SkMatrixGlue::mapRadius}, 381 {"nEquals", "(JJ)Z", (void*) SkMatrixGlue::equals} 382 }; 383 384 static jfieldID sNativeInstanceField; 385 386 int register_android_graphics_Matrix(JNIEnv* env) { 387 int result = RegisterMethodsOrDie(env, "android/graphics/Matrix", methods, NELEM(methods)); 388 389 jclass clazz = FindClassOrDie(env, "android/graphics/Matrix"); 390 sNativeInstanceField = GetFieldIDOrDie(env, clazz, "native_instance", "J"); 391 392 return result; 393 } 394 395 SkMatrix* android_graphics_Matrix_getSkMatrix(JNIEnv* env, jobject matrixObj) { 396 return reinterpret_cast<SkMatrix*>(env->GetLongField(matrixObj, sNativeInstanceField)); 397 } 398 399 } 400