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