private Path createFishPath(float fishCenterX, float fishCenterY) {
    Path path = new Path();

    float fishHeadX = fishCenterX;
    float fishHeadY = fishCenterY - mFishHeight / 2.0f;

    // the head of the fish
    path.moveTo(fishHeadX, fishHeadY);
    // the left body of the fish
    path.quadTo(
        fishHeadX - mFishWidth * 0.333f,
        fishHeadY + mFishHeight * 0.222f,
        fishHeadX - mFishWidth * 0.333f,
        fishHeadY + mFishHeight * 0.444f);
    path.lineTo(fishHeadX - mFishWidth * 0.333f, fishHeadY + mFishHeight * 0.666f);
    path.lineTo(fishHeadX - mFishWidth * 0.5f, fishHeadY + mFishHeight * 0.8f);
    path.lineTo(fishHeadX - mFishWidth * 0.5f, fishHeadY + mFishHeight);

    // the tail of the fish
    path.lineTo(fishHeadX, fishHeadY + mFishHeight * 0.9f);

    // the right body of the fish
    path.lineTo(fishHeadX + mFishWidth * 0.5f, fishHeadY + mFishHeight);
    path.lineTo(fishHeadX + mFishWidth * 0.5f, fishHeadY + mFishHeight * 0.8f);
    path.lineTo(fishHeadX + mFishWidth * 0.333f, fishHeadY + mFishHeight * 0.666f);
    path.lineTo(fishHeadX + mFishWidth * 0.333f, fishHeadY + mFishHeight * 0.444f);
    path.quadTo(
        fishHeadX + mFishWidth * 0.333f, fishHeadY + mFishHeight * 0.222f, fishHeadX, fishHeadY);

    path.close();

    return path;
  }
  private void drawSpring(Canvas canvas, int springDelta) {
    mPath.reset();
    mPath.moveTo(0, 0);
    mPath.lineTo(0, PULL_HEIGHT);
    mPath.quadTo(mWidth / 2, PULL_HEIGHT - springDelta, mWidth, PULL_HEIGHT);
    mPath.lineTo(mWidth, 0);
    canvas.drawPath(mPath, mBackPaint);

    int curH = PULL_HEIGHT - springDelta / 2;

    if (curH > PULL_HEIGHT - PULL_DELTA / 2) {
      int leftX = (int) (mWidth / 2 - 2 * mRadius + getSprRatio() * mRadius);
      mPath.reset();
      mPath.moveTo(leftX, curH);
      mPath.quadTo(mWidth / 2, curH - mRadius * getSprRatio() * 2, mWidth - leftX, curH);
      canvas.drawPath(mPath, mBallPaint);
    } else {
      canvas.drawArc(
          new RectF(mWidth / 2 - mRadius, curH - mRadius, mWidth / 2 + mRadius, curH + mRadius),
          180,
          180,
          true,
          mBallPaint);
    }
  }
 @Override
 public boolean onTouch(View v, MotionEvent event) {
   float x = event.getX();
   float y = event.getY();
   switch (event.getAction()) {
     case MotionEvent.ACTION_DOWN:
       path.reset();
       path.moveTo(x, y);
       x1 = x;
       y1 = y;
       break;
     case MotionEvent.ACTION_MOVE:
       path.quadTo(x1, y1, x, y);
       x1 = x;
       y1 = y;
       canvas.drawPath(path, paint);
       path.reset();
       path.moveTo(x, y);
       break;
     case MotionEvent.ACTION_UP:
       if (x == x1 && y == y1) y1 = y1 + 1;
       path.quadTo(x1, y1, x, y);
       canvas.drawPath(path, paint);
       path.reset();
       break;
   }
   ImageView iv = (ImageView) this.findViewById(R.id.imageView1);
   iv.setImageBitmap(bitmap);
   return true;
 }
