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
121ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static float[] makeValues(AffineTransform matrix) {
122ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] values = new float[MATRIX_SIZE];
123ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[0] = (float) matrix.getScaleX();
124ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[1] = (float) matrix.getShearX();
125ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[2] = (float) matrix.getTranslateX();
126ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[3] = (float) matrix.getShearY();
127ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[4] = (float) matrix.getScaleY();
128ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[5] = (float) matrix.getTranslateY();
129ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[6] = 0.f;
130ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[7] = 0.f;
131ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[8] = 1.f;
132ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
133ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return values;
134ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
135ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
136ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static Matrix_Delegate make(AffineTransform matrix) {
137ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new Matrix_Delegate(makeValues(matrix));
138ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
139ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
140ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean mapRect(RectF dst, RectF src) {
141ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // array with 4 corners
142ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] corners = new float[] {
143ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.left, src.top,
144ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.right, src.top,
145ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.right, src.bottom,
146ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.left, src.bottom,
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        };
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // apply the transform to them.
150ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mapPoints(corners);
151ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
153ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
154ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
158ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
159ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
160ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
161ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
162ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
163ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
164ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
165ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns an {@link AffineTransform} matching the matrix.
166ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
167ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public AffineTransform getAffineTransform() {
168ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getAffineTransform(mValues);
169ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
170ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
171ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean hasPerspective() {
172ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
176ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
177ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- native methods ----
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
1807fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static long nCreate(long native_src_or_zero) {
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the delegate
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate newDelegate = new Matrix_Delegate();
183ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // copy from values if needed.
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (native_src_or_zero > 0) {
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (oldDelegate != null) {
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                System.arraycopy(
189ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        oldDelegate.mValues, 0,
190ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        newDelegate.mValues, 0,
191ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        MATRIX_SIZE);
192ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
193ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
194ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
195ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return sManager.addNewDelegate(newDelegate);
196ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
197ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
198ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
1997fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nIsIdentity(long native_object) {
200ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
201ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
202ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
203ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
204ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return d.isIdentity();
206ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
207ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
208ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2097fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nIsAffine(long native_object) {
210017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        Matrix_Delegate d = sManager.getDelegate(native_object);
211017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        if (d == null) {
212017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta            return true;
213017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        }
214017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta
215017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta        return (d.computeTypeMask() & kPerspective_Mask) == 0;
216017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta    }
217017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta
218017c06241e22e290406ae53402f96e3e2a9597b8Deepanshu Gupta    @LayoutlibDelegate
2197fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nRectStaysRect(long native_object) {
220ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
221ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
222ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
226ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
227ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
228ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2297fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nReset(long native_object) {
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
232ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset(d.mValues);
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2397fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSet(long native_object, long other) {
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
241ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
242ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
244ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
245ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate src = sManager.getDelegate(other);
246ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (src == null) {
247ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
248ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
249ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
251ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
252ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2547fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetTranslate(long native_object, float dx, float dy) {
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(d.mValues, dx, dy);
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2647fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetScale(long native_object, float sx, float sy,
265ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
266ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
269ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
270ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getScale(sx, sy, px, py);
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2757fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetScale(long native_object, float sx, float sy) {
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
280ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[0] = sx;
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[1] = 0;
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[2] = 0;
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[3] = 0;
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[4] = sy;
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[5] = 0;
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[6] = 0;
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[7] = 0;
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
2937fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetRotate(long native_object, float degrees, float px, float py) {
294ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
299ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getRotate(degrees, px, py);
300ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
301ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
302ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3037fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetRotate(long native_object, float degrees) {
304ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
305ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
306ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
307ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
308ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
309ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setRotate(d.mValues, degrees);
310ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
311ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
312ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3137fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue,
314ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
315ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
316ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
317ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
318ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
319ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
320ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
323ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(d.mValues, -px, -py);
324ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
325ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // scale
326ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getRotate(sinValue, cosValue));
327ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot
328ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getTranslate(px, py));
329ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
330ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
331ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3327fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue) {
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
335ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setRotate(d.mValues, sinValue, cosValue);
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3427fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSkew(long native_object, float kx, float ky,
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getSkew(kx, ky, px, py);
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3537fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetSkew(long native_object, float kx, float ky) {
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
358ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[0] = 1;
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[1] = kx;
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[2] = -0;
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[3] = ky;
363ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[4] = 1;
364ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[5] = 0;
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[6] = 0;
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[7] = 0;
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3717fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetConcat(long native_object, long a, long b) {
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a == native_object) {
3737fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            nPreConcat(native_object, b);
374678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            return;
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else if (b == native_object) {
3767fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            nPostConcat(native_object, a);
377678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            return;
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate a_mtx = sManager.getDelegate(a);
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate b_mtx = sManager.getDelegate(b);
383678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null && a_mtx != null && b_mtx != null) {
384678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
385ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
386ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
387ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
388ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3897fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreTranslate(long native_object, float dx, float dy) {
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
391678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
392678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getTranslate(dx, dy));
393ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
394ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
395ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
396ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
3977fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreScale(long native_object, float sx, float sy,
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
400678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
401678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getScale(sx, sy, px, py));
402ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
403ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
404ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4067fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreScale(long native_object, float sx, float sy) {
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
408678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
409678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getScale(sx, sy));
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
411ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
412ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
413ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4147fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreRotate(long native_object, float degrees,
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
417678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
418678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getRotate(degrees, px, py));
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
420ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
421ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
422ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4237fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreRotate(long native_object, float degrees) {
424ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
425678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
426ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
427678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            double rad = Math.toRadians(degrees);
428678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            float sin = (float) Math.sin(rad);
429678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            float cos = (float) Math.cos(rad);
430ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
431678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getRotate(sin, cos));
432678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        }
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
434ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
435ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4367fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreSkew(long native_object, float kx, float ky,
437ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
439678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
440678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getSkew(kx, ky, px, py));
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
442ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
443ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4457fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreSkew(long native_object, float kx, float ky) {
446ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
447678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
448678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(getSkew(kx, ky));
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
450ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
451ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
452ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4537fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPreConcat(long native_object, long other_matrix) {
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
456678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null && other != null) {
457678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.preTransform(other.mValues);
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
459ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
460ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4627fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostTranslate(long native_object, float dx, float dy) {
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
464678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
465678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getTranslate(dx, dy));
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
467ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
468ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4707fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostScale(long native_object, float sx, float sy,
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
472ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
473678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
474678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getScale(sx, sy, px, py));
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
476ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
477ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
478ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4797fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostScale(long native_object, float sx, float sy) {
480ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
481678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
482678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getScale(sx, sy));
483ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
484ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
485ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
486ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4877fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostRotate(long native_object, float degrees,
488ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
489ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
490678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
491678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getRotate(degrees, px, py));
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
493ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
494ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
4967fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostRotate(long native_object, float degrees) {
497ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
498678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
499678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getRotate(degrees));
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
501ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
502ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5047fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostSkew(long native_object, float kx, float ky,
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
507678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
508678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getSkew(kx, ky, px, py));
509ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
510ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
511ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
512ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5137fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostSkew(long native_object, float kx, float ky) {
514ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
515678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null) {
516678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(getSkew(kx, ky));
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
518ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
519ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
520ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5217fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nPostConcat(long native_object, long other_matrix) {
522ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
523ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
524678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta        if (d != null && other != null) {
525678cd7fa884002bc6b746fa543baf41db323a453Deepanshu Gupta            d.postTransform(other.mValues);
526ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
527ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
528ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
529ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5307fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nSetRectToRect(long native_object, RectF src,
531ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            RectF dst, int stf) {
532ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
533ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
534ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
535ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
536ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
537ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (src.isEmpty()) {
538ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            reset(d.mValues);
539ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (dst.isEmpty()) {
543ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski               = d.mValues[6] = d.mValues[7] = 0;
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[8] = 1;
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float    tx, sx = dst.width() / src.width();
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float    ty, sy = dst.height() / src.height();
549ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            boolean  xLarger = false;
550ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (stf != ScaleToFit.FILL.nativeInt) {
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (sx > sy) {
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    xLarger = true;
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    sx = sy;
555ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    sy = sx;
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
560ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            tx = dst.left - src.left * sx;
561ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            ty = dst.top - src.top * sy;
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                float diff;
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (xLarger) {
566ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = dst.width() - src.width() * sy;
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = dst.height() - src.height() * sy;
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (stf == ScaleToFit.CENTER.nativeInt) {
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = diff / 2;
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (xLarger) {
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    tx += diff;
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    ty += diff;
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
582ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[0] = sx;
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[4] = sy;
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[2] = tx;
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[5] = ty;
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // shared cleanup
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
593ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
5957fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nSetPolyToPoly(long native_object, float[] src, int srcIndex,
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float[] dst, int dstIndex, int pointCount) {
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME
598ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Matrix.setPolyToPoly is not supported.",
600ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null, null /*data*/);
601ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return false;
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
603ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
604ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6057fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nInvert(long native_object, long inverse) {
606ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
607ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
608ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
609ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
610ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
611ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
612ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (inv_mtx == null) {
613ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
614ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
615ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
616ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
617ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            AffineTransform affineTransform = d.getAffineTransform();
618ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            AffineTransform inverseTransform = affineTransform.createInverse();
619ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
620ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
621ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
622ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
623ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
624ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
625ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
626ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
627ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } catch (NoninvertibleTransformException e) {
628ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
629ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
630ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
631ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
632ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6337fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nMapPoints(long native_object, float[] dst, int dstIndex,
634ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float[] src, int srcIndex, int ptCount, boolean isPts) {
635ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
636ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
637ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
638ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
639ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
640ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (isPts) {
641ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
642ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
643ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
644ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
645ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
646ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
647ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6487fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nMapRect(long native_object, RectF dst, RectF src) {
649ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
650ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
651ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
652ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
653ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
654ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return d.mapRect(dst, src);
655ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
656ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
657ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6587fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static float nMapRadius(long native_object, float radius) {
659ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
660ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
661ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0.f;
662ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
663ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
664ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] src = new float[] { radius, 0.f, 0.f, radius };
665ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mapVectors(src, 0, src, 0, 2);
666ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
6672460c57a7ac1c2a491a62d0321ac24d9f6bd4fdaNeil Fuller        float l1 = (float) Math.hypot(src[0], src[1]);
6682460c57a7ac1c2a491a62d0321ac24d9f6bd4fdaNeil Fuller        float l2 = (float) Math.hypot(src[2], src[3]);
669ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (float) Math.sqrt(l1 * l2);
670ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
671ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
672ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6737fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nGetValues(long native_object, float[] values) {
674ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
675ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
676ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
677ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
678ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
679e5581b5c1972fb7b23fddceb2027084bf06cb2fbDeepanshu Gupta        System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE);
680ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
681ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
682ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6837fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nSetValues(long native_object, float[] values) {
684ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
685ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
687ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
688ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
689ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
690ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
691ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
6937fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static boolean nEquals(long native_a, long native_b) {
694ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate a = sManager.getDelegate(native_a);
695ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a == null) {
696ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
697ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
698ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
699ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate b = sManager.getDelegate(native_b);
700ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (b == null) {
701ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
702ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
703ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
704ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (a.mValues[i] != b.mValues[i]) {
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return false;
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
710ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
711ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
712ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
713ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
7147fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static long nGetNativeFinalizer() {
7157fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        synchronized (Matrix_Delegate.class) {
7167fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            if (sFinalizer == -1) {
7177fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
7187fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            }
7197fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        }
7207fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        return sFinalizer;
721ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
722ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
723ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Private helper methods ----
724ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
725ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
726ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the AffineTransform constructor takes the value in a different order
727ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // for a matrix [ 0 1 2 ]
728ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        //              [ 3 4 5 ]
729ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the order is 0, 3, 1, 4, 2, 5...
730ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new AffineTransform(
731ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                matrix[0], matrix[3], matrix[1],
732ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                matrix[4], matrix[2], matrix[5]);
733ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
734ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
735ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
736ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Reset a matrix to the identity
737ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
738ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private static void reset(float[] mtx) {
739ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
740ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int j = 0; j < 3; j++, k++) {
741ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mtx[k] = ((i==j) ? 1 : 0);
742ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
743ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
744ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
745ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
746ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
747ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kIdentity_Mask      = 0;
748ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
749ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
750ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
751ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
752ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kRectStaysRect_Mask = 0x10;
753ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
754ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kUnknown_Mask       = 0x80;
755ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
756ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
757ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAllMasks           = kTranslate_Mask |
758ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kScale_Mask |
759ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kAffine_Mask |
760ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kPerspective_Mask |
761ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kRectStaysRect_Mask;
762ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
763ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // these guys align with the masks, so we can compute a mask from a variable 0/1
764ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
765ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kTranslate_Shift = 0;
766ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
767ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kScale_Shift = 1;
768ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
769ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAffine_Shift = 2;
770ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
771ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kPerspective_Shift = 3;
772ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kRectStaysRect_Shift = 4;
773ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
774ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private int computeTypeMask() {
775ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int mask = 0;
776ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
777ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
778ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kPerspective_Mask;
779ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
780ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
781ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mValues[2] != 0. || mValues[5] != 0.) {
782ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kTranslate_Mask;
783ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
784ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
785ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m00 = mValues[0];
786ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m01 = mValues[1];
787ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m10 = mValues[3];
788ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m11 = mValues[4];
789ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
790ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (m01 != 0. || m10 != 0.) {
791ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kAffine_Mask;
792ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
793ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
794ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (m00 != 1. || m11 != 1.) {
795ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kScale_Mask;
796ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
797ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
798ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if ((mask & kPerspective_Mask) == 0) {
799ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // map non-zero to 1
800ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im00 = m00 != 0 ? 1 : 0;
801ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im01 = m01 != 0 ? 1 : 0;
802ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im10 = m10 != 0 ? 1 : 0;
803ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im11 = m11 != 0 ? 1 : 0;
804ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
805ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // record if the (p)rimary and (s)econdary diagonals are all 0 or
806ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // all non-zero (answer is 0 or 1)
807ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
808ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int dp1 = im00 & im11;        // true if both are 1
809ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
810ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int ds1 = im01 & im10;        // true if both are 1
811ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
812ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // return 1 if primary is 1 and secondary is 0 or
813ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // primary is 0 and secondary is 1
814ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
815ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
816ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
817ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mask;
818ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
819ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
820ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Matrix_Delegate() {
821ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset();
822ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
823ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
824ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Matrix_Delegate(float[] values) {
825ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
826ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
827ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
828ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
829ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Adds the given transformation to the current Matrix
830ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does this = this*matrix
831ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param matrix
832ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
833ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void postTransform(float[] matrix) {
834ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
835ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, mValues, matrix);
836ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mValues = tmp;
837ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
838ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
839ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
840ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Adds the given transformation to the current Matrix
841ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does this = matrix*this
842ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param matrix
843ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
844ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void preTransform(float[] matrix) {
845ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
846ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, matrix, mValues);
847ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mValues = tmp;
848ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
849ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
850ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
851ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Apply this matrix to the array of 2D points specified by src, and write
852ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * the transformed points into the array of points specified by dst. The
853ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * two arrays represent their "points" as pairs of floats [x, y].
854ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      *
855ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param dst   The array of dst points (x,y pairs)
856ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param dstIndex The index of the first [x,y] pair of dst floats
857ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param src   The array of src points (x,y pairs)
858ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param srcIndex The index of the first [x,y] pair of src floats
859ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param pointCount The number of points (x,y pairs) to transform
860ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      */
861ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
862ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
863ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                           int pointCount) {
864ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         final int count = pointCount * 2;
865ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
866ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         float[] tmpDest = dst;
867ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         boolean inPlace = dst == src;
868ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (inPlace) {
869ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest = new float[dstIndex + count];
870ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
871ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
872ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         for (int i = 0 ; i < count ; i += 2) {
873ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // just in case we are doing in place, we better put this in temp vars
874ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float x = mValues[0] * src[i + srcIndex] +
875ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[1] * src[i + srcIndex + 1] +
876ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[2];
877ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float y = mValues[3] * src[i + srcIndex] +
878ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[4] * src[i + srcIndex + 1] +
879ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[5];
880ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
881ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest[i + dstIndex]     = x;
882ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest[i + dstIndex + 1] = y;
883ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
884ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
885ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (inPlace) {
886ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
887ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
888ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
889ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
890ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     /**
891ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * Apply this matrix to the array of 2D points, and write the transformed
892ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * points back into the array
893ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      *
894ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
895ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      */
896ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
897ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapPoints(float[] pts) {
898ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         mapPoints(pts, 0, pts, 0, pts.length >> 1);
899ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
900ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
901ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
902ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (hasPerspective()) {
903ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // transform the (0,0) point
904ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float[] origin = new float[] { 0.f, 0.f};
905ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             mapPoints(origin);
906ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
907ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // translate the vector data as points
908ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
909ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
910ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // then substract the transformed origin.
911ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             final int count = ptCount * 2;
912ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             for (int i = 0 ; i < count ; i += 2) {
913ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
914ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
915ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             }
916ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         } else {
917ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // make a copy of the matrix
918ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             Matrix_Delegate copy = new Matrix_Delegate(mValues);
919ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
920ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // remove the translation
921ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             setTranslate(copy.mValues, 0, 0);
922ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
923ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // map the content as points.
924ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
925ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
926ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
927ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
928ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
929ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * multiply two matrices and store them in a 3rd.
930ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does dest = a*b
931ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * dest cannot be the same as a or b.
932ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
933ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
934ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // first row
935ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
936ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
937ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
938ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
939ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // 2nd row
940ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
941ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
942ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
943ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
944ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // 3rd row
945ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
946ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
947ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
948ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
949ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
950ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
951ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a matrix that represents a given translate
952ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param dx
953ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param dy
954ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return
955ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
956ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getTranslate(float dx, float dy) {
957ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setTranslate(new float[9], dx, dy);
958ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
959ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
960ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
961ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = 1;
962ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = 0;
963ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = dx;
964ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = 0;
965ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = 1;
966ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = dy;
967ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = 0;
968ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = 0;
969ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = 1;
970ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dest;
971ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
972ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
973ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getScale(float sx, float sy) {
974ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
975ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
976ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
977ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
978ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a matrix that represents the given scale info.
979ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param sx
980ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param sy
981ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param px
982ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param py
983ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
984ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
985ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
986ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
987ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
988ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
989ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
990ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate tmp so that the pivot is in 0,0
991ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
992ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
993ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // scale into tmp2
994ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, getScale(sx, sy));
995ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
996ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
997ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
998ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
999ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1000ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1001ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1002ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1003ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float degrees) {
1004ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1005ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1006ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1007ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1008ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getRotate(sin, cos);
1009ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1010ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1011ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float sin, float cos) {
1012ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setRotate(new float[9], sin, cos);
1013ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1014ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1015ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setRotate(float[] dest, float degrees) {
1016ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1017ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1018ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1019ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1020ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setRotate(dest, sin, cos);
1021ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1022ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1023ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
1024ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = cos;
1025ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = -sin;
1026ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = 0;
1027ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = sin;
1028ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = cos;
1029ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = 0;
1030ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = 0;
1031ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = 0;
1032ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = 1;
1033ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dest;
1034ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1035ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1036ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float degrees, float px, float py) {
1037ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
1038ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
1039ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1040ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
1041ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1042ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
1043ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1044ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1045ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // rotate into tmp2
1046ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1047ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1048ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1049ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, getRotate(sin, cos));
1050ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1051ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1052ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1053ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1054ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1055ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1056ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1057ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getSkew(float kx, float ky) {
1058ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
1059ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1060ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1061ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
1062ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
1063ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
1064ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1065ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
1066ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1067ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
1068ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1069ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1070ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // skew into tmp2
1071ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
1072ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1073ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1074ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1075ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1076ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1077ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
1078