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