下面列出了android.graphics.RectF#centerX ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Update the icon drawable position or target render view position.
*/
void updateIconPosition()
{
mView.mIconDrawable = mView.mPromptOptions.getIconDrawable();
if (mView.mIconDrawable != null)
{
final RectF mFocalBounds = mView.mPromptOptions.getPromptFocal().getBounds();
mView.mIconDrawableLeft = mFocalBounds.centerX()
- (mView.mIconDrawable.getIntrinsicWidth() / 2);
mView.mIconDrawableTop = mFocalBounds.centerY()
- (mView.mIconDrawable.getIntrinsicHeight() / 2);
}
else if (mView.mTargetRenderView != null)
{
final int[] viewPosition = new int[2];
mView.getLocationInWindow(viewPosition);
final int[] targetPosition = new int[2];
mView.mTargetRenderView.getLocationInWindow(targetPosition);
mView.mIconDrawableLeft = targetPosition[0] - viewPosition[0] - mView.mTargetRenderView.getScrollX();
mView.mIconDrawableTop = targetPosition[1] - viewPosition[1] - mView.mTargetRenderView.getScrollY();
}
}
/**
* Configures the necessary {@link Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(final int viewWidth, final int viewHeight) {
Size previewSize = mSettings.getPreviewSize();
int rotation = Camera2Helper.getDisplayRotation(mContext);
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / previewSize.getHeight(),
(float) viewWidth / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
mTextureView.setTransform(matrix);
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
if (null == mTextureView || null == mPreviewSize) {
return;
}
int rotation = mDisplayOrientation;
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
mTextureView.setTransform(matrix);
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(final int viewWidth, final int viewHeight) {
final Activity activity = getActivity();
if (null == textureView || null == previewSize || null == activity) {
return;
}
final int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
final Matrix matrix = new Matrix();
final RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
final RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
final float centerX = viewRect.centerX();
final float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
final float scale =
Math.max(
(float) viewHeight / previewSize.getHeight(),
(float) viewWidth / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
textureView.setTransform(matrix);
}
/**
* Update the icon drawable position or target render view position.
*/
void updateIconPosition() {
mView.mIconDrawable = mView.mPromptOptions.getIconDrawable();
if (mView.mIconDrawable != null) {
final RectF mFocalBounds = mView.mPromptOptions.getPromptFocal().getBounds();
mView.mIconDrawableLeft = mFocalBounds.centerX()
- (mView.mIconDrawable.getIntrinsicWidth() / 2);
mView.mIconDrawableTop = mFocalBounds.centerY()
- (mView.mIconDrawable.getIntrinsicHeight() / 2);
} else if (mView.mTargetRenderView != null) {
final int[] viewPosition = new int[2];
mView.getLocationInWindow(viewPosition);
final int[] targetPosition = new int[2];
mView.mTargetRenderView.getLocationInWindow(targetPosition);
mView.mIconDrawableLeft = targetPosition[0] - viewPosition[0];
mView.mIconDrawableTop = targetPosition[1] - viewPosition[1];
}
}
/**
* Resizes rectangle to have a certain aspect ratio (center remains
* stationary) while constraining it to remain within the original rect.
*
* @param r rectangle to resize
* @param w new width aspect
* @param h new height aspect
*/
public static void fixAspectRatioContained(RectF r, float w, float h) {
float origW = r.width();
float origH = r.height();
float origA = origW / origH;
float a = w / h;
float finalW = origW;
float finalH = origH;
if (origA < a) {
finalH = origW / a;
r.top = r.centerY() - finalH / 2;
r.bottom = r.top + finalH;
} else {
finalW = origH * a;
r.left = r.centerX() - finalW / 2;
r.right = r.left + finalW;
}
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
if (isViewAvailable()) {
if (null == activityView.getTextureView()) {
return;
}
int rotation = activityView.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / previewSize.getHeight(),
(float) viewWidth / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
activityView.getTextureView().setTransform(matrix);
}
}
@Override
public void prepare(@NonNull final PromptOptions options, final boolean clipToBounds, @NonNull Rect clipBounds)
{
final RectF focalBounds = options.getPromptFocal().getBounds();
final RectF textBounds = options.getPromptText().getBounds();
final float textPadding = options.getTextPadding();
float x1, x2, y1, y2;
if (textBounds.top < focalBounds.top)
{
y1 = textBounds.top - textPadding;
y2 = focalBounds.bottom + textPadding;
}
else
{
y1 = focalBounds.top - textPadding;
y2 = textBounds.bottom + textPadding;
}
x1 = Math.min(textBounds.left - textPadding,
focalBounds.left - textPadding);
x2 = Math.max(textBounds.right + textPadding,
focalBounds.right + textPadding);
mBaseBounds.set(x1, y1, x2, y2);
mFocalCentre.x = focalBounds.centerX();
mFocalCentre.y = focalBounds.centerY();
}
private FaceParsed getFace(RectF rectF, PointF scale, View view) {
//Position
float posX = rectF.centerX() * 100 / view.getWidth();
float posY = rectF.centerY() * 100 / view.getHeight();
PointF positionParsed = new PointF(posX - scale.x / 2, posY - scale.y / 2);
//Scale
float scaleX = rectF.width() * 100 / view.getWidth();
float scaleY = rectF.height() * 100 / view.getHeight();
PointF scaleParsed = new PointF(scaleX, scaleY);
return new FaceParsed(positionParsed, scaleParsed);
}
public Transition(RectF srcRect, RectF dstRect, long duration, Interpolator interpolator) {
if (!MathUtils.haveSameAspectRatio(srcRect, dstRect)) {
throw new IncompatibleRatioException();
}
mSrcRect = srcRect;
mDstRect = dstRect;
mDuration = duration;
mInterpolator = interpolator;
// Precomputes a few variables to avoid doing it in onDraw().
mWidthDiff = dstRect.width() - srcRect.width();
mHeightDiff = dstRect.height() - srcRect.height();
mCenterXDiff = dstRect.centerX() - srcRect.centerX();
mCenterYDiff = dstRect.centerY() - srcRect.centerY();
}
private void ripple(int index, float pressX, float pressY) {
if (index < 0 || !allAngleExpandableButton.rippleEffect) {
return;
}
allAngleExpandableButton.resetRippleInfo();
ButtonData buttonData = allAngleExpandableButton.buttonDatas.get(index);
RectF rectF = allAngleExpandableButton.buttonRects.get(buttonData);
float centerX = rectF.centerX();
float centerY = rectF.centerY();
float radius = rectF.centerX() - rectF.left;
float distanceX = pressX - centerX;
float distanceY = pressY - centerY;
float pressToCenterDistance = (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
if (pressToCenterDistance > radius) {
//press out of the button circle
return;
}
allAngleExpandableButton.rippleInfo.pressX = pressX;
allAngleExpandableButton.rippleInfo.pressY = pressY;
allAngleExpandableButton.rippleInfo.buttonIndex = index;
allAngleExpandableButton.rippleInfo.rippleRadius = radius + pressToCenterDistance;
allAngleExpandableButton.rippleInfo.rippleColor = getRippleColor(allAngleExpandableButton.rippleColor == Integer.MIN_VALUE ?
buttonData.getBackgroundColor() : allAngleExpandableButton.rippleColor);
rippleRadius = allAngleExpandableButton.rippleInfo.rippleRadius;
startRippleAnimator();
}
private void alignCenter(RectF box) {
for (DrawElement element : elements) {
float offset = box.centerX() - element.getOuterBoundingBox().centerX();
offsetMap.put(element, offset);
element.move(offset, 0);
}
}
private void drawShadow(Canvas canvas, Paint paint, ButtonData buttonData) {
if (buttonElevationPx <= 0) {
return;
}
float left, top;
Bitmap bitmap;
if (buttonData.isMainButton()) {
mainShadowBitmap = getButtonShadowBitmap(buttonData);
bitmap = mainShadowBitmap;
} else {
subShadowBitmap = getButtonShadowBitmap(buttonData);
bitmap = subShadowBitmap;
}
int shadowOffset = buttonElevationPx / 2;
RectF rectF = buttonRects.get(buttonData);
left = rectF.centerX() - bitmap.getWidth() / 2;
top = rectF.centerY() - bitmap.getHeight() / 2 + shadowOffset;
shadowMatrix.reset();
if (!buttonData.isMainButton()) {
shadowMatrix.postScale(expandProgress, expandProgress, bitmap.getWidth() / 2, bitmap.getHeight() / 2 + shadowOffset);
}
shadowMatrix.postTranslate(left, top);
if (buttonData.isMainButton()) {
//shadow did not need to perform rotate as button,so rotate reverse
shadowMatrix.postRotate(-mainButtonRotateDegree * rotateProgress, rectF.centerX(), rectF.centerY());
}
paint.setAlpha(255);
canvas.drawBitmap(bitmap, shadowMatrix, paint);
}
@Override
public void update(@NonNull final PromptOptions options, float revealModifier, float alphaModifier)
{
final RectF focalBounds = options.getPromptFocal().getBounds();
final float focalCentreX = focalBounds.centerX();
final float focalCentreY = focalBounds.centerY();
mRadius = mBaseRadius * revealModifier;
mPaint.setAlpha((int) (mBaseColourAlpha * alphaModifier));
// Change the current centre position to be a position scaled from the focal to the base.
mPosition.set(focalCentreX + ((mBasePosition.x - focalCentreX) * revealModifier),
focalCentreY + ((mBasePosition.y - focalCentreY) * revealModifier));
}
@Override
public void prepare(@NonNull final PromptOptions options, final boolean clipToBounds, @NonNull Rect clipBounds)
{
final RectF focalBounds = options.getPromptFocal().getBounds();
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
mBaseBounds.set(0, 0, metrics.widthPixels, metrics.heightPixels);
mFocalCentre.x = focalBounds.centerX();
mFocalCentre.y = focalBounds.centerY();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 计算在当前大小下,内容应该显示的大小和起始位置
int safeW = w - getPaddingLeft() - getPaddingRight();
int safeH = h - getPaddingTop() - getPaddingBottom();
float edgeLength, startX, startY;
float fix = mArcWidth / 2 + mBorderWidth + mShadowRadius * 2; // 修正距离,画笔宽度的修正
if (safeW < safeH) {
// 宽度小于高度,以宽度为准
edgeLength = safeW - fix;
startX = getPaddingLeft();
startY = (safeH - safeW) / 2.0f + getPaddingTop();
} else {
// 宽度大于高度,以高度为准
edgeLength = safeH - fix;
startX = (safeW - safeH) / 2.0f + getPaddingLeft();
startY = getPaddingTop();
}
// 得到显示区域和中心的
RectF content = new RectF(startX + fix, startY + fix, startX + edgeLength, startY + edgeLength);
mCenterX = content.centerX();
mCenterY = content.centerY();
// 得到路径
mSeekPath.reset();
mSeekPath.addArc(content, mOpenAngle / 2, CIRCLE_ANGLE - mOpenAngle);
mSeekPathMeasure.setPath(mSeekPath, false);
computeThumbPos(mProgressPresent);
resetShaderColor();
mInvertMatrix.reset();
mInvertMatrix.preRotate(-mRotateAngle, mCenterX, mCenterY);
mArcPaint.getFillPath(mSeekPath, mBorderPath);
mBorderPath.close();
mArcRegion.setPath(mBorderPath, new Region(0, 0, w, h));
}
/**
* Calculate the bounding rectangle for current crop window, handle non-straight rotation angles.
* <br>
* If the rotation angle is straight then the bounds rectangle is the bitmap rectangle, otherwsie
* we find the max rectangle that is within the image bounds starting from the crop window
* rectangle.
*
* @param rect the crop window rectangle to start finsing bounded rectangle from
* @return true - non straight rotation in place, false - otherwise.
*/
private boolean calculateBounds(RectF rect) {
float left = BitmapUtils.getRectLeft(mBoundsPoints);
float top = BitmapUtils.getRectTop(mBoundsPoints);
float right = BitmapUtils.getRectRight(mBoundsPoints);
float bottom = BitmapUtils.getRectBottom(mBoundsPoints);
if (!isNonStraightAngleRotated()) {
mCalcBounds.set(left, top, right, bottom);
return false;
} else {
float x0 = mBoundsPoints[0];
float y0 = mBoundsPoints[1];
float x2 = mBoundsPoints[4];
float y2 = mBoundsPoints[5];
float x3 = mBoundsPoints[6];
float y3 = mBoundsPoints[7];
if (mBoundsPoints[7] < mBoundsPoints[1]) {
if (mBoundsPoints[1] < mBoundsPoints[3]) {
x0 = mBoundsPoints[6];
y0 = mBoundsPoints[7];
x2 = mBoundsPoints[2];
y2 = mBoundsPoints[3];
x3 = mBoundsPoints[4];
y3 = mBoundsPoints[5];
} else {
x0 = mBoundsPoints[4];
y0 = mBoundsPoints[5];
x2 = mBoundsPoints[0];
y2 = mBoundsPoints[1];
x3 = mBoundsPoints[2];
y3 = mBoundsPoints[3];
}
} else if (mBoundsPoints[1] > mBoundsPoints[3]) {
x0 = mBoundsPoints[2];
y0 = mBoundsPoints[3];
x2 = mBoundsPoints[6];
y2 = mBoundsPoints[7];
x3 = mBoundsPoints[0];
y3 = mBoundsPoints[1];
}
float a0 = (y3 - y0) / (x3 - x0);
float a1 = -1f / a0;
float b0 = y0 - a0 * x0;
float b1 = y0 - a1 * x0;
float b2 = y2 - a0 * x2;
float b3 = y2 - a1 * x2;
float c0 = (rect.centerY() - rect.top) / (rect.centerX() - rect.left);
float c1 = -c0;
float d0 = rect.top - c0 * rect.left;
float d1 = rect.top - c1 * rect.right;
left = Math.max(left, (d0 - b0) / (a0 - c0) < rect.right ? (d0 - b0) / (a0 - c0) : left);
left = Math.max(left, (d0 - b1) / (a1 - c0) < rect.right ? (d0 - b1) / (a1 - c0) : left);
left = Math.max(left, (d1 - b3) / (a1 - c1) < rect.right ? (d1 - b3) / (a1 - c1) : left);
right = Math.min(right, (d1 - b1) / (a1 - c1) > rect.left ? (d1 - b1) / (a1 - c1) : right);
right = Math.min(right, (d1 - b2) / (a0 - c1) > rect.left ? (d1 - b2) / (a0 - c1) : right);
right = Math.min(right, (d0 - b2) / (a0 - c0) > rect.left ? (d0 - b2) / (a0 - c0) : right);
top = Math.max(top, Math.max(a0 * left + b0, a1 * right + b1));
bottom = Math.min(bottom, Math.min(a1 * left + b3, a0 * right + b2));
mCalcBounds.left = left;
mCalcBounds.top = top;
mCalcBounds.right = right;
mCalcBounds.bottom = bottom;
return true;
}
}
@Override
public void prepare(@NonNull final PromptOptions options, final boolean clipToBounds,
@NonNull final Rect clipBounds)
{
// Obtain values from the prompt options.
final PromptText promptText = options.getPromptText();
final RectF focalBounds = options.getPromptFocal().getBounds();
final float focalCentreX = focalBounds.centerX();
final float focalCentreY = focalBounds.centerY();
final float focalPadding = options.getFocalPadding();
final RectF textBounds = promptText.getBounds();
final float textPadding = options.getTextPadding();
final RectF clipBoundsInset88dp = new RectF(clipBounds);
// Default material design offset prompt when more than 88dp inset
final float inset88dp = 88f * options.getResourceFinder().getResources().getDisplayMetrics().density;
clipBoundsInset88dp.inset(inset88dp, inset88dp);
// Is the focal centre more than 88dp from the clip bounds edge
if ((focalCentreX > clipBoundsInset88dp.left
&& focalCentreX < clipBoundsInset88dp.right)
|| (focalCentreY > clipBoundsInset88dp.top
&& focalCentreY < clipBoundsInset88dp.bottom))
{
final boolean isTextAboveTarget = textBounds.top < focalBounds.top;
float x1 = focalCentreX;
float x2 = textBounds.left - textPadding;
float y1, y2;
if (isTextAboveTarget)
{
y1 = focalBounds.bottom + textPadding;
y2 = textBounds.top;
}
else
{
y1 = focalBounds.top - (focalPadding + textPadding);
y2 = textBounds.bottom;
}
final float y3 = y2;
float x3 = promptText.getBounds().right + textPadding;
final float focalLeft = focalBounds.left - focalPadding;
final float focalRight = focalBounds.right + focalPadding;
if (x2 > focalLeft && x2 < focalRight)
{
if (isTextAboveTarget)
{
x1 = focalBounds.left - focalPadding;
}
else
{
x2 -= (focalBounds.width() / 2) - focalPadding;
}
}
else if (x3 > focalLeft && x3 < focalRight)
{
if (isTextAboveTarget)
{
x1 = focalBounds.right + focalPadding;
}
else
{
x3 += (focalBounds.width() / 2) + focalPadding;
}
}
final double offset = Math.pow(x2, 2) + Math.pow(y2, 2);
final double bc = (Math.pow(x1, 2) + Math.pow(y1, 2) - offset) / 2.0;
final double cd = (offset - Math.pow(x3, 2) - Math.pow(y3, 2)) / 2.0;
final double det = (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2);
final double idet = 1 / det;
mBasePosition.set((float) ((bc * (y2 - y3) - cd * (y1 - y2)) * idet),
(float) ((cd * (x1 - x2) - bc * (x2 - x3)) * idet));
mBaseRadius = (float) Math.sqrt(Math.pow(x2 - mBasePosition.x, 2)
+ Math.pow(y2 - mBasePosition.y, 2));
/*point1.set(x1, y1);
point2.set(x2, y2);
point3.set(x3, y3);*/
}
else
{
mBasePosition.set(focalCentreX, focalCentreY);
// Calculate the furthest distance from the a focal side to a text side.
final float length = Math.abs(
(textBounds.left < focalBounds.left ?
textBounds.left - textPadding
: textBounds.right + textPadding)
- focalCentreX);
// Calculate the height based on the distance from the focal centre to the furthest text y position.
float height = (focalBounds.height() / 2) + focalPadding + textBounds.height();
// Calculate the radius based on the calculated width and height
mBaseRadius = (float) Math.sqrt(Math.pow(length, 2) + Math.pow(height, 2));
/*point1.set(focalCentreX + (prompt.mHorizontalTextPositionLeft ? -length : length),
focalCentreY + (prompt.mVerticalTextPositionAbove ? - height : height));*/
}
mPosition.set(mBasePosition);
}
/**
* Calculate the bounding rectangle for current crop window, handle non-straight rotation angles.
* <br>
* If the rotation angle is straight then the bounds rectangle is the bitmap rectangle, otherwsie
* we find the max rectangle that is within the image bounds starting from the crop window
* rectangle.
*
* @param rect the crop window rectangle to start finsing bounded rectangle from
* @return true - non straight rotation in place, false - otherwise.
*/
private boolean calculateBounds(RectF rect) {
float left = BitmapUtils.getRectLeft(mBoundsPoints);
float top = BitmapUtils.getRectTop(mBoundsPoints);
float right = BitmapUtils.getRectRight(mBoundsPoints);
float bottom = BitmapUtils.getRectBottom(mBoundsPoints);
if (!isNonStraightAngleRotated()) {
mCalcBounds.set(left, top, right, bottom);
return false;
} else {
float x0 = mBoundsPoints[0];
float y0 = mBoundsPoints[1];
float x2 = mBoundsPoints[4];
float y2 = mBoundsPoints[5];
float x3 = mBoundsPoints[6];
float y3 = mBoundsPoints[7];
if (mBoundsPoints[7] < mBoundsPoints[1]) {
if (mBoundsPoints[1] < mBoundsPoints[3]) {
x0 = mBoundsPoints[6];
y0 = mBoundsPoints[7];
x2 = mBoundsPoints[2];
y2 = mBoundsPoints[3];
x3 = mBoundsPoints[4];
y3 = mBoundsPoints[5];
} else {
x0 = mBoundsPoints[4];
y0 = mBoundsPoints[5];
x2 = mBoundsPoints[0];
y2 = mBoundsPoints[1];
x3 = mBoundsPoints[2];
y3 = mBoundsPoints[3];
}
} else if (mBoundsPoints[1] > mBoundsPoints[3]) {
x0 = mBoundsPoints[2];
y0 = mBoundsPoints[3];
x2 = mBoundsPoints[6];
y2 = mBoundsPoints[7];
x3 = mBoundsPoints[0];
y3 = mBoundsPoints[1];
}
float a0 = (y3 - y0) / (x3 - x0);
float a1 = -1f / a0;
float b0 = y0 - a0 * x0;
float b1 = y0 - a1 * x0;
float b2 = y2 - a0 * x2;
float b3 = y2 - a1 * x2;
float c0 = (rect.centerY() - rect.top) / (rect.centerX() - rect.left);
float c1 = -c0;
float d0 = rect.top - c0 * rect.left;
float d1 = rect.top - c1 * rect.right;
left = Math.max(left, (d0 - b0) / (a0 - c0) < rect.right ? (d0 - b0) / (a0 - c0) : left);
left = Math.max(left, (d0 - b1) / (a1 - c0) < rect.right ? (d0 - b1) / (a1 - c0) : left);
left = Math.max(left, (d1 - b3) / (a1 - c1) < rect.right ? (d1 - b3) / (a1 - c1) : left);
right = Math.min(right, (d1 - b1) / (a1 - c1) > rect.left ? (d1 - b1) / (a1 - c1) : right);
right = Math.min(right, (d1 - b2) / (a0 - c1) > rect.left ? (d1 - b2) / (a0 - c1) : right);
right = Math.min(right, (d0 - b2) / (a0 - c0) > rect.left ? (d0 - b2) / (a0 - c0) : right);
top = Math.max(top, Math.max(a0 * left + b0, a1 * right + b1));
bottom = Math.min(bottom, Math.min(a1 * left + b3, a0 * right + b2));
mCalcBounds.left = left;
mCalcBounds.top = top;
mCalcBounds.right = right;
mCalcBounds.bottom = bottom;
return true;
}
}
/**
* Build a matrix which can be used when calling setTransform() on a
* TextureView.
* TODO: write unit test when roboletric is available.
*
* @param previewViewSize The TextureView current layout size.
* @param previewStreamSize The selected preview video stream size.
* @return The matrix to transform TextureView.
*/
public Matrix toTransformMatrix(Size previewViewSize, Size previewStreamSize)
{
RectF previewViewRect =
new RectF(0.0f, 0.0f, previewViewSize.width(), previewViewSize.height());
PointF previewViewCenter = new PointF(previewViewRect.centerX(), previewViewRect.centerY());
// If natural orientation is portrait, rotate the buffer dimensions.
Size previewBufferSize = previewStreamSize;
if (mOrientationManager.getDeviceNaturalOrientation() == OrientationManager.DeviceNaturalOrientation.PORTRAIT)
{
previewBufferSize = new Size(previewStreamSize.height(), previewStreamSize.width());
}
Matrix transformMatrix = new Matrix();
// Adjust the effective preview rect to the center of the texture view.
final RectF PreviewBufferRect =
new RectF(0.0f, 0.0f, previewBufferSize.width(), previewBufferSize.height());
final PointF previewBufferCenter =
new PointF(PreviewBufferRect.centerX(), PreviewBufferRect.centerY());
final RectF centeredEffectivePreviewRect = new RectF(PreviewBufferRect);
centeredEffectivePreviewRect.offset(
previewViewCenter.x - previewBufferCenter.x,
previewViewCenter.y - previewBufferCenter.y);
// Undo ScaleToFit.FILL done by the surface
transformMatrix.setRectToRect(
previewViewRect, centeredEffectivePreviewRect, Matrix.ScaleToFit.FILL);
// Rotate buffer contents to proper orientation
int rotateDegree = mOrientationManager.getDisplayRotation().getDegrees();
transformMatrix.postRotate(
rotateDegree,
previewViewCenter.x, previewViewCenter.y);
/**
* Scale to fit view, cropping the longest dimension.
*
* surfaceTextureSize is changed with the device orientation. Since
* previewStreamSize is always in landscape. To calculate the scale
* factor, previewStreamSize needs to be rotated if in portrait.
*/
Size rotatedPreviewSize = previewStreamSize;
if (mOrientationManager.isInPortrait())
{
rotatedPreviewSize = new Size(previewStreamSize.height(), previewStreamSize.width());
}
float scale = Math.min(
(float) previewViewSize.width() / (float) rotatedPreviewSize.width(),
(float) previewViewSize.height() / (float) rotatedPreviewSize.height());
transformMatrix.postScale(scale, scale, previewViewCenter.x, previewViewCenter.y);
RectF scaledPreviewStreamRect = new RectF(
0.0f, 0.0f, previewStreamSize.width() * scale, previewStreamSize.height() * scale);
PointF scaledPreviewStreamCenter =
new PointF(scaledPreviewStreamRect.centerX(), scaledPreviewStreamRect.centerY());
transformMatrix.postTranslate(
scaledPreviewStreamCenter.x - previewViewCenter.x,
scaledPreviewStreamCenter.y - previewViewCenter.y);
return transformMatrix;
}