1<?php 2/** 3 * Simple class to work with units (e.g. 'px', 'pt', 'cm'...) 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author LarsDW223 7 */ 8 9/** 10 * Class helper_plugin_odt_units 11 */ 12class ODTUnits { 13 // All static variables with fixed values 14 // Measure units as defined in "Extensible Stylesheet Language (XSL) Version 1.1" 15 protected static $xsl_units = array('cm', 'mm', 'in', 'pt', 'pc', 'px', 'em'); 16 protected static $point_in_cm = 0.035277778; 17 protected static $inch_in_cm = 2.54; 18 protected static $inch_in_pt = 0.089605556; 19 protected static $pc_in_cm = 0.423333336; 20 protected static $pc_in_pt = 12; 21 protected static $twips_per_point = 20; 22 23 // Non static variables, can be changed 24 protected $px_per_em = 14; 25 protected $twips_per_pixel_x = 16; 26 protected $twips_per_pixel_y = 20; 27 28 /** 29 * Strips of the leading digits from $value. So left over will be the unit only. 30 * 31 * @param int $value The length value string, e.g. '1cm'. 32 * @return string The unit of $value, e.g. 'cm' 33 */ 34 static public function stripDigits ($value) { 35 return ltrim ($value, '-.0123456789'); 36 } 37 38 /** 39 * Gets only the digits from $value without the unit. 40 * 41 * @param string|int $value The length value string, e.g. '1cm'. 42 * @return string The digits of $value, e.g. '1' 43 */ 44 static public function getDigits ($value) { 45 $digits = NULL; 46 $length = strlen ((string)$value); 47 for ($index = 0 ; $index < $length ; $index++ ) { 48 if ( is_numeric ($value [$index]) === false && 49 $value [$index] != '.' && 50 $value [$index] != '-' ) { 51 break; 52 } 53 $digits .= $value [$index]; 54 } 55 return $digits; 56 } 57 58 /** 59 * Checks if $unit is a valid XSL unit. 60 * 61 * @param string $unit The unit string, e.g. 'cm'. 62 * @return boolean true if valid, false otherwise 63 */ 64 static public function isValidXSLUnit($unit) { 65 return in_array($unit, self::$xsl_units); 66 } 67 68 /** 69 * Checks if length value string $value has a valid XSL unit. 70 * 71 * @param string|int $value The length value string, e.g. '1cm'. 72 * @return boolean true if valid, false otherwise 73 */ 74 static public function hasValidXSLUnit($value) { 75 return in_array(self::stripDigits((string)$value), self::$xsl_units); 76 } 77 78 /** 79 * Sets the pixel per em unit used for px to em conversion. 80 * 81 * @param int $value The value to be set. 82 */ 83 public function setPixelPerEm ($value) { 84 $this->px_per_em = $value; 85 } 86 87 /** 88 * Query the pixel per em unit. 89 * 90 * @return int The current value. 91 */ 92 public function getPixelPerEm () { 93 return $this->px_per_em; 94 } 95 96 /** 97 * Sets the twips per pixel (X axis) used for px to pt conversion. 98 * 99 * @param int $value The value to be set. 100 */ 101 public function setTwipsPerPixelX ($value) { 102 $this->twips_per_pixel_x = $value; 103 } 104 105 /** 106 * Sets the twips per pixel (Y axis) unit used for px to pt conversion. 107 * 108 * @param int $value The value to be set. 109 */ 110 public function setTwipsPerPixelY ($value) { 111 $this->twips_per_pixel_y = $value; 112 } 113 114 /** 115 * Query the twips per pixel (X axis) setting. 116 * 117 * @return int The current value. 118 */ 119 public function getTwipsPerPixelX () { 120 return $this->twips_per_pixel_x; 121 } 122 123 /** 124 * Query the twips per pixel (Y axis) setting. 125 * 126 * @return int The current value. 127 */ 128 public function getTwipsPerPixelY () { 129 return $this->twips_per_pixel_y; 130 } 131 132 /** 133 * Convert pixel (X axis) to points according to the current settings. 134 * 135 * @param string|int $pixel String with pixel length value, e.g. '20px' 136 * @return string The current value. 137 */ 138 public function pixelToPointsX ($pixel) { 139 $pixel = self::getDigits ((string)$pixel); 140 $value = $pixel * $this->twips_per_pixel_x / self::$twips_per_point; 141 return round ($value, 2).'pt'; 142 } 143 144 /** 145 * Convert pixel (Y axis) to points according to the current settings. 146 * 147 * @param string|int $pixel String with pixel length value, e.g. '20px' 148 * @return string The current value. 149 */ 150 public function pixelToPointsY ($pixel) { 151 $pixel = self::getDigits ((string)$pixel); 152 $value = $pixel * $this->twips_per_pixel_y / self::$twips_per_point; 153 return round ($value, 2).'pt'; 154 } 155 156 /** 157 * Convert length value with valid XSL unit to points. 158 * 159 * @param string $value String with length value, e.g. '20px', '20cm'... 160 * @param string $axis Is the value to be converted a value on the X or Y axis? Default is 'y'. 161 * Only relevant for conversion from 'px' or 'em'. 162 * @return string The current value. 163 */ 164 public function toPoints ($value, $axis = 'y') { 165 $unit = self::stripDigits ($value); 166 if ( $unit == 'pt' ) { 167 return $value; 168 } 169 170 if ( self::isValidXSLUnit ($unit) === false ) { 171 // Not a vlaid/supported unit. Return original value. 172 return $value; 173 } 174 175 $value = self::getDigits ($value); 176 switch ($unit) { 177 case 'cm': 178 $value = round (($value/self::$point_in_cm), 2).'pt'; 179 break; 180 case 'mm': 181 $value = round (($value/(10 * self::$point_in_cm)), 2).'pt'; 182 break; 183 case 'in': 184 $value = round (($value * self::$inch_in_pt), 2).'pt'; 185 break; 186 case 'pc': 187 $value = round (($value * self::$pc_in_pt), 2).'pt'; 188 break; 189 case 'px': 190 if ( $axis == 'x' || $axis == 'X' ) { 191 $value = $this->pixelToPointsX ($value); 192 } else { 193 $value = $this->pixelToPointsY ($value); 194 } 195 break; 196 case 'em': 197 $value = $this->pixelToPointsY ($value * $this->getPixelPerEm()); 198 break; 199 } 200 return $value; 201 } 202 203 /** 204 * Convert length value with valid XSL unit to points. 205 * 206 * @param string $value String with length value, e.g. '20px', '20pt'... 207 * @param string $axis Is the value to be converted a value on the X or Y axis? Default is 'y'. 208 * Only relevant for conversion from 'px' or 'em'. 209 * @return string The current value. 210 */ 211 public function toCentimeters ($value, $axis = 'y') { 212 $unit = self::stripDigits ($value); 213 if ( $unit == 'cm' ) { 214 return $value; 215 } 216 217 if ( self::isValidXSLUnit ($unit) === false ) { 218 // Not a vlaid/supported unit. Return original value. 219 return $value; 220 } 221 222 $value = self::toPoints ($value, $axis); 223 $value = substr($value, 0, -2); 224 $value = round (($value * self::$point_in_cm), 2).'cm'; 225 return $value; 226 } 227 228 /** 229 * Convert length value with valid XSL unit to pixel. 230 * 231 * @param string $value String with length value, e.g. '20pt'... 232 * @param string $axis Is the value to be converted a value on the X or Y axis? Default is 'y'. 233 * Only relevant for conversion from 'px' or 'em'. 234 * @return string The current value. 235 */ 236 public function toPixel ($value, $axis = 'y') { 237 $unit = self::stripDigits ($value); 238 if ( $unit == 'px' ) { 239 return $value; 240 } 241 242 if ( self::isValidXSLUnit ($unit) === false ) { 243 // Not a vlaid/supported unit. Return original value. 244 return $value; 245 } 246 247 $value = self::toPoints ($value, $axis); 248 $value = substr($value, 0, -2); 249 if ($axis == 'x') { 250 $value = round ((($value*self::$twips_per_point)/$this->twips_per_pixel_x), 2).'px'; 251 } else { 252 $value = round ((($value*self::$twips_per_point)/$this->twips_per_pixel_y), 2).'px'; 253 } 254 return $value; 255 } 256 257 public function getAbsoluteValue ($value, $base) { 258 $unit = self::stripDigits ($value); 259 260 $value = self::getDigits ($value); 261 switch ($unit) { 262 case '%': 263 $value = ($value * $base)/100; 264 break; 265 case 'em': 266 $value = $value * $base; 267 break; 268 default: 269 // Not an relative value. Just keep it. 270 break; 271 } 272 return $value; 273 } 274} 275