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
30a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillardimport libcore.util.NativeAllocationRegistry_Delegate;
31a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delegate implementing the native methods of android.graphics.Matrix
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * by calls to methods of the same name in this delegate class.
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * it and the original Matrix class.
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see DelegateManager
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class Matrix_Delegate {
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int MATRIX_SIZE = 9;
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate manager ----
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final DelegateManager<Matrix_Delegate> sManager =
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
52a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    private static long sFinalizer = -1;
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate data ----
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private float mValues[] = new float[MATRIX_SIZE];
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Public Helper methods ----
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
5988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    public static Matrix_Delegate getDelegate(long native_instance) {
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.getDelegate(native_instance);
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns an {@link AffineTransform} matching the given Matrix.
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static AffineTransform getAffineTransform(Matrix m) {
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.getAffineTransform();
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static boolean hasPerspective(Matrix m) {
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.hasPerspective();
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Sets the content of the matrix with the content of another matrix.
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void set(Matrix_Delegate matrix) {
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Sets the content of the matrix with the content of another matrix represented as an array
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * of values.
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void set(float[] values) {
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Resets the matrix to be the identity matrix.
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void reset() {
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset(mValues);
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns whether or not the matrix is identity.
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean isIdentity() {
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j = 0; j < 3; j++, k++) {
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mValues[k] != ((i==j) ? 1 : 0)) {
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return false;
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static float[] makeValues(AffineTransform matrix) {
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] values = new float[MATRIX_SIZE];
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[0] = (float) matrix.getScaleX();
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[1] = (float) matrix.getShearX();
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[2] = (float) matrix.getTranslateX();
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[3] = (float) matrix.getShearY();
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[4] = (float) matrix.getScaleY();
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[5] = (float) matrix.getTranslateY();
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[6] = 0.f;
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[7] = 0.f;
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        values[8] = 1.f;
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return values;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static Matrix_Delegate make(AffineTransform matrix) {
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new Matrix_Delegate(makeValues(matrix));
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean mapRect(RectF dst, RectF src) {
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // array with 4 corners
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] corners = new float[] {
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.left, src.top,
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.right, src.top,
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.right, src.bottom,
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                src.left, src.bottom,
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        };
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // apply the transform to them.
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapPoints(corners);
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns an {@link AffineTransform} matching the matrix.
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public AffineTransform getAffineTransform() {
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getAffineTransform(mValues);
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean hasPerspective() {
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- native methods ----
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
180a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static long nCreate(long native_src_or_zero) {
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create the delegate
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate newDelegate = new Matrix_Delegate();
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // copy from values if needed.
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (native_src_or_zero > 0) {
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (oldDelegate != null) {
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                System.arraycopy(
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        oldDelegate.mValues, 0,
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        newDelegate.mValues, 0,
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        MATRIX_SIZE);
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.addNewDelegate(newDelegate);
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
199a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nIsIdentity(long native_object) {
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return d.isIdentity();
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
209a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nIsAffine(long native_object) {
210130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        Matrix_Delegate d = sManager.getDelegate(native_object);
211130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        if (d == null) {
212130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta            return true;
213130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        }
214130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta
215130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        return (d.computeTypeMask() & kPerspective_Mask) == 0;
216130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    }
217130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta
218130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    @LayoutlibDelegate
219a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nRectStaysRect(long native_object) {
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
229a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nReset(long native_object) {
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset(d.mValues);
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
239a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSet(long native_object, long other) {
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate src = sManager.getDelegate(other);
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (src == null) {
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
254a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetTranslate(long native_object, float dx, float dy) {
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(d.mValues, dx, dy);
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
264a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetScale(long native_object, float sx, float sy,
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getScale(sx, sy, px, py);
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
275a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetScale(long native_object, float sx, float sy) {
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[0] = sx;
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[1] = 0;
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[2] = 0;
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[3] = 0;
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[4] = sy;
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[5] = 0;
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[6] = 0;
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[7] = 0;
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
293a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetRotate(long native_object, float degrees, float px, float py) {
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getRotate(degrees, px, py);
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
303a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetRotate(long native_object, float degrees) {
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setRotate(d.mValues, degrees);
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
313a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue,
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(d.mValues, -px, -py);
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // scale
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.postTransform(getRotate(sinValue, cosValue));
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.postTransform(getTranslate(px, py));
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
332a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue) {
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setRotate(d.mValues, sinValue, cosValue);
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
342a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetSkew(long native_object, float kx, float ky,
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues = getSkew(kx, ky, px, py);
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
353a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetSkew(long native_object, float kx, float ky) {
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[0] = 1;
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[1] = kx;
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[2] = -0;
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[3] = ky;
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[4] = 1;
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[5] = 0;
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[6] = 0;
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[7] = 0;
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
371a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetConcat(long native_object, long a, long b) {
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (a == native_object) {
373a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard            nPreConcat(native_object, b);
374385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            return;
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (b == native_object) {
376a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard            nPostConcat(native_object, a);
377385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            return;
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate a_mtx = sManager.getDelegate(a);
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate b_mtx = sManager.getDelegate(b);
383385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && a_mtx != null && b_mtx != null) {
384385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
389a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreTranslate(long native_object, float dx, float dy) {
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
391385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
392385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getTranslate(dx, dy));
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
397a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreScale(long native_object, float sx, float sy,
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
400385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
401385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getScale(sx, sy, px, py));
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
406a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreScale(long native_object, float sx, float sy) {
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
408385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
409385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getScale(sx, sy));
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
414a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreRotate(long native_object, float degrees,
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
417385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
418385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getRotate(degrees, px, py));
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
423a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreRotate(long native_object, float degrees) {
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
425385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
427385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            double rad = Math.toRadians(degrees);
428385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            float sin = (float) Math.sin(rad);
429385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            float cos = (float) Math.cos(rad);
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
431385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getRotate(sin, cos));
432385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        }
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
436a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreSkew(long native_object, float kx, float ky,
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
439385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
440385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getSkew(kx, ky, px, py));
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
445a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreSkew(long native_object, float kx, float ky) {
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
447385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
448385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(getSkew(kx, ky));
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
453a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPreConcat(long native_object, long other_matrix) {
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
456385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && other != null) {
457385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.preTransform(other.mValues);
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
462a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostTranslate(long native_object, float dx, float dy) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
464385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
465385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getTranslate(dx, dy));
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
470a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostScale(long native_object, float sx, float sy,
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
473385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
474385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getScale(sx, sy, px, py));
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
479a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostScale(long native_object, float sx, float sy) {
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
481385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
482385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getScale(sx, sy));
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
487a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostRotate(long native_object, float degrees,
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
490385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
491385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getRotate(degrees, px, py));
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
496a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostRotate(long native_object, float degrees) {
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
498385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
499385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getRotate(degrees));
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
504a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostSkew(long native_object, float kx, float ky,
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float px, float py) {
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
507385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
508385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getSkew(kx, ky, px, py));
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
513a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostSkew(long native_object, float kx, float ky) {
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
515385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null) {
516385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(getSkew(kx, ky));
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
521a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nPostConcat(long native_object, long other_matrix) {
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate other = sManager.getDelegate(other_matrix);
524385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta        if (d != null && other != null) {
525385c6b3b6ca370301f82f83715e9004ddaf43caeDeepanshu Gupta            d.postTransform(other.mValues);
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
530a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nSetRectToRect(long native_object, RectF src,
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            RectF dst, int stf) {
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (src.isEmpty()) {
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            reset(d.mValues);
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dst.isEmpty()) {
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               = d.mValues[6] = d.mValues[7] = 0;
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[8] = 1;
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float    tx, sx = dst.width() / src.width();
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float    ty, sy = dst.height() / src.height();
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean  xLarger = false;
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (stf != ScaleToFit.FILL.nativeInt) {
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (sx > sy) {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xLarger = true;
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sx = sy;
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sy = sx;
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tx = dst.left - src.left * sx;
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ty = dst.top - src.top * sy;
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float diff;
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xLarger) {
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = dst.width() - src.width() * sy;
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = dst.height() - src.height() * sy;
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (stf == ScaleToFit.CENTER.nativeInt) {
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    diff = diff / 2;
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xLarger) {
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    tx += diff;
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ty += diff;
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[0] = sx;
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[4] = sy;
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[2] = tx;
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[5] = ty;
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // shared cleanup
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mValues[8] = 1;
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
595a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nSetPolyToPoly(long native_object, float[] src, int srcIndex,
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] dst, int dstIndex, int pointCount) {
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Matrix.setPolyToPoly is not supported.",
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                null, null /*data*/);
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
605a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nInvert(long native_object, long inverse) {
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (inv_mtx == null) {
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AffineTransform affineTransform = d.getAffineTransform();
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AffineTransform inverseTransform = affineTransform.createInverse();
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (NoninvertibleTransformException e) {
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
633a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nMapPoints(long native_object, float[] dst, int dstIndex,
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] src, int srcIndex, int ptCount, boolean isPts) {
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPts) {
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
648a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nMapRect(long native_object, RectF dst, RectF src) {
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return d.mapRect(dst, src);
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
658a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static float nMapRadius(long native_object, float radius) {
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0.f;
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] src = new float[] { radius, 0.f, 0.f, radius };
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d.mapVectors(src, 0, src, 0, 2);
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66733253a4baa6279f81a73425b49dfb6abe5f5416eNeil Fuller        float l1 = (float) Math.hypot(src[0], src[1]);
66833253a4baa6279f81a73425b49dfb6abe5f5416eNeil Fuller        float l2 = (float) Math.hypot(src[2], src[3]);
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (float) Math.sqrt(l1 * l2);
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
673a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nGetValues(long native_object, float[] values) {
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
6799f280a9301566c94a583cc45b6abea8a4488e33cDeepanshu Gupta        System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE);
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
683a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nSetValues(long native_object, float[] values) {
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate d = sManager.getDelegate(native_object);
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d == null) {
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
693a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static boolean nEquals(long native_a, long native_b) {
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate a = sManager.getDelegate(native_a);
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (a == null) {
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate b = sManager.getDelegate(native_b);
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (b == null) {
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (a.mValues[i] != b.mValues[i]) {
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
714a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static long nGetNativeFinalizer() {
715a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        synchronized (Matrix_Delegate.class) {
716a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard            if (sFinalizer == -1) {
717a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
718a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard            }
719a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        }
720a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        return sFinalizer;
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Private helper methods ----
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the AffineTransform constructor takes the value in a different order
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // for a matrix [ 0 1 2 ]
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //              [ 3 4 5 ]
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the order is 0, 3, 1, 4, 2, 5...
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new AffineTransform(
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matrix[0], matrix[3], matrix[1],
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matrix[4], matrix[2], matrix[5]);
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Reset a matrix to the identity
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void reset(float[] mtx) {
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0, k = 0; i < 3; i++) {
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j = 0; j < 3; j++, k++) {
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mtx[k] = ((i==j) ? 1 : 0);
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kIdentity_Mask      = 0;
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kRectStaysRect_Mask = 0x10;
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kUnknown_Mask       = 0x80;
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAllMasks           = kTranslate_Mask |
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kScale_Mask |
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kAffine_Mask |
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kPerspective_Mask |
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   kRectStaysRect_Mask;
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // these guys align with the masks, so we can compute a mask from a variable 0/1
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kTranslate_Shift = 0;
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kScale_Shift = 1;
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kAffine_Shift = 2;
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @SuppressWarnings("unused")
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kPerspective_Shift = 3;
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static int kRectStaysRect_Shift = 4;
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int computeTypeMask() {
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int mask = 0;
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kPerspective_Mask;
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mValues[2] != 0. || mValues[5] != 0.) {
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kTranslate_Mask;
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m00 = mValues[0];
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m01 = mValues[1];
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m10 = mValues[3];
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float m11 = mValues[4];
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (m01 != 0. || m10 != 0.) {
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kAffine_Mask;
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (m00 != 1. || m11 != 1.) {
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= kScale_Mask;
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((mask & kPerspective_Mask) == 0) {
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // map non-zero to 1
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im00 = m00 != 0 ? 1 : 0;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im01 = m01 != 0 ? 1 : 0;
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im10 = m10 != 0 ? 1 : 0;
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int im11 = m11 != 0 ? 1 : 0;
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // record if the (p)rimary and (s)econdary diagonals are all 0 or
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // all non-zero (answer is 0 or 1)
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dp1 = im00 & im11;        // true if both are 1
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ds1 = im01 & im10;        // true if both are 1
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // return 1 if primary is 1 and secondary is 0 or
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // primary is 0 and secondary is 1
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mask;
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Matrix_Delegate() {
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        reset();
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Matrix_Delegate(float[] values) {
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Adds the given transformation to the current Matrix
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does this = this*matrix
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param matrix
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void postTransform(float[] matrix) {
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, mValues, matrix);
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mValues = tmp;
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Adds the given transformation to the current Matrix
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does this = matrix*this
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param matrix
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void preTransform(float[] matrix) {
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, matrix, mValues);
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mValues = tmp;
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Apply this matrix to the array of 2D points specified by src, and write
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * the transformed points into the array of points specified by dst. The
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * two arrays represent their "points" as pairs of floats [x, y].
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      *
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param dst   The array of dst points (x,y pairs)
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param dstIndex The index of the first [x,y] pair of dst floats
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param src   The array of src points (x,y pairs)
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param srcIndex The index of the first [x,y] pair of src floats
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param pointCount The number of points (x,y pairs) to transform
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      */
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           int pointCount) {
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         final int count = pointCount * 2;
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         float[] tmpDest = dst;
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         boolean inPlace = dst == src;
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (inPlace) {
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest = new float[dstIndex + count];
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         for (int i = 0 ; i < count ; i += 2) {
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // just in case we are doing in place, we better put this in temp vars
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float x = mValues[0] * src[i + srcIndex] +
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[1] * src[i + srcIndex + 1] +
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[2];
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float y = mValues[3] * src[i + srcIndex] +
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[4] * src[i + srcIndex + 1] +
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       mValues[5];
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest[i + dstIndex]     = x;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             tmpDest[i + dstIndex + 1] = y;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (inPlace) {
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     /**
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * Apply this matrix to the array of 2D points, and write the transformed
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * points back into the array
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      *
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      */
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapPoints(float[] pts) {
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         mapPoints(pts, 0, pts, 0, pts.length >> 1);
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         if (hasPerspective()) {
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // transform the (0,0) point
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             float[] origin = new float[] { 0.f, 0.f};
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             mapPoints(origin);
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // translate the vector data as points
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // then substract the transformed origin.
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             final int count = ptCount * 2;
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             for (int i = 0 ; i < count ; i += 2) {
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             }
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         } else {
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // make a copy of the matrix
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             Matrix_Delegate copy = new Matrix_Delegate(mValues);
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // remove the translation
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             setTranslate(copy.mValues, 0, 0);
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             // map the content as points.
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         }
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     }
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * multiply two matrices and store them in a 3rd.
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This in effect does dest = a*b
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * dest cannot be the same as a or b.
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // first row
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // 2nd row
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // 3rd row
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a matrix that represents a given translate
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param dx
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param dy
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getTranslate(float dx, float dy) {
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setTranslate(new float[9], dx, dy);
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = 1;
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = 0;
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = dx;
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = 0;
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = 1;
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = dy;
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = 0;
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = 0;
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = 1;
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dest;
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getScale(float sx, float sy) {
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a matrix that represents the given scale info.
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param sx
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param sy
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param px
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param py
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate tmp so that the pivot is in 0,0
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // scale into tmp2
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, getScale(sx, sy));
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float degrees) {
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getRotate(sin, cos);
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float sin, float cos) {
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setRotate(new float[9], sin, cos);
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setRotate(float[] dest, float degrees) {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return setRotate(dest, sin, cos);
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[0] = cos;
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[1] = -sin;
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[2] = 0;
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[3] = sin;
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[4] = cos;
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[5] = 0;
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[6] = 0;
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[7] = 0;
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest[8] = 1;
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dest;
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getRotate(float degrees, float px, float py) {
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // rotate into tmp2
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        double rad = Math.toRadians(degrees);
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float cos = (float)Math.cos(rad);
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float sin = (float)Math.sin(rad);
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, getRotate(sin, cos));
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getSkew(float kx, float ky) {
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp = new float[9];
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float[] tmp2 = new float[9];
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: do it in one pass
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate so that the pivot is in 0,0
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setTranslate(tmp, -px, -py);
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // skew into tmp2
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // translate back the pivot back into tmp
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        multiply(tmp, tmp2, getTranslate(px, py));
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return tmp;
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1078