package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Matrix.ScaleToFit;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
/**
* Delegate implementing the native methods of android.graphics.Matrix
*
* Through the layoutlib_create tool, the original native methods of Matrix have been replaced
* by calls to methods of the same name in this delegate class.
*
* This class behaves like the original native implementation, but in Java, keeping previously
* native data into its own objects and mapping them to int that are sent back and forth between
* it and the original Matrix class.
*
* @see DelegateManager
*
*/
public final class Matrix_Delegate {
private final static int MATRIX_SIZE = 9;
// ---- delegate manager ----
private static final DelegateManager<Matrix_Delegate> sManager =
new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
// ---- delegate data ----
private float mValues[] = new float[MATRIX_SIZE];
// ---- Public Helper methods ----
public static Matrix_Delegate getDelegate(int native_instance) {
return sManager.getDelegate(native_instance);
}
/**
* Returns an {@link AffineTransform} matching the given Matrix.
*/
public static AffineTransform getAffineTransform(Matrix m) {
Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
if (delegate == null) {
return null;
}
return delegate.getAffineTransform();
}
public static boolean hasPerspective(Matrix m) {
Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
if (delegate == null) {
return false;
}
return delegate.hasPerspective();
}
/**
* Sets the content of the matrix with the content of another matrix.
*/
public void set(Matrix_Delegate matrix) {
System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
}
/**
* Sets the content of the matrix with the content of another matrix represented as an array
* of values.
*/
public void set(float[] values) {
System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
}
/**
* Resets the matrix to be the identity matrix.
*/
public void reset() {
reset(mValues);
}
/**
* Returns whether or not the matrix is identity.
*/
public boolean isIdentity() {
for (int i = 0, k = 0; i < 3; i++) {
for (int j = 0; j < 3; j++, k++) {
if (mValues[k] != ((i==j) ? 1 : 0)) {
return false;
}
}
}
return true;
}
public static float[] makeValues(AffineTransform matrix) {
float[] values = new float[MATRIX_SIZE];
values[0] = (float) matrix.getScaleX();
values[1] = (float) matrix.getShearX();
values[2] = (float) matrix.getTranslateX();
values[3] = (float) matrix.getShearY();
values[4] = (float) matrix.getScaleY();
values[5] = (float) matrix.getTranslateY();
values[6] = 0.f;
values[7] = 0.f;
values[8] = 1.f;
return values;
}
public static Matrix_Delegate make(AffineTransform matrix) {
return new Matrix_Delegate(makeValues(matrix));
}
public boolean mapRect(RectF dst, RectF src) {
// array with 4 corners
float[] corners = new float[] {
src.left, src.top,
src.right, src.top,
src.right, src.bottom,
src.left, src.bottom,
};
// apply the transform to them.
mapPoints(corners);
// now put the result in the rect. We take the min/max of Xs and min/max of Ys
dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
return (computeTypeMask() & kRectStaysRect_Mask) != 0;
}
/**
* Returns an {@link AffineTransform} matching the matrix.
*/
public AffineTransform getAffineTransform() {
return getAffineTransform(mValues);
}
public boolean hasPerspective() {
return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
}
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static int native_create(int native_src_or_zero) {
// create the delegate
Matrix_Delegate newDelegate = new Matrix_Delegate();
// copy from values if needed.
if (native_src_or_zero > 0) {
Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
if (oldDelegate != null) {
System.arraycopy(
oldDelegate.mValues, 0,
newDelegate.mValues, 0,
MATRIX_SIZE);
}
}
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static boolean native_isIdentity(int native_object) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return false;
}
return d.isIdentity();
}
@LayoutlibDelegate
/*package*/ static boolean native_rectStaysRect(int native_object) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return true;
}
return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
}
@LayoutlibDelegate
/*package*/ static void native_reset(int native_object) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return;
}
reset(d.mValues);
}
@LayoutlibDelegate
/*package*/ static void native_set(int native_object, int other) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return;
}
Matrix_Delegate src = sManager.getDelegate(other);
if (src == null) {
return;
}
System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
}
@LayoutlibDelegate
/*package*/ static void native_setTranslate(int native_object, float dx, float dy) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return;
}
setTranslate(d.mValues, dx, dy);
}
@LayoutlibDelegate
/*package*/ static void native_setScale(int native_object, float sx, float sy,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return;
}
d.mValues = getScale(sx, sy, px, py);
}
@LayoutlibDelegate
/*package*/ static void native_setScale(int native_object, float sx, float sy) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return;
}
d.mValues[0] = sx;
d.mValues[1] = 0;
d.mValues[2] = 0;
d.mValues[3] = 0;
d.mValues[4] = sy;
d.mValues[5] = 0;
d.mValues[6] = 0;
d.mValues[7] = 0;
d.mValues[8] = 1;
}
@LayoutlibDelegate
/*package*/ static void native_setRotate(int native_object, float degrees, float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
return;
}
d.mValues = getRotate(degrees, p