Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Style;
4
 
5
class Color extends Supervisor
6
{
7
    const NAMED_COLORS = [
8
        'Black',
9
        'White',
10
        'Red',
11
        'Green',
12
        'Blue',
13
        'Yellow',
14
        'Magenta',
15
        'Cyan',
16
    ];
17
 
18
    // Colors
19
    const COLOR_BLACK = 'FF000000';
20
    const COLOR_WHITE = 'FFFFFFFF';
21
    const COLOR_RED = 'FFFF0000';
22
    const COLOR_DARKRED = 'FF800000';
23
    const COLOR_BLUE = 'FF0000FF';
24
    const COLOR_DARKBLUE = 'FF000080';
25
    const COLOR_GREEN = 'FF00FF00';
26
    const COLOR_DARKGREEN = 'FF008000';
27
    const COLOR_YELLOW = 'FFFFFF00';
28
    const COLOR_DARKYELLOW = 'FF808000';
29
    const COLOR_MAGENTA = 'FFFF00FF';
30
    const COLOR_CYAN = 'FF00FFFF';
31
 
32
    const NAMED_COLOR_TRANSLATIONS = [
33
        'Black' => self::COLOR_BLACK,
34
        'White' => self::COLOR_WHITE,
35
        'Red' => self::COLOR_RED,
36
        'Green' => self::COLOR_GREEN,
37
        'Blue' => self::COLOR_BLUE,
38
        'Yellow' => self::COLOR_YELLOW,
39
        'Magenta' => self::COLOR_MAGENTA,
40
        'Cyan' => self::COLOR_CYAN,
41
    ];
42
 
43
    const VALIDATE_ARGB_SIZE = 8;
44
    const VALIDATE_RGB_SIZE = 6;
45
    const VALIDATE_COLOR_6 = '/^[A-F0-9]{6}$/i';
46
    const VALIDATE_COLOR_8 = '/^[A-F0-9]{8}$/i';
47
 
48
    private const INDEXED_COLORS = [
49
        1 => 'FF000000', //  System Colour #1 - Black
50
        2 => 'FFFFFFFF', //  System Colour #2 - White
51
        3 => 'FFFF0000', //  System Colour #3 - Red
52
        4 => 'FF00FF00', //  System Colour #4 - Green
53
        5 => 'FF0000FF', //  System Colour #5 - Blue
54
        6 => 'FFFFFF00', //  System Colour #6 - Yellow
55
        7 => 'FFFF00FF', //  System Colour #7- Magenta
56
        8 => 'FF00FFFF', //  System Colour #8- Cyan
57
        9 => 'FF800000', //  Standard Colour #9
58
        10 => 'FF008000', //  Standard Colour #10
59
        11 => 'FF000080', //  Standard Colour #11
60
        12 => 'FF808000', //  Standard Colour #12
61
        13 => 'FF800080', //  Standard Colour #13
62
        14 => 'FF008080', //  Standard Colour #14
63
        15 => 'FFC0C0C0', //  Standard Colour #15
64
        16 => 'FF808080', //  Standard Colour #16
65
        17 => 'FF9999FF', //  Chart Fill Colour #17
66
        18 => 'FF993366', //  Chart Fill Colour #18
67
        19 => 'FFFFFFCC', //  Chart Fill Colour #19
68
        20 => 'FFCCFFFF', //  Chart Fill Colour #20
69
        21 => 'FF660066', //  Chart Fill Colour #21
70
        22 => 'FFFF8080', //  Chart Fill Colour #22
71
        23 => 'FF0066CC', //  Chart Fill Colour #23
72
        24 => 'FFCCCCFF', //  Chart Fill Colour #24
73
        25 => 'FF000080', //  Chart Line Colour #25
74
        26 => 'FFFF00FF', //  Chart Line Colour #26
75
        27 => 'FFFFFF00', //  Chart Line Colour #27
76
        28 => 'FF00FFFF', //  Chart Line Colour #28
77
        29 => 'FF800080', //  Chart Line Colour #29
78
        30 => 'FF800000', //  Chart Line Colour #30
79
        31 => 'FF008080', //  Chart Line Colour #31
80
        32 => 'FF0000FF', //  Chart Line Colour #32
81
        33 => 'FF00CCFF', //  Standard Colour #33
82
        34 => 'FFCCFFFF', //  Standard Colour #34
83
        35 => 'FFCCFFCC', //  Standard Colour #35
84
        36 => 'FFFFFF99', //  Standard Colour #36
85
        37 => 'FF99CCFF', //  Standard Colour #37
86
        38 => 'FFFF99CC', //  Standard Colour #38
87
        39 => 'FFCC99FF', //  Standard Colour #39
88
        40 => 'FFFFCC99', //  Standard Colour #40
89
        41 => 'FF3366FF', //  Standard Colour #41
90
        42 => 'FF33CCCC', //  Standard Colour #42
91
        43 => 'FF99CC00', //  Standard Colour #43
92
        44 => 'FFFFCC00', //  Standard Colour #44
93
        45 => 'FFFF9900', //  Standard Colour #45
94
        46 => 'FFFF6600', //  Standard Colour #46
95
        47 => 'FF666699', //  Standard Colour #47
96
        48 => 'FF969696', //  Standard Colour #48
97
        49 => 'FF003366', //  Standard Colour #49
98
        50 => 'FF339966', //  Standard Colour #50
99
        51 => 'FF003300', //  Standard Colour #51
100
        52 => 'FF333300', //  Standard Colour #52
101
        53 => 'FF993300', //  Standard Colour #53
102
        54 => 'FF993366', //  Standard Colour #54
103
        55 => 'FF333399', //  Standard Colour #55
104
        56 => 'FF333333', //  Standard Colour #56
105
    ];
106
 
107
    /**
108
     * ARGB - Alpha RGB.
109
     */
110
    protected ?string $argb = null;
111
 
112
    private bool $hasChanged = false;
113
 
114
    /**
115
     * Create a new Color.
116
     *
117
     * @param string $colorValue ARGB value for the colour, or named colour
118
     * @param bool $isSupervisor Flag indicating if this is a supervisor or not
119
     *                                    Leave this value at default unless you understand exactly what
120
     *                                        its ramifications are
121
     * @param bool $isConditional Flag indicating if this is a conditional style or not
122
     *                                    Leave this value at default unless you understand exactly what
123
     *                                        its ramifications are
124
     */
125
    public function __construct(string $colorValue = self::COLOR_BLACK, bool $isSupervisor = false, bool $isConditional = false)
126
    {
127
        //    Supervisor?
128
        parent::__construct($isSupervisor);
129
 
130
        //    Initialise values
131
        if (!$isConditional) {
132
            $this->argb = $this->validateColor($colorValue) ?: self::COLOR_BLACK;
133
        }
134
    }
135
 
136
    /**
137
     * Get the shared style component for the currently active cell in currently active sheet.
138
     * Only used for style supervisor.
139
     */
140
    public function getSharedComponent(): self
141
    {
142
        /** @var Style $parent */
143
        $parent = $this->parent;
144
        /** @var Border|Fill $sharedComponent */
145
        $sharedComponent = $parent->getSharedComponent();
146
        if ($sharedComponent instanceof Fill) {
147
            if ($this->parentPropertyName === 'endColor') {
148
                return $sharedComponent->getEndColor();
149
            }
150
 
151
            return $sharedComponent->getStartColor();
152
        }
153
 
154
        return $sharedComponent->getColor();
155
    }
156
 
157
    /**
158
     * Build style array from subcomponents.
159
     */
160
    public function getStyleArray(array $array): array
161
    {
162
        /** @var Style $parent */
163
        $parent = $this->parent;
164
 
165
        return $parent->getStyleArray([$this->parentPropertyName => $array]);
166
    }
167
 
168
    /**
169
     * Apply styles from array.
170
     *
171
     * <code>
172
     * $spreadsheet->getActiveSheet()->getStyle('B2')->getFont()->getColor()->applyFromArray(['rgb' => '808080']);
173
     * </code>
174
     *
175
     * @param array $styleArray Array containing style information
176
     *
177
     * @return $this
178
     */
179
    public function applyFromArray(array $styleArray): static
180
    {
181
        if ($this->isSupervisor) {
182
            $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($styleArray));
183
        } else {
184
            if (isset($styleArray['rgb'])) {
185
                $this->setRGB($styleArray['rgb']);
186
            }
187
            if (isset($styleArray['argb'])) {
188
                $this->setARGB($styleArray['argb']);
189
            }
190
        }
191
 
192
        return $this;
193
    }