Example #4
0
 public void onTouchMove(Point point) {
   float dx = Math.abs(point.x - mX);
   float dy = Math.abs(point.y - mY);
   if (dx > 0 || dy > 0) {
     path.quadTo(mX, mY, (point.x + mX) / 2, (point.y + mY) / 2);
     mX = point.x;
     mY = point.y;
   } else if (dx == 0 || dy == 0) {
     path.quadTo(mX, mY, (point.x + 1 + mX) / 2, (point.y + 1 + mY) / 2);
     mX = point.x + 1;
     mY = point.y + 1;
   }
 }
  private void drawTail(Canvas canvas, int centerY, int bottom, float fraction) {
    int bezier1w = (int) (mWidth / 2 + (mRadius * 3 / 4) * (1 - fraction));
    PointF start = new PointF(mWidth / 2 + mRadius, centerY);
    PointF bezier1 = new PointF(bezier1w, bottom);
    PointF bezier2 = new PointF(bezier1w + mRadius / 2, bottom);

    mPath.reset();
    mPath.moveTo(start.x, start.y);
    mPath.quadTo(bezier1.x, bezier1.y, bezier2.x, bezier2.y);
    mPath.lineTo(mWidth - bezier2.x, bezier2.y);
    mPath.quadTo(mWidth - bezier1.x, bezier1.y, mWidth - start.x, start.y);
    canvas.drawPath(mPath, mBallPaint);
  }
  @Override
  public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    path.moveTo(a.x, a.y);
    path.lineTo(b.x, b.y);
    path.quadTo(anchorB.x, anchorB.y, c.x, c.y);
    path.lineTo(d.x, d.y);
    path.quadTo(anchorA.x, anchorA.y, a.x, a.y);
    path.close();

    canvas.drawPath(path, paint);
  }
  /**
   * 通过绘制Path构建一个ShapeDrawable,用来绘制到画布Canvas上
   *
   * @return
   */
  private ShapeDrawable drawGooView() {
    Path path = new Path();

    // 1. 根据当前两圆圆心的距离计算出固定圆的半径
    float distance = (float) GeometryUtil.getDistanceBetween2Points(mDragCenter, mStickCenter);
    stickCircleTempRadius = getCurrentRadius(distance);

    // 2. 计算出经过两圆圆心连线的垂线的dragLineK(对边比临边)。求出四个交点坐标
    float xDiff = mStickCenter.x - mDragCenter.x;
    Double dragLineK = null;
    if (xDiff != 0) {
      dragLineK = (double) ((mStickCenter.y - mDragCenter.y) / xDiff);
    }

    // 分别获得经过两圆圆心连线的垂线与圆的交点(两条垂线平行,所以dragLineK相等)。
    PointF[] dragPoints =
        GeometryUtil.getIntersectionPoints(mDragCenter, dragCircleRadius, dragLineK);
    PointF[] stickPoints =
        GeometryUtil.getIntersectionPoints(mStickCenter, stickCircleTempRadius, dragLineK);

    // 3. 以两圆连线的0.618处作为 贝塞尔曲线 的控制点。(选一个中间点附近的控制点)
    PointF pointByPercent = GeometryUtil.getPointByPercent(mDragCenter, mStickCenter, 0.618f);

    // 绘制两圆连接
    // 此处参见示意图{@link https://github.com/PoplarTang/DragGooView }
    path.moveTo((float) stickPoints[0].x, (float) stickPoints[0].y);
    path.quadTo(
        (float) pointByPercent.x,
        (float) pointByPercent.y,
        (float) dragPoints[0].x,
        (float) dragPoints[0].y);
    path.lineTo((float) dragPoints[1].x, (float) dragPoints[1].y);
    path.quadTo(
        (float) pointByPercent.x,
        (float) pointByPercent.y,
        (float) stickPoints[1].x,
        (float) stickPoints[1].y);
    path.close();

    // 将四个交点画到屏幕上
    //		path.addCircle((float)dragPoints[0].x, (float)dragPoints[0].y, 5, Direction.CW);
    //		path.addCircle((float)dragPoints[1].x, (float)dragPoints[1].y, 5, Direction.CW);
    //		path.addCircle((float)stickPoints[0].x, (float)stickPoints[0].y, 5, Direction.CW);
    //		path.addCircle((float)stickPoints[1].x, (float)stickPoints[1].y, 5, Direction.CW);

    // 构建ShapeDrawable
    ShapeDrawable shapeDrawable = new ShapeDrawable(new PathShape(path, 50f, 50f));
    shapeDrawable.getPaint().setColor(Color.RED);
    return shapeDrawable;
  }
 // TODO Extract all this methods to a new utilities class
 private Path getRoundedRectPath(int left, int top, int right, int bottom, int rx, int ry) {
   int width = right - left;
   int height = bottom - top;
   Path path = new Path();
   path.moveTo(rx, 0);
   path.lineTo(width - rx, 0);
   path.quadTo(width, 0, width, ry);
   path.lineTo(width, height - ry);
   path.quadTo(width, height, width - rx, height);
   path.lineTo(rx, height);
   path.quadTo(0, height, 0, height - ry);
   path.lineTo(0, ry);
   path.quadTo(0, 0, rx, 0);
   return path;
 }
  private void splat(PointF start, PointF end, PointF mid, float d) {

    Path firstPath = new Path();
    if (d < 0) {
      d = 0;
    }

    firstPath.moveTo(start.x, start.y);
    firstPath.quadTo(mid.x, mid.y, end.x, end.y);
    fCurrentOperation.addPath(firstPath, d);

    float dst = dist(start.x, start.y, end.x, end.y);
    int quarterDrips = fDrips / 4;
    int nbDrips = quarterDrips + RANDOM.nextInt(fDrips);

    for (int i = 0; i < nbDrips; i++) {
      // positioning of splotch varies between ±4dd, tending towards 0

      float x4 = dst * getProbability(0.5f);
      float y4 = dst * getProbability(0.5f);
      // direction of splotch varies between ±0.5
      float x5 = getProbability(0.5f);
      float y5 = getProbability(0.5f);

      float dd = Math.min(d * (RANDOM.nextFloat() + 0.4f), d);
      Path subPath = new Path();
      subPath.moveTo(start.x + x4, start.y + y4);
      subPath.lineTo(start.x + x4 + x5, start.y + y4 + y5);
      fCurrentOperation.addPath(subPath, dd);
    }
  }
