title: Path draw in opposite direction at canvas when rotate android
body: <p><img src="https://i.stack.imgur.com/8PgAz.png" alt="enter image description here">
  Hi i am erasing bitmap that is draw at canvas with touch (fingers) that is working fine the problem i am facing is after rotate bitmap at canvas paths draw in opposition direction mean bitmap erase in opposition direction of my finger touch .</p>
  
  <p><strong>DrawingPane.class</strong></p>
  
  <pre><code>public class DrawingPanel extends ImageView implements OnTouchListener {
  
  
  private Matrix mMatrix = new Matrix();
  private float mScaleFactor = 1f;
  private float mRotationDegrees = 0.f;
  private float mFocusX = 0.f;
  private float mFocusY = 0.f;  
  private int mAlpha = 255;
  private int mImageHeight, mImageWidth;
  
  private ScaleGestureDetector mScaleDetector;
  private RotateGestureDetector mRotateDetector;
  private MoveGestureDetector mMoveDetector;
  private ShoveGestureDetector mShoveDetector; 
  private boolean isMoving=false;
  EditPhotoActivity editActivity;
  
  
  Bitmap overlayDefault;
  Bitmap overlay;
  Bitmap bmp,bmp2;
  Paint pTouch; 
  int whichTabSelected=0;
  
  private Path mPath;
  Display display ;
  private ArrayList&lt;Path&gt; paths = new ArrayList&lt;Path&gt;();
  private ArrayList&lt;Float&gt; xlist = new ArrayList&lt;Float&gt;();
  private ArrayList&lt;Float&gt; ylist = new ArrayList&lt;Float&gt;();
  @SuppressLint("NewApi")
  public DrawingPanel(Context context, int colorPaint,Bitmap bmp) {
      super(context);
  
  
      if (Build.VERSION.SDK_INT &gt;= 11) {
          setLayerType(View.LAYER_TYPE_HARDWARE, null);
      }
      display = ((Activity)context).getWindowManager().getDefaultDisplay();
  
      mFocusX = display.getWidth()/2f;
      mFocusY = display.getHeight()/2f;
      try {
  
          overlayDefault=bmp;
          overlay=bmp;
          overlay=overlay.copy(Config.ARGB_8888, true);
          overlay.setHasAlpha(true);
  
      } catch (Exception e) {
  
          e.printStackTrace();
      }
  
      mImageHeight    = getHeight();
      mImageWidth     = getWidth();
  
  
      // Setup Gesture Detectors
      mScaleDetector  = new ScaleGestureDetector(context, new ScaleListener());
      mRotateDetector = new RotateGestureDetector(context, new RotateListener());
      mMoveDetector   = new MoveGestureDetector(context, new MoveListener());
      mShoveDetector  = new ShoveGestureDetector(context, new ShoveListener());
  
  
      pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);         
      pTouch.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); 
      pTouch.setColor(Color.TRANSPARENT);
      //pTouch.setMaskFilter(new BlurMaskFilter(30, Blur.SOLID));
      pTouch.setStyle(Paint.Style.STROKE);
      pTouch.setStrokeJoin(Paint.Join.ROUND);
      pTouch.setStrokeCap(Paint.Cap.ROUND);
      pTouch.setStrokeWidth(50);
      pTouch.setAntiAlias(true);
      setFocusable(true);
      setFocusableInTouchMode(true);
      mPath = new Path();
      paths.add(mPath);
  }
  
  
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
      super.onSizeChanged(w, h, oldw, oldh);
      mImageHeight=getHeight();
      mImageWidth=getWidth();
      bmp  = Bitmap.createScaledBitmap(overlay, w, h, false);
      bmp2  = Bitmap.createScaledBitmap(overlayDefault, w, h, false);
      overlay = bmp.copy(Config.ARGB_8888, true);
      overlayDefault = bmp2.copy(Config.ARGB_8888, true);
  
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      // TODO Auto-generated method stub
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
  }
  
  @Override
  protected void onDraw(Canvas canvas) {
  
       //  mCanvas.drawBitmap(overlayDefault,0, 0, null); //exclude this line to show all as you draw
  
      //  mCanvas.drawCircle(X, Y, 80, pTouch);
      //draw the overlay over the background 
  
          float scaledImageCenterX = (mImageWidth*mScaleFactor)/2;
          float scaledImageCenterY = (mImageHeight*mScaleFactor)/2;
          mMatrix.reset();
          mMatrix.postScale(mScaleFactor, mScaleFactor);
          mMatrix.postRotate(mRotationDegrees,  scaledImageCenterX, scaledImageCenterY);
  
          if(isMoving)
          {
              mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY - scaledImageCenterY);
          }
          else
          {
                mMatrix.postTranslate(0,0);
          }
  
          canvas.setMatrix(mMatrix);
  
          canvas.drawBitmap(overlay,0,0, null);
  
          for (Path p : paths) {
              canvas.drawPath(p, pTouch);
           }
          super.onDraw(canvas);
  }
  
  
  public Bitmap getBitmap(){
      Bitmap b  = Bitmap.createScaledBitmap(overlay,display.getWidth()    ,display.getWidth(), false);
      overlay = b.copy(Config.ARGB_8888, true);
      return overlay;
  }
  public void setBitmap(Bitmap bmp1){
      overlay = bmp1;
  
      invalidate();
  }
  private float mX, mY;
  private static final float TOUCH_TOLERANCE = 0;
  
  public void touch_start(float x, float y) {
  
      if(xlist.size()&gt;0 &amp;&amp; ylist.size()&gt;0){
          xlist.clear();
          ylist.clear();
      }
      xlist.add(x);
      ylist.add(y);
      mPath.reset();
      mPath.moveTo(x, y);
      mX = x;
      mY = y;
      mPath.transform(mMatrix, mPath);
      invalidate();
  }
  
  public void touch_move(float x, float y) {
      float dx = Math.abs(x - mX);
      float dy = Math.abs(y - mY);
      if (dx &gt;= TOUCH_TOLERANCE || dy &gt;= TOUCH_TOLERANCE) {
  
          mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
          mX = x;
          mY = y;
          mPath.transform(mMatrix, mPath);
      }
      xlist.add(x);
      ylist.add(y);
      invalidate();
  }
  
  public void touch_up() {
      mPath.lineTo(mX, mY);
  
      mPath = new Path();
      mPath.transform(mMatrix, mPath);
      paths.add(mPath);
      invalidate();
  }
  
  
  public void OnTouchParent(MotionEvent event){
       mScaleDetector.onTouchEvent(event);
          mRotateDetector.onTouchEvent(event);
          mMoveDetector.onTouchEvent(event);
          mShoveDetector.onTouchEvent(event);
          float scaledImageCenterX = (mImageWidth*mScaleFactor)/2;
          float scaledImageCenterY = (mImageHeight*mScaleFactor)/2;
  
          mMatrix.reset();
          mMatrix.postScale(mScaleFactor, mScaleFactor);
          mMatrix.postRotate(mRotationDegrees,  scaledImageCenterX, scaledImageCenterY);
          mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY - scaledImageCenterY);
  
          float x = event.getX();
          float y = event.getY();
  
          /*switch (event.getAction()) {
  
          case MotionEvent.ACTION_DOWN:
              if(whichTabSelected==Constant.ERASE)
              {
              touch_start(x, y);
              invalidate();
              }
              break;
  
          case MotionEvent.ACTION_MOVE:
              if(whichTabSelected==Constant.ERASE)
              {
              touch_move(x, y);
              invalidate();
              }
              break;
  
          case MotionEvent.ACTION_UP:
              if(whichTabSelected==Constant.ERASE)
              {
              touch_up();
              invalidate();
              }
              break;
          }
          if(whichTabSelected==Constant.ERASE)
          {
          return true;
          }
          else
          {
              return false;
          }*/
  
          invalidate();
  
  }
  @Override
  public boolean onTouch(View arg0, MotionEvent event) {
  
  
      if(getTabMode()==Constant.PANZOOM)
      {
      mScaleDetector.onTouchEvent(event);
      mRotateDetector.onTouchEvent(event);
      mMoveDetector.onTouchEvent(event);
      mShoveDetector.onTouchEvent(event);
  
      float scaledImageCenterX = (mImageWidth*mScaleFactor)/2;
      float scaledImageCenterY = (mImageHeight*mScaleFactor)/2;
  
  
  
      }
  
      float x = event.getX();
      float y = event.getY();
  
      switch (event.getAction()) {
  
      case MotionEvent.ACTION_DOWN:
          if(getTabMode()==Constant.ERASE)
          {
          touch_start(x, y);
          invalidate();
          }
          break;
  
      case MotionEvent.ACTION_MOVE:
          if(getTabMode()==Constant.ERASE)
          {
          touch_move(x, y);
          invalidate();
          }
          break;
  
      case MotionEvent.ACTION_UP:
          if(getTabMode()==Constant.ERASE)
          {
          touch_up();
          invalidate();
          }
          break;
      }
  
  
      invalidate();
      return true;
  }
  public void setBottomTabMode(int mode)
  {
      whichTabSelected=mode;
  }
  public int getTabMode()
  {
      return whichTabSelected;
  }
  
  
  private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
      @Override
      public boolean onScale(ScaleGestureDetector detector) {
          mScaleFactor *= detector.getScaleFactor(); // scale change since previous event
  
          // Don't let the object get too small or too large.
  
          mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); 
          return true;
      }
  }
  
  private class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
      @Override
      public boolean onRotate(RotateGestureDetector detector) {
          mRotationDegrees -= detector.getRotationDegreesDelta();
          return true;
      }
  }   
  
  private class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener {
      @Override
      public boolean onMove(MoveGestureDetector detector) {
          PointF d = detector.getFocusDelta();
          mFocusX += d.x;
          mFocusY += d.y;     
          isMoving=true;
          // mFocusX = detector.getFocusX();
          // mFocusY = detector.getFocusY();
          return true;
      }
  }       
  
  private class ShoveListener extends ShoveGestureDetector.SimpleOnShoveGestureListener {
      @Override
      public boolean onShove(ShoveGestureDetector detector) {
          mAlpha += detector.getShovePixelsDelta();
          if (mAlpha &gt; 255)
              mAlpha = 255;
          else if (mAlpha &lt; 0)
              mAlpha = 0;
  
          return true;
      }
  }
  }
  </code></pre>