Matrix_Delegate.java revision 385c6b3b6ca370301f82f83715e9004ddaf43cae
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2010 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage android.graphics;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.DelegateManager;
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Matrix.ScaleToFit;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.geom.AffineTransform;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.geom.NoninvertibleTransformException;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delegate implementing the native methods of android.graphics.Matrix
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * by calls to methods of the same name in this delegate class.
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * it and the original Matrix class.
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see DelegateManager
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class Matrix_Delegate {
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int MATRIX_SIZE = 9;
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate manager ----
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final DelegateManager<Matrix_Delegate> sManager =
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate data ----
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private float mValues[] = new float[MATRIX_SIZE];
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Public Helper methods ----
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
5688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    public static Matrix_Delegate getDelegate(long native_instance) {
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.getDelegate(native_instance);
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns an {@link AffineTransform} matching the given Matrix.
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static AffineTransform getAffineTransform(Matrix m) {
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.getAffineTransform();
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static boolean hasPerspective(Matrix m) {
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.hasPerspective();
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Sets the content of the matrix with the content of another matrix.
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void set(Matrix_Delegate matrix) {
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Sets the content of the matrix with the content of another matrix represented as an array
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * of values.
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void set(float[] values) {
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Resets the matrix to be the identity matrix.
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void reset() {
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset(mValues);
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns whether or not the matrix is identity.
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean isIdentity() {
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j = 0; j < 3; j++, k++) {
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mValues[k] != ((i==j) ? 1 : 0)) {
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return false;
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static float[] makeValues(AffineTransform matrix) {
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] values = new float[MATRIX_SIZE];
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[0] = (float) matrix.getScaleX();
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[1] = (float) matrix.getShearX();
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[2] = (float) matrix.getTranslateX();
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[3] = (float) matrix.getShearY();
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[4] = (float) matrix.getScaleY();
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[5] = (float) matrix.getTranslateY();
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[6] = 0.f;
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[7] = 0.f;
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[8] = 1.f;
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return values;
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static Matrix_Delegate make(AffineTransform matrix) {
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new Matrix_Delegate(makeValues(matrix));
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean mapRect(RectF dst, RectF src) {
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // array with 4 corners
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] corners = new float[] {
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.left, src.top,
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.right, src.top,
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.right, src.bottom,
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.left, src.bottom,
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        };
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // apply the transform to them.
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapPoints(corners);
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns an {@link AffineTransform} matching the matrix.
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public AffineTransform getAffineTransform() {
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getAffineTransform(mValues);
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean hasPerspective() {
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- native methods ----
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
17788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static long native_create(long native_src_or_zero) {
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create the delegate
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate newDelegate = new Matrix_Delegate();
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // copy from values if needed.
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (native_src_or_zero > 0) {
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (oldDelegate != null) {
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                System.arraycopy(
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        oldDelegate.mValues, 0,
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        newDelegate.mValues, 0,
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        MATRIX_SIZE);
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.addNewDelegate(newDelegate);
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
19688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_isIdentity(long native_object) {
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return d.isIdentity();
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
20688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_rectStaysRect(long native_object) {
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
21688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_reset(long native_object) {
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset(d.mValues);
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
22688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_set(long native_object, long other) {
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate src = sManager.getDelegate(other);
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (src == null) {
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
24188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setTranslate(long native_object, float dx, float dy) {
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(d.mValues, dx, dy);
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
25188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy,
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getScale(sx, sy, px, py);
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
26288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy) {
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[0] = sx;
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[1] = 0;
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[2] = 0;
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[3] = 0;
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[4] = sy;
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[5] = 0;
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[6] = 0;
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[7] = 0;
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
28088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees, float px, float py) {
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getRotate(degrees, px, py);
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
29088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees) {
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setRotate(d.mValues, degrees);
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
30088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue,
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(d.mValues, -px, -py);
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // scale
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.postTransform(getRotate(sinValue, cosValue));
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.postTransform(getTranslate(px, py));
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
31988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue) {
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setRotate(d.mValues, sinValue, cosValue);
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
32988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky,
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getSkew(kx, ky, px, py);
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
34088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky) {
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[0] = 1;
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[1] = kx;
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[2] = -0;
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[3] = ky;
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[4] = 1;
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[5] = 0;
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[6] = 0;
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[7] = 0;
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
358385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_setConcat(long native_object, long a, long b) {
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (a == native_object) {
360385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            native_preConcat(native_object, b);
361385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            return;
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (b == native_object) {
363385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            native_postConcat(native_object, a);
364385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            return;
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate a_mtx = sManager.getDelegate(a);
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate b_mtx = sManager.getDelegate(b);
370385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && a_mtx != null && b_mtx != null) {
371385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
376385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preTranslate(long native_object, float dx, float dy) {
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
378385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
379385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getTranslate(dx, dy));
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
384385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preScale(long native_object, float sx, float sy,
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
387385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
388385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getScale(sx, sy, px, py));
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
393385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preScale(long native_object, float sx, float sy) {
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
395385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
396385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getScale(sx, sy));
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
401385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preRotate(long native_object, float degrees,
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
404385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
405385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getRotate(degrees, px, py));
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
410385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preRotate(long native_object, float degrees) {
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
412385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
414385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            double rad = Math.toRadians(degrees);
415385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            float sin = (float) Math.sin(rad);
416385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            float cos = (float) Math.cos(rad);
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
418385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getRotate(sin, cos));
419385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        }
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
423385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preSkew(long native_object, float kx, float ky,
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
426385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
427385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getSkew(kx, ky, px, py));
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
432385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preSkew(long native_object, float kx, float ky) {
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
434385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
435385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getSkew(kx, ky));
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
440385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preConcat(long native_object, long other_matrix) {
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
443385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && other != null) {
444385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(other.mValues);
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
449385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postTranslate(long native_object, float dx, float dy) {
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
451385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
452385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getTranslate(dx, dy));
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
457385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postScale(long native_object, float sx, float sy,
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
460385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
461385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getScale(sx, sy, px, py));
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
466385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postScale(long native_object, float sx, float sy) {
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
468385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
469385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getScale(sx, sy));
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
474385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postRotate(long native_object, float degrees,
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
477385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
478385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getRotate(degrees, px, py));
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
483385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postRotate(long native_object, float degrees) {
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
485385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
486385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getRotate(degrees));
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
491385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postSkew(long native_object, float kx, float ky,
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
494385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
495385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getSkew(kx, ky, px, py));
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
500385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postSkew(long native_object, float kx, float ky) {
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
502385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
503385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getSkew(kx, ky));
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
508385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postConcat(long native_object, long other_matrix) {
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
511385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && other != null) {
512385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(other.mValues);
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
51788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_setRectToRect(long native_object, RectF src,
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            RectF dst, int stf) {
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (src.isEmpty()) {
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            reset(d.mValues);
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dst.isEmpty()) {
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               = d.mValues[6] = d.mValues[7] = 0;
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[8] = 1;
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float    tx, sx = dst.width() / src.width();
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float    ty, sy = dst.height() / src.height();
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean  xLarger = false;
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (stf != ScaleToFit.FILL.nativeInt) {
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (sx > sy) {
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xLarger = true;
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sx = sy;
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sy = sx;
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tx = dst.left - src.left * sx;
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ty = dst.top - src.top * sy;
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float diff;
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xLarger) {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = dst.width() - src.width() * sy;
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = dst.height() - src.height() * sy;
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (stf == ScaleToFit.CENTER.nativeInt) {
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = diff / 2;
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xLarger) {
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    tx += diff;
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ty += diff;
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[0] = sx;
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[4] = sy;
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[2] = tx;
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[5] = ty;
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // shared cleanup
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
58288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_setPolyToPoly(long native_object, float[] src, int srcIndex,
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] dst, int dstIndex, int pointCount) {
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Matrix.setPolyToPoly is not supported.",
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                null, null /*data*/);
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
592e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta    /*package*/ static boolean native_invert(long native_object, long inverse) {
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (inv_mtx == null) {
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AffineTransform affineTransform = d.getAffineTransform();
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AffineTransform inverseTransform = affineTransform.createInverse();
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (NoninvertibleTransformException e) {
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
62088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_mapPoints(long native_object, float[] dst, int dstIndex,
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] src, int srcIndex, int ptCount, boolean isPts) {
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPts) {
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
63588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_mapRect(long native_object, RectF dst, RectF src) {
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return d.mapRect(dst, src);
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
64588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static float native_mapRadius(long native_object, float radius) {
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0.f;
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] src = new float[] { radius, 0.f, 0.f, radius };
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mapVectors(src, 0, src, 0, 2);
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float l1 = getPointLength(src, 0);
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float l2 = getPointLength(src, 2);
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (float) Math.sqrt(l1 * l2);
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
66188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_getValues(long native_object, float[] values) {
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
67188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setValues(long native_object, float[] values) {
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
68188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_equals(long native_a, long native_b) {
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate a = sManager.getDelegate(native_a);
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (a == null) {
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate b = sManager.getDelegate(native_b);
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (b == null) {
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (a.mValues[i] != b.mValues[i]) {
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
70288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void finalizer(long native_instance) {
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sManager.removeJavaReferenceFor(native_instance);
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Private helper methods ----
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the AffineTransform constructor takes the value in a different order
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // for a matrix [ 0 1 2 ]
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //              [ 3 4 5 ]
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the order is 0, 3, 1, 4, 2, 5...
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new AffineTransform(
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matrix[0], matrix[3], matrix[1],
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matrix[4], matrix[2], matrix[5]);
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Reset a matrix to the identity
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void reset(float[] mtx) {
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j = 0; j < 3; j++, k++) {
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mtx[k] = ((i==j) ? 1 : 0);
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kIdentity_Mask      = 0;
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kRectStaysRect_Mask = 0x10;
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kUnknown_Mask       = 0x80;
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAllMasks           = kTranslate_Mask |
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kScale_Mask |
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kAffine_Mask |
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kPerspective_Mask |
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kRectStaysRect_Mask;
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // these guys align with the masks, so we can compute a mask from a variable 0/1
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kTranslate_Shift = 0;
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kScale_Shift = 1;
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAffine_Shift = 2;
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kPerspective_Shift = 3;
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kRectStaysRect_Shift = 4;
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int computeTypeMask() {
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int mask = 0;
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kPerspective_Mask;
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mValues[2] != 0. || mValues[5] != 0.) {
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kTranslate_Mask;
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m00 = mValues[0];
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m01 = mValues[1];
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m10 = mValues[3];
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m11 = mValues[4];
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (m01 != 0. || m10 != 0.) {
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kAffine_Mask;
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (m00 != 1. || m11 != 1.) {
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kScale_Mask;
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((mask & kPerspective_Mask) == 0) {
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // map non-zero to 1
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im00 = m00 != 0 ? 1 : 0;
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im01 = m01 != 0 ? 1 : 0;
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im10 = m10 != 0 ? 1 : 0;
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im11 = m11 != 0 ? 1 : 0;
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // record if the (p)rimary and (s)econdary diagonals are all 0 or
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // all non-zero (answer is 0 or 1)
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dp1 = im00 & im11;        // true if both are 1
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ds1 = im01 & im10;        // true if both are 1
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // return 1 if primary is 1 and secondary is 0 or
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // primary is 0 and secondary is 1
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mask;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Matrix_Delegate() {
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset();
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Matrix_Delegate(float[] values) {
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Adds the given transformation to the current Matrix
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does this = this*matrix
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param matrix
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void postTransform(float[] matrix) {
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, mValues, matrix);
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mValues = tmp;
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Adds the given transformation to the current Matrix
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does this = matrix*this
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param matrix
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void preTransform(float[] matrix) {
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, matrix, mValues);
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mValues = tmp;
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Apply this matrix to the array of 2D points specified by src, and write
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * the transformed points into the array of points specified by dst. The
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * two arrays represent their "points" as pairs of floats [x, y].
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      *
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param dst   The array of dst points (x,y pairs)
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param dstIndex The index of the first [x,y] pair of dst floats
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param src   The array of src points (x,y pairs)
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param srcIndex The index of the first [x,y] pair of src floats
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param pointCount The number of points (x,y pairs) to transform
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      */
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           int pointCount) {
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         final int count = pointCount * 2;
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         float[] tmpDest = dst;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         boolean inPlace = dst == src;
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (inPlace) {
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest = new float[dstIndex + count];
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         for (int i = 0 ; i < count ; i += 2) {
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // just in case we are doing in place, we better put this in temp vars
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float x = mValues[0] * src[i + srcIndex] +
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[1] * src[i + srcIndex + 1] +
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[2];
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float y = mValues[3] * src[i + srcIndex] +
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[4] * src[i + srcIndex + 1] +
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[5];
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest[i + dstIndex]     = x;
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest[i + dstIndex + 1] = y;
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (inPlace) {
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     /**
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * Apply this matrix to the array of 2D points, and write the transformed
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * points back into the array
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      *
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      */
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapPoints(float[] pts) {
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         mapPoints(pts, 0, pts, 0, pts.length >> 1);
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (hasPerspective()) {
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // transform the (0,0) point
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float[] origin = new float[] { 0.f, 0.f};
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             mapPoints(origin);
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // translate the vector data as points
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // then substract the transformed origin.
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             final int count = ptCount * 2;
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             for (int i = 0 ; i < count ; i += 2) {
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             }
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         } else {
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // make a copy of the matrix
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             Matrix_Delegate copy = new Matrix_Delegate(mValues);
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // remove the translation
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             setTranslate(copy.mValues, 0, 0);
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // map the content as points.
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private static float getPointLength(float[] src, int index) {
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         return (float) Math.sqrt(src[index] * src[index] + src[index + 1] * src[index + 1]);
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * multiply two matrices and store them in a 3rd.
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does dest = a*b
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * dest cannot be the same as a or b.
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // first row
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // 2nd row
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // 3rd row
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a matrix that represents a given translate
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param dx
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param dy
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getTranslate(float dx, float dy) {
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setTranslate(new float[9], dx, dy);
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = 1;
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = 0;
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = dx;
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = 0;
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = 1;
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = dy;
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = 0;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = 0;
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = 1;
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dest;
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getScale(float sx, float sy) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a matrix that represents the given scale info.
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param sx
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param sy
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param px
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param py
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate tmp so that the pivot is in 0,0
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // scale into tmp2
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, getScale(sx, sy));
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float degrees) {
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getRotate(sin, cos);
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float sin, float cos) {
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setRotate(new float[9], sin, cos);
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setRotate(float[] dest, float degrees) {
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setRotate(dest, sin, cos);
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = cos;
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = -sin;
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = 0;
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = sin;
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = cos;
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = 0;
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = 0;
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = 0;
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = 1;
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dest;
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float degrees, float px, float py) {
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // rotate into tmp2
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, getRotate(sin, cos));
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getSkew(float kx, float ky) {
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // skew into tmp2
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1065