Example #10
0
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        curX = x;
        curY = y;
        path.moveTo(curX, curY);
        isMoving = true;
        break;
      case MotionEvent.ACTION_MOVE:
        path.quadTo(curX, curY, x, y);
        curX = x;
        curY = y;

        isMoving = true;

        break;
      case MotionEvent.ACTION_UP:
        cacheCanvas.drawPath(path, mPaint);
        path.reset();
        isMoving = false;
        break;

      default:
        break;
    }
    invalidate();
    return true;
  }
Example #11
0
  /** View的事件将会在7/12详解 */
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    /*
     * 获取当前事件位置坐标
     */
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN: // 手指接触屏幕重置路径
        mPath.reset();
        mPath.moveTo(x, y);
        preX = x;
        preY = y;
        break;
      case MotionEvent.ACTION_MOVE: // 手指移动时连接路径
        float dx = Math.abs(x - preX);
        float dy = Math.abs(y - preY);
        if (dx >= MIN_MOVE_DIS || dy >= MIN_MOVE_DIS) {
          mPath.quadTo(preX, preY, (x + preX) / 2, (y + preY) / 2);
          preX = x;
          preY = y;
        }
        break;
    }

    // 重绘视图
    invalidate();
    return true;
  }
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    mPath.moveTo(-1 / 4F * vWidth, waveY);

    mPath.quadTo(ctrX, ctrY, vWidth + 1 / 4f, waveY);

    mPath.lineTo(vWidth + 1 / 4f, vHeight);
    mPath.lineTo(-1 / 4F * vWidth, vHeight);
    mPath.close();

    canvas.drawPath(mPath, mPaint);

    if (ctrX >= vWidth + 0.25f * vWidth) {
      isInc = false;
    } else if (ctrX <= -0.25f * vWidth) {
      isInc = true;
    }

    ctrX = isInc ? ctrX + 20 : ctrX - 20;

    if (ctrY <= vHeight) {
      ctrY += 2;
      waveY += 2;
    }

    mPath.reset();

    invalidate();
  }
