diff options
Diffstat (limited to 'tools/layoutlib/bridge/src/android/graphics/Matrix.java')
-rw-r--r-- | tools/layoutlib/bridge/src/android/graphics/Matrix.java | 1032 |
1 files changed, 0 insertions, 1032 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix.java b/tools/layoutlib/bridge/src/android/graphics/Matrix.java deleted file mode 100644 index 9e30671..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix.java +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; - - -/** - * A matrix implementation overridden by the LayoutLib bridge. - */ -public class Matrix extends _Original_Matrix { - - float mValues[] = new float[9]; - - /** - * Create an identity matrix - */ - public Matrix() { - reset(); - } - - /** - * Create a matrix that is a (deep) copy of src - * @param src The matrix to copy into this matrix - */ - public Matrix(Matrix src) { - set(src); - } - - /** - * Creates a Matrix object from the float array. The array becomes the internal storage - * of the object. - * @param data - */ - private Matrix(float[] data) { - assert data.length != 9; - mValues = data; - } - - //---------- Custom Methods - - /** - * Adds the given transformation to the current Matrix - * <p/>This in effect does this = this*matrix - * @param matrix - */ - private void addTransform(float[] matrix) { - float[] tmp = new float[9]; - - // first row - tmp[0] = matrix[0] * mValues[0] + matrix[1] * mValues[3] + matrix[2] * mValues[6]; - tmp[1] = matrix[0] * mValues[1] + matrix[1] * mValues[4] + matrix[2] * mValues[7]; - tmp[2] = matrix[0] * mValues[2] + matrix[1] * mValues[5] + matrix[2] * mValues[8]; - - // 2nd row - tmp[3] = matrix[3] * mValues[0] + matrix[4] * mValues[3] + matrix[5] * mValues[6]; - tmp[4] = matrix[3] * mValues[1] + matrix[4] * mValues[4] + matrix[5] * mValues[7]; - tmp[5] = matrix[3] * mValues[2] + matrix[4] * mValues[5] + matrix[5] * mValues[8]; - - // 3rd row - tmp[6] = matrix[6] * mValues[0] + matrix[7] * mValues[3] + matrix[8] * mValues[6]; - tmp[7] = matrix[6] * mValues[1] + matrix[7] * mValues[4] + matrix[8] * mValues[7]; - tmp[8] = matrix[6] * mValues[2] + matrix[7] * mValues[5] + matrix[8] * mValues[8]; - - // copy the result over to mValues - mValues = tmp; - } - - public AffineTransform getTransform() { - // the AffineTransform constructor takes the value in a different order - // for a matrix [ 0 1 2 ] - // [ 3 4 5 ] - // the order is 0, 3, 1, 4, 2, 5... - return new AffineTransform(mValues[0], mValues[3], mValues[1], - mValues[4], mValues[2], mValues[5]); - } - - public boolean hasPerspective() { - return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1); - } - - //---------- - - /** - * Returns true if the matrix is identity. - * This maybe faster than testing if (getType() == 0) - */ - @Override - 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; - } - - /** - * Returns true if will map a rectangle to another rectangle. This can be - * true if the matrix is identity, scale-only, or rotates a multiple of 90 - * degrees. - */ - @Override - public boolean rectStaysRect() { - return (computeTypeMask() & kRectStaysRect_Mask) != 0; - } - - /** - * (deep) copy the src matrix into this matrix. If src is null, reset this - * matrix to the identity matrix. - */ - public void set(Matrix src) { - if (src == null) { - reset(); - } else { - System.arraycopy(src.mValues, 0, mValues, 0, mValues.length); - } - } - - @Override - public void set(_Original_Matrix src) { - throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); - } - - /** Returns true if obj is a Matrix and its values equal our values. - */ - @Override - public boolean equals(Object obj) { - if (obj != null && obj instanceof Matrix) { - Matrix matrix = (Matrix)obj; - for (int i = 0 ; i < 9 ; i++) { - if (mValues[i] != matrix.mValues[i]) { - return false; - } - } - - return true; - } - - return false; - } - - /** Set the matrix to identity */ - @Override - public void reset() { - for (int i = 0, k = 0; i < 3; i++) { - for (int j = 0; j < 3; j++, k++) { - mValues[k] = ((i==j) ? 1 : 0); - } - } - } - - /** Set the matrix to translate by (dx, dy). */ - @Override - public void setTranslate(float dx, float dy) { - mValues[0] = 1; - mValues[1] = 0; - mValues[2] = dx; - mValues[3] = 0; - mValues[4] = 1; - mValues[5] = dy; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - } - - /** - * Set the matrix to scale by sx and sy, with a pivot point at (px, py). - * The pivot point is the coordinate that should remain unchanged by the - * specified transformation. - */ - @Override - public void setScale(float sx, float sy, float px, float py) { - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - mValues[0] = 1; - mValues[1] = 0; - mValues[2] = -px; - mValues[3] = 0; - mValues[4] = 1; - mValues[5] = -py; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - - // scale - addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - } - - /** Set the matrix to scale by sx and sy. */ - @Override - public void setScale(float sx, float sy) { - mValues[0] = sx; - mValues[1] = 0; - mValues[2] = 0; - mValues[3] = 0; - mValues[4] = sy; - mValues[5] = 0; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - } - - /** - * Set the matrix to rotate by the specified number of degrees, with a pivot - * point at (px, py). The pivot point is the coordinate that should remain - * unchanged by the specified transformation. - */ - @Override - public void setRotate(float degrees, float px, float py) { - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - mValues[0] = 1; - mValues[1] = 0; - mValues[2] = -px; - mValues[3] = 0; - mValues[4] = 1; - mValues[5] = -py; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - - // scale - double rad = Math.toRadians(degrees); - float cos = (float)Math.cos(rad); - float sin = (float)Math.sin(rad); - addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - } - - /** - * Set the matrix to rotate about (0,0) by the specified number of degrees. - */ - @Override - public void setRotate(float degrees) { - double rad = Math.toRadians(degrees); - float cos = (float)Math.cos(rad); - float sin = (float)Math.sin(rad); - - mValues[0] = cos; - mValues[1] = -sin; - mValues[2] = 0; - mValues[3] = sin; - mValues[4] = cos; - mValues[5] = 0; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - } - - /** - * Set the matrix to rotate by the specified sine and cosine values, with a - * pivot point at (px, py). The pivot point is the coordinate that should - * remain unchanged by the specified transformation. - */ - @Override - public void setSinCos(float sinValue, float cosValue, float px, float py) { - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - mValues[0] = 1; - mValues[1] = 0; - mValues[2] = -px; - mValues[3] = 0; - mValues[4] = 1; - mValues[5] = -py; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - - // scale - addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - } - - /** Set the matrix to rotate by the specified sine and cosine values. */ - @Override - public void setSinCos(float sinValue, float cosValue) { - mValues[0] = cosValue; - mValues[1] = -sinValue; - mValues[2] = 0; - mValues[3] = sinValue; - mValues[4] = cosValue; - mValues[5] = 0; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - } - - /** - * Set the matrix to skew by sx and sy, with a pivot point at (px, py). - * The pivot point is the coordinate that should remain unchanged by the - * specified transformation. - */ - @Override - public void setSkew(float kx, float ky, float px, float py) { - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - mValues[0] = 1; - mValues[1] = 0; - mValues[2] = -px; - mValues[3] = 0; - mValues[4] = 1; - mValues[5] = -py; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - - // scale - addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - } - - /** Set the matrix to skew by sx and sy. */ - @Override - public void setSkew(float kx, float ky) { - mValues[0] = 1; - mValues[1] = kx; - mValues[2] = -0; - mValues[3] = ky; - mValues[4] = 1; - mValues[5] = 0; - mValues[6] = 0; - mValues[7] = 0; - mValues[8] = 1; - } - - /** - * Set the matrix to the concatenation of the two specified matrices, - * returning true if the the result can be represented. Either of the two - * matrices may also be the target matrix. this = a * b - */ - public boolean setConcat(Matrix a, Matrix b) { - if (a == this) { - preConcat(b); - } else if (b == this) { - postConcat(b); - } else { - Matrix tmp = new Matrix(b); - tmp.addTransform(a.mValues); - set(tmp); - } - - return true; - } - - @Override - public boolean setConcat(_Original_Matrix a, _Original_Matrix b) { - throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); - } - - /** - * Preconcats the matrix with the specified translation. - * M' = M * T(dx, dy) - */ - @Override - public boolean preTranslate(float dx, float dy) { - // create a matrix that will be multiply by this - Matrix m = new Matrix(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 }); - m.addTransform(this.mValues); - - System.arraycopy(m.mValues, 0, mValues, 0, 9); - return true; - } - - /** - * Preconcats the matrix with the specified scale. - * M' = M * S(sx, sy, px, py) - */ - @Override - public boolean preScale(float sx, float sy, float px, float py) { - Matrix m = new Matrix(); - m.setScale(sx, sy, px, py); - m.addTransform(mValues); - set(m); - - return true; - } - - /** - * Preconcats the matrix with the specified scale. - * M' = M * S(sx, sy) - */ - @Override - public boolean preScale(float sx, float sy) { - Matrix m = new Matrix(); - m.setScale(sx, sy); - m.addTransform(mValues); - set(m); - - return true; - } - - /** - * Preconcats the matrix with the specified rotation. - * M' = M * R(degrees, px, py) - */ - @Override - public boolean preRotate(float degrees, float px, float py) { - Matrix m = new Matrix(); - m.setRotate(degrees, px, py); - m.addTransform(mValues); - set(m); - - return true; - } - - /** - * Preconcats the matrix with the specified rotation. - * M' = M * R(degrees) - */ - @Override - public boolean preRotate(float degrees) { - Matrix m = new Matrix(); - m.setRotate(degrees); - m.addTransform(mValues); - set(m); - - return true; - } - - /** - * Preconcats the matrix with the specified skew. - * M' = M * K(kx, ky, px, py) - */ - @Override - public boolean preSkew(float kx, float ky, float px, float py) { - Matrix m = new Matrix(); - m.setSkew(kx, ky, px, py); - m.addTransform(mValues); - set(m); - - return true; - } - - /** - * Preconcats the matrix with the specified skew. - * M' = M * K(kx, ky) - */ - @Override - public boolean preSkew(float kx, float ky) { - Matrix m = new Matrix(); - m.setSkew(kx, ky); - m.addTransform(mValues); - set(m); - - return true; - } - - /** - * Preconcats the matrix with the specified matrix. - * M' = M * other - */ - public boolean preConcat(Matrix other) { - Matrix m = new Matrix(other); - other.addTransform(mValues); - set(m); - - return true; - } - - @Override - public boolean preConcat(_Original_Matrix other) { - throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); - } - - /** - * Postconcats the matrix with the specified translation. - * M' = T(dx, dy) * M - */ - @Override - public boolean postTranslate(float dx, float dy) { - addTransform(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 }); - return true; - } - - /** - * Postconcats the matrix with the specified scale. - * M' = S(sx, sy, px, py) * M - */ - @Override - public boolean postScale(float sx, float sy, float px, float py) { - // TODO: do it in one pass - // translate so that the pivot is in 0,0 - addTransform(new float[] { 1, 0, -px, 0, 1, py, 0, 0, 1 }); - // scale - addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - - return true; - } - - /** - * Postconcats the matrix with the specified scale. - * M' = S(sx, sy) * M - */ - @Override - public boolean postScale(float sx, float sy) { - addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }); - return true; - } - - /** - * Postconcats the matrix with the specified rotation. - * M' = R(degrees, px, py) * M - */ - @Override - public boolean postRotate(float degrees, float px, float py) { - // TODO: do it in one pass - // translate so that the pivot is in 0,0 - addTransform(new float[] { 1, 0, -px, 0, 1, py, 0, 0, 1 }); - // scale - double rad = Math.toRadians(degrees); - float cos = (float)Math.cos(rad); - float sin = (float)Math.sin(rad); - addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - - return true; - } - - /** - * Postconcats the matrix with the specified rotation. - * M' = R(degrees) * M - */ - @Override - public boolean postRotate(float degrees) { - double rad = Math.toRadians(degrees); - float cos = (float)Math.cos(rad); - float sin = (float)Math.sin(rad); - addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); - - return true; - } - - /** - * Postconcats the matrix with the specified skew. - * M' = K(kx, ky, px, py) * M - */ - @Override - public boolean postSkew(float kx, float ky, float px, float py) { - // TODO: do it in one pass - // translate so that the pivot is in 0,0 - addTransform(new float[] { 1, 0, -px, 0, 1, py, 0, 0, 1 }); - // scale - addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); - // translate back the pivot - addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - - return true; - } - - /** - * Postconcats the matrix with the specified skew. - * M' = K(kx, ky) * M - */ - @Override - public boolean postSkew(float kx, float ky) { - addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); - - return true; - } - - /** - * Postconcats the matrix with the specified matrix. - * M' = other * M - */ - public boolean postConcat(Matrix other) { - addTransform(other.mValues); - - return true; - } - - @Override - public boolean postConcat(_Original_Matrix other) { - throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); - } - - /** Controlls how the src rect should align into the dst rect for - setRectToRect(). - */ - public enum ScaleToFit { - /** - * Scale in X and Y independently, so that src matches dst exactly. - * This may change the aspect ratio of the src. - */ - FILL (0), - /** - * Compute a scale that will maintain the original src aspect ratio, - * but will also ensure that src fits entirely inside dst. At least one - * axis (X or Y) will fit exactly. START aligns the result to the - * left and top edges of dst. - */ - START (1), - /** - * Compute a scale that will maintain the original src aspect ratio, - * but will also ensure that src fits entirely inside dst. At least one - * axis (X or Y) will fit exactly. The result is centered inside dst. - */ - CENTER (2), - /** - * Compute a scale that will maintain the original src aspect ratio, - * but will also ensure that src fits entirely inside dst. At least one - * axis (X or Y) will fit exactly. END aligns the result to the - * right and bottom edges of dst. - */ - END (3); - - // the native values must match those in SkMatrix.h - ScaleToFit(int nativeInt) { - this.nativeInt = nativeInt; - } - final int nativeInt; - } - - /** - * Set the matrix to the scale and translate values that map the source - * rectangle to the destination rectangle, returning true if the result - * can be represented. - * - * @param src the source rectangle to map from. - * @param dst the destination rectangle to map to. - * @param stf the ScaleToFit option - * @return true if the matrix can be represented by the rectangle mapping. - */ - public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf) { - if (dst == null || src == null) { - throw new NullPointerException(); - } - - if (src.isEmpty()) { - reset(); - return false; - } - - if (dst.isEmpty()) { - mValues[0] = mValues[1] = mValues[2] = mValues[3] = mValues[4] = mValues[5] - = mValues[6] = mValues[7] = 0; - mValues[8] = 1; - } else { - float tx, sx = dst.width() / src.width(); - float ty, sy = dst.height() / src.height(); - boolean xLarger = false; - - if (stf != ScaleToFit.FILL) { - if (sx > sy) { - xLarger = true; - sx = sy; - } else { - sy = sx; - } - } - - tx = dst.left - src.left * sx; - ty = dst.top - src.top * sy; - if (stf == ScaleToFit.CENTER || stf == ScaleToFit.END) { - float diff; - - if (xLarger) { - diff = dst.width() - src.width() * sy; - } else { - diff = dst.height() - src.height() * sy; - } - - if (stf == ScaleToFit.CENTER) { - diff = diff / 2; - } - - if (xLarger) { - tx += diff; - } else { - ty += diff; - } - } - - mValues[0] = sx; - mValues[4] = sy; - mValues[2] = tx; - mValues[5] = ty; - mValues[1] = mValues[3] = mValues[6] = mValues[7] = 0; - - } - // shared cleanup - mValues[8] = 1; - return true; - } - - @Override - public boolean setRectToRect(RectF src, RectF dst, _Original_Matrix.ScaleToFit stf) { - throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); - } - - /** - * Set the matrix such that the specified src points would map to the - * specified dst points. The "points" are represented as an array of floats, - * order [x0, y0, x1, y1, ...], where each "point" is 2 float values. - * - * @param src The array of src [x,y] pairs (points) - * @param srcIndex Index of the first pair of src values - * @param dst The array of dst [x,y] pairs (points) - * @param dstIndex Index of the first pair of dst values - * @param pointCount The number of pairs/points to be used. Must be [0..4] - * @return true if the matrix was set to the specified transformation - */ - @Override - public boolean setPolyToPoly(float[] src, int srcIndex, - float[] dst, int dstIndex, - int pointCount) { - if (pointCount > 4) { - throw new IllegalArgumentException(); - } - checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); - throw new UnsupportedOperationException("STUB NEEDED"); - } - - /** - * If this matrix can be inverted, return true and if inverse is not null, - * set inverse to be the inverse of this matrix. If this matrix cannot be - * inverted, ignore inverse and return false. - */ - public boolean invert(Matrix inverse) { - if (inverse == null) { - return false; - } - - try { - AffineTransform affineTransform = getTransform(); - AffineTransform inverseTransform = affineTransform.createInverse(); - inverse.mValues[0] = (float)inverseTransform.getScaleX(); - inverse.mValues[1] = (float)inverseTransform.getShearX(); - inverse.mValues[2] = (float)inverseTransform.getTranslateX(); - inverse.mValues[3] = (float)inverseTransform.getScaleX(); - inverse.mValues[4] = (float)inverseTransform.getShearY(); - inverse.mValues[5] = (float)inverseTransform.getTranslateY(); - - return true; - } catch (NoninvertibleTransformException e) { - return false; - } - } - - @Override - public boolean invert(_Original_Matrix inverse) { - throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); - } - - /** - * Apply this matrix to the array of 2D points specified by src, and write - * the transformed points into the array of points specified by dst. The - * two arrays represent their "points" as pairs of floats [x, y]. - * - * @param dst The array of dst points (x,y pairs) - * @param dstIndex The index of the first [x,y] pair of dst floats - * @param src The array of src points (x,y pairs) - * @param srcIndex The index of the first [x,y] pair of src floats - * @param pointCount The number of points (x,y pairs) to transform - */ - @Override - public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, - int pointCount) { - checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); - - for (int i = 0 ; i < pointCount ; i++) { - // just in case we are doing in place, we better put this in temp vars - float x = mValues[0] * src[i + srcIndex] + - mValues[1] * src[i + srcIndex + 1] + - mValues[2]; - float y = mValues[3] * src[i + srcIndex] + - mValues[4] * src[i + srcIndex + 1] + - mValues[5]; - - dst[i + dstIndex] = x; - dst[i + dstIndex + 1] = y; - } - } - - /** - * Apply this matrix to the array of 2D vectors specified by src, and write - * the transformed vectors into the array of vectors specified by dst. The - * two arrays represent their "vectors" as pairs of floats [x, y]. - * - * @param dst The array of dst vectors (x,y pairs) - * @param dstIndex The index of the first [x,y] pair of dst floats - * @param src The array of src vectors (x,y pairs) - * @param srcIndex The index of the first [x,y] pair of src floats - * @param vectorCount The number of vectors (x,y pairs) to transform - */ - @Override - public void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, - int vectorCount) { - checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount); - throw new UnsupportedOperationException("STUB NEEDED"); - } - - /** - * Apply this matrix to the array of 2D points specified by src, and write - * the transformed points into the array of points specified by dst. The - * two arrays represent their "points" as pairs of floats [x, y]. - * - * @param dst The array of dst points (x,y pairs) - * @param src The array of src points (x,y pairs) - */ - @Override - public void mapPoints(float[] dst, float[] src) { - if (dst.length != src.length) { - throw new ArrayIndexOutOfBoundsException(); - } - mapPoints(dst, 0, src, 0, dst.length >> 1); - } - - /** - * Apply this matrix to the array of 2D vectors specified by src, and write - * the transformed vectors into the array of vectors specified by dst. The - * two arrays represent their "vectors" as pairs of floats [x, y]. - * - * @param dst The array of dst vectors (x,y pairs) - * @param src The array of src vectors (x,y pairs) - */ - @Override - public void mapVectors(float[] dst, float[] src) { - if (dst.length != src.length) { - throw new ArrayIndexOutOfBoundsException(); - } - mapVectors(dst, 0, src, 0, dst.length >> 1); - } - - /** - * Apply this matrix to the array of 2D points, and write the transformed - * points back into the array - * - * @param pts The array [x0, y0, x1, y1, ...] of points to transform. - */ - @Override - public void mapPoints(float[] pts) { - mapPoints(pts, 0, pts, 0, pts.length >> 1); - } - - /** - * Apply this matrix to the array of 2D vectors, and write the transformed - * vectors back into the array. - * @param vecs The array [x0, y0, x1, y1, ...] of vectors to transform. - */ - @Override - public void mapVectors(float[] vecs) { - mapVectors(vecs, 0, vecs, 0, vecs.length >> 1); - } - - /** - * Apply this matrix to the src rectangle, and write the transformed - * rectangle into dst. This is accomplished by transforming the 4 corners of - * src, and then setting dst to the bounds of those points. - * - * @param dst Where the transformed rectangle is written. - * @param src The original rectangle to be transformed. - * @return the result of calling rectStaysRect() - */ - @Override - public boolean mapRect(RectF dst, RectF src) { - if (dst == null || src == null) { - throw new NullPointerException(); - } - - // 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 rectStaysRect(); - } - - /** - * Apply this matrix to the rectangle, and write the transformed rectangle - * back into it. This is accomplished by transforming the 4 corners of rect, - * and then setting it to the bounds of those points - * - * @param rect The rectangle to transform. - * @return the result of calling rectStaysRect() - */ - @Override - public boolean mapRect(RectF rect) { - return mapRect(rect, rect); - } - - /** - * Return the mean radius of a circle after it has been mapped by - * this matrix. NOTE: in perspective this value assumes the circle - * has its center at the origin. - */ - @Override - public float mapRadius(float radius) { - throw new UnsupportedOperationException("STUB NEEDED"); - } - - /** Copy 9 values from the matrix into the array. - */ - @Override - public void getValues(float[] values) { - if (values.length < 9) { - throw new ArrayIndexOutOfBoundsException(); - } - System.arraycopy(mValues, 0, values, 0, mValues.length); - } - - /** Copy 9 values from the array into the matrix. - Depending on the implementation of Matrix, these may be - transformed into 16.16 integers in the Matrix, such that - a subsequent call to getValues() will not yield exactly - the same values. - */ - @Override - public void setValues(float[] values) { - if (values.length < 9) { - throw new ArrayIndexOutOfBoundsException(); - } - System.arraycopy(values, 0, mValues, 0, mValues.length); - } - - @SuppressWarnings("unused") - private final static int kIdentity_Mask = 0; - private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation - private final static int kScale_Mask = 0x02; //!< set if the matrix has X or Y scale - private final static int kAffine_Mask = 0x04; //!< set if the matrix skews or rotates - private final static int kPerspective_Mask = 0x08; //!< set if the matrix is in perspective - private final static int kRectStaysRect_Mask = 0x10; - @SuppressWarnings("unused") - private final static int kUnknown_Mask = 0x80; - - @SuppressWarnings("unused") - private final static int kAllMasks = kTranslate_Mask | - kScale_Mask | - kAffine_Mask | - kPerspective_Mask | - kRectStaysRect_Mask; - - // these guys align with the masks, so we can compute a mask from a variable 0/1 - @SuppressWarnings("unused") - private final static int kTranslate_Shift = 0; - @SuppressWarnings("unused") - private final static int kScale_Shift = 1; - @SuppressWarnings("unused") - private final static int kAffine_Shift = 2; - @SuppressWarnings("unused") - private final static int kPerspective_Shift = 3; - private final static int kRectStaysRect_Shift = 4; - - private int computeTypeMask() { - int mask = 0; - - if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) { - mask |= kPerspective_Mask; - } - - if (mValues[2] != 0. || mValues[5] != 0.) { - mask |= kTranslate_Mask; - } - - float m00 = mValues[0]; - float m01 = mValues[1]; - float m10 = mValues[3]; - float m11 = mValues[4]; - - if (m01 != 0. || m10 != 0.) { - mask |= kAffine_Mask; - } - - if (m00 != 1. || m11 != 1.) { - mask |= kScale_Mask; - } - - if ((mask & kPerspective_Mask) == 0) { - // map non-zero to 1 - int im00 = m00 != 0 ? 1 : 0; - int im01 = m01 != 0 ? 1 : 0; - int im10 = m10 != 0 ? 1 : 0; - int im11 = m11 != 0 ? 1 : 0; - - // record if the (p)rimary and (s)econdary diagonals are all 0 or - // all non-zero (answer is 0 or 1) - int dp0 = (im00 | im11) ^ 1; // true if both are 0 - int dp1 = im00 & im11; // true if both are 1 - int ds0 = (im01 | im10) ^ 1; // true if both are 0 - int ds1 = im01 & im10; // true if both are 1 - - // return 1 if primary is 1 and secondary is 0 or - // primary is 0 and secondary is 1 - mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift; - } - - return mask; - } -} |