194
 
195
    private function validateColor(?string $colorValue): string
196
    {
197
        if ($colorValue === null || $colorValue === '') {
198
            return self::COLOR_BLACK;
199
        }
200
        $named = ucfirst(strtolower($colorValue));
201
        if (array_key_exists($named, self::NAMED_COLOR_TRANSLATIONS)) {
202
            return self::NAMED_COLOR_TRANSLATIONS[$named];
203
        }
204
        if (preg_match(self::VALIDATE_COLOR_8, $colorValue) === 1) {
205
            return $colorValue;
206
        }
207
        if (preg_match(self::VALIDATE_COLOR_6, $colorValue) === 1) {
208
            return 'FF' . $colorValue;
209
        }
210
 
211
        return '';
212
    }
213
 
214
    /**
215
     * Get ARGB.
216
     */
217
    public function getARGB(): ?string
218
    {
219
        if ($this->isSupervisor) {
220
            return $this->getSharedComponent()->getARGB();
221
        }
222
 
223
        return $this->argb;
224
    }
225
 
226
    /**
227
     * Set ARGB.
228
     *
229
     * @param ?string $colorValue  ARGB value, or a named color
230
     *
231
     * @return $this
232
     */
233
    public function setARGB(?string $colorValue = self::COLOR_BLACK, bool $nullStringOkay = false): static
