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