1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../../include/fpdfapi/fpdf_page.h"
8 #include "../../../include/fpdfapi/fpdf_module.h"
9 #include "../../../include/fxcodec/fx_codec.h"
10 #include "pageint.h"
11 #include <limits.h>
sRGB_to_AdobeCMYK(FX_FLOAT R,FX_FLOAT G,FX_FLOAT B,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k)12 void sRGB_to_AdobeCMYK(FX_FLOAT R, FX_FLOAT G, FX_FLOAT B, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k)
13 {
14 c = 1.0f - R;
15 m = 1.0f - G;
16 y = 1.0f - B;
17 k = c;
18 if (m < k) {
19 k = m;
20 }
21 if (y < k) {
22 k = y;
23 }
24 }
CPDF_DeviceCS(int family)25 CPDF_DeviceCS::CPDF_DeviceCS(int family)
26 {
27 m_Family = family;
28 if (m_Family == PDFCS_DEVICERGB) {
29 m_nComponents = 3;
30 } else if (m_Family == PDFCS_DEVICEGRAY) {
31 m_nComponents = 1;
32 } else {
33 m_nComponents = 4;
34 }
35 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const36 FX_BOOL CPDF_DeviceCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
37 {
38 if (m_Family == PDFCS_DEVICERGB) {
39 R = pBuf[0];
40 if (R < 0) {
41 R = 0;
42 } else if (R > 1) {
43 R = 1;
44 }
45 G = pBuf[1];
46 if (G < 0) {
47 G = 0;
48 } else if (G > 1) {
49 G = 1;
50 }
51 B = pBuf[2];
52 if (B < 0) {
53 B = 0;
54 } else if (B > 1) {
55 B = 1;
56 }
57 } else if (m_Family == PDFCS_DEVICEGRAY) {
58 R = *pBuf;
59 if (R < 0) {
60 R = 0;
61 } else if (R > 1) {
62 R = 1;
63 }
64 G = B = R;
65 } else if (m_Family == PDFCS_DEVICECMYK) {
66 if (!m_dwStdConversion) {
67 AdobeCMYK_to_sRGB(pBuf[0], pBuf[1], pBuf[2], pBuf[3], R, G, B);
68 } else {
69 FX_FLOAT k = pBuf[3];
70 R = 1.0f - FX_MIN(1.0f, pBuf[0] + k);
71 G = 1.0f - FX_MIN(1.0f, pBuf[1] + k);
72 B = 1.0f - FX_MIN(1.0f, pBuf[2] + k);
73 }
74 } else {
75 ASSERT(m_Family == PDFCS_PATTERN);
76 R = G = B = 0;
77 return FALSE;
78 }
79 return TRUE;
80 }
v_GetCMYK(FX_FLOAT * pBuf,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k) const81 FX_BOOL CPDF_DeviceCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
82 {
83 if (m_Family != PDFCS_DEVICECMYK) {
84 return FALSE;
85 }
86 c = pBuf[0];
87 m = pBuf[1];
88 y = pBuf[2];
89 k = pBuf[3];
90 return TRUE;
91 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const92 FX_BOOL CPDF_DeviceCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
93 {
94 if (m_Family == PDFCS_DEVICERGB) {
95 pBuf[0] = R;
96 pBuf[1] = G;
97 pBuf[2] = B;
98 return TRUE;
99 } else if (m_Family == PDFCS_DEVICEGRAY) {
100 if (R == G && R == B) {
101 *pBuf = R;
102 return TRUE;
103 } else {
104 return FALSE;
105 }
106 } else if (m_Family == PDFCS_DEVICECMYK) {
107 sRGB_to_AdobeCMYK(R, G, B, pBuf[0], pBuf[1], pBuf[2], pBuf[3]);
108 return TRUE;
109 }
110 return FALSE;
111 }
v_SetCMYK(FX_FLOAT * pBuf,FX_FLOAT c,FX_FLOAT m,FX_FLOAT y,FX_FLOAT k) const112 FX_BOOL CPDF_DeviceCS::v_SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const
113 {
114 if (m_Family == PDFCS_DEVICERGB) {
115 AdobeCMYK_to_sRGB(c, m, y, k, pBuf[0], pBuf[1], pBuf[2]);
116 return TRUE;
117 } else if (m_Family == PDFCS_DEVICEGRAY) {
118 return FALSE;
119 } else if (m_Family == PDFCS_DEVICECMYK) {
120 pBuf[0] = c;
121 pBuf[1] = m;
122 pBuf[2] = y;
123 pBuf[3] = k;
124 return TRUE;
125 }
126 return FALSE;
127 }
ReverseRGB(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels)128 static void ReverseRGB(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels)
129 {
130 if (pDestBuf == pSrcBuf)
131 for (int i = 0; i < pixels; i ++) {
132 FX_BYTE temp = pDestBuf[2];
133 pDestBuf[2] = pDestBuf[0];
134 pDestBuf[0] = temp;
135 pDestBuf += 3;
136 }
137 else
138 for (int i = 0; i < pixels; i ++) {
139 *pDestBuf ++ = pSrcBuf[2];
140 *pDestBuf ++ = pSrcBuf[1];
141 *pDestBuf ++ = pSrcBuf[0];
142 pSrcBuf += 3;
143 }
144 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const145 void CPDF_DeviceCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
146 {
147 if (bTransMask && m_Family == PDFCS_DEVICECMYK) {
148 for (int i = 0; i < pixels; i ++) {
149 int k = 255 - pSrcBuf[3];
150 pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255;
151 pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255;
152 pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255;
153 pDestBuf += 3;
154 pSrcBuf += 4;
155 }
156 return;
157 }
158 if (m_Family == PDFCS_DEVICERGB) {
159 ReverseRGB(pDestBuf, pSrcBuf, pixels);
160 } else if (m_Family == PDFCS_DEVICEGRAY) {
161 for (int i = 0; i < pixels; i ++) {
162 *pDestBuf ++ = pSrcBuf[i];
163 *pDestBuf ++ = pSrcBuf[i];
164 *pDestBuf ++ = pSrcBuf[i];
165 }
166 } else {
167 for (int i = 0; i < pixels; i ++) {
168 if (!m_dwStdConversion) {
169 AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2], pSrcBuf[3], pDestBuf[2], pDestBuf[1], pDestBuf[0]);
170 } else {
171 FX_BYTE k = pSrcBuf[3];
172 pDestBuf[2] = 255 - FX_MIN(255, pSrcBuf[0] + k);
173 pDestBuf[1] = 255 - FX_MIN(255, pSrcBuf[1] + k);
174 pDestBuf[0] = 255 - FX_MIN(255, pSrcBuf[2] + k);
175 }
176 pSrcBuf += 4;
177 pDestBuf += 3;
178 }
179 }
180 }
181 const FX_BYTE g_sRGBSamples1[] = {
182 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31, 32,
183 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
184 49, 50, 51, 52, 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61,
185 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 67, 68, 68, 69, 70, 70,
186 71, 71, 72, 72, 73, 73, 74, 74, 75, 76, 76, 77, 77, 78, 78, 79,
187 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 85, 86,
188 86, 87, 87, 88, 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, 92, 93,
189 93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 97, 97, 98, 98, 98, 99,
190 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104,
191 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110,
192 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115,
193 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120,
194 };
195 const FX_BYTE g_sRGBSamples2[] = {
196 120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
197 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151,
198 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164,
199 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 175, 176,
200 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184, 185, 185, 186, 187, 187,
201 188, 189, 189, 190, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 197,
202 198, 199, 199, 200, 200, 201, 202, 202, 203, 203, 204, 205, 205, 206, 206, 207,
203 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216,
204 216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
205 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
206 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240,
207 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248,
208 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
209 };
XYZ_to_sRGB(FX_FLOAT X,FX_FLOAT Y,FX_FLOAT Z,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B)210 static void XYZ_to_sRGB(FX_FLOAT X, FX_FLOAT Y, FX_FLOAT Z, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B)
211 {
212 FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
213 FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
214 FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
215 if (R1 > 1) {
216 R1 = 1;
217 }
218 if (R1 < 0) {
219 R1 = 0;
220 }
221 if (G1 > 1) {
222 G1 = 1;
223 }
224 if (G1 < 0) {
225 G1 = 0;
226 }
227 if (B1 > 1) {
228 B1 = 1;
229 }
230 if (B1 < 0) {
231 B1 = 0;
232 }
233 int scale = (int)(R1 * 1023);
234 if (scale < 0) {
235 scale = 0;
236 }
237 if (scale < 192) {
238 R = (g_sRGBSamples1[scale] / 255.0f);
239 } else {
240 R = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
241 }
242 scale = (int)(G1 * 1023);
243 if (scale < 0) {
244 scale = 0;
245 }
246 if (scale < 192) {
247 G = (g_sRGBSamples1[scale] / 255.0f);
248 } else {
249 G = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
250 }
251 scale = (int)(B1 * 1023);
252 if (scale < 0) {
253 scale = 0;
254 }
255 if (scale < 192) {
256 B = (g_sRGBSamples1[scale] / 255.0f);
257 } else {
258 B = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
259 }
260 }
261 class CPDF_CalGray : public CPDF_ColorSpace
262 {
263 public:
264 CPDF_CalGray();
265 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
266 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
267 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
268 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
269 FX_FLOAT m_WhitePoint[3];
270 FX_FLOAT m_BlackPoint[3];
271 FX_FLOAT m_Gamma;
272 };
CPDF_CalGray()273 CPDF_CalGray::CPDF_CalGray()
274 {
275 m_Family = PDFCS_CALGRAY;
276 m_nComponents = 1;
277 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)278 FX_BOOL CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
279 {
280 CPDF_Dictionary* pDict = pArray->GetDict(1);
281 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
282 int i;
283 for (i = 0; i < 3; i ++) {
284 m_WhitePoint[i] = pParam->GetNumber(i);
285 }
286 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
287 for (i = 0; i < 3; i ++) {
288 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
289 }
290 m_Gamma = pDict->GetNumber(FX_BSTRC("Gamma"));
291 if (m_Gamma == 0) {
292 m_Gamma = 1.0f;
293 }
294 return TRUE;
295 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const296 FX_BOOL CPDF_CalGray::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
297 {
298 R = G = B = *pBuf;
299 return TRUE;
300 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const301 FX_BOOL CPDF_CalGray::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
302 {
303 if (R == G && R == B) {
304 *pBuf = R;
305 return TRUE;
306 } else {
307 return FALSE;
308 }
309 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const310 void CPDF_CalGray::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
311 {
312 for (int i = 0; i < pixels; i ++) {
313 *pDestBuf ++ = pSrcBuf[i];
314 *pDestBuf ++ = pSrcBuf[i];
315 *pDestBuf ++ = pSrcBuf[i];
316 }
317 }
318 class CPDF_CalRGB : public CPDF_ColorSpace
319 {
320 public:
321 CPDF_CalRGB();
322 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
323 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
324 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
325 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
326 FX_FLOAT m_WhitePoint[3];
327 FX_FLOAT m_BlackPoint[3];
328 FX_FLOAT m_Gamma[3];
329 FX_FLOAT m_Matrix[9];
330 FX_BOOL m_bGamma, m_bMatrix;
331 };
CPDF_CalRGB()332 CPDF_CalRGB::CPDF_CalRGB()
333 {
334 m_Family = PDFCS_CALRGB;
335 m_nComponents = 3;
336 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)337 FX_BOOL CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
338 {
339 CPDF_Dictionary* pDict = pArray->GetDict(1);
340 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
341 int i;
342 for (i = 0; i < 3; i ++) {
343 m_WhitePoint[i] = pParam->GetNumber(i);
344 }
345 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
346 for (i = 0; i < 3; i ++) {
347 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
348 }
349 pParam = pDict->GetArray(FX_BSTRC("Gamma"));
350 if (pParam) {
351 m_bGamma = TRUE;
352 for (i = 0; i < 3; i ++) {
353 m_Gamma[i] = pParam->GetNumber(i);
354 }
355 } else {
356 m_bGamma = FALSE;
357 }
358 pParam = pDict->GetArray(FX_BSTRC("Matrix"));
359 if (pParam) {
360 m_bMatrix = TRUE;
361 for (i = 0; i < 9; i ++) {
362 m_Matrix[i] = pParam->GetNumber(i);
363 }
364 } else {
365 m_bMatrix = FALSE;
366 }
367 return TRUE;
368 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const369 FX_BOOL CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
370 {
371 FX_FLOAT A_ = pBuf[0];
372 FX_FLOAT B_ = pBuf[1];
373 FX_FLOAT C_ = pBuf[2];
374 if (m_bGamma) {
375 A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]);
376 B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]);
377 C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]);
378 }
379 FX_FLOAT X, Y, Z;
380 if (m_bMatrix) {
381 X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_;
382 Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_;
383 Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_;
384 } else {
385 X = A_;
386 Y = B_;
387 Z = C_;
388 }
389 XYZ_to_sRGB(X, Y, Z, R, G, B);
390 return TRUE;
391 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const392 FX_BOOL CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
393 {
394 pBuf[0] = R;
395 pBuf[1] = G;
396 pBuf[2] = B;
397 return TRUE;
398 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const399 void CPDF_CalRGB::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
400 {
401 if (bTransMask) {
402 FX_FLOAT Cal[3];
403 FX_FLOAT R, G, B;
404 for(int i = 0; i < pixels; i ++) {
405 Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255;
406 Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255;
407 Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255;
408 GetRGB(Cal, R, G, B);
409 pDestBuf[0] = FXSYS_round(B * 255);
410 pDestBuf[1] = FXSYS_round(G * 255);
411 pDestBuf[2] = FXSYS_round(R * 255);
412 pSrcBuf += 3;
413 pDestBuf += 3;
414 }
415 }
416 ReverseRGB(pDestBuf, pSrcBuf, pixels);
417 }
418 class CPDF_LabCS : public CPDF_ColorSpace
419 {
420 public:
CPDF_LabCS()421 CPDF_LabCS()
422 {
423 m_Family = PDFCS_LAB;
424 m_nComponents = 3;
425 }
426 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
427 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const;
428 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
429 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
430 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
431 FX_FLOAT m_WhitePoint[3];
432 FX_FLOAT m_BlackPoint[3];
433 FX_FLOAT m_Ranges[4];
434 };
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)435 FX_BOOL CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
436 {
437 CPDF_Dictionary* pDict = pArray->GetDict(1);
438 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
439 int i;
440 for (i = 0; i < 3; i ++) {
441 m_WhitePoint[i] = pParam->GetNumber(i);
442 }
443 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
444 for (i = 0; i < 3; i ++) {
445 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
446 }
447 pParam = pDict->GetArray(FX_BSTRC("Range"));
448 const FX_FLOAT def_ranges[4] = { -100 * 1.0f, 100 * 1.0f, -100 * 1.0f, 100 * 1.0f};
449 for (i = 0; i < 4; i ++) {
450 m_Ranges[i] = pParam ? pParam->GetNumber(i) : def_ranges[i];
451 }
452 return TRUE;
453 }
GetDefaultValue(int iComponent,FX_FLOAT & value,FX_FLOAT & min,FX_FLOAT & max) const454 void CPDF_LabCS::GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
455 {
456 value = 0;
457 if (iComponent == 0) {
458 min = 0;
459 max = 100 * 1.0f;
460 } else {
461 min = m_Ranges[iComponent * 2 - 2];
462 max = m_Ranges[iComponent * 2 - 1];
463 if (value < min) {
464 value = min;
465 } else if (value > max) {
466 value = max;
467 }
468 }
469 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const470 FX_BOOL CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
471 {
472 FX_FLOAT Lstar = pBuf[0];
473 FX_FLOAT astar = pBuf[1];
474 FX_FLOAT bstar = pBuf[2];
475 FX_FLOAT M = (Lstar + 16.0f) / 116.0f;
476 FX_FLOAT L = M + astar / 500.0f;
477 FX_FLOAT N = M - bstar / 200.0f;
478 FX_FLOAT X, Y, Z;
479 if (L < 0.2069f) {
480 X = 0.957f * 0.12842f * (L - 0.1379f);
481 } else {
482 X = 0.957f * L * L * L;
483 }
484 if (M < 0.2069f) {
485 Y = 0.12842f * (M - 0.1379f);
486 } else {
487 Y = M * M * M;
488 }
489 if (N < 0.2069f) {
490 Z = 1.0889f * 0.12842f * (N - 0.1379f);
491 } else {
492 Z = 1.0889f * N * N * N;
493 }
494 XYZ_to_sRGB(X, Y, Z, R, G, B);
495 return TRUE;
496 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const497 FX_BOOL CPDF_LabCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
498 {
499 return FALSE;
500 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const501 void CPDF_LabCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
502 {
503 for (int i = 0; i < pixels; i ++) {
504 FX_FLOAT lab[3];
505 FX_FLOAT R, G, B;
506 lab[0] = (pSrcBuf[0] * 100 / 255.0f);
507 lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128);
508 lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128);
509 GetRGB(lab, R, G, B);
510 pDestBuf[0] = (FX_INT32)(B * 255);
511 pDestBuf[1] = (FX_INT32)(G * 255);
512 pDestBuf[2] = (FX_INT32)(R * 255);
513 pDestBuf += 3;
514 pSrcBuf += 3;
515 }
516 }
CPDF_IccProfile(FX_LPCBYTE pData,FX_DWORD dwSize,int nComponents)517 CPDF_IccProfile::CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize, int nComponents)
518 {
519 m_bsRGB = nComponents == 3 && dwSize == 3144 && FXSYS_memcmp32(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0;
520 m_pTransform = NULL;
521 if (!m_bsRGB && CPDF_ModuleMgr::Get()->GetIccModule()) {
522 m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(pData, dwSize, nComponents);
523 }
524 }
~CPDF_IccProfile()525 CPDF_IccProfile::~CPDF_IccProfile()
526 {
527 if (m_pTransform) {
528 CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform);
529 }
530 }
531 class CPDF_ICCBasedCS : public CPDF_ColorSpace
532 {
533 public:
534 CPDF_ICCBasedCS();
535 virtual ~CPDF_ICCBasedCS();
536 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
GetDefaultValue(int i,FX_FLOAT & min,FX_FLOAT & max) const537 void GetDefaultValue(int i, FX_FLOAT& min, FX_FLOAT& max) const
538 {
539 min = m_pRanges[i * 2];
540 max = m_pRanges[i * 2 + 1];
541 }
542 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
543 FX_BOOL v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const;
544 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
545 virtual void EnableStdConversion(FX_BOOL bEnabled);
546 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
547 FX_FLOAT* m_pRanges;
548 CPDF_IccProfile* m_pProfile;
549 CPDF_ColorSpace* m_pAlterCS;
550 FX_LPBYTE m_pCache;
551 FX_BOOL m_bOwn;
552 };
CPDF_ICCBasedCS()553 CPDF_ICCBasedCS::CPDF_ICCBasedCS()
554 {
555 m_pAlterCS = NULL;
556 m_pProfile = NULL;
557 m_Family = PDFCS_ICCBASED;
558 m_pCache = NULL;
559 m_pRanges = NULL;
560 m_bOwn = FALSE;
561 }
~CPDF_ICCBasedCS()562 CPDF_ICCBasedCS::~CPDF_ICCBasedCS()
563 {
564 if (m_pCache) {
565 FX_Free(m_pCache);
566 }
567 if (m_pRanges) {
568 FX_Free(m_pRanges);
569 }
570 if (m_pAlterCS && m_bOwn) {
571 m_pAlterCS->ReleaseCS();
572 }
573 if (m_pProfile && m_pDocument) {
574 m_pDocument->GetPageData()->ReleaseIccProfile(NULL, m_pProfile);
575 }
576 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)577 FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
578 {
579 CPDF_Stream* pStream = pArray->GetStream(1);
580 if (pStream == NULL) {
581 return FALSE;
582 }
583 m_nComponents = pStream->GetDict()->GetInteger(FX_BSTRC("N"));
584 if (m_nComponents < 0 || m_nComponents > (1 << 16)) {
585 return FALSE;
586 }
587 CPDF_Array* pRanges = pStream->GetDict()->GetArray(FX_BSTRC("Range"));
588 m_pRanges = FX_Alloc(FX_FLOAT, m_nComponents * 2);
589 for (int i = 0; i < m_nComponents * 2; i ++) {
590 if (pRanges) {
591 m_pRanges[i] = pRanges->GetNumber(i);
592 } else if (i % 2) {
593 m_pRanges[i] = 1.0f;
594 } else {
595 m_pRanges[i] = 0;
596 }
597 }
598 m_pProfile = pDoc->LoadIccProfile(pStream, m_nComponents);
599 if (!m_pProfile) {
600 return FALSE;
601 }
602 if (m_pProfile->m_pTransform == NULL) {
603 CPDF_Object* pAlterCSObj = pStream->GetDict()->GetElementValue(FX_BSTRC("Alternate"));
604 if (pAlterCSObj) {
605 CPDF_ColorSpace* alter_cs = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
606 if (alter_cs) {
607 if (alter_cs->CountComponents() > m_nComponents) {
608 alter_cs->ReleaseCS();
609 } else {
610 m_pAlterCS = alter_cs;
611 m_bOwn = TRUE;
612 }
613 }
614 }
615 if (!m_pAlterCS) {
616 if (m_nComponents == 3) {
617 m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
618 } else if (m_nComponents == 4) {
619 m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
620 } else {
621 m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
622 }
623 }
624 }
625 return TRUE;
626 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const627 FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
628 {
629 if (m_pProfile && m_pProfile->m_bsRGB) {
630 R = pBuf[0];
631 G = pBuf[1];
632 B = pBuf[2];
633 return TRUE;
634 }
635 ICodec_IccModule *pIccModule = CPDF_ModuleMgr::Get()->GetIccModule();
636 if (m_pProfile->m_pTransform == NULL || pIccModule == NULL) {
637 if (m_pAlterCS) {
638 m_pAlterCS->GetRGB(pBuf, R, G, B);
639 } else {
640 R = G = B = 0.0f;
641 }
642 return TRUE;
643 }
644 FX_FLOAT rgb[3];
645 pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb);
646 R = rgb[0];
647 G = rgb[1];
648 B = rgb[2];
649 return TRUE;
650 }
v_GetCMYK(FX_FLOAT * pBuf,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k) const651 FX_BOOL CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
652 {
653 if (m_nComponents != 4) {
654 return FALSE;
655 }
656 c = pBuf[0];
657 m = pBuf[1];
658 y = pBuf[2];
659 k = pBuf[3];
660 return TRUE;
661 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const662 FX_BOOL CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
663 {
664 return FALSE;
665 }
EnableStdConversion(FX_BOOL bEnabled)666 void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled)
667 {
668 CPDF_ColorSpace::EnableStdConversion(bEnabled);
669 if (m_pAlterCS) {
670 m_pAlterCS->EnableStdConversion(bEnabled);
671 }
672 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const673 void CPDF_ICCBasedCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
674 {
675 if (m_pProfile->m_bsRGB) {
676 ReverseRGB(pDestBuf, pSrcBuf, pixels);
677 } else if (m_pProfile->m_pTransform) {
678 int nMaxColors = 1;
679 for (int i = 0; i < m_nComponents; i ++) {
680 nMaxColors *= 52;
681 }
682 if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) {
683 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels);
684 } else {
685 if (m_pCache == NULL) {
686 ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc(FX_BYTE, nMaxColors * 3);
687 FX_LPBYTE temp_src = FX_Alloc(FX_BYTE, nMaxColors * m_nComponents);
688 FX_LPBYTE pSrc = temp_src;
689 for (int i = 0; i < nMaxColors; i ++) {
690 FX_DWORD color = i;
691 FX_DWORD order = nMaxColors / 52;
692 for (int c = 0; c < m_nComponents; c ++) {
693 *pSrc++ = (FX_BYTE)(color / order * 5);
694 color %= order;
695 order /= 52;
696 }
697 }
698 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors);
699 FX_Free(temp_src);
700 }
701 for (int i = 0; i < pixels; i ++) {
702 int index = 0;
703 for (int c = 0; c < m_nComponents; c ++) {
704 index = index * 52 + (*pSrcBuf) / 5;
705 pSrcBuf ++;
706 }
707 index *= 3;
708 *pDestBuf++ = m_pCache[index];
709 *pDestBuf++ = m_pCache[index + 1];
710 *pDestBuf++ = m_pCache[index + 2];
711 }
712 }
713 } else if (m_pAlterCS) {
714 m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, image_height);
715 }
716 }
717 class CPDF_IndexedCS : public CPDF_ColorSpace
718 {
719 public:
720 CPDF_IndexedCS();
721 virtual ~CPDF_IndexedCS();
722 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
GetDefaultValue(int iComponent,FX_FLOAT & min,FX_FLOAT & max) const723 void GetDefaultValue(int iComponent, FX_FLOAT& min, FX_FLOAT& max) const
724 {
725 min = 0;
726 max = (FX_FLOAT)m_MaxIndex;
727 }
728 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
GetBaseCS() const729 virtual CPDF_ColorSpace* GetBaseCS() const
730 {
731 return m_pBaseCS;
732 }
733 virtual void EnableStdConversion(FX_BOOL bEnabled);
734 CPDF_ColorSpace* m_pBaseCS;
735 int m_nBaseComponents;
736 int m_MaxIndex;
737 CFX_ByteString m_Table;
738 FX_FLOAT* m_pCompMinMax;
739 };
CPDF_IndexedCS()740 CPDF_IndexedCS::CPDF_IndexedCS()
741 {
742 m_pBaseCS = NULL;
743 m_Family = PDFCS_INDEXED;
744 m_nComponents = 1;
745 m_pCompMinMax = NULL;
746 }
~CPDF_IndexedCS()747 CPDF_IndexedCS::~CPDF_IndexedCS()
748 {
749 if (m_pCompMinMax) {
750 FX_Free(m_pCompMinMax);
751 }
752 CPDF_ColorSpace* pCS = m_pBaseCS;
753 if (pCS && m_pDocument) {
754 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
755 }
756 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)757 FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
758 {
759 if (pArray->GetCount() < 4) {
760 return FALSE;
761 }
762 CPDF_Object* pBaseObj = pArray->GetElementValue(1);
763 if (pBaseObj == m_pArray) {
764 return FALSE;
765 }
766 CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
767 m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL);
768 if (m_pBaseCS == NULL) {
769 return FALSE;
770 }
771 m_nBaseComponents = m_pBaseCS->CountComponents();
772 m_pCompMinMax = FX_Alloc(FX_FLOAT, m_nBaseComponents * 2);
773 FX_FLOAT defvalue;
774 for (int i = 0; i < m_nBaseComponents; i ++) {
775 m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], m_pCompMinMax[i * 2 + 1]);
776 m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2];
777 }
778 m_MaxIndex = pArray->GetInteger(2);
779 CPDF_Object* pTableObj = pArray->GetElementValue(3);
780 if (pTableObj == NULL) {
781 return FALSE;
782 }
783 FX_LPCBYTE pTable = NULL;
784 FX_DWORD size = 0;
785 CPDF_StreamAcc* pStreamAcc = NULL;
786 if (pTableObj->GetType() == PDFOBJ_STRING) {
787 m_Table = ((CPDF_String*)pTableObj)->GetString();
788 } else if (pTableObj->GetType() == PDFOBJ_STREAM) {
789 CPDF_StreamAcc acc;
790 acc.LoadAllData((CPDF_Stream*)pTableObj, FALSE);
791 m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize());
792 }
793 return TRUE;
794 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const795 FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
796 {
797 int index = (FX_INT32)(*pBuf);
798 if (index < 0 || index > m_MaxIndex) {
799 return FALSE;
800 }
801 if (m_nBaseComponents) {
802 if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents ||
803 (index + 1)*m_nBaseComponents > (int)m_Table.GetLength()) {
804 R = G = B = 0;
805 return FALSE;
806 }
807 }
808 CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents);
809 FX_FLOAT* comps = Comps;
810 FX_LPCBYTE pTable = m_Table;
811 for (int i = 0; i < m_nBaseComponents; i ++) {
812 comps[i] = m_pCompMinMax[i * 2] + m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255;
813 }
814 m_pBaseCS->GetRGB(comps, R, G, B);
815 return TRUE;
816 }
EnableStdConversion(FX_BOOL bEnabled)817 void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled)
818 {
819 CPDF_ColorSpace::EnableStdConversion(bEnabled);
820 if (m_pBaseCS) {
821 m_pBaseCS->EnableStdConversion(bEnabled);
822 }
823 }
824 #define MAX_PATTERN_COLORCOMPS 16
825 typedef struct _PatternValue {
826 CPDF_Pattern* m_pPattern;
827 int m_nComps;
828 FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS];
829 } PatternValue;
CPDF_PatternCS()830 CPDF_PatternCS::CPDF_PatternCS()
831 {
832 m_Family = PDFCS_PATTERN;
833 m_pBaseCS = NULL;
834 m_nComponents = 1;
835 }
~CPDF_PatternCS()836 CPDF_PatternCS::~CPDF_PatternCS()
837 {
838 CPDF_ColorSpace* pCS = m_pBaseCS;
839 if (pCS && m_pDocument) {
840 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
841 }
842 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)843 FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
844 {
845 CPDF_Object* pBaseCS = pArray->GetElementValue(1);
846 if (pBaseCS == m_pArray) {
847 return FALSE;
848 }
849 CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
850 m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, NULL);
851 if (m_pBaseCS) {
852 m_nComponents = m_pBaseCS->CountComponents() + 1;
853 if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) {
854 return FALSE;
855 }
856 } else {
857 m_nComponents = 1;
858 }
859 return TRUE;
860 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const861 FX_BOOL CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
862 {
863 if (m_pBaseCS) {
864 PatternValue* pvalue = (PatternValue*)pBuf;
865 m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B);
866 return TRUE;
867 }
868 R = G = B = 0.75f;
869 return FALSE;
870 }
871 class CPDF_SeparationCS : public CPDF_ColorSpace
872 {
873 public:
874 CPDF_SeparationCS();
875 virtual ~CPDF_SeparationCS();
GetDefaultValue(int iComponent,FX_FLOAT & value,FX_FLOAT & min,FX_FLOAT & max) const876 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
877 {
878 value = 1.0f;
879 min = 0;
880 max = 1.0f;
881 }
882 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
883 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
884 virtual void EnableStdConversion(FX_BOOL bEnabled);
885 CPDF_ColorSpace* m_pAltCS;
886 CPDF_Function* m_pFunc;
887 enum {None, All, Colorant} m_Type;
888 };
CPDF_SeparationCS()889 CPDF_SeparationCS::CPDF_SeparationCS()
890 {
891 m_Family = PDFCS_SEPARATION;
892 m_pAltCS = NULL;
893 m_pFunc = NULL;
894 m_nComponents = 1;
895 }
~CPDF_SeparationCS()896 CPDF_SeparationCS::~CPDF_SeparationCS()
897 {
898 if (m_pAltCS) {
899 m_pAltCS->ReleaseCS();
900 }
901 if (m_pFunc) {
902 delete m_pFunc;
903 }
904 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)905 FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
906 {
907 CFX_ByteString name = pArray->GetString(1);
908 if (name == FX_BSTRC("None")) {
909 m_Type = None;
910 } else {
911 m_Type = Colorant;
912 CPDF_Object* pAltCS = pArray->GetElementValue(2);
913 if (pAltCS == m_pArray) {
914 return FALSE;
915 }
916 m_pAltCS = Load(pDoc, pAltCS);
917 CPDF_Object* pFuncObj = pArray->GetElementValue(3);
918 if (pFuncObj && pFuncObj->GetType() != PDFOBJ_NAME) {
919 m_pFunc = CPDF_Function::Load(pFuncObj);
920 }
921 if (m_pFunc && m_pAltCS && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
922 delete m_pFunc;
923 m_pFunc = NULL;
924 }
925 }
926 return TRUE;
927 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const928 FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
929 {
930 if (m_Type == None) {
931 return FALSE;
932 }
933 if (m_pFunc == NULL) {
934 if (m_pAltCS == NULL) {
935 return FALSE;
936 }
937 int nComps = m_pAltCS->CountComponents();
938 CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps);
939 for (int i = 0; i < nComps; i ++) {
940 results[i] = *pBuf;
941 }
942 m_pAltCS->GetRGB(results, R, G, B);
943 return TRUE;
944 }
945 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
946 int nresults;
947 m_pFunc->Call(pBuf, 1, results, nresults);
948 if (nresults == 0) {
949 return FALSE;
950 }
951 if (m_pAltCS) {
952 m_pAltCS->GetRGB(results, R, G, B);
953 return TRUE;
954 } else {
955 R = G = B = 0;
956 return FALSE;
957 }
958 }
EnableStdConversion(FX_BOOL bEnabled)959 void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled)
960 {
961 CPDF_ColorSpace::EnableStdConversion(bEnabled);
962 if (m_pAltCS) {
963 m_pAltCS->EnableStdConversion(bEnabled);
964 }
965 }
966 class CPDF_DeviceNCS : public CPDF_ColorSpace
967 {
968 public:
969 CPDF_DeviceNCS();
970 virtual ~CPDF_DeviceNCS();
GetDefaultValue(int iComponent,FX_FLOAT & value,FX_FLOAT & min,FX_FLOAT & max) const971 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
972 {
973 value = 1.0f;
974 min = 0;
975 max = 1.0f;
976 }
977 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
978 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
979 virtual void EnableStdConversion(FX_BOOL bEnabled);
980 CPDF_ColorSpace* m_pAltCS;
981 CPDF_Function* m_pFunc;
982 };
CPDF_DeviceNCS()983 CPDF_DeviceNCS::CPDF_DeviceNCS()
984 {
985 m_Family = PDFCS_DEVICEN;
986 m_pAltCS = NULL;
987 m_pFunc = NULL;
988 }
~CPDF_DeviceNCS()989 CPDF_DeviceNCS::~CPDF_DeviceNCS()
990 {
991 if (m_pFunc) {
992 delete m_pFunc;
993 }
994 if (m_pAltCS) {
995 m_pAltCS->ReleaseCS();
996 }
997 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)998 FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
999 {
1000 CPDF_Object* pObj = pArray->GetElementValue(1);
1001 if (!pObj) {
1002 return FALSE;
1003 }
1004 if (pObj->GetType() != PDFOBJ_ARRAY) {
1005 return FALSE;
1006 }
1007 m_nComponents = ((CPDF_Array*)pObj)->GetCount();
1008 CPDF_Object* pAltCS = pArray->GetElementValue(2);
1009 if (!pAltCS || pAltCS == m_pArray) {
1010 return FALSE;
1011 }
1012 m_pAltCS = Load(pDoc, pAltCS);
1013 m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3));
1014 if (m_pAltCS == NULL || m_pFunc == NULL) {
1015 return FALSE;
1016 }
1017 if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
1018 return FALSE;
1019 }
1020 return TRUE;
1021 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const1022 FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
1023 {
1024 if (m_pFunc == NULL) {
1025 return FALSE;
1026 }
1027 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
1028 int nresults;
1029 m_pFunc->Call(pBuf, m_nComponents, results, nresults);
1030 if (nresults == 0) {
1031 return FALSE;
1032 }
1033 m_pAltCS->GetRGB(results, R, G, B);
1034 return TRUE;
1035 }
EnableStdConversion(FX_BOOL bEnabled)1036 void CPDF_DeviceNCS::EnableStdConversion(FX_BOOL bEnabled)
1037 {
1038 CPDF_ColorSpace::EnableStdConversion(bEnabled);
1039 if (m_pAltCS) {
1040 m_pAltCS->EnableStdConversion(bEnabled);
1041 }
1042 }
GetStockCS(int family)1043 CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family)
1044 {
1045 return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family);;
1046 }
_CSFromName(const CFX_ByteString & name)1047 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name)
1048 {
1049 if (name == FX_BSTRC("DeviceRGB") || name == FX_BSTRC("RGB")) {
1050 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
1051 }
1052 if (name == FX_BSTRC("DeviceGray") || name == FX_BSTRC("G")) {
1053 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
1054 }
1055 if (name == FX_BSTRC("DeviceCMYK") || name == FX_BSTRC("CMYK")) {
1056 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
1057 }
1058 if (name == FX_BSTRC("Pattern")) {
1059 return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
1060 }
1061 return NULL;
1062 }
Load(CPDF_Document * pDoc,CPDF_Object * pObj)1063 CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj)
1064 {
1065 if (pObj == NULL) {
1066 return NULL;
1067 }
1068 if (pObj->GetType() == PDFOBJ_NAME) {
1069 return _CSFromName(pObj->GetString());
1070 }
1071 if (pObj->GetType() == PDFOBJ_STREAM) {
1072 CPDF_Dictionary *pDict = ((CPDF_Stream *)pObj)->GetDict();
1073 if (!pDict) {
1074 return NULL;
1075 }
1076 CPDF_ColorSpace *pRet = NULL;
1077 FX_POSITION pos = pDict->GetStartPos();
1078 while (pos) {
1079 CFX_ByteString bsKey;
1080 CPDF_Object *pValue = pDict->GetNextElement(pos, bsKey);
1081 if (pValue->GetType() == PDFOBJ_NAME) {
1082 pRet = _CSFromName(pValue->GetString());
1083 }
1084 if (pRet) {
1085 return pRet;
1086 }
1087 }
1088 return NULL;
1089 }
1090 if (pObj->GetType() != PDFOBJ_ARRAY) {
1091 return NULL;
1092 }
1093 CPDF_Array* pArray = (CPDF_Array*)pObj;
1094 if (pArray->GetCount() == 0) {
1095 return NULL;
1096 }
1097 CFX_ByteString familyname = pArray->GetElementValue(0)->GetString();
1098 if (pArray->GetCount() == 1) {
1099 return _CSFromName(familyname);
1100 }
1101 CPDF_ColorSpace* pCS = NULL;
1102 FX_DWORD id = familyname.GetID();
1103 if (id == FXBSTR_ID('C', 'a', 'l', 'G')) {
1104 pCS = FX_NEW CPDF_CalGray();
1105 } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) {
1106 pCS = FX_NEW CPDF_CalRGB();
1107 } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) {
1108 pCS = FX_NEW CPDF_LabCS();
1109 } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) {
1110 pCS = FX_NEW CPDF_ICCBasedCS();
1111 } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || id == FXBSTR_ID('I', 0, 0, 0)) {
1112 pCS = FX_NEW CPDF_IndexedCS();
1113 } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) {
1114 pCS = FX_NEW CPDF_SeparationCS();
1115 } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) {
1116 pCS = FX_NEW CPDF_DeviceNCS();
1117 } else if (id == FXBSTR_ID('P', 'a', 't', 't')) {
1118 pCS = FX_NEW CPDF_PatternCS();
1119 } else {
1120 return NULL;
1121 }
1122 pCS->m_pDocument = pDoc;
1123 pCS->m_pArray = pArray;
1124 if (!pCS->v_Load(pDoc, pArray)) {
1125 pCS->ReleaseCS();
1126 return NULL;
1127 }
1128 return pCS;
1129 }
CPDF_ColorSpace()1130 CPDF_ColorSpace::CPDF_ColorSpace()
1131 {
1132 m_Family = 0;
1133 m_pArray = NULL;
1134 m_dwStdConversion = 0;
1135 m_pDocument = NULL;
1136 }
ReleaseCS()1137 void CPDF_ColorSpace::ReleaseCS()
1138 {
1139 if (this == GetStockCS(PDFCS_DEVICERGB)) {
1140 return;
1141 }
1142 if (this == GetStockCS(PDFCS_DEVICEGRAY)) {
1143 return;
1144 }
1145 if (this == GetStockCS(PDFCS_DEVICECMYK)) {
1146 return;
1147 }
1148 if (this == GetStockCS(PDFCS_PATTERN)) {
1149 return;
1150 }
1151 delete this;
1152 }
GetBufSize() const1153 int CPDF_ColorSpace::GetBufSize() const
1154 {
1155 if (m_Family == PDFCS_PATTERN) {
1156 return sizeof(PatternValue);
1157 }
1158 return m_nComponents * sizeof(FX_FLOAT);
1159 }
CreateBuf()1160 FX_FLOAT* CPDF_ColorSpace::CreateBuf()
1161 {
1162 int size = GetBufSize();
1163 FX_BYTE* pBuf = FX_Alloc(FX_BYTE, size);
1164 FXSYS_memset32(pBuf, 0, size);
1165 return (FX_FLOAT*)pBuf;
1166 }
sRGB() const1167 FX_BOOL CPDF_ColorSpace::sRGB() const
1168 {
1169 if (m_Family == PDFCS_DEVICERGB) {
1170 return TRUE;
1171 }
1172 if (m_Family != PDFCS_ICCBASED) {
1173 return FALSE;
1174 }
1175 CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this;
1176 return pCS->m_pProfile->m_bsRGB;
1177 }
GetCMYK(FX_FLOAT * pBuf,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k) const1178 FX_BOOL CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
1179 {
1180 if (v_GetCMYK(pBuf, c, m, y, k)) {
1181 return TRUE;
1182 }
1183 FX_FLOAT R, G, B;
1184 if (!GetRGB(pBuf, R, G, B)) {
1185 return FALSE;
1186 }
1187 sRGB_to_AdobeCMYK(R, G, B, c, m, y, k);
1188 return TRUE;
1189 }
SetCMYK(FX_FLOAT * pBuf,FX_FLOAT c,FX_FLOAT m,FX_FLOAT y,FX_FLOAT k) const1190 FX_BOOL CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const
1191 {
1192 if (v_SetCMYK(pBuf, c, m, y, k)) {
1193 return TRUE;
1194 }
1195 FX_FLOAT R, G, B;
1196 AdobeCMYK_to_sRGB(c, m, y, k, R, G, B);
1197 return SetRGB(pBuf, R, G, B);
1198 }
GetDefaultColor(FX_FLOAT * buf) const1199 void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const
1200 {
1201 if (buf == NULL || m_Family == PDFCS_PATTERN) {
1202 return;
1203 }
1204 FX_FLOAT min, max;
1205 for (int i = 0; i < m_nComponents; i ++) {
1206 GetDefaultValue(i, buf[i], min, max);
1207 }
1208 }
GetMaxIndex() const1209 int CPDF_ColorSpace::GetMaxIndex() const
1210 {
1211 if (m_Family != PDFCS_INDEXED) {
1212 return 0;
1213 }
1214 CPDF_IndexedCS* pCS = (CPDF_IndexedCS*)this;
1215 return pCS->m_MaxIndex;
1216 }
TranslateImageLine(FX_LPBYTE dest_buf,FX_LPCBYTE src_buf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const1217 void CPDF_ColorSpace::TranslateImageLine(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
1218 {
1219 CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents);
1220 FX_FLOAT* src = srcbuf;
1221 FX_FLOAT R, G, B;
1222 for (int i = 0; i < pixels; i ++) {
1223 for (int j = 0; j < m_nComponents; j ++)
1224 if (m_Family == PDFCS_INDEXED) {
1225 src[j] = (FX_FLOAT)(*src_buf ++);
1226 } else {
1227 src[j] = (FX_FLOAT)(*src_buf ++) / 255;
1228 }
1229 GetRGB(src, R, G, B);
1230 *dest_buf ++ = (FX_INT32)(B * 255);
1231 *dest_buf ++ = (FX_INT32)(G * 255);
1232 *dest_buf ++ = (FX_INT32)(R * 255);
1233 }
1234 }
EnableStdConversion(FX_BOOL bEnabled)1235 void CPDF_ColorSpace::EnableStdConversion(FX_BOOL bEnabled)
1236 {
1237 if (bEnabled) {
1238 m_dwStdConversion ++;
1239 } else if (m_dwStdConversion) {
1240 m_dwStdConversion --;
1241 }
1242 }
CPDF_Color(int family)1243 CPDF_Color::CPDF_Color(int family)
1244 {
1245 m_pCS = CPDF_ColorSpace::GetStockCS(family);
1246 int nComps = 3;
1247 if (family == PDFCS_DEVICEGRAY) {
1248 nComps = 1;
1249 } else if (family == PDFCS_DEVICECMYK) {
1250 nComps = 4;
1251 }
1252 m_pBuffer = FX_Alloc(FX_FLOAT, nComps);
1253 for (int i = 0; i < nComps; i ++) {
1254 m_pBuffer[i] = 0;
1255 }
1256 }
~CPDF_Color()1257 CPDF_Color::~CPDF_Color()
1258 {
1259 ReleaseBuffer();
1260 ReleaseColorSpace();
1261 }
ReleaseBuffer()1262 void CPDF_Color::ReleaseBuffer()
1263 {
1264 if (!m_pBuffer) {
1265 return;
1266 }
1267 if (m_pCS->GetFamily() == PDFCS_PATTERN) {
1268 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1269 CPDF_Pattern* pPattern = pvalue->m_pPattern;
1270 if (pPattern && pPattern->m_pDocument) {
1271 pPattern->m_pDocument->GetPageData()->ReleasePattern(pPattern->m_pPatternObj);
1272 }
1273 }
1274 FX_Free(m_pBuffer);
1275 m_pBuffer = NULL;
1276 }
ReleaseColorSpace()1277 void CPDF_Color::ReleaseColorSpace()
1278 {
1279 if (m_pCS && m_pCS->m_pDocument && m_pCS->GetArray()) {
1280 m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray());
1281 m_pCS = NULL;
1282 }
1283 }
SetColorSpace(CPDF_ColorSpace * pCS)1284 void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS)
1285 {
1286 if (m_pCS == pCS) {
1287 if (m_pBuffer == NULL) {
1288 m_pBuffer = pCS->CreateBuf();
1289 }
1290 ReleaseColorSpace();
1291 m_pCS = pCS;
1292 return;
1293 }
1294 ReleaseBuffer();
1295 ReleaseColorSpace();
1296 m_pCS = pCS;
1297 if (m_pCS) {
1298 m_pBuffer = pCS->CreateBuf();
1299 pCS->GetDefaultColor(m_pBuffer);
1300 }
1301 }
SetValue(FX_FLOAT * comps)1302 void CPDF_Color::SetValue(FX_FLOAT* comps)
1303 {
1304 if (m_pBuffer == NULL) {
1305 return;
1306 }
1307 if (m_pCS->GetFamily() != PDFCS_PATTERN) {
1308 FXSYS_memcpy32(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT));
1309 }
1310 }
SetValue(CPDF_Pattern * pPattern,FX_FLOAT * comps,int ncomps)1311 void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps)
1312 {
1313 if (ncomps > MAX_PATTERN_COLORCOMPS) {
1314 return;
1315 }
1316 if (m_pCS == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1317 if (m_pBuffer) {
1318 FX_Free(m_pBuffer);
1319 }
1320 m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
1321 m_pBuffer = m_pCS->CreateBuf();
1322 }
1323 CPDF_DocPageData* pDocPageData = NULL;
1324 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1325 if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
1326 pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
1327 pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
1328 }
1329 pvalue->m_nComps = ncomps;
1330 pvalue->m_pPattern = pPattern;
1331 if (ncomps) {
1332 FXSYS_memcpy32(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
1333 }
1334 }
Copy(const CPDF_Color * pSrc)1335 void CPDF_Color::Copy(const CPDF_Color* pSrc)
1336 {
1337 ReleaseBuffer();
1338 ReleaseColorSpace();
1339 m_pCS = pSrc->m_pCS;
1340 if (m_pCS && m_pCS->m_pDocument) {
1341 CPDF_Array* pArray = m_pCS->GetArray();
1342 if (pArray) {
1343 m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray);
1344 }
1345 }
1346 if (m_pCS == NULL) {
1347 return;
1348 }
1349 m_pBuffer = m_pCS->CreateBuf();
1350 FXSYS_memcpy32(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
1351 if (m_pCS->GetFamily() == PDFCS_PATTERN) {
1352 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1353 if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
1354 pvalue->m_pPattern = pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(pvalue->m_pPattern->m_pPatternObj, FALSE, &pvalue->m_pPattern->m_ParentMatrix);
1355 }
1356 }
1357 }
GetRGB(int & R,int & G,int & B) const1358 FX_BOOL CPDF_Color::GetRGB(int& R, int& G, int& B) const
1359 {
1360 if (m_pCS == NULL || m_pBuffer == NULL) {
1361 return FALSE;
1362 }
1363 FX_FLOAT r, g, b;
1364 if (!m_pCS->GetRGB(m_pBuffer, r, g, b)) {
1365 return FALSE;
1366 }
1367 R = (FX_INT32)(r * 255 + 0.5f);
1368 G = (FX_INT32)(g * 255 + 0.5f);
1369 B = (FX_INT32)(b * 255 + 0.5f);
1370 return TRUE;
1371 }
GetPattern() const1372 CPDF_Pattern* CPDF_Color::GetPattern() const
1373 {
1374 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1375 return NULL;
1376 }
1377 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1378 return pvalue->m_pPattern;
1379 }
GetPatternCS() const1380 CPDF_ColorSpace* CPDF_Color::GetPatternCS() const
1381 {
1382 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1383 return NULL;
1384 }
1385 return m_pCS->GetBaseCS();
1386 }
GetPatternColor() const1387 FX_FLOAT* CPDF_Color::GetPatternColor() const
1388 {
1389 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1390 return NULL;
1391 }
1392 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1393 return pvalue->m_nComps ? pvalue->m_Comps : NULL;
1394 }
IsEqual(const CPDF_Color & other) const1395 FX_BOOL CPDF_Color::IsEqual(const CPDF_Color& other) const
1396 {
1397 if (m_pCS != other.m_pCS || m_pCS == NULL) {
1398 return FALSE;
1399 }
1400 return FXSYS_memcmp32(m_pBuffer, other.m_pBuffer, m_pCS->GetBufSize()) == 0;
1401 }
1402