1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8                           sccolor.cpp  -  description
9                              -------------------
10     begin                : Sun Sep 9 2001
11     copyright            : (C) 2001 by Franz Schmid
12     email                : Franz.Schmid@altmuehlnet.de
13  ***************************************************************************/
14 
15 /***************************************************************************
16  *                                                                         *
17  *   This program is free software; you can redistribute it and/or modify  *
18  *   it under the terms of the GNU General Public License as published by  *
19  *   the Free Software Foundation; either version 2 of the License, or     *
20  *   (at your option) any later version.                                   *
21  *                                                                         *
22  ***************************************************************************/
23 
24 #include <cmath>
25 
26 #include "sccolorengine.h"
27 #include "scribuscore.h"
28 #include "scribusdoc.h"
29 #include "colormgmt/sccolormgmtengine.h"
30 
getRGBColor(const ScColor & color,const ScribusDoc * doc)31 QColor ScColorEngine::getRGBColor(const ScColor& color, const ScribusDoc* doc)
32 {
33 	RGBColor rgb;
34 	getRGBValues(color, doc, rgb);
35 	return QColor(rgb.r, rgb.g, rgb.b);
36 }
37 
convertToModel(const ScColor & color,const ScribusDoc * doc,colorModel model)38 ScColor ScColorEngine::convertToModel(const ScColor& color, const ScribusDoc* doc, colorModel model)
39 {
40 	colorModel oldModel = color.getColorModel();
41 	if (oldModel == model)
42 		return ScColor(color);
43 	ScColor newCol;
44 	if (model == colorModelRGB)
45 	{
46 		RGBColorF rgb;
47 		getRGBValues(color, doc, rgb);
48 		newCol.setRgbColorF(rgb.r, rgb.g, rgb.b);
49 	}
50 	else if (model == colorModelCMYK)
51 	{
52 		CMYKColorF cmyk;
53 		getCMYKValues(color, doc, cmyk);
54 		newCol.setColorF(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
55 	}
56 	else if (model == colorModelLab)
57 	{
58 		ScColorMgmtEngine engine(ScCore->defaultEngine);
59 		if (oldModel == colorModelRGB)
60 		{
61 			ScColorProfile profRGB = doc ? doc->DocInputRGBProf : ScCore->defaultRGBProfile;
62 			ScColorProfile profLab = ScCore->defaultLabProfile;
63 			ScColorTransform trans = engine.createTransform(profRGB, Format_RGB_16, profLab, Format_Lab_Dbl, Intent_Perceptual, 0);
64 			double outC[3];
65 			unsigned short inC[3];
66 			inC[0] = qRound(color.m_values[0] * 65535);
67 			inC[1] = qRound(color.m_values[1] * 65535);
68 			inC[2] = qRound(color.m_values[2] * 65535);
69 			trans.apply(inC, outC, 1);
70 			newCol.setLabColor(outC[0], outC[1], outC[2]);
71 		}
72 		else
73 		{
74 			ScColorProfile profCMYK = doc ? doc->DocInputCMYKProf : ScCore->defaultCMYKProfile;
75 			ScColorProfile profLab = ScCore->defaultLabProfile;
76 			ScColorTransform trans = engine.createTransform(profCMYK, Format_CMYK_16, profLab, Format_Lab_Dbl, Intent_Perceptual, 0);
77 			double outC[3];
78 			unsigned short inC[4];
79 			inC[0] = qRound(color.m_values[0] * 65535);
80 			inC[1] = qRound(color.m_values[1] * 65535);
81 			inC[2] = qRound(color.m_values[2] * 65535);
82 			inC[3] = qRound(color.m_values[3] * 65535);
83 			trans.apply(inC, outC, 1);
84 			newCol.setLabColor(outC[0], outC[1], outC[2]);
85 		}
86 	}
87 	return newCol;
88 }
89 
getRGBValues(const ScColor & color,const ScribusDoc * doc,RGBColor & rgb)90 void ScColorEngine::getRGBValues(const ScColor& color, const ScribusDoc* doc, RGBColor& rgb)
91 {
92 	colorModel    model = color.getColorModel();
93 	ScColorTransform transRGB = doc ? doc->stdTransRGB : ScCore->defaultCMYKToRGBTrans;
94 	if (ScCore->haveCMS() && transRGB)
95 	{
96 		if (model == colorModelRGB)
97 		{
98 			rgb.r = qRound(color.m_values[0] * 255.0);
99 			rgb.g = qRound(color.m_values[1] * 255.0);
100 			rgb.b = qRound(color.m_values[2] * 255.0);
101 		}
102 		else if (model == colorModelCMYK)
103 		{
104 			unsigned short inC[4];
105 			unsigned short outC[4];
106 			inC[0] = qRound(color.m_values[0] * 65535);
107 			inC[1] = qRound(color.m_values[1] * 65535);
108 			inC[2] = qRound(color.m_values[2] * 65535);
109 			inC[3] = qRound(color.m_values[3] * 65535);
110 			transRGB.apply(inC, outC, 1);
111 			rgb.r = outC[0] / 257;
112 			rgb.g = outC[1] / 257;
113 			rgb.b = outC[2] / 257;
114 		}
115 		else if (model == colorModelLab)
116 		{
117 			ScColorTransform trans = doc ? doc->stdLabToRGBTrans : ScCore->defaultLabToRGBTrans;
118 			double inC[3];
119 			inC[0] = color.m_L_val;
120 			inC[1] = color.m_a_val;
121 			inC[2] = color.m_b_val;
122 			quint16 outC[3];
123 			trans.apply(inC, outC, 1);
124 			rgb.r = outC[0] / 257;
125 			rgb.g = outC[1] / 257;
126 			rgb.b = outC[2] / 257;
127 		}
128 	}
129 	else if (model == colorModelCMYK)
130 	{
131 		double r = 1.0 - qMin(1.0, color.m_values[0] + color.m_values[3]);
132 		double g = 1.0 - qMin(1.0, color.m_values[1] + color.m_values[3]);
133 		double b = 1.0 - qMin(1.0, color.m_values[2] + color.m_values[3]);
134 		rgb.r = qRound(r * 255.0);
135 		rgb.g = qRound(g * 255.0);
136 		rgb.b = qRound(b * 255.0);
137 	}
138 	else if (model == colorModelRGB)
139 	{
140 		rgb.r = qRound(color.m_values[0] * 255.0);
141 		rgb.g = qRound(color.m_values[1] * 255.0);
142 		rgb.b = qRound(color.m_values[2] * 255.0);
143 	}
144 	else if (model == colorModelLab)
145 	{
146 		// First step: Lab -> XYZ
147 		double var_Y = (color.m_L_val + 16) / 116.0;
148 		double var_X = color.m_a_val / 500.0 + var_Y;
149 		double var_Z = var_Y - color.m_b_val / 200.0;
150 		if (pow(var_Y, 3) > 0.008856)
151 			var_Y = pow(var_Y, 3);
152 		else
153 			var_Y = (var_Y - 16.0 / 116.0) / 7.787;
154 		if (pow(var_X, 3) > 0.008856)
155 			var_X = pow(var_X, 3);
156 		else
157 			var_X = (var_X - 16.0 / 116.0) / 7.787;
158 		if (pow(var_Z, 3) > 0.008856)
159 			var_Z = pow(var_Z, 3);
160 		else
161 			var_Z = (var_Z - 16.0 / 116.0) / 7.787;
162 		// Second step: XYZ -> RGB
163 		// Whitepoint D50
164 		var_X = 0.990720 * var_X;
165 		var_Y = 1.00000  * var_Y;
166 		var_Z = 0.825210 * var_Z;
167 		double var_R = var_X *  3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
168 		double var_G = var_X * -0.9689 + var_Y *  1.8758 + var_Z *  0.0415;
169 		double var_B = var_X *  0.0557 + var_Y * -0.2040 + var_Z *  1.0570;
170 		if (var_R > 0.0031308)
171 			var_R = 1.055 * (pow(var_R, (1.0 / 2.4))) - 0.055;
172 		else
173 			var_R = 12.92 * var_R;
174 		if (var_G > 0.0031308)
175 			var_G = 1.055 * (pow(var_G, (1.0 / 2.4))) - 0.055;
176 		else
177 			var_G = 12.92 * var_G;
178 		if (var_B > 0.0031308)
179 			var_B = 1.055 * (pow(var_B, (1.0 / 2.4))) - 0.055;
180 		else
181 			var_B = 12.92 * var_B;
182 		rgb.r = qRound(qMax(qMin(var_R, 1.0), 0.0) * 255.0);
183 		rgb.g = qRound(qMax(qMin(var_G, 1.0), 0.0) * 255.0);
184 		rgb.b = qRound(qMax(qMin(var_B, 1.0), 0.0) * 255.0);
185 	/*	ScColorTransform trans = doc ? doc->stdLabToRGBTrans : ScCore->defaultLabToRGBTrans;
186 		double inC[3];
187 		inC[0] = color.L_val;
188 		inC[1] = color.a_val;
189 		inC[2] = color.b_val;
190 		quint16 outC[3];
191 		trans.apply(inC, outC, 1);
192 		rgb.r = outC[0] / 257;
193 		rgb.g = outC[1] / 257;
194 		rgb.b = outC[2] / 257;*/
195 	}
196 }
197 
getRGBValues(const ScColor & color,const ScribusDoc * doc,RGBColorF & rgb)198 void ScColorEngine::getRGBValues(const ScColor& color, const ScribusDoc* doc, RGBColorF& rgb)
199 {
200 	colorModel    model = color.getColorModel();
201 	ScColorTransform transRGB = doc ? doc->stdTransRGB : ScCore->defaultCMYKToRGBTrans;
202 	if (ScCore->haveCMS() && transRGB)
203 	{
204 		if (model == colorModelRGB)
205 		{
206 			rgb.r = color.m_values[0];
207 			rgb.g = color.m_values[1];
208 			rgb.b = color.m_values[2];
209 		}
210 		else if (model == colorModelCMYK)
211 		{
212 			unsigned short inC[4];
213 			unsigned short outC[4];
214 			inC[0] = qRound(color.m_values[0] * 65535);
215 			inC[1] = qRound(color.m_values[1] * 65535);
216 			inC[2] = qRound(color.m_values[2] * 65535);
217 			inC[3] = qRound(color.m_values[3] * 65535);
218 			transRGB.apply(inC, outC, 1);
219 			rgb.r = outC[0] / 65535.0;
220 			rgb.g = outC[1] / 65535.0;
221 			rgb.b = outC[2] / 65535.0;
222 		}
223 		else if (model == colorModelLab)
224 		{
225 			ScColorTransform trans = doc ? doc->stdLabToRGBTrans : ScCore->defaultLabToRGBTrans;
226 			double inC[3];
227 			inC[0] = color.m_L_val;
228 			inC[1] = color.m_a_val;
229 			inC[2] = color.m_b_val;
230 			quint16 outC[3];
231 			trans.apply(inC, outC, 1);
232 			rgb.r = outC[0] / 65535.0;
233 			rgb.g = outC[1] / 65535.0;
234 			rgb.b = outC[2] / 65535.0;
235 		}
236 	}
237 	else if (model == colorModelCMYK)
238 	{
239 		rgb.r = 1.0 - qMin(1.0, color.m_values[0] + color.m_values[3]);
240 		rgb.g = 1.0 - qMin(1.0, color.m_values[1] + color.m_values[3]);
241 		rgb.b = 1.0 - qMin(1.0, color.m_values[2] + color.m_values[3]);
242 	}
243 	else if (model == colorModelRGB)
244 	{
245 		rgb.r = color.m_values[0];
246 		rgb.g = color.m_values[1];
247 		rgb.b = color.m_values[2];
248 	}
249 	else if (model == colorModelLab)
250 	{
251 		// First step: Lab -> XYZ
252 		double var_Y = (color.m_L_val + 16) / 116.0;
253 		double var_X = color.m_a_val / 500.0 + var_Y;
254 		double var_Z = var_Y - color.m_b_val / 200.0;
255 		if (pow(var_Y, 3) > 0.008856)
256 			var_Y = pow(var_Y, 3);
257 		else
258 			var_Y = (var_Y - 16.0 / 116.0) / 7.787;
259 		if (pow(var_X, 3) > 0.008856)
260 			var_X = pow(var_X, 3);
261 		else
262 			var_X = (var_X - 16.0 / 116.0) / 7.787;
263 		if (pow(var_Z, 3) > 0.008856)
264 			var_Z = pow(var_Z, 3);
265 		else
266 			var_Z = (var_Z - 16.0 / 116.0) / 7.787;
267 		// Second step: XYZ -> RGB
268 		// Whitepoint D50
269 		var_X = 0.990720 * var_X;
270 		var_Y = 1.00000  * var_Y;
271 		var_Z = 0.825210 * var_Z;
272 		double var_R = var_X *  3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
273 		double var_G = var_X * -0.9689 + var_Y *  1.8758 + var_Z *  0.0415;
274 		double var_B = var_X *  0.0557 + var_Y * -0.2040 + var_Z *  1.0570;
275 		if (var_R > 0.0031308)
276 			var_R = 1.055 * (pow(var_R, (1.0 / 2.4))) - 0.055;
277 		else
278 			var_R = 12.92 * var_R;
279 		if (var_G > 0.0031308)
280 			var_G = 1.055 * (pow(var_G, (1.0 / 2.4))) - 0.055;
281 		else
282 			var_G = 12.92 * var_G;
283 		if (var_B > 0.0031308)
284 			var_B = 1.055 * (pow(var_B, (1.0 / 2.4))) - 0.055;
285 		else
286 			var_B = 12.92 * var_B;
287 		rgb.r = qMax(0.0, qMin(var_R, 1.0));
288 		rgb.g = qMax(0.0, qMin(var_G, 1.0));
289 		rgb.b = qMax(0.0, qMin(var_B, 1.0));
290 	/*	ScColorTransform trans = doc ? doc->stdLabToRGBTrans : ScCore->defaultLabToRGBTrans;
291 		double inC[3];
292 		inC[0] = color.L_val;
293 		inC[1] = color.a_val;
294 		inC[2] = color.b_val;
295 		quint16 outC[3];
296 		trans.apply(inC, outC, 1);
297 		rgb.r = outC[0] / 65535.0;
298 		rgb.g = outC[1] / 65535.0;
299 		rgb.b = outC[2] / 65535.0;*/
300 	}
301 }
302 
getCMYKValues(const ScColor & color,const ScribusDoc * doc,CMYKColor & cmyk)303 void ScColorEngine::getCMYKValues(const ScColor& color, const ScribusDoc* doc, CMYKColor& cmyk)
304 {
305 	unsigned short inC[4];
306 	unsigned short outC[4];
307 	colorModel model = color.getColorModel();
308 	ScColorTransform transCMYK = doc ? doc->stdTransCMYK : ScCore->defaultRGBToCMYKTrans;
309 	if (ScCore->haveCMS() && transCMYK)
310 	{
311 		if (model == colorModelRGB)
312 		{
313 			// allow RGB greys to go to CMYK greys without transform
314 			if (color.m_values[0] == color.m_values[1] && color.m_values[1] == color.m_values[2])
315 			{
316 				cmyk.c = cmyk.m = cmyk.y = 0;
317 				cmyk.k = 255 - qRound(color.m_values[0] * 255.0);
318 			}
319 			else
320 			{
321 				inC[0] = qRound(color.m_values[0] * 65535.0);
322 				inC[1] = qRound(color.m_values[1] * 65535.0);
323 				inC[2] = qRound(color.m_values[2] * 65535.0);
324 				transCMYK.apply(inC, outC, 1);
325 				cmyk.c = outC[0] / 257;
326 				cmyk.m = outC[1] / 257;
327 				cmyk.y = outC[2] / 257;
328 				cmyk.k = outC[3] / 257;
329 			}
330 		}
331 		else if (model == colorModelCMYK)
332 		{
333 			cmyk.c = qRound(color.m_values[0] * 255.0);
334 			cmyk.m = qRound(color.m_values[1] * 255.0);
335 			cmyk.y = qRound(color.m_values[2] * 255.0);
336 			cmyk.k = qRound(color.m_values[3] * 255.0);
337 		}
338 		else if (model == colorModelLab)
339 		{
340 			ScColorTransform trans = doc ? doc->stdLabToCMYKTrans : ScCore->defaultLabToCMYKTrans;
341 			double inC[3];
342 			inC[0] = color.m_L_val;
343 			inC[1] = color.m_a_val;
344 			inC[2] = color.m_b_val;
345 			quint16 outC[4];
346 			trans.apply(inC, outC, 1);
347 			cmyk.c = outC[0] / 257;
348 			cmyk.m = outC[1] / 257;
349 			cmyk.y = outC[2] / 257;
350 			cmyk.k = outC[3] / 257;
351 		}
352 	}
353 	else if (model == colorModelRGB)
354 	{
355 		double k = qMin(qMin(1.0 - color.m_values[0], 1.0 - color.m_values[1]), 1.0 - color.m_values[2]);
356 		cmyk.k = qRound(k * 255.0);
357 		cmyk.c = 255 - qRound((color.m_values[0] - k) * 255.0);
358 		cmyk.m = 255 - qRound((color.m_values[1] - k) * 255.0);
359 		cmyk.y = 255 - qRound((color.m_values[2] - k) * 255.0);
360 	}
361 	else if (model == colorModelCMYK)
362 	{
363 		cmyk.c = qRound(color.m_values[0] * 255.0);
364 		cmyk.m = qRound(color.m_values[1] * 255.0);
365 		cmyk.y = qRound(color.m_values[2] * 255.0);
366 		cmyk.k = qRound(color.m_values[3] * 255.0);
367 	}
368 	else if (model == colorModelLab)
369 	{
370 		ScColorTransform trans = doc ? doc->stdLabToCMYKTrans : ScCore->defaultLabToCMYKTrans;
371 		double inC[3];
372 		inC[0] = color.m_L_val;
373 		inC[1] = color.m_a_val;
374 		inC[2] = color.m_b_val;
375 		quint16 outC[4];
376 		trans.apply(inC, outC, 1);
377 		cmyk.c = outC[0] / 257;
378 		cmyk.m = outC[1] / 257;
379 		cmyk.y = outC[2] / 257;
380 		cmyk.k = outC[3] / 257;
381 	}
382 }
383 
getCMYKValues(const ScColor & color,const ScribusDoc * doc,CMYKColorF & cmyk)384 void ScColorEngine::getCMYKValues(const ScColor& color, const ScribusDoc* doc, CMYKColorF& cmyk)
385 {
386 	unsigned short inC[4];
387 	unsigned short outC[4];
388 	colorModel model = color.getColorModel();
389 	ScColorTransform transCMYK = doc ? doc->stdTransCMYK : ScCore->defaultRGBToCMYKTrans;
390 	if (ScCore->haveCMS() && transCMYK)
391 	{
392 		if (model == colorModelRGB)
393 		{
394 			// allow RGB greys to go to CMYK greys without transform
395 			if (color.m_values[0] == color.m_values[1] && color.m_values[1] == color.m_values[2])
396 			{
397 				cmyk.c = cmyk.m = cmyk.y = 0;
398 				cmyk.k = 1.0 - color.m_values[0];
399 			}
400 			else
401 			{
402 				inC[0] = qRound(color.m_values[0] * 65535.0);
403 				inC[1] = qRound(color.m_values[1] * 65535.0);
404 				inC[2] = qRound(color.m_values[2] * 65535.0);
405 				transCMYK.apply(inC, outC, 1);
406 				cmyk.c = outC[0] / 65535.0;
407 				cmyk.m = outC[1] / 65535.0;
408 				cmyk.y = outC[2] / 65535.0;
409 				cmyk.k = outC[3] / 65535.0;
410 			}
411 		}
412 		else if (model == colorModelCMYK)
413 		{
414 			cmyk.c = color.m_values[0];
415 			cmyk.m = color.m_values[1];
416 			cmyk.y = color.m_values[2];
417 			cmyk.k = color.m_values[3];
418 		}
419 		else if (model == colorModelLab)
420 		{
421 			ScColorTransform trans = doc ? doc->stdLabToCMYKTrans : ScCore->defaultLabToCMYKTrans;
422 			double inC[3];
423 			inC[0] = color.m_L_val;
424 			inC[1] = color.m_a_val;
425 			inC[2] = color.m_b_val;
426 			quint16 outC[4];
427 			trans.apply(inC, outC, 1);
428 			cmyk.c = outC[0] / 65535.0;
429 			cmyk.m = outC[1] / 65535.0;
430 			cmyk.y = outC[2] / 65535.0;
431 			cmyk.k = outC[3] / 65535.0;
432 		}
433 	}
434 	else if (model == colorModelRGB)
435 	{
436 		cmyk.k = qMin(qMin(1.0 - color.m_values[0], 1.0 - color.m_values[1]), 1.0 - color.m_values[2]);
437 		cmyk.c = 1.0 - (color.m_values[0] - cmyk.k);
438 		cmyk.m = 1.0 - (color.m_values[1] - cmyk.k);
439 		cmyk.y = 1.0 - (color.m_values[2] - cmyk.k);
440 	}
441 	else if (model == colorModelCMYK)
442 	{
443 		cmyk.c = color.m_values[0];
444 		cmyk.m = color.m_values[1];
445 		cmyk.y = color.m_values[2];
446 		cmyk.k = color.m_values[3];
447 	}
448 	else if (model == colorModelLab)
449 	{
450 		ScColorTransform trans = doc ? doc->stdLabToCMYKTrans : ScCore->defaultLabToCMYKTrans;
451 		double inC[3];
452 		inC[0] = color.m_L_val;
453 		inC[1] = color.m_a_val;
454 		inC[2] = color.m_b_val;
455 		quint16 outC[4];
456 		trans.apply(inC, outC, 1);
457 		cmyk.c = outC[0] / 65535.0;
458 		cmyk.m = outC[1] / 65535.0;
459 		cmyk.y = outC[2] / 65535.0;
460 		cmyk.k = outC[3] / 65535.0;
461 	}
462 }
463 
getShadeColorCMYK(const ScColor & color,const ScribusDoc * doc,CMYKColor & cmyk,double level)464 void ScColorEngine::getShadeColorCMYK(const ScColor& color, const ScribusDoc* doc,
465 										  CMYKColor& cmyk, double level)
466 {
467 	if (color.getColorModel() == colorModelRGB)
468 	{
469 		RGBColorF rgb;
470 		getShadeColorRGB(color, doc, rgb, level);
471 		ScColor tmpR;
472 		tmpR.setRgbColorF(rgb.r, rgb.g, rgb.b);
473 		getCMYKValues(tmpR, doc, cmyk);
474 	}
475 	else if (color.getColorModel() == colorModelCMYK)
476 	{
477 		cmyk.c = qRound(color.m_values[0] * level / 100.0 * 255.0);
478 		cmyk.m = qRound(color.m_values[1] * level / 100.0 * 255.0);
479 		cmyk.y = qRound(color.m_values[2] * level / 100.0 * 255.0);
480 		cmyk.k = qRound(color.m_values[3] * level / 100.0 * 255.0);
481 	}
482 	else if (color.getColorModel() == colorModelLab)
483 	{
484 		ScColorTransform trans = doc ? doc->stdLabToCMYKTrans : ScCore->defaultLabToCMYKTrans;
485 		double inC[3];
486 		inC[0] = 100 - (100 - color.m_L_val) * (level / 100.0);
487 		inC[1] = color.m_a_val * (level / 100.0);
488 		inC[2] = color.m_b_val * (level / 100.0);
489 		quint16 outC[4];
490 		trans.apply(inC, outC, 1);
491 		cmyk.c = outC[0] / 257;
492 		cmyk.m = outC[1] / 257;
493 		cmyk.y = outC[2] / 257;
494 		cmyk.k = outC[3] / 257;
495 	}
496 }
497 
getShadeColorCMYK(const ScColor & color,const ScribusDoc * doc,CMYKColorF & cmyk,double level)498 void ScColorEngine::getShadeColorCMYK(const ScColor& color, const ScribusDoc* doc, CMYKColorF& cmyk, double level)
499 {
500 	if (color.getColorModel() == colorModelRGB)
501 	{
502 		RGBColorF rgb;
503 		getShadeColorRGB(color, doc, rgb, level);
504 		ScColor tmpR;
505 		tmpR.setRgbColorF(rgb.r, rgb.g, rgb.b);
506 		getCMYKValues(tmpR, doc, cmyk);
507 	}
508 	else if (color.getColorModel() == colorModelCMYK)
509 	{
510 		cmyk.c = color.m_values[0] * level / 100.0;
511 		cmyk.m = color.m_values[1] * level / 100.0;
512 		cmyk.y = color.m_values[2] * level / 100.0;
513 		cmyk.k = color.m_values[3] * level / 100.0;
514 	}
515 	else if (color.getColorModel() == colorModelLab)
516 	{
517 		ScColorTransform trans = doc ? doc->stdLabToCMYKTrans : ScCore->defaultLabToCMYKTrans;
518 		double inC[3];
519 		inC[0] = 100 - (100 - color.m_L_val) * (level / 100.0);
520 		inC[1] = color.m_a_val * (level / 100.0);
521 		inC[2] = color.m_b_val * (level / 100.0);
522 		quint16 outC[4];
523 		trans.apply(inC, outC, 1);
524 		cmyk.c = outC[0] / 65535.0;
525 		cmyk.m = outC[1] / 65535.0;
526 		cmyk.y = outC[2] / 65535.0;
527 		cmyk.k = outC[3] / 65535.0;
528 	}
529 }
530 
getShadeColorRGB(const ScColor & color,const ScribusDoc * doc,RGBColor & rgb,double level)531 void ScColorEngine::getShadeColorRGB(const ScColor& color, const ScribusDoc* doc, RGBColor& rgb, double level)
532 {
533 	if (color.getColorModel() == colorModelCMYK)
534 	{
535 		CMYKColor cmyk;
536 		getShadeColorCMYK(color, doc, cmyk, level);
537 		ScColor tmpC(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
538 		getRGBValues(tmpC, doc, rgb);
539 	}
540 	else if (color.getColorModel() == colorModelRGB)
541 	{
542 		HSVColorF hsv;
543 		RGBColorF rgbF;
544 		color.getRawRGBColor(&rgbF);
545 		rgbF.toHsv(hsv);
546 		hsv.s = hsv.s * (level / 100.0);
547 		hsv.v = 1.0 - (1.0 - hsv.v) * (level / 100.0);
548 		hsv.toRgb(rgb);
549 		//We could also compute rgb shade using rgb directly
550 		/*rgb.r = 255 - ((255 - color.m_values[0]) * level / 100);
551 		rgb.g = 255 - ((255 - color.m_values[1]) * level / 100);
552 		rgb.b = 255 - ((255 - color.m_values[2]) * level / 100);*/
553 	}
554 	else if (color.getColorModel() == colorModelLab)
555 	{
556 		ScColorTransform trans = doc ? doc->stdLabToRGBTrans : ScCore->defaultLabToRGBTrans;
557 		double inC[3];
558 		inC[0] = 100 - (100 - color.m_L_val) * (level / 100.0);
559 		inC[1] = color.m_a_val * (level / 100.0);
560 		inC[2] = color.m_b_val * (level / 100.0);
561 		quint16 outC[3];
562 		trans.apply(inC, outC, 1);
563 		rgb.r = outC[0] / 257;
564 		rgb.g = outC[1] / 257;
565 		rgb.b = outC[2] / 257;
566 	}
567 }
568 
getShadeColorRGB(const ScColor & color,const ScribusDoc * doc,RGBColorF & rgb,double level)569 void ScColorEngine::getShadeColorRGB(const ScColor& color, const ScribusDoc* doc, RGBColorF& rgb, double level)
570 {
571 	if (color.getColorModel() == colorModelCMYK)
572 	{
573 		CMYKColorF cmyk;
574 		getShadeColorCMYK(color, doc, cmyk, level);
575 		ScColor tmpC;
576 		tmpC.setColorF(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
577 		getRGBValues(tmpC, doc, rgb);
578 	}
579 	else if (color.getColorModel() == colorModelRGB)
580 	{
581 		HSVColorF hsv;
582 		color.getRawRGBColor(&rgb);
583 		rgb.toHsv(hsv);
584 		hsv.s = hsv.s * (level / 100.0);
585 		hsv.v = 1.0 - (1.0 - hsv.v) * (level / 100.0);
586 		hsv.toRgb(rgb);
587 		//We could also compute rgb shade using rgb directly
588 		/*rgb.r = 1.0 - ((1.0 - color.m_values[0]) * level / 100.0);
589 		rgb.g = 1.0 - ((1.0 - color.m_values[1]) * level / 100.0);
590 		rgb.b = 1.0 - ((1.0 - color.m_values[2]) * level / 100.0);*/
591 	}
592 	else if (color.getColorModel() == colorModelLab)
593 	{
594 		ScColorTransform trans = doc ? doc->stdLabToRGBTrans : ScCore->defaultLabToRGBTrans;
595 		double inC[3];
596 		inC[0] = 100 - (100 - color.m_L_val) * (level / 100.0);
597 		inC[1] = color.m_a_val * (level / 100.0);
598 		inC[2] = color.m_b_val * (level / 100.0);
599 		quint16 outC[3];
600 		trans.apply(inC, outC, 1);
601 		rgb.r = outC[0] / 65535.0;
602 		rgb.g = outC[1] / 65535.0;
603 		rgb.b = outC[2] / 65535.0;
604 	}
605 }
606 
getDisplayColor(const ScColor & color,const ScribusDoc * doc)607 QColor ScColorEngine::getDisplayColor(const ScColor& color, const ScribusDoc* doc)
608 {
609 	QColor tmp;
610 	if (color.getColorModel() == colorModelRGB)
611 	{
612 		RGBColorF rgb;
613 		rgb.r = color.m_values[0];
614 		rgb.g = color.m_values[1];
615 		rgb.b = color.m_values[2];
616 		tmp = getDisplayColor(rgb, doc, color.isSpotColor());
617 	}
618 	else if (color.getColorModel() == colorModelCMYK)
619 	{
620 		CMYKColorF cmyk;
621 		cmyk.c = color.m_values[0];
622 		cmyk.m = color.m_values[1];
623 		cmyk.y = color.m_values[2];
624 		cmyk.k = color.m_values[3];
625 		tmp = getDisplayColor(cmyk, doc, color.isSpotColor());
626 	}
627 	else if (color.getColorModel() == colorModelLab)
628 	{
629 		bool cmsUse = doc ? doc->HasCMS : false;
630 		ScColorTransform trans  = doc ? doc->stdLabToScreenTrans : ScCore->defaultLabToRGBTrans;
631 		if (cmsUse && trans)
632 		{
633 			double inC[3];
634 			inC[0] = color.m_L_val;
635 			inC[1] = color.m_a_val;
636 			inC[2] = color.m_b_val;
637 			quint16 outC[3];
638 			trans.apply(inC, outC, 1);
639 			tmp = QColor(outC[0] / 257, outC[1] / 257, outC[2] / 257);
640 		}
641 		else
642 		{
643 			// First step: Lab -> XYZ
644 			double var_Y = (color.m_L_val + 16) / 116.0;
645 			double var_X = color.m_a_val / 500.0 + var_Y;
646 			double var_Z = var_Y - color.m_b_val / 200.0;
647 			if (pow(var_Y, 3) > 0.008856)
648 				var_Y = pow(var_Y, 3);
649 			else
650 				var_Y = (var_Y - 16.0 / 116.0) / 7.787;
651 			if (pow(var_X, 3) > 0.008856)
652 				var_X = pow(var_X, 3);
653 			else
654 				var_X = (var_X - 16.0 / 116.0) / 7.787;
655 			if (pow(var_Z, 3) > 0.008856)
656 				var_Z = pow(var_Z, 3);
657 			else
658 				var_Z = (var_Z - 16.0 / 116.0) / 7.787;
659 			// Second step: XYZ -> RGB
660 			// Whitepoint D50
661 			var_X = 0.990720 * var_X;
662 			var_Y = 1.00000  * var_Y;
663 			var_Z = 0.825210 * var_Z;
664 			double var_R = var_X *  3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
665 			double var_G = var_X * -0.9689 + var_Y *  1.8758 + var_Z *  0.0415;
666 			double var_B = var_X *  0.0557 + var_Y * -0.2040 + var_Z *  1.0570;
667 			if (var_R > 0.0031308)
668 				var_R = 1.055 * (pow(var_R, (1.0 / 2.4))) - 0.055;
669 			else
670 				var_R = 12.92 * var_R;
671 			if (var_G > 0.0031308)
672 				var_G = 1.055 * (pow(var_G, (1.0 / 2.4))) - 0.055;
673 			else
674 				var_G = 12.92 * var_G;
675 			if (var_B > 0.0031308)
676 				var_B = 1.055 * (pow(var_B, (1.0 / 2.4))) - 0.055;
677 			else
678 				var_B = 12.92 * var_B;
679 			tmp = QColor(0, 0, 0, 0);
680 			var_R = qMax(qMin(var_R, 1.0), 0.0);
681 			var_G = qMax(qMin(var_G, 1.0), 0.0);
682 			var_B = qMax(qMin(var_B, 1.0), 0.0);
683 			tmp.setRgbF(var_R, var_G, var_B);
684 		}
685 	}
686 	return tmp;
687 }
688 
getDisplayColor(const ScColor & color,const ScribusDoc * doc,double level)689 QColor ScColorEngine::getDisplayColor(const ScColor& color, const ScribusDoc* doc, double level)
690 {
691 	QColor tmp;
692 	if (color.getColorModel() == colorModelRGB)
693 	{
694 		RGBColorF rgb;
695 		rgb.r = color.m_values[0];
696 		rgb.g = color.m_values[1];
697 		rgb.b = color.m_values[2];
698 		getShadeColorRGB(color, doc, rgb, level);
699 		tmp = getDisplayColor(rgb, doc, color.isSpotColor());
700 	}
701 	else if (color.getColorModel() == colorModelCMYK)
702 	{
703 		CMYKColorF cmyk;
704 		cmyk.c = color.m_values[0];
705 		cmyk.m = color.m_values[1];
706 		cmyk.y = color.m_values[2];
707 		cmyk.k = color.m_values[3];
708 		getShadeColorCMYK(color, doc, cmyk, level);
709 		tmp = getDisplayColor(cmyk, doc, color.isSpotColor());
710 	}
711 	else if (color.getColorModel() == colorModelLab)
712 	{
713 		ScColorTransform trans  = doc ? doc->stdLabToScreenTrans : ScCore->defaultLabToRGBTrans;
714 		double inC[3];
715 		inC[0] = 100 - (100 - color.m_L_val) * (level / 100.0);
716 		inC[1] = color.m_a_val * (level / 100.0);
717 		inC[2] = color.m_b_val * (level / 100.0);
718 		quint16 outC[3];
719 		trans.apply(inC, outC, 1);
720 		tmp = QColor(outC[0] / 257, outC[1] / 257, outC[2] / 257);
721 	}
722 	return tmp;
723 }
724 
getDisplayColorGC(const ScColor & color,const ScribusDoc * doc,bool * outOfG)725 QColor ScColorEngine::getDisplayColorGC(const ScColor& color, const ScribusDoc* doc, bool *outOfG)
726 {
727 	QColor tmp;
728 	bool doSoftProofing = doc ? doc->SoftProofing : false;
729 	bool doGamutCheck   = doc ? doc->Gamut : false;
730 	if (doSoftProofing && doGamutCheck)
731 	{
732 		bool outOfGamutFlag = isOutOfGamut(color, doc);
733 		if (outOfG != nullptr)
734 			*outOfG = outOfGamutFlag;
735 		tmp = outOfGamutFlag ? QColor(0, 255, 0) : getDisplayColor(color, doc);
736 	}
737 	else
738 		tmp = getDisplayColor(color, doc);
739 	return tmp;
740 }
741 
getColorProof(const ScColor & color,const ScribusDoc * doc,bool gamutCheck)742 QColor ScColorEngine::getColorProof(const ScColor& color, const ScribusDoc* doc, bool gamutCheck)
743 {
744 	QColor tmp;
745 	bool gamutChkEnabled = doc ? doc->Gamut : false;
746 	bool spot = color.isSpotColor();
747 	if (color.getColorModel() == colorModelRGB)
748 	{
749 		// Match 133x behavior (RGB greys map to cmyk greys) until we are able to make rgb profiled output
750 		if (color.m_values[0] == color.m_values[1] && color.m_values[1] == color.m_values[2])
751 			gamutChkEnabled = false;
752 		RGBColor rgb;
753 		rgb.r = qRound(color.m_values[0] * 255.0);
754 		rgb.g = qRound(color.m_values[1] * 255.0);
755 		rgb.b = qRound(color.m_values[2] * 255.0);
756 		tmp = getColorProof(rgb, doc, spot, gamutCheck & gamutChkEnabled);
757 	}
758 	else
759 	{
760 		CMYKColor cmyk;
761 		cmyk.c = qRound(color.m_values[0] * 255.0);
762 		cmyk.m = qRound(color.m_values[1] * 255.0);
763 		cmyk.y = qRound(color.m_values[2] * 255.0);
764 		cmyk.k = qRound(color.m_values[3] * 255.0);
765 		tmp = getColorProof(cmyk, doc, spot, gamutCheck & gamutChkEnabled);
766 	}
767 	return tmp;
768 }
769 
getShadeColor(const ScColor & color,const ScribusDoc * doc,double level)770 QColor ScColorEngine::getShadeColor(const ScColor& color, const ScribusDoc* doc, double level)
771 {
772 	RGBColor rgb;
773 	rgb.r = qRound(color.m_values[0] * 255.0);
774 	rgb.g = qRound(color.m_values[1] * 255.0);
775 	rgb.b = qRound(color.m_values[2] * 255.0);
776 	getShadeColorRGB(color, doc, rgb, level);
777 	return QColor(rgb.r, rgb.g, rgb.b);
778 }
779 
getShadeColorProof(const ScColor & color,const ScribusDoc * doc,double level)780 QColor ScColorEngine::getShadeColorProof(const ScColor& color, const ScribusDoc* doc, double level)
781 {
782 	QColor tmp;
783 	bool doGC = doc ? doc->Gamut : false;
784 	bool cmsUse = doc ? doc->HasCMS : false;
785 	bool softProof = doc ? doc->SoftProofing : false;
786 
787 	if (color.getColorModel() == colorModelRGB)
788 	{
789 		RGBColorF rgb;
790 		rgb.r = color.m_values[0];
791 		rgb.g = color.m_values[1];
792 		rgb.b = color.m_values[2];
793 		getShadeColorRGB(color, doc, rgb, level);
794 		// Match 133x behavior for rgb grey until we are able to make rgb profiled output
795 		// (RGB greys map to cmyk greys)
796 		if ((cmsUse && softProof) && (rgb.r == rgb.g && rgb.g == rgb.b))
797 		{
798 			doGC = false;
799 			CMYKColorF cmyk;
800 			cmyk.c = cmyk.m = cmyk.y = 0;
801 			cmyk.k = 1.0 - rgb.g;
802 			tmp = getColorProof(cmyk, doc, color.isSpotColor(), doGC);
803 		}
804 		else
805 			tmp = getColorProof(rgb, doc, color.isSpotColor(), doGC);
806 	}
807 	else if (color.getColorModel() == colorModelCMYK)
808 	{
809 		CMYKColorF cmyk;
810 		cmyk.c = color.m_values[0];
811 		cmyk.m = color.m_values[1];
812 		cmyk.y = color.m_values[2];
813 		cmyk.k = color.m_values[3];
814 		getShadeColorCMYK(color, doc, cmyk, level);
815 		tmp = getColorProof(cmyk, doc, color.isSpotColor(), doGC);
816 	}
817 	else if (color.getColorModel() == colorModelLab)
818 	{
819 		double inC[3];
820 		inC[0] = 100 - (100 - color.m_L_val) * (level / 100.0);
821 		inC[1] = color.m_a_val * (level / 100.0);
822 		inC[2] = color.m_b_val * (level / 100.0);
823 		quint16 outC[3];
824 		ScColorTransform trans  = doc ? doc->stdLabToScreenTrans : ScCore->defaultLabToRGBTrans;
825 		ScColorTransform transProof   = doc ? doc->stdProofLab   : ScCore->defaultLabToRGBTrans;
826 		ScColorTransform transProofGC = doc ? doc->stdProofLabGC : ScCore->defaultLabToRGBTrans;
827 		if (cmsUse && doc && doc->SoftProofing)
828 		{
829 			ScColorTransform xform = doGC ? transProofGC : transProof;
830 			xform.apply(inC, outC, 1);
831 			tmp = QColor(outC[0] / 257, outC[1] / 257, outC[2] / 257);
832 		}
833 		else
834 		{
835 			trans.apply(inC, outC, 1);
836 			tmp = QColor(outC[0] / 257, outC[1] / 257, outC[2] / 257);
837 		}
838 	}
839 
840 	return tmp;
841 }
842 
getColorProof(RGBColor & rgb,const ScribusDoc * doc,bool spot,bool gamutCkeck)843 QColor ScColorEngine::getColorProof(RGBColor& rgb, const ScribusDoc* doc, bool spot, bool gamutCkeck)
844 {
845 	unsigned short inC[4];
846 	unsigned short outC[4];
847 	int  r = rgb.r, g = rgb.g, b = rgb.b;
848 	ScColorTransform transRGBMon  = doc ? doc->stdTransRGBMon : ScCore->defaultRGBToScreenSolidTrans;
849 	ScColorTransform transProof   = doc ? doc->stdProof   : ScCore->defaultRGBToScreenSolidTrans;
850 	ScColorTransform transProofGC = doc ? doc->stdProofGC : ScCore->defaultRGBToScreenSolidTrans;
851 	bool cmsUse   = doc ? doc->HasCMS : false;
852 	bool cmsTrans = (transRGBMon && transProof && transProofGC);
853 	if (ScCore->haveCMS() && cmsTrans)
854 	{
855 		inC[0] = rgb.r * 257;
856 		inC[1] = rgb.g * 257;
857 		inC[2] = rgb.b * 257;
858 		if (cmsUse && !spot && doc->SoftProofing)
859 		{
860 			ScColorTransform xform = gamutCkeck ? transProofGC : transProof;
861 			xform.apply(inC, outC, 1);
862 			r = outC[0] / 257;
863 			g = outC[1] / 257;
864 			b = outC[2] / 257;
865 		}
866 		else
867 		{
868 			transRGBMon.apply(inC, outC, 1);
869 			r = outC[0] / 257;
870 			g = outC[1] / 257;
871 			b = outC[2] / 257;
872 		}
873 	}
874 	return QColor(r, g, b);
875 }
876 
getColorProof(RGBColorF & rgb,const ScribusDoc * doc,bool spot,bool gamutCkeck)877 QColor ScColorEngine::getColorProof(RGBColorF& rgb, const ScribusDoc* doc, bool spot, bool gamutCkeck)
878 {
879 	unsigned short inC[4];
880 	unsigned short outC[4];
881 	int r = qRound(rgb.r * 255.0);
882 	int g = qRound(rgb.g * 255.0);
883 	int b = qRound(rgb.b * 255.0);
884 	ScColorTransform transRGBMon  = doc ? doc->stdTransRGBMon : ScCore->defaultRGBToScreenSolidTrans;
885 	ScColorTransform transProof   = doc ? doc->stdProof   : ScCore->defaultRGBToScreenSolidTrans;
886 	ScColorTransform transProofGC = doc ? doc->stdProofGC : ScCore->defaultRGBToScreenSolidTrans;
887 	bool cmsUse   = doc ? doc->HasCMS : false;
888 	bool cmsTrans = (transRGBMon && transProof && transProofGC);
889 	if (ScCore->haveCMS() && cmsTrans)
890 	{
891 		inC[0] = rgb.r * 65535.0;
892 		inC[1] = rgb.g * 65535.0;
893 		inC[2] = rgb.b * 65535.0;
894 		if (cmsUse && !spot && doc->SoftProofing)
895 		{
896 			ScColorTransform xform = gamutCkeck ? transProofGC : transProof;
897 			xform.apply(inC, outC, 1);
898 			r = outC[0] / 257;
899 			g = outC[1] / 257;
900 			b = outC[2] / 257;
901 		}
902 		else
903 		{
904 			transRGBMon.apply(inC, outC, 1);
905 			r = outC[0] / 257;
906 			g = outC[1] / 257;
907 			b = outC[2] / 257;
908 		}
909 	}
910 	return QColor(r, g, b);
911 }
912 
getColorProof(CMYKColor & cmyk,const ScribusDoc * doc,bool spot,bool gamutCkeck)913 QColor ScColorEngine::getColorProof(CMYKColor& cmyk, const ScribusDoc* doc, bool spot, bool gamutCkeck)
914 {
915 	int  r = 0, g = 0, b = 0;
916 	unsigned short inC[4];
917 	unsigned short outC[4];
918 	ScColorTransform transCMYKMon     = doc ? doc->stdTransCMYKMon : ScCore->defaultCMYKToRGBTrans;
919 	ScColorTransform transProofCMYK   = doc ? doc->stdProofCMYK   : ScCore->defaultCMYKToRGBTrans;
920 	ScColorTransform transProofCMYKGC = doc ? doc->stdProofCMYKGC : ScCore->defaultCMYKToRGBTrans;
921 	bool cmsUse   = doc ? doc->HasCMS : false;
922 	bool cmsTrans = (transCMYKMon && transProofCMYK && transProofCMYKGC);
923 	if (ScCore->haveCMS() && cmsTrans)
924 	{
925 		inC[0] = cmyk.c * 257;
926 		inC[1] = cmyk.m * 257;
927 		inC[2] = cmyk.y * 257;
928 		inC[3] = cmyk.k * 257;
929 		if (cmsUse && !spot && doc->SoftProofing)
930 		{
931 			ScColorTransform xform = gamutCkeck ? transProofCMYKGC : transProofCMYK;
932 			xform.apply(inC, outC, 1);
933 			r = outC[0] / 257;
934 			g = outC[1] / 257;
935 			b = outC[2] / 257;
936 		}
937 		else
938 		{
939 			transCMYKMon.apply(inC, outC, 1);
940 			r = outC[0] / 257;
941 			g = outC[1] / 257;
942 			b = outC[2] / 257;
943 		}
944 	}
945 	else
946 	{
947 		r = 255 - qMin(255, cmyk.c + cmyk.k);
948 		g = 255 - qMin(255, cmyk.m + cmyk.k);
949 		b = 255 - qMin(255, cmyk.y + cmyk.k);
950 	}
951 	return QColor(r, g, b);
952 }
953 
getColorProof(CMYKColorF & cmyk,const ScribusDoc * doc,bool spot,bool gamutCkeck)954 QColor ScColorEngine::getColorProof(CMYKColorF& cmyk, const ScribusDoc* doc, bool spot, bool gamutCkeck)
955 {
956 	int  r = 0, g = 0, b = 0;
957 	unsigned short inC[4];
958 	unsigned short outC[4];
959 	ScColorTransform transCMYKMon     = doc ? doc->stdTransCMYKMon : ScCore->defaultCMYKToRGBTrans;
960 	ScColorTransform transProofCMYK   = doc ? doc->stdProofCMYK   : ScCore->defaultCMYKToRGBTrans;
961 	ScColorTransform transProofCMYKGC = doc ? doc->stdProofCMYKGC : ScCore->defaultCMYKToRGBTrans;
962 	bool cmsUse   = doc ? doc->HasCMS : false;
963 	bool cmsTrans = (transCMYKMon && transProofCMYK && transProofCMYKGC);
964 	if (ScCore->haveCMS() && cmsTrans)
965 	{
966 		inC[0] = cmyk.c * 65535.0;
967 		inC[1] = cmyk.m * 65535.0;
968 		inC[2] = cmyk.y * 65535.0;
969 		inC[3] = cmyk.k * 65535.0;
970 		if (cmsUse && !spot && doc->SoftProofing)
971 		{
972 			ScColorTransform xform = gamutCkeck ? transProofCMYKGC : transProofCMYK;
973 			xform.apply(inC, outC, 1);
974 			r = outC[0] / 257;
975 			g = outC[1] / 257;
976 			b = outC[2] / 257;
977 		}
978 		else
979 		{
980 			transCMYKMon.apply(inC, outC, 1);
981 			r = outC[0] / 257;
982 			g = outC[1] / 257;
983 			b = outC[2] / 257;
984 		}
985 	}
986 	else
987 	{
988 		r = 255 - qMin(255, qRound((cmyk.c + cmyk.k) * 255.0));
989 		g = 255 - qMin(255, qRound((cmyk.m + cmyk.k) * 255.0));
990 		b = 255 - qMin(255, qRound((cmyk.y + cmyk.k) * 255.0));
991 	}
992 	return QColor(r, g, b);
993 }
994 
getDisplayColor(RGBColor & rgb,const ScribusDoc * doc,bool spot)995 QColor ScColorEngine::getDisplayColor(RGBColor& rgb, const ScribusDoc* doc, bool spot)
996 {
997 	unsigned short inC[4];
998 	unsigned short outC[4];
999 	int r = rgb.r;
1000 	int g = rgb.g;
1001 	int b = rgb.b;
1002 	ScColorTransform transRGBMon = doc ? doc->stdTransRGBMon : ScCore->defaultRGBToScreenSolidTrans;
1003 	if (ScCore->haveCMS() && transRGBMon)
1004 	{
1005 		inC[0] = r * 257;
1006 		inC[1] = g * 257;
1007 		inC[2] = b * 257;
1008 		transRGBMon.apply(inC, outC, 1);
1009 		r = outC[0] / 257;
1010 		g = outC[1] / 257;
1011 		b = outC[2] / 257;
1012 	}
1013 	return QColor(r, g, b);
1014 }
1015 
getDisplayColor(RGBColorF & rgb,const ScribusDoc * doc,bool spot)1016 QColor ScColorEngine::getDisplayColor(RGBColorF& rgb, const ScribusDoc* doc, bool spot)
1017 {
1018 	unsigned short inC[4];
1019 	unsigned short outC[4];
1020 	int r = rgb.r * 255.0;
1021 	int g = rgb.g * 255.0;
1022 	int b = rgb.b * 255.0;
1023 	ScColorTransform transRGBMon = doc ? doc->stdTransRGBMon : ScCore->defaultRGBToScreenSolidTrans;
1024 	if (ScCore->haveCMS() && transRGBMon)
1025 	{
1026 		inC[0] = rgb.r * 65535.0;
1027 		inC[1] = rgb.g * 65535.0;
1028 		inC[2] = rgb.b * 65535.0;
1029 		transRGBMon.apply(inC, outC, 1);
1030 		r = outC[0] / 257;
1031 		g = outC[1] / 257;
1032 		b = outC[2] / 257;
1033 	}
1034 	return QColor(r, g, b);
1035 }
1036 
getDisplayColor(CMYKColor & cmyk,const ScribusDoc * doc,bool spot)1037 QColor ScColorEngine::getDisplayColor(CMYKColor& cmyk, const ScribusDoc* doc, bool spot)
1038 {
1039 	int  r = 0, g = 0, b = 0;
1040 	unsigned short inC[4];
1041 	unsigned short outC[4];
1042 	ScColorTransform transCMYKMon = doc ? doc->stdTransCMYKMon : ScCore->defaultCMYKToRGBTrans;
1043 	if (ScCore->haveCMS() && transCMYKMon)
1044 	{
1045 		inC[0] = cmyk.c * 257;
1046 		inC[1] = cmyk.m * 257;
1047 		inC[2] = cmyk.y * 257;
1048 		inC[3] = cmyk.k * 257;
1049 		transCMYKMon.apply(inC, outC, 1);
1050 		r = outC[0] / 257;
1051 		g = outC[1] / 257;
1052 		b = outC[2] / 257;
1053 	}
1054 	else
1055 	{
1056 		r = 255 - qMin(255, cmyk.c + cmyk.k);
1057 		g = 255 - qMin(255, cmyk.m + cmyk.k);
1058 		b = 255 - qMin(255, cmyk.y + cmyk.k);
1059 	}
1060 	return QColor(r, g, b);
1061 }
1062 
getDisplayColor(CMYKColorF & cmyk,const ScribusDoc * doc,bool spot)1063 QColor ScColorEngine::getDisplayColor(CMYKColorF& cmyk, const ScribusDoc* doc, bool spot)
1064 {
1065 	int  r = 0, g = 0, b = 0;
1066 	unsigned short inC[4];
1067 	unsigned short outC[4];
1068 	ScColorTransform transCMYKMon = doc ? doc->stdTransCMYKMon : ScCore->defaultCMYKToRGBTrans;
1069 	if (ScCore->haveCMS() && transCMYKMon)
1070 	{
1071 		inC[0] = cmyk.c * 65535.0;
1072 		inC[1] = cmyk.m * 65535.0;
1073 		inC[2] = cmyk.y * 65535.0;
1074 		inC[3] = cmyk.k * 65535.0;
1075 		transCMYKMon.apply(inC, outC, 1);
1076 		r = outC[0] / 257;
1077 		g = outC[1] / 257;
1078 		b = outC[2] / 257;
1079 	}
1080 	else
1081 	{
1082 		r = 255 - qMin(255, qRound((cmyk.c + cmyk.k) * 255.0));
1083 		g = 255 - qMin(255, qRound((cmyk.m + cmyk.k) * 255.0));
1084 		b = 255 - qMin(255, qRound((cmyk.y + cmyk.k) * 255.0));
1085 	}
1086 	return QColor(r, g, b);
1087 }
1088 
isOutOfGamut(const ScColor & color,const ScribusDoc * doc)1089 bool ScColorEngine::isOutOfGamut(const ScColor& color, const ScribusDoc* doc)
1090 {
1091 	bool outOfGamutFlag = false;
1092 	if (color.isSpotColor())
1093 		return false;
1094 	unsigned short inC[4];
1095 	unsigned short outC[4];
1096 	bool cmsUse = doc ? doc->HasCMS : false;
1097 	if (ScCore->haveCMS() && cmsUse)
1098 	{
1099 		bool alert = true;
1100 		ScColorTransform xformProof;
1101 		if (color.getColorModel() == colorModelRGB)
1102 		{
1103 			inC[0] = qRound(color.m_values[0] * 65535.0);
1104 			inC[1] = qRound(color.m_values[1] * 65535.0);
1105 			inC[2] = qRound(color.m_values[2] * 65535.0);
1106 			xformProof = doc->stdProofGC;
1107 			if ((color.m_values[0] == 0) && (color.m_values[1] == 0) && (color.m_values[2] == 1.0))
1108 				alert = false;
1109 			if ((color.m_values[0] == color.m_values[1] && color.m_values[1] == color.m_values[2]))
1110 				alert = false;
1111 		}
1112 		else if (color.getColorModel() == colorModelCMYK)
1113 		{
1114 			inC[0] = qRound(color.m_values[0] * 65535.0);
1115 			inC[1] = qRound(color.m_values[1] * 65535.0);
1116 			inC[2] = qRound(color.m_values[2] * 65535.0);
1117 			inC[3] = qRound(color.m_values[3] * 65535.0);
1118 			xformProof = doc->stdProofCMYKGC;
1119 			if ((color.m_values[0] == 1.0) && (color.m_values[1] == 0) && (color.m_values[3] == 0) && (color.m_values[2] == 1.0))
1120 				alert = false;
1121 			if ((color.m_values[0] == 0.0) && (color.m_values[1] == 0) && (color.m_values[2] == 0))
1122 				alert = false;
1123 			if ((color.m_values[0] == color.m_values[1]) && (color.m_values[0] == color.m_values[2]) && (color.m_values[2] == color.m_values[3]))
1124 				alert = false;
1125 		}
1126 		else if (color.getColorModel() == colorModelLab)
1127 		{
1128 			double inC[3];
1129 			inC[0] = color.m_L_val;
1130 			inC[1] = color.m_a_val;
1131 			inC[2] = color.m_b_val;
1132 			xformProof = doc->stdProofLabGC;
1133 			xformProof.apply(inC, outC, 1);
1134 			if ((outC[0]/257 == 0) && (outC[1]/257 == 255) && (outC[2]/257 == 0))
1135 				outOfGamutFlag = true;
1136 			alert = false;
1137 		}
1138 		if (alert)
1139 		{
1140 			xformProof.apply(inC, outC, 1);
1141 			if ((outC[0]/257 == 0) && (outC[1]/257 == 255) && (outC[2]/257 == 0))
1142 				outOfGamutFlag = true;
1143 		}
1144 	}
1145 	return outOfGamutFlag;
1146 }
1147 
applyGCR(ScColor & color,const ScribusDoc * doc)1148 void ScColorEngine::applyGCR(ScColor& color, const ScribusDoc* doc)
1149 {
1150 	bool cmsUse = doc ? doc->HasCMS : false;
1151 	if (!(ScCore->haveCMS() && cmsUse) && (color.getColorModel() != colorModelLab))
1152 	{
1153 		CMYKColor cmyk;
1154 		getCMYKValues(color, doc, cmyk);
1155 		int k = qMin(qMin(cmyk.c, cmyk.m), cmyk.y);
1156 		color.m_values[0] = (cmyk.c - k) / 255.0;
1157 		color.m_values[1] = (cmyk.m - k) / 255.0;
1158 		color.m_values[2] = (cmyk.y - k) / 255.0;
1159 		color.m_values[3] = qMin((cmyk.k + k) / 255.0, 1.0);
1160 	}
1161 }
1162