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 "jni.h" 19 #include "GraphicsJNI.h" 20 #include <android_runtime/AndroidRuntime.h> 21 22 #include "SkMatrix.h" 23 #include "SkTemplates.h" 24 25 #include "Matrix.h" 26 27 #include <Caches.h> 28 29 namespace android { 30 31 class SkMatrixGlue { 32 public: 33 34 static void finalizer(JNIEnv* env, jobject clazz, SkMatrix* obj) { 35 delete obj; 36 } 37 38 static SkMatrix* create(JNIEnv* env, jobject clazz, const SkMatrix* src) { 39 SkMatrix* obj = new SkMatrix(); 40 if (src) 41 *obj = *src; 42 else 43 obj->reset(); 44 return obj; 45 } 46 47 static jboolean isIdentity(JNIEnv* env, jobject clazz, SkMatrix* obj) { 48 return obj->isIdentity(); 49 } 50 51 static jboolean rectStaysRect(JNIEnv* env, jobject clazz, SkMatrix* obj) { 52 return obj->rectStaysRect(); 53 } 54 55 static void reset(JNIEnv* env, jobject clazz, SkMatrix* obj) { 56 obj->reset(); 57 } 58 59 static void set(JNIEnv* env, jobject clazz, SkMatrix* obj, SkMatrix* other) { 60 *obj = *other; 61 } 62 63 static void setTranslate(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat dx, jfloat dy) { 64 SkScalar dx_ = SkFloatToScalar(dx); 65 SkScalar dy_ = SkFloatToScalar(dy); 66 obj->setTranslate(dx_, dy_); 67 } 68 69 static void setScale__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sx, jfloat sy, jfloat px, jfloat py) { 70 SkScalar sx_ = SkFloatToScalar(sx); 71 SkScalar sy_ = SkFloatToScalar(sy); 72 SkScalar px_ = SkFloatToScalar(px); 73 SkScalar py_ = SkFloatToScalar(py); 74 obj->setScale(sx_, sy_, px_, py_); 75 } 76 77 static void setScale__FF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sx, jfloat sy) { 78 SkScalar sx_ = SkFloatToScalar(sx); 79 SkScalar sy_ = SkFloatToScalar(sy); 80 obj->setScale(sx_, sy_); 81 } 82 83 static void setRotate__FFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat degrees, jfloat px, jfloat py) { 84 SkScalar degrees_ = SkFloatToScalar(degrees); 85 SkScalar px_ = SkFloatToScalar(px); 86 SkScalar py_ = SkFloatToScalar(py); 87 obj->setRotate(degrees_, px_, py_); 88 } 89 90 static void setRotate__F(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat degrees) { 91 SkScalar degrees_ = SkFloatToScalar(degrees); 92 obj->setRotate(degrees_); 93 } 94 95 static void setSinCos__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sinValue, jfloat cosValue, jfloat px, jfloat py) { 96 SkScalar sinValue_ = SkFloatToScalar(sinValue); 97 SkScalar cosValue_ = SkFloatToScalar(cosValue); 98 SkScalar px_ = SkFloatToScalar(px); 99 SkScalar py_ = SkFloatToScalar(py); 100 obj->setSinCos(sinValue_, cosValue_, px_, py_); 101 } 102 103 static void setSinCos__FF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sinValue, jfloat cosValue) { 104 SkScalar sinValue_ = SkFloatToScalar(sinValue); 105 SkScalar cosValue_ = SkFloatToScalar(cosValue); 106 obj->setSinCos(sinValue_, cosValue_); 107 } 108 109 static void setSkew__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat kx, jfloat ky, jfloat px, jfloat py) { 110 SkScalar kx_ = SkFloatToScalar(kx); 111 SkScalar ky_ = SkFloatToScalar(ky); 112 SkScalar px_ = SkFloatToScalar(px); 113 SkScalar py_ = SkFloatToScalar(py); 114 obj->setSkew(kx_, ky_, px_, py_); 115 } 116 117 static void setSkew__FF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat kx, jfloat ky) { 118 SkScalar kx_ = SkFloatToScalar(kx); 119 SkScalar ky_ = SkFloatToScalar(ky); 120 obj->setSkew(kx_, ky_); 121 } 122 123 static jboolean setConcat(JNIEnv* env, jobject clazz, SkMatrix* obj, SkMatrix* a, SkMatrix* b) { 124 return obj->setConcat(*a, *b); 125 } 126 127 static jboolean preTranslate(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat dx, jfloat dy) { 128 SkScalar dx_ = SkFloatToScalar(dx); 129 SkScalar dy_ = SkFloatToScalar(dy); 130 return obj->preTranslate(dx_, dy_); 131 } 132 133 static jboolean preScale__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sx, jfloat sy, jfloat px, jfloat py) { 134 SkScalar sx_ = SkFloatToScalar(sx); 135 SkScalar sy_ = SkFloatToScalar(sy); 136 SkScalar px_ = SkFloatToScalar(px); 137 SkScalar py_ = SkFloatToScalar(py); 138 return obj->preScale(sx_, sy_, px_, py_); 139 } 140 141 static jboolean preScale__FF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sx, jfloat sy) { 142 SkScalar sx_ = SkFloatToScalar(sx); 143 SkScalar sy_ = SkFloatToScalar(sy); 144 return obj->preScale(sx_, sy_); 145 } 146 147 static jboolean preRotate__FFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat degrees, jfloat px, jfloat py) { 148 SkScalar degrees_ = SkFloatToScalar(degrees); 149 SkScalar px_ = SkFloatToScalar(px); 150 SkScalar py_ = SkFloatToScalar(py); 151 return obj->preRotate(degrees_, px_, py_); 152 } 153 154 static jboolean preRotate__F(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat degrees) { 155 SkScalar degrees_ = SkFloatToScalar(degrees); 156 return obj->preRotate(degrees_); 157 } 158 159 static jboolean preSkew__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat kx, jfloat ky, jfloat px, jfloat py) { 160 SkScalar kx_ = SkFloatToScalar(kx); 161 SkScalar ky_ = SkFloatToScalar(ky); 162 SkScalar px_ = SkFloatToScalar(px); 163 SkScalar py_ = SkFloatToScalar(py); 164 return obj->preSkew(kx_, ky_, px_, py_); 165 } 166 167 static jboolean preSkew__FF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat kx, jfloat ky) { 168 SkScalar kx_ = SkFloatToScalar(kx); 169 SkScalar ky_ = SkFloatToScalar(ky); 170 return obj->preSkew(kx_, ky_); 171 } 172 173 static jboolean preConcat(JNIEnv* env, jobject clazz, SkMatrix* obj, SkMatrix* other) { 174 return obj->preConcat(*other); 175 } 176 177 static jboolean postTranslate(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat dx, jfloat dy) { 178 SkScalar dx_ = SkFloatToScalar(dx); 179 SkScalar dy_ = SkFloatToScalar(dy); 180 return obj->postTranslate(dx_, dy_); 181 } 182 183 static jboolean postScale__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sx, jfloat sy, jfloat px, jfloat py) { 184 SkScalar sx_ = SkFloatToScalar(sx); 185 SkScalar sy_ = SkFloatToScalar(sy); 186 SkScalar px_ = SkFloatToScalar(px); 187 SkScalar py_ = SkFloatToScalar(py); 188 return obj->postScale(sx_, sy_, px_, py_); 189 } 190 191 static jboolean postScale__FF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat sx, jfloat sy) { 192 SkScalar sx_ = SkFloatToScalar(sx); 193 SkScalar sy_ = SkFloatToScalar(sy); 194 return obj->postScale(sx_, sy_); 195 } 196 197 static jboolean postRotate__FFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat degrees, jfloat px, jfloat py) { 198 SkScalar degrees_ = SkFloatToScalar(degrees); 199 SkScalar px_ = SkFloatToScalar(px); 200 SkScalar py_ = SkFloatToScalar(py); 201 return obj->postRotate(degrees_, px_, py_); 202 } 203 204 static jboolean postRotate__F(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat degrees) { 205 SkScalar degrees_ = SkFloatToScalar(degrees); 206 return obj->postRotate(degrees_); 207 } 208 209 static jboolean postSkew__FFFF(JNIEnv* env, jobject clazz, SkMatrix* obj, jfloat kx, jfloat ky, jfloat px, jfloat py) { 210 SkScalar kx_ = SkFloatToScalar(kx); 211 SkScalar ky_ = SkFloatToScalar(ky); 212 SkScalar px_ = SkFloatToScalar(px); 213 SkScalar py_ = SkFloatToScalar(py); 214 return obj->postSkew(kx_, ky_, px_, py_); 215 } 216 217 static jboolean postSkew__FF(JNIEnv* env, jobject clazz, SkMatrix* matrix, jfloat kx, jfloat ky) { 218 SkScalar kx_ = SkFloatToScalar(kx); 219 SkScalar ky_ = SkFloatToScalar(ky); 220 return matrix->postSkew(kx_, ky_); 221 } 222 223 static jboolean postConcat(JNIEnv* env, jobject clazz, SkMatrix* matrix, SkMatrix* other) { 224 return matrix->postConcat(*other); 225 } 226 227 static jboolean setRectToRect(JNIEnv* env, jobject clazz, SkMatrix* matrix, jobject src, jobject dst, SkMatrix::ScaleToFit stf) { 228 SkRect src_; 229 GraphicsJNI::jrectf_to_rect(env, src, &src_); 230 SkRect dst_; 231 GraphicsJNI::jrectf_to_rect(env, dst, &dst_); 232 return matrix->setRectToRect(src_, dst_, stf); 233 } 234 235 static jboolean setPolyToPoly(JNIEnv* env, jobject clazz, SkMatrix* matrix, 236 jfloatArray jsrc, int srcIndex, 237 jfloatArray jdst, int dstIndex, int ptCount) { 238 SkASSERT(srcIndex >= 0); 239 SkASSERT(dstIndex >= 0); 240 SkASSERT((unsigned)ptCount <= 4); 241 242 AutoJavaFloatArray autoSrc(env, jsrc, srcIndex + (ptCount << 1)); 243 AutoJavaFloatArray autoDst(env, jdst, dstIndex + (ptCount << 1)); 244 float* src = autoSrc.ptr() + srcIndex; 245 float* dst = autoDst.ptr() + dstIndex; 246 247 #ifdef SK_SCALAR_IS_FIXED 248 SkPoint srcPt[4], dstPt[4]; 249 for (int i = 0; i < ptCount; i++) { 250 int x = i << 1; 251 int y = x + 1; 252 srcPt[i].set(SkFloatToScalar(src[x]), SkFloatToScalar(src[y])); 253 dstPt[i].set(SkFloatToScalar(dst[x]), SkFloatToScalar(dst[y])); 254 } 255 return matrix->setPolyToPoly(srcPt, dstPt, ptCount); 256 #else 257 return matrix->setPolyToPoly((const SkPoint*)src, (const SkPoint*)dst, 258 ptCount); 259 #endif 260 } 261 262 static jboolean invert(JNIEnv* env, jobject clazz, SkMatrix* matrix, SkMatrix* inverse) { 263 return matrix->invert(inverse); 264 } 265 266 static void mapPoints(JNIEnv* env, jobject clazz, SkMatrix* matrix, 267 jfloatArray dst, int dstIndex, 268 jfloatArray src, int srcIndex, 269 int ptCount, bool isPts) { 270 SkASSERT(ptCount >= 0); 271 AutoJavaFloatArray autoSrc(env, src, srcIndex + (ptCount << 1)); 272 AutoJavaFloatArray autoDst(env, dst, dstIndex + (ptCount << 1)); 273 float* srcArray = autoSrc.ptr() + srcIndex; 274 float* dstArray = autoDst.ptr() + dstIndex; 275 276 #ifdef SK_SCALAR_IS_FIXED 277 // we allocate twice the count, 1 set for src, 1 for dst 278 SkAutoSTMalloc<32, SkPoint> storage(ptCount * 2); 279 SkPoint* pts = storage.get(); 280 SkPoint* srcPt = pts; 281 SkPoint* dstPt = pts + ptCount; 282 283 int i; 284 for (i = 0; i < ptCount; i++) { 285 srcPt[i].set(SkFloatToScalar(srcArray[i << 1]), 286 SkFloatToScalar(srcArray[(i << 1) + 1])); 287 } 288 289 if (isPts) 290 matrix->mapPoints(dstPt, srcPt, ptCount); 291 else 292 matrix->mapVectors(dstPt, srcPt, ptCount); 293 294 for (i = 0; i < ptCount; i++) { 295 dstArray[i << 1] = SkScalarToFloat(dstPt[i].fX); 296 dstArray[(i << 1) + 1] = SkScalarToFloat(dstPt[i].fY); 297 } 298 #else 299 if (isPts) 300 matrix->mapPoints((SkPoint*)dstArray, (const SkPoint*)srcArray, 301 ptCount); 302 else 303 matrix->mapVectors((SkVector*)dstArray, (const SkVector*)srcArray, 304 ptCount); 305 #endif 306 } 307 308 static jboolean mapRect__RectFRectF(JNIEnv* env, jobject clazz, SkMatrix* matrix, jobjectArray dst, jobject src) { 309 SkRect dst_, src_; 310 GraphicsJNI::jrectf_to_rect(env, src, &src_); 311 jboolean rectStaysRect = matrix->mapRect(&dst_, src_); 312 GraphicsJNI::rect_to_jrectf(dst_, env, dst); 313 return rectStaysRect; 314 } 315 316 static jfloat mapRadius(JNIEnv* env, jobject clazz, SkMatrix* matrix, jfloat radius) { 317 return SkScalarToFloat(matrix->mapRadius(SkFloatToScalar(radius))); 318 } 319 320 static void getValues(JNIEnv* env, jobject clazz, SkMatrix* matrix, jfloatArray values) { 321 AutoJavaFloatArray autoValues(env, values, 9); 322 float* dst = autoValues.ptr(); 323 324 #ifdef SK_SCALAR_IS_FIXED 325 for (int i = 0; i < 6; i++) { 326 dst[i] = SkFixedToFloat(matrix->get(i)); 327 } 328 for (int j = 6; j < 9; j++) { 329 dst[j] = SkFractToFloat(matrix->get(j)); 330 } 331 #else 332 for (int i = 0; i < 9; i++) { 333 dst[i] = matrix->get(i); 334 } 335 #endif 336 } 337 338 static void setValues(JNIEnv* env, jobject clazz, SkMatrix* matrix, jfloatArray values) { 339 AutoJavaFloatArray autoValues(env, values, 9); 340 const float* src = autoValues.ptr(); 341 342 #ifdef SK_SCALAR_IS_FIXED 343 for (int i = 0; i < 6; i++) { 344 matrix->set(i, SkFloatToFixed(src[i])); 345 } 346 for (int j = 6; j < 9; j++) { 347 matrix->set(j, SkFloatToFract(src[j])); 348 } 349 #else 350 for (int i = 0; i < 9; i++) { 351 matrix->set(i, src[i]); 352 } 353 #endif 354 } 355 356 static jboolean equals(JNIEnv* env, jobject clazz, const SkMatrix* a, const SkMatrix* b) { 357 return *a == *b; 358 } 359 }; 360 361 static JNINativeMethod methods[] = { 362 {"finalizer", "(I)V", (void*) SkMatrixGlue::finalizer}, 363 {"native_create","(I)I", (void*) SkMatrixGlue::create}, 364 {"native_isIdentity","(I)Z", (void*) SkMatrixGlue::isIdentity}, 365 {"native_rectStaysRect","(I)Z", (void*) SkMatrixGlue::rectStaysRect}, 366 {"native_reset","(I)V", (void*) SkMatrixGlue::reset}, 367 {"native_set","(II)V", (void*) SkMatrixGlue::set}, 368 {"native_setTranslate","(IFF)V", (void*) SkMatrixGlue::setTranslate}, 369 {"native_setScale","(IFFFF)V", (void*) SkMatrixGlue::setScale__FFFF}, 370 {"native_setScale","(IFF)V", (void*) SkMatrixGlue::setScale__FF}, 371 {"native_setRotate","(IFFF)V", (void*) SkMatrixGlue::setRotate__FFF}, 372 {"native_setRotate","(IF)V", (void*) SkMatrixGlue::setRotate__F}, 373 {"native_setSinCos","(IFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF}, 374 {"native_setSinCos","(IFF)V", (void*) SkMatrixGlue::setSinCos__FF}, 375 {"native_setSkew","(IFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF}, 376 {"native_setSkew","(IFF)V", (void*) SkMatrixGlue::setSkew__FF}, 377 {"native_setConcat","(III)Z", (void*) SkMatrixGlue::setConcat}, 378 {"native_preTranslate","(IFF)Z", (void*) SkMatrixGlue::preTranslate}, 379 {"native_preScale","(IFFFF)Z", (void*) SkMatrixGlue::preScale__FFFF}, 380 {"native_preScale","(IFF)Z", (void*) SkMatrixGlue::preScale__FF}, 381 {"native_preRotate","(IFFF)Z", (void*) SkMatrixGlue::preRotate__FFF}, 382 {"native_preRotate","(IF)Z", (void*) SkMatrixGlue::preRotate__F}, 383 {"native_preSkew","(IFFFF)Z", (void*) SkMatrixGlue::preSkew__FFFF}, 384 {"native_preSkew","(IFF)Z", (void*) SkMatrixGlue::preSkew__FF}, 385 {"native_preConcat","(II)Z", (void*) SkMatrixGlue::preConcat}, 386 {"native_postTranslate","(IFF)Z", (void*) SkMatrixGlue::postTranslate}, 387 {"native_postScale","(IFFFF)Z", (void*) SkMatrixGlue::postScale__FFFF}, 388 {"native_postScale","(IFF)Z", (void*) SkMatrixGlue::postScale__FF}, 389 {"native_postRotate","(IFFF)Z", (void*) SkMatrixGlue::postRotate__FFF}, 390 {"native_postRotate","(IF)Z", (void*) SkMatrixGlue::postRotate__F}, 391 {"native_postSkew","(IFFFF)Z", (void*) SkMatrixGlue::postSkew__FFFF}, 392 {"native_postSkew","(IFF)Z", (void*) SkMatrixGlue::postSkew__FF}, 393 {"native_postConcat","(II)Z", (void*) SkMatrixGlue::postConcat}, 394 {"native_setRectToRect","(ILandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect}, 395 {"native_setPolyToPoly","(I[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly}, 396 {"native_invert","(II)Z", (void*) SkMatrixGlue::invert}, 397 {"native_mapPoints","(I[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints}, 398 {"native_mapRect","(ILandroid/graphics/RectF;Landroid/graphics/RectF;)Z", (void*) SkMatrixGlue::mapRect__RectFRectF}, 399 {"native_mapRadius","(IF)F", (void*) SkMatrixGlue::mapRadius}, 400 {"native_getValues","(I[F)V", (void*) SkMatrixGlue::getValues}, 401 {"native_setValues","(I[F)V", (void*) SkMatrixGlue::setValues}, 402 {"native_equals", "(II)Z", (void*) SkMatrixGlue::equals} 403 }; 404 405 static jfieldID sNativeInstanceField; 406 407 int register_android_graphics_Matrix(JNIEnv* env) { 408 int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Matrix", methods, 409 sizeof(methods) / sizeof(methods[0])); 410 411 jclass clazz = env->FindClass("android/graphics/Matrix"); 412 sNativeInstanceField = env->GetFieldID(clazz, "native_instance", "I"); 413 414 return result; 415 } 416 417 SkMatrix* android_graphics_Matrix_getSkMatrix(JNIEnv* env, jobject matrixObj) { 418 return reinterpret_cast<SkMatrix*>(env->GetIntField(matrixObj, sNativeInstanceField)); 419 } 420 421 } 422