See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
1 <?php 2 3 namespace Sabberworm\CSS\Value; 4 5 use Sabberworm\CSS\OutputFormat; 6 use Sabberworm\CSS\Parsing\ParserState; 7 use Sabberworm\CSS\Parsing\UnexpectedEOFException; 8 use Sabberworm\CSS\Parsing\UnexpectedTokenException; 9 10 class Size extends PrimitiveValue 11 { 12 /** 13 * vh/vw/vm(ax)/vmin/rem are absolute insofar as they don’t scale to the immediate parent (only the viewport) 14 * 15 * @var array<int, string> 16 */ 17 const ABSOLUTE_SIZE_UNITS = ['px', 'cm', 'mm', 'mozmm', 'in', 'pt', 'pc', 'vh', 'vw', 'vmin', 'vmax', 'rem']; 18 19 /** 20 * @var array<int, string> 21 */ 22 const RELATIVE_SIZE_UNITS = ['%', 'em', 'ex', 'ch', 'fr']; 23 24 /** 25 * @var array<int, string> 26 */ 27 const NON_SIZE_UNITS = ['deg', 'grad', 'rad', 's', 'ms', 'turns', 'Hz', 'kHz']; 28 29 /** 30 * @var array<int, array<string, string>>|null 31 */ 32 private static $SIZE_UNITS = null; 33 34 /** 35 * @var float 36 */ 37 private $fSize; 38 39 /** 40 * @var string|null 41 */ 42 private $sUnit; 43 44 /** 45 * @var bool 46 */ 47 private $bIsColorComponent; 48 49 /** 50 * @param float|int|string $fSize 51 * @param string|null $sUnit 52 * @param bool $bIsColorComponent 53 * @param int $iLineNo 54 */ 55 public function __construct($fSize, $sUnit = null, $bIsColorComponent = false, $iLineNo = 0) 56 { 57 parent::__construct($iLineNo); 58 $this->fSize = (float)$fSize; 59 $this->sUnit = $sUnit; 60 $this->bIsColorComponent = $bIsColorComponent; 61 } 62 63 /** 64 * @param bool $bIsColorComponent 65 * 66 * @return Size 67 * 68 * @throws UnexpectedEOFException 69 * @throws UnexpectedTokenException 70 */ 71 public static function parse(ParserState $oParserState, $bIsColorComponent = false) 72 { 73 $sSize = ''; 74 if ($oParserState->comes('-')) { 75 $sSize .= $oParserState->consume('-'); 76 } 77 while (is_numeric($oParserState->peek()) || $oParserState->comes('.')) { 78 if ($oParserState->comes('.')) { 79 $sSize .= $oParserState->consume('.'); 80 } else { 81 $sSize .= $oParserState->consume(1); 82 } 83 } 84 85 $sUnit = null; 86 $aSizeUnits = self::getSizeUnits(); 87 foreach ($aSizeUnits as $iLength => &$aValues) { 88 $sKey = strtolower($oParserState->peek($iLength)); 89 if (array_key_exists($sKey, $aValues)) { 90 if (($sUnit = $aValues[$sKey]) !== null) { 91 $oParserState->consume($iLength); 92 break; 93 } 94 } 95 } 96 return new Size((float)$sSize, $sUnit, $bIsColorComponent, $oParserState->currentLine()); 97 } 98 99 /** 100 * @return array<int, array<string, string>> 101 */ 102 private static function getSizeUnits() 103 { 104 if (!is_array(self::$SIZE_UNITS)) { 105 self::$SIZE_UNITS = []; 106 foreach (array_merge(self::ABSOLUTE_SIZE_UNITS, self::RELATIVE_SIZE_UNITS, self::NON_SIZE_UNITS) as $val) { 107 $iSize = strlen($val); 108 if (!isset(self::$SIZE_UNITS[$iSize])) { 109 self::$SIZE_UNITS[$iSize] = []; 110 } 111 self::$SIZE_UNITS[$iSize][strtolower($val)] = $val; 112 } 113 114 krsort(self::$SIZE_UNITS, SORT_NUMERIC); 115 } 116 117 return self::$SIZE_UNITS; 118 } 119 120 /** 121 * @param string $sUnit 122 * 123 * @return void 124 */ 125 public function setUnit($sUnit) 126 { 127 $this->sUnit = $sUnit; 128 } 129 130 /** 131 * @return string|null 132 */ 133 public function getUnit() 134 { 135 return $this->sUnit; 136 } 137 138 /** 139 * @param float|int|string $fSize 140 */ 141 public function setSize($fSize) 142 { 143 $this->fSize = (float)$fSize; 144 } 145 146 /** 147 * @return float 148 */ 149 public function getSize() 150 { 151 return $this->fSize; 152 } 153 154 /** 155 * @return bool 156 */ 157 public function isColorComponent() 158 { 159 return $this->bIsColorComponent; 160 } 161 162 /** 163 * Returns whether the number stored in this Size really represents a size (as in a length of something on screen). 164 * 165 * @return false if the unit an angle, a duration, a frequency or the number is a component in a Color object. 166 */ 167 public function isSize() 168 { 169 if (in_array($this->sUnit, self::NON_SIZE_UNITS, true)) { 170 return false; 171 } 172 return !$this->isColorComponent(); 173 } 174 175 /** 176 * @return bool 177 */ 178 public function isRelative() 179 { 180 if (in_array($this->sUnit, self::RELATIVE_SIZE_UNITS, true)) { 181 return true; 182 } 183 if ($this->sUnit === null && $this->fSize != 0) { 184 return true; 185 } 186 return false; 187 } 188 189 /** 190 * @return string 191 */ 192 public function __toString() 193 { 194 return $this->render(new OutputFormat()); 195 } 196 197 /** 198 * @return string 199 */ 200 public function render(OutputFormat $oOutputFormat) 201 { 202 $l = localeconv(); 203 $sPoint = preg_quote($l['decimal_point'], '/'); 204 $sSize = preg_match("/[\d\.]+e[+-]?\d+/i", (string)$this->fSize) 205 ? preg_replace("/$sPoint?0+$/", "", sprintf("%f", $this->fSize)) : $this->fSize; 206 return preg_replace(["/$sPoint/", "/^(-?)0\./"], ['.', '$1.'], $sSize) 207 . ($this->sUnit === null ? '' : $this->sUnit); 208 } 209 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body