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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fpdfapi/fpdf_page.h"
8 #include "../../../include/fpdfapi/fpdf_module.h"
9 #include "../../../include/fxcodec/fx_codec.h"
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)
25 CPDF_DeviceCS::CPDF_DeviceCS(int family)
28 if (m_Family == PDFCS_DEVICERGB) {
30 } else if (m_Family == PDFCS_DEVICEGRAY) {
36 FX_BOOL CPDF_DeviceCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
38 if (m_Family == PDFCS_DEVICERGB) {
57 } else if (m_Family == PDFCS_DEVICEGRAY) {
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);
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);
75 ASSERT(m_Family == PDFCS_PATTERN);
81 FX_BOOL CPDF_DeviceCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
83 if (m_Family != PDFCS_DEVICECMYK) {
92 FX_BOOL CPDF_DeviceCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
94 if (m_Family == PDFCS_DEVICERGB) {
99 } else if (m_Family == PDFCS_DEVICEGRAY) {
100 if (R == G && R == B) {
106 } else if (m_Family == PDFCS_DEVICECMYK) {
107 sRGB_to_AdobeCMYK(R, G, B, pBuf[0], pBuf[1], pBuf[2], pBuf[3]);
112 FX_BOOL CPDF_DeviceCS::v_SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const
114 if (m_Family == PDFCS_DEVICERGB) {
115 AdobeCMYK_to_sRGB(c, m, y, k, pBuf[0], pBuf[1], pBuf[2]);
117 } else if (m_Family == PDFCS_DEVICEGRAY) {
119 } else if (m_Family == PDFCS_DEVICECMYK) {
128 static void ReverseRGB(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels)
130 if (pDestBuf == pSrcBuf)
131 for (int i = 0; i < pixels; i ++) {
132 FX_BYTE temp = pDestBuf[2];
133 pDestBuf[2] = pDestBuf[0];
138 for (int i = 0; i < pixels; i ++) {
139 *pDestBuf ++ = pSrcBuf[2];
140 *pDestBuf ++ = pSrcBuf[1];
141 *pDestBuf ++ = pSrcBuf[0];
145 void CPDF_DeviceCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
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;
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];
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]);
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);
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,
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,
211 static FX_FLOAT RGB_Conversion(FX_FLOAT colorComponent)
213 if (colorComponent > 1) {
216 if (colorComponent < 0) {
219 int scale = (int)(colorComponent * 1023);
224 colorComponent = (g_sRGBSamples1[scale] / 255.0f);
227 colorComponent = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
229 return colorComponent;
232 static void XYZ_to_sRGB(FX_FLOAT X, FX_FLOAT Y, FX_FLOAT Z, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B)
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;
238 R = RGB_Conversion(R1);
239 G = RGB_Conversion(G1);
240 B = RGB_Conversion(B1);
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)
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}
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);
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);
260 R = RGB_Conversion(RGB.a);
261 G = RGB_Conversion(RGB.b);
262 B = RGB_Conversion(RGB.c);
264 class CPDF_CalGray : public CPDF_ColorSpace
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];
276 CPDF_CalGray::CPDF_CalGray()
278 m_Family = PDFCS_CALGRAY;
281 FX_BOOL CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
283 CPDF_Dictionary* pDict = pArray->GetDict(1);
284 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
286 for (i = 0; i < 3; i ++) {
287 m_WhitePoint[i] = pParam ? pParam->GetNumber(i) : 0;
289 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
290 for (i = 0; i < 3; i ++) {
291 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
293 m_Gamma = pDict->GetNumber(FX_BSTRC("Gamma"));
299 FX_BOOL CPDF_CalGray::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
304 FX_BOOL CPDF_CalGray::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
306 if (R == G && R == B) {
313 void CPDF_CalGray::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
315 for (int i = 0; i < pixels; i ++) {
316 *pDestBuf ++ = pSrcBuf[i];
317 *pDestBuf ++ = pSrcBuf[i];
318 *pDestBuf ++ = pSrcBuf[i];
321 class CPDF_CalRGB : public CPDF_ColorSpace
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];
332 FX_FLOAT m_Matrix[9];
333 FX_BOOL m_bGamma, m_bMatrix;
335 CPDF_CalRGB::CPDF_CalRGB()
337 m_Family = PDFCS_CALRGB;
340 FX_BOOL CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
342 CPDF_Dictionary* pDict = pArray->GetDict(1);
343 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
345 for (i = 0; i < 3; i ++) {
346 m_WhitePoint[i] = pParam ? pParam->GetNumber(i) : 0;
348 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
349 for (i = 0; i < 3; i ++) {
350 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
352 pParam = pDict->GetArray(FX_BSTRC("Gamma"));
355 for (i = 0; i < 3; i ++) {
356 m_Gamma[i] = pParam->GetNumber(i);
361 pParam = pDict->GetArray(FX_BSTRC("Matrix"));
364 for (i = 0; i < 9; i ++) {
365 m_Matrix[i] = pParam->GetNumber(i);
372 FX_BOOL CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
374 FX_FLOAT A_ = pBuf[0];
375 FX_FLOAT B_ = pBuf[1];
376 FX_FLOAT C_ = pBuf[2];
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]);
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_;
392 XYZ_to_sRGB_WhitePoint(X, Y, Z, R, G, B, m_WhitePoint[0], m_WhitePoint[1], m_WhitePoint[2]);
395 FX_BOOL CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
402 void CPDF_CalRGB::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
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);
419 ReverseRGB(pDestBuf, pSrcBuf, pixels);
421 class CPDF_LabCS : public CPDF_ColorSpace
426 m_Family = PDFCS_LAB;
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];
438 FX_BOOL CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
440 CPDF_Dictionary* pDict = pArray->GetDict(1);
441 CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint"));
443 for (i = 0; i < 3; i ++) {
444 m_WhitePoint[i] = pParam ? pParam->GetNumber(i) : 0;
446 pParam = pDict->GetArray(FX_BSTRC("BlackPoint"));
447 for (i = 0; i < 3; i ++) {
448 m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0;
450 pParam = pDict->GetArray(FX_BSTRC("Range"));
451 const FX_FLOAT def_ranges[4] = { -100 * 1.0f, 100 * 1.0f, -100 * 1.0f, 100 * 1.0f};
452 for (i = 0; i < 4; i ++) {
453 m_Ranges[i] = pParam ? pParam->GetNumber(i) : def_ranges[i];
457 void CPDF_LabCS::GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
459 assert(iComponent < 3);
461 if (iComponent == 0) {
465 min = m_Ranges[iComponent * 2 - 2];
466 max = m_Ranges[iComponent * 2 - 1];
469 } else if (value > max) {
474 FX_BOOL CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
476 FX_FLOAT Lstar = pBuf[0];
477 FX_FLOAT astar = pBuf[1];
478 FX_FLOAT bstar = pBuf[2];
479 FX_FLOAT M = (Lstar + 16.0f) / 116.0f;
480 FX_FLOAT L = M + astar / 500.0f;
481 FX_FLOAT N = M - bstar / 200.0f;
484 X = 0.957f * 0.12842f * (L - 0.1379f);
486 X = 0.957f * L * L * L;
489 Y = 0.12842f * (M - 0.1379f);
494 Z = 1.0889f * 0.12842f * (N - 0.1379f);
496 Z = 1.0889f * N * N * N;
498 XYZ_to_sRGB(X, Y, Z, R, G, B);
501 FX_BOOL CPDF_LabCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
505 void CPDF_LabCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
507 for (int i = 0; i < pixels; i ++) {
510 lab[0] = (pSrcBuf[0] * 100 / 255.0f);
511 lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128);
512 lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128);
513 GetRGB(lab, R, G, B);
514 pDestBuf[0] = (FX_INT32)(B * 255);
515 pDestBuf[1] = (FX_INT32)(G * 255);
516 pDestBuf[2] = (FX_INT32)(R * 255);
521 CPDF_IccProfile::CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize):
526 if (dwSize == 3144 && FXSYS_memcmp32(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0) {
528 m_nSrcComponents = 3;
530 else if (CPDF_ModuleMgr::Get()->GetIccModule()) {
531 m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(pData, dwSize, m_nSrcComponents);
534 CPDF_IccProfile::~CPDF_IccProfile()
537 CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform);
540 class CPDF_ICCBasedCS : public CPDF_ColorSpace
544 virtual ~CPDF_ICCBasedCS();
545 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
546 void GetDefaultValue(int i, FX_FLOAT& min, FX_FLOAT& max) const
548 min = m_pRanges[i * 2];
549 max = m_pRanges[i * 2 + 1];
551 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
552 FX_BOOL v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const;
553 FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const;
554 virtual void EnableStdConversion(FX_BOOL bEnabled);
555 virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;
557 CPDF_IccProfile* m_pProfile;
558 CPDF_ColorSpace* m_pAlterCS;
562 CPDF_ICCBasedCS::CPDF_ICCBasedCS()
566 m_Family = PDFCS_ICCBASED;
571 CPDF_ICCBasedCS::~CPDF_ICCBasedCS()
579 if (m_pAlterCS && m_bOwn) {
580 m_pAlterCS->ReleaseCS();
582 if (m_pProfile && m_pDocument) {
583 m_pDocument->GetPageData()->ReleaseIccProfile(NULL, m_pProfile);
586 FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
588 CPDF_Stream* pStream = pArray->GetStream(1);
589 if (pStream == NULL) {
592 m_pProfile = pDoc->LoadIccProfile(pStream);
596 m_nComponents = m_pProfile->GetComponents(); //Try using the nComponents from ICC profile
597 CPDF_Dictionary* pDict = pStream->GetDict();
598 if (m_pProfile->m_pTransform == NULL) { // No valid ICC profile or using sRGB
599 CPDF_Object* pAlterCSObj = pDict ? pDict->GetElementValue(FX_BSTRC("Alternate")) : NULL;
601 CPDF_ColorSpace* pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
603 if (m_nComponents == 0) { // NO valid ICC profile
604 if (pAlterCS->CountComponents() > 0) { // Use Alternative colorspace
605 m_nComponents = pAlterCS->CountComponents();
606 m_pAlterCS = pAlterCS;
609 else { // No valid alternative colorspace
610 pAlterCS->ReleaseCS();
611 FX_INT32 nDictComponents = pDict ? pDict->GetInteger(FX_BSTRC("N")) : 0;
612 if (nDictComponents != 1 && nDictComponents != 3 && nDictComponents != 4) {
615 m_nComponents = nDictComponents;
620 if (pAlterCS->CountComponents() != m_nComponents) {
621 pAlterCS->ReleaseCS();
624 m_pAlterCS = pAlterCS;
631 if (m_nComponents == 1) {
632 m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
634 else if (m_nComponents == 3) {
635 m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
637 else if (m_nComponents == 4) {
638 m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
642 CPDF_Array* pRanges = pDict->GetArray(FX_BSTRC("Range"));
643 m_pRanges = FX_Alloc(FX_FLOAT, m_nComponents * 2);
644 for (int i = 0; i < m_nComponents * 2; i ++) {
646 m_pRanges[i] = pRanges->GetNumber(i);
655 FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
657 if (m_pProfile && m_pProfile->m_bsRGB) {
663 ICodec_IccModule *pIccModule = CPDF_ModuleMgr::Get()->GetIccModule();
664 if (m_pProfile->m_pTransform == NULL || pIccModule == NULL) {
666 m_pAlterCS->GetRGB(pBuf, R, G, B);
673 pIccModule->SetComponents(m_nComponents);
674 pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb);
680 FX_BOOL CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
682 if (m_nComponents != 4) {
691 FX_BOOL CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const
695 void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled)
697 CPDF_ColorSpace::EnableStdConversion(bEnabled);
699 m_pAlterCS->EnableStdConversion(bEnabled);
702 void CPDF_ICCBasedCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
704 if (m_pProfile->m_bsRGB) {
705 ReverseRGB(pDestBuf, pSrcBuf, pixels);
706 } else if (m_pProfile->m_pTransform) {
708 for (int i = 0; i < m_nComponents; i ++) {
711 if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) {
712 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels);
714 if (m_pCache == NULL) {
715 ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc(FX_BYTE, nMaxColors * 3);
716 FX_LPBYTE temp_src = FX_Alloc(FX_BYTE, nMaxColors * m_nComponents);
717 FX_LPBYTE pSrc = temp_src;
718 for (int i = 0; i < nMaxColors; i ++) {
720 FX_DWORD order = nMaxColors / 52;
721 for (int c = 0; c < m_nComponents; c ++) {
722 *pSrc++ = (FX_BYTE)(color / order * 5);
727 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors);
730 for (int i = 0; i < pixels; i ++) {
732 for (int c = 0; c < m_nComponents; c ++) {
733 index = index * 52 + (*pSrcBuf) / 5;
737 *pDestBuf++ = m_pCache[index];
738 *pDestBuf++ = m_pCache[index + 1];
739 *pDestBuf++ = m_pCache[index + 2];
742 } else if (m_pAlterCS) {
743 m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, image_height);
746 class CPDF_IndexedCS : public CPDF_ColorSpace
750 virtual ~CPDF_IndexedCS();
751 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
752 void GetDefaultValue(int iComponent, FX_FLOAT& min, FX_FLOAT& max) const
755 max = (FX_FLOAT)m_MaxIndex;
757 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
758 virtual CPDF_ColorSpace* GetBaseCS() const
762 virtual void EnableStdConversion(FX_BOOL bEnabled);
763 CPDF_ColorSpace* m_pBaseCS;
764 CPDF_CountedColorSpace* m_pCountedBaseCS;
765 int m_nBaseComponents;
767 CFX_ByteString m_Table;
768 FX_FLOAT* m_pCompMinMax;
770 CPDF_IndexedCS::CPDF_IndexedCS()
773 m_pCountedBaseCS = NULL;
774 m_Family = PDFCS_INDEXED;
776 m_pCompMinMax = NULL;
778 CPDF_IndexedCS::~CPDF_IndexedCS()
781 FX_Free(m_pCompMinMax);
783 CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->m_Obj : NULL;
784 if (pCS && m_pDocument) {
785 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
788 FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
790 if (pArray->GetCount() < 4) {
793 CPDF_Object* pBaseObj = pArray->GetElementValue(1);
794 if (pBaseObj == m_pArray) {
797 CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
798 m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL);
799 if (m_pBaseCS == NULL) {
802 m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
803 m_nBaseComponents = m_pBaseCS->CountComponents();
804 m_pCompMinMax = FX_Alloc(FX_FLOAT, m_nBaseComponents * 2);
806 for (int i = 0; i < m_nBaseComponents; i ++) {
807 m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], m_pCompMinMax[i * 2 + 1]);
808 m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2];
810 m_MaxIndex = pArray->GetInteger(2);
811 CPDF_Object* pTableObj = pArray->GetElementValue(3);
812 if (pTableObj == NULL) {
815 if (pTableObj->GetType() == PDFOBJ_STRING) {
816 m_Table = ((CPDF_String*)pTableObj)->GetString();
817 } else if (pTableObj->GetType() == PDFOBJ_STREAM) {
819 acc.LoadAllData((CPDF_Stream*)pTableObj, FALSE);
820 m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize());
824 FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
826 int index = (FX_INT32)(*pBuf);
827 if (index < 0 || index > m_MaxIndex) {
830 if (m_nBaseComponents) {
831 if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents ||
832 (index + 1)*m_nBaseComponents > (int)m_Table.GetLength()) {
837 CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents);
838 FX_FLOAT* comps = Comps;
839 FX_LPCBYTE pTable = m_Table;
840 for (int i = 0; i < m_nBaseComponents; i ++) {
841 comps[i] = m_pCompMinMax[i * 2] + m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255;
843 m_pBaseCS->GetRGB(comps, R, G, B);
846 void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled)
848 CPDF_ColorSpace::EnableStdConversion(bEnabled);
850 m_pBaseCS->EnableStdConversion(bEnabled);
853 #define MAX_PATTERN_COLORCOMPS 16
854 typedef struct _PatternValue {
855 CPDF_Pattern* m_pPattern;
856 CPDF_CountedPattern* m_pCountedPattern;
858 FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS];
860 CPDF_PatternCS::CPDF_PatternCS()
862 m_Family = PDFCS_PATTERN;
865 m_pCountedBaseCS = NULL;
867 CPDF_PatternCS::~CPDF_PatternCS()
869 CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->m_Obj : NULL;
870 if (pCS && m_pDocument) {
871 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
874 FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
876 CPDF_Object* pBaseCS = pArray->GetElementValue(1);
877 if (pBaseCS == m_pArray) {
880 CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
881 m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, NULL);
883 if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) {
886 m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
887 m_nComponents = m_pBaseCS->CountComponents() + 1;
888 if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) {
896 FX_BOOL CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
899 ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN);
900 PatternValue* pvalue = (PatternValue*)pBuf;
901 if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) {
908 class CPDF_SeparationCS : public CPDF_ColorSpace
912 virtual ~CPDF_SeparationCS();
913 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
919 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
920 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
921 virtual void EnableStdConversion(FX_BOOL bEnabled);
922 CPDF_ColorSpace* m_pAltCS;
923 CPDF_Function* m_pFunc;
924 enum {None, All, Colorant} m_Type;
926 CPDF_SeparationCS::CPDF_SeparationCS()
928 m_Family = PDFCS_SEPARATION;
933 CPDF_SeparationCS::~CPDF_SeparationCS()
936 m_pAltCS->ReleaseCS();
942 FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
944 CFX_ByteString name = pArray->GetString(1);
945 if (name == FX_BSTRC("None")) {
949 CPDF_Object* pAltCS = pArray->GetElementValue(2);
950 if (pAltCS == m_pArray) {
953 m_pAltCS = Load(pDoc, pAltCS);
954 CPDF_Object* pFuncObj = pArray->GetElementValue(3);
955 if (pFuncObj && pFuncObj->GetType() != PDFOBJ_NAME) {
956 m_pFunc = CPDF_Function::Load(pFuncObj);
958 if (m_pFunc && m_pAltCS && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
965 FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
967 if (m_Type == None) {
970 if (m_pFunc == NULL) {
971 if (m_pAltCS == NULL) {
974 int nComps = m_pAltCS->CountComponents();
975 CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps);
976 for (int i = 0; i < nComps; i ++) {
979 m_pAltCS->GetRGB(results, R, G, B);
982 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
984 m_pFunc->Call(pBuf, 1, results, nresults);
989 m_pAltCS->GetRGB(results, R, G, B);
996 void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled)
998 CPDF_ColorSpace::EnableStdConversion(bEnabled);
1000 m_pAltCS->EnableStdConversion(bEnabled);
1003 class CPDF_DeviceNCS : public CPDF_ColorSpace
1007 virtual ~CPDF_DeviceNCS();
1008 virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
1014 virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray);
1015 virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const;
1016 virtual void EnableStdConversion(FX_BOOL bEnabled);
1017 CPDF_ColorSpace* m_pAltCS;
1018 CPDF_Function* m_pFunc;
1020 CPDF_DeviceNCS::CPDF_DeviceNCS()
1022 m_Family = PDFCS_DEVICEN;
1026 CPDF_DeviceNCS::~CPDF_DeviceNCS()
1032 m_pAltCS->ReleaseCS();
1035 FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
1037 CPDF_Object* pObj = pArray->GetElementValue(1);
1041 if (pObj->GetType() != PDFOBJ_ARRAY) {
1044 m_nComponents = ((CPDF_Array*)pObj)->GetCount();
1045 CPDF_Object* pAltCS = pArray->GetElementValue(2);
1046 if (!pAltCS || pAltCS == m_pArray) {
1049 m_pAltCS = Load(pDoc, pAltCS);
1050 m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3));
1051 if (m_pAltCS == NULL || m_pFunc == NULL) {
1054 if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
1059 FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
1061 if (m_pFunc == NULL) {
1064 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
1066 m_pFunc->Call(pBuf, m_nComponents, results, nresults);
1067 if (nresults == 0) {
1070 m_pAltCS->GetRGB(results, R, G, B);
1073 void CPDF_DeviceNCS::EnableStdConversion(FX_BOOL bEnabled)
1075 CPDF_ColorSpace::EnableStdConversion(bEnabled);
1077 m_pAltCS->EnableStdConversion(bEnabled);
1080 CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family)
1082 return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family);;
1084 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name)
1086 if (name == FX_BSTRC("DeviceRGB") || name == FX_BSTRC("RGB")) {
1087 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
1089 if (name == FX_BSTRC("DeviceGray") || name == FX_BSTRC("G")) {
1090 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
1092 if (name == FX_BSTRC("DeviceCMYK") || name == FX_BSTRC("CMYK")) {
1093 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
1095 if (name == FX_BSTRC("Pattern")) {
1096 return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
1100 CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj)
1105 if (pObj->GetType() == PDFOBJ_NAME) {
1106 return _CSFromName(pObj->GetString());
1108 if (pObj->GetType() == PDFOBJ_STREAM) {
1109 CPDF_Dictionary *pDict = ((CPDF_Stream *)pObj)->GetDict();
1113 CPDF_ColorSpace *pRet = NULL;
1114 FX_POSITION pos = pDict->GetStartPos();
1116 CFX_ByteString bsKey;
1117 CPDF_Object *pValue = pDict->GetNextElement(pos, bsKey);
1118 if (pValue && pValue->GetType() == PDFOBJ_NAME) {
1119 pRet = _CSFromName(pValue->GetString());
1127 if (pObj->GetType() != PDFOBJ_ARRAY) {
1130 CPDF_Array* pArray = (CPDF_Array*)pObj;
1131 if (pArray->GetCount() == 0) {
1134 CPDF_Object *pFamilyObj = pArray->GetElementValue(0);
1138 CFX_ByteString familyname = pFamilyObj->GetString();
1139 if (pArray->GetCount() == 1) {
1140 return _CSFromName(familyname);
1142 CPDF_ColorSpace* pCS = NULL;
1143 FX_DWORD id = familyname.GetID();
1144 if (id == FXBSTR_ID('C', 'a', 'l', 'G')) {
1145 pCS = FX_NEW CPDF_CalGray();
1146 } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) {
1147 pCS = FX_NEW CPDF_CalRGB();
1148 } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) {
1149 pCS = FX_NEW CPDF_LabCS();
1150 } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) {
1151 pCS = FX_NEW CPDF_ICCBasedCS();
1152 } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || id == FXBSTR_ID('I', 0, 0, 0)) {
1153 pCS = FX_NEW CPDF_IndexedCS();
1154 } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) {
1155 pCS = FX_NEW CPDF_SeparationCS();
1156 } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) {
1157 pCS = FX_NEW CPDF_DeviceNCS();
1158 } else if (id == FXBSTR_ID('P', 'a', 't', 't')) {
1159 pCS = FX_NEW CPDF_PatternCS();
1163 pCS->m_pDocument = pDoc;
1164 pCS->m_pArray = pArray;
1165 if (!pCS->v_Load(pDoc, pArray)) {
1171 CPDF_ColorSpace::CPDF_ColorSpace()
1175 m_dwStdConversion = 0;
1178 void CPDF_ColorSpace::ReleaseCS()
1180 if (this == GetStockCS(PDFCS_DEVICERGB)) {
1183 if (this == GetStockCS(PDFCS_DEVICEGRAY)) {
1186 if (this == GetStockCS(PDFCS_DEVICECMYK)) {
1189 if (this == GetStockCS(PDFCS_PATTERN)) {
1194 int CPDF_ColorSpace::GetBufSize() const
1196 if (m_Family == PDFCS_PATTERN) {
1197 return sizeof(PatternValue);
1199 return m_nComponents * sizeof(FX_FLOAT);
1201 FX_FLOAT* CPDF_ColorSpace::CreateBuf()
1203 int size = GetBufSize();
1204 FX_BYTE* pBuf = FX_Alloc(FX_BYTE, size);
1205 return (FX_FLOAT*)pBuf;
1207 FX_BOOL CPDF_ColorSpace::sRGB() const
1209 if (m_Family == PDFCS_DEVICERGB) {
1212 if (m_Family != PDFCS_ICCBASED) {
1215 CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this;
1216 return pCS->m_pProfile->m_bsRGB;
1218 FX_BOOL CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const
1220 if (v_GetCMYK(pBuf, c, m, y, k)) {
1224 if (!GetRGB(pBuf, R, G, B)) {
1227 sRGB_to_AdobeCMYK(R, G, B, c, m, y, k);
1230 FX_BOOL CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const
1232 if (v_SetCMYK(pBuf, c, m, y, k)) {
1236 AdobeCMYK_to_sRGB(c, m, y, k, R, G, B);
1237 return SetRGB(pBuf, R, G, B);
1239 void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const
1241 if (buf == NULL || m_Family == PDFCS_PATTERN) {
1245 for (int i = 0; i < m_nComponents; i ++) {
1246 GetDefaultValue(i, buf[i], min, max);
1249 int CPDF_ColorSpace::GetMaxIndex() const
1251 if (m_Family != PDFCS_INDEXED) {
1254 CPDF_IndexedCS* pCS = (CPDF_IndexedCS*)this;
1255 return pCS->m_MaxIndex;
1257 void CPDF_ColorSpace::TranslateImageLine(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
1259 CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents);
1260 FX_FLOAT* src = srcbuf;
1262 for (int i = 0; i < pixels; i ++) {
1263 for (int j = 0; j < m_nComponents; j ++)
1264 if (m_Family == PDFCS_INDEXED) {
1265 src[j] = (FX_FLOAT)(*src_buf ++);
1267 src[j] = (FX_FLOAT)(*src_buf ++) / 255;
1269 GetRGB(src, R, G, B);
1270 *dest_buf ++ = (FX_INT32)(B * 255);
1271 *dest_buf ++ = (FX_INT32)(G * 255);
1272 *dest_buf ++ = (FX_INT32)(R * 255);
1275 void CPDF_ColorSpace::EnableStdConversion(FX_BOOL bEnabled)
1278 m_dwStdConversion ++;
1279 } else if (m_dwStdConversion) {
1280 m_dwStdConversion --;
1283 CPDF_Color::CPDF_Color(int family)
1285 m_pCS = CPDF_ColorSpace::GetStockCS(family);
1287 if (family == PDFCS_DEVICEGRAY) {
1289 } else if (family == PDFCS_DEVICECMYK) {
1292 m_pBuffer = FX_Alloc(FX_FLOAT, nComps);
1293 for (int i = 0; i < nComps; i ++) {
1297 CPDF_Color::~CPDF_Color()
1300 ReleaseColorSpace();
1302 void CPDF_Color::ReleaseBuffer()
1307 if (m_pCS->GetFamily() == PDFCS_PATTERN) {
1308 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1309 CPDF_Pattern* pPattern = pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->m_Obj : NULL;
1310 if (pPattern && pPattern->m_pDocument) {
1311 CPDF_DocPageData *pPageData = pPattern->m_pDocument->GetPageData();
1313 pPageData->ReleasePattern(pPattern->m_pPatternObj);
1320 void CPDF_Color::ReleaseColorSpace()
1322 if (m_pCS && m_pCS->m_pDocument && m_pCS->GetArray()) {
1323 m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray());
1327 void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS)
1330 if (m_pBuffer == NULL) {
1331 m_pBuffer = pCS->CreateBuf();
1333 ReleaseColorSpace();
1338 ReleaseColorSpace();
1341 m_pBuffer = pCS->CreateBuf();
1342 pCS->GetDefaultColor(m_pBuffer);
1345 void CPDF_Color::SetValue(FX_FLOAT* comps)
1347 if (m_pBuffer == NULL) {
1350 if (m_pCS->GetFamily() != PDFCS_PATTERN) {
1351 FXSYS_memcpy32(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT));
1354 void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps)
1356 if (ncomps > MAX_PATTERN_COLORCOMPS) {
1359 if (m_pCS == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1363 m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
1364 m_pBuffer = m_pCS->CreateBuf();
1366 CPDF_DocPageData *pDocPageData = NULL;
1367 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1368 if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
1369 pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
1371 pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
1374 pvalue->m_nComps = ncomps;
1375 pvalue->m_pPattern = pPattern;
1377 FXSYS_memcpy32(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
1379 pvalue->m_pCountedPattern = NULL;
1380 if (pPattern && pPattern->m_pDocument)
1382 if (!pDocPageData) {
1383 pDocPageData = pPattern->m_pDocument->GetPageData();
1385 pvalue->m_pCountedPattern = pDocPageData->FindPatternPtr(pPattern->m_pPatternObj);
1388 void CPDF_Color::Copy(const CPDF_Color* pSrc)
1391 ReleaseColorSpace();
1392 m_pCS = pSrc->m_pCS;
1393 if (m_pCS && m_pCS->m_pDocument) {
1394 CPDF_Array* pArray = m_pCS->GetArray();
1396 m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray);
1399 if (m_pCS == NULL) {
1402 m_pBuffer = m_pCS->CreateBuf();
1403 FXSYS_memcpy32(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
1404 if (m_pCS->GetFamily() == PDFCS_PATTERN) {
1405 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1406 if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
1407 pvalue->m_pPattern = pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(pvalue->m_pPattern->m_pPatternObj, FALSE, &pvalue->m_pPattern->m_ParentMatrix);
1411 FX_BOOL CPDF_Color::GetRGB(int& R, int& G, int& B) const
1413 if (m_pCS == NULL || m_pBuffer == NULL) {
1416 FX_FLOAT r=0.0f, g=0.0f, b=0.0f;
1417 if (!m_pCS->GetRGB(m_pBuffer, r, g, b)) {
1420 R = (FX_INT32)(r * 255 + 0.5f);
1421 G = (FX_INT32)(g * 255 + 0.5f);
1422 B = (FX_INT32)(b * 255 + 0.5f);
1425 CPDF_Pattern* CPDF_Color::GetPattern() const
1427 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1430 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1431 return pvalue->m_pPattern;
1433 CPDF_ColorSpace* CPDF_Color::GetPatternCS() const
1435 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1438 return m_pCS->GetBaseCS();
1440 FX_FLOAT* CPDF_Color::GetPatternColor() const
1442 if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) {
1445 PatternValue* pvalue = (PatternValue*)m_pBuffer;
1446 return pvalue->m_nComps ? pvalue->m_Comps : NULL;
1448 FX_BOOL CPDF_Color::IsEqual(const CPDF_Color& other) const
1450 if (m_pCS != other.m_pCS || m_pCS == NULL) {
1453 return FXSYS_memcmp32(m_pBuffer, other.m_pBuffer, m_pCS->GetBufSize()) == 0;