234
    {
235
        $this->hasChanged = true;
236
        if (!$nullStringOkay || $colorValue !== '') {
237
            $colorValue = $this->validateColor($colorValue);
238
            if ($colorValue === '') {
239
                return $this;
240
            }
241
        }
242
 
243
        if ($this->isSupervisor) {
244
            $styleArray = $this->getStyleArray(['argb' => $colorValue]);
245
            $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
246
        } else {
247
            $this->argb = $colorValue;
248
        }
249
 
250
        return $this;
251
    }
252
 
253
    /**
254
     * Get RGB.
255
     */
256
    public function getRGB(): string
257
    {
258
        if ($this->isSupervisor) {
259
            return $this->getSharedComponent()->getRGB();
260
        }
261
 
262
        return substr($this->argb ?? '', 2);
263
    }
264
 
265
    /**
266
     * Set RGB.
267
     *
268
     * @param ?string $colorValue RGB value, or a named color
269
     *
270
     * @return $this
271
     */
272
    public function setRGB(?string $colorValue = self::COLOR_BLACK): static
273
    {
274
        return $this->setARGB($colorValue);
275
    }
276
 
277
    /**
278
     * Get a specified colour component of an RGB value.
279
     *
280
     * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE
281
     * @param int $offset Position within the RGB value to extract
282
     * @param bool $hex Flag indicating whether the component should be returned as a hex or a
283
     *                                    decimal value
284
     *
285
     * @return int|string The extracted colour component
286
     */
287
    private static function getColourComponent(string $rgbValue, int $offset, bool $hex = true): string|int
288
    {
289
        $colour = substr($rgbValue, $offset, 2) ?: '';
290
        if (preg_match('/^[0-9a-f]{2}$/i', $colour) !== 1) {
291
            $colour = '00';
292
        }
293
 
294
        return ($hex) ? $colour : (int) hexdec($colour);
295
    }
296
 
297
    /**
298
     * Get the red colour component of an RGB value.
299
     *
300
     * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE
301
     * @param bool $hex Flag indicating whether the component should be returned as a hex or a
302
     *                                    decimal value
303
     *
304
     * @return int|string The red colour component
305
     */
