title: Android Java, draw on a scaled canvas
body: <p>i'm developing an android drawing application, it has a relativelayout with a custom view in it for drawing with. So far it all works except when I scale the canvas the drawing happens in the wrong spot, it's probably best to show the code rather than try to explain it. Yes I have tried with using path.offset but with no success. The main issue is that when you draw on it when it's been scaled in, while it paints in the right spot, the path is too sensitive, when your finger is centered it's fine but if you go up/down or side to side the path moves faster than your finger.</p>
  
  <pre><code>package com.nick.sketchr;
  
  import android.content.Context;
  import android.graphics.Bitmap;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.graphics.Path;
  import android.graphics.Rect;
  import android.view.MotionEvent;
  import android.view.View;
  
  public class CustomCanvas extends View {
  private Bitmap  mBitmap;
  private Canvas  mCanvas;
  private Path    mPath;
  private Paint   mBitmapPaint;
  private Paint   mPaint;
  private float   old_scale;
  private float   dmx,dmy;
  private double  scale;
  private long    timevar2;
  private Rect    bounds;
  public CustomCanvas(Context c) {
      super(c);
      mPath = new Path();
      mBitmapPaint = new Paint(Paint.DITHER_FLAG);
      mPaint = new Paint();
      mPaint.setAntiAlias(true);
      mPaint.setDither(true);
      mPaint.setColor(0xFF000000);
      mPaint.setStyle(Paint.Style.STROKE);
      mPaint.setStrokeJoin(Paint.Join.ROUND);
      mPaint.setStrokeCap(Paint.Cap.ROUND);
      mPaint.setStrokeWidth(3);
      dmx = Main_App.w/2/2;
      dmy = Main_App.h/2/2;
      scale = 1;
  }
  
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
      super.onSizeChanged(w, h, oldw, oldh);
      mBitmap = Bitmap.createBitmap(Main_App.w/2, Main_App.h/2, Bitmap.Config.ARGB_8888);
      mCanvas = new Canvas(mBitmap);
      mBitmap.eraseColor(Color.WHITE);
  }
  
  @Override
  protected void onDraw(Canvas canvas) {
      float sc = (float) scale;
      canvas.scale(sc, sc, Main_App.w/2, Main_App.h/2);
      canvas.drawBitmap(mBitmap, dmx, dmy, mBitmapPaint);
      canvas.drawPath(mPath, mPaint);
  }
  private float mX, mY;
  private static final float TOUCH_TOLERANCE = 4;
  
  private void touch_start(float x, float y) {
      mPath.reset();
      mPath.moveTo(x, y);
      mX = x;
      mY = y;
  }
  private 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;
      }
  }
  private void touch_up() {
      mPath.lineTo(mX, mY);
      mPath.offset(-dmx, -dmy); //this is the problem area
      //also the path shows wrong when canvas is scaled... o_o
      mCanvas.drawPath(mPath, mPaint);
      mPath.reset();
  }
  @Override
  public boolean onTouchEvent(MotionEvent event){
      float x = event.getX()/(float)scale+bounds.left;
      float y = event.getY()/(float)scale+bounds.top;
      if(event.getPointerCount() == 2){
          timevar2 = event.getEventTime();
          float newx = event.getX(0);
          float newy = event.getY(0);
          float oldx = event.getX(1);
          float oldy = event.getY(1);
          mPath.reset();
          float equa = (float) (Math.pow(newx - oldx, 2) + Math.pow(newy - oldy, 2));
          float cscale = (float) Math.sqrt(equa)/100;
          float scaled = (cscale - old_scale);
          if(scaled &lt; -0.1){
              if(scale &gt; 0.1){
                scale -= 0.03;
              }
          }
          if(scaled &gt; 0.1){
              scale += 0.03;
          }
          dmx = (float) (((newx + oldx)/2)-(Main_App.w/2/2)*scale);
          dmy = (float) (((newy + oldy)/2)-(Main_App.h/2/2)*scale);
          old_scale = cscale;
          invalidate();
          return true;
      }
      long dt = event.getEventTime() - timevar2;
      if(dt &lt; 100){
          return true;
      }
      switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
              touch_start(x, y);
              invalidate();
              break;
          case MotionEvent.ACTION_MOVE:
              touch_move(x, y);
              invalidate();
              break;
          case MotionEvent.ACTION_UP:
              touch_up();
              invalidate();
              break;
          }
      return true;
  }
  
  public void clear(){
      mBitmap.eraseColor(Color.TRANSPARENT);
      invalidate();
      System.gc();
  }
  }
  </code></pre>