ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
HTMLPurifier_UnitConverter Class Reference

Class for converting between different unit-lengths as specified by CSS. More...

+ Collaboration diagram for HTMLPurifier_UnitConverter:

Public Member Functions

 __construct ($output_precision=4, $internal_precision=10, $force_no_bcmath=false)
 
 convert ($length, $to_unit)
 Converts a length object of one unit into another unit. More...
 
 getSigFigs ($n)
 Returns the number of significant figures in a string number. More...
 

Data Fields

const ENGLISH = 1
 
const METRIC = 2
 
const DIGITAL = 3
 

Protected Attributes

 $outputPrecision
 Minimum bcmath precision for output. More...
 
 $internalPrecision
 Bcmath precision for internal calculations. More...
 

Static Protected Attributes

static $units
 Units information array. More...
 

Private Member Functions

 add ($s1, $s2, $scale)
 Adds two numbers, using arbitrary precision when available. More...
 
 mul ($s1, $s2, $scale)
 Multiples two numbers, using arbitrary precision when available. More...
 
 div ($s1, $s2, $scale)
 Divides two numbers, using arbitrary precision when available. More...
 
 round ($n, $sigfigs)
 Rounds a number according to the number of sigfigs it should have, using arbitrary precision when available. More...
 
 scale ($r, $scale)
 Scales a float to $scale digits right of decimal point, like BCMath. More...
 

Private Attributes

 $bcmath
 Whether or not BCMath is available. More...
 

Detailed Description

Class for converting between different unit-lengths as specified by CSS.

Definition at line 7 of file UnitConverter.php.

Constructor & Destructor Documentation

◆ __construct()

HTMLPurifier_UnitConverter::__construct (   $output_precision = 4,
  $internal_precision = 10,
  $force_no_bcmath = false 
)

Definition at line 56 of file UnitConverter.php.

57  {
58  $this->outputPrecision = $output_precision;
59  $this->internalPrecision = $internal_precision;
60  $this->bcmath = !$force_no_bcmath && function_exists('bcmul');
61  }

Member Function Documentation

◆ add()

HTMLPurifier_UnitConverter::add (   $s1,
  $s2,
  $scale 
)
private

Adds two numbers, using arbitrary precision when available.

Parameters
string$s1
string$s2
int$scale
Returns
string

Definition at line 214 of file UnitConverter.php.

References scale().

215  {
216  if ($this->bcmath) {
217  return bcadd($s1, $s2, $scale);
218  } else {
219  return $this->scale((float)$s1 + (float)$s2, $scale);
220  }
221  }
scale($r, $scale)
Scales a float to $scale digits right of decimal point, like BCMath.
+ Here is the call graph for this function:

◆ convert()

HTMLPurifier_UnitConverter::convert (   $length,
  $to_unit 
)

Converts a length object of one unit into another unit.

Parameters
HTMLPurifier_Length$lengthInstance of HTMLPurifier_Length to convert. You must validate() it before passing it here!
string$to_unitUnit to convert to.
Returns
HTMLPurifier_Length|bool
Note
About precision: This conversion function pays very special attention to the incoming precision of values and attempts to maintain a number of significant figure. Results are fairly accurate up to nine digits. Some caveats:
  • If a number is zero-padded as a result of this significant figure tracking, the zeroes will be eliminated.
  • If a number contains less than four sigfigs ($outputPrecision) and this causes some decimals to be excluded, those decimals will be added on.

Definition at line 82 of file UnitConverter.php.

References $i, $log, $n, $outputPrecision, $state, $x, div(), getSigFigs(), mul(), and round().

