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