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 };
210
RGB_Conversion(FX_FLOAT colorComponent)211 static FX_FLOAT RGB_Conversion(FX_FLOAT colorComponent)
212 {
213 if (colorComponent > 1) {
214 colorComponent = 1;
215 }
216 if (colorComponent < 0) {
217 colorComponent = 0;
218 }
219 int scale = (int)(colorComponent * 1023);
220 if (scale < 0) {
221 scale = 0;
222 }
223 if (scale < 192) {
224 colorComponent = (g_sRGBSamples1[scale] / 255.0f);
225 }
226 else {
227 colorComponent = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
228 }
229 return colorComponent;
230 }
231
XYZ_to_sRGB(FX_FLOAT X,FX_FLOAT Y,FX_FLOAT Z,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B)232 static void XYZ_to_sRGB(FX_FLOAT X, FX_FLOAT Y, FX_FLOAT Z, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B)
233 {
234 FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
235 FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
236 FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
237
238 R = RGB_Conversion(R1);
239 G = RGB_Conversion(G1);
240 B = RGB_Conversion(B1);
241 }
242
XYZ_to_sRGB_WhitePoint(FX_FLOAT X,FX_FLOAT Y,FX_FLOAT Z,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B,FX_FLOAT Xw,FX_FLOAT Yw,FX_FLOAT Zw)243 static void XYZ_to_sRGB_WhitePoint(FX_FLOAT X, FX_FLOAT Y, FX_FLOAT Z, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B, FX_FLOAT Xw, FX_FLOAT Yw, FX_FLOAT Zw)
244 {
245 // The following RGB_xyz is based on
246 // sRGB value {Rx,Ry}={0.64, 0.33}, {Gx,Gy}={0.30, 0.60}, {Bx,By}={0.15, 0.06}
247
248 FX_FLOAT Rx = 0.64f, Ry = 0.33f;
249 FX_FLOAT Gx = 0.30f, Gy = 0.60f;
250 FX_FLOAT Bx = 0.15f, By = 0.06f;
251 CFX_Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy, 1 - Bx - By);
252 CFX_Vector_3by1 whitePoint(Xw, Yw, Zw);
253 CFX_Vector_3by1 XYZ(X, Y, Z);
254
255 CFX_Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint);
256 CFX_Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0, 0, RGB_Sum_XYZ.c);
257 CFX_Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG);
258 CFX_Vector_3by1 RGB = M.Inverse().TransformVector(XYZ);
259
260 R = RGB_Conversion(RGB.a);
261 G = RGB_Conversion(RGB.b);
262 B = RGB_Conversion(RGB.c);
263 }
264 class CPDF_CalGray : public CPDF_ColorSpace
265 {
266 public:
267 CPDF_CalGray();
268 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
269 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
270 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
271 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
272 FX_FLOAT m_WhitePoint[3];
273 FX_FLOAT m_BlackPoint[3];
274 FX_FLOAT m_Gamma;
275 };
CPDF_CalGray()276 CPDF_CalGray::CPDF_CalGray()
277 {
278 m_Family = PDFCS_CALGRAY;
279 m_nComponents = 1;
280 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)281 FX_BOOL CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
282 {
283 CPDF_Dictionary* pDict = pArray->GetDict(1);
284 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
285 int i;
286 for (i = 0; i < 3; i ++) {
287 m_WhitePoint[i] = pParam ? pParam->GetNumber(i) : 0;
288 }
289 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
290 for (i = 0; i < 3; i ++) {
291 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
292 }
293 m_Gamma = pDict->GetNumber(FX_BSTRC("Gamma"));
294 if (m_Gamma == 0) {
295 m_Gamma = 1.0f;
296 }
297 return TRUE;
298 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const299 FX_BOOL CPDF_CalGray::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
300 {
301 R = G = B = *pBuf;
302 return TRUE;
303 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const304 FX_BOOL CPDF_CalGray::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
305 {
306 if (R == G && R == B) {
307 *pBuf = R;
308 return TRUE;
309 } else {
310 return FALSE;
311 }
312 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const313 void CPDF_CalGray::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
314 {
315 for (int i = 0; i < pixels; i ++) {
316 *pDestBuf ++ = pSrcBuf[i];
317 *pDestBuf ++ = pSrcBuf[i];
318 *pDestBuf ++ = pSrcBuf[i];
319 }
320 }
321 class CPDF_CalRGB : public CPDF_ColorSpace
322 {
323 public:
324 CPDF_CalRGB();
325 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
326 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
327 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
328 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
329 FX_FLOAT m_WhitePoint[3];
330 FX_FLOAT m_BlackPoint[3];
331 FX_FLOAT m_Gamma[3];
332 FX_FLOAT m_Matrix[9];
333 FX_BOOL m_bGamma, m_bMatrix;
334 };
CPDF_CalRGB()335 CPDF_CalRGB::CPDF_CalRGB()
336 {
337 m_Family = PDFCS_CALRGB;
338 m_nComponents = 3;
339 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)340 FX_BOOL CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
341 {
342 CPDF_Dictionary* pDict = pArray->GetDict(1);
343 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
344 int i;
345 for (i = 0; i < 3; i ++) {
346 m_WhitePoint[i] = pParam ? pParam->GetNumber(i) : 0;
347 }
348 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
349 for (i = 0; i < 3; i ++) {
350 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
351 }
352 pParam = pDict->GetArray(FX_BSTRC("Gamma"));
353 if (pParam) {
354 m_bGamma = TRUE;
355 for (i = 0; i < 3; i ++) {
356 m_Gamma[i] = pParam->GetNumber(i);
357 }
358 } else {
359 m_bGamma = FALSE;
360 }
361 pParam = pDict->GetArray(FX_BSTRC("Matrix"));
362 if (pParam) {
363 m_bMatrix = TRUE;
364 for (i = 0; i < 9; i ++) {
365 m_Matrix[i] = pParam->GetNumber(i);
366 }
367 } else {
368 m_bMatrix = FALSE;
369 }
370 return TRUE;
371 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const372 FX_BOOL CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
373 {
374 FX_FLOAT A_ = pBuf[0];
375 FX_FLOAT B_ = pBuf[1];
376 FX_FLOAT C_ = pBuf[2];
377 if (m_bGamma) {
378 A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]);
379 B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]);
380 C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]);
381 }
382 FX_FLOAT X, Y, Z;
383 if (m_bMatrix) {
384 X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_;
385 Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_;
386 Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_;
387 } else {
388 X = A_;
389 Y = B_;
390 Z = C_;
391 }
392 XYZ_to_sRGB_WhitePoint(X, Y, Z, R, G, B, m_WhitePoint[0], m_WhitePoint[1], m_WhitePoint[2]);
393 return TRUE;
394 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const395 FX_BOOL CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
396 {
397 pBuf[0] = R;
398 pBuf[1] = G;
399 pBuf[2] = B;
400 return TRUE;
401 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const402 void CPDF_CalRGB::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
403 {
404 if (bTransMask) {
405 FX_FLOAT Cal[3];
406 FX_FLOAT R, G, B;
407 for(int i = 0; i < pixels; i ++) {
408 Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255;
409 Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255;
410 Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255;
411 GetRGB(Cal, R, G, B);
412 pDestBuf[0] = FXSYS_round(B * 255);
413 pDestBuf[1] = FXSYS_round(G * 255);
414 pDestBuf[2] = FXSYS_round(R * 255);
415 pSrcBuf += 3;
416 pDestBuf += 3;
417 }
418 }
419 ReverseRGB(pDestBuf, pSrcBuf, pixels);
420 }
421 class CPDF_LabCS : public CPDF_ColorSpace
422 {
423 public:
CPDF_LabCS()424 CPDF_LabCS()
425 {
426 m_Family = PDFCS_LAB;
427 m_nComponents = 3;
428 }
429 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
430 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const;
431 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
432 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
433 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
434 FX_FLOAT m_WhitePoint[3];
435 FX_FLOAT m_BlackPoint[3];
436 FX_FLOAT m_Ranges[4];
437 };
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)438 FX_BOOL CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
439 {
440 CPDF_Dictionary* pDict = pArray->GetDict(1);
441 if (!pDict) {
442 return FALSE;
443 }
444 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
445 int i;
446 for (i = 0; i < 3; i ++) {
447 m_WhitePoint[i] = pParam ? pParam->GetNumber(i) : 0;
448 }
449 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
450 for (i = 0; i < 3; i ++) {
451 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
452 }
453 pParam = pDict->GetArray(FX_BSTRC("Range"));
454 const FX_FLOAT def_ranges[4] = { -100 * 1.0f, 100 * 1.0f, -100 * 1.0f, 100 * 1.0f};
455 for (i = 0; i < 4; i ++) {
456 m_Ranges[i] = pParam ? pParam->GetNumber(i) : def_ranges[i];
457 }
458 return TRUE;
459 }
GetDefaultValue(int iComponent,FX_FLOAT & value,FX_FLOAT & min,FX_FLOAT & max) const460 void CPDF_LabCS::GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
461 {
462 assert(iComponent < 3);
463 value = 0;
464 if (iComponent == 0) {
465 min = 0;
466 max = 100 * 1.0f;
467 } else {
468 min = m_Ranges[iComponent * 2 - 2];
469 max = m_Ranges[iComponent * 2 - 1];
470 if (value < min) {
471 value = min;
472 } else if (value > max) {
473 value = max;
474 }
475 }
476 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const477 FX_BOOL CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
478 {
479 FX_FLOAT Lstar = pBuf[0];
480 FX_FLOAT astar = pBuf[1];
481 FX_FLOAT bstar = pBuf[2];
482 FX_FLOAT M = (Lstar + 16.0f) / 116.0f;
483 FX_FLOAT L = M + astar / 500.0f;
484 FX_FLOAT N = M - bstar / 200.0f;
485 FX_FLOAT X, Y, Z;
486 if (L < 0.2069f) {
487 X = 0.957f * 0.12842f * (L - 0.1379f);
488 } else {
489 X = 0.957f * L * L * L;
490 }
491 if (M < 0.2069f) {
492 Y = 0.12842f * (M - 0.1379f);
493 } else {
494 Y = M * M * M;
495 }
496 if (N < 0.2069f) {
497 Z = 1.0889f * 0.12842f * (N - 0.1379f);
498 } else {
499 Z = 1.0889f * N * N * N;
500 }
501 XYZ_to_sRGB(X, Y, Z, R, G, B);
502 return TRUE;
503 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const504 FX_BOOL CPDF_LabCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
505 {
506 return FALSE;
507 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const508 void CPDF_LabCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
509 {
510 for (int i = 0; i < pixels; i ++) {
511 FX_FLOAT lab[3];
512 FX_FLOAT R, G, B;
513 lab[0] = (pSrcBuf[0] * 100 / 255.0f);
514 lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128);
515 lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128);
516 GetRGB(lab, R, G, B);
517 pDestBuf[0] = (FX_INT32)(B * 255);
518 pDestBuf[1] = (FX_INT32)(G * 255);
519 pDestBuf[2] = (FX_INT32)(R * 255);
520 pDestBuf += 3;
521 pSrcBuf += 3;
522 }
523 }
CPDF_IccProfile(FX_LPCBYTE pData,FX_DWORD dwSize)524 CPDF_IccProfile::CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize):
525 m_bsRGB(FALSE),
526 m_pTransform(NULL),
527 m_nSrcComponents(0)
528 {
529 if (dwSize == 3144 && FXSYS_memcmp32(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0) {
530 m_bsRGB = TRUE;
531 m_nSrcComponents = 3;
532 }
533 else if (CPDF_ModuleMgr::Get()->GetIccModule()) {
534 m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(pData, dwSize, m_nSrcComponents);
535 }
536 }
~CPDF_IccProfile()537 CPDF_IccProfile::~CPDF_IccProfile()
538 {
539 if (m_pTransform) {
540 CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform);
541 }
542 }
543 class CPDF_ICCBasedCS : public CPDF_ColorSpace
544 {
545 public:
546 CPDF_ICCBasedCS();
547 virtual ~CPDF_ICCBasedCS();
548 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
GetDefaultValue(int i,FX_FLOAT & min,FX_FLOAT & max) const549 void GetDefaultValue(int i, FX_FLOAT& min, FX_FLOAT& max) const
550 {
551 min = m_pRanges[i * 2];
552 max = m_pRanges[i * 2 + 1];
553 }
554 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
555 FX_BOOL v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const;
556 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
557 virtual void EnableStdConversion(FX_BOOL bEnabled);
558 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
559 FX_FLOAT* m_pRanges;
560 CPDF_IccProfile* m_pProfile;
561 CPDF_ColorSpace* m_pAlterCS;
562 FX_LPBYTE m_pCache;
563 FX_BOOL m_bOwn;
564 };
CPDF_ICCBasedCS()565 CPDF_ICCBasedCS::CPDF_ICCBasedCS()
566 {
567 m_pAlterCS = NULL;
568 m_pProfile = NULL;
569 m_Family = PDFCS_ICCBASED;
570 m_pCache = NULL;
571 m_pRanges = NULL;
572 m_bOwn = FALSE;
573 }
~CPDF_ICCBasedCS()574 CPDF_ICCBasedCS::~CPDF_ICCBasedCS()
575 {
576 if (m_pCache) {
577 FX_Free(m_pCache);
578 }
579 if (m_pRanges) {
580 FX_Free(m_pRanges);
581 }
582 if (m_pAlterCS && m_bOwn) {
583 m_pAlterCS->ReleaseCS();
584 }
585 if (m_pProfile && m_pDocument) {
586 m_pDocument->GetPageData()->ReleaseIccProfile(NULL, m_pProfile);
587 }
588 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)589 FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
590 {
591 CPDF_Stream* pStream = pArray->GetStream(1);
592 if (pStream == NULL) {
593 return FALSE;
594 }
595 m_pProfile = pDoc->LoadIccProfile(pStream);
596 if (!m_pProfile) {
597 return FALSE;
598 }
599 m_nComponents = m_pProfile->GetComponents(); //Try using the nComponents from ICC profile
600 CPDF_Dictionary* pDict = pStream->GetDict();
601 if (m_pProfile->m_pTransform == NULL) { // No valid ICC profile or using sRGB
602 CPDF_Object* pAlterCSObj = pDict ? pDict->GetElementValue(FX_BSTRC("Alternate")) : NULL;
603 if (pAlterCSObj) {
604 CPDF_ColorSpace* pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
605 if (pAlterCS) {
606 if (m_nComponents == 0) { // NO valid ICC profile
607 if (pAlterCS->CountComponents() > 0) { // Use Alternative colorspace
608 m_nComponents = pAlterCS->CountComponents();
609 m_pAlterCS = pAlterCS;
610 m_bOwn = TRUE;
611 }
612 else { // No valid alternative colorspace
613 pAlterCS->ReleaseCS();
614 FX_INT32 nDictComponents = pDict ? pDict->GetInteger(FX_BSTRC("N")) : 0;
615 if (nDictComponents != 1 && nDictComponents != 3 && nDictComponents != 4) {
616 return FALSE;
617 }
618 m_nComponents = nDictComponents;
619 }
620
621 }
622 else { // Using sRGB
623 if (pAlterCS->CountComponents() != m_nComponents) {
624 pAlterCS->ReleaseCS();
625 }
626 else {
627 m_pAlterCS = pAlterCS;
628 m_bOwn = TRUE;
629 }
630 }
631 }
632 }
633 if (!m_pAlterCS) {
634 if (m_nComponents == 1) {
635 m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
636 }
637 else if (m_nComponents == 3) {
638 m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
639 }
640 else if (m_nComponents == 4) {
641 m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
642 }
643 }
644 }
645 CPDF_Array* pRanges = pDict->GetArray(FX_BSTRC("Range"));
646 m_pRanges = FX_Alloc2D(FX_FLOAT, m_nComponents, 2);
647 for (int i = 0; i < m_nComponents * 2; i ++) {
648 if (pRanges) {
649 m_pRanges[i] = pRanges->GetNumber(i);
650 } else if (i % 2) {
651 m_pRanges[i] = 1.0f;
652 } else {
653 m_pRanges[i] = 0;
654 }
655 }
656 return TRUE;
657 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const658 FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
659 {
660 if (m_pProfile && m_pProfile->m_bsRGB) {
661 R = pBuf[0];
662 G = pBuf[1];
663 B = pBuf[2];
664 return TRUE;
665 }
666 ICodec_IccModule *pIccModule = CPDF_ModuleMgr::Get()->GetIccModule();
667 if (m_pProfile->m_pTransform == NULL || pIccModule == NULL) {
668 if (m_pAlterCS) {
669 m_pAlterCS->GetRGB(pBuf, R, G, B);
670 } else {
671 R = G = B = 0.0f;
672 }
673 return TRUE;
674 }
675 FX_FLOAT rgb[3];
676 pIccModule->SetComponents(m_nComponents);
677 pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb);
678 R = rgb[0];
679 G = rgb[1];
680 B = rgb[2];
681 return TRUE;
682 }
v_GetCMYK(FX_FLOAT * pBuf,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k) const683 FX_BOOL CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
684 {
685 if (m_nComponents != 4) {
686 return FALSE;
687 }
688 c = pBuf[0];
689 m = pBuf[1];
690 y = pBuf[2];
691 k = pBuf[3];
692 return TRUE;
693 }
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const694 FX_BOOL CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
695 {
696 return FALSE;
697 }
EnableStdConversion(FX_BOOL bEnabled)698 void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled)
699 {
700 CPDF_ColorSpace::EnableStdConversion(bEnabled);
701 if (m_pAlterCS) {
702 m_pAlterCS->EnableStdConversion(bEnabled);
703 }
704 }
TranslateImageLine(FX_LPBYTE pDestBuf,FX_LPCBYTE pSrcBuf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const705 void CPDF_ICCBasedCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
706 {
707 if (m_pProfile->m_bsRGB) {
708 ReverseRGB(pDestBuf, pSrcBuf, pixels);
709 } else if (m_pProfile->m_pTransform) {
710 int nMaxColors = 1;
711 for (int i = 0; i < m_nComponents; i ++) {
712 nMaxColors *= 52;
713 }
714 if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) {
715 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels);
716 } else {
717 if (m_pCache == NULL) {
718 ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc2D(FX_BYTE, nMaxColors, 3);
719 FX_LPBYTE temp_src = FX_Alloc2D(FX_BYTE, nMaxColors, m_nComponents);
720 FX_LPBYTE pSrc = temp_src;
721 for (int i = 0; i < nMaxColors; i ++) {
722 FX_DWORD color = i;
723 FX_DWORD order = nMaxColors / 52;
724 for (int c = 0; c < m_nComponents; c ++) {
725 *pSrc++ = (FX_BYTE)(color / order * 5);
726 color %= order;
727 order /= 52;
728 }
729 }
730 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors);
731 FX_Free(temp_src);
732 }
733 for (int i = 0; i < pixels; i ++) {
734 int index = 0;
735 for (int c = 0; c < m_nComponents; c ++) {
736 index = index * 52 + (*pSrcBuf) / 5;
737 pSrcBuf ++;
738 }
739 index *= 3;
740 *pDestBuf++ = m_pCache[index];
741 *pDestBuf++ = m_pCache[index + 1];
742 *pDestBuf++ = m_pCache[index + 2];
743 }
744 }
745 } else if (m_pAlterCS) {
746 m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, image_height);
747 }
748 }
749 class CPDF_IndexedCS : public CPDF_ColorSpace
750 {
751 public:
752 CPDF_IndexedCS();
753 virtual ~CPDF_IndexedCS();
754 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
GetDefaultValue(int iComponent,FX_FLOAT & min,FX_FLOAT & max) const755 void GetDefaultValue(int iComponent, FX_FLOAT& min, FX_FLOAT& max) const
756 {
757 min = 0;
758 max = (FX_FLOAT)m_MaxIndex;
759 }
760 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
GetBaseCS() const761 virtual CPDF_ColorSpace* GetBaseCS() const
762 {
763 return m_pBaseCS;
764 }
765 virtual void EnableStdConversion(FX_BOOL bEnabled);
766 CPDF_ColorSpace* m_pBaseCS;
767 CPDF_CountedColorSpace* m_pCountedBaseCS;
768 int m_nBaseComponents;
769 int m_MaxIndex;
770 CFX_ByteString m_Table;
771 FX_FLOAT* m_pCompMinMax;
772 };
CPDF_IndexedCS()773 CPDF_IndexedCS::CPDF_IndexedCS()
774 {
775 m_pBaseCS = NULL;
776 m_pCountedBaseCS = NULL;
777 m_Family = PDFCS_INDEXED;
778 m_nComponents = 1;
779 m_pCompMinMax = NULL;
780 }
~CPDF_IndexedCS()781 CPDF_IndexedCS::~CPDF_IndexedCS()
782 {
783 if (m_pCompMinMax) {
784 FX_Free(m_pCompMinMax);
785 }
786 CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->m_Obj : NULL;
787 if (pCS && m_pDocument) {
788 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
789 }
790 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)791 FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
792 {
793 if (pArray->GetCount() < 4) {
794 return FALSE;
795 }
796 CPDF_Object* pBaseObj = pArray->GetElementValue(1);
797 if (pBaseObj == m_pArray) {
798 return FALSE;
799 }
800 CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
801 m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL);
802 if (m_pBaseCS == NULL) {
803 return FALSE;
804 }
805 m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
806 m_nBaseComponents = m_pBaseCS->CountComponents();
807 m_pCompMinMax = FX_Alloc2D(FX_FLOAT, m_nBaseComponents, 2);
808 FX_FLOAT defvalue;
809 for (int i = 0; i < m_nBaseComponents; i ++) {
810 m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], m_pCompMinMax[i * 2 + 1]);
811 m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2];
812 }
813 m_MaxIndex = pArray->GetInteger(2);
814 CPDF_Object* pTableObj = pArray->GetElementValue(3);
815 if (pTableObj == NULL) {
816 return FALSE;
817 }
818 if (pTableObj->GetType() == PDFOBJ_STRING) {
819 m_Table = ((CPDF_String*)pTableObj)->GetString();
820 } else if (pTableObj->GetType() == PDFOBJ_STREAM) {
821 CPDF_StreamAcc acc;
822 acc.LoadAllData((CPDF_Stream*)pTableObj, FALSE);
823 m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize());
824 }
825 return TRUE;
826 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const827 FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
828 {
829 int index = (FX_INT32)(*pBuf);
830 if (index < 0 || index > m_MaxIndex) {
831 return FALSE;
832 }
833 if (m_nBaseComponents) {
834 if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents ||
835 (index + 1)*m_nBaseComponents > (int)m_Table.GetLength()) {
836 R = G = B = 0;
837 return FALSE;
838 }
839 }
840 CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents);
841 FX_FLOAT* comps = Comps;
842 FX_LPCBYTE pTable = m_Table;
843 for (int i = 0; i < m_nBaseComponents; i ++) {
844 comps[i] = m_pCompMinMax[i * 2] + m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255;
845 }
846 m_pBaseCS->GetRGB(comps, R, G, B);
847 return TRUE;
848 }
EnableStdConversion(FX_BOOL bEnabled)849 void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled)
850 {
851 CPDF_ColorSpace::EnableStdConversion(bEnabled);
852 if (m_pBaseCS) {
853 m_pBaseCS->EnableStdConversion(bEnabled);
854 }
855 }
856 #define MAX_PATTERN_COLORCOMPS 16
857 typedef struct _PatternValue {
858 CPDF_Pattern* m_pPattern;
859 CPDF_CountedPattern* m_pCountedPattern;
860 int m_nComps;
861 FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS];
862 } PatternValue;
CPDF_PatternCS()863 CPDF_PatternCS::CPDF_PatternCS()
864 {
865 m_Family = PDFCS_PATTERN;
866 m_pBaseCS = NULL;
867 m_nComponents = 1;
868 m_pCountedBaseCS = NULL;
869 }
~CPDF_PatternCS()870 CPDF_PatternCS::~CPDF_PatternCS()
871 {
872 CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->m_Obj : NULL;
873 if (pCS && m_pDocument) {
874 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
875 }
876 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)877 FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
878 {
879 CPDF_Object* pBaseCS = pArray->GetElementValue(1);
880 if (pBaseCS == m_pArray) {
881 return FALSE;
882 }
883 CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
884 m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, NULL);
885 if (m_pBaseCS) {
886 if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) {
887 return FALSE;
888 }
889 m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
890 m_nComponents = m_pBaseCS->CountComponents() + 1;
891 if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) {
892 return FALSE;
893 }
894 } else {
895 m_nComponents = 1;
896 }
897 return TRUE;
898 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const899 FX_BOOL CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
900 {
901 if (m_pBaseCS) {
902 ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN);
903 PatternValue* pvalue = (PatternValue*)pBuf;
904 if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) {
905 return TRUE;
906 }
907 }
908 R = G = B = 0.75f;
909 return FALSE;
910 }
911 class CPDF_SeparationCS : public CPDF_ColorSpace
912 {
913 public:
914 CPDF_SeparationCS();
915 virtual ~CPDF_SeparationCS();
GetDefaultValue(int iComponent,FX_FLOAT & value,FX_FLOAT & min,FX_FLOAT & max) const916 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
917 {
918 value = 1.0f;
919 min = 0;
920 max = 1.0f;
921 }
922 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
923 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
924 virtual void EnableStdConversion(FX_BOOL bEnabled);
925 CPDF_ColorSpace* m_pAltCS;
926 CPDF_Function* m_pFunc;
927 enum {None, All, Colorant} m_Type;
928 };
CPDF_SeparationCS()929 CPDF_SeparationCS::CPDF_SeparationCS()
930 {
931 m_Family = PDFCS_SEPARATION;
932 m_pAltCS = NULL;
933 m_pFunc = NULL;
934 m_nComponents = 1;
935 }
~CPDF_SeparationCS()936 CPDF_SeparationCS::~CPDF_SeparationCS()
937 {
938 if (m_pAltCS) {
939 m_pAltCS->ReleaseCS();
940 }
941 if (m_pFunc) {
942 delete m_pFunc;
943 }
944 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)945 FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
946 {
947 CFX_ByteString name = pArray->GetString(1);
948 if (name == FX_BSTRC("None")) {
949 m_Type = None;
950 } else {
951 m_Type = Colorant;
952 CPDF_Object* pAltCS = pArray->GetElementValue(2);
953 if (pAltCS == m_pArray) {
954 return FALSE;
955 }
956 m_pAltCS = Load(pDoc, pAltCS);
957 CPDF_Object* pFuncObj = pArray->GetElementValue(3);
958 if (pFuncObj && pFuncObj->GetType() != PDFOBJ_NAME) {
959 m_pFunc = CPDF_Function::Load(pFuncObj);
960 }
961 if (m_pFunc && m_pAltCS && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
962 delete m_pFunc;
963 m_pFunc = NULL;
964 }
965 }
966 return TRUE;
967 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const968 FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
969 {
970 if (m_Type == None) {
971 return FALSE;
972 }
973 if (m_pFunc == NULL) {
974 if (m_pAltCS == NULL) {
975 return FALSE;
976 }
977 int nComps = m_pAltCS->CountComponents();
978 CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps);
979 for (int i = 0; i < nComps; i ++) {
980 results[i] = *pBuf;
981 }
982 m_pAltCS->GetRGB(results, R, G, B);
983 return TRUE;
984 }
985 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
986 int nresults = 0;
987 m_pFunc->Call(pBuf, 1, results, nresults);
988 if (nresults == 0) {
989 return FALSE;
990 }
991 if (m_pAltCS) {
992 m_pAltCS->GetRGB(results, R, G, B);
993 return TRUE;
994 } else {
995 R = G = B = 0;
996 return FALSE;
997 }
998 }
EnableStdConversion(FX_BOOL bEnabled)999 void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled)
1000 {
1001 CPDF_ColorSpace::EnableStdConversion(bEnabled);
1002 if (m_pAltCS) {
1003 m_pAltCS->EnableStdConversion(bEnabled);
1004 }
1005 }
1006 class CPDF_DeviceNCS : public CPDF_ColorSpace
1007 {
1008 public:
1009 CPDF_DeviceNCS();
1010 virtual ~CPDF_DeviceNCS();
GetDefaultValue(int iComponent,FX_FLOAT & value,FX_FLOAT & min,FX_FLOAT & max) const1011 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
1012 {
1013 value = 1.0f;
1014 min = 0;
1015 max = 1.0f;
1016 }
1017 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
1018 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
1019 virtual void EnableStdConversion(FX_BOOL bEnabled);
1020 CPDF_ColorSpace* m_pAltCS;
1021 CPDF_Function* m_pFunc;
1022 };
CPDF_DeviceNCS()1023 CPDF_DeviceNCS::CPDF_DeviceNCS()
1024 {
1025 m_Family = PDFCS_DEVICEN;
1026 m_pAltCS = NULL;
1027 m_pFunc = NULL;
1028 }
~CPDF_DeviceNCS()1029 CPDF_DeviceNCS::~CPDF_DeviceNCS()
1030 {
1031 if (m_pFunc) {
1032 delete m_pFunc;
1033 }
1034 if (m_pAltCS) {
1035 m_pAltCS->ReleaseCS();
1036 }
1037 }
v_Load(CPDF_Document * pDoc,CPDF_Array * pArray)1038 FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
1039 {
1040 CPDF_Object* pObj = pArray->GetElementValue(1);
1041 if (!pObj) {
1042 return FALSE;
1043 }
1044 if (pObj->GetType() != PDFOBJ_ARRAY) {
1045 return FALSE;
1046 }
1047 m_nComponents = ((CPDF_Array*)pObj)->GetCount();
1048 CPDF_Object* pAltCS = pArray->GetElementValue(2);
1049 if (!pAltCS || pAltCS == m_pArray) {
1050 return FALSE;
1051 }
1052 m_pAltCS = Load(pDoc, pAltCS);
1053 m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3));
1054 if (m_pAltCS == NULL || m_pFunc == NULL) {
1055 return FALSE;
1056 }
1057 if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
1058 return FALSE;
1059 }
1060 return TRUE;
1061 }
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const1062 FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
1063 {
1064 if (m_pFunc == NULL) {
1065 return FALSE;
1066 }
1067 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
1068 int nresults = 0;
1069 m_pFunc->Call(pBuf, m_nComponents, results, nresults);
1070 if (nresults == 0) {
1071 return FALSE;
1072 }
1073 m_pAltCS->GetRGB(results, R, G, B);
1074 return TRUE;
1075 }
EnableStdConversion(FX_BOOL bEnabled)1076 void CPDF_DeviceNCS::EnableStdConversion(FX_BOOL bEnabled)
1077 {
1078 CPDF_ColorSpace::EnableStdConversion(bEnabled);
1079 if (m_pAltCS) {
1080 m_pAltCS->EnableStdConversion(bEnabled);
1081 }
1082 }
GetStockCS(int family)1083 CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family)
1084 {
1085 return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family);;
1086 }
_CSFromName(const CFX_ByteString & name)1087 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name)
1088 {
1089 if (name == FX_BSTRC("DeviceRGB") || name == FX_BSTRC("RGB")) {
1090 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
1091 }
1092 if (name == FX_BSTRC("DeviceGray") || name == FX_BSTRC("G")) {
1093 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
1094 }
1095 if (name == FX_BSTRC("DeviceCMYK") || name == FX_BSTRC("CMYK")) {
1096 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
1097 }
1098 if (name == FX_BSTRC("Pattern")) {
1099 return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
1100 }
1101 return NULL;
1102 }
Load(CPDF_Document * pDoc,CPDF_Object * pObj)1103 CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj)
1104 {
1105 if (pObj == NULL) {
1106 return NULL;
1107 }
1108 if (pObj->GetType() == PDFOBJ_NAME) {
1109 return _CSFromName(pObj->GetString());
1110 }
1111 if (pObj->GetType() == PDFOBJ_STREAM) {
1112 CPDF_Dictionary *pDict = ((CPDF_Stream *)pObj)->GetDict();
1113 if (!pDict) {
1114 return NULL;
1115 }
1116 CPDF_ColorSpace *pRet = NULL;
1117 FX_POSITION pos = pDict->GetStartPos();
1118 while (pos) {
1119 CFX_ByteString bsKey;
1120 CPDF_Object *pValue = pDict->GetNextElement(pos, bsKey);
1121 if (pValue && pValue->GetType() == PDFOBJ_NAME) {
1122 pRet = _CSFromName(pValue->GetString());
1123 }
1124 if (pRet) {
1125 return pRet;
1126 }
1127 }
1128 return NULL;
1129 }
1130 if (pObj->GetType() != PDFOBJ_ARRAY) {
1131 return NULL;
1132 }
1133 CPDF_Array* pArray = (CPDF_Array*)pObj;
1134 if (pArray->GetCount() == 0) {
1135 return NULL;
1136 }
1137 CPDF_Object *pFamilyObj = pArray->GetElementValue(0);
1138 if (!pFamilyObj) {
1139 return NULL;
1140 }
1141 CFX_ByteString familyname = pFamilyObj->GetString();
1142 if (pArray->GetCount() == 1) {
1143 return _CSFromName(familyname);
1144 }
1145 CPDF_ColorSpace* pCS = NULL;
1146 FX_DWORD id = familyname.GetID();
1147 if (id == FXBSTR_ID('C', 'a', 'l', 'G')) {
1148 pCS = new CPDF_CalGray();
1149 } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) {
1150 pCS = new CPDF_CalRGB();
1151 } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) {
1152 pCS = new CPDF_LabCS();
1153 } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) {
1154 pCS = new CPDF_ICCBasedCS();
1155 } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || id == FXBSTR_ID('I', 0, 0, 0)) {
1156 pCS = new CPDF_IndexedCS();
1157 } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) {
1158 pCS = new CPDF_SeparationCS();
1159 } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) {
1160 pCS = new CPDF_DeviceNCS();
1161 } else if (id == FXBSTR_ID('P', 'a', 't', 't')) {
1162 pCS = new CPDF_PatternCS();
1163 } else {
1164 return NULL;
1165 }
1166 pCS->m_pDocument = pDoc;
1167 pCS->m_pArray = pArray;
1168 if (!pCS->v_Load(pDoc, pArray)) {
1169 pCS->ReleaseCS();
1170 return NULL;
1171 }
1172 return pCS;
1173 }
CPDF_ColorSpace()1174 CPDF_ColorSpace::CPDF_ColorSpace()
1175 {
1176 m_Family = 0;
1177 m_pArray = NULL;
1178 m_dwStdConversion = 0;
1179 m_pDocument = NULL;
1180 }
ReleaseCS()1181 void CPDF_ColorSpace::ReleaseCS()
1182 {
1183 if (this == GetStockCS(PDFCS_DEVICERGB)) {
1184 return;
1185 }
1186 if (this == GetStockCS(PDFCS_DEVICEGRAY)) {
1187 return;
1188 }
1189 if (this == GetStockCS(PDFCS_DEVICECMYK)) {
1190 return;
1191 }
1192 if (this == GetStockCS(PDFCS_PATTERN)) {
1193 return;
1194 }
1195 delete this;
1196 }
GetBufSize() const1197 int CPDF_ColorSpace::GetBufSize() const
1198 {
1199 if (m_Family == PDFCS_PATTERN) {
1200 return sizeof(PatternValue);
1201 }
1202 return m_nComponents * sizeof(FX_FLOAT);
1203 }
CreateBuf()1204 FX_FLOAT* CPDF_ColorSpace::CreateBuf()
1205 {
1206 int size = GetBufSize();
1207 FX_BYTE* pBuf = FX_Alloc(FX_BYTE, size);
1208 return (FX_FLOAT*)pBuf;
1209 }
sRGB() const1210 FX_BOOL CPDF_ColorSpace::sRGB() const
1211 {
1212 if (m_Family == PDFCS_DEVICERGB) {
1213 return TRUE;
1214 }
1215 if (m_Family != PDFCS_ICCBASED) {
1216 return FALSE;
1217 }
1218 CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this;
1219 return pCS->m_pProfile->m_bsRGB;
1220 }
GetCMYK(FX_FLOAT * pBuf,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k) const1221 FX_BOOL CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
1222 {
1223 if (v_GetCMYK(pBuf, c, m, y, k)) {
1224 return TRUE;
1225 }
1226 FX_FLOAT R, G, B;
1227 if (!GetRGB(pBuf, R, G, B)) {
1228 return FALSE;
1229 }
1230 sRGB_to_AdobeCMYK(R, G, B, c, m, y, k);
1231 return TRUE;
1232 }
SetCMYK(FX_FLOAT * pBuf,FX_FLOAT c,FX_FLOAT m,FX_FLOAT y,FX_FLOAT k) const1233 FX_BOOL CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const
1234 {
1235 if (v_SetCMYK(pBuf, c, m, y, k)) {
1236 return TRUE;
1237 }
1238 FX_FLOAT R, G, B;
1239 AdobeCMYK_to_sRGB(c, m, y, k, R, G, B);
1240 return SetRGB(pBuf, R, G, B);
1241 }
GetDefaultColor(FX_FLOAT * buf) const1242 void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const
1243 {
1244 if (buf == NULL || m_Family == PDFCS_PATTERN) {
1245 return;
1246 }
1247 FX_FLOAT min, max;
1248 for (int i = 0; i < m_nComponents; i ++) {
1249 GetDefaultValue(i, buf[i], min, max);
1250 }
1251 }
GetMaxIndex() const1252 int CPDF_ColorSpace::GetMaxIndex() const
1253 {
1254 if (m_Family != PDFCS_INDEXED) {
1255 return 0;
1256 }
1257 CPDF_IndexedCS* pCS = (CPDF_IndexedCS*)this;
1258 return pCS->m_MaxIndex;
1259 }
TranslateImageLine(FX_LPBYTE dest_buf,FX_LPCBYTE src_buf,int pixels,int image_width,int image_height,FX_BOOL bTransMask) const1260 void CPDF_ColorSpace::TranslateImageLine(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
1261 {
1262 CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents);
1263 FX_FLOAT* src = srcbuf;
1264 FX_FLOAT R, G, B;
1265 for (int i = 0; i < pixels; i ++) {
1266 for (int j = 0; j < m_nComponents; j ++)
1267 if (m_Family == PDFCS_INDEXED) {
1268 src[j] = (FX_FLOAT)(*src_buf ++);
1269 } else {
1270 src[j] = (FX_FLOAT)(*src_buf ++) / 255;
1271 }
1272 GetRGB(src, R, G, B);
1273 *dest_buf ++ = (FX_INT32)(B * 255);
1274 *dest_buf ++ = (FX_INT32)(G * 255);
1275 *dest_buf ++ = (FX_INT32)(R * 255);
1276 }
1277 }
EnableStdConversion(FX_BOOL bEnabled)1278 void CPDF_ColorSpace::EnableStdConversion(FX_BOOL bEnabled)
1279 {
1280 if (bEnabled) {
1281 m_dwStdConversion ++;
1282 } else if (m_dwStdConversion) {
1283 m_dwStdConversion --;
1284 }
1285 }
CPDF_Color(int family)1286 CPDF_Color::CPDF_Color(int family)
1287 {
1288 m_pCS = CPDF_ColorSpace::GetStockCS(family);
1289 int nComps = 3;
1290 if (family == PDFCS_DEVICEGRAY) {
1291 nComps = 1;
1292 } else if (family == PDFCS_DEVICECMYK) {
1293 nComps = 4;
1294 }
1295 m_pBuffer = FX_Alloc(FX_FLOAT, nComps);
1296 for (int i = 0; i < nComps; i ++) {
1297 m_pBuffer[i] = 0;
1298 }
1299 }
~CPDF_Color()1300 CPDF_Color::~CPDF_Color()
1301 {
1302 ReleaseBuffer();
1303 ReleaseColorSpace();
1304 }
ReleaseBuffer()1305 void CPDF_Color::ReleaseBuffer()
1306 {
1307 if (!m_pBuffer) {
1308 return;
1309 }
1310 if (m_pCS->GetFamily() == PDFCS_PATTERN) {
1311 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1312 CPDF_Pattern* pPattern = pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->m_Obj : NULL;
1313 if (pPattern && pPattern->m_pDocument) {
1314 CPDF_DocPageData *pPageData = pPattern->m_pDocument->GetPageData();
1315 if (pPageData) {
1316 pPageData->ReleasePattern(pPattern->m_pPatternObj);
1317 }
1318 }
1319 }
1320 FX_Free(m_pBuffer);
1321 m_pBuffer = NULL;
1322 }
ReleaseColorSpace()1323 void CPDF_Color::ReleaseColorSpace()
1324 {
1325 if (m_pCS && m_pCS->m_pDocument && m_pCS->GetArray()) {
1326 m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray());
1327 m_pCS = NULL;
1328 }
1329 }
SetColorSpace(CPDF_ColorSpace * pCS)1330 void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS)
1331 {
1332 if (m_pCS == pCS) {
1333 if (m_pBuffer == NULL) {
1334 m_pBuffer = pCS->CreateBuf();
1335 }
1336 ReleaseColorSpace();
1337 m_pCS = pCS;
1338 return;
1339 }
1340 ReleaseBuffer();
1341 ReleaseColorSpace();
1342 m_pCS = pCS;
1343 if (m_pCS) {
1344 m_pBuffer = pCS->CreateBuf();
1345 pCS->GetDefaultColor(m_pBuffer);
1346 }
1347 }
SetValue(FX_FLOAT * comps)1348 void CPDF_Color::SetValue(FX_FLOAT* comps)
1349 {
1350 if (m_pBuffer == NULL) {
1351 return;
1352 }
1353 if (m_pCS->GetFamily() != PDFCS_PATTERN) {
1354 FXSYS_memcpy32(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT));
1355 }
1356 }
SetValue(CPDF_Pattern * pPattern,FX_FLOAT * comps,int ncomps)1357 void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps)
1358 {
1359 if (ncomps > MAX_PATTERN_COLORCOMPS) {
1360 return;
1361 }
1362 if (m_pCS == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1363 if (m_pBuffer) {
1364 FX_Free(m_pBuffer);
1365 }
1366 m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
1367 m_pBuffer = m_pCS->CreateBuf();
1368 }
1369 CPDF_DocPageData *pDocPageData = NULL;
1370 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1371 if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
1372 pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
1373 if (pDocPageData) {
1374 pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
1375 }
1376 }
1377 pvalue->m_nComps = ncomps;
1378 pvalue->m_pPattern = pPattern;
1379 if (ncomps) {
1380 FXSYS_memcpy32(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
1381 }
1382 pvalue->m_pCountedPattern = NULL;
1383 if (pPattern && pPattern->m_pDocument)
1384 {
1385 if (!pDocPageData) {
1386 pDocPageData = pPattern->m_pDocument->GetPageData();
1387 }
1388 pvalue->m_pCountedPattern = pDocPageData->FindPatternPtr(pPattern->m_pPatternObj);
1389 }
1390 }
Copy(const CPDF_Color * pSrc)1391 void CPDF_Color::Copy(const CPDF_Color* pSrc)
1392 {
1393 ReleaseBuffer();
1394 ReleaseColorSpace();
1395 m_pCS = pSrc->m_pCS;
1396 if (m_pCS && m_pCS->m_pDocument) {
1397 CPDF_Array* pArray = m_pCS->GetArray();
1398 if (pArray) {
1399 m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray);
1400 }
1401 }
1402 if (m_pCS == NULL) {
1403 return;
1404 }
1405 m_pBuffer = m_pCS->CreateBuf();
1406 FXSYS_memcpy32(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
1407 if (m_pCS->GetFamily() == PDFCS_PATTERN) {
1408 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1409 if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
1410 pvalue->m_pPattern = pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(pvalue->m_pPattern->m_pPatternObj, FALSE, &pvalue->m_pPattern->m_ParentMatrix);
1411 }
1412 }
1413 }
GetRGB(int & R,int & G,int & B) const1414 FX_BOOL CPDF_Color::GetRGB(int& R, int& G, int& B) const
1415 {
1416 if (m_pCS == NULL || m_pBuffer == NULL) {
1417 return FALSE;
1418 }
1419 FX_FLOAT r=0.0f, g=0.0f, b=0.0f;
1420 if (!m_pCS->GetRGB(m_pBuffer, r, g, b)) {
1421 return FALSE;
1422 }
1423 R = (FX_INT32)(r * 255 + 0.5f);
1424 G = (FX_INT32)(g * 255 + 0.5f);
1425 B = (FX_INT32)(b * 255 + 0.5f);
1426 return TRUE;
1427 }
GetPattern() const1428 CPDF_Pattern* CPDF_Color::GetPattern() const
1429 {
1430 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1431 return NULL;
1432 }
1433 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1434 return pvalue->m_pPattern;
1435 }
GetPatternCS() const1436 CPDF_ColorSpace* CPDF_Color::GetPatternCS() const
1437 {
1438 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1439 return NULL;
1440 }
1441 return m_pCS->GetBaseCS();
1442 }
GetPatternColor() const1443 FX_FLOAT* CPDF_Color::GetPatternColor() const
1444 {
1445 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1446 return NULL;
1447 }
1448 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1449 return pvalue->m_nComps ? pvalue->m_Comps : NULL;
1450 }
IsEqual(const CPDF_Color & other) const1451 FX_BOOL CPDF_Color::IsEqual(const CPDF_Color& other) const
1452 {
1453 if (m_pCS != other.m_pCS || m_pCS == NULL) {
1454 return FALSE;
1455 }
1456 return FXSYS_memcmp32(m_pBuffer, other.m_pBuffer, m_pCS->GetBufSize()) == 0;
1457 }
1458