Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}