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