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