001package com.hfg.graphics.units; 002 003 004import java.util.regex.Matcher; 005import java.util.regex.Pattern; 006 007import com.hfg.units.UnitException; 008import com.hfg.util.StringUtil; 009 010//------------------------------------------------------------------------------ 011/** 012 * Interface for a unit-independent graphic length measurement. 013 * 014 * @author J. Alex Taylor, hairyfatguy.com 015 */ 016//------------------------------------------------------------------------------ 017// com.hfg XML/HTML Coding Library 018// 019// This library is free software; you can redistribute it and/or 020// modify it under the terms of the GNU Lesser General Public 021// License as published by the Free Software Foundation; either 022// version 2.1 of the License, or (at your option) any later version. 023// 024// This library is distributed in the hope that it will be useful, 025// but WITHOUT ANY WARRANTY; without even the implied warranty of 026// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 027// Lesser General Public License for more details. 028// 029// You should have received a copy of the GNU Lesser General Public 030// License along with this library; if not, write to the Free Software 031// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 032// 033// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 034// jataylor@hairyfatguy.com 035//------------------------------------------------------------------------------ 036 037public interface GfxSize 038{ 039 040 public float to(GfxUnits inUnits); 041 042 public int toInt(GfxUnits inUnits); 043 044 public float value(); 045 046 public GfxUnits getUnits(); 047 048 public GfxSize add(GfxSize inValue); 049 public GfxSize subtract(GfxSize inValue); 050 051 public void scale(float inScalingFactor); 052 053 static final Pattern MEASUREMENT_PATTERN = Pattern.compile("(\\-?[\\d\\.]+)\\s*(\\w+)?"); 054 055 static final Pattern INT_WITH_UNITS_PATTERN = Pattern.compile("(-?\\d+)\\s?+([^\\d]+)"); 056 static final Pattern DOUBLE_WITH_UNITS_PATTERN = Pattern.compile("(-?\\d+\\.\\d+)\\s?+([^\\d]+)"); 057 static final Pattern SCIENTIFIC_NOTATION_WITH_UNITS_PATTERN = Pattern.compile("(-?\\d+(?:\\.\\d+)?E\\-?\\d+)\\s?+(\\S+)"); 058 059 //--------------------------------------------------------------------------- 060 /** 061 Convenience allocator that accepts a string with a value followed by units. 062 * @param inStringValue the string value 063 */ 064 public static GfxSize allocate(String inStringValue) 065 { 066 float floatVal; 067 GfxUnits units; 068 069 Matcher m = INT_WITH_UNITS_PATTERN.matcher(inStringValue.trim()); 070 if (m.matches()) 071 { 072 floatVal = Float.parseFloat(m.group(1)); 073 units = GfxUnits.valueOf(m.group(2)); 074 } 075 else 076 { 077 m = DOUBLE_WITH_UNITS_PATTERN.matcher(inStringValue.trim()); 078 if (m.matches()) 079 { 080 floatVal = Float.parseFloat(m.group(1)); 081 units = GfxUnits.valueOf(m.group(2)); 082 } 083 else 084 { 085 m = SCIENTIFIC_NOTATION_WITH_UNITS_PATTERN.matcher(inStringValue.trim()); 086 if (m.matches()) 087 { 088 floatVal = Float.parseFloat(m.group(1)); 089 units = GfxUnits.valueOf(m.group(2)); 090 } 091 else 092 { 093 throw new UnitException("Couldn't parse " + StringUtil.singleQuote(inStringValue) + " into a GfxSize!"); 094 } 095 } 096 } 097 098 099 if (null == units) 100 { 101 throw new UnitException("Couldn't parse " + StringUtil.singleQuote(inStringValue) + " into a GfxSize! Unrecognized units value."); 102 } 103 104 GfxSize size = null; 105 106 if (units.equals(GfxUnits.pixels)) 107 { 108 size = new Pixels((int)floatVal); 109 } 110 else if (units.equals(GfxUnits.points)) 111 { 112 size = new Points(floatVal); 113 } 114 else if (units.equals(GfxUnits.dxa)) 115 { 116 size = new Points(floatVal / 20); 117 } 118 else if (units.equals(GfxUnits.inches)) 119 { 120 size = new Points(floatVal * 72f); // There are 72 points per inch 121 } 122 123 return size; 124 } 125 126 //-------------------------------------------------------------------------- 127 /** 128 Function for converting a string representation of a graphics measurement into its appropriate object. 129 @param inStringValue the string representation (ex: "10px", "12pt", or "17.5") 130 @param inDefaultUnits the units to use if the string representation is unit-less. 131 @return a GfxSize-extending object 132 */ 133 public static GfxSize allocate(String inStringValue, GfxUnits inDefaultUnits) 134 { 135 if (! StringUtil.isSet(inStringValue)) 136 { 137 throw new RuntimeException("No String value sent to GfxSize.allocate()!"); 138 } 139 140 inStringValue = inStringValue.trim(); 141 142 Matcher m = MEASUREMENT_PATTERN.matcher(inStringValue); 143 if (! m.matches()) 144 { 145 throw new RuntimeException(StringUtil.singleQuote(inStringValue) + " could not be interpreted by GfxSize.allocate()!"); 146 } 147 148 float floatVal = Float.parseFloat(m.group(1)); 149 GfxSize size = null; 150 GfxUnits units = GfxUnits.valueOf(m.group(2)); 151 if (null == units) 152 { 153 units = inDefaultUnits; 154 } 155 156 if (units.equals(GfxUnits.pixels)) 157 { 158 size = new Pixels((int)floatVal); 159 } 160 else if (units.equals(GfxUnits.points)) 161 { 162 size = new Points(floatVal); 163 } 164 else if (units.equals(GfxUnits.dxa)) 165 { 166 size = new Points(floatVal / 20); 167 } 168 else if (units.equals(GfxUnits.inches)) 169 { 170 size = new Points(floatVal * 72f); // There are 72 points per inch 171 } 172 173 return size; 174 } 175 176 //-------------------------------------------------------------------------- 177 /** 178 Function for constructing a GfxSize object. 179 @param inValue the integer value 180 @param inUnits the units to use 181 @return a GfxSize-extending object 182 */ 183 public static GfxSize allocate(int inValue, GfxUnits inUnits) 184 { 185 return new GfxSizeImpl(inValue, inUnits); 186 } 187 188 //-------------------------------------------------------------------------- 189 /** 190 Function for constructing a GfxSize object. 191 @param inValue the float value 192 @param inUnits the units to use 193 @return a GfxSize-extending object 194 */ 195 public static GfxSize allocate(float inValue, GfxUnits inUnits) 196 { 197 return new GfxSizeImpl(inValue, inUnits); 198 } 199 200 //--------------------------------------------------------------------------- 201 public default boolean greaterThan(GfxSize inValue) 202 { 203 boolean result = false; 204 if (inValue != null) 205 { 206 result = to(getUnits()) > inValue.to(getUnits()); 207 } 208 209 return result; 210 } 211 212 //--------------------------------------------------------------------------- 213 public default boolean lessThan(GfxSize inValue) 214 { 215 boolean result = false; 216 if (inValue != null) 217 { 218 result = to(getUnits()) < inValue.to(getUnits()); 219 } 220 221 return result; 222 } 223 224}