1ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/*
2ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Copyright (C) 2010 The Android Open Source Project
3ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
4ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * you may not use this file except in compliance with the License.
6ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * You may obtain a copy of the License at
7ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
8ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
10ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * See the License for the specific language governing permissions and
14ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * limitations under the License.
15ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
16ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
17ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipackage android.graphics;
18ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
19ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
20ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
21ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.Bridge;
22ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.impl.DelegateManager;
23ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
24ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
25ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.graphics.Matrix.ScaleToFit;
26ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
27ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.awt.geom.AffineTransform;
28ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.awt.geom.NoninvertibleTransformException;
29ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
307fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillardimport libcore.util.NativeAllocationRegistry_Delegate;
317fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
32ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/**
33ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Delegate implementing the native methods of android.graphics.Matrix
34ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
35ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
36ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * by calls to methods of the same name in this delegate class.
37ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
38ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
39ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
40ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * it and the original Matrix class.
41ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
42ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * @see DelegateManager
43ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
44ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
45ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipublic final class Matrix_Delegate {
46ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
47ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int MATRIX_SIZE = 9;
48ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
49ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate manager ----
50ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private static final DelegateManager<Matrix_Delegate> sManager =
51ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
527fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    private static long sFinalizer = -1;
53ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
54ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate data ----
55ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private float mValues[] = new float[MATRIX_SIZE];
56ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
57ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Public Helper methods ----
58ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
59ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    public static Matrix_Delegate getDelegate(long native_instance) {
60ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return sManager.getDelegate(native_instance);
61ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
62ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
63ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
64ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns an {@link AffineTransform} matching the given Matrix.
65ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
66ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static AffineTransform getAffineTransform(Matrix m) {
67ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
68ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
69ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
70ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
71ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
72ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.getAffineTransform();
73ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
74ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
75ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static boolean hasPerspective(Matrix m) {
76ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
77ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
78ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
79ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
80ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
81ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.hasPerspective();
82ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
83ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
84ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
85ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Sets the content of the matrix with the content of another matrix.
86ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
87ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void set(Matrix_Delegate matrix) {
88ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
89ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
90ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
91ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
92ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Sets the content of the matrix with the content of another matrix represented as an array
93ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * of values.
94ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
95ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void set(float[] values) {
96ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
97ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
98ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
99ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
100ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Resets the matrix to be the identity matrix.
101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void reset() {
103ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset(mValues);
104ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
105ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
106ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns whether or not the matrix is identity.
108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean isIdentity() {
110ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
111ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int j = 0; j < 3; j++, k++) {
112ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (mValues[k] != ((i==j) ? 1 : 0)) {
113ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    return false;
114ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
115ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
116ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
117ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
118ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
119ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
120ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1219a92f1849a1bcb593965a6ff1270ac8273ff259eDiego Perez    private static float[] setValues(AffineTransform matrix, float[] values) {
122ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[0] = (float) matrix.getScaleX();
123ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[1] = (float) matrix.getShearX();
124ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[2] = (float) matrix.getTranslateX();
125ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[3] = (float) matrix.getShearY();
126ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[4] = (float) matrix.getScaleY();
127ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[5] = (float) matrix.getTranslateY();
128ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[6] = 0.f;
129ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[7] = 0.f;
130ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[8] = 1.f;
131ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
132ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return values;
133ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
134ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1359a92f1849a1bcb593965a6ff1270ac8273ff259eDiego Perez    public static float[] makeValues(AffineTransform matrix) {
1369a92f1849a1bcb593965a6ff1270ac8273ff259eDiego Perez        return setValues(matrix, new float[MATRIX_SIZE]);
1379a92f1849a1bcb593965a6ff1270ac8273ff259eDiego Perez    }
1389a92f1849a1bcb593965a6ff1270ac8273ff259eDiego Perez
139ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static Matrix_Delegate make(AffineTransform matrix) {
140ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new Matrix_Delegate(makeValues(matrix));
141ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
142ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
143ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean mapRect(RectF dst, RectF src) {
144ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // array with 4 corners
145ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] corners = new float[] {
146ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.left, src.top,
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.right, src.top,
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.right, src.bottom,
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.left, src.bottom,
150ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        };
151ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // apply the transform to them.
153ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mapPoints(corners);
154ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
158ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
159ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
160ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
161ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
162ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
163ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
164ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
165ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
166ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
167ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
168ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns an {@link AffineTransform} matching the matrix.
169ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
170ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public AffineTransform getAffineTransform() {
171ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getAffineTransform(mValues);
172ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean hasPerspective() {
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
176ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
177ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
180ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- native methods ----
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
1837fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static long nCreate(long native_src_or_zero) {
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the delegate
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate newDelegate = new Matrix_Delegate();
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // copy from values if needed.
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (native_src_or_zero > 0) {
189ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
190ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (oldDelegate != null) {
191ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                System.arraycopy(
192ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        oldDelegate.mValues, 0,
193ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        newDelegate.mValues, 0,
194ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        MATRIX_SIZE);
195ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
196ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
197ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
198ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return sManager.addNewDelegate(newDelegate);
199ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
200ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
201ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2027fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nIsIdentity(long native_object) {
203ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
204ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
206ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
207ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
208ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return d.isIdentity();
209ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
210ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
211ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2127fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nIsAffine(long native_object) {
213017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        Matrix_Delegate d = sManager.getDelegate(native_object);
214017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        if (d == null) {
215017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta            return true;
216017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        }
217017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta
218017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        return (d.computeTypeMask() & kPerspective_Mask) == 0;
219017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta    }
220017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta
221017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta    @LayoutlibDelegate
2227fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nRectStaysRect(long native_object) {
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
226ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
227ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
228ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
229ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2327fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nReset(long native_object) {
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset(d.mValues);
239ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
241ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2427fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSet(long native_object, long other) {
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
244ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
245ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
246ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
247ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
248ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate src = sManager.getDelegate(other);
249ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (src == null) {
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
251ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
252ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2577fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetTranslate(long native_object, float dx, float dy) {
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(d.mValues, dx, dy);
264ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
265ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
266ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2677fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetScale(long native_object, float sx, float sy,
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
269ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
270ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getScale(sx, sy, px, py);
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2787fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetScale(long native_object, float sx, float sy) {
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
280ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[0] = sx;
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[1] = 0;
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[2] = 0;
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[3] = 0;
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[4] = sy;
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[5] = 0;
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[6] = 0;
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[7] = 0;
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
293ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
294ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2967fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetRotate(long native_object, float degrees, float px, float py) {
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
299ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
300ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
301ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
302ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getRotate(degrees, px, py);
303ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
304ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
305ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3067fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetRotate(long native_object, float degrees) {
307ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
308ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
309ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
310ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
311ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
312ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setRotate(d.mValues, degrees);
313ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
314ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
315ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3167fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue,
317ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
318ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
319ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
320ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
323ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
324ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
325ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
326ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(d.mValues, -px, -py);
327ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
328ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // scale
329ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getRotate(sinValue, cosValue));
330ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot
331ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getTranslate(px, py));
332ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3357fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue) {
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setRotate(d.mValues, sinValue, cosValue);
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3457fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSkew(long native_object, float kx, float ky,
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getSkew(kx, ky, px, py);
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3567fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSkew(long native_object, float kx, float ky) {
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
358ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[0] = 1;
363ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[1] = kx;
364ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[2] = -0;
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[3] = ky;
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[4] = 1;
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[5] = 0;
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[6] = 0;
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[7] = 0;
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3747fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetConcat(long native_object, long a, long b) {
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a == native_object) {
3767fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            nPreConcat(native_object, b);
377678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            return;
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else if (b == native_object) {
3797fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            nPostConcat(native_object, a);
380678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            return;
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
384ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate a_mtx = sManager.getDelegate(a);
385ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate b_mtx = sManager.getDelegate(b);
386678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null && a_mtx != null && b_mtx != null) {
387678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
388ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
389ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
391ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3927fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreTranslate(long native_object, float dx, float dy) {
393ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
394678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
395678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getTranslate(dx, dy));
396ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
397ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4007fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreScale(long native_object, float sx, float sy,
401ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
402ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
403678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
404678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getScale(sx, sy, px, py));
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
406ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
408ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4097fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreScale(long native_object, float sx, float sy) {
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
411678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
412678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getScale(sx, sy));
413ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
414ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4177fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreRotate(long native_object, float degrees,
418ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
420678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
421678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getRotate(degrees, px, py));
422ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
423ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
424ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
425ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4267fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreRotate(long native_object, float degrees) {
427ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
428678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
429ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
430678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            double rad = Math.toRadians(degrees);
431678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            float sin = (float) Math.sin(rad);
432678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            float cos = (float) Math.cos(rad);
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
434678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getRotate(sin, cos));
435678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        }
436ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
437ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4397fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreSkew(long native_object, float kx, float ky,
440ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
442678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
443678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getSkew(kx, ky, px, py));
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
445ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
446ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
447ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4487fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreSkew(long native_object, float kx, float ky) {
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
450678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
451678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getSkew(kx, ky));
452ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
453ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4567fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreConcat(long native_object, long other_matrix) {
457ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
459678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null && other != null) {
460678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(other.mValues);
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
462ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
464ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4657fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostTranslate(long native_object, float dx, float dy) {
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
467678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
468678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getTranslate(dx, dy));
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
470ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
472ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4737fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostScale(long native_object, float sx, float sy,
474ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
476678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
477678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getScale(sx, sy, px, py));
478ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
479ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
480ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
481ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4827fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostScale(long native_object, float sx, float sy) {
483ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
484678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
485678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getScale(sx, sy));
486ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
487ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
488ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
489ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4907fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostRotate(long native_object, float degrees,
491ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
493678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
494678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getRotate(degrees, px, py));
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
496ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
497ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
498ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4997fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostRotate(long native_object, float degrees) {
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
501678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
502678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getRotate(degrees));
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
504ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5077fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostSkew(long native_object, float kx, float ky,
508ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
509ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
510678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
511678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getSkew(kx, ky, px, py));
512ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
513ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
514ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
515ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5167fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostSkew(long native_object, float kx, float ky) {
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
518678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
519678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getSkew(kx, ky));
520ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
521ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
522ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
523ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5247fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostConcat(long native_object, long other_matrix) {
525ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
526ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
527678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null && other != null) {
528678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(other.mValues);
529ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
530ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
531ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
532ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5337fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nSetRectToRect(long native_object, RectF src,
534ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            RectF dst, int stf) {
535ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
536ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
537ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
538ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
539ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (src.isEmpty()) {
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            reset(d.mValues);
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
543ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (dst.isEmpty()) {
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski               = d.mValues[6] = d.mValues[7] = 0;
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[8] = 1;
549ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
550ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float    tx, sx = dst.width() / src.width();
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float    ty, sy = dst.height() / src.height();
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            boolean  xLarger = false;
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (stf != ScaleToFit.FILL.nativeInt) {
555ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (sx > sy) {
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    xLarger = true;
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    sx = sy;
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    sy = sx;
560ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
561ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            tx = dst.left - src.left * sx;
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            ty = dst.top - src.top * sy;
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
566ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                float diff;
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (xLarger) {
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = dst.width() - src.width() * sy;
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = dst.height() - src.height() * sy;
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (stf == ScaleToFit.CENTER.nativeInt) {
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = diff / 2;
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (xLarger) {
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    tx += diff;
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    ty += diff;
582ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[0] = sx;
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[4] = sy;
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[2] = tx;
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[5] = ty;
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // shared cleanup
593ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
595ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5987fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nSetPolyToPoly(long native_object, float[] src, int srcIndex,
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float[] dst, int dstIndex, int pointCount) {
600ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME
601ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Matrix.setPolyToPoly is not supported.",
603ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null, null /*data*/);
604ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return false;
605ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
606ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
607ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6087fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nInvert(long native_object, long inverse) {
609ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
610ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
611ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
612ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
613ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
614ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
615ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (inv_mtx == null) {
616ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
617ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
618ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
619ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
620ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            AffineTransform affineTransform = d.getAffineTransform();
621ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            AffineTransform inverseTransform = affineTransform.createInverse();
6229a92f1849a1bcb593965a6ff1270ac8273ff259eDiego Perez            setValues(inverseTransform, inv_mtx.mValues);
623ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
624ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
625ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } catch (NoninvertibleTransformException e) {
626ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
627ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
628ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
629ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
630ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6317fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nMapPoints(long native_object, float[] dst, int dstIndex,
632ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float[] src, int srcIndex, int ptCount, boolean isPts) {
633ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
634ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
635ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
636ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
637ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
638ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (isPts) {
639ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
640ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
641ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
642ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
643ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
644ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
645ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6467fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nMapRect(long native_object, RectF dst, RectF src) {
647ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
648ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
649ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
650ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
651ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
652ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return d.mapRect(dst, src);
653ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
654ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
655ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6567fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static float nMapRadius(long native_object, float radius) {
657ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
658ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
659ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0.f;
660ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
661ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
662ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] src = new float[] { radius, 0.f, 0.f, radius };
663ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mapVectors(src, 0, src, 0, 2);
664ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
6652460c57a7ac1c2a491a62d0321ac24d9f6bd4fdaNeil Fuller        float l1 = (float) Math.hypot(src[0], src[1]);
6662460c57a7ac1c2a491a62d0321ac24d9f6bd4fdaNeil Fuller        float l2 = (float) Math.hypot(src[2], src[3]);
667ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (float) Math.sqrt(l1 * l2);
668ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
669ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
670ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6717fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nGetValues(long native_object, float[] values) {
672ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
673ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
674ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
675ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
676ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
677e5581b5c1972fb7b23fddceb2027084bf06cb2fbDeepanshu Gupta        System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE);
678ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
679ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
680ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6817fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetValues(long native_object, float[] values) {
682ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
683ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
684ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
685ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
687ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
688ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
689ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
690ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6917fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nEquals(long native_a, long native_b) {
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate a = sManager.getDelegate(native_a);
693ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a == null) {
694ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
695ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
696ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
697ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate b = sManager.getDelegate(native_b);
698ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (b == null) {
699ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
700ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
701ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
702ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
703ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (a.mValues[i] != b.mValues[i]) {
704ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return false;
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
710ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
711ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
7127fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static long nGetNativeFinalizer() {
7137fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        synchronized (Matrix_Delegate.class) {
7147fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            if (sFinalizer == -1) {
7157fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
7167fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            }
7177fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        }
7187fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        return sFinalizer;
719ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
720ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
721ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Private helper methods ----
722ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
723ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
724ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the AffineTransform constructor takes the value in a different order
725ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // for a matrix [ 0 1 2 ]
726ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        //              [ 3 4 5 ]
727ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the order is 0, 3, 1, 4, 2, 5...
728ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new AffineTransform(
729ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                matrix[0], matrix[3], matrix[1],
730ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                matrix[4], matrix[2], matrix[5]);
731ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
732ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
733ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
734ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Reset a matrix to the identity
735ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
736ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private static void reset(float[] mtx) {
737ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
738ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int j = 0; j < 3; j++, k++) {
739ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mtx[k] = ((i==j) ? 1 : 0);
740ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
741ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
742ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
743ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
744ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
745ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kIdentity_Mask      = 0;
746ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
747ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
748ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
749ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
750ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kRectStaysRect_Mask = 0x10;
751ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
752ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kUnknown_Mask       = 0x80;
753ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
754ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
755ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAllMasks           = kTranslate_Mask |
756ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kScale_Mask |
757ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kAffine_Mask |
758ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kPerspective_Mask |
759ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kRectStaysRect_Mask;
760ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
761ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // these guys align with the masks, so we can compute a mask from a variable 0/1
762ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
763ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kTranslate_Shift = 0;
764ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
765ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kScale_Shift = 1;
766ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
767ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAffine_Shift = 2;
768ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
769ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kPerspective_Shift = 3;
770ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kRectStaysRect_Shift = 4;
771ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
772ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private int computeTypeMask() {
773ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int mask = 0;
774ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
775ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
776ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kPerspective_Mask;
777ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
778ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
779ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mValues[2] != 0. || mValues[5] != 0.) {
780ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kTranslate_Mask;
781ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
782ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
783ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m00 = mValues[0];
784ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m01 = mValues[1];
785ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m10 = mValues[3];
786ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m11 = mValues[4];
787ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
788ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (m01 != 0. || m10 != 0.) {
789ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kAffine_Mask;
790ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
791ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
792ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (m00 != 1. || m11 != 1.) {
793ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kScale_Mask;
794ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
795ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
796ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if ((mask & kPerspective_Mask) == 0) {
797ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // map non-zero to 1
798ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im00 = m00 != 0 ? 1 : 0;
799ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im01 = m01 != 0 ? 1 : 0;
800ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im10 = m10 != 0 ? 1 : 0;
801ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im11 = m11 != 0 ? 1 : 0;
802ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
803ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // record if the (p)rimary and (s)econdary diagonals are all 0 or
804ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // all non-zero (answer is 0 or 1)
805ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
806ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int dp1 = im00 & im11;        // true if both are 1
807ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
808ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int ds1 = im01 & im10;        // true if both are 1
809ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
810ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // return 1 if primary is 1 and secondary is 0 or
811ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // primary is 0 and secondary is 1
812ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
813ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
814ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
815ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mask;
816ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
817ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
818ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Matrix_Delegate() {
819ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset();
820ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
821ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
822ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Matrix_Delegate(float[] values) {
823ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
824ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
825ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
826ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
827ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Adds the given transformation to the current Matrix
828ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does this = this*matrix
829ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param matrix
830ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
831ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void postTransform(float[] matrix) {
832ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
833ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, mValues, matrix);
834ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mValues = tmp;
835ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
836ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
837ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
838ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Adds the given transformation to the current Matrix
839ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does this = matrix*this
840ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param matrix
841ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
842ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void preTransform(float[] matrix) {
843ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
844ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, matrix, mValues);
845ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mValues = tmp;
846ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
847ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
848ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
849ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Apply this matrix to the array of 2D points specified by src, and write
850ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * the transformed points into the array of points specified by dst. The
851ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * two arrays represent their "points" as pairs of floats [x, y].
852ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      *
853ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param dst   The array of dst points (x,y pairs)
854ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param dstIndex The index of the first [x,y] pair of dst floats
855ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param src   The array of src points (x,y pairs)
856ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param srcIndex The index of the first [x,y] pair of src floats
857ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param pointCount The number of points (x,y pairs) to transform
858ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      */
859ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
860ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
861ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                           int pointCount) {
862ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         final int count = pointCount * 2;
863ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
864ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         float[] tmpDest = dst;
865ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         boolean inPlace = dst == src;
866ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (inPlace) {
867ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest = new float[dstIndex + count];
868ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
869ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
870ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         for (int i = 0 ; i < count ; i += 2) {
871ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // just in case we are doing in place, we better put this in temp vars
872ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float x = mValues[0] * src[i + srcIndex] +
873ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[1] * src[i + srcIndex + 1] +
874ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[2];
875ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float y = mValues[3] * src[i + srcIndex] +
876ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[4] * src[i + srcIndex + 1] +
877ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[5];
878ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
879ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest[i + dstIndex]     = x;
880ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest[i + dstIndex + 1] = y;
881ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
882ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
883ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (inPlace) {
884ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
885ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
886ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
887ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
888ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     /**
889ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * Apply this matrix to the array of 2D points, and write the transformed
890ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * points back into the array
891ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      *
892ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
893ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      */
894ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
895ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapPoints(float[] pts) {
896ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         mapPoints(pts, 0, pts, 0, pts.length >> 1);
897ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
898ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
899ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
900ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (hasPerspective()) {
901ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // transform the (0,0) point
902ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float[] origin = new float[] { 0.f, 0.f};
903ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             mapPoints(origin);
904ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
905ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // translate the vector data as points
906ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
907ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
908ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // then substract the transformed origin.
909ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             final int count = ptCount * 2;
910ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             for (int i = 0 ; i < count ; i += 2) {
911ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
912ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
913ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             }
914ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         } else {
915ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // make a copy of the matrix
916ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             Matrix_Delegate copy = new Matrix_Delegate(mValues);
917ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
918ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // remove the translation
919ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             setTranslate(copy.mValues, 0, 0);
920ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
921ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // map the content as points.
922ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
923ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
924ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
925ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
926ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
927ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * multiply two matrices and store them in a 3rd.
928ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does dest = a*b
929ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * dest cannot be the same as a or b.
930ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
931ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
932ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // first row
933ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
934ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
935ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
936ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
937ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // 2nd row
938ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
939ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
940ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
941ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
942ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // 3rd row
943ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
944ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
945ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
946ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
947ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
948ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
949ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a matrix that represents a given translate
950ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param dx
951ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param dy
952ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return
953ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
954ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getTranslate(float dx, float dy) {
955ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setTranslate(new float[9], dx, dy);
956ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
957ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
958ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
959ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = 1;
960ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = 0;
961ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = dx;
962ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = 0;
963ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = 1;
964ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = dy;
965ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = 0;
966ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = 0;
967ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = 1;
968ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dest;
969ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
970ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
971ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getScale(float sx, float sy) {
972ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
973ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
974ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
975ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
976ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a matrix that represents the given scale info.
977ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param sx
978ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param sy
979ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param px
980ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param py
981ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
982ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
983ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
984ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
985ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
986ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
987ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
988ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate tmp so that the pivot is in 0,0
989ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
990ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
991ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // scale into tmp2
992ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, getScale(sx, sy));
993ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
994ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
995ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
996ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
997ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
998ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
999ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1000ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1001ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float degrees) {
1002ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1003ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1004ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1005ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1006ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getRotate(sin, cos);
1007ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1008ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1009ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float sin, float cos) {
1010ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setRotate(new float[9], sin, cos);
1011ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1012ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1013ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setRotate(float[] dest, float degrees) {
1014ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1015ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1016ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1017ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1018ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setRotate(dest, sin, cos);
1019ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1020ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1021ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
1022ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = cos;
1023ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = -sin;
1024ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = 0;
1025ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = sin;
1026ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = cos;
1027ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = 0;
1028ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = 0;
1029ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = 0;
1030ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = 1;
1031ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dest;
1032ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1033ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1034ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float degrees, float px, float py) {
1035ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
1036ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
1037ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1038ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
1039ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1040ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
1041ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1042ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1043ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // rotate into tmp2
1044ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1045ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1046ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1047ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, getRotate(sin, cos));
1048ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1049ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1050ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1051ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1052ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1053ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1054ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1055ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getSkew(float kx, float ky) {
1056ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
1057ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1058ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1059ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
1060ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
1061ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
1062ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1063ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
1064ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1065ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
1066ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1067ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1068ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // skew into tmp2
1069ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
1070ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1071ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1072ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1073ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1074ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1075ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
1076