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
56251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet    public static Matrix_Delegate getDelegate(int 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
1775de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static int native_create(int 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
1965de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_isIdentity(int 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
2065de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_rectStaysRect(int 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
2165de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_reset(int 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
2265de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_set(int native_object, int 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
2415de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setTranslate(int 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
251cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static void native_setScale(int 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
2625de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setScale(int 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
2805de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setRotate(int 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
2905de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setRotate(int 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
3005de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setSinCos(int 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
3195de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setSinCos(int 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
329cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static void native_setSkew(int 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
3405de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setSkew(int 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
3585de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_setConcat(int native_object, int a, int 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
3865de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preTranslate(int 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
3975de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preScale(int 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
4095de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preScale(int 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
420cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static boolean native_preRotate(int 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
4325de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preRotate(int 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
4475de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preSkew(int 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
4595de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preSkew(int 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
4705de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_preConcat(int native_object, int 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
4865de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postTranslate(int 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
4975de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postScale(int 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
5095de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postScale(int 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
520cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static boolean native_postRotate(int 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
5325de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postRotate(int 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
5435de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postSkew(int 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
5555de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postSkew(int 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
5665de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_postConcat(int native_object, int 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
582cfdc784b6cdcbbb2bf2ba4d53d9a9eb2c37278a3Xavier Ducrohet    /*package*/ static boolean native_setRectToRect(int 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
6475de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_setPolyToPoly(int 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
6575de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_invert(int native_object, int 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
6855de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_mapPoints(int 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
7005de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_mapRect(int 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
7105de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static float native_mapRadius(int 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
71910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        float l1 = getPointLength(src, 0);
72010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        float l2 = getPointLength(src, 2);
72110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
72210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet        return (float) Math.sqrt(l1 * l2);
7234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7259a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
7265de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_getValues(int native_object, float[] values) {
7274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
7284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
7294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
7304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
7334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7359a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
7365de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void native_setValues(int native_object, float[] values) {
7374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate d = sManager.getDelegate(native_object);
7384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (d == null) {
7394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return;
7404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
7434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7459a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
7465de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static boolean native_equals(int native_a, int native_b) {
7474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate a = sManager.getDelegate(native_a);
7484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (a == null) {
7494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
7504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        Matrix_Delegate b = sManager.getDelegate(native_b);
7534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (b == null) {
7544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return false;
7554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
7584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            if (a.mValues[i] != b.mValues[i]) {
7594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                return false;
7604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
7614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return true;
7644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7669a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
7675de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohet    /*package*/ static void finalizer(int native_instance) {
768cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        sManager.removeJavaReferenceFor(native_instance);
7694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // ---- Private helper methods ----
7724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7735802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
7744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // the AffineTransform constructor takes the value in a different order
7754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // for a matrix [ 0 1 2 ]
7764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        //              [ 3 4 5 ]
7774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // the order is 0, 3, 1, 4, 2, 5...
7784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new AffineTransform(
7795802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet                matrix[0], matrix[3], matrix[1],
7805802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet                matrix[4], matrix[2], matrix[5]);
7814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
7844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Reset a matrix to the identity
7854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
7864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private static void reset(float[] mtx) {
7874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        for (int i = 0, k = 0; i < 3; i++) {
7884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            for (int j = 0; j < 3; j++, k++) {
7894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                mtx[k] = ((i==j) ? 1 : 0);
7904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            }
7914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
7924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
7934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
7944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
7954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kIdentity_Mask      = 0;
7964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
7974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
7984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
7994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
8004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kRectStaysRect_Mask = 0x10;
8014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kUnknown_Mask       = 0x80;
8034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAllMasks           = kTranslate_Mask |
8064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kScale_Mask |
8074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kAffine_Mask |
8084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kPerspective_Mask |
8094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                                                   kRectStaysRect_Mask;
8104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    // these guys align with the masks, so we can compute a mask from a variable 0/1
8124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kTranslate_Shift = 0;
8144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kScale_Shift = 1;
8164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kAffine_Shift = 2;
8184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    @SuppressWarnings("unused")
8194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kPerspective_Shift = 3;
8204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final static int kRectStaysRect_Shift = 4;
8214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private int computeTypeMask() {
8234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        int mask = 0;
8244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
8264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kPerspective_Mask;
8274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (mValues[2] != 0. || mValues[5] != 0.) {
8304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kTranslate_Mask;
8314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m00 = mValues[0];
8344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m01 = mValues[1];
8354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m10 = mValues[3];
8364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float m11 = mValues[4];
8374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (m01 != 0. || m10 != 0.) {
8394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kAffine_Mask;
8404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if (m00 != 1. || m11 != 1.) {
8434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= kScale_Mask;
8444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        if ((mask & kPerspective_Mask) == 0) {
8474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // map non-zero to 1
8484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im00 = m00 != 0 ? 1 : 0;
8494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im01 = m01 != 0 ? 1 : 0;
8504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im10 = m10 != 0 ? 1 : 0;
8514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int im11 = m11 != 0 ? 1 : 0;
8524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // record if the (p)rimary and (s)econdary diagonals are all 0 or
8544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // all non-zero (answer is 0 or 1)
8554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
8564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int dp1 = im00 & im11;        // true if both are 1
8574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
8584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int ds1 = im01 & im10;        // true if both are 1
8594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // return 1 if primary is 1 and secondary is 0 or
8614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            // primary is 0 and secondary is 1
8624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
8634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
8644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return mask;
8664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
868d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet    private Matrix_Delegate() {
869d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet        reset();
870d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet    }
871d73868859bf71bd98496157b94e21ef95fadd495Xavier Ducrohet
872d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    private Matrix_Delegate(float[] values) {
873d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
874d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet    }
875d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohet
8764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds the given transformation to the current Matrix
8784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does this = this*matrix
8794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param matrix
8804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
8814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private void postTransform(float[] matrix) {
8824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
8834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, mValues, matrix);
8844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        mValues = tmp;
8854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds the given transformation to the current Matrix
8894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does this = matrix*this
8904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param matrix
8914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
8924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private void preTransform(float[] matrix) {
8934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
8944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, matrix, mValues);
8954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        mValues = tmp;
8964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
8974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
8984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
8994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Apply this matrix to the array of 2D points specified by src, and write
9004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * the transformed points into the array of points specified by dst. The
9014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * two arrays represent their "points" as pairs of floats [x, y].
9024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      *
9034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param dst   The array of dst points (x,y pairs)
9044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param dstIndex The index of the first [x,y] pair of dst floats
9054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param src   The array of src points (x,y pairs)
9064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param srcIndex The index of the first [x,y] pair of src floats
9074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param pointCount The number of points (x,y pairs) to transform
9084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      */
9094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
9114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                           int pointCount) {
91210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         final int count = pointCount * 2;
9134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         float[] tmpDest = dst;
9154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         boolean inPlace = dst == src;
9164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         if (inPlace) {
91710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             tmpDest = new float[dstIndex + count];
9184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
9194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
92010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         for (int i = 0 ; i < count ; i += 2) {
9214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             // just in case we are doing in place, we better put this in temp vars
9224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             float x = mValues[0] * src[i + srcIndex] +
9234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[1] * src[i + srcIndex + 1] +
9244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[2];
9254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             float y = mValues[3] * src[i + srcIndex] +
9264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[4] * src[i + srcIndex + 1] +
9274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet                       mValues[5];
9284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             tmpDest[i + dstIndex]     = x;
9304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet             tmpDest[i + dstIndex + 1] = y;
9314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
9324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         if (inPlace) {
93410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
9354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         }
9364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     }
9374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     /**
9394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * Apply this matrix to the array of 2D points, and write the transformed
9404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * points back into the array
9414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      *
9424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
9434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet      */
9444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     private void mapPoints(float[] pts) {
9464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet         mapPoints(pts, 0, pts, 0, pts.length >> 1);
9474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     }
9484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
94910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
95010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         if (hasPerspective()) {
95110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // transform the (0,0) point
95210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             float[] origin = new float[] { 0.f, 0.f};
95310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             mapPoints(origin);
95410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
95510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // translate the vector data as points
95610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
95710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
95810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // then substract the transformed origin.
95910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             final int count = ptCount * 2;
96010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             for (int i = 0 ; i < count ; i += 2) {
96110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
96210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
96310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             }
96410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         } else {
96510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // make a copy of the matrix
96610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             Matrix_Delegate copy = new Matrix_Delegate(mValues);
96710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
96810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // remove the translation
96910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             setTranslate(copy.mValues, 0, 0);
97010af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
97110af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             // map the content as points.
97210af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
97310af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         }
97410af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     }
97510af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
97610af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     private static float getPointLength(float[] src, int index) {
97710af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet         return (float) Math.sqrt(src[index] * src[index] + src[index + 1] * src[index + 1]);
97810af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet     }
97910af738336cb18c5d86710b2961d91e2d3e8d410Xavier Ducrohet
9804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
9814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * multiply two matrices and store them in a 3rd.
9824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * <p/>This in effect does dest = a*b
9834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * dest cannot be the same as a or b.
9844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
9855802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet     /*package*/ static void multiply(float dest[], float[] a, float[] b) {
9864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // first row
9874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
9884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
9894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
9904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // 2nd row
9924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
9934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
9944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
9954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
9964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // 3rd row
9974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
9984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
9994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
10004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
10034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns a matrix that represents a given translate
10044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param dx
10054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param dy
10064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @return
10074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
10085802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getTranslate(float dx, float dy) {
10094f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setTranslate(new float[9], dx, dy);
10104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10125802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
10134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = 1;
10144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = 0;
10154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = dx;
10164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = 0;
10174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = 1;
10184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = dy;
10194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = 0;
10204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = 0;
10214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = 1;
10224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return dest;
10234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10255802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getScale(float sx, float sy) {
10264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
10274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
10304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns a matrix that represents the given scale info.
10314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param sx
10324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param sy
10334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param px
10344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param py
10354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
10365802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
10374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
10384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
10394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
10414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate tmp so that the pivot is in 0,0
10434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
10444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // scale into tmp2
10464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, getScale(sx, sy));
10474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
10494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
10504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
10524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10555802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float degrees) {
10564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return getRotate(sin, cos);
10614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10635802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float sin, float cos) {
10644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setRotate(new float[9], sin, cos);
10654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10675802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setRotate(float[] dest, float degrees) {
10684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
10704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
10714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return setRotate(dest, sin, cos);
10734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10755802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
10764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[0] = cos;
10774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[1] = -sin;
10784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[2] = 0;
10794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[3] = sin;
10804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[4] = cos;
10814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[5] = 0;
10824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[6] = 0;
10834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[7] = 0;
10844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        dest[8] = 1;
10854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return dest;
10864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
10874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10885802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getRotate(float degrees, float px, float py) {
10894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
10904f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
10914f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10924f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
10934f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10944f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
10954f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
10964f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
10974f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // rotate into tmp2
10984f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        double rad = Math.toRadians(degrees);
10994f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float cos = (float)Math.cos(rad);
11004f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float sin = (float)Math.sin(rad);
11014f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, getRotate(sin, cos));
11024f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11034f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
11044f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
11054f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11064f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
11074f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
11084f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11095802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getSkew(float kx, float ky) {
11104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
11114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
11124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11135802deabf06a0754c36e990ce2af7b5c8727e543Xavier Ducrohet    /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
11144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp = new float[9];
11154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        float[] tmp2 = new float[9];
11164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // TODO: do it in one pass
11184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate so that the pivot is in 0,0
11204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        setTranslate(tmp, -px, -py);
11214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // skew into tmp2
11234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
11244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        // translate back the pivot back into tmp
11254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        multiply(tmp, tmp2, getTranslate(px, py));
11264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
11274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        return tmp;
11284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
11294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet}
1130