Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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
/**
11
 * `Color's can be input in the form #rrggbb, #rgb or schema(val1, val2, …) but are always stored as an array of
12
 * ('s' => val1, 'c' => val2, 'h' => val3, …) and output in the second form.
13
 */
14
class Color extends CSSFunction
15
{
16
    /**
17
     * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aColor
18
     * @param int $iLineNo
19
     */
20
    public function __construct(array $aColor, $iLineNo = 0)
21
    {
22
        parent::__construct(implode('', array_keys($aColor)), $aColor, ',', $iLineNo);
23
    }
24
 
25
    /**
26
     * @param ParserState $oParserState
27
     * @param bool $bIgnoreCase
28
     *
29
     * @return Color|CSSFunction
30
     *
31
     * @throws UnexpectedEOFException
32
     * @throws UnexpectedTokenException
33
     */
34
    public static function parse(ParserState $oParserState, $bIgnoreCase = false)
35
    {
36
        $aColor = [];
37
        if ($oParserState->comes('#')) {
38
            $oParserState->consume('#');
39
            $sValue = $oParserState->parseIdentifier(false);
40
            if ($oParserState->strlen($sValue) === 3) {
41
                $sValue = $sValue[0] . $sValue[0] . $sValue[1] . $sValue[1] . $sValue[2] . $sValue[2];
42
            } elseif ($oParserState->strlen($sValue) === 4) {
43
                $sValue = $sValue[0] . $sValue[0] . $sValue[1] . $sValue[1] . $sValue[2] . $sValue[2] . $sValue[3]
44
                    . $sValue[3];
45
            }
46
 
47
            if ($oParserState->strlen($sValue) === 8) {
48
                $aColor = [
49
                    'r' => new Size(intval($sValue[0] . $sValue[1], 16), null, true, $oParserState->currentLine()),
50
                    'g' => new Size(intval($sValue[2] . $sValue[3], 16), null, true, $oParserState->currentLine()),
51
                    'b' => new Size(intval($sValue[4] . $sValue[5], 16), null, true, $oParserState->currentLine()),
52
                    'a' => new Size(
53
                        round(self::mapRange(intval($sValue[6] . $sValue[7], 16), 0, 255, 0, 1), 2),
54
                        null,
55
                        true,
56
                        $oParserState->currentLine()
57
                    ),
58
                ];
59
            } elseif ($oParserState->strlen($sValue) === 6) {
60
                $aColor = [
61
                    'r' => new Size(intval($sValue[0] . $sValue[1], 16), null, true, $oParserState->currentLine()),
62
                    'g' => new Size(intval($sValue[2] . $sValue[3], 16), null, true, $oParserState->currentLine()),
63
                    'b' => new Size(intval($sValue[4] . $sValue[5], 16), null, true, $oParserState->currentLine()),
64
                ];
65
            } else {
66
                throw new UnexpectedTokenException(
67
                    'Invalid hex color value',
68
                    $sValue,
69
                    'custom',
70
                    $oParserState->currentLine()
71
                );
72
            }
73
        } else {
74
            $sColorMode = $oParserState->parseIdentifier(true);
75
            $oParserState->consumeWhiteSpace();
76
            $oParserState->consume('(');
77
 
78
            $bContainsVar = false;
79
            $iLength = $oParserState->strlen($sColorMode);
80
            for ($i = 0; $i < $iLength; ++$i) {
81
                $oParserState->consumeWhiteSpace();
82
                if ($oParserState->comes('var')) {
83
                    $aColor[$sColorMode[$i]] = CSSFunction::parseIdentifierOrFunction($oParserState);
84
                    $bContainsVar = true;
85
                } else {
86
                    $aColor[$sColorMode[$i]] = Size::parse($oParserState, true);
87
                }
88
 
89
                if ($bContainsVar && $oParserState->comes(')')) {
90
                    // With a var argument the function can have fewer arguments
91
                    break;
92
                }
93
 
94
                $oParserState->consumeWhiteSpace();
95
                if ($i < ($iLength - 1)) {
96
                    $oParserState->consume(',');
97
                }
98
            }
99
            $oParserState->consume(')');
100
 
101
            if ($bContainsVar) {
102
                return new CSSFunction($sColorMode, array_values($aColor), ',', $oParserState->currentLine());
103
            }
104
        }
105
        return new Color($aColor, $oParserState->currentLine());
106
    }
107
 
108
    /**
109
     * @param float $fVal
110
     * @param float $fFromMin
111
     * @param float $fFromMax
112
     * @param float $fToMin
113
     * @param float $fToMax
114
     *
115
     * @return float
116
     */
117
    private static function mapRange($fVal, $fFromMin, $fFromMax, $fToMin, $fToMax)
118
    {
119
        $fFromRange = $fFromMax - $fFromMin;
120
        $fToRange = $fToMax - $fToMin;
121
        $fMultiplier = $fToRange / $fFromRange;
122
        $fNewVal = $fVal - $fFromMin;
123
        $fNewVal *= $fMultiplier;
124
        return $fNewVal + $fToMin;
125
    }
126
 
127
    /**
128
     * @return array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string>
129
     */
130
    public function getColor()
131
    {
132
        return $this->aComponents;
133
    }
134
 
135
    /**
136
     * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aColor
137
     *
138
     * @return void
139
     */
140
    public function setColor(array $aColor)
141
    {
142
        $this->setName(implode('', array_keys($aColor)));
143
        $this->aComponents = $aColor;
144
    }
145
 
146
    /**
147
     * @return string
148
     */
149
    public function getColorDescription()
150
    {
151
        return $this->getName();
152
    }
153
 
154
    /**
155
     * @return string
156
     */
157
    public function __toString()
158
    {
159
        return $this->render(new OutputFormat());
160
    }
161
 
162
    /**
163
     * @param OutputFormat|null $oOutputFormat
164
     *
165
     * @return string
166
     */
167
    public function render($oOutputFormat)
168
    {
169
        // Shorthand RGB color values
170
        if ($oOutputFormat->getRGBHashNotation() && implode('', array_keys($this->aComponents)) === 'rgb') {
171
            $sResult = sprintf(
172
                '%02x%02x%02x',
173
                $this->aComponents['r']->getSize(),
174
                $this->aComponents['g']->getSize(),
175
                $this->aComponents['b']->getSize()
176
            );
177
            return '#' . (($sResult[0] == $sResult[1]) && ($sResult[2] == $sResult[3]) && ($sResult[4] == $sResult[5])
178
                    ? "$sResult[0]$sResult[2]$sResult[4]" : $sResult);
179
        }
180
        return parent::render($oOutputFormat);
181
    }
182
}