Home » openjdk-7 » java » awt » geom » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.awt.geom;
   27   
   28   import java.io.Serializable;
   29   
   30   /**
   31    * The <code>RoundRectangle2D</code> class defines a rectangle with
   32    * rounded corners defined by a location {@code (x,y)}, a
   33    * dimension {@code (w x h)}, and the width and height of an arc
   34    * with which to round the corners.
   35    * <p>
   36    * This class is the abstract superclass for all objects that
   37    * store a 2D rounded rectangle.
   38    * The actual storage representation of the coordinates is left to
   39    * the subclass.
   40    *
   41    * @author      Jim Graham
   42    * @since 1.2
   43    */
   44   public abstract class RoundRectangle2D extends RectangularShape {
   45   
   46       /**
   47        * The <code>Float</code> class defines a rectangle with rounded
   48        * corners all specified in <code>float</code> coordinates.
   49        * @since 1.2
   50        */
   51       public static class Float extends RoundRectangle2D
   52           implements Serializable
   53       {
   54           /**
   55            * The X coordinate of this <code>RoundRectangle2D</code>.
   56            * @since 1.2
   57            * @serial
   58            */
   59           public float x;
   60   
   61           /**
   62            * The Y coordinate of this <code>RoundRectangle2D</code>.
   63            * @since 1.2
   64            * @serial
   65            */
   66           public float y;
   67   
   68           /**
   69            * The width of this <code>RoundRectangle2D</code>.
   70            * @since 1.2
   71            * @serial
   72            */
   73           public float width;
   74   
   75           /**
   76            * The height of this <code>RoundRectangle2D</code>.
   77            * @since 1.2
   78            * @serial
   79            */
   80           public float height;
   81   
   82           /**
   83            * The width of the arc that rounds off the corners.
   84            * @since 1.2
   85            * @serial
   86            */
   87           public float arcwidth;
   88   
   89           /**
   90            * The height of the arc that rounds off the corners.
   91            * @since 1.2
   92            * @serial
   93            */
   94           public float archeight;
   95   
   96           /**
   97            * Constructs a new <code>RoundRectangle2D</code>, initialized to
   98            * location (0.0,&nbsp;0.0), size (0.0,&nbsp;0.0), and corner arcs
   99            * of radius 0.0.
  100            * @since 1.2
  101            */
  102           public Float() {
  103           }
  104   
  105           /**
  106            * Constructs and initializes a <code>RoundRectangle2D</code>
  107            * from the specified <code>float</code> coordinates.
  108            *
  109            * @param x the X coordinate of the newly
  110            *          constructed <code>RoundRectangle2D</code>
  111            * @param y the Y coordinate of the newly
  112            *          constructed <code>RoundRectangle2D</code>
  113            * @param w the width to which to set the newly
  114            *          constructed <code>RoundRectangle2D</code>
  115            * @param h the height to which to set the newly
  116            *          constructed <code>RoundRectangle2D</code>
  117            * @param arcw the width of the arc to use to round off the
  118            *             corners of the newly constructed
  119            *             <code>RoundRectangle2D</code>
  120            * @param arch the height of the arc to use to round off the
  121            *             corners of the newly constructed
  122            *             <code>RoundRectangle2D</code>
  123            * @since 1.2
  124            */
  125           public Float(float x, float y, float w, float h,
  126                        float arcw, float arch)
  127           {
  128               setRoundRect(x, y, w, h, arcw, arch);
  129           }
  130   
  131           /**
  132            * {@inheritDoc}
  133            * @since 1.2
  134            */
  135           public double getX() {
  136               return (double) x;
  137           }
  138   
  139           /**
  140            * {@inheritDoc}
  141            * @since 1.2
  142            */
  143           public double getY() {
  144               return (double) y;
  145           }
  146   
  147           /**
  148            * {@inheritDoc}
  149            * @since 1.2
  150            */
  151           public double getWidth() {
  152               return (double) width;
  153           }
  154   
  155           /**
  156            * {@inheritDoc}
  157            * @since 1.2
  158            */
  159           public double getHeight() {
  160               return (double) height;
  161           }
  162   
  163           /**
  164            * {@inheritDoc}
  165            * @since 1.2
  166            */
  167           public double getArcWidth() {
  168               return (double) arcwidth;
  169           }
  170   
  171           /**
  172            * {@inheritDoc}
  173            * @since 1.2
  174            */
  175           public double getArcHeight() {
  176               return (double) archeight;
  177           }
  178   
  179           /**
  180            * {@inheritDoc}
  181            * @since 1.2
  182            */
  183           public boolean isEmpty() {
  184               return (width <= 0.0f) || (height <= 0.0f);
  185           }
  186   
  187           /**
  188            * Sets the location, size, and corner radii of this
  189            * <code>RoundRectangle2D</code> to the specified
  190            * <code>float</code> values.
  191            *
  192            * @param x the X coordinate to which to set the
  193            *          location of this <code>RoundRectangle2D</code>
  194            * @param y the Y coordinate to which to set the
  195            *          location of this <code>RoundRectangle2D</code>
  196            * @param w the width to which to set this
  197            *          <code>RoundRectangle2D</code>
  198            * @param h the height to which to set this
  199            *          <code>RoundRectangle2D</code>
  200            * @param arcw the width to which to set the arc of this
  201            *             <code>RoundRectangle2D</code>
  202            * @param arch the height to which to set the arc of this
  203            *             <code>RoundRectangle2D</code>
  204            * @since 1.2
  205            */
  206           public void setRoundRect(float x, float y, float w, float h,
  207                                    float arcw, float arch)
  208           {
  209               this.x = x;
  210               this.y = y;
  211               this.width = w;
  212               this.height = h;
  213               this.arcwidth = arcw;
  214               this.archeight = arch;
  215           }
  216   
  217           /**
  218            * {@inheritDoc}
  219            * @since 1.2
  220            */
  221           public void setRoundRect(double x, double y, double w, double h,
  222                                    double arcw, double arch)
  223           {
  224               this.x = (float) x;
  225               this.y = (float) y;
  226               this.width = (float) w;
  227               this.height = (float) h;
  228               this.arcwidth = (float) arcw;
  229               this.archeight = (float) arch;
  230           }
  231   
  232           /**
  233            * {@inheritDoc}
  234            * @since 1.2
  235            */
  236           public void setRoundRect(RoundRectangle2D rr) {
  237               this.x = (float) rr.getX();
  238               this.y = (float) rr.getY();
  239               this.width = (float) rr.getWidth();
  240               this.height = (float) rr.getHeight();
  241               this.arcwidth = (float) rr.getArcWidth();
  242               this.archeight = (float) rr.getArcHeight();
  243           }
  244   
  245           /**
  246            * {@inheritDoc}
  247            * @since 1.2
  248            */
  249           public Rectangle2D getBounds2D() {
  250               return new Rectangle2D.Float(x, y, width, height);
  251           }
  252   
  253           /*
  254            * JDK 1.6 serialVersionUID
  255            */
  256           private static final long serialVersionUID = -3423150618393866922L;
  257       }
  258   
  259       /**
  260        * The <code>Double</code> class defines a rectangle with rounded
  261        * corners all specified in <code>double</code> coordinates.
  262        * @since 1.2
  263        */
  264       public static class Double extends RoundRectangle2D
  265           implements Serializable
  266       {
  267           /**
  268            * The X coordinate of this <code>RoundRectangle2D</code>.
  269            * @since 1.2
  270            * @serial
  271            */
  272           public double x;
  273   
  274           /**
  275            * The Y coordinate of this <code>RoundRectangle2D</code>.
  276            * @since 1.2
  277            * @serial
  278            */
  279           public double y;
  280   
  281           /**
  282            * The width of this <code>RoundRectangle2D</code>.
  283            * @since 1.2
  284            * @serial
  285            */
  286           public double width;
  287   
  288           /**
  289            * The height of this <code>RoundRectangle2D</code>.
  290            * @since 1.2
  291            * @serial
  292            */
  293           public double height;
  294   
  295           /**
  296            * The width of the arc that rounds off the corners.
  297            * @since 1.2
  298            * @serial
  299            */
  300           public double arcwidth;
  301   
  302           /**
  303            * The height of the arc that rounds off the corners.
  304            * @since 1.2
  305            * @serial
  306            */
  307           public double archeight;
  308   
  309           /**
  310            * Constructs a new <code>RoundRectangle2D</code>, initialized to
  311            * location (0.0,&nbsp;0.0), size (0.0,&nbsp;0.0), and corner arcs
  312            * of radius 0.0.
  313            * @since 1.2
  314            */
  315           public Double() {
  316           }
  317   
  318           /**
  319            * Constructs and initializes a <code>RoundRectangle2D</code>
  320            * from the specified <code>double</code> coordinates.
  321            *
  322            * @param x the X coordinate of the newly
  323            *          constructed <code>RoundRectangle2D</code>
  324            * @param y the Y coordinate of the newly
  325            *          constructed <code>RoundRectangle2D</code>
  326            * @param w the width to which to set the newly
  327            *          constructed <code>RoundRectangle2D</code>
  328            * @param h the height to which to set the newly
  329            *          constructed <code>RoundRectangle2D</code>
  330            * @param arcw the width of the arc to use to round off the
  331            *             corners of the newly constructed
  332            *             <code>RoundRectangle2D</code>
  333            * @param arch the height of the arc to use to round off the
  334            *             corners of the newly constructed
  335            *             <code>RoundRectangle2D</code>
  336            * @since 1.2
  337            */
  338           public Double(double x, double y, double w, double h,
  339                         double arcw, double arch)
  340           {
  341               setRoundRect(x, y, w, h, arcw, arch);
  342           }
  343   
  344           /**
  345            * {@inheritDoc}
  346            * @since 1.2
  347            */
  348           public double getX() {
  349               return x;
  350           }
  351   
  352           /**
  353            * {@inheritDoc}
  354            * @since 1.2
  355            */
  356           public double getY() {
  357               return y;
  358           }
  359   
  360           /**
  361            * {@inheritDoc}
  362            * @since 1.2
  363            */
  364           public double getWidth() {
  365               return width;
  366           }
  367   
  368           /**
  369            * {@inheritDoc}
  370            * @since 1.2
  371            */
  372           public double getHeight() {
  373               return height;
  374           }
  375   
  376           /**
  377            * {@inheritDoc}
  378            * @since 1.2
  379            */
  380           public double getArcWidth() {
  381               return arcwidth;
  382           }
  383   
  384           /**
  385            * {@inheritDoc}
  386            * @since 1.2
  387            */
  388           public double getArcHeight() {
  389               return archeight;
  390           }
  391   
  392           /**
  393            * {@inheritDoc}
  394            * @since 1.2
  395            */
  396           public boolean isEmpty() {
  397               return (width <= 0.0f) || (height <= 0.0f);
  398           }
  399   
  400           /**
  401            * {@inheritDoc}
  402            * @since 1.2
  403            */
  404           public void setRoundRect(double x, double y, double w, double h,
  405                                    double arcw, double arch)
  406           {
  407               this.x = x;
  408               this.y = y;
  409               this.width = w;
  410               this.height = h;
  411               this.arcwidth = arcw;
  412               this.archeight = arch;
  413           }
  414   
  415           /**
  416            * {@inheritDoc}
  417            * @since 1.2
  418            */
  419           public void setRoundRect(RoundRectangle2D rr) {
  420               this.x = rr.getX();
  421               this.y = rr.getY();
  422               this.width = rr.getWidth();
  423               this.height = rr.getHeight();
  424               this.arcwidth = rr.getArcWidth();
  425               this.archeight = rr.getArcHeight();
  426           }
  427   
  428           /**
  429            * {@inheritDoc}
  430            * @since 1.2
  431            */
  432           public Rectangle2D getBounds2D() {
  433               return new Rectangle2D.Double(x, y, width, height);
  434           }
  435   
  436           /*
  437            * JDK 1.6 serialVersionUID
  438            */
  439           private static final long serialVersionUID = 1048939333485206117L;
  440       }
  441   
  442       /**
  443        * This is an abstract class that cannot be instantiated directly.
  444        * Type-specific implementation subclasses are available for
  445        * instantiation and provide a number of formats for storing
  446        * the information necessary to satisfy the various accessor
  447        * methods below.
  448        *
  449        * @see java.awt.geom.RoundRectangle2D.Float
  450        * @see java.awt.geom.RoundRectangle2D.Double
  451        * @since 1.2
  452        */
  453       protected RoundRectangle2D() {
  454       }
  455   
  456       /**
  457        * Gets the width of the arc that rounds off the corners.
  458        * @return the width of the arc that rounds off the corners
  459        * of this <code>RoundRectangle2D</code>.
  460        * @since 1.2
  461        */
  462       public abstract double getArcWidth();
  463   
  464       /**
  465        * Gets the height of the arc that rounds off the corners.
  466        * @return the height of the arc that rounds off the corners
  467        * of this <code>RoundRectangle2D</code>.
  468        * @since 1.2
  469        */
  470       public abstract double getArcHeight();
  471   
  472       /**
  473        * Sets the location, size, and corner radii of this
  474        * <code>RoundRectangle2D</code> to the specified
  475        * <code>double</code> values.
  476        *
  477        * @param x the X coordinate to which to set the
  478        *          location of this <code>RoundRectangle2D</code>
  479        * @param y the Y coordinate to which to set the
  480        *          location of this <code>RoundRectangle2D</code>
  481        * @param w the width to which to set this
  482        *          <code>RoundRectangle2D</code>
  483        * @param h the height to which to set this
  484        *          <code>RoundRectangle2D</code>
  485        * @param arcWidth the width to which to set the arc of this
  486        *                 <code>RoundRectangle2D</code>
  487        * @param arcHeight the height to which to set the arc of this
  488        *                  <code>RoundRectangle2D</code>
  489        * @since 1.2
  490        */
  491       public abstract void setRoundRect(double x, double y, double w, double h,
  492                                         double arcWidth, double arcHeight);
  493   
  494       /**
  495        * Sets this <code>RoundRectangle2D</code> to be the same as the
  496        * specified <code>RoundRectangle2D</code>.
  497        * @param rr the specified <code>RoundRectangle2D</code>
  498        * @since 1.2
  499        */
  500       public void setRoundRect(RoundRectangle2D rr) {
  501           setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
  502                        rr.getArcWidth(), rr.getArcHeight());
  503       }
  504   
  505       /**
  506        * {@inheritDoc}
  507        * @since 1.2
  508        */
  509       public void setFrame(double x, double y, double w, double h) {
  510           setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
  511       }
  512   
  513       /**
  514        * {@inheritDoc}
  515        * @since 1.2
  516        */
  517       public boolean contains(double x, double y) {
  518           if (isEmpty()) {
  519               return false;
  520           }
  521           double rrx0 = getX();
  522           double rry0 = getY();
  523           double rrx1 = rrx0 + getWidth();
  524           double rry1 = rry0 + getHeight();
  525           // Check for trivial rejection - point is outside bounding rectangle
  526           if (x < rrx0 || y < rry0 || x >= rrx1 || y >= rry1) {
  527               return false;
  528           }
  529           double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
  530           double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
  531           // Check which corner point is in and do circular containment
  532           // test - otherwise simple acceptance
  533           if (x >= (rrx0 += aw) && x < (rrx0 = rrx1 - aw)) {
  534               return true;
  535           }
  536           if (y >= (rry0 += ah) && y < (rry0 = rry1 - ah)) {
  537               return true;
  538           }
  539           x = (x - rrx0) / aw;
  540           y = (y - rry0) / ah;
  541           return (x * x + y * y <= 1.0);
  542       }
  543   
  544       private int classify(double coord, double left, double right,
  545                            double arcsize)
  546       {
  547           if (coord < left) {
  548               return 0;
  549           } else if (coord < left + arcsize) {
  550               return 1;
  551           } else if (coord < right - arcsize) {
  552               return 2;
  553           } else if (coord < right) {
  554               return 3;
  555           } else {
  556               return 4;
  557           }
  558       }
  559   
  560       /**
  561        * {@inheritDoc}
  562        * @since 1.2
  563        */
  564       public boolean intersects(double x, double y, double w, double h) {
  565           if (isEmpty() || w <= 0 || h <= 0) {
  566               return false;
  567           }
  568           double rrx0 = getX();
  569           double rry0 = getY();
  570           double rrx1 = rrx0 + getWidth();
  571           double rry1 = rry0 + getHeight();
  572           // Check for trivial rejection - bounding rectangles do not intersect
  573           if (x + w <= rrx0 || x >= rrx1 || y + h <= rry0 || y >= rry1) {
  574               return false;
  575           }
  576           double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
  577           double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
  578           int x0class = classify(x, rrx0, rrx1, aw);
  579           int x1class = classify(x + w, rrx0, rrx1, aw);
  580           int y0class = classify(y, rry0, rry1, ah);
  581           int y1class = classify(y + h, rry0, rry1, ah);
  582           // Trivially accept if any point is inside inner rectangle
  583           if (x0class == 2 || x1class == 2 || y0class == 2 || y1class == 2) {
  584               return true;
  585           }
  586           // Trivially accept if either edge spans inner rectangle
  587           if ((x0class < 2 && x1class > 2) || (y0class < 2 && y1class > 2)) {
  588               return true;
  589           }
  590           // Since neither edge spans the center, then one of the corners
  591           // must be in one of the rounded edges.  We detect this case if
  592           // a [xy]0class is 3 or a [xy]1class is 1.  One of those two cases
  593           // must be true for each direction.
  594           // We now find a "nearest point" to test for being inside a rounded
  595           // corner.
  596           x = (x1class == 1) ? (x = x + w - (rrx0 + aw)) : (x = x - (rrx1 - aw));
  597           y = (y1class == 1) ? (y = y + h - (rry0 + ah)) : (y = y - (rry1 - ah));
  598           x = x / aw;
  599           y = y / ah;
  600           return (x * x + y * y <= 1.0);
  601       }
  602   
  603       /**
  604        * {@inheritDoc}
  605        * @since 1.2
  606        */
  607       public boolean contains(double x, double y, double w, double h) {
  608           if (isEmpty() || w <= 0 || h <= 0) {
  609               return false;
  610           }
  611           return (contains(x, y) &&
  612                   contains(x + w, y) &&
  613                   contains(x, y + h) &&
  614                   contains(x + w, y + h));
  615       }
  616   
  617       /**
  618        * Returns an iteration object that defines the boundary of this
  619        * <code>RoundRectangle2D</code>.
  620        * The iterator for this class is multi-threaded safe, which means
  621        * that this <code>RoundRectangle2D</code> class guarantees that
  622        * modifications to the geometry of this <code>RoundRectangle2D</code>
  623        * object do not affect any iterations of that geometry that
  624        * are already in process.
  625        * @param at an optional <code>AffineTransform</code> to be applied to
  626        * the coordinates as they are returned in the iteration, or
  627        * <code>null</code> if untransformed coordinates are desired
  628        * @return    the <code>PathIterator</code> object that returns the
  629        *          geometry of the outline of this
  630        *          <code>RoundRectangle2D</code>, one segment at a time.
  631        * @since 1.2
  632        */
  633       public PathIterator getPathIterator(AffineTransform at) {
  634           return new RoundRectIterator(this, at);
  635       }
  636   
  637       /**
  638        * Returns the hashcode for this <code>RoundRectangle2D</code>.
  639        * @return the hashcode for this <code>RoundRectangle2D</code>.
  640        * @since 1.6
  641        */
  642       public int hashCode() {
  643           long bits = java.lang.Double.doubleToLongBits(getX());
  644           bits += java.lang.Double.doubleToLongBits(getY()) * 37;
  645           bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
  646           bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
  647           bits += java.lang.Double.doubleToLongBits(getArcWidth()) * 53;
  648           bits += java.lang.Double.doubleToLongBits(getArcHeight()) * 59;
  649           return (((int) bits) ^ ((int) (bits >> 32)));
  650       }
  651   
  652       /**
  653        * Determines whether or not the specified <code>Object</code> is
  654        * equal to this <code>RoundRectangle2D</code>.  The specified
  655        * <code>Object</code> is equal to this <code>RoundRectangle2D</code>
  656        * if it is an instance of <code>RoundRectangle2D</code> and if its
  657        * location, size, and corner arc dimensions are the same as this
  658        * <code>RoundRectangle2D</code>.
  659        * @param obj  an <code>Object</code> to be compared with this
  660        *             <code>RoundRectangle2D</code>.
  661        * @return  <code>true</code> if <code>obj</code> is an instance
  662        *          of <code>RoundRectangle2D</code> and has the same values;
  663        *          <code>false</code> otherwise.
  664        * @since 1.6
  665        */
  666       public boolean equals(Object obj) {
  667           if (obj == this) {
  668               return true;
  669           }
  670           if (obj instanceof RoundRectangle2D) {
  671               RoundRectangle2D rr2d = (RoundRectangle2D) obj;
  672               return ((getX() == rr2d.getX()) &&
  673                       (getY() == rr2d.getY()) &&
  674                       (getWidth() == rr2d.getWidth()) &&
  675                       (getHeight() == rr2d.getHeight()) &&
  676                       (getArcWidth() == rr2d.getArcWidth()) &&
  677                       (getArcHeight() == rr2d.getArcHeight()));
  678           }
  679           return false;
  680       }
  681   }

Home » openjdk-7 » java » awt » geom » [javadoc | source]