1 /*
   2  * Copyright (c) 2008, 2013, 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 javafx.css;
  27 
  28 import javafx.scene.text.Font;
  29 
  30 
  31 /**
  32  * Represents a size specified in a particular unit, such as 14px or 0.2em.
  33  *
  34  * @since 9
  35  */
  36 final public class Size {
  37 
  38     final private double value;
  39     final private SizeUnits units;
  40     public Size(double value, SizeUnits units) {
  41         this.value = value;
  42         this.units = (units != null) ? units : SizeUnits.PX;
  43     }
  44 
  45     /** */
  46     public double getValue() {
  47         return value;
  48     }
  49 
  50     /** */
  51     public SizeUnits getUnits() {
  52         return units;
  53     }
  54     
  55     /**
  56      * Return whether or not this Size is an absolute value or a relative value.
  57      */
  58     public boolean isAbsolute() {
  59         return units.isAbsolute();
  60     }
  61     
  62     /** Convert this size into Points units, a Point is 1/72 of a inch */
  63     double points(Font font) {
  64         return points(1.0, font);
  65     }
  66 
  67     /**
  68       * Convert this size into points
  69       *
  70       * @param multiplier   The multiplier for PERCENTAGE sizes
  71       * @param font         The font for EM sizes
  72       */
  73     double points(double multiplier, Font font) {
  74         return units.points(value, multiplier, font);
  75     }
  76 
  77     /**
  78       * Convert this size into pixels
  79       *
  80       * @param multiplier   The multiplier for PERCENTAGE sizes
  81       * @param font         The font for EM sizes
  82       */
  83     public double pixels(double multiplier, Font font) {
  84         return units.pixels(value, multiplier, font);
  85     }
  86 
  87     /**
  88       * If size is not an absolute size, return the product of font size in pixels
  89       * and value. Otherwise, return the absolute value.
  90       */
  91     public double pixels(Font font) {
  92         return pixels(1.0f, font);
  93     }
  94 
  95     /**
  96       * If size is not an absolute size, return the product of multiplier
  97       * and value. Otherwise, return the absolute value.
  98       */
  99     double pixels(double multiplier) {
 100         return pixels(multiplier, null);
 101     }
 102 
 103     /**
 104       * A convenience method for calling <code>pixels(1)</code>
 105       */
 106     public double pixels() {
 107         return pixels(1.0f, null);
 108     }
 109 
 110     @Override public String toString() {
 111         return Double.toString(value) + units.toString();
 112     }
 113 
 114     @Override public int hashCode() {
 115         long bits = 17L;
 116         bits = 37L * bits + Double.doubleToLongBits(value);
 117         bits = 37L * bits + units.hashCode();
 118         return (int) (bits ^ (bits >> 32));
 119     }
 120 
 121     @Override public boolean equals(Object obj) {
 122         if (this == obj) return true;
 123 
 124         if (obj == null || obj.getClass() != this.getClass()) {
 125             return false;
 126         }
 127         final Size other = (Size)obj;
 128 
 129         if (units != other.units) {
 130             return false;
 131         }
 132 
 133         if (value == other.value) {
 134             return true;
 135         }
 136 
 137         if ((value > 0) ? other.value > 0 : other.value < 0) {
 138             //
 139             // double == double is not reliable since a double is kind of
 140             // a fuzzy value. And Double.compare is too precise.
 141             // For javafx, most sizes are rounded to the nearest tenth
 142             // (see SizeUnits.round) so comparing  here to the nearest
 143             // millionth is more than adequate. In the case of rads and
 144             // percents, this is also be more than adequate.
 145             //
 146             // Math.abs is too slow!
 147             final double v0 = value > 0 ? value : -value;
 148             final double v1 = other.value > 0 ? other.value : -other.value;
 149             final double diff = value  - other.value;
 150             if (diff < -0.000001 || 0.000001 < diff) {
 151                 return false;
 152             }
 153 
 154             return true;
 155         }
 156         return false;
 157     }
 158 
 159 }
 160