| 1 |
<?php |
| 2 |
|
| 3 |
namespace PhpOffice\PhpSpreadsheet\Helper; |
| 4 |
|
| 5 |
use PhpOffice\PhpSpreadsheet\Exception; |
| 6 |
use PhpOffice\PhpSpreadsheet\Shared\Drawing; |
| 7 |
use PhpOffice\PhpSpreadsheet\Style\Font; |
| 8 |
|
| 9 |
class Dimension |
| 10 |
{ |
| 11 |
public const UOM_CENTIMETERS = 'cm'; |
| 12 |
public const UOM_MILLIMETERS = 'mm'; |
| 13 |
public const UOM_INCHES = 'in'; |
| 14 |
public const UOM_PIXELS = 'px'; |
| 15 |
public const UOM_POINTS = 'pt'; |
| 16 |
public const UOM_PICA = 'pc'; |
| 17 |
|
| 18 |
/** |
| 19 |
* Based on 96 dpi. |
| 20 |
*/ |
| 21 |
const ABSOLUTE_UNITS = [ |
| 22 |
self::UOM_CENTIMETERS => 96.0 / 2.54, |
| 23 |
self::UOM_MILLIMETERS => 96.0 / 25.4, |
| 24 |
self::UOM_INCHES => 96.0, |
| 25 |
self::UOM_PIXELS => 1.0, |
| 26 |
self::UOM_POINTS => 96.0 / 72, |
| 27 |
self::UOM_PICA => 96.0 * 12 / 72, |
| 28 |
]; |
| 29 |
|
| 30 |
/** |
| 31 |
* Based on a standard column width of 8.54 units in MS Excel. |
| 32 |
*/ |
| 33 |
const RELATIVE_UNITS = [ |
| 34 |
'em' => 10.0 / 8.54, |
| 35 |
'ex' => 10.0 / 8.54, |
| 36 |
'ch' => 10.0 / 8.54, |
| 37 |
'rem' => 10.0 / 8.54, |
| 38 |
'vw' => 8.54, |
| 39 |
'vh' => 8.54, |
| 40 |
'vmin' => 8.54, |
| 41 |
'vmax' => 8.54, |
| 42 |
'%' => 8.54 / 100, |
| 43 |
]; |
| 44 |
|
| 45 |
/** |
| 46 |
* @var float|int If this is a width, then size is measured in pixels (if is set) |
| 47 |
* or in Excel's default column width units if $unit is null. |
| 48 |
* If this is a height, then size is measured in pixels () |
| 49 |
* or in points () if $unit is null. |
| 50 |
*/ |
| 51 |
protected $size; |
| 52 |
|
| 53 |
/** |
| 54 |
* @var null|string |
| 55 |
*/ |
| 56 |
protected $unit; |
| 57 |
|
| 58 |
/** |
| 59 |
* Phpstan bug has been fixed; this function allows us to |
| 60 |
* pass Phpstan whether fixed or not. |
| 61 |
* |
| 62 |
* @param mixed $value |
| 63 |
*/ |
| 64 |
private static function stanBugFixed($value): array |
| 65 |
{ |
| 66 |
return is_array($value) ? $value : [null, null]; |
| 67 |
} |
| 68 |
|
| 69 |
public function __construct(string $dimension) |
| 70 |
{ |
| 71 |
[$size, $unit] = self::stanBugFixed(sscanf($dimension, '%[1234567890.]%s')); |
| 72 |
$unit = strtolower(trim($unit ?? '')); |
| 73 |
$size = (float) $size; |
| 74 |
|
| 75 |
// If a UoM is specified, then convert the size to pixels for internal storage |
| 76 |
if (isset(self::ABSOLUTE_UNITS[$unit])) { |
| 77 |
$size *= self::ABSOLUTE_UNITS[$unit]; |
| 78 |
$this->unit = self::UOM_PIXELS; |
| 79 |
} elseif (isset(self::RELATIVE_UNITS[$unit])) { |
| 80 |
$size *= self::RELATIVE_UNITS[$unit]; |
| 81 |
$size = round($size, 4); |
| 82 |
} |
| 83 |
|
| 84 |
$this->size = $size; |
| 85 |
} |
| 86 |
|
| 87 |
public function width(): float |
| 88 |
{ |
| 89 |
return (float) ($this->unit === null) |
| 90 |
? $this->size |
| 91 |
: round(Drawing::pixelsToCellDimension((int) $this->size, new Font(false)), 4); |
| 92 |
} |
| 93 |
|
| 94 |
public function height(): float |
| 95 |
{ |
| 96 |
return (float) ($this->unit === null) |
| 97 |
? $this->size |
| 98 |
: $this->toUnit(self::UOM_POINTS); |
| 99 |
} |
| 100 |
|
| 101 |
public function toUnit(string $unitOfMeasure): float |
| 102 |
{ |
| 103 |
$unitOfMeasure = strtolower($unitOfMeasure); |
| 104 |
if (!array_key_exists($unitOfMeasure, self::ABSOLUTE_UNITS)) { |
| 105 |
throw new Exception("{$unitOfMeasure} is not a vaid unit of measure"); |
| 106 |
} |
| 107 |
|
| 108 |
$size = $this->size; |
| 109 |
if ($this->unit === null) { |
| 110 |
$size = Drawing::cellDimensionToPixels($size, new Font(false)); |
| 111 |
} |
| 112 |
|
| 113 |
return $size / self::ABSOLUTE_UNITS[$unitOfMeasure]; |
| 114 |
} |
| 115 |
} |
| 116 |
|