Matrix_Delegate.java revision 10af738336cb18c5d86710b2961d91e2d3e8d410
14f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet/*
24f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
34f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
44f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
54f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * you may not use this file except in compliance with the License.
64f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * You may obtain a copy of the License at
74f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
84f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
94f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * See the License for the specific language governing permissions and
144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * limitations under the License.
154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet */
164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetpackage android.graphics;
184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
21c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager;
224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport android.graphics.Matrix.ScaleToFit;
244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport java.awt.geom.AffineTransform;
264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport java.awt.geom.NoninvertibleTransformException;
274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet/**
294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Delegate implementing the native methods of android.graphics.Matrix
304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * by calls to methods of the same name in this delegate class.
334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * This class behaves like the original native implementation, but in Java, keeping previously
354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * native data into its own objects and mapping them to int that are sent back and forth between
364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * it and the original Matrix class.
374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * @see DelegateManager
394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet */
414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetpublic final class Matrix_Delegate {
424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int MATRIX_SIZE = 9;
444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- delegate manager ----
464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private static final DelegateManager<Matrix_Delegate> sManager =
474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            new DelegateManager<Matrix_Delegate>();
484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- delegate data ----
504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private float mValues[] = new float[MATRIX_SIZE];
514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- Public Helper methods ----
534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
54251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public static Matrix_Delegate getDelegate(int native_instance) {
55251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        return sManager.getDelegate(native_instance);
56251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
57251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns an {@link AffineTransform} matching the given Matrix.
604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public static AffineTransform getAffineTransform(Matrix m) {
624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (delegate == null) {
644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return null;
654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return delegate.getAffineTransform();
684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public static boolean hasPerspective(Matrix m) {
714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (delegate == null) {
734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return delegate.hasPerspective();
774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
79251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    /**
80251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     * Sets the content of the matrix with the content of another matrix.
81251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     */
82251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public void set(Matrix_Delegate matrix) {
83251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
84251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
85251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
86251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    /**
87251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     * Resets the matrix to be the identity matrix.
88251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     */
89251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public void reset() {
90251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        reset(mValues);
91251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
92251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
93251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    /**
94251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     * Returns whether or not the matrix is identity.
95251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     */
96251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public boolean isIdentity() {
97251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        for (int i = 0, k = 0; i < 3; i++) {
98251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet            for (int j = 0; j < 3; j++, k++) {
99251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet                if (mValues[k] != ((i==j) ? 1 : 0)) {
100251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet                    return false;
101251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet                }
102251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet            }
103251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        }
104251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
105251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        return true;
106251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
107251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
108d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    public static Matrix_Delegate make(AffineTransform matrix) {
109d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        float[] values = new float[MATRIX_SIZE];
110d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[0] = (float) matrix.getScaleX();
111d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[1] = (float) matrix.getShearX();
112d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[2] = (float) matrix.getTranslateX();
113d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[3] = (float) matrix.getShearY();
114d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[4] = (float) matrix.getScaleY();
115d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[5] = (float) matrix.getTranslateY();
116d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[6] = 0.f;
117d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[7] = 0.f;
118d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[8] = 1.f;
119d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
120d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        return new Matrix_Delegate(values);
121d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
122d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
123d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    public boolean mapRect(RectF dst, RectF src) {
124d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        // array with 4 corners
125d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        float[] corners = new float[] {
126d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.left, src.top,
127d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.right, src.top,
128d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.right, src.bottom,
129d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.left, src.bottom,
130d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        };
131d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
132d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        // apply the transform to them.
133d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        mapPoints(corners);
134d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
135d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
136d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
137d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
138d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
139d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
140d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
141d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
142d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
143d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
144d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
145d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
146d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
1472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Returns an {@link AffineTransform} matching the matrix.
1492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
1502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    public AffineTransform getAffineTransform() {
1512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return getAffineTransform(mValues);
1522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    public boolean hasPerspective() {
1552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
1562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- native methods ----
1614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1625de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static int native_create(int native_src_or_zero) {
1634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // create the delegate
1644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate newDelegate = new Matrix_Delegate();
1654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // copy from values if needed.
1674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (native_src_or_zero > 0) {
1684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
1694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (oldDelegate != null) {
1704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                System.arraycopy(
1714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                        oldDelegate.mValues, 0,
1724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                        newDelegate.mValues, 0,
1734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                        MATRIX_SIZE);
1744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
1754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
1764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return sManager.addDelegate(newDelegate);
1784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
1794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1805de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_isIdentity(int native_object) {
1814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
1824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
1834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
1844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
1854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
186251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        return d.isIdentity();
1874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
1884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1895de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_rectStaysRect(int native_object) {
1904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
1914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
1924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return true;
1934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
1944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
1964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
1974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1985de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_reset(int native_object) {
1994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        reset(d.mValues);
2054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2075de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_set(int native_object, int other) {
2084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate src = sManager.getDelegate(other);
2144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (src == null) {
2154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
2194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2215de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setTranslate(int native_object, float dx, float dy) {
2224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(d.mValues, dx, dy);
2284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
230cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static void native_setScale(int native_object, float sx, float sy,
231cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
2324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues = getScale(sx, sy, px, py);
2384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2405de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setScale(int native_object, float sx, float sy) {
2414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[0] = sx;
2474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[1] = 0;
2484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[2] = 0;
2494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[3] = 0;
2504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[4] = sy;
2514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[5] = 0;
2524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[6] = 0;
2534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[7] = 0;
2544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[8] = 1;
2554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2575de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setRotate(int native_object, float degrees, float px, float py) {
2584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues = getRotate(degrees, px, py);
2644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2665de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setRotate(int native_object, float degrees) {
2674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setRotate(d.mValues, degrees);
2734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2755de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue,
2764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
2774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
2834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
2854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(d.mValues, -px, -py);
2864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // scale
2884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getRotate(sinValue, cosValue));
2894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot
2904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getTranslate(px, py));
2914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2935de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue) {
2944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setRotate(d.mValues, sinValue, cosValue);
3004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
302cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static void native_setSkew(int native_object, float kx, float ky,
303cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
3044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
3074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues = getSkew(kx, ky, px, py);
3104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3125de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setSkew(int native_object, float kx, float ky) {
3134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
3164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[0] = 1;
3194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[1] = kx;
3204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[2] = -0;
3214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[3] = ky;
3224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[4] = 1;
3234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[5] = 0;
3244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[6] = 0;
3254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[7] = 0;
3264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[8] = 1;
3274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3295de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_setConcat(int native_object, int a, int b) {
3304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a == native_object) {
3314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return native_preConcat(native_object, b);
3324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } else if (b == native_object) {
3334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return native_postConcat(native_object, a);
3344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate a_mtx = sManager.getDelegate(a);
3424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a_mtx == null) {
3434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate b_mtx = sManager.getDelegate(b);
3474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (b_mtx == null) {
3484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
3524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3565de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preTranslate(int native_object, float dx, float dy) {
3574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getTranslate(dx, dy));
3634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3665de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preScale(int native_object, float sx, float sy,
3674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
3684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getScale(sx, sy, px, py));
3744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3775de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preScale(int native_object, float sx, float sy) {
3784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getScale(sx, sy));
3844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
387cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static boolean native_preRotate(int native_object, float degrees,
388cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
3894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getRotate(degrees, px, py));
3954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3985de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preRotate(int native_object, float degrees) {
3994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
4054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
4064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
4074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getRotate(sin, cos));
4094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4125de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preSkew(int native_object, float kx, float ky,
4134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
4144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getSkew(kx, ky, px, py));
4204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4235de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preSkew(int native_object, float kx, float ky) {
4244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getSkew(kx, ky));
4304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4335de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preConcat(int native_object, int other_matrix) {
4344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate other = sManager.getDelegate(other_matrix);
4404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(other.mValues);
4454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4485de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postTranslate(int native_object, float dx, float dy) {
4494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getTranslate(dx, dy));
4554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4585de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postScale(int native_object, float sx, float sy,
4594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
4604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getScale(sx, sy, px, py));
4664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4695de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postScale(int native_object, float sx, float sy) {
4704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getScale(sx, sy));
4764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
479cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static boolean native_postRotate(int native_object, float degrees,
480cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
4814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
486d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet        d.postTransform(getRotate(degrees, px, py));
4874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4905de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postRotate(int native_object, float degrees) {
4914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getRotate(degrees));
4974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5005de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postSkew(int native_object, float kx, float ky,
5014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
5024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getSkew(kx, ky, px, py));
5084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5115de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postSkew(int native_object, float kx, float ky) {
5124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getSkew(kx, ky));
5184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5215de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postConcat(int native_object, int other_matrix) {
5224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate other = sManager.getDelegate(other_matrix);
5284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(other.mValues);
5334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
536cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static boolean native_setRectToRect(int native_object, RectF src,
537cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            RectF dst, int stf) {
5384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (src.isEmpty()) {
5444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            reset(d.mValues);
5454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (dst.isEmpty()) {
5494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
5504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet               = d.mValues[6] = d.mValues[7] = 0;
5514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[8] = 1;
5524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } else {
5534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float    tx, sx = dst.width() / src.width();
5544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float    ty, sy = dst.height() / src.height();
5554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            boolean  xLarger = false;
5564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (stf != ScaleToFit.FILL.nativeInt) {
5584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (sx > sy) {
5594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    xLarger = true;
5604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    sx = sy;
5614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                } else {
5624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    sy = sx;
5634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
5644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
5654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            tx = dst.left - src.left * sx;
5674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            ty = dst.top - src.top * sy;
5684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
5694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                float diff;
5704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (xLarger) {
5724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    diff = dst.width() - src.width() * sy;
5734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                } else {
5744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    diff = dst.height() - src.height() * sy;
5754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
5764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (stf == ScaleToFit.CENTER.nativeInt) {
5784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    diff = diff / 2;
5794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
5804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (xLarger) {
5824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    tx += diff;
5834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                } else {
5844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    ty += diff;
5854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
5864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
5874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[0] = sx;
5894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[4] = sy;
5904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[2] = tx;
5914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[5] = ty;
5924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
5934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // shared cleanup
5964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[8] = 1;
5974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6005de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex,
6014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float[] dst, int dstIndex, int pointCount) {
6024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // FIXME
60310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        Bridge.getLog().fidelityWarning(null,
60410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                "Matrix.setPolyToPoly is not supported.",
60510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                null);
60610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        return false;
6074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6095de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_invert(int native_object, int inverse) {
6104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
6164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (inv_mtx == null) {
6174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        try {
6212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            AffineTransform affineTransform = d.getAffineTransform();
6224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            AffineTransform inverseTransform = affineTransform.createInverse();
6234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
6244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
6254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
6264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
6274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
6284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
6294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return true;
6314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } catch (NoninvertibleTransformException e) {
6324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6365de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_mapPoints(int native_object, float[] dst, int dstIndex,
6374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float[] src, int srcIndex, int ptCount, boolean isPts) {
6384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
6414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (isPts) {
6444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
6454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } else {
64610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
6474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6505de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_mapRect(int native_object, RectF dst, RectF src) {
6514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
656d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        return d.mapRect(dst, src);
6574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6595de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static float native_mapRadius(int native_object, float radius) {
66010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
66110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        if (d == null) {
66210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet            return 0.f;
66310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        }
66410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
66510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        float[] src = new float[] { radius, 0.f, 0.f, radius };
66610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        d.mapVectors(src, 0, src, 0, 2);
66710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
66810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        float l1 = getPointLength(src, 0);
66910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        float l2 = getPointLength(src, 2);
67010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
67110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        return (float) Math.sqrt(l1 * l2);
6724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6745de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_getValues(int native_object, float[] values) {
6754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
6784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
6814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6835de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setValues(int native_object, float[] values) {
6844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
6874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
6904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6925de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_equals(int native_a, int native_b) {
6934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate a = sManager.getDelegate(native_a);
6944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a == null) {
6954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate b = sManager.getDelegate(native_b);
6994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (b == null) {
7004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
7014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
7044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (a.mValues[i] != b.mValues[i]) {
7054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                return false;
7064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
7074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
7104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7125de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void finalizer(int native_instance) {
7134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        sManager.removeDelegate(native_instance);
7144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- Private helper methods ----
7174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7185802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
7194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // the AffineTransform constructor takes the value in a different order
7204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // for a matrix [ 0 1 2 ]
7214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        //              [ 3 4 5 ]
7224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // the order is 0, 3, 1, 4, 2, 5...
7234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new AffineTransform(
7245802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet                matrix[0], matrix[3], matrix[1],
7255802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet                matrix[4], matrix[2], matrix[5]);
7264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
7294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Reset a matrix to the identity
7304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
7314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private static void reset(float[] mtx) {
7324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        for (int i = 0, k = 0; i < 3; i++) {
7334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            for (int j = 0; j < 3; j++, k++) {
7344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                mtx[k] = ((i==j) ? 1 : 0);
7354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
7364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kIdentity_Mask      = 0;
7414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
7424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
7434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
7444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
7454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kRectStaysRect_Mask = 0x10;
7464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kUnknown_Mask       = 0x80;
7484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAllMasks           = kTranslate_Mask |
7514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kScale_Mask |
7524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kAffine_Mask |
7534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kPerspective_Mask |
7544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kRectStaysRect_Mask;
7554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // these guys align with the masks, so we can compute a mask from a variable 0/1
7574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kTranslate_Shift = 0;
7594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kScale_Shift = 1;
7614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAffine_Shift = 2;
7634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kPerspective_Shift = 3;
7654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kRectStaysRect_Shift = 4;
7664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private int computeTypeMask() {
7684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        int mask = 0;
7694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
7714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kPerspective_Mask;
7724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (mValues[2] != 0. || mValues[5] != 0.) {
7754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kTranslate_Mask;
7764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m00 = mValues[0];
7794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m01 = mValues[1];
7804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m10 = mValues[3];
7814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m11 = mValues[4];
7824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (m01 != 0. || m10 != 0.) {
7844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kAffine_Mask;
7854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (m00 != 1. || m11 != 1.) {
7884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kScale_Mask;
7894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if ((mask & kPerspective_Mask) == 0) {
7924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // map non-zero to 1
7934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im00 = m00 != 0 ? 1 : 0;
7944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im01 = m01 != 0 ? 1 : 0;
7954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im10 = m10 != 0 ? 1 : 0;
7964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im11 = m11 != 0 ? 1 : 0;
7974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // record if the (p)rimary and (s)econdary diagonals are all 0 or
7994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // all non-zero (answer is 0 or 1)
8004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
8014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int dp1 = im00 & im11;        // true if both are 1
8024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
8034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int ds1 = im01 & im10;        // true if both are 1
8044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // return 1 if primary is 1 and secondary is 0 or
8064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // primary is 0 and secondary is 1
8074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
8084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return mask;
8114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
813d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet    private Matrix_Delegate() {
814d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet        reset();
815d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet    }
816d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet
817d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    private Matrix_Delegate(float[] values) {
818d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
819d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
820d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
8214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds the given transformation to the current Matrix
8234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does this = this*matrix
8244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param matrix
8254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
8264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private void postTransform(float[] matrix) {
8274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
8284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, mValues, matrix);
8294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        mValues = tmp;
8304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds the given transformation to the current Matrix
8344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does this = matrix*this
8354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param matrix
8364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
8374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private void preTransform(float[] matrix) {
8384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
8394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, matrix, mValues);
8404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        mValues = tmp;
8414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Apply this matrix to the array of 2D points specified by src, and write
8454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * the transformed points into the array of points specified by dst. The
8464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * two arrays represent their "points" as pairs of floats [x, y].
8474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      *
8484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param dst   The array of dst points (x,y pairs)
8494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param dstIndex The index of the first [x,y] pair of dst floats
8504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param src   The array of src points (x,y pairs)
8514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param srcIndex The index of the first [x,y] pair of src floats
8524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param pointCount The number of points (x,y pairs) to transform
8534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      */
8544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
8564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                           int pointCount) {
85710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         final int count = pointCount * 2;
8584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         float[] tmpDest = dst;
8604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         boolean inPlace = dst == src;
8614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         if (inPlace) {
86210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             tmpDest = new float[dstIndex + count];
8634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
8644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
86510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         for (int i = 0 ; i < count ; i += 2) {
8664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             // just in case we are doing in place, we better put this in temp vars
8674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             float x = mValues[0] * src[i + srcIndex] +
8684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[1] * src[i + srcIndex + 1] +
8694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[2];
8704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             float y = mValues[3] * src[i + srcIndex] +
8714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[4] * src[i + srcIndex + 1] +
8724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[5];
8734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             tmpDest[i + dstIndex]     = x;
8754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             tmpDest[i + dstIndex + 1] = y;
8764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
8774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         if (inPlace) {
87910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
8804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
8814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     }
8824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     /**
8844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * Apply this matrix to the array of 2D points, and write the transformed
8854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * points back into the array
8864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      *
8874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
8884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      */
8894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     private void mapPoints(float[] pts) {
8914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         mapPoints(pts, 0, pts, 0, pts.length >> 1);
8924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     }
8934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
89410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
89510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         if (hasPerspective()) {
89610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // transform the (0,0) point
89710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             float[] origin = new float[] { 0.f, 0.f};
89810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             mapPoints(origin);
89910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
90010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // translate the vector data as points
90110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
90210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
90310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // then substract the transformed origin.
90410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             final int count = ptCount * 2;
90510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             for (int i = 0 ; i < count ; i += 2) {
90610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
90710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
90810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             }
90910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         } else {
91010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // make a copy of the matrix
91110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             Matrix_Delegate copy = new Matrix_Delegate(mValues);
91210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
91310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // remove the translation
91410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             setTranslate(copy.mValues, 0, 0);
91510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
91610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // map the content as points.
91710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
91810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         }
91910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     }
92010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
92110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     private static float getPointLength(float[] src, int index) {
92210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         return (float) Math.sqrt(src[index] * src[index] + src[index + 1] * src[index + 1]);
92310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     }
92410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
9254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
9264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * multiply two matrices and store them in a 3rd.
9274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does dest = a*b
9284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * dest cannot be the same as a or b.
9294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
9305802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
9314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // first row
9324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
9334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
9344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
9354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // 2nd row
9374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
9384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
9394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
9404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // 3rd row
9424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
9434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
9444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
9454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
9464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
9484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns a matrix that represents a given translate
9494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param dx
9504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param dy
9514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @return
9524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
9535802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getTranslate(float dx, float dy) {
9544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setTranslate(new float[9], dx, dy);
9554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
9564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9575802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
9584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = 1;
9594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = 0;
9604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = dx;
9614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = 0;
9624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = 1;
9634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = dy;
9644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = 0;
9654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = 0;
9664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = 1;
9674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return dest;
9684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
9694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9705802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getScale(float sx, float sy) {
9714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
9724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
9734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
9754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns a matrix that represents the given scale info.
9764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param sx
9774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param sy
9784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param px
9794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param py
9804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
9815802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
9824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
9834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
9844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
9864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate tmp so that the pivot is in 0,0
9884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
9894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // scale into tmp2
9914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, getScale(sx, sy));
9924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
9944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
9954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
9974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
9984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10005802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float degrees) {
10014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return getRotate(sin, cos);
10064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10085802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float sin, float cos) {
10094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setRotate(new float[9], sin, cos);
10104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10125802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setRotate(float[] dest, float degrees) {
10134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setRotate(dest, sin, cos);
10184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10205802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
10214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = cos;
10224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = -sin;
10234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = 0;
10244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = sin;
10254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = cos;
10264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = 0;
10274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = 0;
10284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = 0;
10294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = 1;
10304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return dest;
10314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10335802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float degrees, float px, float py) {
10344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
10354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
10364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
10384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
10404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
10414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // rotate into tmp2
10434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, getRotate(sin, cos));
10474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
10494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
10504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
10524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10545802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getSkew(float kx, float ky) {
10554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
10564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10585802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
10594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
10604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
10614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
10634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
10654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
10664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // skew into tmp2
10684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
10694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
10704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
10714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
10734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet}
1075