final float getMatrixScale(Matrix matrix) { // Given unit vectors A = (0, 1) and B = (1, 0). // After matrix mapping, we got A' and B'. Let theta = the angle b/t A' and B'. // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)), // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|); // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0. // For non-skew case, which is most of the cases, matrix scale is computing exactly the // scale on x and y axis, and take the minimal of these two. // For skew case, an unit square will mapped to a parallelogram. And this function will // return the minimal height of the 2 bases. final float[] unitVectors = tempUnitVectors; unitVectors[0] = 0; unitVectors[1] = 1; unitVectors[2] = 1; unitVectors[3] = 0; matrix.mapVectors(unitVectors); final float scaleX = (float) Math.hypot(unitVectors[0], unitVectors[1]); final float scaleY = (float) Math.hypot(unitVectors[2], unitVectors[3]); final float crossProduct = cross(unitVectors[0], unitVectors[1], unitVectors[2], unitVectors[3]); final float maxScale = Math.max(scaleX, scaleY); return maxScale > 0 ? Math.abs(crossProduct) / maxScale : 0; }
@Override public final void draw(Canvas canvas, Matrix parentMatrix, PointF viewportScale) { final float pivotX = this.pivotX.getAnimatedValue(); final float pivotY = this.pivotY.getAnimatedValue(); final float rotation = this.rotation.getAnimatedValue(); final float scaleX = this.scaleX.getAnimatedValue(); final float scaleY = this.scaleY.getAnimatedValue(); final float translateX = this.translateX.getAnimatedValue(); final float translateY = this.translateY.getAnimatedValue(); tempMatrix.set(parentMatrix); if (translateX + pivotX != 0f || translateY + pivotY != 0f) { tempMatrix.preTranslate(translateX + pivotX, translateY + pivotY); } if (rotation != 0f) { tempMatrix.preRotate(rotation, 0, 0); } if (scaleX != 1f || scaleY != 1f) { tempMatrix.preScale(scaleX, scaleY); } if (pivotX != 0f || pivotY != 0f) { tempMatrix.preTranslate(-pivotX, -pivotY); } onDraw(canvas, tempMatrix, viewportScale); }
public BaseLayer(PropertyTimeline timeline, BaseNode node) { this.timeline = timeline; rotation = registerAnimatableProperty(node.getRotation()); pivotX = registerAnimatableProperty(node.getPivotX()); pivotY = registerAnimatableProperty(node.getPivotY()); scaleX = registerAnimatableProperty(node.getScaleX()); scaleY = registerAnimatableProperty(node.getScaleY()); translateX = registerAnimatableProperty(node.getTranslateX()); translateY = registerAnimatableProperty(node.getTranslateY()); }