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