gt:         float outerRadius = shorterSide * size;
context: /*
   * This is the source code of Telegram for Android v. 3.x.x
   * It is licensed under GNU GPL v. 2 or later.
   * You should have received a copy of the license in this archive (see LICENSE).
   *
   * Copyright Nikolai Kudashov, 2013-2016.
   */
  
  package org.telegram.ui.Components;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.graphics.Paint;
  import android.graphics.RectF;
  import android.view.MotionEvent;
  import android.widget.FrameLayout;
  
  import org.telegram.messenger.AndroidUtilities;
  
  public class PhotoFilterBlurControl extends FrameLayout {
  
      public interface PhotoFilterLinearBlurControlDelegate {
          void valueChanged(Point centerPoint, float falloff, float size, float angle);
      }
  
      private final static float BlurInsetProximity = AndroidUtilities.dp(20);
      private final static float BlurMinimumFalloff = 0.1f;
      private final static float BlurMinimumDifference = 0.02f;
      private final static float BlurViewCenterInset = AndroidUtilities.dp(30.0f);
      private final static float BlurViewRadiusInset = AndroidUtilities.dp(30.0f);
  
      private enum BlurViewActiveControl {
          BlurViewActiveControlNone,
          BlurViewActiveControlCenter,
          BlurViewActiveControlInnerRadius,
          BlurViewActiveControlOuterRadius,
          BlurViewActiveControlWholeArea,
          BlurViewActiveControlRotation
      }
  
      private final int GestureStateBegan = 1;
      private final int GestureStateChanged = 2;
      private final int GestureStateEnded = 3;
      private final int GestureStateCancelled = 4;
      private final int GestureStateFailed = 5;
  
      private BlurViewActiveControl activeControl;
      private Point startCenterPoint = new Point();
      private float startDistance;
      private float startRadius;
      private Size actualAreaSize = new Size();
      private Point centerPoint = new Point(0.5f, 0.5f);
      private float falloff = 0.15f;
      private float size = 0.35f;
      private float angle;
      private RectF arcRect = new RectF();
  
      private float pointerStartX;
      private float pointerStartY;
      private float startPointerDistance;
      private float pointerScale = 1;
      private boolean isMoving;
      private boolean isZooming;
      private boolean checkForMoving;
      private boolean checkForZooming;
  
      private int type;
  
      private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
      private Paint arcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  
      private PhotoFilterLinearBlurControlDelegate delegate;
  
      public PhotoFilterBlurControl(Context context) {
          super(context);
          setWillNotDraw(false);
          paint.setColor(0xffffffff);
          arcPaint.setColor(0xffffffff);
          arcPaint.setStrokeWidth(AndroidUtilities.dp(2));
          arcPaint.setStyle(Paint.Style.STROKE);
      }
  
      public void setType(int blurType) {
          type = blurType;
      }
  
      public void setDelegate(PhotoFilterLinearBlurControlDelegate delegate) {
          this.delegate = delegate;
      }
  
      private float getDistance(MotionEvent event) {
          if (event.getPointerCount() != 2) {
              return 0;
          }
          float x1 = event.getX(0);
          float y1 = event.getY(0);
          float x2 = event.getX(1);
          float y2 = event.getY(1);
          return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
      }
  
      private float degreesToRadians(float degrees) {
          return degrees * (float) Math.PI / 180.0f;
      }
  
      @Override
      public boolean onTouchEvent(MotionEvent event) {
          int action = event.getActionMasked();
  
          switch (action) {
              case MotionEvent.ACTION_POINTER_DOWN:
              case MotionEvent.ACTION_DOWN: {
                  if (event.getPointerCount() == 1) {
                      if (checkForMoving && !isMoving) {
                          float locationX = event.getX();
                          float locationY = event.getY();
                          Point centerPoint = getActualCenterPoint();
                          Point delta = new Point(locationX - centerPoint.x, locationY - centerPoint.y);
                          float radialDistance = (float) Math.sqrt(delta.x * delta.x + delta.y * delta.y);
                          float innerRadius = getActualInnerRadius();
                          float outerRadius = getActualOuterRadius();
                          boolean close = Math.abs(outerRadius - innerRadius) < BlurInsetProximity;
                          float innerRadiusOuterInset = close ? 0 : BlurViewRadiusInset;
                          float outerRadiusInnerInset = close ? 0 : BlurViewRadiusInset;
  
                          if (type == 0) {
                              float distance = (float) Math.abs(delta.x * Math.cos(degreesToRadians(angle) + Math.PI / 2) + delta.y * Math.sin(degreesToRadians(angle) + Math.PI / 2));
                              if (radialDistance < BlurViewCenterInset) {
                                  isMoving = true;
                              } else if (distance > innerRadius - BlurViewRadiusInset && distance < innerRadius + innerRadiusOuterInset) {
                                  isMoving = true;
                              } else if (distance > outerRadius - outerRadiusInnerInset && distance < outerRadius + BlurViewRadiusInset) {
                                  isMoving = true;
                              } else if ((distance <= innerRadius - BlurViewRadiusInset) || distance >= outerRadius + BlurViewRadiusInset) {
                                  isMoving = true;
                              }
                          } else if (type == 1) {
                              if (radialDistance < BlurViewCenterInset) {
                                  isMoving = true;
                              } else if (radialDistance > innerRadius - BlurViewRadiusInset && radialDistance < innerRadius + innerRadiusOuterInset) {
                                  isMoving = true;
                              } else if (radialDistance > outerRadius - outerRadiusInnerInset && radialDistance < outerRadius + BlurViewRadiusInset) {
                                  isMoving = true;
                              }
                          }
                          checkForMoving = false;
                          if (isMoving) {
                              handlePan(GestureStateBegan, event);
                          }
                      }
                  } else {
                      if (isMoving) {
                          handlePan(GestureStateEnded, event);
                          checkForMoving = true;
                          isMoving = false;
                      }
                      if (event.getPointerCount() == 2) {
                          if (checkForZooming && !isZooming) {
                              handlePinch(GestureStateBegan, event);
                              isZooming = true;
                          }
                      } else {
                          handlePinch(GestureStateEnded, event);
                          checkForZooming = true;
                          isZooming = false;
                      }
                  }
                  break;
              }
  
              case MotionEvent.ACTION_POINTER_UP:
              case MotionEvent.ACTION_CANCEL:
              case MotionEvent.ACTION_UP: {
                  if (isMoving) {
                      handlePan(GestureStateEnded, event);
                      isMoving = false;
                  } else if (isZooming) {
                      handlePinch(GestureStateEnded, event);
                      isZooming = false;
                  }
                  checkForMoving = true;
                  checkForZooming = true;
                  break;
              }
  
              case MotionEvent.ACTION_MOVE: {
                  if (isMoving) {
                      handlePan(GestureStateChanged, event);
                  } else if (isZooming) {
                      handlePinch(GestureStateChanged, event);
                  }
              }
          }
          return true;
      }
  
      private void handlePan(int state, MotionEvent event) {
          float locationX = event.getX();
          float locationY = event.getY();
          Point actualCenterPoint = getActualCenterPoint();
          Point delta = new Point(locationX - actualCenterPoint.x, locationY - actualCenterPoint.y);
          float radialDistance = (float) Math.sqrt(delta.x * delta.x + delta.y * delta.y);
          float shorterSide = (actualAreaSize.width > actualAreaSize.height) ? actualAreaSize.height : actualAreaSize.width;
          float innerRadius = shorterSide * falloff;
  