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] [Versions 401 and 402] [Versions 401 and 403]
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 * @var null|string 111 */ 112 protected $argb; 113 114 /** @var bool */ 115 private $hasChanged = false; 116 117 /** 118 * Create a new Color. 119 * 120 * @param string $colorValue ARGB value for the colour, or named colour 121 * @param bool $isSupervisor Flag indicating if this is a supervisor or not 122 * Leave this value at default unless you understand exactly what 123 * its ramifications are 124 * @param bool $isConditional Flag indicating if this is a conditional style or not 125 * Leave this value at default unless you understand exactly what 126 * its ramifications are 127 */ 128 public function __construct($colorValue = self::COLOR_BLACK, $isSupervisor = false, $isConditional = false) 129 { 130 // Supervisor? 131 parent::__construct($isSupervisor); 132 133 // Initialise values 134 if (!$isConditional) { 135 $this->argb = $this->validateColor($colorValue) ?: self::COLOR_BLACK; 136 } 137 } 138 139 /** 140 * Get the shared style component for the currently active cell in currently active sheet. 141 * Only used for style supervisor. 142 * 143 * @return Color 144 */ 145 public function getSharedComponent() 146 { 147 /** @var Style */ 148 $parent = $this->parent; 149 /** @var Border|Fill $sharedComponent */ 150 $sharedComponent = $parent->getSharedComponent(); 151 if ($sharedComponent instanceof Fill) { 152 if ($this->parentPropertyName === 'endColor') { 153 return $sharedComponent->getEndColor(); 154 } 155 156 return $sharedComponent->getStartColor(); 157 } 158 159 return $sharedComponent->getColor(); 160 } 161 162 /** 163 * Build style array from subcomponents. 164 * 165 * @param array $array 166 * 167 * @return array 168 */ 169 public function getStyleArray($array) 170 { 171 /** @var Style */ 172 $parent = $this->parent; 173 174 return $parent->getStyleArray([$this->parentPropertyName => $array]); 175 } 176 177 /** 178 * Apply styles from array. 179 * 180 * <code> 181 * $spreadsheet->getActiveSheet()->getStyle('B2')->getFont()->getColor()->applyFromArray(['rgb' => '808080']); 182 * </code> 183 * 184 * @param array $styleArray Array containing style information 185 * 186 * @return $this 187 */ 188 public function applyFromArray(array $styleArray) 189 { 190 if ($this->isSupervisor) { 191 $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($styleArray)); 192 } else { 193 if (isset($styleArray['rgb'])) { 194 $this->setRGB($styleArray['rgb']); 195 } 196 if (isset($styleArray['argb'])) { 197 $this->setARGB($styleArray['argb']); 198 } 199 } 200 201 return $this; 202 } 203 204 private function validateColor(?string $colorValue): string 205 { 206 if ($colorValue === null || $colorValue === '') { 207 return self::COLOR_BLACK; 208 } 209 $named = ucfirst(strtolower($colorValue)); 210 if (array_key_exists($named, self::NAMED_COLOR_TRANSLATIONS)) { 211 return self::NAMED_COLOR_TRANSLATIONS[$named]; 212 } 213 if (preg_match(self::VALIDATE_COLOR_8, $colorValue) === 1) { 214 return $colorValue; 215 } 216 if (preg_match(self::VALIDATE_COLOR_6, $colorValue) === 1) { 217 return 'FF' . $colorValue; 218 } 219 220 return ''; 221 } 222 223 /** 224 * Get ARGB. 225 */ 226 public function getARGB(): ?string 227 { 228 if ($this->isSupervisor) { 229 return $this->getSharedComponent()->getARGB(); 230 } 231 232 return $this->argb; 233 } 234 235 /** 236 * Set ARGB. 237 * 238 * @param string $colorValue ARGB value, or a named color 239 * 240 * @return $this 241 */ 242 public function setARGB(?string $colorValue = self::COLOR_BLACK) 243 { 244 $this->hasChanged = true; 245 $colorValue = $this->validateColor($colorValue); 246 if ($colorValue === '') { 247 return $this; 248 } 249 250 if ($this->isSupervisor) { 251 $styleArray = $this->getStyleArray(['argb' => $colorValue]); 252 $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); 253 } else { 254 $this->argb = $colorValue; 255 } 256 257 return $this; 258 } 259 260 /** 261 * Get RGB. 262 */ 263 public function getRGB(): string 264 { 265 if ($this->isSupervisor) { 266 return $this->getSharedComponent()->getRGB(); 267 } 268 269 return substr($this->argb ?? '', 2); 270 } 271 272 /** 273 * Set RGB. 274 * 275 * @param string $colorValue RGB value, or a named color 276 * 277 * @return $this 278 */ 279 public function setRGB(?string $colorValue = self::COLOR_BLACK) 280 { 281 return $this->setARGB($colorValue); 282 } 283 284 /** 285 * Get a specified colour component of an RGB value. 286 * 287 * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE 288 * @param int $offset Position within the RGB value to extract 289 * @param bool $hex Flag indicating whether the component should be returned as a hex or a 290 * decimal value 291 * 292 * @return int|string The extracted colour component 293 */ 294 private static function getColourComponent($rgbValue, $offset, $hex = true) 295 { 296 $colour = substr($rgbValue, $offset, 2) ?: ''; 297 if (preg_match('/^[0-9a-f]{2}$/i', $colour) !== 1) { 298 $colour = '00'; 299 } 300 301 return ($hex) ? $colour : (int) hexdec($colour); 302 } 303 304 /** 305 * Get the red colour component of an RGB value. 306 * 307 * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE 308 * @param bool $hex Flag indicating whether the component should be returned as a hex or a 309 * decimal value 310 * 311 * @return int|string The red colour component 312 */ 313 public static function getRed($rgbValue, $hex = true) 314 { 315 return self::getColourComponent($rgbValue, strlen($rgbValue) - 6, $hex); 316 } 317 318 /** 319 * Get the green colour component of an RGB value. 320 * 321 * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE 322 * @param bool $hex Flag indicating whether the component should be returned as a hex or a 323 * decimal value 324 * 325 * @return int|string The green colour component 326 */ 327 public static function getGreen($rgbValue, $hex = true) 328 { 329 return self::getColourComponent($rgbValue, strlen($rgbValue) - 4, $hex); 330 } 331 332 /** 333 * Get the blue colour component of an RGB value. 334 * 335 * @param string $rgbValue The colour as an RGB value (e.g. FF00CCCC or CCDDEE 336 * @param bool $hex Flag indicating whether the component should be returned as a hex or a 337 * decimal value 338 * 339 * @return int|string The blue colour component 340 */ 341 public static function getBlue($rgbValue, $hex = true) 342 { 343 return self::getColourComponent($rgbValue, strlen($rgbValue) - 2, $hex); 344 } 345 346 /** 347 * Adjust the brightness of a color. 348 * 349 * @param string $hexColourValue The colour as an RGBA or RGB value (e.g. FF00CCCC or CCDDEE) 350 * @param float $adjustPercentage The percentage by which to adjust the colour as a float from -1 to 1 351 * 352 * @return string The adjusted colour as an RGBA or RGB value (e.g. FF00CCCC or CCDDEE) 353 */ 354 public static function changeBrightness($hexColourValue, $adjustPercentage) 355 { 356 $rgba = (strlen($hexColourValue) === 8); 357 $adjustPercentage = max(-1.0, min(1.0, $adjustPercentage)); 358 359 /** @var int $red */ 360 $red = self::getRed($hexColourValue, false); 361 /** @var int $green */ 362 $green = self::getGreen($hexColourValue, false); 363 /** @var int $blue */ 364 $blue = self::getBlue($hexColourValue, false); 365 if ($adjustPercentage > 0) { 366 $red += (255 - $red) * $adjustPercentage; 367 $green += (255 - $green) * $adjustPercentage; 368 $blue += (255 - $blue) * $adjustPercentage; 369 } else { 370 $red += $red * $adjustPercentage; 371 $green += $green * $adjustPercentage; 372 $blue += $blue * $adjustPercentage; 373 } 374 375 $rgb = strtoupper( 376 str_pad(dechex((int) $red), 2, '0', 0) . 377 str_pad(dechex((int) $green), 2, '0', 0) . 378 str_pad(dechex((int) $blue), 2, '0', 0) 379 ); 380 381 return (($rgba) ? 'FF' : '') . $rgb; 382 } 383 384 /** 385 * Get indexed color. 386 * 387 * @param int $colorIndex Index entry point into the colour array 388 * @param bool $background Flag to indicate whether default background or foreground colour 389 * should be returned if the indexed colour doesn't exist 390 */ 391 public static function indexedColor($colorIndex, $background = false, ?array $palette = null): self 392 { 393 // Clean parameter 394 $colorIndex = (int) $colorIndex; 395 396 if (empty($palette)) { 397 if (isset(self::INDEXED_COLORS[$colorIndex])) { 398 return new self(self::INDEXED_COLORS[$colorIndex]); 399 } 400 } else { 401 if (isset($palette[$colorIndex])) { 402 return new self($palette[$colorIndex]); 403 } 404 } 405 406 return ($background) ? new self(self::COLOR_WHITE) : new self(self::COLOR_BLACK); 407 } 408 409 /** 410 * Get hash code. 411 * 412 * @return string Hash code 413 */ 414 public function getHashCode(): string 415 { 416 if ($this->isSupervisor) { 417 return $this->getSharedComponent()->getHashCode(); 418 } 419 420 return md5( 421 $this->argb . 422 __CLASS__ 423 ); 424 } 425 426 protected function exportArray1(): array 427 { 428 $exportedArray = []; 429 $this->exportArray2($exportedArray, 'argb', $this->getARGB()); 430 431 return $exportedArray; 432 } 433 434 public function getHasChanged(): bool 435 { 436 if ($this->isSupervisor) { 437 return $this->getSharedComponent()->hasChanged; 438 } 439 440 return $this->hasChanged; 441 } 442 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body