Example #13
0
  private void drawBG(Canvas canvas) {
    Path path = new Path();
    int currentPointY = 0;
    switch (mStatus) {
      case NONE:
        currentPointY = mMaxArcHeight;
        break;
      case STATUS_SMOOTH_UP:
      case STATUS_UP:
        currentPointY =
            getHeight()
                - (int)
                    ((getHeight() - mMaxArcHeight)
                        * Math.min(
                            1, (mArcHeight - mMaxArcHeight / 4) * 2.0 / mMaxArcHeight * 1.3));
        break;
      case STATUS_DOWN:
        currentPointY = mMaxArcHeight;
        break;
    }

    path.moveTo(0, currentPointY);
    path.quadTo(getWidth() / 2, currentPointY - mArcHeight, getWidth(), currentPointY);
    path.lineTo(getWidth(), getHeight());
    path.lineTo(0, getHeight());
    path.lineTo(0, currentPointY);
    canvas.drawPath(path, mPaint);
  }
 private void touch_move(float x, float y) {
   float dx = Math.abs(x - tiX);
   float dy = Math.abs(y - tiY);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     tiPath.quadTo(tiX, tiY, (x + tiX) / 2, (y + tiY) / 2);
     tiX = x;
     tiY = y;
   }
 }
Example #15
0
 private void touch2_move(float x, float y) {
   float dx = Math.abs(x - mX2);
   float dy = Math.abs(y - mY2);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     mPath2.quadTo(mX2, mY2, (x + mX2) / 2, (y + mY2) / 2);
     mX2 = x;
     mY2 = y;
   }
 }
Example #16
0
 private void touchMove(float x, float y) {
   float dx = Math.abs(x - mX);
   float dy = Math.abs(y - mY);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
     mX = x;
     mY = y;
   }
 }
  private void drawDrag(Canvas canvas) {
    canvas.drawRect(0, 0, mWidth, PULL_HEIGHT, mBackPaint);

    mPath.reset();
    mPath.moveTo(0, PULL_HEIGHT);
    mPath.quadTo(
        mWidthOffset * mWidth, PULL_HEIGHT + (mHeight - PULL_HEIGHT) * 2, mWidth, PULL_HEIGHT);
    canvas.drawPath(mPath, mBackPaint);
  }
Example #18
0
 private void touch_move(float x, float y) {
   float dx = Math.abs(x - mX1);
   float dy = Math.abs(y - mY1);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     mPath1.quadTo(mX1, mY1, (x + mX1) / 2, (y + mY1) / 2);
     mX1 = x;
     mY1 = y;
   }
 }
 private static void touch_move(Path path, int x, int y) {
   float dx = Math.abs(x - mX);
   float dy = Math.abs(y - mY);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
     mX = x;
     mY = y;
   }
 }