83  {
84  if (!$length->isValid()) {
85  return false;
86  }
87 
88  $n = $length->getN();
89  $unit = $length->getUnit();
90 
91  if ($n === '0' || $unit === false) {
92  return new HTMLPurifier_Length('0', false);
93  }
94 
95  $state = $dest_state = false;
96  foreach (self::$units as $k => $x) {
97  if (isset($x[$unit])) {
98  $state = $k;
99  }
100  if (isset($x[$to_unit])) {
101  $dest_state = $k;
102  }
103  }
104  if (!$state || !$dest_state) {
105  return false;
106  }
107 
108  // Some calculations about the initial precision of the number;
109  // this will be useful when we need to do final rounding.
110  $sigfigs = $this->getSigFigs($n);
111  if ($sigfigs < $this->outputPrecision) {
112  $sigfigs = $this->outputPrecision;
113  }
114 
115  // BCMath's internal precision deals only with decimals. Use
116  // our default if the initial number has no decimals, or increase
117  // it by how ever many decimals, thus, the number of guard digits
118  // will always be greater than or equal to internalPrecision.
119  $log = (int)floor(log(abs($n), 10));
120  $cp = ($log < 0) ? $this->internalPrecision - $log : $this->internalPrecision; // internal precision
121 
122  for ($i = 0; $i < 2; $i++) {
123 
124  // Determine what unit IN THIS SYSTEM we need to convert to
125  if ($dest_state === $state) {
126  // Simple conversion
127  $dest_unit = $to_unit;
128  } else {
129  // Convert to the smallest unit, pending a system shift
130  $dest_unit = self::$units[$state][$dest_state][0];
131  }
132 
133  // Do the conversion if necessary
134  if ($dest_unit !== $unit) {
135  $factor = $this->div(self::$units[$state][$unit], self::$units[$state][$dest_unit], $cp);
136  $n = $this->mul($n, $factor, $cp);
137  $unit = $dest_unit;
138  }
139 
140  // Output was zero, so bail out early. Shouldn't ever happen.
141  if ($n === '') {
142  $n = '0';
143  $unit = $to_unit;
144  break;
145  }
146 
147  // It was a simple conversion, so bail out
148  if ($dest_state === $state) {
149  break;
150  }
151 
152  if ($i !== 0) {
153  // Conversion failed! Apparently, the system we forwarded
154  // to didn't have this unit. This should never happen!
155  return false;
156  }
157 
158  // Pre-condition: $i == 0
159 
160  // Perform conversion to next system of units
161  $n = $this->mul($n, self::$units[$state][$dest_state][1], $cp);
162  $unit = self::$units[$state][$dest_state][2];
163  $state = $dest_state;
164 
165  // One more loop around to convert the unit in the new system.
166 
167  }
168 
169  // Post-condition: $unit == $to_unit
170  if ($unit !== $to_unit) {
171  return false;
172  }
173 
174  // Useful for debugging:
175  //echo "<pre>n";
176  //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n</pre>\n";
177 
178  $n = $this->round($n, $sigfigs);
179  if (strpos($n, '.') !== false) {
180  $n = rtrim($n, '0');
181  }
182  $n = rtrim($n, '.');
183 
184  return new HTMLPurifier_Length($n, $unit);
185  }
mul($s1, $s2, $scale)
Multiples two numbers, using arbitrary precision when available.
$x
Definition: example_009.php:98
getSigFigs($n)
Returns the number of significant figures in a string number.
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
div($s1, $s2, $scale)
Divides two numbers, using arbitrary precision when available.
$n
Definition: RandomTest.php:85
Represents a measurable length, with a string numeric magnitude and a unit.
Definition: Length.php:7
$i
Definition: disco.tpl.php:19
round($n, $sigfigs)
Rounds a number according to the number of sigfigs it should have, using arbitrary precision when ava...
$outputPrecision
Minimum bcmath precision for output.
+ Here is the call graph for this function:

◆ div()

HTMLPurifier_UnitConverter::div (   $s1,
  $s2,
  $scale 
)
private

Divides two numbers, using arbitrary precision when available.

Parameters
string$s1
string$s2
int$scale
Returns
string

Definition at line 246 of file UnitConverter.php.

References scale().

Referenced by convert().

247  {
248  if ($this->bcmath) {
249  return bcdiv($s1, $s2, $scale);
250  } else {
251  return $this->scale((float)$s1 / (float)$s2, $scale);
252  }
253  }
scale($r, $scale)
Scales a float to $scale digits right of decimal point, like BCMath.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getSigFigs()

HTMLPurifier_UnitConverter::getSigFigs (   $n)

Returns the number of significant figures in a string number.

Parameters
string$nDecimal number
Returns
int number of sigfigs

Definition at line 192 of file UnitConverter.php.

References $n.

Referenced by convert().

193  {
194  $n = ltrim($n, '0+-');
195  $dp = strpos($n, '.'); // decimal position
196  if ($dp === false) {
197  $sigfigs = strlen(rtrim($n, '0'));
198  } else {
199  $sigfigs = strlen(ltrim($n, '0.')); // eliminate extra decimal character
200  if ($dp !== 0) {
201  $sigfigs--;
202  }
203  }
204  return $sigfigs;
205  }
$n
Definition: RandomTest.php:85
+ Here is the caller graph for this function:

◆ mul()

HTMLPurifier_UnitConverter::mul (   $s1,
  $s2,
  $scale 
)
private

Multiples two numbers, using arbitrary precision when available.

Parameters
string$s1
string$s2
int$scale
Returns
string

Definition at line 230 of file UnitConverter.php.

References scale().

Referenced by convert().

