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
finalizer(jlong objHandle)37 static void finalizer(jlong objHandle) {
38 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
39 delete obj;
40 }
41
getNativeFinalizer(JNIEnv * env,jobject clazz)42 static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
43 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&finalizer));
44 }
45
create(JNIEnv * env,jobject clazz,jlong srcHandle)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
mapPoints(JNIEnv * env,jobject clazz,jlong matrixHandle,jfloatArray dst,jint dstIndex,jfloatArray src,jint srcIndex,jint ptCount,jboolean isPts)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
mapRect__RectFRectF(JNIEnv * env,jobject clazz,jlong matrixHandle,jobjectArray dst,jobject src)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
setRectToRect(JNIEnv * env,jobject clazz,jlong matrixHandle,jobject src,jobject dst,jint stfHandle)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
setPolyToPoly(JNIEnv * env,jobject clazz,jlong matrixHandle,jfloatArray jsrc,jint srcIndex,jfloatArray jdst,jint dstIndex,jint ptCount)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
getValues(JNIEnv * env,jobject clazz,jlong matrixHandle,jfloatArray values)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
setValues(JNIEnv * env,jobject clazz,jlong matrixHandle,jfloatArray values)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
isIdentity(jlong objHandle)142 static jboolean isIdentity(jlong objHandle) {
143 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
144 return obj->isIdentity() ? JNI_TRUE : JNI_FALSE;
145 }
146
isAffine(jlong objHandle)147 static jboolean isAffine(jlong objHandle) {
148 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
149 return obj->asAffine(NULL) ? JNI_TRUE : JNI_FALSE;
150 }
151
rectStaysRect(jlong objHandle)152 static jboolean rectStaysRect(jlong objHandle) {
153 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
154 return obj->rectStaysRect() ? JNI_TRUE : JNI_FALSE;
155 }
156
reset(jlong objHandle)157 static void reset(jlong objHandle) {
158 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
159 obj->reset();
160 }
161
set(jlong objHandle,jlong otherHandle)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
setTranslate(jlong objHandle,jfloat dx,jfloat dy)168 static void setTranslate(jlong objHandle, jfloat dx, jfloat dy) {
169 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
170 obj->setTranslate(dx, dy);
171 }
172
setScale__FFFF(jlong objHandle,jfloat sx,jfloat sy,jfloat px,jfloat py)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
setScale__FF(jlong objHandle,jfloat sx,jfloat sy)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
setRotate__FFF(jlong objHandle,jfloat degrees,jfloat px,jfloat py)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
setRotate__F(jlong objHandle,jfloat degrees)190 static void setRotate__F(jlong objHandle, jfloat degrees) {
191 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
192 obj->setRotate(degrees);
193 }
194
setSinCos__FFFF(jlong objHandle,jfloat sinValue,jfloat cosValue,jfloat px,jfloat py)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
setSinCos__FF(jlong objHandle,jfloat sinValue,jfloat cosValue)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
setSkew__FFFF(jlong objHandle,jfloat kx,jfloat ky,jfloat px,jfloat py)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
setSkew__FF(jlong objHandle,jfloat kx,jfloat ky)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
setConcat(jlong objHandle,jlong aHandle,jlong bHandle)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
preTranslate(jlong objHandle,jfloat dx,jfloat dy)225 static void preTranslate(jlong objHandle, jfloat dx, jfloat dy) {
226 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
227 obj->preTranslate(dx, dy);
228 }
229
preScale__FFFF(jlong objHandle,jfloat sx,jfloat sy,jfloat px,jfloat py)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
preScale__FF(jlong objHandle,jfloat sx,jfloat sy)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
preRotate__FFF(jlong objHandle,jfloat degrees,jfloat px,jfloat py)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
preRotate__F(jlong objHandle,jfloat degrees)247 static void preRotate__F(jlong objHandle, jfloat degrees) {
248 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
249 obj->preRotate(degrees);
250 }
251
preSkew__FFFF(jlong objHandle,jfloat kx,jfloat ky,jfloat px,jfloat py)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
preSkew__FF(jlong objHandle,jfloat kx,jfloat ky)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
preConcat(jlong objHandle,jlong otherHandle)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
postTranslate(jlong objHandle,jfloat dx,jfloat dy)269 static void postTranslate(jlong objHandle, jfloat dx, jfloat dy) {
270 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
271 obj->postTranslate(dx, dy);
272 }
273
postScale__FFFF(jlong objHandle,jfloat sx,jfloat sy,jfloat px,jfloat py)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
postScale__FF(jlong objHandle,jfloat sx,jfloat sy)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
postRotate__FFF(jlong objHandle,jfloat degrees,jfloat px,jfloat py)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
postRotate__F(jlong objHandle,jfloat degrees)291 static void postRotate__F(jlong objHandle, jfloat degrees) {
292 SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
293 obj->postRotate(degrees);
294 }
295
postSkew__FFFF(jlong objHandle,jfloat kx,jfloat ky,jfloat px,jfloat py)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
postSkew__FF(jlong matrixHandle,jfloat kx,jfloat ky)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
postConcat(jlong matrixHandle,jlong otherHandle)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
invert(jlong matrixHandle,jlong inverseHandle)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
mapRadius(jlong matrixHandle,jfloat radius)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
equals(jlong aHandle,jlong bHandle)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
register_android_graphics_Matrix(JNIEnv * env)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
android_graphics_Matrix_getSkMatrix(JNIEnv * env,jobject matrixObj)395 SkMatrix* android_graphics_Matrix_getSkMatrix(JNIEnv* env, jobject matrixObj) {
396 return reinterpret_cast<SkMatrix*>(env->GetLongField(matrixObj, sNativeInstanceField));
397 }
398
399 }
400