Matrix_Delegate.java revision ec4118922fa844ef31b73d16adc76f4da4c6c8e6
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
30ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/**
31ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Delegate implementing the native methods of android.graphics.Matrix
32ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
33ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
34ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * by calls to methods of the same name in this delegate class.
35ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
36ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
37ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
38ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * it and the original Matrix class.
39ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
40ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * @see DelegateManager
41ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
42ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
43ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipublic final class Matrix_Delegate {
44ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
45ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int MATRIX_SIZE = 9;
46ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
47ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate manager ----
48ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private static final DelegateManager<Matrix_Delegate> sManager =
49ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
50ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
51ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate data ----
52ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private float mValues[] = new float[MATRIX_SIZE];
53ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
54ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Public Helper methods ----
55ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
56ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    public static Matrix_Delegate getDelegate(long native_instance) {
57ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return sManager.getDelegate(native_instance);
58ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
59ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
60ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
61ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns an {@link AffineTransform} matching the given Matrix.
62ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
63ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static AffineTransform getAffineTransform(Matrix m) {
64ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
65ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
66ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
67ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
68ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
69ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.getAffineTransform();
70ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
71ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
72ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static boolean hasPerspective(Matrix m) {
73ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
74ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
75ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
76ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
77ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
78ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.hasPerspective();
79ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
80ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
81ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
82ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Sets the content of the matrix with the content of another matrix.
83ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
84ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void set(Matrix_Delegate matrix) {
85ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
86ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
87ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
88ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
89ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Sets the content of the matrix with the content of another matrix represented as an array
90ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * of values.
91ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
92ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void set(float[] values) {
93ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
94ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
95ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
96ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
97ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Resets the matrix to be the identity matrix.
98ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
99ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void reset() {
100ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset(mValues);
101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
103ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
104ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns whether or not the matrix is identity.
105ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
106ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean isIdentity() {
107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int j = 0; j < 3; j++, k++) {
109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (mValues[k] != ((i==j) ? 1 : 0)) {
110ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    return false;
111ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
112ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
113ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
114ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
115ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
116ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
117ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
118ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static float[] makeValues(AffineTransform matrix) {
119ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] values = new float[MATRIX_SIZE];
120ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[0] = (float) matrix.getScaleX();
121ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[1] = (float) matrix.getShearX();
122ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[2] = (float) matrix.getTranslateX();
123ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[3] = (float) matrix.getShearY();
124ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[4] = (float) matrix.getScaleY();
125ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[5] = (float) matrix.getTranslateY();
126ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[6] = 0.f;
127ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[7] = 0.f;
128ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        values[8] = 1.f;
129ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
130ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return values;
131ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
132ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
133ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static Matrix_Delegate make(AffineTransform matrix) {
134ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new Matrix_Delegate(makeValues(matrix));
135ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
136ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
137ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean mapRect(RectF dst, RectF src) {
138ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // array with 4 corners
139ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] corners = new float[] {
140ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.left, src.top,
141ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.right, src.top,
142ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.right, src.bottom,
143ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                src.left, src.bottom,
144ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        };
145ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
146ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // apply the transform to them.
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mapPoints(corners);
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
150ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
151ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
153ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
154ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
158ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
159ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
160ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
161ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
162ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns an {@link AffineTransform} matching the matrix.
163ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
164ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public AffineTransform getAffineTransform() {
165ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getAffineTransform(mValues);
166ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
167ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
168ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean hasPerspective() {
169ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
170ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
171ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
172ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- native methods ----
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
176ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
177ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static long native_create(long native_src_or_zero) {
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the delegate
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate newDelegate = new Matrix_Delegate();
180ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // copy from values if needed.
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (native_src_or_zero > 0) {
183ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (oldDelegate != null) {
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                System.arraycopy(
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        oldDelegate.mValues, 0,
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        newDelegate.mValues, 0,
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        MATRIX_SIZE);
189ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
190ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
191ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
192ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return sManager.addNewDelegate(newDelegate);
193ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
194ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
195ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
196ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_isIdentity(long native_object) {
197ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
198ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
199ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
200ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
201ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
202ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return d.isIdentity();
203ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
204ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
206ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_rectStaysRect(long native_object) {
207ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
208ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
209ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
210ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
211ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
212ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
213ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
214ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
215ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
216ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_reset(long native_object) {
217ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
218ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
219ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
220ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
221ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
222ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset(d.mValues);
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
226ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_set(long native_object, long other) {
227ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
228ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
229ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
232ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate src = sManager.getDelegate(other);
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (src == null) {
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
239ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
241ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setTranslate(long native_object, float dx, float dy) {
242ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
244ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
245ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
246ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
247ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(d.mValues, dx, dy);
248ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
249ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
251ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy,
252ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getScale(sx, sy, px, py);
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
262ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy) {
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
264ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
265ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
266ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[0] = sx;
269ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[1] = 0;
270ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[2] = 0;
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[3] = 0;
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[4] = sy;
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[5] = 0;
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[6] = 0;
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[7] = 0;
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
280ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees, float px, float py) {
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getRotate(degrees, px, py);
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
290ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees) {
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
293ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
294ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setRotate(d.mValues, degrees);
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
299ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
300ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue,
301ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
302ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
303ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
304ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
305ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
306ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
307ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
308ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
309ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
310ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(d.mValues, -px, -py);
311ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
312ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // scale
313ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getRotate(sinValue, cosValue));
314ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot
315ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getTranslate(px, py));
316ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
317ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
318ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
319ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue) {
320ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
323ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
324ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
325ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setRotate(d.mValues, sinValue, cosValue);
326ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
327ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
328ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
329ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky,
330ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
331ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
332ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
335ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues = getSkew(kx, ky, px, py);
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
340ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky) {
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[0] = 1;
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[1] = kx;
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[2] = -0;
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[3] = ky;
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[4] = 1;
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[5] = 0;
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[6] = 0;
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[7] = 0;
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
358ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_setConcat(long native_object, long a, long b) {
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a == native_object) {
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return native_preConcat(native_object, b);
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else if (b == native_object) {
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return native_postConcat(native_object, a);
363ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
364ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate a_mtx = sManager.getDelegate(a);
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a_mtx == null) {
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
374ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate b_mtx = sManager.getDelegate(b);
376ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (b_mtx == null) {
377ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
384ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
385ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
386ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preTranslate(long native_object, float dx, float dy) {
387ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
388ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
389ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
391ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
392ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getTranslate(dx, dy));
393ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
394ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
395ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
396ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
397ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preScale(long native_object, float sx, float sy,
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
400ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
401ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
402ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
403ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
404ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getScale(sx, sy, px, py));
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
406ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
408ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
409ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preScale(long native_object, float sx, float sy) {
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
411ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
412ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
413ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
414ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getScale(sx, sy));
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
417ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
418ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
420ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preRotate(long native_object, float degrees,
421ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
422ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
423ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
424ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
425ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
426ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
427ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getRotate(degrees, px, py));
428ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
429ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
430ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
431ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
432ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preRotate(long native_object, float degrees) {
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
434ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
435ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
436ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
437ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
439ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
440ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
442ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getRotate(sin, cos));
443ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
445ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
446ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
447ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preSkew(long native_object, float kx, float ky,
448ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
450ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
451ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
452ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
453ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getSkew(kx, ky, px, py));
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
456ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
457ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
459ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preSkew(long native_object, float kx, float ky) {
460ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
462ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
464ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
465ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(getSkew(kx, ky));
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
467ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
468ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
470ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_preConcat(long native_object, long other_matrix) {
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
472ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
473ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
474ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
476ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
477ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (other == null) {
478ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
479ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
480ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
481ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.preTransform(other.mValues);
482ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
483ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
484ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
485ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
486ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postTranslate(long native_object, float dx, float dy) {
487ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
488ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
489ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
490ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
491ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getTranslate(dx, dy));
493ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
494ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
496ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
497ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postScale(long native_object, float sx, float sy,
498ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
499ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
501ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
502ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
504ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getScale(sx, sy, px, py));
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
507ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
508ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
509ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postScale(long native_object, float sx, float sy) {
510ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
511ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
512ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
513ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
514ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
515ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getScale(sx, sy));
516ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
518ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
519ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
520ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postRotate(long native_object, float degrees,
521ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
522ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
523ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
524ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
525ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
526ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
527ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getRotate(degrees, px, py));
528ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
529ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
530ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
531ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
532ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postRotate(long native_object, float degrees) {
533ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
534ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
535ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
536ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
537ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
538ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getRotate(degrees));
539ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
543ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postSkew(long native_object, float kx, float ky,
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float px, float py) {
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
549ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
550ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getSkew(kx, ky, px, py));
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
555ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postSkew(long native_object, float kx, float ky) {
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
560ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
561ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(getSkew(kx, ky));
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
566ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_postConcat(long native_object, long other_matrix) {
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (other == null) {
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.postTransform(other.mValues);
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
582ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_setRectToRect(long native_object, RectF src,
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            RectF dst, int stf) {
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (src.isEmpty()) {
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            reset(d.mValues);
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
593ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (dst.isEmpty()) {
595ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski               = d.mValues[6] = d.mValues[7] = 0;
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[8] = 1;
598ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float    tx, sx = dst.width() / src.width();
600ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float    ty, sy = dst.height() / src.height();
601ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            boolean  xLarger = false;
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
603ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (stf != ScaleToFit.FILL.nativeInt) {
604ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (sx > sy) {
605ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    xLarger = true;
606ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    sx = sy;
607ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
608ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    sy = sx;
609ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
610ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
611ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
612ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            tx = dst.left - src.left * sx;
613ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            ty = dst.top - src.top * sy;
614ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
615ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                float diff;
616ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
617ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (xLarger) {
618ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = dst.width() - src.width() * sy;
619ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
620ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = dst.height() - src.height() * sy;
621ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
622ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
623ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (stf == ScaleToFit.CENTER.nativeInt) {
624ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    diff = diff / 2;
625ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
626ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
627ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (xLarger) {
628ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    tx += diff;
629ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } else {
630ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    ty += diff;
631ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
632ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
633ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
634ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[0] = sx;
635ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[4] = sy;
636ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[2] = tx;
637ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[5] = ty;
638ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
639ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
640ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
641ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // shared cleanup
642ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mValues[8] = 1;
643ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
644ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
645ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
646ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
647ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_setPolyToPoly(long native_object, float[] src, int srcIndex,
648ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float[] dst, int dstIndex, int pointCount) {
649ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME
650ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
651ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Matrix.setPolyToPoly is not supported.",
652ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null, null /*data*/);
653ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return false;
654ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
655ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
656ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
657ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_invert(long native_object, int inverse) {
658ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
659ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
660ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
661ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
662ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
663ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
664ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (inv_mtx == null) {
665ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
666ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
667ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
668ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
669ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            AffineTransform affineTransform = d.getAffineTransform();
670ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            AffineTransform inverseTransform = affineTransform.createInverse();
671ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
672ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
673ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
674ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
675ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
676ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
677ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
678ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
679ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } catch (NoninvertibleTransformException e) {
680ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
681ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
682ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
683ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
684ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
685ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_mapPoints(long native_object, float[] dst, int dstIndex,
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float[] src, int srcIndex, int ptCount, boolean isPts) {
687ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
688ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
689ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
690ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
691ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (isPts) {
693ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
694ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
695ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
696ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
697ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
698ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
699ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
700ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_mapRect(long native_object, RectF dst, RectF src) {
701ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
702ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
703ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
704ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return d.mapRect(dst, src);
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
710ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static float native_mapRadius(long native_object, float radius) {
711ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
712ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
713ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0.f;
714ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
715ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
716ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] src = new float[] { radius, 0.f, 0.f, radius };
717ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        d.mapVectors(src, 0, src, 0, 2);
718ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
719ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float l1 = getPointLength(src, 0);
720ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float l2 = getPointLength(src, 2);
721ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
722ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (float) Math.sqrt(l1 * l2);
723ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
724ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
725ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
726ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_getValues(long native_object, float[] values) {
727ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
728ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
729ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
730ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
731ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
732ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
733ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
734ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
735ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
736ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void native_setValues(long native_object, float[] values) {
737ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
738ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (d == null) {
739ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
740ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
741ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
742ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
743ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
744ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
745ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
746ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean native_equals(long native_a, long native_b) {
747ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate a = sManager.getDelegate(native_a);
748ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (a == null) {
749ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
750ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
751ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
752ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Matrix_Delegate b = sManager.getDelegate(native_b);
753ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (b == null) {
754ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
755ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
756ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
757ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
758ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (a.mValues[i] != b.mValues[i]) {
759ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return false;
760ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
761ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
762ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
763ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
764ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
765ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
766ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
767ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void finalizer(long native_instance) {
768ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        sManager.removeJavaReferenceFor(native_instance);
769ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
770ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
771ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Private helper methods ----
772ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
773ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
774ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the AffineTransform constructor takes the value in a different order
775ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // for a matrix [ 0 1 2 ]
776ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        //              [ 3 4 5 ]
777ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the order is 0, 3, 1, 4, 2, 5...
778ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new AffineTransform(
779ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                matrix[0], matrix[3], matrix[1],
780ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                matrix[4], matrix[2], matrix[5]);
781ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
782ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
783ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
784ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Reset a matrix to the identity
785ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
786ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private static void reset(float[] mtx) {
787ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
788ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int j = 0; j < 3; j++, k++) {
789ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mtx[k] = ((i==j) ? 1 : 0);
790ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
791ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
792ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
793ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
794ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
795ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kIdentity_Mask      = 0;
796ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
797ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
798ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
799ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
800ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kRectStaysRect_Mask = 0x10;
801ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
802ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kUnknown_Mask       = 0x80;
803ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
804ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
805ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAllMasks           = kTranslate_Mask |
806ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kScale_Mask |
807ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kAffine_Mask |
808ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kPerspective_Mask |
809ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                                                   kRectStaysRect_Mask;
810ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
811ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // these guys align with the masks, so we can compute a mask from a variable 0/1
812ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
813ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kTranslate_Shift = 0;
814ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
815ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kScale_Shift = 1;
816ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
817ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kAffine_Shift = 2;
818ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @SuppressWarnings("unused")
819ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kPerspective_Shift = 3;
820ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final static int kRectStaysRect_Shift = 4;
821ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
822ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private int computeTypeMask() {
823ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int mask = 0;
824ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
825ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
826ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kPerspective_Mask;
827ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
828ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
829ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mValues[2] != 0. || mValues[5] != 0.) {
830ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kTranslate_Mask;
831ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
832ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
833ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m00 = mValues[0];
834ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m01 = mValues[1];
835ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m10 = mValues[3];
836ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float m11 = mValues[4];
837ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
838ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (m01 != 0. || m10 != 0.) {
839ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kAffine_Mask;
840ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
841ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
842ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (m00 != 1. || m11 != 1.) {
843ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= kScale_Mask;
844ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
845ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
846ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if ((mask & kPerspective_Mask) == 0) {
847ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // map non-zero to 1
848ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im00 = m00 != 0 ? 1 : 0;
849ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im01 = m01 != 0 ? 1 : 0;
850ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im10 = m10 != 0 ? 1 : 0;
851ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int im11 = m11 != 0 ? 1 : 0;
852ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
853ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // record if the (p)rimary and (s)econdary diagonals are all 0 or
854ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // all non-zero (answer is 0 or 1)
855ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
856ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int dp1 = im00 & im11;        // true if both are 1
857ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
858ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int ds1 = im01 & im10;        // true if both are 1
859ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
860ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // return 1 if primary is 1 and secondary is 0 or
861ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // primary is 0 and secondary is 1
862ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
863ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
864ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
865ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mask;
866ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
867ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
868ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Matrix_Delegate() {
869ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        reset();
870ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
871ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
872ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Matrix_Delegate(float[] values) {
873ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
874ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
875ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
876ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
877ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Adds the given transformation to the current Matrix
878ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does this = this*matrix
879ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param matrix
880ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
881ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void postTransform(float[] matrix) {
882ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
883ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, mValues, matrix);
884ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mValues = tmp;
885ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
886ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
887ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
888ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Adds the given transformation to the current Matrix
889ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does this = matrix*this
890ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param matrix
891ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
892ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void preTransform(float[] matrix) {
893ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
894ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, matrix, mValues);
895ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mValues = tmp;
896ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
897ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
898ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
899ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Apply this matrix to the array of 2D points specified by src, and write
900ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * the transformed points into the array of points specified by dst. The
901ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * two arrays represent their "points" as pairs of floats [x, y].
902ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      *
903ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param dst   The array of dst points (x,y pairs)
904ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param dstIndex The index of the first [x,y] pair of dst floats
905ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param src   The array of src points (x,y pairs)
906ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param srcIndex The index of the first [x,y] pair of src floats
907ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param pointCount The number of points (x,y pairs) to transform
908ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      */
909ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
910ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
911ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                           int pointCount) {
912ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         final int count = pointCount * 2;
913ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
914ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         float[] tmpDest = dst;
915ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         boolean inPlace = dst == src;
916ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (inPlace) {
917ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest = new float[dstIndex + count];
918ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
919ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
920ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         for (int i = 0 ; i < count ; i += 2) {
921ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // just in case we are doing in place, we better put this in temp vars
922ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float x = mValues[0] * src[i + srcIndex] +
923ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[1] * src[i + srcIndex + 1] +
924ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[2];
925ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float y = mValues[3] * src[i + srcIndex] +
926ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[4] * src[i + srcIndex + 1] +
927ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                       mValues[5];
928ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
929ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest[i + dstIndex]     = x;
930ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             tmpDest[i + dstIndex + 1] = y;
931ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
932ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
933ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (inPlace) {
934ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
935ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
936ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
937ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
938ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     /**
939ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * Apply this matrix to the array of 2D points, and write the transformed
940ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * points back into the array
941ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      *
942ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
943ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski      */
944ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
945ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapPoints(float[] pts) {
946ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         mapPoints(pts, 0, pts, 0, pts.length >> 1);
947ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
948ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
949ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
950ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         if (hasPerspective()) {
951ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // transform the (0,0) point
952ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             float[] origin = new float[] { 0.f, 0.f};
953ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             mapPoints(origin);
954ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
955ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // translate the vector data as points
956ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
957ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
958ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // then substract the transformed origin.
959ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             final int count = ptCount * 2;
960ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             for (int i = 0 ; i < count ; i += 2) {
961ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
962ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
963ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             }
964ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         } else {
965ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // make a copy of the matrix
966ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             Matrix_Delegate copy = new Matrix_Delegate(mValues);
967ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
968ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // remove the translation
969ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             setTranslate(copy.mValues, 0, 0);
970ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
971ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             // map the content as points.
972ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
973ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         }
974ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
975ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
976ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     private static float getPointLength(float[] src, int index) {
977ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         return (float) Math.sqrt(src[index] * src[index] + src[index + 1] * src[index + 1]);
978ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     }
979ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
980ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
981ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * multiply two matrices and store them in a 3rd.
982ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This in effect does dest = a*b
983ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * dest cannot be the same as a or b.
984ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
985ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
986ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // first row
987ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
988ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
989ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
990ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
991ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // 2nd row
992ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
993ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
994ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
995ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
996ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // 3rd row
997ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
998ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
999ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
1000ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1001ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1002ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
1003ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a matrix that represents a given translate
1004ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param dx
1005ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param dy
1006ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return
1007ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
1008ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getTranslate(float dx, float dy) {
1009ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setTranslate(new float[9], dx, dy);
1010ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1011ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1012ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
1013ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = 1;
1014ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = 0;
1015ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = dx;
1016ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = 0;
1017ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = 1;
1018ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = dy;
1019ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = 0;
1020ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = 0;
1021ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = 1;
1022ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dest;
1023ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1024ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1025ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getScale(float sx, float sy) {
1026ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
1027ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1028ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1029ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
1030ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a matrix that represents the given scale info.
1031ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param sx
1032ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param sy
1033ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param px
1034ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param py
1035ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
1036ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getScale(float sx, float sy, 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 tmp so that the pivot is in 0,0
1043ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1044ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1045ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // scale into tmp2
1046ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, getScale(sx, sy));
1047ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1048ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1049ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1050ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1051ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1052ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1053ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1054ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1055ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float degrees) {
1056ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1057ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1058ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1059ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1060ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getRotate(sin, cos);
1061ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1062ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1063ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float sin, float cos) {
1064ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setRotate(new float[9], sin, cos);
1065ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1066ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1067ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setRotate(float[] dest, float degrees) {
1068ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1069ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1070ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1071ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1072ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return setRotate(dest, sin, cos);
1073ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1074ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1075ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
1076ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[0] = cos;
1077ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[1] = -sin;
1078ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[2] = 0;
1079ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[3] = sin;
1080ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[4] = cos;
1081ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[5] = 0;
1082ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[6] = 0;
1083ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[7] = 0;
1084ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        dest[8] = 1;
1085ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dest;
1086ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1087ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1088ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getRotate(float degrees, float px, float py) {
1089ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
1090ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
1091ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1092ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
1093ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1094ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
1095ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1096ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1097ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // rotate into tmp2
1098ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        double rad = Math.toRadians(degrees);
1099ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float cos = (float)Math.cos(rad);
1100ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float sin = (float)Math.sin(rad);
1101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, getRotate(sin, cos));
1102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1103ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1104ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1105ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1106ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getSkew(float kx, float ky) {
1110ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
1111ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1112ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1113ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
1114ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp = new float[9];
1115ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        float[] tmp2 = new float[9];
1116ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1117ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // TODO: do it in one pass
1118ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1119ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate so that the pivot is in 0,0
1120ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        setTranslate(tmp, -px, -py);
1121ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1122ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // skew into tmp2
1123ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
1124ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // translate back the pivot back into tmp
1125ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1126ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1127ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return tmp;
1128ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
1129ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
1130