• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import dalvik.annotation.optimization.CriticalNative;
20 import dalvik.annotation.optimization.FastNative;
21 
22 import libcore.util.NativeAllocationRegistry;
23 
24 import java.io.PrintWriter;
25 
26 /**
27  * The Matrix class holds a 3x3 matrix for transforming coordinates.
28  */
29 public class Matrix {
30 
31     public static final int MSCALE_X = 0;   //!< use with getValues/setValues
32     public static final int MSKEW_X  = 1;   //!< use with getValues/setValues
33     public static final int MTRANS_X = 2;   //!< use with getValues/setValues
34     public static final int MSKEW_Y  = 3;   //!< use with getValues/setValues
35     public static final int MSCALE_Y = 4;   //!< use with getValues/setValues
36     public static final int MTRANS_Y = 5;   //!< use with getValues/setValues
37     public static final int MPERSP_0 = 6;   //!< use with getValues/setValues
38     public static final int MPERSP_1 = 7;   //!< use with getValues/setValues
39     public static final int MPERSP_2 = 8;   //!< use with getValues/setValues
40 
41     /** @hide */
42     public final static Matrix IDENTITY_MATRIX = new Matrix() {
43         void oops() {
44             throw new IllegalStateException("Matrix can not be modified");
45         }
46 
47         @Override
48         public void set(Matrix src) {
49             oops();
50         }
51 
52         @Override
53         public void reset() {
54             oops();
55         }
56 
57         @Override
58         public void setTranslate(float dx, float dy) {
59             oops();
60         }
61 
62         @Override
63         public void setScale(float sx, float sy, float px, float py) {
64             oops();
65         }
66 
67         @Override
68         public void setScale(float sx, float sy) {
69             oops();
70         }
71 
72         @Override
73         public void setRotate(float degrees, float px, float py) {
74             oops();
75         }
76 
77         @Override
78         public void setRotate(float degrees) {
79             oops();
80         }
81 
82         @Override
83         public void setSinCos(float sinValue, float cosValue, float px, float py) {
84             oops();
85         }
86 
87         @Override
88         public void setSinCos(float sinValue, float cosValue) {
89             oops();
90         }
91 
92         @Override
93         public void setSkew(float kx, float ky, float px, float py) {
94             oops();
95         }
96 
97         @Override
98         public void setSkew(float kx, float ky) {
99             oops();
100         }
101 
102         @Override
103         public boolean setConcat(Matrix a, Matrix b) {
104             oops();
105             return false;
106         }
107 
108         @Override
109         public boolean preTranslate(float dx, float dy) {
110             oops();
111             return false;
112         }
113 
114         @Override
115         public boolean preScale(float sx, float sy, float px, float py) {
116             oops();
117             return false;
118         }
119 
120         @Override
121         public boolean preScale(float sx, float sy) {
122             oops();
123             return false;
124         }
125 
126         @Override
127         public boolean preRotate(float degrees, float px, float py) {
128             oops();
129             return false;
130         }
131 
132         @Override
133         public boolean preRotate(float degrees) {
134             oops();
135             return false;
136         }
137 
138         @Override
139         public boolean preSkew(float kx, float ky, float px, float py) {
140             oops();
141             return false;
142         }
143 
144         @Override
145         public boolean preSkew(float kx, float ky) {
146             oops();
147             return false;
148         }
149 
150         @Override
151         public boolean preConcat(Matrix other) {
152             oops();
153             return false;
154         }
155 
156         @Override
157         public boolean postTranslate(float dx, float dy) {
158             oops();
159             return false;
160         }
161 
162         @Override
163         public boolean postScale(float sx, float sy, float px, float py) {
164             oops();
165             return false;
166         }
167 
168         @Override
169         public boolean postScale(float sx, float sy) {
170             oops();
171             return false;
172         }
173 
174         @Override
175         public boolean postRotate(float degrees, float px, float py) {
176             oops();
177             return false;
178         }
179 
180         @Override
181         public boolean postRotate(float degrees) {
182             oops();
183             return false;
184         }
185 
186         @Override
187         public boolean postSkew(float kx, float ky, float px, float py) {
188             oops();
189             return false;
190         }
191 
192         @Override
193         public boolean postSkew(float kx, float ky) {
194             oops();
195             return false;
196         }
197 
198         @Override
199         public boolean postConcat(Matrix other) {
200             oops();
201             return false;
202         }
203 
204         @Override
205         public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf) {
206             oops();
207             return false;
208         }
209 
210         @Override
211         public boolean setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex,
212                 int pointCount) {
213             oops();
214             return false;
215         }
216 
217         @Override
218         public void setValues(float[] values) {
219             oops();
220         }
221     };
222 
223     // sizeof(SkMatrix) is 9 * sizeof(float) + uint32_t
224     private static final long NATIVE_ALLOCATION_SIZE = 40;
225 
226     private static class NoImagePreloadHolder {
227         public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
228                 Matrix.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
229     }
230 
231     /**
232      * @hide
233      */
234     public final long native_instance;
235 
236     /**
237      * Create an identity matrix
238      */
Matrix()239     public Matrix() {
240         native_instance = nCreate(0);
241         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
242     }
243 
244     /**
245      * Create a matrix that is a (deep) copy of src
246      *
247      * @param src The matrix to copy into this matrix
248      */
Matrix(Matrix src)249     public Matrix(Matrix src) {
250         native_instance = nCreate(src != null ? src.native_instance : 0);
251         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
252     }
253 
254     /**
255      * Returns true if the matrix is identity. This maybe faster than testing if (getType() == 0)
256      */
isIdentity()257     public boolean isIdentity() {
258         return nIsIdentity(native_instance);
259     }
260 
261     /**
262      * Gets whether this matrix is affine. An affine matrix preserves straight lines and has no
263      * perspective.
264      *
265      * @return Whether the matrix is affine.
266      */
isAffine()267     public boolean isAffine() {
268         return nIsAffine(native_instance);
269     }
270 
271     /**
272      * Returns true if will map a rectangle to another rectangle. This can be true if the matrix is
273      * identity, scale-only, or rotates a multiple of 90 degrees.
274      */
rectStaysRect()275     public boolean rectStaysRect() {
276         return nRectStaysRect(native_instance);
277     }
278 
279     /**
280      * (deep) copy the src matrix into this matrix. If src is null, reset this matrix to the
281      * identity matrix.
282      */
set(Matrix src)283     public void set(Matrix src) {
284         if (src == null) {
285             reset();
286         } else {
287             nSet(native_instance, src.native_instance);
288         }
289     }
290 
291     /**
292      * Returns true iff obj is a Matrix and its values equal our values.
293      */
294     @Override
equals(Object obj)295     public boolean equals(Object obj) {
296         // if (obj == this) return true; -- NaN value would mean matrix != itself
297         if (!(obj instanceof Matrix)) {
298             return false;
299         }
300         return nEquals(native_instance, ((Matrix) obj).native_instance);
301     }
302 
303     @Override
hashCode()304     public int hashCode() {
305         // This should generate the hash code by performing some arithmetic operation on all
306         // the matrix elements -- our equals() does an element-by-element comparison, and we
307         // need to ensure that the hash code for two equal objects is the same. We're not
308         // really using this at the moment, so we take the easy way out.
309         return 44;
310     }
311 
312     /** Set the matrix to identity */
reset()313     public void reset() {
314         nReset(native_instance);
315     }
316 
317     /** Set the matrix to translate by (dx, dy). */
setTranslate(float dx, float dy)318     public void setTranslate(float dx, float dy) {
319         nSetTranslate(native_instance, dx, dy);
320     }
321 
322     /**
323      * Set the matrix to scale by sx and sy, with a pivot point at (px, py). The pivot point is the
324      * coordinate that should remain unchanged by the specified transformation.
325      */
setScale(float sx, float sy, float px, float py)326     public void setScale(float sx, float sy, float px, float py) {
327         nSetScale(native_instance, sx, sy, px, py);
328     }
329 
330     /** Set the matrix to scale by sx and sy. */
setScale(float sx, float sy)331     public void setScale(float sx, float sy) {
332         nSetScale(native_instance, sx, sy);
333     }
334 
335     /**
336      * Set the matrix to rotate by the specified number of degrees, with a pivot point at (px, py).
337      * The pivot point is the coordinate that should remain unchanged by the specified
338      * transformation.
339      */
setRotate(float degrees, float px, float py)340     public void setRotate(float degrees, float px, float py) {
341         nSetRotate(native_instance, degrees, px, py);
342     }
343 
344     /**
345      * Set the matrix to rotate about (0,0) by the specified number of degrees.
346      */
setRotate(float degrees)347     public void setRotate(float degrees) {
348         nSetRotate(native_instance, degrees);
349     }
350 
351     /**
352      * Set the matrix to rotate by the specified sine and cosine values, with a pivot point at (px,
353      * py). The pivot point is the coordinate that should remain unchanged by the specified
354      * transformation.
355      */
setSinCos(float sinValue, float cosValue, float px, float py)356     public void setSinCos(float sinValue, float cosValue, float px, float py) {
357         nSetSinCos(native_instance, sinValue, cosValue, px, py);
358     }
359 
360     /** Set the matrix to rotate by the specified sine and cosine values. */
setSinCos(float sinValue, float cosValue)361     public void setSinCos(float sinValue, float cosValue) {
362         nSetSinCos(native_instance, sinValue, cosValue);
363     }
364 
365     /**
366      * Set the matrix to skew by sx and sy, with a pivot point at (px, py). The pivot point is the
367      * coordinate that should remain unchanged by the specified transformation.
368      */
setSkew(float kx, float ky, float px, float py)369     public void setSkew(float kx, float ky, float px, float py) {
370         nSetSkew(native_instance, kx, ky, px, py);
371     }
372 
373     /** Set the matrix to skew by sx and sy. */
setSkew(float kx, float ky)374     public void setSkew(float kx, float ky) {
375         nSetSkew(native_instance, kx, ky);
376     }
377 
378     /**
379      * Set the matrix to the concatenation of the two specified matrices and return true.
380      * <p>
381      * Either of the two matrices may also be the target matrix, that is
382      * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid.
383      * </p>
384      * <p class="note">
385      * In {@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1} and below, this function returns
386      * true only if the result can be represented. In
387      * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and above, it always returns true.
388      * </p>
389      */
setConcat(Matrix a, Matrix b)390     public boolean setConcat(Matrix a, Matrix b) {
391         nSetConcat(native_instance, a.native_instance, b.native_instance);
392         return true;
393     }
394 
395     /**
396      * Preconcats the matrix with the specified translation. M' = M * T(dx, dy)
397      */
preTranslate(float dx, float dy)398     public boolean preTranslate(float dx, float dy) {
399         nPreTranslate(native_instance, dx, dy);
400         return true;
401     }
402 
403     /**
404      * Preconcats the matrix with the specified scale. M' = M * S(sx, sy, px, py)
405      */
preScale(float sx, float sy, float px, float py)406     public boolean preScale(float sx, float sy, float px, float py) {
407         nPreScale(native_instance, sx, sy, px, py);
408         return true;
409     }
410 
411     /**
412      * Preconcats the matrix with the specified scale. M' = M * S(sx, sy)
413      */
preScale(float sx, float sy)414     public boolean preScale(float sx, float sy) {
415         nPreScale(native_instance, sx, sy);
416         return true;
417     }
418 
419     /**
420      * Preconcats the matrix with the specified rotation. M' = M * R(degrees, px, py)
421      */
preRotate(float degrees, float px, float py)422     public boolean preRotate(float degrees, float px, float py) {
423         nPreRotate(native_instance, degrees, px, py);
424         return true;
425     }
426 
427     /**
428      * Preconcats the matrix with the specified rotation. M' = M * R(degrees)
429      */
preRotate(float degrees)430     public boolean preRotate(float degrees) {
431         nPreRotate(native_instance, degrees);
432         return true;
433     }
434 
435     /**
436      * Preconcats the matrix with the specified skew. M' = M * K(kx, ky, px, py)
437      */
preSkew(float kx, float ky, float px, float py)438     public boolean preSkew(float kx, float ky, float px, float py) {
439         nPreSkew(native_instance, kx, ky, px, py);
440         return true;
441     }
442 
443     /**
444      * Preconcats the matrix with the specified skew. M' = M * K(kx, ky)
445      */
preSkew(float kx, float ky)446     public boolean preSkew(float kx, float ky) {
447         nPreSkew(native_instance, kx, ky);
448         return true;
449     }
450 
451     /**
452      * Preconcats the matrix with the specified matrix. M' = M * other
453      */
preConcat(Matrix other)454     public boolean preConcat(Matrix other) {
455         nPreConcat(native_instance, other.native_instance);
456         return true;
457     }
458 
459     /**
460      * Postconcats the matrix with the specified translation. M' = T(dx, dy) * M
461      */
postTranslate(float dx, float dy)462     public boolean postTranslate(float dx, float dy) {
463         nPostTranslate(native_instance, dx, dy);
464         return true;
465     }
466 
467     /**
468      * Postconcats the matrix with the specified scale. M' = S(sx, sy, px, py) * M
469      */
postScale(float sx, float sy, float px, float py)470     public boolean postScale(float sx, float sy, float px, float py) {
471         nPostScale(native_instance, sx, sy, px, py);
472         return true;
473     }
474 
475     /**
476      * Postconcats the matrix with the specified scale. M' = S(sx, sy) * M
477      */
postScale(float sx, float sy)478     public boolean postScale(float sx, float sy) {
479         nPostScale(native_instance, sx, sy);
480         return true;
481     }
482 
483     /**
484      * Postconcats the matrix with the specified rotation. M' = R(degrees, px, py) * M
485      */
postRotate(float degrees, float px, float py)486     public boolean postRotate(float degrees, float px, float py) {
487         nPostRotate(native_instance, degrees, px, py);
488         return true;
489     }
490 
491     /**
492      * Postconcats the matrix with the specified rotation. M' = R(degrees) * M
493      */
postRotate(float degrees)494     public boolean postRotate(float degrees) {
495         nPostRotate(native_instance, degrees);
496         return true;
497     }
498 
499     /**
500      * Postconcats the matrix with the specified skew. M' = K(kx, ky, px, py) * M
501      */
postSkew(float kx, float ky, float px, float py)502     public boolean postSkew(float kx, float ky, float px, float py) {
503         nPostSkew(native_instance, kx, ky, px, py);
504         return true;
505     }
506 
507     /**
508      * Postconcats the matrix with the specified skew. M' = K(kx, ky) * M
509      */
postSkew(float kx, float ky)510     public boolean postSkew(float kx, float ky) {
511         nPostSkew(native_instance, kx, ky);
512         return true;
513     }
514 
515     /**
516      * Postconcats the matrix with the specified matrix. M' = other * M
517      */
postConcat(Matrix other)518     public boolean postConcat(Matrix other) {
519         nPostConcat(native_instance, other.native_instance);
520         return true;
521     }
522 
523     /**
524      * Controlls how the src rect should align into the dst rect for setRectToRect().
525      */
526     public enum ScaleToFit {
527         /**
528          * Scale in X and Y independently, so that src matches dst exactly. This may change the
529          * aspect ratio of the src.
530          */
531         FILL(0),
532         /**
533          * Compute a scale that will maintain the original src aspect ratio, but will also ensure
534          * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. START
535          * aligns the result to the left and top edges of dst.
536          */
537         START(1),
538         /**
539          * Compute a scale that will maintain the original src aspect ratio, but will also ensure
540          * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. The
541          * result is centered inside dst.
542          */
543         CENTER(2),
544         /**
545          * Compute a scale that will maintain the original src aspect ratio, but will also ensure
546          * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. END
547          * aligns the result to the right and bottom edges of dst.
548          */
549         END(3);
550 
551         // the native values must match those in SkMatrix.h
ScaleToFit(int nativeInt)552         ScaleToFit(int nativeInt) {
553             this.nativeInt = nativeInt;
554         }
555 
556         final int nativeInt;
557     }
558 
559     /**
560      * Set the matrix to the scale and translate values that map the source rectangle to the
561      * destination rectangle, returning true if the the result can be represented.
562      *
563      * @param src the source rectangle to map from.
564      * @param dst the destination rectangle to map to.
565      * @param stf the ScaleToFit option
566      * @return true if the matrix can be represented by the rectangle mapping.
567      */
setRectToRect(RectF src, RectF dst, ScaleToFit stf)568     public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf) {
569         if (dst == null || src == null) {
570             throw new NullPointerException();
571         }
572         return nSetRectToRect(native_instance, src, dst, stf.nativeInt);
573     }
574 
575     // private helper to perform range checks on arrays of "points"
checkPointArrays(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)576     private static void checkPointArrays(float[] src, int srcIndex,
577             float[] dst, int dstIndex,
578             int pointCount) {
579         // check for too-small and too-big indices
580         int srcStop = srcIndex + (pointCount << 1);
581         int dstStop = dstIndex + (pointCount << 1);
582         if ((pointCount | srcIndex | dstIndex | srcStop | dstStop) < 0 ||
583                 srcStop > src.length || dstStop > dst.length) {
584             throw new ArrayIndexOutOfBoundsException();
585         }
586     }
587 
588     /**
589      * Set the matrix such that the specified src points would map to the specified dst points. The
590      * "points" are represented as an array of floats, order [x0, y0, x1, y1, ...], where each
591      * "point" is 2 float values.
592      *
593      * @param src The array of src [x,y] pairs (points)
594      * @param srcIndex Index of the first pair of src values
595      * @param dst The array of dst [x,y] pairs (points)
596      * @param dstIndex Index of the first pair of dst values
597      * @param pointCount The number of pairs/points to be used. Must be [0..4]
598      * @return true if the matrix was set to the specified transformation
599      */
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)600     public boolean setPolyToPoly(float[] src, int srcIndex,
601             float[] dst, int dstIndex,
602             int pointCount) {
603         if (pointCount > 4) {
604             throw new IllegalArgumentException();
605         }
606         checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
607         return nSetPolyToPoly(native_instance, src, srcIndex,
608                 dst, dstIndex, pointCount);
609     }
610 
611     /**
612      * If this matrix can be inverted, return true and if inverse is not null, set inverse to be the
613      * inverse of this matrix. If this matrix cannot be inverted, ignore inverse and return false.
614      */
invert(Matrix inverse)615     public boolean invert(Matrix inverse) {
616         return nInvert(native_instance, inverse.native_instance);
617     }
618 
619     /**
620      * Apply this matrix to the array of 2D points specified by src, and write the transformed
621      * points into the array of points specified by dst. The two arrays represent their "points" as
622      * pairs of floats [x, y].
623      *
624      * @param dst The array of dst points (x,y pairs)
625      * @param dstIndex The index of the first [x,y] pair of dst floats
626      * @param src The array of src points (x,y pairs)
627      * @param srcIndex The index of the first [x,y] pair of src floats
628      * @param pointCount The number of points (x,y pairs) to transform
629      */
mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, int pointCount)630     public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
631             int pointCount) {
632         checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
633         nMapPoints(native_instance, dst, dstIndex, src, srcIndex,
634                 pointCount, true);
635     }
636 
637     /**
638      * Apply this matrix to the array of 2D vectors specified by src, and write the transformed
639      * vectors into the array of vectors specified by dst. The two arrays represent their "vectors"
640      * as pairs of floats [x, y]. Note: this method does not apply the translation associated with
641      * the matrix. Use {@link Matrix#mapPoints(float[], int, float[], int, int)} if you want the
642      * translation to be applied.
643      *
644      * @param dst The array of dst vectors (x,y pairs)
645      * @param dstIndex The index of the first [x,y] pair of dst floats
646      * @param src The array of src vectors (x,y pairs)
647      * @param srcIndex The index of the first [x,y] pair of src floats
648      * @param vectorCount The number of vectors (x,y pairs) to transform
649      */
mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)650     public void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex,
651             int vectorCount) {
652         checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount);
653         nMapPoints(native_instance, dst, dstIndex, src, srcIndex,
654                 vectorCount, false);
655     }
656 
657     /**
658      * Apply this matrix to the array of 2D points specified by src, and write the transformed
659      * points into the array of points specified by dst. The two arrays represent their "points" as
660      * pairs of floats [x, y].
661      *
662      * @param dst The array of dst points (x,y pairs)
663      * @param src The array of src points (x,y pairs)
664      */
mapPoints(float[] dst, float[] src)665     public void mapPoints(float[] dst, float[] src) {
666         if (dst.length != src.length) {
667             throw new ArrayIndexOutOfBoundsException();
668         }
669         mapPoints(dst, 0, src, 0, dst.length >> 1);
670     }
671 
672     /**
673      * Apply this matrix to the array of 2D vectors specified by src, and write the transformed
674      * vectors into the array of vectors specified by dst. The two arrays represent their "vectors"
675      * as pairs of floats [x, y]. Note: this method does not apply the translation associated with
676      * the matrix. Use {@link Matrix#mapPoints(float[], float[])} if you want the translation to be
677      * applied.
678      *
679      * @param dst The array of dst vectors (x,y pairs)
680      * @param src The array of src vectors (x,y pairs)
681      */
mapVectors(float[] dst, float[] src)682     public void mapVectors(float[] dst, float[] src) {
683         if (dst.length != src.length) {
684             throw new ArrayIndexOutOfBoundsException();
685         }
686         mapVectors(dst, 0, src, 0, dst.length >> 1);
687     }
688 
689     /**
690      * Apply this matrix to the array of 2D points, and write the transformed points back into the
691      * array
692      *
693      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
694      */
mapPoints(float[] pts)695     public void mapPoints(float[] pts) {
696         mapPoints(pts, 0, pts, 0, pts.length >> 1);
697     }
698 
699     /**
700      * Apply this matrix to the array of 2D vectors, and write the transformed vectors back into the
701      * array. Note: this method does not apply the translation associated with the matrix. Use
702      * {@link Matrix#mapPoints(float[])} if you want the translation to be applied.
703      *
704      * @param vecs The array [x0, y0, x1, y1, ...] of vectors to transform.
705      */
mapVectors(float[] vecs)706     public void mapVectors(float[] vecs) {
707         mapVectors(vecs, 0, vecs, 0, vecs.length >> 1);
708     }
709 
710     /**
711      * Apply this matrix to the src rectangle, and write the transformed rectangle into dst. This is
712      * accomplished by transforming the 4 corners of src, and then setting dst to the bounds of
713      * those points.
714      *
715      * @param dst Where the transformed rectangle is written.
716      * @param src The original rectangle to be transformed.
717      * @return the result of calling rectStaysRect()
718      */
mapRect(RectF dst, RectF src)719     public boolean mapRect(RectF dst, RectF src) {
720         if (dst == null || src == null) {
721             throw new NullPointerException();
722         }
723         return nMapRect(native_instance, dst, src);
724     }
725 
726     /**
727      * Apply this matrix to the rectangle, and write the transformed rectangle back into it. This is
728      * accomplished by transforming the 4 corners of rect, and then setting it to the bounds of
729      * those points
730      *
731      * @param rect The rectangle to transform.
732      * @return the result of calling rectStaysRect()
733      */
mapRect(RectF rect)734     public boolean mapRect(RectF rect) {
735         return mapRect(rect, rect);
736     }
737 
738     /**
739      * Return the mean radius of a circle after it has been mapped by this matrix. NOTE: in
740      * perspective this value assumes the circle has its center at the origin.
741      */
mapRadius(float radius)742     public float mapRadius(float radius) {
743         return nMapRadius(native_instance, radius);
744     }
745 
746     /**
747      * Copy 9 values from the matrix into the array.
748      */
getValues(float[] values)749     public void getValues(float[] values) {
750         if (values.length < 9) {
751             throw new ArrayIndexOutOfBoundsException();
752         }
753         nGetValues(native_instance, values);
754     }
755 
756     /**
757      * Copy 9 values from the array into the matrix. Depending on the implementation of Matrix,
758      * these may be transformed into 16.16 integers in the Matrix, such that a subsequent call to
759      * getValues() will not yield exactly the same values.
760      */
setValues(float[] values)761     public void setValues(float[] values) {
762         if (values.length < 9) {
763             throw new ArrayIndexOutOfBoundsException();
764         }
765         nSetValues(native_instance, values);
766     }
767 
768     @Override
toString()769     public String toString() {
770         StringBuilder sb = new StringBuilder(64);
771         sb.append("Matrix{");
772         toShortString(sb);
773         sb.append('}');
774         return sb.toString();
775 
776     }
777 
toShortString()778     public String toShortString() {
779         StringBuilder sb = new StringBuilder(64);
780         toShortString(sb);
781         return sb.toString();
782     }
783 
784     /**
785      * @hide
786      */
toShortString(StringBuilder sb)787     public void toShortString(StringBuilder sb) {
788         float[] values = new float[9];
789         getValues(values);
790         sb.append('[');
791         sb.append(values[0]);
792         sb.append(", ");
793         sb.append(values[1]);
794         sb.append(", ");
795         sb.append(values[2]);
796         sb.append("][");
797         sb.append(values[3]);
798         sb.append(", ");
799         sb.append(values[4]);
800         sb.append(", ");
801         sb.append(values[5]);
802         sb.append("][");
803         sb.append(values[6]);
804         sb.append(", ");
805         sb.append(values[7]);
806         sb.append(", ");
807         sb.append(values[8]);
808         sb.append(']');
809     }
810 
811     /**
812      * Print short string, to optimize dumping.
813      *
814      * @hide
815      */
printShortString(PrintWriter pw)816     public void printShortString(PrintWriter pw) {
817         float[] values = new float[9];
818         getValues(values);
819         pw.print('[');
820         pw.print(values[0]);
821         pw.print(", ");
822         pw.print(values[1]);
823         pw.print(", ");
824         pw.print(values[2]);
825         pw.print("][");
826         pw.print(values[3]);
827         pw.print(", ");
828         pw.print(values[4]);
829         pw.print(", ");
830         pw.print(values[5]);
831         pw.print("][");
832         pw.print(values[6]);
833         pw.print(", ");
834         pw.print(values[7]);
835         pw.print(", ");
836         pw.print(values[8]);
837         pw.print(']');
838 
839     }
840 
841     /** @hide */
ni()842     public final long ni() {
843         return native_instance;
844     }
845 
846     // ------------------ Regular JNI ------------------------
847 
nCreate(long nSrc_or_zero)848     private static native long nCreate(long nSrc_or_zero);
nGetNativeFinalizer()849     private static native long nGetNativeFinalizer();
850 
851 
852     // ------------------ Fast JNI ------------------------
853 
854     @FastNative
nSetRectToRect(long nObject, RectF src, RectF dst, int stf)855     private static native boolean nSetRectToRect(long nObject,
856             RectF src, RectF dst, int stf);
857     @FastNative
nSetPolyToPoly(long nObject, float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)858     private static native boolean nSetPolyToPoly(long nObject,
859             float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount);
860     @FastNative
nMapPoints(long nObject, float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount, boolean isPts)861     private static native void nMapPoints(long nObject,
862             float[] dst, int dstIndex, float[] src, int srcIndex,
863             int ptCount, boolean isPts);
864     @FastNative
nMapRect(long nObject, RectF dst, RectF src)865     private static native boolean nMapRect(long nObject, RectF dst, RectF src);
866     @FastNative
nGetValues(long nObject, float[] values)867     private static native void nGetValues(long nObject, float[] values);
868     @FastNative
nSetValues(long nObject, float[] values)869     private static native void nSetValues(long nObject, float[] values);
870 
871 
872     // ------------------ Critical JNI ------------------------
873 
874     @CriticalNative
nIsIdentity(long nObject)875     private static native boolean nIsIdentity(long nObject);
876     @CriticalNative
nIsAffine(long nObject)877     private static native boolean nIsAffine(long nObject);
878     @CriticalNative
nRectStaysRect(long nObject)879     private static native boolean nRectStaysRect(long nObject);
880     @CriticalNative
nReset(long nObject)881     private static native void nReset(long nObject);
882     @CriticalNative
nSet(long nObject, long nOther)883     private static native void nSet(long nObject, long nOther);
884     @CriticalNative
nSetTranslate(long nObject, float dx, float dy)885     private static native void nSetTranslate(long nObject, float dx, float dy);
886     @CriticalNative
nSetScale(long nObject, float sx, float sy, float px, float py)887     private static native void nSetScale(long nObject, float sx, float sy, float px, float py);
888     @CriticalNative
nSetScale(long nObject, float sx, float sy)889     private static native void nSetScale(long nObject, float sx, float sy);
890     @CriticalNative
nSetRotate(long nObject, float degrees, float px, float py)891     private static native void nSetRotate(long nObject, float degrees, float px, float py);
892     @CriticalNative
nSetRotate(long nObject, float degrees)893     private static native void nSetRotate(long nObject, float degrees);
894     @CriticalNative
nSetSinCos(long nObject, float sinValue, float cosValue, float px, float py)895     private static native void nSetSinCos(long nObject, float sinValue, float cosValue,
896             float px, float py);
897     @CriticalNative
nSetSinCos(long nObject, float sinValue, float cosValue)898     private static native void nSetSinCos(long nObject, float sinValue, float cosValue);
899     @CriticalNative
nSetSkew(long nObject, float kx, float ky, float px, float py)900     private static native void nSetSkew(long nObject, float kx, float ky, float px, float py);
901     @CriticalNative
nSetSkew(long nObject, float kx, float ky)902     private static native void nSetSkew(long nObject, float kx, float ky);
903     @CriticalNative
nSetConcat(long nObject, long nA, long nB)904     private static native void nSetConcat(long nObject, long nA, long nB);
905     @CriticalNative
nPreTranslate(long nObject, float dx, float dy)906     private static native void nPreTranslate(long nObject, float dx, float dy);
907     @CriticalNative
nPreScale(long nObject, float sx, float sy, float px, float py)908     private static native void nPreScale(long nObject, float sx, float sy, float px, float py);
909     @CriticalNative
nPreScale(long nObject, float sx, float sy)910     private static native void nPreScale(long nObject, float sx, float sy);
911     @CriticalNative
nPreRotate(long nObject, float degrees, float px, float py)912     private static native void nPreRotate(long nObject, float degrees, float px, float py);
913     @CriticalNative
nPreRotate(long nObject, float degrees)914     private static native void nPreRotate(long nObject, float degrees);
915     @CriticalNative
nPreSkew(long nObject, float kx, float ky, float px, float py)916     private static native void nPreSkew(long nObject, float kx, float ky, float px, float py);
917     @CriticalNative
nPreSkew(long nObject, float kx, float ky)918     private static native void nPreSkew(long nObject, float kx, float ky);
919     @CriticalNative
nPreConcat(long nObject, long nOther_matrix)920     private static native void nPreConcat(long nObject, long nOther_matrix);
921     @CriticalNative
nPostTranslate(long nObject, float dx, float dy)922     private static native void nPostTranslate(long nObject, float dx, float dy);
923     @CriticalNative
nPostScale(long nObject, float sx, float sy, float px, float py)924     private static native void nPostScale(long nObject, float sx, float sy, float px, float py);
925     @CriticalNative
nPostScale(long nObject, float sx, float sy)926     private static native void nPostScale(long nObject, float sx, float sy);
927     @CriticalNative
nPostRotate(long nObject, float degrees, float px, float py)928     private static native void nPostRotate(long nObject, float degrees, float px, float py);
929     @CriticalNative
nPostRotate(long nObject, float degrees)930     private static native void nPostRotate(long nObject, float degrees);
931     @CriticalNative
nPostSkew(long nObject, float kx, float ky, float px, float py)932     private static native void nPostSkew(long nObject, float kx, float ky, float px, float py);
933     @CriticalNative
nPostSkew(long nObject, float kx, float ky)934     private static native void nPostSkew(long nObject, float kx, float ky);
935     @CriticalNative
nPostConcat(long nObject, long nOther_matrix)936     private static native void nPostConcat(long nObject, long nOther_matrix);
937     @CriticalNative
nInvert(long nObject, long nInverse)938     private static native boolean nInvert(long nObject, long nInverse);
939     @CriticalNative
nMapRadius(long nObject, float radius)940     private static native float nMapRadius(long nObject, float radius);
941     @CriticalNative
nEquals(long nA, long nB)942     private static native boolean nEquals(long nA, long nB);
943 }
944