@Override
 protected void onBoundsChange(Rect bounds) {
   super.onBoundsChange(bounds);
   fBounds.left = bounds.left + mBorderWidth / 2f + .5f;
   fBounds.right = bounds.right - mBorderWidth / 2f - .5f;
   fBounds.top = bounds.top + mBorderWidth / 2f + .5f;
   fBounds.bottom = bounds.bottom - mBorderWidth / 2f - .5f;
 }
  /** Resets the dirty region when the motion event occurs. */
  private void resetDirtyRect(float eventX, float eventY) {

    // The lastTouchX and lastTouchY were set when the ACTION_DOWN
    // motion event occurred.
    dirtyRect.left = Math.min(lastTouchX, eventX);
    dirtyRect.right = Math.max(lastTouchX, eventX);
    dirtyRect.top = Math.min(lastTouchY, eventY);
    dirtyRect.bottom = Math.max(lastTouchY, eventY);
  }
 private RectF getRectF() {
   if (backgroundRectF == null) {
     backgroundRectF = new RectF();
     backgroundRectF.left = mPadding;
     backgroundRectF.top = mPadding;
     backgroundRectF.right = getWidth() - mPadding;
     backgroundRectF.bottom = getHeight() - mPadding;
   }
   return backgroundRectF;
 }
 /** Called when replaying history to ensure the dirty region includes all points. */
 private void expandDirtyRect(float historicalX, float historicalY) {
   if (historicalX < dirtyRect.left) {
     dirtyRect.left = historicalX;
   } else if (historicalX > dirtyRect.right) {
     dirtyRect.right = historicalX;
   }
   if (historicalY < dirtyRect.top) {
     dirtyRect.top = historicalY;
   } else if (historicalY > dirtyRect.bottom) {
     dirtyRect.bottom = historicalY;
   }
 }
 private void doLimits(float x, float y) {
   if (x < limits.left) {
     limits.left = x;
   }
   if (x > limits.right) {
     limits.right = x;
   }
   if (y < limits.top) {
     limits.top = y;
   }
   if (y > limits.bottom) {
     limits.bottom = y;
   }
 }