Example #20
0
  @Override
  protected void onDraw(Canvas canvas) {
    mFrontPath.reset();
    mFrontPath.moveTo(mFrontPointsList.get(0).x, mFrontPointsList.get(0).y);

    mBackPath.reset();
    mBackPath.moveTo(mBackPointsList.get(0).x, mBackPointsList.get(0).y);

    // 画笔已经实现移动到初始位置
    int size = mFrontPointsList.size() - 2;
    // 在连续绘制时,起始点需要跳过,只需要控制点和结束点
    for (int i = 0; i < size; i = i + 2) {
      mFrontPath.quadTo(
          mFrontPointsList.get(i + 1).x,
          mFrontPointsList.get(i + 1).y,
          mFrontPointsList.get(i + 2).x,
          mFrontPointsList.get(i + 2).y);

      mBackPath.quadTo(
          mBackPointsList.get(i + 1).x,
          mBackPointsList.get(i + 1).y,
          mBackPointsList.get(i + 2).x,
          mBackPointsList.get(i + 2).y);
    }

    mFrontPath.lineTo(getWidth(), getHeight());
    mFrontPath.lineTo(0, getHeight());
    mFrontPath.close();

    mBackPath.lineTo(getWidth() + mWaveWidth, getHeight());
    mBackPath.lineTo(0, getHeight());
    mBackPath.close();

    canvas.clipPath(mOutBorderPath, Region.Op.INTERSECT);

    // 白色
    canvas.drawPath(mOutBorderPath, mWhitePaint);
    // 前波浪
    canvas.drawPath(mBackPath, mBackPaint);
    // 后波浪
    canvas.drawPath(mFrontPath, mFrontPaint);
    // 外边框
    canvas.drawPath(mOutBorderPath, mOutBorderPaint);
  }
Example #21
0
 public void touch_move(float x, float y) {
   float dx = Math.abs(x - mX);
   float dy = Math.abs(y - mY);
   if ((dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) && (outOfBoundry < maxError)) {
     mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
     mX = x;
     mY = y;
     invalidate();
   }
 }
Example #22
0
 private void touch_move(float x, float y) {
   float dx = Math.abs(x - mX);
   float dy = Math.abs(y - mY);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
     mX = x;
     mY = y;
   }
   mCanvas.drawPath(mPath, mPaint);
 }
 private void drawOutCir(Canvas canvas) {
   mPath.reset();
   mPath.moveTo(0, 0);
   mPath.lineTo(0, PULL_HEIGHT);
   mPath.quadTo(mWidth / 2, PULL_HEIGHT - (1 - getOutRatio()) * PULL_DELTA, mWidth, PULL_HEIGHT);
   mPath.lineTo(mWidth, 0);
   canvas.drawPath(mPath, mBackPaint);
   int innerY = PULL_HEIGHT - PULL_DELTA / 2 - mRadius * 2;
   canvas.drawCircle(mWidth / 2, innerY, mRadius, mBallPaint);
 }
  private void drawBZLine(
      float startX, float startY, float stopX, float stopY, float endX, Canvas canvas) {
    if (null == mBzLine) mBzLine = new Path();

    getLabelLinePaint().setStyle(Style.STROKE);
    // 绘制贝塞尔曲线
    mBzLine.reset();
    mBzLine.moveTo(startX, startY);
    mBzLine.quadTo(stopX, stopY, endX, stopY);
    canvas.drawPath(mBzLine, getLabelLinePaint());
  }
Example #25
0
 @Override
 protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   canvas.drawColor(Color.BLACK);
   //        mPath.lineTo(x, y);
   mPath.quadTo(x, y, x, y);
   canvas.translate(-transX, 0);
   countInfo();
   canvas.drawPath(mPath, mPaint);
   invalidate();
 }
Example #26
0
 @Override
 public void fingerMove(float x, float y, Canvas canvas) {
   float dx = Math.abs(x - mX);
   float dy = Math.abs(y - mY);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
     mX = x;
     mY = y;
   }
   this.draw(canvas);
 }
Example #27
0
 private void Touch_Move(float x, float y) {
   float dx = Math.abs(x - mX);
   float dy = Math.abs(y - mY);
   if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
     mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
     mX = x;
     mY = y;
     if (IsRecordPath) {
       listener.addNodeToPath(x, y, MotionEvent.ACTION_MOVE, IsPaint);
     }
   }
 }