306
    public static function getRed(string $rgbValue, bool $hex = true)
307
    {
308
        return self::getColourComponent($rgbValue, strlen($rgbValue) - 6, $hex);
309
    }
310
 
311
    /**
312
     * Get the green colour component of an RGB value.
313
     *
314
     * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE
315
     * @param bool $hex Flag indicating whether the component should be returned as a hex or a
316
     *                                    decimal value
317
     *
318
     * @return int|string The green colour component
319
     */
320
    public static function getGreen(string $rgbValue, bool $hex = true)
321
    {
322
        return self::getColourComponent($rgbValue, strlen($rgbValue) - 4, $hex);
323
    }
324
 
325
    /**
326
     * Get the blue colour component of an RGB value.
327
     *
328
     * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE
329
     * @param bool $hex Flag indicating whether the component should be returned as a hex or a
330
     *                                    decimal value
331
     *
332
     * @return int|string The blue colour component
333
     */
334
    public static function getBlue(string $rgbValue, bool $hex = true)
335
    {
336
        return self::getColourComponent($rgbValue, strlen($rgbValue) - 2, $hex);
337
    }
338
 
339
    /**
340
     * Adjust the brightness of a color.
341
     *
342
     * @param string $hexColourValue The colour as an RGBA or RGB value (e.g. FF00CCCC or CCDDEE)
343
     * @param float $adjustPercentage The percentage by which to adjust the colour as a float from -1 to 1
344
     *
345
     * @return string The adjusted colour as an RGBA or RGB value (e.g. FF00CCCC or CCDDEE)
346
     */
347
    public static function changeBrightness(string $hexColourValue, float $adjustPercentage): string
348
    {
349
        $rgba = (strlen($hexColourValue) === 8);
350
        $adjustPercentage = max(-1.0, min(1.0, $adjustPercentage));
351
 
352
        /** @var int $red */
353
        $red = self::getRed($hexColourValue, false);
354
        /** @var int $green */
355
        $green = self::getGreen($hexColourValue, false);
356
        /** @var int $blue */
357
        $blue = self::getBlue($hexColourValue, false);
358
 
359
        return (($rgba) ? 'FF' : '') . RgbTint::rgbAndTintToRgb($red, $green, $blue, $adjustPercentage);
360
    }
361
 
362
    /**
363
     * Get indexed color.
364
     *
365
     * @param int $colorIndex Index entry point into the colour array
366
     * @param bool $background Flag to indicate whether default background or foreground colour
367
     *                                            should be returned if the indexed colour doesn't exist
368
     */
369
    public static function indexedColor(int $colorIndex, bool $background = false, ?array $palette = null): self
370
    {
371
        // Clean parameter
372
        $colorIndex = (int) $colorIndex;
373
 
374
        if (empty($palette)) {
375
            if (isset(self::INDEXED_COLORS[$colorIndex])) {
376
                return new self(self::INDEXED_COLORS[$colorIndex]);
377
            }
378
        } else {
379
            if (isset($palette[$colorIndex])) {
380
                return new self($palette[$colorIndex]);
381
            }
382
        }
383
 
384
        return ($background) ? new self(self::COLOR_WHITE) : new self(self::COLOR_BLACK);
385
    }
386
 
387
    /**
388
     * Get hash code.
389
     *
390
     * @return string Hash code
391
     */
392
    public function getHashCode(): string
393
    {
394
        if ($this->isSupervisor) {
395
            return $this->getSharedComponent()->getHashCode();
396
        }
397
 
398
        return md5(
399
            $this->argb
400
            . __CLASS__
401
        );
402
    }
403
 
404
    protected function exportArray1(): array
405
    {
406
        $exportedArray = [];
407
        $this->exportArray2($exportedArray, 'argb', $this->getARGB());
408
 
409
        return $exportedArray;
410
    }
411
 
412
    public function getHasChanged(): bool
413
    {
414
        if ($this->isSupervisor) {
415
            return $this->getSharedComponent()->hasChanged;
416
        }
417
 
418
        return $this->hasChanged;
419
    }
420
}