IdenticonStyle.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <?php
  2. /**
  3. * This file is part of Jdenticon for PHP.
  4. * https://github.com/dmester/jdenticon-php/
  5. *
  6. * Copyright (c) 2025 Daniel Mester Pirttijärvi
  7. * Copyright (c) 2024 Peter Putzer
  8. *
  9. * For full license information, please see the LICENSE file that was
  10. * distributed with this source code.
  11. */
  12. namespace Jdenticon;
  13. use Jdenticon\Color;
  14. /**
  15. * Specifies the color style of an identicon.
  16. */
  17. class IdenticonStyle
  18. {
  19. private Color $backgroundColor;
  20. private float $padding;
  21. private float $colorSaturation;
  22. private float $grayscaleSaturation;
  23. private array $colorLightness;
  24. private array $grayscaleLightness;
  25. private ?array $hues = null;
  26. public function __construct(?array $options = null)
  27. {
  28. $this->backgroundColor = self::getDefaultBackgroundColor();
  29. $this->padding = self::getDefaultPadding();
  30. $this->colorSaturation = self::getDefaultColorSaturation();
  31. $this->grayscaleSaturation = self::getDefaultGrayscaleSaturation();
  32. $this->colorLightness = self::getDefaultColorLightness();
  33. $this->grayscaleLightness = self::getDefaultGrayscaleLightness();
  34. if ($options !== null) {
  35. $this->setOptions($options);
  36. }
  37. }
  38. /**
  39. * Gets an associative array of all options of this style.
  40. *
  41. * @return array
  42. */
  43. public function getOptions(): array
  44. {
  45. $options = [];
  46. $options['backgroundColor'] = $this->getBackgroundColor()->__toString();
  47. $options['padding'] = $this->getPadding();
  48. $options['colorSaturation'] = $this->getColorSaturation();
  49. $options['grayscaleSaturation'] = $this->getGrayscaleSaturation();
  50. $options['colorLightness'] = $this->getColorLightness();
  51. $options['grayscaleLightness'] = $this->getGrayscaleLightness();
  52. if ($this->hues !== null) {
  53. $options['hues'] = $this->getHues();
  54. }
  55. return $options;
  56. }
  57. /**
  58. * Sets options in this style by specifying an associative array of option
  59. * values.
  60. *
  61. * @param array $options Options to set.
  62. * @return self
  63. */
  64. public function setOptions(array $options): self
  65. {
  66. foreach ($options as $key => $value) {
  67. $this->__set($key, $value);
  68. }
  69. return $this;
  70. }
  71. public function __get(string $name)
  72. {
  73. switch (strtolower($name)) {
  74. case 'backgroundcolor':
  75. return $this->getBackgroundColor();
  76. case 'padding':
  77. return $this->getPadding();
  78. case 'colorsaturation':
  79. return $this->getColorSaturation();
  80. case 'grayscalesaturation':
  81. return $this->getGrayscaleSaturation();
  82. case 'colorlightness':
  83. return $this->getColorLightness();
  84. case 'grayscalelightness':
  85. return $this->getGrayscaleLightness();
  86. case 'hues':
  87. return $this->getHues();
  88. default:
  89. throw new \InvalidArgumentException(
  90. "Unknown IdenticonStyle option '$name'.");
  91. }
  92. }
  93. public function __set(string $name, $value): void
  94. {
  95. switch (strtolower($name)) {
  96. case 'backgroundcolor':
  97. $this->setBackgroundColor($value);
  98. break;
  99. case 'padding':
  100. $this->setPadding($value);
  101. break;
  102. case 'colorsaturation':
  103. $this->setColorSaturation($value);
  104. break;
  105. case 'grayscalesaturation':
  106. $this->setGrayscaleSaturation($value);
  107. break;
  108. case 'colorlightness':
  109. $this->setColorLightness($value);
  110. break;
  111. case 'grayscalelightness':
  112. $this->setGrayscaleLightness($value);
  113. break;
  114. case 'hues':
  115. $this->setHues($value);
  116. break;
  117. default:
  118. throw new \InvalidArgumentException(
  119. "Unknown IdenticonStyle option '$name'.");
  120. }
  121. }
  122. /**
  123. * Normalizes a hue to the first turn [0, 360).
  124. *
  125. * @param int|float $hue
  126. * @return integer
  127. */
  128. private static function normalizeHue($hue): int
  129. {
  130. if (!is_numeric($hue)) {
  131. throw new \InvalidArgumentException(
  132. "'$hue' is not a valid hue.");
  133. }
  134. $hue = (int)$hue % 360;
  135. if ($hue < 0) {
  136. $hue += 360;
  137. }
  138. return $hue;
  139. }
  140. /**
  141. * Gets an array of allowed hues, or null if there are no restrictions.
  142. *
  143. * @return array<int>|null
  144. */
  145. public function getHues(): ?array
  146. {
  147. return $this->hues;
  148. }
  149. /**
  150. * Sets the allowed hues of generated icons.
  151. *
  152. * @param array<integer>|integer|null $value A hue specified in degrees,
  153. * or an array of hues specified in degrees. If set to null, the hue
  154. * list is cleared.
  155. * @return self
  156. */
  157. public function setHues($value): self
  158. {
  159. $hues = [];
  160. if ($value !== null) {
  161. if (is_array($value)) {
  162. foreach ($value as $hue) {
  163. $hues[] = self::normalizeHue($hue);
  164. }
  165. } else {
  166. $hues[] = self::normalizeHue($value);
  167. }
  168. }
  169. $this->hues = empty($hues) ? null : $hues;
  170. return $this;
  171. }
  172. /**
  173. * Gets the padding of an icon in percents in the range [0.0, 0.4].
  174. *
  175. * @return float
  176. */
  177. public function getPadding(): float
  178. {
  179. return $this->padding;
  180. }
  181. /**
  182. * Sets the padding of an icon in percents.
  183. *
  184. * @param float $value New padding in the range [0.0, 0.4].
  185. * @return self
  186. */
  187. public function setPadding(float $value): self
  188. {
  189. if ($value < 0 || $value > 0.4) {
  190. throw new \InvalidArgumentException(
  191. "Padding '$value' out of range. ".
  192. "Values in the range [0.0, 0.4] are allowed.");
  193. }
  194. $this->padding = (float)$value;
  195. return $this;
  196. }
  197. /**
  198. * Gets the color of the identicon background.
  199. *
  200. * @return \Jdenticon\Color
  201. */
  202. public function getBackgroundColor(): Color
  203. {
  204. return $this->backgroundColor;
  205. }
  206. /**
  207. * Sets the color of the identicon background.
  208. *
  209. * @param \Jdenticon\Color|string $value New background color.
  210. * @return \Jdenticon\IdenticonStyle
  211. */
  212. public function setBackgroundColor($value): self
  213. {
  214. if ($value instanceof Color) {
  215. $this->backgroundColor = $value;
  216. } else {
  217. $this->backgroundColor = Color::parse($value);
  218. }
  219. return $this;
  220. }
  221. /**
  222. * Gets the saturation of the originally grayscale identicon shapes.
  223. *
  224. * @return float Saturation in the range [0.0, 1.0].
  225. */
  226. public function getGrayscaleSaturation(): float
  227. {
  228. return $this->grayscaleSaturation;
  229. }
  230. /**
  231. * Sets the saturation of the originally grayscale identicon shapes.
  232. *
  233. * @param $value float Saturation in the range [0.0, 1.0].
  234. * @return self
  235. */
  236. public function setGrayscaleSaturation(float $value): self
  237. {
  238. if ($value < 0 || $value > 1) {
  239. throw new \InvalidArgumentException(
  240. "The grayscale saturation was invalid. ".
  241. "Only values in the range [0.0, 1.0] are allowed.");
  242. }
  243. $this->grayscaleSaturation = (float)$value;
  244. return $this;
  245. }
  246. /**
  247. * Gets the saturation of the colored identicon shapes.
  248. *
  249. * @return float Saturation in the range [0.0, 1.0].
  250. */
  251. public function getColorSaturation(): float
  252. {
  253. return $this->colorSaturation;
  254. }
  255. /**
  256. * Sets the saturation of the colored identicon shapes.
  257. *
  258. * @param $value float Saturation in the range [0.0, 1.0].
  259. * @return self
  260. */
  261. public function setColorSaturation(float $value): self
  262. {
  263. if ($value < 0 || $value > 1) {
  264. throw new \InvalidArgumentException(
  265. "The color saturation was invalid. ".
  266. "Only values in the range [0.0, 1.0] are allowed.");
  267. }
  268. $this->colorSaturation = (float)$value;
  269. return $this;
  270. }
  271. /**
  272. * Gets the value of the ColorLightness property.
  273. *
  274. * @return array<float>
  275. */
  276. public function getColorLightness(): array
  277. {
  278. return $this->colorLightness;
  279. }
  280. /**
  281. * Sets the value of the ColorLightness property.
  282. *
  283. * @param array<float> $value Lightness range.
  284. * @return self
  285. */
  286. public function setColorLightness(array $value): self
  287. {
  288. if (!array_key_exists(0, $value) ||
  289. !array_key_exists(1, $value) ||
  290. !is_numeric($value[0]) ||
  291. !is_numeric($value[1]) ||
  292. $value[0] < 0 || $value[0] > 1 ||
  293. $value[1] < 0 || $value[1] > 1
  294. ) {
  295. throw new \InvalidArgumentException(
  296. "The value passed to setColorLightness was invalid. ".
  297. "Please check the documentation.");
  298. }
  299. $this->colorLightness = [(float)$value[0], (float)$value[1]];
  300. return $this;
  301. }
  302. /**
  303. * Gets the value of the GrayscaleLightness property.
  304. *
  305. * @return array<float>
  306. */
  307. public function getGrayscaleLightness(): array
  308. {
  309. return $this->grayscaleLightness;
  310. }
  311. /**
  312. * Sets the value of the GrayscaleLightness property.
  313. *
  314. * @param array<float> $value Lightness range.
  315. * @return self
  316. */
  317. public function setGrayscaleLightness(array $value): self
  318. {
  319. if (!array_key_exists(0, $value) ||
  320. !array_key_exists(1, $value) ||
  321. !is_numeric($value[0]) ||
  322. !is_numeric($value[1]) ||
  323. $value[0] < 0 || $value[0] > 1 ||
  324. $value[1] < 0 || $value[1] > 1
  325. ) {
  326. throw new \InvalidArgumentException(
  327. "The value passed to setGrayscaleLightness was invalid. ".
  328. "Please check the documentation.");
  329. }
  330. $this->grayscaleLightness = [(float)$value[0], (float)$value[1]];
  331. return $this;
  332. }
  333. /**
  334. * Gets the default value of the BackgroundColor property. Resolves to transparent.
  335. *
  336. * @return \Jdenticon\Color
  337. */
  338. public static function getDefaultBackgroundColor(): Color
  339. {
  340. return Color::fromRgb(255, 255, 255, 255);
  341. }
  342. /**
  343. * Gets the default value of the Padding property. Resolves to 0.08.
  344. *
  345. * @return float
  346. */
  347. public static function getDefaultPadding(): float
  348. {
  349. return 0.08;
  350. }
  351. /**
  352. * Gets the default value of the ColorSaturation property. Resolves to 0.5.
  353. *
  354. * @return float
  355. */
  356. public static function getDefaultColorSaturation(): float
  357. {
  358. return 0.5;
  359. }
  360. /**
  361. * Gets the default value of the GrayscaleSaturation property. Resolves to 0.
  362. *
  363. * @return float
  364. */
  365. public static function getDefaultGrayscaleSaturation(): float
  366. {
  367. return 0;
  368. }
  369. /**
  370. * Gets the default value of the ColorLightness property. Resolves to [0.4, 0.8].
  371. *
  372. * @return array<float>
  373. */
  374. public static function getDefaultColorLightness(): array
  375. {
  376. return [0.4, 0.8];
  377. }
  378. /**
  379. * Gets the default value of the GrayscaleLightness property. Resolves to [0.3, 0.9].
  380. *
  381. * @return array<float>
  382. */
  383. public static function getDefaultGrayscaleLightness(): array
  384. {
  385. return [0.3, 0.9];
  386. }
  387. }