/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.drawee.drawable;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.internal.VisibleForTesting;
/**
* Drawable that automatically rotates the underlying drawable with a pivot in the center of the
* drawable bounds based on a rotation angle.
*/
public class OrientedDrawable extends ForwardingDrawable {
@VisibleForTesting final Matrix mRotationMatrix;
private int mRotationAngle;
// Temporary objects preallocated in advance to save future allocations.
private final Matrix mTempMatrix = new Matrix();
private final RectF mTempRectF = new RectF();
/**
* Creates a new OrientedDrawable. The only rotation angles allowed are multiples of 90 or -1 if
* the angle is unknown.
*/
public OrientedDrawable(Drawable drawable, int rotationAngle) {
super(drawable);
Preconditions.checkArgument(rotationAngle % 90 == 0);
mRotationMatrix = new Matrix();
mRotationAngle = rotationAngle;
}
@Override
public void draw(Canvas canvas) {
if (mRotationAngle <= 0) {
super.draw(canvas);
return;
}
int saveCount = canvas.save();
canvas.concat(mRotationMatrix);
super.draw(canvas);
canvas.restoreToCount(saveCount);
}
@Override
public int getIntrinsicWidth() {
return (mRotationAngle % 180 == 0) ? super.getIntrinsicWidth() : super.getIntrinsicHeight();
}
@Override
public int getIntrinsicHeight() {
return (mRotationAngle % 180 == 0) ? super.getIntrinsicHeight() : super.getIntrinsicWidth();
}
@Override
protected void onBoundsChange(Rect bounds) {
Drawable underlyingDrawable = getCurrent();
if (mRotationAngle > 0) {
mRotationMatrix.setRotate(mRotationAngle, bounds.centerX(), bounds.centerY());
// Set the rotated bounds on the underlying drawable
mTempMatrix.reset();
mRotationMatrix.invert(mTempMatrix);
mTempRectF.set(bounds);
mTempMatrix.mapRect(mTempRectF);
underlyingDrawable.setBounds(
(int) mTempRectF.left,
(int) mTempRectF.top,
(int) mTempRectF.right,
(int) mTempRectF.bottom);
} else {
underlyingDrawable.setBounds(bounds);
}
}
@Override
public void getTransform(Matrix transform) {
getParentTransform(transform);
if (!mRotationMatrix.isIdentity()) {
transform.preConcat(mRotationMatrix);
}
}
}