Example #28
0
  void drawOneStroke(Canvas canvas, int nStroke, float fScale) {
    ArrayList pplist = pathDrawing.getPointList();
    List<PathLine.point> list = (List) pplist.get(nStroke);
    path.reset();
    point p = new point(((PathLine.point) list.get(0)).x, ((PathLine.point) list.get(0)).y);
    p.x = (p.x - (float) l);
    p.y = (p.y - (float) t);
    if (p.x < 0x0) {
      Log.d("error", "posx exception");
    }
    if (p.y < 0) {
      Log.d("error", "posy exception");
    }
    p.x = (p.x * fScale);
    p.y = (p.y * fScale);
    if (sHWRate < 0.1f) {
      p.y = 10.0f;
    }
    p.x = (p.x + (float) nstartx);
    p.y = (p.y + (float) nstarty);
    path.moveTo(p.x, p.y);
    float mX = p.x;
    float mY = p.y;
    for (int i = 0x1; i < list.size(); i = i + 0x1) {

      p.setXY(
          (((PathLine.point) list.get(i)).x - (float) l),
          (((PathLine.point) list.get(i)).y - (float) t));
      p.x = (p.x * fScale);
      p.y = (p.y * fScale);
      if (sHWRate < 0.1f) {
        p.y = 10.0f;
      }
      if (p.x < 0x0) {
        Log.d("error", "pos exception");
      }
      if (p.y < 0) {
        Log.d("error", "posy exception");
      }
      p.x = (p.x + (float) nstartx);
      p.y = (p.y + (float) nstarty);
      path.quadTo(mX, mY, ((p.x + mX) / 2.0f), ((p.y + mY) / 2.0f));
      mX = p.x;
      mY = p.y;
    }
    try {
      canvas.drawPath(path, thinPen);
      return;
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
Example #29
0
 void draw_wave(Canvas canvas) {
   float h = height / 2;
   path.moveTo(0, h / 2 + y_values[0]); // start position
   for (int i = 1; i < y_values.length - 1; i += 2) {
     path.quadTo(
         i * space,
         h / 2 + y_values[i],
         (i + 1) * space,
         h / 2 + y_values[i + 1]); // create bezier between critical points
   }
   canvas.drawPath(path, paint);
   path.reset();
 }
Example #30
0
  private void handDraw(byte[] packetData) {
    try {
      int penWidthNum = myConvertByteArrToInt_bigend(packetData, 4);
      int penColorNum = myConvertByteArrToInt_bigend(packetData, 8);
      int nums = myConvertByteArrToInt_bigend(packetData, 12);

      int BYTES_PER_COORDINATE = 2;

      for (int i = 0; i < nums / 4; i++) {
        int x =
            xCoordinateMap(
                myConvertByteArrToShort_bigend(packetData, 16 + i * 2 * BYTES_PER_COORDINATE));
        int y =
            yCoordinateMap(
                myConvertByteArrToShort_bigend(
                    packetData, 16 + i * 2 * BYTES_PER_COORDINATE + BYTES_PER_COORDINATE));
        String str = (i + 1) + " (x=" + x + ",y=" + y + ")";
        writeToMyLogFile(str);
        if (i == 0) {
          lastX = x;
          lastY = y;

          mPath = new Path();
          mPath.moveTo(x, y);

          mPaint = getAPaint();
          mPaint.setStrokeWidth(penWidthMap.get(penWidthNum));
          mPaint.setColor(penColorMap.get(penColorNum));
          HistoryItem item = new HistoryItem(HistoryItem.TYPE_PATH, mPaint, mPath, null, null);
          undoPathList.add(item); //

          mCacheCanvas.drawPoint(x, y, mPaint);
        } else {
          int dx = Math.abs(x - lastX);
          int dy = Math.abs(y - lastY);
          if (dx >= BezierCurveMinGap || dy >= BezierCurveMinGap) {
            mPath.quadTo(lastX, lastY, ((lastX + x) / 2.0f), ((lastY + y) / 2.0f));

            lastX = x;
            lastY = y;

            mCacheCanvas.drawPath(mPath, mPaint);
            handler.sendEmptyMessage(CustomDrawViewCH_INVALIDATE);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
      Logg.e(TAG, "handdraw error");
    }
  }