Matrix_Delegate.java revision 33253a4baa6279f81a73425b49dfb6abe5f5416e
14f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet/*
24f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
34f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
44f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
54f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * you may not use this file except in compliance with the License.
64f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * You may obtain a copy of the License at
74f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
84f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
94f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * See the License for the specific language governing permissions and
144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * limitations under the License.
154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet */
164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetpackage android.graphics;
184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
20918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog;
2110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
22c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager;
239a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport android.graphics.Matrix.ScaleToFit;
264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport java.awt.geom.AffineTransform;
284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport java.awt.geom.NoninvertibleTransformException;
294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet/**
314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Delegate implementing the native methods of android.graphics.Matrix
324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * by calls to methods of the same name in this delegate class.
354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * This class behaves like the original native implementation, but in Java, keeping previously
374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * native data into its own objects and mapping them to int that are sent back and forth between
384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * it and the original Matrix class.
394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * @see DelegateManager
414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet */
434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetpublic final class Matrix_Delegate {
444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int MATRIX_SIZE = 9;
464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- delegate manager ----
484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private static final DelegateManager<Matrix_Delegate> sManager =
49f0a53435f14d23d9555fc46014352ee6a7baa647Xavier Ducrohet            new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- delegate data ----
524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private float mValues[] = new float[MATRIX_SIZE];
534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- Public Helper methods ----
554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    public static Matrix_Delegate getDelegate(long native_instance) {
57251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        return sManager.getDelegate(native_instance);
58251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
59251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns an {@link AffineTransform} matching the given Matrix.
624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public static AffineTransform getAffineTransform(Matrix m) {
644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (delegate == null) {
664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return null;
674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return delegate.getAffineTransform();
704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public static boolean hasPerspective(Matrix m) {
734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (delegate == null) {
754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return delegate.hasPerspective();
794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
81251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    /**
82251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     * Sets the content of the matrix with the content of another matrix.
83251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     */
84251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public void set(Matrix_Delegate matrix) {
85251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
86251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
87251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
88251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    /**
89b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet     * Sets the content of the matrix with the content of another matrix represented as an array
90b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet     * of values.
91b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet     */
92b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    public void set(float[] values) {
93b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
94b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    }
95b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet
96b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    /**
97251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     * Resets the matrix to be the identity matrix.
98251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     */
99251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public void reset() {
100251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        reset(mValues);
101251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
102251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
103251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    /**
104251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     * Returns whether or not the matrix is identity.
105251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet     */
106251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public boolean isIdentity() {
107251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        for (int i = 0, k = 0; i < 3; i++) {
108251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet            for (int j = 0; j < 3; j++, k++) {
109251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet                if (mValues[k] != ((i==j) ? 1 : 0)) {
110251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet                    return false;
111251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet                }
112251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet            }
113251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        }
114251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
115251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        return true;
116251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    }
117251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet
118b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    public static float[] makeValues(AffineTransform matrix) {
119d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        float[] values = new float[MATRIX_SIZE];
120d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[0] = (float) matrix.getScaleX();
121d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[1] = (float) matrix.getShearX();
122d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[2] = (float) matrix.getTranslateX();
123d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[3] = (float) matrix.getShearY();
124d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[4] = (float) matrix.getScaleY();
125d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[5] = (float) matrix.getTranslateY();
126d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[6] = 0.f;
127d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[7] = 0.f;
128d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        values[8] = 1.f;
129d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
130b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet        return values;
131b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    }
132b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet
133b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    public static Matrix_Delegate make(AffineTransform matrix) {
134b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet        return new Matrix_Delegate(makeValues(matrix));
135d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
136d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
137d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    public boolean mapRect(RectF dst, RectF src) {
138d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        // array with 4 corners
139d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        float[] corners = new float[] {
140d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.left, src.top,
141d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.right, src.top,
142d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.right, src.bottom,
143d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet                src.left, src.bottom,
144d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        };
145d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
146d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        // apply the transform to them.
147d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        mapPoints(corners);
148d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
149d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
150d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
151d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
152d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
153d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
154d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
155d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
156d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
157d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
158d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
159d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
160d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Returns an {@link AffineTransform} matching the matrix.
1632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    public AffineTransform getAffineTransform() {
1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return getAffineTransform(mValues);
1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    public boolean hasPerspective() {
1692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
1702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- native methods ----
1754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1769a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
17784151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static long native_create(long native_src_or_zero) {
1784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // create the delegate
1794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate newDelegate = new Matrix_Delegate();
1804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // copy from values if needed.
1824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (native_src_or_zero > 0) {
1834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
1844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (oldDelegate != null) {
1854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                System.arraycopy(
1864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                        oldDelegate.mValues, 0,
1874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                        newDelegate.mValues, 0,
1884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                        MATRIX_SIZE);
1894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
1904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
1914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
192cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        return sManager.addNewDelegate(newDelegate);
1934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
1944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
1959a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
19684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_isIdentity(long native_object) {
1974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
1984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
1994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
2004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
202251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet        return d.isIdentity();
2034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2059a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
20684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_rectStaysRect(long native_object) {
2074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return true;
2104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
2134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2159a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
21684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_reset(long native_object) {
2174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        reset(d.mValues);
2234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2259a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
22684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_set(long native_object, long other) {
2274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate src = sManager.getDelegate(other);
2334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (src == null) {
2344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
2384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2409a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
24184151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setTranslate(long native_object, float dx, float dy) {
2424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(d.mValues, dx, dy);
2484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2509a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
25184151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy,
252cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
2534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues = getScale(sx, sy, px, py);
2594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2619a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
26284151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setScale(long native_object, float sx, float sy) {
2634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[0] = sx;
2694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[1] = 0;
2704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[2] = 0;
2714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[3] = 0;
2724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[4] = sy;
2734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[5] = 0;
2744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[6] = 0;
2754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[7] = 0;
2764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[8] = 1;
2774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2799a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
28084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees, float px, float py) {
2814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues = getRotate(degrees, px, py);
2874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2899a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
29084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setRotate(long native_object, float degrees) {
2914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
2924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
2934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
2944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
2954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setRotate(d.mValues, degrees);
2974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
2984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
2999a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
30084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue,
3014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
3024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
3054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
3084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
3104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(d.mValues, -px, -py);
3114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // scale
3134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getRotate(sinValue, cosValue));
3144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot
3154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getTranslate(px, py));
3164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3189a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
31984151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setSinCos(long native_object, float sinValue, float cosValue) {
3204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
3234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setRotate(d.mValues, sinValue, cosValue);
3264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3289a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
32984151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky,
330cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
3314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
3344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues = getSkew(kx, ky, px, py);
3374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3399a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
34084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setSkew(long native_object, float kx, float ky) {
3414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
3444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[0] = 1;
3474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[1] = kx;
3484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[2] = -0;
3494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[3] = ky;
3504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[4] = 1;
3514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[5] = 0;
3524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[6] = 0;
3534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[7] = 0;
3544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[8] = 1;
3554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3579a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
35884151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_setConcat(long native_object, long a, long b) {
3594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a == native_object) {
3604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return native_preConcat(native_object, b);
3614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } else if (b == native_object) {
3624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return native_postConcat(native_object, a);
3634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate a_mtx = sManager.getDelegate(a);
3714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a_mtx == null) {
3724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate b_mtx = sManager.getDelegate(b);
3764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (b_mtx == null) {
3774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
3814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3859a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
38684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preTranslate(long native_object, float dx, float dy) {
3874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
3884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
3894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
3904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
3914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getTranslate(dx, dy));
3934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
3944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
3954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
3969a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
39784151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preScale(long native_object, float sx, float sy,
3984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
3994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getScale(sx, sy, px, py));
4054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4089a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
40984151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preScale(long native_object, float sx, float sy) {
4104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getScale(sx, sy));
4164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4199a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
42084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preRotate(long native_object, float degrees,
421cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
4224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getRotate(degrees, px, py));
4284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4319a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
43284151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preRotate(long native_object, float degrees) {
4334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
4394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
4404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
4414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getRotate(sin, cos));
4434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4469a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
44784151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preSkew(long native_object, float kx, float ky,
4484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
4494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getSkew(kx, ky, px, py));
4554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4589a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
45984151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preSkew(long native_object, float kx, float ky) {
4604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(getSkew(kx, ky));
4664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4699a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
47084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_preConcat(long native_object, long other_matrix) {
4714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate other = sManager.getDelegate(other_matrix);
4777396348dfcfb45b7ad055f4c18cabbe5e8270d26Xavier Ducrohet        if (other == null) {
4784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.preTransform(other.mValues);
4824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4859a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
48684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postTranslate(long native_object, float dx, float dy) {
4874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
4884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
4894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
4904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
4914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getTranslate(dx, dy));
4934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
4944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
4954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
4969a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
49784151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postScale(long native_object, float sx, float sy,
4984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
4994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getScale(sx, sy, px, py));
5054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5089a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
50984151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postScale(long native_object, float sx, float sy) {
5104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getScale(sx, sy));
5164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5199a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
52084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postRotate(long native_object, float degrees,
521cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            float px, float py) {
5224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
527d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet        d.postTransform(getRotate(degrees, px, py));
5284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5319a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
53284151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postRotate(long native_object, float degrees) {
5334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getRotate(degrees));
5394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5429a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
54384151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postSkew(long native_object, float kx, float ky,
5444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float px, float py) {
5454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getSkew(kx, ky, px, py));
5514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5549a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
55584151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postSkew(long native_object, float kx, float ky) {
5564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(getSkew(kx, ky));
5624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5659a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
56684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_postConcat(long native_object, long other_matrix) {
5674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate other = sManager.getDelegate(other_matrix);
5737396348dfcfb45b7ad055f4c18cabbe5e8270d26Xavier Ducrohet        if (other == null) {
5744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.postTransform(other.mValues);
5784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
5794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
5804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5819a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
58284151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_setRectToRect(long native_object, RectF src,
583cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet            RectF dst, int stf) {
5844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
5854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
5864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (src.isEmpty()) {
5904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            reset(d.mValues);
5914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
5924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
5934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
5944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (dst.isEmpty()) {
5954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
5964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet               = d.mValues[6] = d.mValues[7] = 0;
5974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[8] = 1;
5984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } else {
5994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float    tx, sx = dst.width() / src.width();
6004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float    ty, sy = dst.height() / src.height();
6014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            boolean  xLarger = false;
6024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (stf != ScaleToFit.FILL.nativeInt) {
6044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (sx > sy) {
6054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    xLarger = true;
6064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    sx = sy;
6074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                } else {
6084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    sy = sx;
6094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
6104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
6114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            tx = dst.left - src.left * sx;
6134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            ty = dst.top - src.top * sy;
6144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
6154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                float diff;
6164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (xLarger) {
6184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    diff = dst.width() - src.width() * sy;
6194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                } else {
6204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    diff = dst.height() - src.height() * sy;
6214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
6224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (stf == ScaleToFit.CENTER.nativeInt) {
6244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    diff = diff / 2;
6254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
6264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                if (xLarger) {
6284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    tx += diff;
6294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                } else {
6304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                    ty += diff;
6314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                }
6324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
6334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[0] = sx;
6354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[4] = sy;
6364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[2] = tx;
6374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[5] = ty;
6384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
6394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // shared cleanup
6424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        d.mValues[8] = 1;
6434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
6444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6469a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
64784151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_setPolyToPoly(long native_object, float[] src, int srcIndex,
6484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float[] dst, int dstIndex, int pointCount) {
6494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // FIXME
650918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
65110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                "Matrix.setPolyToPoly is not supported.",
65251a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet                null, null /*data*/);
65310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        return false;
6544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6569a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
65740582000e078361d2e5995abdf25f923fa656e86Narayan Kamath    /*package*/ static boolean native_invert(long native_object, long inverse) {
6584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
6644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (inv_mtx == null) {
6654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        try {
6692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            AffineTransform affineTransform = d.getAffineTransform();
6704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            AffineTransform inverseTransform = affineTransform.createInverse();
6714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
6724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
6734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
6744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
6754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
6764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
6774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return true;
6794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } catch (NoninvertibleTransformException e) {
6804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
6814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6849a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
68584151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_mapPoints(long native_object, float[] dst, int dstIndex,
6864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            float[] src, int srcIndex, int ptCount, boolean isPts) {
6874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
6884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
6894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
6904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (isPts) {
6934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
6944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        } else {
69510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
6964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
6974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
6984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
6999a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
70084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_mapRect(long native_object, RectF dst, RectF src) {
7014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
7024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
7034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
7044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
706d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        return d.mapRect(dst, src);
7074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7099a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
71084151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static float native_mapRadius(long native_object, float radius) {
71110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
71210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        if (d == null) {
71310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet            return 0.f;
71410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        }
71510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
71610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        float[] src = new float[] { radius, 0.f, 0.f, radius };
71710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        d.mapVectors(src, 0, src, 0, 2);
71810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
71933253a4baa6279f81a73425b49dfb6abe5f5416eNeil Fuller        float l1 = (float) Math.hypot(src[0], src[1]);
72033253a4baa6279f81a73425b49dfb6abe5f5416eNeil Fuller        float l2 = (float) Math.hypot(src[2], src[3]);
72110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        return (float) Math.sqrt(l1 * l2);
7224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7249a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
72584151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_getValues(long native_object, float[] values) {
7264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
7274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
7284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
7294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
7324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7349a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
73584151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void native_setValues(long native_object, float[] values) {
7364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
7374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
7384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
7394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
7424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7449a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
74584151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static boolean native_equals(long native_a, long native_b) {
7464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate a = sManager.getDelegate(native_a);
7474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a == null) {
7484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
7494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate b = sManager.getDelegate(native_b);
7524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (b == null) {
7534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
7544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
7574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (a.mValues[i] != b.mValues[i]) {
7584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                return false;
7594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
7604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
7634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7659a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
76684151432e7ead6666eb8cf6377bff577b2027694Narayan Kamath    /*package*/ static void finalizer(long native_instance) {
767cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        sManager.removeJavaReferenceFor(native_instance);
7684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- Private helper methods ----
7714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7725802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
7734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // the AffineTransform constructor takes the value in a different order
7744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // for a matrix [ 0 1 2 ]
7754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        //              [ 3 4 5 ]
7764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // the order is 0, 3, 1, 4, 2, 5...
7774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new AffineTransform(
7785802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet                matrix[0], matrix[3], matrix[1],
7795802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet                matrix[4], matrix[2], matrix[5]);
7804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
7834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Reset a matrix to the identity
7844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
7854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private static void reset(float[] mtx) {
7864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        for (int i = 0, k = 0; i < 3; i++) {
7874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            for (int j = 0; j < 3; j++, k++) {
7884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                mtx[k] = ((i==j) ? 1 : 0);
7894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
7904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kIdentity_Mask      = 0;
7954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
7964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
7974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
7984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
7994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kRectStaysRect_Mask = 0x10;
8004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kUnknown_Mask       = 0x80;
8024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAllMasks           = kTranslate_Mask |
8054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kScale_Mask |
8064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kAffine_Mask |
8074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kPerspective_Mask |
8084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kRectStaysRect_Mask;
8094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // these guys align with the masks, so we can compute a mask from a variable 0/1
8114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kTranslate_Shift = 0;
8134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kScale_Shift = 1;
8154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAffine_Shift = 2;
8174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kPerspective_Shift = 3;
8194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kRectStaysRect_Shift = 4;
8204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private int computeTypeMask() {
8224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        int mask = 0;
8234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
8254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kPerspective_Mask;
8264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (mValues[2] != 0. || mValues[5] != 0.) {
8294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kTranslate_Mask;
8304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m00 = mValues[0];
8334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m01 = mValues[1];
8344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m10 = mValues[3];
8354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m11 = mValues[4];
8364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (m01 != 0. || m10 != 0.) {
8384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kAffine_Mask;
8394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (m00 != 1. || m11 != 1.) {
8424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kScale_Mask;
8434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if ((mask & kPerspective_Mask) == 0) {
8464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // map non-zero to 1
8474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im00 = m00 != 0 ? 1 : 0;
8484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im01 = m01 != 0 ? 1 : 0;
8494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im10 = m10 != 0 ? 1 : 0;
8504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im11 = m11 != 0 ? 1 : 0;
8514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // record if the (p)rimary and (s)econdary diagonals are all 0 or
8534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // all non-zero (answer is 0 or 1)
8544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
8554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int dp1 = im00 & im11;        // true if both are 1
8564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
8574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int ds1 = im01 & im10;        // true if both are 1
8584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // return 1 if primary is 1 and secondary is 0 or
8604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // primary is 0 and secondary is 1
8614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
8624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return mask;
8654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
867d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet    private Matrix_Delegate() {
868d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet        reset();
869d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet    }
870d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet
871d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    private Matrix_Delegate(float[] values) {
872d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
873d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
874d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
8754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds the given transformation to the current Matrix
8774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does this = this*matrix
8784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param matrix
8794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
8804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private void postTransform(float[] matrix) {
8814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
8824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, mValues, matrix);
8834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        mValues = tmp;
8844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds the given transformation to the current Matrix
8884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does this = matrix*this
8894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param matrix
8904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
8914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private void preTransform(float[] matrix) {
8924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
8934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, matrix, mValues);
8944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        mValues = tmp;
8954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Apply this matrix to the array of 2D points specified by src, and write
8994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * the transformed points into the array of points specified by dst. The
9004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * two arrays represent their "points" as pairs of floats [x, y].
9014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      *
9024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param dst   The array of dst points (x,y pairs)
9034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param dstIndex The index of the first [x,y] pair of dst floats
9044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param src   The array of src points (x,y pairs)
9054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param srcIndex The index of the first [x,y] pair of src floats
9064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param pointCount The number of points (x,y pairs) to transform
9074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      */
9084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
9104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                           int pointCount) {
91110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         final int count = pointCount * 2;
9124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         float[] tmpDest = dst;
9144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         boolean inPlace = dst == src;
9154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         if (inPlace) {
91610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             tmpDest = new float[dstIndex + count];
9174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
9184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
91910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         for (int i = 0 ; i < count ; i += 2) {
9204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             // just in case we are doing in place, we better put this in temp vars
9214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             float x = mValues[0] * src[i + srcIndex] +
9224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[1] * src[i + srcIndex + 1] +
9234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[2];
9244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             float y = mValues[3] * src[i + srcIndex] +
9254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[4] * src[i + srcIndex + 1] +
9264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[5];
9274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             tmpDest[i + dstIndex]     = x;
9294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             tmpDest[i + dstIndex + 1] = y;
9304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
9314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         if (inPlace) {
93310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
9344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
9354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     }
9364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     /**
9384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * Apply this matrix to the array of 2D points, and write the transformed
9394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * points back into the array
9404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      *
9414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
9424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      */
9434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     private void mapPoints(float[] pts) {
9454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         mapPoints(pts, 0, pts, 0, pts.length >> 1);
9464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     }
9474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
94810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
94910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         if (hasPerspective()) {
95010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // transform the (0,0) point
95110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             float[] origin = new float[] { 0.f, 0.f};
95210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             mapPoints(origin);
95310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
95410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // translate the vector data as points
95510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
95610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
95710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // then substract the transformed origin.
95810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             final int count = ptCount * 2;
95910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             for (int i = 0 ; i < count ; i += 2) {
96010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
96110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
96210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             }
96310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         } else {
96410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // make a copy of the matrix
96510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             Matrix_Delegate copy = new Matrix_Delegate(mValues);
96610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
96710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // remove the translation
96810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             setTranslate(copy.mValues, 0, 0);
96910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
97010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // map the content as points.
97110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
97210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         }
97310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     }
97410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
9754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
9764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * multiply two matrices and store them in a 3rd.
9774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does dest = a*b
9784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * dest cannot be the same as a or b.
9794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
9805802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
9814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // first row
9824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
9834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
9844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
9854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // 2nd row
9874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
9884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
9894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
9904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // 3rd row
9924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
9934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
9944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
9954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
9964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
9984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns a matrix that represents a given translate
9994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param dx
10004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param dy
10014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @return
10024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
10035802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getTranslate(float dx, float dy) {
10044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setTranslate(new float[9], dx, dy);
10054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10075802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
10084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = 1;
10094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = 0;
10104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = dx;
10114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = 0;
10124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = 1;
10134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = dy;
10144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = 0;
10154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = 0;
10164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = 1;
10174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return dest;
10184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10205802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getScale(float sx, float sy) {
10214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
10224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
10254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns a matrix that represents the given scale info.
10264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param sx
10274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param sy
10284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param px
10294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param py
10304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
10315802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
10324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
10334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
10344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
10364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate tmp so that the pivot is in 0,0
10384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
10394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // scale into tmp2
10414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, getScale(sx, sy));
10424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
10444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
10454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
10474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10505802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float degrees) {
10514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return getRotate(sin, cos);
10564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10585802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float sin, float cos) {
10594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setRotate(new float[9], sin, cos);
10604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10625802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setRotate(float[] dest, float degrees) {
10634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setRotate(dest, sin, cos);
10684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10705802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
10714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = cos;
10724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = -sin;
10734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = 0;
10744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = sin;
10754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = cos;
10764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = 0;
10774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = 0;
10784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = 0;
10794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = 1;
10804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return dest;
10814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10835802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float degrees, float px, float py) {
10844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
10854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
10864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
10884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
10904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
10914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // rotate into tmp2
10934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, getRotate(sin, cos));
10974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
10994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
11004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
11024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
11034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11045802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getSkew(float kx, float ky) {
11054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
11064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
11074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11085802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
11094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
11104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
11114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
11134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
11154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
11164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // skew into tmp2
11184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
11194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
11204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
11214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
11234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
11244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet}
1125