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
206130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    /*package*/ static boolean native_isAffine(long native_object) {
207130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        Matrix_Delegate d = sManager.getDelegate(native_object);
208130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        if (d == null) {
209130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta            return true;
210130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        }
211130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta
212130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        return (d.computeTypeMask() & kPerspective_Mask) == 0;
213130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    }
214130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta
215130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    @LayoutlibDelegate
21688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_rectStaysRect(long native_object) {
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
22688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_reset(long native_object) {
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset(d.mValues);
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
23688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_set(long native_object, long other) {
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate src = sManager.getDelegate(other);
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (src == null) {
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
25188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setTranslate(long native_object, float dx, float dy) {
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(d.mValues, dx, dy);
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
26188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy,
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
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 = getScale(sx, sy, px, py);
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
27288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy) {
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[0] = sx;
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[1] = 0;
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[2] = 0;
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[3] = 0;
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[4] = sy;
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[5] = 0;
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[6] = 0;
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[7] = 0;
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
29088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees, float px, float py) {
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getRotate(degrees, px, py);
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
30088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees) {
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setRotate(d.mValues, degrees);
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
31088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue,
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(d.mValues, -px, -py);
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // scale
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.postTransform(getRotate(sinValue, cosValue));
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.postTransform(getTranslate(px, py));
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
32988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue) {
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setRotate(d.mValues, sinValue, cosValue);
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
33988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky,
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
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 = getSkew(kx, ky, px, py);
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
35088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky) {
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[0] = 1;
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[1] = kx;
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[2] = -0;
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[3] = ky;
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[4] = 1;
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[5] = 0;
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[6] = 0;
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[7] = 0;
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
368385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_setConcat(long native_object, long a, long b) {
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (a == native_object) {
370385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            native_preConcat(native_object, b);
371385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            return;
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (b == native_object) {
373385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            native_postConcat(native_object, a);
374385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            return;
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate a_mtx = sManager.getDelegate(a);
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate b_mtx = sManager.getDelegate(b);
380385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && a_mtx != null && b_mtx != null) {
381385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
386385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preTranslate(long native_object, float dx, float dy) {
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
388385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
389385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getTranslate(dx, dy));
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
394385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preScale(long native_object, float sx, float sy,
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
397385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
398385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getScale(sx, sy, px, py));
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
403385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preScale(long native_object, float sx, float sy) {
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
405385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
406385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getScale(sx, sy));
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
411385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preRotate(long native_object, float degrees,
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
414385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
415385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getRotate(degrees, px, py));
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
420385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preRotate(long native_object, float degrees) {
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
422385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
424385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            double rad = Math.toRadians(degrees);
425385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            float sin = (float) Math.sin(rad);
426385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            float cos = (float) Math.cos(rad);
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
428385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getRotate(sin, cos));
429385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        }
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
433385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preSkew(long native_object, float kx, float ky,
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
436385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
437385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getSkew(kx, ky, px, py));
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
442385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preSkew(long native_object, float kx, float ky) {
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
444385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
445385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getSkew(kx, ky));
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
450385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_preConcat(long native_object, long other_matrix) {
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
453385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && other != null) {
454385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(other.mValues);
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
459385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postTranslate(long native_object, float dx, float dy) {
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
461385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
462385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getTranslate(dx, dy));
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
467385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postScale(long native_object, float sx, float sy,
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
470385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
471385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getScale(sx, sy, px, py));
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
476385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postScale(long native_object, float sx, float sy) {
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
478385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
479385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getScale(sx, sy));
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
484385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postRotate(long native_object, float degrees,
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
487385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
488385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getRotate(degrees, px, py));
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
493385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postRotate(long native_object, float degrees) {
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
495385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
496385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getRotate(degrees));
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
501385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postSkew(long native_object, float kx, float ky,
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
504385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
505385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getSkew(kx, ky, px, py));
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
510385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postSkew(long native_object, float kx, float ky) {
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
512385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
513385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getSkew(kx, ky));
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
518385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta    /*package*/ static void native_postConcat(long native_object, long other_matrix) {
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
521385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && other != null) {
522385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(other.mValues);
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
52788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_setRectToRect(long native_object, RectF src,
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            RectF dst, int stf) {
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (src.isEmpty()) {
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            reset(d.mValues);
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dst.isEmpty()) {
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               = d.mValues[6] = d.mValues[7] = 0;
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[8] = 1;
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float    tx, sx = dst.width() / src.width();
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float    ty, sy = dst.height() / src.height();
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean  xLarger = false;
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (stf != ScaleToFit.FILL.nativeInt) {
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (sx > sy) {
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xLarger = true;
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sx = sy;
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sy = sx;
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tx = dst.left - src.left * sx;
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ty = dst.top - src.top * sy;
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float diff;
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xLarger) {
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = dst.width() - src.width() * sy;
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = dst.height() - src.height() * sy;
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (stf == ScaleToFit.CENTER.nativeInt) {
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = diff / 2;
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xLarger) {
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    tx += diff;
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ty += diff;
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[0] = sx;
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[4] = sy;
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[2] = tx;
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[5] = ty;
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // shared cleanup
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
59288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_setPolyToPoly(long native_object, float[] src, int srcIndex,
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] dst, int dstIndex, int pointCount) {
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Matrix.setPolyToPoly is not supported.",
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                null, null /*data*/);
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
602e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta    /*package*/ static boolean native_invert(long native_object, long inverse) {
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (inv_mtx == null) {
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AffineTransform affineTransform = d.getAffineTransform();
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AffineTransform inverseTransform = affineTransform.createInverse();
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (NoninvertibleTransformException e) {
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
63088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_mapPoints(long native_object, float[] dst, int dstIndex,
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] src, int srcIndex, int ptCount, boolean isPts) {
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPts) {
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
64588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_mapRect(long native_object, RectF dst, RectF src) {
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return d.mapRect(dst, src);
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
65588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static float native_mapRadius(long native_object, float radius) {
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0.f;
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] src = new float[] { radius, 0.f, 0.f, radius };
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mapVectors(src, 0, src, 0, 2);
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66433253a4baa6279f81a73425b49dfb6abe5f5416eNeil Fuller        float l1 = (float) Math.hypot(src[0], src[1]);
66533253a4baa6279f81a73425b49dfb6abe5f5416eNeil Fuller        float l2 = (float) Math.hypot(src[2], src[3]);
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (float) Math.sqrt(l1 * l2);
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
67088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_getValues(long native_object, float[] values) {
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
6769f280a9301566c94a583cc45b6abea8a4488e33cDeepanshu Gupta        System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE);
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
68088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setValues(long native_object, float[] values) {
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
69088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_equals(long native_a, long native_b) {
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate a = sManager.getDelegate(native_a);
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (a == null) {
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate b = sManager.getDelegate(native_b);
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (b == null) {
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (a.mValues[i] != b.mValues[i]) {
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
71188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void finalizer(long native_instance) {
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sManager.removeJavaReferenceFor(native_instance);
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Private helper methods ----
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the AffineTransform constructor takes the value in a different order
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // for a matrix [ 0 1 2 ]
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //              [ 3 4 5 ]
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the order is 0, 3, 1, 4, 2, 5...
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new AffineTransform(
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matrix[0], matrix[3], matrix[1],
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matrix[4], matrix[2], matrix[5]);
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Reset a matrix to the identity
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void reset(float[] mtx) {
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j = 0; j < 3; j++, k++) {
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mtx[k] = ((i==j) ? 1 : 0);
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kIdentity_Mask      = 0;
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kRectStaysRect_Mask = 0x10;
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kUnknown_Mask       = 0x80;
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAllMasks           = kTranslate_Mask |
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kScale_Mask |
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kAffine_Mask |
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kPerspective_Mask |
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kRectStaysRect_Mask;
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // these guys align with the masks, so we can compute a mask from a variable 0/1
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kTranslate_Shift = 0;
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kScale_Shift = 1;
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAffine_Shift = 2;
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kPerspective_Shift = 3;
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kRectStaysRect_Shift = 4;
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int computeTypeMask() {
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int mask = 0;
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kPerspective_Mask;
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mValues[2] != 0. || mValues[5] != 0.) {
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kTranslate_Mask;
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m00 = mValues[0];
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m01 = mValues[1];
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m10 = mValues[3];
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m11 = mValues[4];
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (m01 != 0. || m10 != 0.) {
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kAffine_Mask;
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (m00 != 1. || m11 != 1.) {
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kScale_Mask;
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((mask & kPerspective_Mask) == 0) {
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // map non-zero to 1
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im00 = m00 != 0 ? 1 : 0;
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im01 = m01 != 0 ? 1 : 0;
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im10 = m10 != 0 ? 1 : 0;
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im11 = m11 != 0 ? 1 : 0;
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // record if the (p)rimary and (s)econdary diagonals are all 0 or
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // all non-zero (answer is 0 or 1)
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dp1 = im00 & im11;        // true if both are 1
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ds1 = im01 & im10;        // true if both are 1
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // return 1 if primary is 1 and secondary is 0 or
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // primary is 0 and secondary is 1
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mask;
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Matrix_Delegate() {
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset();
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Matrix_Delegate(float[] values) {
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Adds the given transformation to the current Matrix
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does this = this*matrix
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param matrix
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void postTransform(float[] matrix) {
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, mValues, matrix);
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mValues = tmp;
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Adds the given transformation to the current Matrix
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does this = matrix*this
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param matrix
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void preTransform(float[] matrix) {
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, matrix, mValues);
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mValues = tmp;
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Apply this matrix to the array of 2D points specified by src, and write
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * the transformed points into the array of points specified by dst. The
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * two arrays represent their "points" as pairs of floats [x, y].
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      *
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param dst   The array of dst points (x,y pairs)
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param dstIndex The index of the first [x,y] pair of dst floats
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param src   The array of src points (x,y pairs)
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param srcIndex The index of the first [x,y] pair of src floats
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param pointCount The number of points (x,y pairs) to transform
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      */
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           int pointCount) {
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         final int count = pointCount * 2;
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         float[] tmpDest = dst;
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         boolean inPlace = dst == src;
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (inPlace) {
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest = new float[dstIndex + count];
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         for (int i = 0 ; i < count ; i += 2) {
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // just in case we are doing in place, we better put this in temp vars
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float x = mValues[0] * src[i + srcIndex] +
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[1] * src[i + srcIndex + 1] +
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[2];
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float y = mValues[3] * src[i + srcIndex] +
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[4] * src[i + srcIndex + 1] +
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[5];
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest[i + dstIndex]     = x;
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest[i + dstIndex + 1] = y;
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (inPlace) {
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     /**
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * Apply this matrix to the array of 2D points, and write the transformed
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * points back into the array
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      *
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      */
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapPoints(float[] pts) {
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         mapPoints(pts, 0, pts, 0, pts.length >> 1);
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (hasPerspective()) {
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // transform the (0,0) point
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float[] origin = new float[] { 0.f, 0.f};
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             mapPoints(origin);
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // translate the vector data as points
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // then substract the transformed origin.
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             final int count = ptCount * 2;
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             for (int i = 0 ; i < count ; i += 2) {
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             }
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         } else {
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // make a copy of the matrix
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             Matrix_Delegate copy = new Matrix_Delegate(mValues);
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // remove the translation
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             setTranslate(copy.mValues, 0, 0);
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // map the content as points.
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * multiply two matrices and store them in a 3rd.
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does dest = a*b
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * dest cannot be the same as a or b.
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // first row
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // 2nd row
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // 3rd row
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a matrix that represents a given translate
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param dx
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param dy
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getTranslate(float dx, float dy) {
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setTranslate(new float[9], dx, dy);
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = 1;
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = 0;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = dx;
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = 0;
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = 1;
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = dy;
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = 0;
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = 0;
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = 1;
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dest;
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getScale(float sx, float sy) {
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a matrix that represents the given scale info.
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param sx
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param sy
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param px
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param py
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate tmp so that the pivot is in 0,0
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // scale into tmp2
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, getScale(sx, sy));
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float degrees) {
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getRotate(sin, cos);
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float sin, float cos) {
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setRotate(new float[9], sin, cos);
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setRotate(float[] dest, float degrees) {
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setRotate(dest, sin, cos);
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = cos;
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = -sin;
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = 0;
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = sin;
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = cos;
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = 0;
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = 0;
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = 0;
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = 1;
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dest;
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float degrees, float px, float py) {
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // rotate into tmp2
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, getRotate(sin, cos));
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getSkew(float kx, float ky) {
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // skew into tmp2
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1070