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