1<?php
2
3namespace Mpdf\Color;
4
5use Mpdf\Mpdf;
6
7class ColorSpaceRestrictor
8{
9
10	const RESTRICT_TO_GRAYSCALE = 1;
11
12	const RESTRICT_TO_RGB_SPOT_GRAYSCALE = 2;
13
14	const RESTRICT_TO_CMYK_SPOT_GRAYSCALE = 3;
15
16	/**
17	 * @var \Mpdf\Mpdf
18	 */
19	private $mpdf;
20
21	/**
22	 * @var \Mpdf\Color\ColorModeConverter
23	 */
24	private $colorModeConverter;
25
26	/**
27	 * @var int
28	 */
29	private $mode;
30
31	/**
32	 * Process $mode settings
33	 *     1 - allow GRAYSCALE only [convert CMYK/RGB->gray]
34	 *     2 - allow RGB / SPOT COLOR / Grayscale [convert CMYK->RGB]
35	 *     3 - allow CMYK / SPOT COLOR / Grayscale [convert RGB->CMYK]
36	 *
37	 * @param \Mpdf\Mpdf $mpdf
38	 * @param \Mpdf\Color\ColorModeConverter $colorModeConverter
39	 * @param int $mode
40	 */
41	public function __construct(Mpdf $mpdf, ColorModeConverter $colorModeConverter, $mode)
42	{
43		$this->mpdf = $mpdf;
44		$this->colorModeConverter = $colorModeConverter;
45		$this->mode = $mode;
46	}
47
48	/**
49	 * @param mixed $c
50	 * @param string $color
51	 * @param string[] $PDFAXwarnings
52	 *
53	 * @return float[]|mixed
54	 */
55	public function restrictColorSpace($c, $color, &$PDFAXwarnings = [])
56	{
57		if (!is_array($c)) {
58			return $c;
59		}
60
61		$mode = (int) $c[0];
62		switch ($mode) {
63			case 1:
64				return $c;
65			case 2:
66				return $this->restrictSpotColorSpace($c, $PDFAXwarnings);
67			case 3:
68				return $this->restrictRgbColorSpace($c, $color, $PDFAXwarnings);
69			case 4:
70				return $this->restrictCmykColorSpace($c, $color, $PDFAXwarnings);
71			case 5:
72				return $this->restrictRgbaColorSpace($c, $color, $PDFAXwarnings);
73			case 6:
74				return $this->restrictCmykaColorSpace($c, $color, $PDFAXwarnings);
75		}
76
77		return $c;
78	}
79
80	/**
81	 * @param string $c
82	 * @param string[] $PDFAXwarnings
83	 *
84	 * @return float[]
85	 */
86	private function restrictSpotColorSpace($c, &$PDFAXwarnings = [])
87	{
88		if (!isset($this->mpdf->spotColorIDs[$c[1]])) {
89				throw new \Mpdf\MpdfException('Error: Spot colour has not been defined - ' . $this->mpdf->spotColorIDs[$c[1]]);
90		}
91
92		if ($this->mpdf->PDFA) {
93			if ($this->mpdf->PDFA && !$this->mpdf->PDFAauto) {
94				$PDFAXwarnings[] = "Spot color specified '" . $this->mpdf->spotColorIDs[$c[1]] . "' (converted to process color)";
95			}
96			if ($this->mode != 3) {
97				$sp = $this->mpdf->spotColors[$this->mpdf->spotColorIDs[$c[1]]];
98				$c = $this->colorModeConverter->cmyk2rgb([4, $sp['c'], $sp['m'], $sp['y'], $sp['k']]);
99			}
100		} elseif ($this->mode == 1) {
101			$sp = $this->mpdf->spotColors[$this->mpdf->spotColorIDs[$c[1]]];
102			$c = $this->colorModeConverter->cmyk2gray([4, $sp['c'], $sp['m'], $sp['y'], $sp['k']]);
103		}
104
105		return $c;
106	}
107
108	/**
109	 * @param mixed $c
110	 * @param string $color
111	 * @param string[] $PDFAXwarnings
112	 *
113	 * @return float[]
114	 */
115	private function restrictRgbColorSpace($c, $color, &$PDFAXwarnings = [])
116	{
117		if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mode == 3)) {
118			if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
119				$PDFAXwarnings[] = "RGB color specified '" . $color . "' (converted to CMYK)";
120			}
121			$c = $this->colorModeConverter->rgb2cmyk($c);
122		} elseif ($this->mode == 1) {
123			$c = $this->colorModeConverter->rgb2gray($c);
124		} elseif ($this->mode == 3) {
125			$c = $this->colorModeConverter->rgb2cmyk($c);
126		}
127
128		return $c;
129	}
130
131	/**
132	 * @param mixed $c
133	 * @param string $color
134	 * @param string[] $PDFAXwarnings
135	 *
136	 * @return float[]
137	 */
138	private function restrictCmykColorSpace($c, $color, &$PDFAXwarnings = [])
139	{
140		if ($this->mpdf->PDFA && $this->mode != 3) {
141			if ($this->mpdf->PDFA && !$this->mpdf->PDFAauto) {
142				$PDFAXwarnings[] = "CMYK color specified '" . $color . "' (converted to RGB)";
143			}
144			$c = $this->colorModeConverter->cmyk2rgb($c);
145		} elseif ($this->mode == 1) {
146			$c = $this->colorModeConverter->cmyk2gray($c);
147		} elseif ($this->mode == 2) {
148			$c = $this->colorModeConverter->cmyk2rgb($c);
149		}
150
151		return $c;
152	}
153
154	/**
155	 * @param mixed $c
156	 * @param string $color
157	 * @param string[] $PDFAXwarnings
158	 *
159	 * @return float[]
160	 */
161	private function restrictRgbaColorSpace($c, $color, &$PDFAXwarnings = [])
162	{
163		if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mode == 3)) {
164			if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
165				$PDFAXwarnings[] = "RGB color with transparency specified '" . $color . "' (converted to CMYK without transparency)";
166			}
167			$c = $this->colorModeConverter->rgb2cmyk($c);
168			$c = [4, $c[1], $c[2], $c[3], $c[4]];
169		} elseif ($this->mpdf->PDFA && $this->mode != 3) {
170			if (!$this->mpdf->PDFAauto) {
171				$PDFAXwarnings[] = "RGB color with transparency specified '" . $color . "' (converted to RGB without transparency)";
172			}
173			$c = $this->colorModeConverter->rgb2cmyk($c);
174			$c = [4, $c[1], $c[2], $c[3], $c[4]];
175		} elseif ($this->mode == 1) {
176			$c = $this->colorModeConverter->rgb2gray($c);
177		} elseif ($this->mode == 3) {
178			$c = $this->colorModeConverter->rgb2cmyk($c);
179		}
180
181		return $c;
182	}
183
184	/**
185	 * @param mixed $c
186	 * @param string $color
187	 * @param string[] $PDFAXwarnings
188	 *
189	 * @return float[]
190	 */
191	private function restrictCmykaColorSpace($c, $color, &$PDFAXwarnings = [])
192	{
193		if ($this->mpdf->PDFA && $this->mode != 3) {
194			if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
195				$PDFAXwarnings[] = "CMYK color with transparency specified '" . $color . "' (converted to RGB without transparency)";
196			}
197			$c = $this->colorModeConverter->cmyk2rgb($c);
198			$c = [3, $c[1], $c[2], $c[3]];
199		} elseif ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mode == 3)) {
200			if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
201				$PDFAXwarnings[] = "CMYK color with transparency specified '" . $color . "' (converted to CMYK without transparency)";
202			}
203			$c = $this->colorModeConverter->cmyk2rgb($c);
204			$c = [3, $c[1], $c[2], $c[3]];
205		} elseif ($this->mode == 1) {
206			$c = $this->colorModeConverter->cmyk2gray($c);
207		} elseif ($this->mode == 2) {
208			$c = $this->colorModeConverter->cmyk2rgb($c);
209		}
210
211		return $c;
212	}
213
214}
215