/** Constrains a point to the current grid. */
  protected Point constrainPoint(Point p) {
    // constrain to view size
    Dimension size = getSize();
    // p.x = Math.min(size.width, Math.max(1, p.x));
    // p.y = Math.min(size.height, Math.max(1, p.y));
    p.x = Geom.range(1, size.width, p.x);
    p.y = Geom.range(1, size.height, p.y);

    if (fConstrainer != null) {
      return fConstrainer.constrainPoint(p);
    }
    return p;
  }
 @Override
 public Rectangle2D.Double getDrawingArea() {
   if (cachedDrawingArea == null) {
     Rectangle2D rx = getBounds();
     Rectangle2D.Double r =
         (rx instanceof Rectangle2D.Double)
             ? (Rectangle2D.Double) rx
             : new Rectangle2D.Double(rx.getX(), rx.getY(), rx.getWidth(), rx.getHeight());
     double g = SVGAttributeKeys.getPerpendicularHitGrowth(this);
     Geom.grow(r, g, g);
     if (TRANSFORM.get(this) == null) {
       cachedDrawingArea = r;
     } else {
       cachedDrawingArea = new Rectangle2D.Double();
       cachedDrawingArea.setRect(TRANSFORM.get(this).createTransformedShape(r).getBounds2D());
     }
   }
   return (Rectangle2D.Double) cachedDrawingArea.clone();
 }