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