231  {
232  if ($this->bcmath) {
233  return bcmul($s1, $s2, $scale);
234  } else {
235  return $this->scale((float)$s1 * (float)$s2, $scale);
236  }
237  }
scale($r, $scale)
Scales a float to $scale digits right of decimal point, like BCMath.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ round()

HTMLPurifier_UnitConverter::round (   $n,
  $sigfigs 
)
private

Rounds a number according to the number of sigfigs it should have, using arbitrary precision when available.

Parameters
float$n
int$sigfigs
Returns
string

Definition at line 262 of file UnitConverter.php.

References $n, and scale().

Referenced by convert(), and scale().

263  {
264  $new_log = (int)floor(log(abs($n), 10)); // Number of digits left of decimal - 1
265  $rp = $sigfigs - $new_log - 1; // Number of decimal places needed
266  $neg = $n < 0 ? '-' : ''; // Negative sign
267  if ($this->bcmath) {
268  if ($rp >= 0) {
269  $n = bcadd($n, $neg . '0.' . str_repeat('0', $rp) . '5', $rp + 1);
270  $n = bcdiv($n, '1', $rp);
271  } else {
272  // This algorithm partially depends on the standardized
273  // form of numbers that comes out of bcmath.
274  $n = bcadd($n, $neg . '5' . str_repeat('0', $new_log - $sigfigs), 0);
275  $n = substr($n, 0, $sigfigs + strlen($neg)) . str_repeat('0', $new_log - $sigfigs + 1);
276  }
277  return $n;
278  } else {
279  return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1);
280  }
281  }
scale($r, $scale)
Scales a float to $scale digits right of decimal point, like BCMath.
$n
Definition: RandomTest.php:85
round($n, $sigfigs)
Rounds a number according to the number of sigfigs it should have, using arbitrary precision when ava...
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ scale()

HTMLPurifier_UnitConverter::scale (   $r,
  $scale 
)
private

Scales a float to $scale digits right of decimal point, like BCMath.

Parameters
float$r
int$scale
Returns
string

Definition at line 289 of file UnitConverter.php.

References $r, round(), and string.

Referenced by add(), div(), mul(), and round().

290  {
291  if ($scale < 0) {
292  // The f sprintf type doesn't support negative numbers, so we
293  // need to cludge things manually. First get the string.
294  $r = sprintf('%.0f', (float)$r);
295  // Due to floating point precision loss, $r will more than likely
296  // look something like 4652999999999.9234. We grab one more digit
297  // than we need to precise from $r and then use that to round
298  // appropriately.
299  $precise = (string)round(substr($r, 0, strlen($r) + $scale), -1);
300  // Now we return it, truncating the zero that was rounded off.
301  return substr($precise, 0, -1) . str_repeat('0', -$scale + 1);
302  }
303  return sprintf('%.' . $scale . 'f', (float)$r);
304  }
Add rich text string
$r
Definition: example_031.php:79
round($n, $sigfigs)
Rounds a number according to the number of sigfigs it should have, using arbitrary precision when ava...
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $bcmath

HTMLPurifier_UnitConverter::$bcmath
private

Whether or not BCMath is available.

bool

Definition at line 54 of file UnitConverter.php.

◆ $internalPrecision

HTMLPurifier_UnitConverter::$internalPrecision
protected

Bcmath precision for internal calculations.

int

Definition at line 48 of file UnitConverter.php.

◆ $outputPrecision

HTMLPurifier_UnitConverter::$outputPrecision
protected

Minimum bcmath precision for output.

int

Definition at line 42 of file UnitConverter.php.

Referenced by convert().

◆ $units

HTMLPurifier_UnitConverter::$units
staticprotected
Initial value:
self::ENGLISH => array(
'px' => 3,
'pt' => 4,
'pc' => 48,
'in' => 288,
self::METRIC => array('pt', '0.352777778', 'mm'),
),
self::METRIC => array(
'mm' => 1,
'cm' => 10,
self::ENGLISH => array('mm', '2.83464567', 'pt'),
),
)

Units information array.

Units are grouped into measuring systems (English, Metric), and are assigned an integer representing the conversion factor between that unit and the smallest unit in the system. Numeric indexes are actually magical constants that encode conversion data from one system to the next, with a O(n^2) constraint on memory (this is generally not a problem, since the number of measuring systems is small.)

Definition at line 23 of file UnitConverter.php.

◆ DIGITAL

const HTMLPurifier_UnitConverter::DIGITAL = 3

Definition at line 12 of file UnitConverter.php.

◆ ENGLISH

const HTMLPurifier_UnitConverter::ENGLISH = 1

Definition at line 10 of file UnitConverter.php.

◆ METRIC

const HTMLPurifier_UnitConverter::METRIC = 2

Definition at line 11 of file UnitConverter.php.


The documentation for this class was generated from the following file: