home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / geom / RoundRectangle2D.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  11.6 KB  |  472 lines

  1. /*
  2.  * @(#)RoundRectangle2D.java    1.6 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.awt.geom;
  16.  
  17. /**
  18.  * A rectangle with rounded corners defined by a location (x, y), a
  19.  * dimension (w x h), and the width and height of an arc to round the
  20.  * corners with.
  21.  * <p>
  22.  * This class is only the abstract superclass for all objects which
  23.  * store a 2D rounded rectangle.
  24.  * The actual storage representation of the coordinates is left to
  25.  * the subclass.
  26.  *
  27.  * @version 10 Feb 1997
  28.  * @author    Jim Graham
  29.  */
  30. public abstract class RoundRectangle2D extends RectangularShape {
  31.     /**
  32.      * A rectangle with rounded corners all specified in float coordinates.
  33.      */
  34.     public static class Float extends RoundRectangle2D {
  35.     /**
  36.      * The x coordinate of the rectangle.
  37.      */
  38.     public float x;
  39.  
  40.     /**
  41.      * The y coordinate of the rectangle.
  42.      */
  43.     public float y;
  44.  
  45.     /**
  46.      * The width of the rectangle.
  47.      */
  48.     public float width;
  49.  
  50.     /**
  51.      * The height of the rectangle.
  52.      */
  53.     public float height;
  54.  
  55.     /**
  56.      * The width of the arc that rounds off the corners.
  57.      */
  58.     public float arcwidth;
  59.  
  60.     /**
  61.      * The height of the arc that rounds off the corners.
  62.      */
  63.     public float archeight;
  64.  
  65.     /**
  66.      * Constructs a new rounded rectangle, initialized to location (0.0, 0.0),
  67.      * size (0.0, 0.0), and corner arcs of radius 0.0.
  68.      */
  69.     public Float() {
  70.     }
  71.  
  72.     /**
  73.      * Constructs and initializes a rectangle from the specified coordinates.
  74.      * @param x the x coordinate
  75.      * @param y the y coordinate
  76.      * @param width the width of the rectangle
  77.      * @param height the height of the rectangle
  78.     */
  79.     public Float(float x, float y, float w, float h,
  80.                    float arcw, float arch) {
  81.         setRoundRect(x, y, w, h, arcw, arch);
  82.     }
  83.  
  84.     /**
  85.      * Returns the X coordinate of the rounded rectangle in double precision.
  86.      */
  87.     public double getX() {
  88.         return (double) x;
  89.     }
  90.  
  91.     /**
  92.      * Returns the Y coordinate of the rounded rectangle in double precision.
  93.      */
  94.     public double getY() {
  95.         return (double) y;
  96.     }
  97.  
  98.     /**
  99.      * Returns the width of the rounded rectangle in double precision.
  100.      */
  101.     public double getWidth() {
  102.         return (double) width;
  103.     }
  104.  
  105.     /**
  106.      * Returns the height of the rounded rectangle in double precision.
  107.      */
  108.     public double getHeight() {
  109.         return (double) height;
  110.     }
  111.  
  112.     /**
  113.      * Gets the width of the arc that rounds off the corners.
  114.      */
  115.     public double getArcWidth() {
  116.         return (double) arcwidth;
  117.     }
  118.  
  119.     /**
  120.      * Gets the height of the arc that rounds off the corners.
  121.      */
  122.     public double getArcHeight() {
  123.         return (double) archeight;
  124.     }
  125.  
  126.     /**
  127.      * Determines whether the rounded rectangle is empty.
  128.      */
  129.     public boolean isEmpty() {
  130.         return (width <= 0.0f) || (height <= 0.0f);
  131.     }
  132.  
  133.     /**
  134.      * Sets the location, size, and arc radii of this rectangle to the
  135.      * specified float values.
  136.      */
  137.     public void setRoundRect(float x, float y, float w, float h,
  138.                  float arcw, float arch) {
  139.         this.x = x;
  140.         this.y = y;
  141.         this.width = w;
  142.         this.height = h;
  143.         this.arcwidth = arcw;
  144.         this.archeight = arch;
  145.     }
  146.  
  147.     /**
  148.      * Sets the location, size, and arc radii of this rectangle to the
  149.      * specified double values.
  150.      */
  151.     public void setRoundRect(double x, double y, double w, double h,
  152.                  double arcw, double arch) {
  153.         this.x = (float) x;
  154.         this.y = (float) y;
  155.         this.width = (float) w;
  156.         this.height = (float) h;
  157.         this.arcwidth = (float) arcw;
  158.         this.archeight = (float) arch;
  159.     }
  160.  
  161.     /**
  162.      * Sets this rounded rectangle to be the same as the specified
  163.      * RoundRectangle.
  164.      */
  165.     public void setRoundRect(RoundRectangle2D rr) {
  166.         this.x = (float) rr.getX();
  167.         this.y = (float) rr.getY();
  168.         this.width = (float) rr.getWidth();
  169.         this.height = (float) rr.getHeight();
  170.         this.arcwidth = (float) rr.getArcWidth();
  171.         this.archeight = (float) rr.getArcHeight();
  172.     }
  173.  
  174.     /**
  175.      * Return the high precision bounding box of the shape.
  176.      */
  177.     public Rectangle2D getBounds2D() {
  178.         return new Rectangle2D.Float(x, y, width, height);
  179.     }
  180.     }
  181.  
  182.     /**
  183.      * A rectangle with rounded corners all specified in double coordinates.
  184.      */
  185.     public static class Double extends RoundRectangle2D {
  186.     /**
  187.      * The x coordinate of the rectangle.
  188.      */
  189.     public double x;
  190.  
  191.     /**
  192.      * The y coordinate of the rectangle.
  193.      */
  194.     public double y;
  195.  
  196.     /**
  197.      * The width of the rectangle.
  198.      */
  199.     public double width;
  200.  
  201.     /**
  202.      * The height of the rectangle.
  203.      */
  204.     public double height;
  205.  
  206.     /**
  207.      * The width of the arc that rounds off the corners.
  208.      */
  209.     public double arcwidth;
  210.  
  211.     /**
  212.      * The height of the arc that rounds off the corners.
  213.      */
  214.     public double archeight;
  215.  
  216.     /**
  217.      * Constructs a new rounded rectangle,
  218.      * initialized to location (0.0, 0.0),
  219.      * size (0.0, 0.0),
  220.      * and corner arcs of radius 0.0.
  221.      */
  222.     public Double() {
  223.     }
  224.  
  225.     /**
  226.      * Constructs and initializes a rectangle from the
  227.      * specified coordinates.
  228.      * @param x the x coordinate
  229.      * @param y the y coordinate
  230.      * @param width the width of the rectangle
  231.      * @param height the height of the rectangle
  232.     */
  233.     public Double(double x, double y, double w, double h,
  234.               double arcw, double arch) {
  235.         setRoundRect(x, y, w, h, arcw, arch);
  236.     }
  237.  
  238.     /**
  239.      * Returns the X coordinate of the rounded rectangle in
  240.      * double precision.
  241.      */
  242.     public double getX() {
  243.         return x;
  244.     }
  245.  
  246.     /**
  247.      * Returns the Y coordinate of the rounded rectangle in
  248.      * double precision.
  249.      */
  250.     public double getY() {
  251.         return y;
  252.     }
  253.  
  254.     /**
  255.      * Returns the width of the rounded rectangle in
  256.      * double precision.
  257.      */
  258.     public double getWidth() {
  259.         return width;
  260.     }
  261.  
  262.     /**
  263.      * Returns the height of the rounded rectangle in double precision.
  264.      */
  265.     public double getHeight() {
  266.         return height;
  267.     }
  268.  
  269.     /**
  270.      * Gets the width of the arc that rounds off the corners.
  271.      */
  272.     public double getArcWidth() {
  273.         return arcwidth;
  274.     }
  275.  
  276.     /**
  277.      * Gets the height of the arc that rounds off the corners.
  278.      */
  279.     public double getArcHeight() {
  280.         return archeight;
  281.     }
  282.  
  283.     /**
  284.      * Determines whether the rounded rectangle is empty.
  285.      */
  286.     public boolean isEmpty() {
  287.         return (width <= 0.0f) || (height <= 0.0f);
  288.     }
  289.  
  290.     /**
  291.      * Sets the location, size, and arc radii of this rectangle to the
  292.      * specified double values.
  293.      */
  294.     public void setRoundRect(double x, double y, double w, double h,
  295.                  double arcw, double arch) {
  296.         this.x = x;
  297.         this.y = y;
  298.         this.width = w;
  299.         this.height = h;
  300.         this.arcwidth = arcw;
  301.         this.archeight = arch;
  302.     }
  303.  
  304.     /**
  305.      * Sets this rounded rectangle to be the same as the specified
  306.      * RoundRectangle.
  307.      */
  308.     public void setRoundRect(RoundRectangle2D rr) {
  309.         this.x = rr.getX();
  310.         this.y = rr.getY();
  311.         this.width = rr.getWidth();
  312.         this.height = rr.getHeight();
  313.         this.arcwidth = rr.getArcWidth();
  314.         this.archeight = rr.getArcHeight();
  315.     }
  316.  
  317.     /**
  318.      * Return the high precision bounding box of the shape.
  319.      */
  320.     public Rectangle2D getBounds2D() {
  321.         return new Rectangle2D.Double(x, y, width, height);
  322.     }
  323.     }
  324.  
  325.     protected RoundRectangle2D() {
  326.     }
  327.  
  328.     /**
  329.      * Gets the width of the arc that rounds off the corners.
  330.      */
  331.     public abstract double getArcWidth();
  332.  
  333.     /**
  334.      * Gets the height of the arc that rounds off the corners.
  335.      */
  336.     public abstract double getArcHeight();
  337.  
  338.     /**
  339.      * Sets the location, size, and corner radii of this rounded
  340.      * rectangle to the specified double values.
  341.      */
  342.     public abstract void setRoundRect(double x, double y, double w, double h,
  343.                       double arcWidth, double arcHeight);
  344.  
  345.     /**
  346.      * Sets this rounded rectangle to be the same as the specified
  347.      * RoundRectangle.
  348.      */
  349.     public void setRoundRect(RoundRectangle2D rr) {
  350.     setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
  351.              rr.getArcWidth(), rr.getArcHeight());
  352.     }
  353.  
  354.     /**
  355.      * Sets the location and size of the outer bounds of this shape
  356.      * to the specified rectangular values.
  357.      */
  358.     public void setBounds(double x, double y, double w, double h) {
  359.     setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
  360.     }
  361.  
  362.     /**
  363.      * Test if a given coordinate is inside the boundary of the shape.
  364.      */
  365.     public boolean contains(double x, double y) {
  366.     if (isEmpty()) {
  367.         return false;
  368.     }
  369.     double rrx0 = getX();
  370.     double rry0 = getY();
  371.     double rrx1 = rrx0 + getWidth();
  372.     double rry1 = rry0 + getHeight();
  373.     // Check for trivial rejection - point is outside bounding rectangle
  374.     if (x < rrx0 || y < rry0 || x >= rrx1 || y >= rry1) {
  375.         return false;
  376.     }
  377.     double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
  378.     double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
  379.     // Check which corner point is in and do circular containment
  380.     // test - otherwise simple acceptance
  381.     if (x >= (rrx0 += aw) && x < (rrx0 = rrx1 - aw)) {
  382.         return true;
  383.     }
  384.     if (y >= (rry0 += ah) && y < (rry0 = rry1 - ah)) {
  385.         return true;
  386.     }
  387.     x = (x - rrx0) / aw;
  388.     y = (y - rry0) / ah;
  389.     return (x * x + y * y <= 1.0);
  390.     }
  391.  
  392.     private int classify(double coord, double left, double right,
  393.              double arcsize) {
  394.     if (coord < left) {
  395.         return 0;
  396.     } else if (coord < left + arcsize) {
  397.         return 1;
  398.     } else if (coord < right - arcsize) {
  399.         return 2;
  400.     } else if (coord < right) {
  401.         return 3;
  402.     } else {
  403.         return 4;
  404.     }
  405.     }
  406.  
  407.     /**
  408.      * Test if the interior of the Shape intersects the interior of a given
  409.      * set of rectangular coordinates.
  410.      */
  411.     public boolean intersects(double x, double y, double w, double h) {
  412.     if (isEmpty() || w <= 0 || h <= 0) {
  413.         return false;
  414.     }
  415.     double rrx0 = getX();
  416.     double rry0 = getY();
  417.     double rrx1 = rrx0 + getWidth();
  418.     double rry1 = rry0 + getHeight();
  419.     // Check for trivial rejection - bounding rectangles do not intersect
  420.     if (x + w <= rrx0 || x >= rrx1 || y + h <= rry0 || y >= rry1) {
  421.         return false;
  422.     }
  423.     double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
  424.     double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
  425.     int x0class = classify(x, rrx0, rrx1, aw);
  426.     int x1class = classify(x + w, rrx0, rrx1, aw);
  427.     int y0class = classify(y, rry0, rry1, ah);
  428.     int y1class = classify(y + h, rry0, rry1, ah);
  429.     // Trivially accept if any point is inside inner rectangle
  430.     if (x0class == 2 || x1class == 2 || y0class == 2 || y1class == 2) {
  431.         return true;
  432.     }
  433.     // Trivially accept if either edge spans inner rectangle
  434.     if ((x0class < 2 && x1class > 2) || (y0class < 2 && y1class > 2)) {
  435.         return true;
  436.     }
  437.     // Since neither edge spans the center, then one of the corners
  438.     // must be in one of the rounded edges.  We detect this case if
  439.     // a [xy]0class is 3 or a [xy]1class is 1.  One of those two cases
  440.     // must be true for each direction.
  441.     // We now find a "nearest point" to test for being inside a rounded
  442.     // corner.
  443.     x = (x1class == 1) ? (x = x + w - (rrx0 + aw)) : (x = x - (rrx1 - aw));
  444.     y = (y1class == 1) ? (y = y + h - (rry0 + ah)) : (y = y - (rry1 - ah));
  445.     x = x / aw;
  446.     y = y / ah;
  447.     return (x * x + y * y <= 1.0);
  448.     }
  449.  
  450.     /**
  451.      * Test if the interior of the Shape entirely contains the given
  452.      * set of rectangular coordinates.
  453.      */
  454.     public boolean contains(double x, double y, double w, double h) {
  455.     if (isEmpty() || w <= 0 || h <= 0) {
  456.         return false;
  457.     }
  458.     return (contains(x, y) &&
  459.         contains(x + w, y) &&
  460.         contains(x, y + h) &&
  461.         contains(x + w, y + h));
  462.     }
  463.  
  464.     /**
  465.      * Return an iteration object that defines the boundary of the
  466.      * shape.
  467.      */
  468.     public PathIterator getPathIterator(AffineTransform at) {
  469.     return new RoundRectIterator(this, at);
  470.     }
  471. }
  472.