boolean restrictStateBounds(State state, State prevState, float pivotX, float pivotY,
            boolean allowOverscroll, boolean allowOverzoom, boolean restrictRotation) {

        if (!settings.isRestrictBounds()) {
            return false;
        }

        // Calculating default pivot point, if not provided
        if (Float.isNaN(pivotX) || Float.isNaN(pivotY)) {
            GravityUtils.getDefaultPivot(settings, tmpPoint);
            pivotX = tmpPoint.x;
            pivotY = tmpPoint.y;
        }

        boolean isStateChanged = false;

        if (restrictRotation && settings.isRestrictRotation()) {
            float rotation = Math.round(state.getRotation() / 90f) * 90f;
            if (!State.equals(rotation, state.getRotation())) {
                state.rotateTo(rotation, pivotX, pivotY);
                isStateChanged = true;
            }
        }

        zoomBounds.set(state);
        final float minZoom = zoomBounds.getMinZoom();
        final float maxZoom = zoomBounds.getMaxZoom();

        final float extraZoom = allowOverzoom ? settings.getOverzoomFactor() : 1f;
        float zoom = zoomBounds.restrict(state.getZoom(), extraZoom);

        // Applying elastic overzoom
        if (prevState != null) {
            zoom = applyZoomResilience(zoom, prevState.getZoom(), minZoom, maxZoom, extraZoom);
        }

        if (!State.equals(zoom, state.getZoom())) {
            state.zoomTo(zoom, pivotX, pivotY);
            isStateChanged = true;
        }

        float extraX = allowOverscroll ? settings.getOverscrollDistanceX() : 0f;
        float extraY = allowOverscroll ? settings.getOverscrollDistanceY() : 0f;

        movBounds.set(state);
        movBounds.restrict(state.getX(), state.getY(), extraX, extraY, tmpPointF);
        float newX = tmpPointF.x;
        float newY = tmpPointF.y;

        if (zoom < minZoom) {
            // Decreasing overscroll if zooming less than minimum zoom
            float factor = (extraZoom * zoom / minZoom - 1f) / (extraZoom - 1f);
            factor = (float) Math.sqrt(factor);

            movBounds.restrict(newX, newY, tmpPointF);
            float strictX = tmpPointF.x;
            float strictY = tmpPointF.y;

            newX = strictX + factor * (newX - strictX);
            newY = strictY + factor * (newY - strictY);
        }

        if (prevState != null) {
            movBounds.getExternalBounds(tmpRectF);
            newX = applyTranslationResilience(newX, prevState.getX(),
                    tmpRectF.left, tmpRectF.right, extraX);
            newY = applyTranslationResilience(newY, prevState.getY(),
                    tmpRectF.top, tmpRectF.bottom, extraY);
        }

        if (!State.equals(newX, state.getX()) || !State.equals(newY, state.getY())) {
            state.translateTo(newX, newY);
            isStateChanged = true;
        }

        return isStateChanged;
    }
boolean restrictStateBounds ( State state , State prevState , float pivotX , float pivotY , boolean allowOverscroll , boolean allowOverzoom , boolean restrictRotation ) { if ( ! settings . isRestrictBounds ( ) ) { return false ; } if ( Float . isNaN ( pivotX ) || Float . isNaN ( pivotY ) ) { GravityUtils . getDefaultPivot ( settings , tmpPoint ) ; pivotX = tmpPoint . x ; pivotY = tmpPoint . y ; } boolean isStateChanged = false ; if ( restrictRotation && settings . isRestrictRotation ( ) ) { float rotation = Math . round ( state . getRotation ( ) / 90f ) * 90f ; if ( ! State . equals ( rotation , state . getRotation ( ) ) ) { state . rotateTo ( rotation , pivotX , pivotY ) ; isStateChanged = true ; } } zoomBounds . set ( state ) ; final float minZoom = zoomBounds . getMinZoom ( ) ; final float maxZoom = zoomBounds . getMaxZoom ( ) ; final float extraZoom = allowOverzoom ? settings . getOverzoomFactor ( ) : 1f ; float zoom = zoomBounds . restrict ( state . getZoom ( ) , extraZoom ) ; if ( prevState != null ) { zoom = applyZoomResilience ( zoom , prevState . getZoom ( ) , minZoom , maxZoom , extraZoom ) ; } if ( ! State . equals ( zoom , state . getZoom ( ) ) ) { state . zoomTo ( zoom , pivotX , pivotY ) ; isStateChanged = true ; } float extraX = allowOverscroll ? settings . getOverscrollDistanceX ( ) : 0f ; float extraY = allowOverscroll ? settings . getOverscrollDistanceY ( ) : 0f ; movBounds . set ( state ) ; movBounds . restrict ( state . getX ( ) , state . getY ( ) , extraX , extraY , tmpPointF ) ; float newX = tmpPointF . x ; float newY = tmpPointF . y ; if ( zoom < minZoom ) { float factor = ( extraZoom * zoom / minZoom - 1f ) / ( extraZoom - 1f ) ; factor = ( float ) Math . sqrt ( factor ) ; movBounds . restrict ( newX , newY , tmpPointF ) ; float strictX = tmpPointF . x ; float strictY = tmpPointF . y ; newX = strictX + factor * ( newX - strictX ) ; newY = strictY + factor * ( newY - strictY ) ; } if ( prevState != null ) { movBounds . getExternalBounds ( tmpRectF ) ; newX = applyTranslationResilience ( newX , prevState . getX ( ) , tmpRectF . left , tmpRectF . right , extraX ) ; newY = applyTranslationResilience ( newY , prevState . getY ( ) , tmpRectF . top , tmpRectF . bottom , extraY ) ; } if ( ! State . equals ( newX , state . getX ( ) ) || ! State . equals ( newY , state . getY ( ) ) ) { state . translateTo ( newX , newY ) ; isStateChanged = true ; } return isStateChanged ; }
Restricts state's translation and zoom bounds. If {@code prevState} is not null and
{@code allowOverscroll (allowOverzoom)} parameter is true then resilience
will be applied to translation (zoom) changes if they are out of bounds.

@param state State to be restricted
@param prevState Previous state to calculate overscroll and overzoom (optional)
@param pivotX Pivot's X coordinate
@param pivotY Pivot's Y coordinate
@param allowOverscroll Whether overscroll is allowed
@param allowOverzoom Whether overzoom is allowed
@param restrictRotation Whether rotation should be restricted to a nearest N*90 angle
@return true if state was changed, false otherwise.