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
17package android.graphics;
18
19import java.io.PrintWriter;
20
21
22/**
23 * The Matrix class holds a 3x3 matrix for transforming coordinates.
24 */
25public 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     */
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     */
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     */
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     */
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     */
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     */
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
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
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 */
297    public void reset() {
298        native_reset(native_instance);
299    }
300
301    /** Set the matrix to translate by (dx, 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     */
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. */
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     */
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     */
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     */
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. */
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     */
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. */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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"
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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    */
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    */
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
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
788    public String toShortString() {
789        StringBuilder sb = new StringBuilder(64);
790        toShortString(sb);
791        return sb.toString();
792    }
793
794    /**
795     * @hide
796     */
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     */
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
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
836    /*package*/ final long ni() {
837        return native_instance;
838    }
839
840    private static native long native_create(long native_src_or_zero);
841    private static native boolean native_isIdentity(long native_object);
842    private static native boolean native_isAffine(long native_object);
843    private static native boolean native_rectStaysRect(long native_object);
844    private static native void native_reset(long native_object);
845    private static native void native_set(long native_object,
846                                          long native_other);
847    private static native void native_setTranslate(long native_object,
848                                                   float dx, float dy);
849    private static native void native_setScale(long native_object,
850                                        float sx, float sy, float px, float py);
851    private static native void native_setScale(long native_object,
852                                               float sx, float sy);
853    private static native void native_setRotate(long native_object,
854                                            float degrees, float px, float py);
855    private static native void native_setRotate(long native_object,
856                                                float degrees);
857    private static native void native_setSinCos(long native_object,
858                            float sinValue, float cosValue, float px, float py);
859    private static native void native_setSinCos(long native_object,
860                                                float sinValue, float cosValue);
861    private static native void native_setSkew(long native_object,
862                                        float kx, float ky, float px, float py);
863    private static native void native_setSkew(long native_object,
864                                              float kx, float ky);
865    private static native void native_setConcat(long native_object,
866                                                long native_a,
867                                                long native_b);
868    private static native void native_preTranslate(long native_object,
869                                                   float dx, float dy);
870    private static native void native_preScale(long native_object,
871                                               float sx, float sy, float px, float py);
872    private static native void native_preScale(long native_object,
873                                               float sx, float sy);
874    private static native void native_preRotate(long native_object,
875                                                float degrees, float px, float py);
876    private static native void native_preRotate(long native_object,
877                                                float degrees);
878    private static native void native_preSkew(long native_object,
879                                              float kx, float ky, float px, float py);
880    private static native void native_preSkew(long native_object,
881                                              float kx, float ky);
882    private static native void native_preConcat(long native_object,
883                                                long native_other_matrix);
884    private static native void native_postTranslate(long native_object,
885                                                    float dx, float dy);
886    private static native void native_postScale(long native_object,
887                                                float sx, float sy, float px, float py);
888    private static native void native_postScale(long native_object,
889                                                float sx, float sy);
890    private static native void native_postRotate(long native_object,
891                                                 float degrees, float px, float py);
892    private static native void native_postRotate(long native_object,
893                                                 float degrees);
894    private static native void native_postSkew(long native_object,
895                                               float kx, float ky, float px, float py);
896    private static native void native_postSkew(long native_object,
897                                               float kx, float ky);
898    private static native void native_postConcat(long native_object,
899                                                 long native_other_matrix);
900    private static native boolean native_setRectToRect(long native_object,
901                                                RectF src, RectF dst, int stf);
902    private static native boolean native_setPolyToPoly(long native_object,
903        float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount);
904    private static native boolean native_invert(long native_object,
905                                                long native_inverse);
906    private static native void native_mapPoints(long native_object,
907                        float[] dst, int dstIndex, float[] src, int srcIndex,
908                        int ptCount, boolean isPts);
909    private static native boolean native_mapRect(long native_object,
910                                                 RectF dst, RectF src);
911    private static native float native_mapRadius(long native_object,
912                                                 float radius);
913    private static native void native_getValues(long native_object,
914                                                float[] values);
915    private static native void native_setValues(long native_object,
916                                                float[] values);
917    private static native boolean native_equals(long native_a, long native_b);
918    private static native void finalizer(long native_instance);
919}
920