Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

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