// Copyright 2014 PDFium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
#include "../../../include/fpdfapi/fpdf_page.h" | |
#include "../../../include/fpdfapi/fpdf_module.h" | |
#include "../../../include/fxcodec/fx_codec.h" | |
#include "pageint.h" | |
#include <limits.h> | |
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) | |
{ | |
c = 1.0f - R; | |
m = 1.0f - G; | |
y = 1.0f - B; | |
k = c; | |
if (m < k) { | |
k = m; | |
} | |
if (y < k) { | |
k = y; | |
} | |
} | |
CPDF_DeviceCS::CPDF_DeviceCS(int family) | |
{ | |
m_Family = family; | |
if (m_Family == PDFCS_DEVICERGB) { | |
m_nComponents = 3; | |
} else if (m_Family == PDFCS_DEVICEGRAY) { | |
m_nComponents = 1; | |
} else { | |
m_nComponents = 4; | |
} | |
} | |
FX_BOOL CPDF_DeviceCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
if (m_Family == PDFCS_DEVICERGB) { | |
R = pBuf[0]; | |
if (R < 0) { | |
R = 0; | |
} else if (R > 1) { | |
R = 1; | |
} | |
G = pBuf[1]; | |
if (G < 0) { | |
G = 0; | |
} else if (G > 1) { | |
G = 1; | |
} | |
B = pBuf[2]; | |
if (B < 0) { | |
B = 0; | |
} else if (B > 1) { | |
B = 1; | |
} | |
} else if (m_Family == PDFCS_DEVICEGRAY) { | |
R = *pBuf; | |
if (R < 0) { | |
R = 0; | |
} else if (R > 1) { | |
R = 1; | |
} | |
G = B = R; | |
} else if (m_Family == PDFCS_DEVICECMYK) { | |
if (!m_dwStdConversion) { | |
AdobeCMYK_to_sRGB(pBuf[0], pBuf[1], pBuf[2], pBuf[3], R, G, B); | |
} else { | |
FX_FLOAT k = pBuf[3]; | |
R = 1.0f - FX_MIN(1.0f, pBuf[0] + k); | |
G = 1.0f - FX_MIN(1.0f, pBuf[1] + k); | |
B = 1.0f - FX_MIN(1.0f, pBuf[2] + k); | |
} | |
} else { | |
ASSERT(m_Family == PDFCS_PATTERN); | |
R = G = B = 0; | |
return FALSE; | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_DeviceCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const | |
{ | |
if (m_Family != PDFCS_DEVICECMYK) { | |
return FALSE; | |
} | |
c = pBuf[0]; | |
m = pBuf[1]; | |
y = pBuf[2]; | |
k = pBuf[3]; | |
return TRUE; | |
} | |
FX_BOOL CPDF_DeviceCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const | |
{ | |
if (m_Family == PDFCS_DEVICERGB) { | |
pBuf[0] = R; | |
pBuf[1] = G; | |
pBuf[2] = B; | |
return TRUE; | |
} else if (m_Family == PDFCS_DEVICEGRAY) { | |
if (R == G && R == B) { | |
*pBuf = R; | |
return TRUE; | |
} else { | |
return FALSE; | |
} | |
} else if (m_Family == PDFCS_DEVICECMYK) { | |
sRGB_to_AdobeCMYK(R, G, B, pBuf[0], pBuf[1], pBuf[2], pBuf[3]); | |
return TRUE; | |
} | |
return FALSE; | |
} | |
FX_BOOL CPDF_DeviceCS::v_SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const | |
{ | |
if (m_Family == PDFCS_DEVICERGB) { | |
AdobeCMYK_to_sRGB(c, m, y, k, pBuf[0], pBuf[1], pBuf[2]); | |
return TRUE; | |
} else if (m_Family == PDFCS_DEVICEGRAY) { | |
return FALSE; | |
} else if (m_Family == PDFCS_DEVICECMYK) { | |
pBuf[0] = c; | |
pBuf[1] = m; | |
pBuf[2] = y; | |
pBuf[3] = k; | |
return TRUE; | |
} | |
return FALSE; | |
} | |
static void ReverseRGB(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels) | |
{ | |
if (pDestBuf == pSrcBuf) | |
for (int i = 0; i < pixels; i ++) { | |
FX_BYTE temp = pDestBuf[2]; | |
pDestBuf[2] = pDestBuf[0]; | |
pDestBuf[0] = temp; | |
pDestBuf += 3; | |
} | |
else | |
for (int i = 0; i < pixels; i ++) { | |
*pDestBuf ++ = pSrcBuf[2]; | |
*pDestBuf ++ = pSrcBuf[1]; | |
*pDestBuf ++ = pSrcBuf[0]; | |
pSrcBuf += 3; | |
} | |
} | |
void CPDF_DeviceCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const | |
{ | |
if (bTransMask && m_Family == PDFCS_DEVICECMYK) { | |
for (int i = 0; i < pixels; i ++) { | |
int k = 255 - pSrcBuf[3]; | |
pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255; | |
pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255; | |
pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255; | |
pDestBuf += 3; | |
pSrcBuf += 4; | |
} | |
return; | |
} | |
if (m_Family == PDFCS_DEVICERGB) { | |
ReverseRGB(pDestBuf, pSrcBuf, pixels); | |
} else if (m_Family == PDFCS_DEVICEGRAY) { | |
for (int i = 0; i < pixels; i ++) { | |
*pDestBuf ++ = pSrcBuf[i]; | |
*pDestBuf ++ = pSrcBuf[i]; | |
*pDestBuf ++ = pSrcBuf[i]; | |
} | |
} else { | |
for (int i = 0; i < pixels; i ++) { | |
if (!m_dwStdConversion) { | |
AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2], pSrcBuf[3], pDestBuf[2], pDestBuf[1], pDestBuf[0]); | |
} else { | |
FX_BYTE k = pSrcBuf[3]; | |
pDestBuf[2] = 255 - FX_MIN(255, pSrcBuf[0] + k); | |
pDestBuf[1] = 255 - FX_MIN(255, pSrcBuf[1] + k); | |
pDestBuf[0] = 255 - FX_MIN(255, pSrcBuf[2] + k); | |
} | |
pSrcBuf += 4; | |
pDestBuf += 3; | |
} | |
} | |
} | |
const FX_BYTE g_sRGBSamples1[] = { | |
0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31, 32, | |
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, | |
49, 50, 51, 52, 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, | |
61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, | |
71, 71, 72, 72, 73, 73, 74, 74, 75, 76, 76, 77, 77, 78, 78, 79, | |
79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 85, 86, | |
86, 87, 87, 88, 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, 92, 93, | |
93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 97, 97, 98, 98, 98, 99, | |
99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, | |
105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, | |
110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, | |
115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120, | |
}; | |
const FX_BYTE g_sRGBSamples2[] = { | |
120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, | |
137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151, | |
152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, | |
165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 175, 176, | |
177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184, 185, 185, 186, 187, 187, | |
188, 189, 189, 190, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 197, | |
198, 199, 199, 200, 200, 201, 202, 202, 203, 203, 204, 205, 205, 206, 206, 207, | |
208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, | |
216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, | |
225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, | |
233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, | |
241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, | |
248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255, | |
}; | |
static void XYZ_to_sRGB(FX_FLOAT X, FX_FLOAT Y, FX_FLOAT Z, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) | |
{ | |
FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z; | |
FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z; | |
FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z; | |
if (R1 > 1) { | |
R1 = 1; | |
} | |
if (R1 < 0) { | |
R1 = 0; | |
} | |
if (G1 > 1) { | |
G1 = 1; | |
} | |
if (G1 < 0) { | |
G1 = 0; | |
} | |
if (B1 > 1) { | |
B1 = 1; | |
} | |
if (B1 < 0) { | |
B1 = 0; | |
} | |
int scale = (int)(R1 * 1023); | |
if (scale < 0) { | |
scale = 0; | |
} | |
if (scale < 192) { | |
R = (g_sRGBSamples1[scale] / 255.0f); | |
} else { | |
R = (g_sRGBSamples2[scale / 4 - 48] / 255.0f); | |
} | |
scale = (int)(G1 * 1023); | |
if (scale < 0) { | |
scale = 0; | |
} | |
if (scale < 192) { | |
G = (g_sRGBSamples1[scale] / 255.0f); | |
} else { | |
G = (g_sRGBSamples2[scale / 4 - 48] / 255.0f); | |
} | |
scale = (int)(B1 * 1023); | |
if (scale < 0) { | |
scale = 0; | |
} | |
if (scale < 192) { | |
B = (g_sRGBSamples1[scale] / 255.0f); | |
} else { | |
B = (g_sRGBSamples2[scale / 4 - 48] / 255.0f); | |
} | |
} | |
class CPDF_CalGray : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_CalGray(); | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const; | |
FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const; | |
FX_FLOAT m_WhitePoint[3]; | |
FX_FLOAT m_BlackPoint[3]; | |
FX_FLOAT m_Gamma; | |
}; | |
CPDF_CalGray::CPDF_CalGray() | |
{ | |
m_Family = PDFCS_CALGRAY; | |
m_nComponents = 1; | |
} | |
FX_BOOL CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CPDF_Dictionary* pDict = pArray->GetDict(1); | |
CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint")); | |
int i; | |
for (i = 0; i < 3; i ++) { | |
m_WhitePoint[i] = pParam->GetNumber(i); | |
} | |
pParam = pDict->GetArray(FX_BSTRC("BlackPoint")); | |
for (i = 0; i < 3; i ++) { | |
m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0; | |
} | |
m_Gamma = pDict->GetNumber(FX_BSTRC("Gamma")); | |
if (m_Gamma == 0) { | |
m_Gamma = 1.0f; | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_CalGray::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
R = G = B = *pBuf; | |
return TRUE; | |
} | |
FX_BOOL CPDF_CalGray::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const | |
{ | |
if (R == G && R == B) { | |
*pBuf = R; | |
return TRUE; | |
} else { | |
return FALSE; | |
} | |
} | |
void CPDF_CalGray::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const | |
{ | |
for (int i = 0; i < pixels; i ++) { | |
*pDestBuf ++ = pSrcBuf[i]; | |
*pDestBuf ++ = pSrcBuf[i]; | |
*pDestBuf ++ = pSrcBuf[i]; | |
} | |
} | |
class CPDF_CalRGB : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_CalRGB(); | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const; | |
FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const; | |
FX_FLOAT m_WhitePoint[3]; | |
FX_FLOAT m_BlackPoint[3]; | |
FX_FLOAT m_Gamma[3]; | |
FX_FLOAT m_Matrix[9]; | |
FX_BOOL m_bGamma, m_bMatrix; | |
}; | |
CPDF_CalRGB::CPDF_CalRGB() | |
{ | |
m_Family = PDFCS_CALRGB; | |
m_nComponents = 3; | |
} | |
FX_BOOL CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CPDF_Dictionary* pDict = pArray->GetDict(1); | |
CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint")); | |
int i; | |
for (i = 0; i < 3; i ++) { | |
m_WhitePoint[i] = pParam->GetNumber(i); | |
} | |
pParam = pDict->GetArray(FX_BSTRC("BlackPoint")); | |
for (i = 0; i < 3; i ++) { | |
m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0; | |
} | |
pParam = pDict->GetArray(FX_BSTRC("Gamma")); | |
if (pParam) { | |
m_bGamma = TRUE; | |
for (i = 0; i < 3; i ++) { | |
m_Gamma[i] = pParam->GetNumber(i); | |
} | |
} else { | |
m_bGamma = FALSE; | |
} | |
pParam = pDict->GetArray(FX_BSTRC("Matrix")); | |
if (pParam) { | |
m_bMatrix = TRUE; | |
for (i = 0; i < 9; i ++) { | |
m_Matrix[i] = pParam->GetNumber(i); | |
} | |
} else { | |
m_bMatrix = FALSE; | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
FX_FLOAT A_ = pBuf[0]; | |
FX_FLOAT B_ = pBuf[1]; | |
FX_FLOAT C_ = pBuf[2]; | |
if (m_bGamma) { | |
A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]); | |
B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]); | |
C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]); | |
} | |
FX_FLOAT X, Y, Z; | |
if (m_bMatrix) { | |
X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_; | |
Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_; | |
Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_; | |
} else { | |
X = A_; | |
Y = B_; | |
Z = C_; | |
} | |
XYZ_to_sRGB(X, Y, Z, R, G, B); | |
return TRUE; | |
} | |
FX_BOOL CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const | |
{ | |
pBuf[0] = R; | |
pBuf[1] = G; | |
pBuf[2] = B; | |
return TRUE; | |
} | |
void CPDF_CalRGB::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const | |
{ | |
if (bTransMask) { | |
FX_FLOAT Cal[3]; | |
FX_FLOAT R, G, B; | |
for(int i = 0; i < pixels; i ++) { | |
Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255; | |
Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255; | |
Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255; | |
GetRGB(Cal, R, G, B); | |
pDestBuf[0] = FXSYS_round(B * 255); | |
pDestBuf[1] = FXSYS_round(G * 255); | |
pDestBuf[2] = FXSYS_round(R * 255); | |
pSrcBuf += 3; | |
pDestBuf += 3; | |
} | |
} | |
ReverseRGB(pDestBuf, pSrcBuf, pixels); | |
} | |
class CPDF_LabCS : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_LabCS() | |
{ | |
m_Family = PDFCS_LAB; | |
m_nComponents = 3; | |
} | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const; | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const; | |
virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const; | |
FX_FLOAT m_WhitePoint[3]; | |
FX_FLOAT m_BlackPoint[3]; | |
FX_FLOAT m_Ranges[4]; | |
}; | |
FX_BOOL CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CPDF_Dictionary* pDict = pArray->GetDict(1); | |
CPDF_Array* pParam = pDict->GetArray(FX_BSTRC("WhitePoint")); | |
int i; | |
for (i = 0; i < 3; i ++) { | |
m_WhitePoint[i] = pParam->GetNumber(i); | |
} | |
pParam = pDict->GetArray(FX_BSTRC("BlackPoint")); | |
for (i = 0; i < 3; i ++) { | |
m_BlackPoint[i] = pParam ? pParam->GetNumber(i) : 0; | |
} | |
pParam = pDict->GetArray(FX_BSTRC("Range")); | |
const FX_FLOAT def_ranges[4] = { -100 * 1.0f, 100 * 1.0f, -100 * 1.0f, 100 * 1.0f}; | |
for (i = 0; i < 4; i ++) { | |
m_Ranges[i] = pParam ? pParam->GetNumber(i) : def_ranges[i]; | |
} | |
return TRUE; | |
} | |
void CPDF_LabCS::GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const | |
{ | |
value = 0; | |
if (iComponent == 0) { | |
min = 0; | |
max = 100 * 1.0f; | |
} else { | |
min = m_Ranges[iComponent * 2 - 2]; | |
max = m_Ranges[iComponent * 2 - 1]; | |
if (value < min) { | |
value = min; | |
} else if (value > max) { | |
value = max; | |
} | |
} | |
} | |
FX_BOOL CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
FX_FLOAT Lstar = pBuf[0]; | |
FX_FLOAT astar = pBuf[1]; | |
FX_FLOAT bstar = pBuf[2]; | |
FX_FLOAT M = (Lstar + 16.0f) / 116.0f; | |
FX_FLOAT L = M + astar / 500.0f; | |
FX_FLOAT N = M - bstar / 200.0f; | |
FX_FLOAT X, Y, Z; | |
if (L < 0.2069f) { | |
X = 0.957f * 0.12842f * (L - 0.1379f); | |
} else { | |
X = 0.957f * L * L * L; | |
} | |
if (M < 0.2069f) { | |
Y = 0.12842f * (M - 0.1379f); | |
} else { | |
Y = M * M * M; | |
} | |
if (N < 0.2069f) { | |
Z = 1.0889f * 0.12842f * (N - 0.1379f); | |
} else { | |
Z = 1.0889f * N * N * N; | |
} | |
XYZ_to_sRGB(X, Y, Z, R, G, B); | |
return TRUE; | |
} | |
FX_BOOL CPDF_LabCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const | |
{ | |
return FALSE; | |
} | |
void CPDF_LabCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const | |
{ | |
for (int i = 0; i < pixels; i ++) { | |
FX_FLOAT lab[3]; | |
FX_FLOAT R, G, B; | |
lab[0] = (pSrcBuf[0] * 100 / 255.0f); | |
lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128); | |
lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128); | |
GetRGB(lab, R, G, B); | |
pDestBuf[0] = (FX_INT32)(B * 255); | |
pDestBuf[1] = (FX_INT32)(G * 255); | |
pDestBuf[2] = (FX_INT32)(R * 255); | |
pDestBuf += 3; | |
pSrcBuf += 3; | |
} | |
} | |
CPDF_IccProfile::CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize, int nComponents) | |
{ | |
m_bsRGB = nComponents == 3 && dwSize == 3144 && FXSYS_memcmp32(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0; | |
m_pTransform = NULL; | |
if (!m_bsRGB && CPDF_ModuleMgr::Get()->GetIccModule()) { | |
m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(pData, dwSize, nComponents); | |
} | |
} | |
CPDF_IccProfile::~CPDF_IccProfile() | |
{ | |
if (m_pTransform) { | |
CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform); | |
} | |
} | |
class CPDF_ICCBasedCS : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_ICCBasedCS(); | |
virtual ~CPDF_ICCBasedCS(); | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
void GetDefaultValue(int i, FX_FLOAT& min, FX_FLOAT& max) const | |
{ | |
min = m_pRanges[i * 2]; | |
max = m_pRanges[i * 2 + 1]; | |
} | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
FX_BOOL v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const; | |
FX_BOOL SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const; | |
virtual void EnableStdConversion(FX_BOOL bEnabled); | |
virtual void TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask = FALSE) const; | |
FX_FLOAT* m_pRanges; | |
CPDF_IccProfile* m_pProfile; | |
CPDF_ColorSpace* m_pAlterCS; | |
FX_LPBYTE m_pCache; | |
FX_BOOL m_bOwn; | |
}; | |
CPDF_ICCBasedCS::CPDF_ICCBasedCS() | |
{ | |
m_pAlterCS = NULL; | |
m_pProfile = NULL; | |
m_Family = PDFCS_ICCBASED; | |
m_pCache = NULL; | |
m_pRanges = NULL; | |
m_bOwn = FALSE; | |
} | |
CPDF_ICCBasedCS::~CPDF_ICCBasedCS() | |
{ | |
if (m_pCache) { | |
FX_Free(m_pCache); | |
} | |
if (m_pRanges) { | |
FX_Free(m_pRanges); | |
} | |
if (m_pAlterCS && m_bOwn) { | |
m_pAlterCS->ReleaseCS(); | |
} | |
if (m_pProfile && m_pDocument) { | |
m_pDocument->GetPageData()->ReleaseIccProfile(NULL, m_pProfile); | |
} | |
} | |
FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CPDF_Stream* pStream = pArray->GetStream(1); | |
if (pStream == NULL) { | |
return FALSE; | |
} | |
m_nComponents = pStream->GetDict()->GetInteger(FX_BSTRC("N")); | |
if (m_nComponents < 0 || m_nComponents > (1 << 16)) { | |
return FALSE; | |
} | |
CPDF_Array* pRanges = pStream->GetDict()->GetArray(FX_BSTRC("Range")); | |
m_pRanges = FX_Alloc(FX_FLOAT, m_nComponents * 2); | |
for (int i = 0; i < m_nComponents * 2; i ++) { | |
if (pRanges) { | |
m_pRanges[i] = pRanges->GetNumber(i); | |
} else if (i % 2) { | |
m_pRanges[i] = 1.0f; | |
} else { | |
m_pRanges[i] = 0; | |
} | |
} | |
m_pProfile = pDoc->LoadIccProfile(pStream, m_nComponents); | |
if (!m_pProfile) { | |
return FALSE; | |
} | |
if (m_pProfile->m_pTransform == NULL) { | |
CPDF_Object* pAlterCSObj = pStream->GetDict()->GetElementValue(FX_BSTRC("Alternate")); | |
if (pAlterCSObj) { | |
CPDF_ColorSpace* alter_cs = CPDF_ColorSpace::Load(pDoc, pAlterCSObj); | |
if (alter_cs) { | |
if (alter_cs->CountComponents() > m_nComponents) { | |
alter_cs->ReleaseCS(); | |
} else { | |
m_pAlterCS = alter_cs; | |
m_bOwn = TRUE; | |
} | |
} | |
} | |
if (!m_pAlterCS) { | |
if (m_nComponents == 3) { | |
m_pAlterCS = GetStockCS(PDFCS_DEVICERGB); | |
} else if (m_nComponents == 4) { | |
m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK); | |
} else { | |
m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY); | |
} | |
} | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
if (m_pProfile && m_pProfile->m_bsRGB) { | |
R = pBuf[0]; | |
G = pBuf[1]; | |
B = pBuf[2]; | |
return TRUE; | |
} | |
ICodec_IccModule *pIccModule = CPDF_ModuleMgr::Get()->GetIccModule(); | |
if (m_pProfile->m_pTransform == NULL || pIccModule == NULL) { | |
if (m_pAlterCS) { | |
m_pAlterCS->GetRGB(pBuf, R, G, B); | |
} else { | |
R = G = B = 0.0f; | |
} | |
return TRUE; | |
} | |
FX_FLOAT rgb[3]; | |
pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb); | |
R = rgb[0]; | |
G = rgb[1]; | |
B = rgb[2]; | |
return TRUE; | |
} | |
FX_BOOL CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const | |
{ | |
if (m_nComponents != 4) { | |
return FALSE; | |
} | |
c = pBuf[0]; | |
m = pBuf[1]; | |
y = pBuf[2]; | |
k = pBuf[3]; | |
return TRUE; | |
} | |
FX_BOOL CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const | |
{ | |
return FALSE; | |
} | |
void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled) | |
{ | |
CPDF_ColorSpace::EnableStdConversion(bEnabled); | |
if (m_pAlterCS) { | |
m_pAlterCS->EnableStdConversion(bEnabled); | |
} | |
} | |
void CPDF_ICCBasedCS::TranslateImageLine(FX_LPBYTE pDestBuf, FX_LPCBYTE pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const | |
{ | |
if (m_pProfile->m_bsRGB) { | |
ReverseRGB(pDestBuf, pSrcBuf, pixels); | |
} else if (m_pProfile->m_pTransform) { | |
int nMaxColors = 1; | |
for (int i = 0; i < m_nComponents; i ++) { | |
nMaxColors *= 52; | |
} | |
if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) { | |
CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels); | |
} else { | |
if (m_pCache == NULL) { | |
((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc(FX_BYTE, nMaxColors * 3); | |
FX_LPBYTE temp_src = FX_Alloc(FX_BYTE, nMaxColors * m_nComponents); | |
FX_LPBYTE pSrc = temp_src; | |
for (int i = 0; i < nMaxColors; i ++) { | |
FX_DWORD color = i; | |
FX_DWORD order = nMaxColors / 52; | |
for (int c = 0; c < m_nComponents; c ++) { | |
*pSrc++ = (FX_BYTE)(color / order * 5); | |
color %= order; | |
order /= 52; | |
} | |
} | |
CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors); | |
FX_Free(temp_src); | |
} | |
for (int i = 0; i < pixels; i ++) { | |
int index = 0; | |
for (int c = 0; c < m_nComponents; c ++) { | |
index = index * 52 + (*pSrcBuf) / 5; | |
pSrcBuf ++; | |
} | |
index *= 3; | |
*pDestBuf++ = m_pCache[index]; | |
*pDestBuf++ = m_pCache[index + 1]; | |
*pDestBuf++ = m_pCache[index + 2]; | |
} | |
} | |
} else if (m_pAlterCS) { | |
m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, image_height); | |
} | |
} | |
class CPDF_IndexedCS : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_IndexedCS(); | |
virtual ~CPDF_IndexedCS(); | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
void GetDefaultValue(int iComponent, FX_FLOAT& min, FX_FLOAT& max) const | |
{ | |
min = 0; | |
max = (FX_FLOAT)m_MaxIndex; | |
} | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
virtual CPDF_ColorSpace* GetBaseCS() const | |
{ | |
return m_pBaseCS; | |
} | |
virtual void EnableStdConversion(FX_BOOL bEnabled); | |
CPDF_ColorSpace* m_pBaseCS; | |
int m_nBaseComponents; | |
int m_MaxIndex; | |
CFX_ByteString m_Table; | |
FX_FLOAT* m_pCompMinMax; | |
}; | |
CPDF_IndexedCS::CPDF_IndexedCS() | |
{ | |
m_pBaseCS = NULL; | |
m_Family = PDFCS_INDEXED; | |
m_nComponents = 1; | |
m_pCompMinMax = NULL; | |
} | |
CPDF_IndexedCS::~CPDF_IndexedCS() | |
{ | |
if (m_pCompMinMax) { | |
FX_Free(m_pCompMinMax); | |
} | |
CPDF_ColorSpace* pCS = m_pBaseCS; | |
if (pCS && m_pDocument) { | |
m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); | |
} | |
} | |
FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
if (pArray->GetCount() < 4) { | |
return FALSE; | |
} | |
CPDF_Object* pBaseObj = pArray->GetElementValue(1); | |
if (pBaseObj == m_pArray) { | |
return FALSE; | |
} | |
CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); | |
m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL); | |
if (m_pBaseCS == NULL) { | |
return FALSE; | |
} | |
m_nBaseComponents = m_pBaseCS->CountComponents(); | |
m_pCompMinMax = FX_Alloc(FX_FLOAT, m_nBaseComponents * 2); | |
FX_FLOAT defvalue; | |
for (int i = 0; i < m_nBaseComponents; i ++) { | |
m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], m_pCompMinMax[i * 2 + 1]); | |
m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2]; | |
} | |
m_MaxIndex = pArray->GetInteger(2); | |
CPDF_Object* pTableObj = pArray->GetElementValue(3); | |
if (pTableObj == NULL) { | |
return FALSE; | |
} | |
FX_LPCBYTE pTable = NULL; | |
FX_DWORD size = 0; | |
CPDF_StreamAcc* pStreamAcc = NULL; | |
if (pTableObj->GetType() == PDFOBJ_STRING) { | |
m_Table = ((CPDF_String*)pTableObj)->GetString(); | |
} else if (pTableObj->GetType() == PDFOBJ_STREAM) { | |
CPDF_StreamAcc acc; | |
acc.LoadAllData((CPDF_Stream*)pTableObj, FALSE); | |
m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize()); | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
int index = (FX_INT32)(*pBuf); | |
if (index < 0 || index > m_MaxIndex) { | |
return FALSE; | |
} | |
if (m_nBaseComponents) { | |
if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents || | |
(index + 1)*m_nBaseComponents > (int)m_Table.GetLength()) { | |
R = G = B = 0; | |
return FALSE; | |
} | |
} | |
CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents); | |
FX_FLOAT* comps = Comps; | |
FX_LPCBYTE pTable = m_Table; | |
for (int i = 0; i < m_nBaseComponents; i ++) { | |
comps[i] = m_pCompMinMax[i * 2] + m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255; | |
} | |
m_pBaseCS->GetRGB(comps, R, G, B); | |
return TRUE; | |
} | |
void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled) | |
{ | |
CPDF_ColorSpace::EnableStdConversion(bEnabled); | |
if (m_pBaseCS) { | |
m_pBaseCS->EnableStdConversion(bEnabled); | |
} | |
} | |
#define MAX_PATTERN_COLORCOMPS 16 | |
typedef struct _PatternValue { | |
CPDF_Pattern* m_pPattern; | |
int m_nComps; | |
FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS]; | |
} PatternValue; | |
CPDF_PatternCS::CPDF_PatternCS() | |
{ | |
m_Family = PDFCS_PATTERN; | |
m_pBaseCS = NULL; | |
m_nComponents = 1; | |
} | |
CPDF_PatternCS::~CPDF_PatternCS() | |
{ | |
CPDF_ColorSpace* pCS = m_pBaseCS; | |
if (pCS && m_pDocument) { | |
m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); | |
} | |
} | |
FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CPDF_Object* pBaseCS = pArray->GetElementValue(1); | |
if (pBaseCS == m_pArray) { | |
return FALSE; | |
} | |
CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); | |
m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, NULL); | |
if (m_pBaseCS) { | |
m_nComponents = m_pBaseCS->CountComponents() + 1; | |
if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) { | |
return FALSE; | |
} | |
} else { | |
m_nComponents = 1; | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
if (m_pBaseCS) { | |
PatternValue* pvalue = (PatternValue*)pBuf; | |
m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B); | |
return TRUE; | |
} | |
R = G = B = 0.75f; | |
return FALSE; | |
} | |
class CPDF_SeparationCS : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_SeparationCS(); | |
virtual ~CPDF_SeparationCS(); | |
virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const | |
{ | |
value = 1.0f; | |
min = 0; | |
max = 1.0f; | |
} | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
virtual void EnableStdConversion(FX_BOOL bEnabled); | |
CPDF_ColorSpace* m_pAltCS; | |
CPDF_Function* m_pFunc; | |
enum {None, All, Colorant} m_Type; | |
}; | |
CPDF_SeparationCS::CPDF_SeparationCS() | |
{ | |
m_Family = PDFCS_SEPARATION; | |
m_pAltCS = NULL; | |
m_pFunc = NULL; | |
m_nComponents = 1; | |
} | |
CPDF_SeparationCS::~CPDF_SeparationCS() | |
{ | |
if (m_pAltCS) { | |
m_pAltCS->ReleaseCS(); | |
} | |
if (m_pFunc) { | |
delete m_pFunc; | |
} | |
} | |
FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CFX_ByteString name = pArray->GetString(1); | |
if (name == FX_BSTRC("None")) { | |
m_Type = None; | |
} else { | |
m_Type = Colorant; | |
CPDF_Object* pAltCS = pArray->GetElementValue(2); | |
if (pAltCS == m_pArray) { | |
return FALSE; | |
} | |
m_pAltCS = Load(pDoc, pAltCS); | |
CPDF_Object* pFuncObj = pArray->GetElementValue(3); | |
if (pFuncObj && pFuncObj->GetType() != PDFOBJ_NAME) { | |
m_pFunc = CPDF_Function::Load(pFuncObj); | |
} | |
if (m_pFunc && m_pAltCS && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) { | |
delete m_pFunc; | |
m_pFunc = NULL; | |
} | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
if (m_Type == None) { | |
return FALSE; | |
} | |
if (m_pFunc == NULL) { | |
if (m_pAltCS == NULL) { | |
return FALSE; | |
} | |
int nComps = m_pAltCS->CountComponents(); | |
CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps); | |
for (int i = 0; i < nComps; i ++) { | |
results[i] = *pBuf; | |
} | |
m_pAltCS->GetRGB(results, R, G, B); | |
return TRUE; | |
} | |
CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs()); | |
int nresults; | |
m_pFunc->Call(pBuf, 1, results, nresults); | |
if (nresults == 0) { | |
return FALSE; | |
} | |
if (m_pAltCS) { | |
m_pAltCS->GetRGB(results, R, G, B); | |
return TRUE; | |
} else { | |
R = G = B = 0; | |
return FALSE; | |
} | |
} | |
void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled) | |
{ | |
CPDF_ColorSpace::EnableStdConversion(bEnabled); | |
if (m_pAltCS) { | |
m_pAltCS->EnableStdConversion(bEnabled); | |
} | |
} | |
class CPDF_DeviceNCS : public CPDF_ColorSpace | |
{ | |
public: | |
CPDF_DeviceNCS(); | |
virtual ~CPDF_DeviceNCS(); | |
virtual void GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const | |
{ | |
value = 1.0f; | |
min = 0; | |
max = 1.0f; | |
} | |
virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); | |
virtual FX_BOOL GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const; | |
virtual void EnableStdConversion(FX_BOOL bEnabled); | |
CPDF_ColorSpace* m_pAltCS; | |
CPDF_Function* m_pFunc; | |
}; | |
CPDF_DeviceNCS::CPDF_DeviceNCS() | |
{ | |
m_Family = PDFCS_DEVICEN; | |
m_pAltCS = NULL; | |
m_pFunc = NULL; | |
} | |
CPDF_DeviceNCS::~CPDF_DeviceNCS() | |
{ | |
if (m_pFunc) { | |
delete m_pFunc; | |
} | |
if (m_pAltCS) { | |
m_pAltCS->ReleaseCS(); | |
} | |
} | |
FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) | |
{ | |
CPDF_Object* pObj = pArray->GetElementValue(1); | |
if (!pObj) { | |
return FALSE; | |
} | |
if (pObj->GetType() != PDFOBJ_ARRAY) { | |
return FALSE; | |
} | |
m_nComponents = ((CPDF_Array*)pObj)->GetCount(); | |
CPDF_Object* pAltCS = pArray->GetElementValue(2); | |
if (!pAltCS || pAltCS == m_pArray) { | |
return FALSE; | |
} | |
m_pAltCS = Load(pDoc, pAltCS); | |
m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3)); | |
if (m_pAltCS == NULL || m_pFunc == NULL) { | |
return FALSE; | |
} | |
if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) { | |
return FALSE; | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const | |
{ | |
if (m_pFunc == NULL) { | |
return FALSE; | |
} | |
CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs()); | |
int nresults; | |
m_pFunc->Call(pBuf, m_nComponents, results, nresults); | |
if (nresults == 0) { | |
return FALSE; | |
} | |
m_pAltCS->GetRGB(results, R, G, B); | |
return TRUE; | |
} | |
void CPDF_DeviceNCS::EnableStdConversion(FX_BOOL bEnabled) | |
{ | |
CPDF_ColorSpace::EnableStdConversion(bEnabled); | |
if (m_pAltCS) { | |
m_pAltCS->EnableStdConversion(bEnabled); | |
} | |
} | |
CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family) | |
{ | |
return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family);; | |
} | |
CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name) | |
{ | |
if (name == FX_BSTRC("DeviceRGB") || name == FX_BSTRC("RGB")) { | |
return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
} | |
if (name == FX_BSTRC("DeviceGray") || name == FX_BSTRC("G")) { | |
return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
} | |
if (name == FX_BSTRC("DeviceCMYK") || name == FX_BSTRC("CMYK")) { | |
return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
} | |
if (name == FX_BSTRC("Pattern")) { | |
return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN); | |
} | |
return NULL; | |
} | |
CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj) | |
{ | |
if (pObj == NULL) { | |
return NULL; | |
} | |
if (pObj->GetType() == PDFOBJ_NAME) { | |
return _CSFromName(pObj->GetString()); | |
} | |
if (pObj->GetType() == PDFOBJ_STREAM) { | |
CPDF_Dictionary *pDict = ((CPDF_Stream *)pObj)->GetDict(); | |
if (!pDict) { | |
return NULL; | |
} | |
CPDF_ColorSpace *pRet = NULL; | |
FX_POSITION pos = pDict->GetStartPos(); | |
while (pos) { | |
CFX_ByteString bsKey; | |
CPDF_Object *pValue = pDict->GetNextElement(pos, bsKey); | |
if (pValue->GetType() == PDFOBJ_NAME) { | |
pRet = _CSFromName(pValue->GetString()); | |
} | |
if (pRet) { | |
return pRet; | |
} | |
} | |
return NULL; | |
} | |
if (pObj->GetType() != PDFOBJ_ARRAY) { | |
return NULL; | |
} | |
CPDF_Array* pArray = (CPDF_Array*)pObj; | |
if (pArray->GetCount() == 0) { | |
return NULL; | |
} | |
CFX_ByteString familyname = pArray->GetElementValue(0)->GetString(); | |
if (pArray->GetCount() == 1) { | |
return _CSFromName(familyname); | |
} | |
CPDF_ColorSpace* pCS = NULL; | |
FX_DWORD id = familyname.GetID(); | |
if (id == FXBSTR_ID('C', 'a', 'l', 'G')) { | |
pCS = FX_NEW CPDF_CalGray(); | |
} else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) { | |
pCS = FX_NEW CPDF_CalRGB(); | |
} else if (id == FXBSTR_ID('L', 'a', 'b', 0)) { | |
pCS = FX_NEW CPDF_LabCS(); | |
} else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) { | |
pCS = FX_NEW CPDF_ICCBasedCS(); | |
} else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || id == FXBSTR_ID('I', 0, 0, 0)) { | |
pCS = FX_NEW CPDF_IndexedCS(); | |
} else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) { | |
pCS = FX_NEW CPDF_SeparationCS(); | |
} else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) { | |
pCS = FX_NEW CPDF_DeviceNCS(); | |
} else if (id == FXBSTR_ID('P', 'a', 't', 't')) { | |
pCS = FX_NEW CPDF_PatternCS(); | |
} else { | |
return NULL; | |
} | |
pCS->m_pDocument = pDoc; | |
pCS->m_pArray = pArray; | |
if (!pCS->v_Load(pDoc, pArray)) { | |
pCS->ReleaseCS(); | |
return NULL; | |
} | |
return pCS; | |
} | |
CPDF_ColorSpace::CPDF_ColorSpace() | |
{ | |
m_Family = 0; | |
m_pArray = NULL; | |
m_dwStdConversion = 0; | |
m_pDocument = NULL; | |
} | |
void CPDF_ColorSpace::ReleaseCS() | |
{ | |
if (this == GetStockCS(PDFCS_DEVICERGB)) { | |
return; | |
} | |
if (this == GetStockCS(PDFCS_DEVICEGRAY)) { | |
return; | |
} | |
if (this == GetStockCS(PDFCS_DEVICECMYK)) { | |
return; | |
} | |
if (this == GetStockCS(PDFCS_PATTERN)) { | |
return; | |
} | |
delete this; | |
} | |
int CPDF_ColorSpace::GetBufSize() const | |
{ | |
if (m_Family == PDFCS_PATTERN) { | |
return sizeof(PatternValue); | |
} | |
return m_nComponents * sizeof(FX_FLOAT); | |
} | |
FX_FLOAT* CPDF_ColorSpace::CreateBuf() | |
{ | |
int size = GetBufSize(); | |
FX_BYTE* pBuf = FX_Alloc(FX_BYTE, size); | |
FXSYS_memset32(pBuf, 0, size); | |
return (FX_FLOAT*)pBuf; | |
} | |
FX_BOOL CPDF_ColorSpace::sRGB() const | |
{ | |
if (m_Family == PDFCS_DEVICERGB) { | |
return TRUE; | |
} | |
if (m_Family != PDFCS_ICCBASED) { | |
return FALSE; | |
} | |
CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this; | |
return pCS->m_pProfile->m_bsRGB; | |
} | |
FX_BOOL CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const | |
{ | |
if (v_GetCMYK(pBuf, c, m, y, k)) { | |
return TRUE; | |
} | |
FX_FLOAT R, G, B; | |
if (!GetRGB(pBuf, R, G, B)) { | |
return FALSE; | |
} | |
sRGB_to_AdobeCMYK(R, G, B, c, m, y, k); | |
return TRUE; | |
} | |
FX_BOOL CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const | |
{ | |
if (v_SetCMYK(pBuf, c, m, y, k)) { | |
return TRUE; | |
} | |
FX_FLOAT R, G, B; | |
AdobeCMYK_to_sRGB(c, m, y, k, R, G, B); | |
return SetRGB(pBuf, R, G, B); | |
} | |
void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const | |
{ | |
if (buf == NULL || m_Family == PDFCS_PATTERN) { | |
return; | |
} | |
FX_FLOAT min, max; | |
for (int i = 0; i < m_nComponents; i ++) { | |
GetDefaultValue(i, buf[i], min, max); | |
} | |
} | |
int CPDF_ColorSpace::GetMaxIndex() const | |
{ | |
if (m_Family != PDFCS_INDEXED) { | |
return 0; | |
} | |
CPDF_IndexedCS* pCS = (CPDF_IndexedCS*)this; | |
return pCS->m_MaxIndex; | |
} | |
void CPDF_ColorSpace::TranslateImageLine(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const | |
{ | |
CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents); | |
FX_FLOAT* src = srcbuf; | |
FX_FLOAT R, G, B; | |
for (int i = 0; i < pixels; i ++) { | |
for (int j = 0; j < m_nComponents; j ++) | |
if (m_Family == PDFCS_INDEXED) { | |
src[j] = (FX_FLOAT)(*src_buf ++); | |
} else { | |
src[j] = (FX_FLOAT)(*src_buf ++) / 255; | |
} | |
GetRGB(src, R, G, B); | |
*dest_buf ++ = (FX_INT32)(B * 255); | |
*dest_buf ++ = (FX_INT32)(G * 255); | |
*dest_buf ++ = (FX_INT32)(R * 255); | |
} | |
} | |
void CPDF_ColorSpace::EnableStdConversion(FX_BOOL bEnabled) | |
{ | |
if (bEnabled) { | |
m_dwStdConversion ++; | |
} else if (m_dwStdConversion) { | |
m_dwStdConversion --; | |
} | |
} | |
CPDF_Color::CPDF_Color(int family) | |
{ | |
m_pCS = CPDF_ColorSpace::GetStockCS(family); | |
int nComps = 3; | |
if (family == PDFCS_DEVICEGRAY) { | |
nComps = 1; | |
} else if (family == PDFCS_DEVICECMYK) { | |
nComps = 4; | |
} | |
m_pBuffer = FX_Alloc(FX_FLOAT, nComps); | |
for (int i = 0; i < nComps; i ++) { | |
m_pBuffer[i] = 0; | |
} | |
} | |
CPDF_Color::~CPDF_Color() | |
{ | |
ReleaseBuffer(); | |
ReleaseColorSpace(); | |
} | |
void CPDF_Color::ReleaseBuffer() | |
{ | |
if (!m_pBuffer) { | |
return; | |
} | |
if (m_pCS->GetFamily() == PDFCS_PATTERN) { | |
PatternValue* pvalue = (PatternValue*)m_pBuffer; | |
CPDF_Pattern* pPattern = pvalue->m_pPattern; | |
if (pPattern && pPattern->m_pDocument) { | |
pPattern->m_pDocument->GetPageData()->ReleasePattern(pPattern->m_pPatternObj); | |
} | |
} | |
FX_Free(m_pBuffer); | |
m_pBuffer = NULL; | |
} | |
void CPDF_Color::ReleaseColorSpace() | |
{ | |
if (m_pCS && m_pCS->m_pDocument && m_pCS->GetArray()) { | |
m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray()); | |
m_pCS = NULL; | |
} | |
} | |
void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS) | |
{ | |
if (m_pCS == pCS) { | |
if (m_pBuffer == NULL) { | |
m_pBuffer = pCS->CreateBuf(); | |
} | |
ReleaseColorSpace(); | |
m_pCS = pCS; | |
return; | |
} | |
ReleaseBuffer(); | |
ReleaseColorSpace(); | |
m_pCS = pCS; | |
if (m_pCS) { | |
m_pBuffer = pCS->CreateBuf(); | |
pCS->GetDefaultColor(m_pBuffer); | |
} | |
} | |
void CPDF_Color::SetValue(FX_FLOAT* comps) | |
{ | |
if (m_pBuffer == NULL) { | |
return; | |
} | |
if (m_pCS->GetFamily() != PDFCS_PATTERN) { | |
FXSYS_memcpy32(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT)); | |
} | |
} | |
void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps) | |
{ | |
if (ncomps > MAX_PATTERN_COLORCOMPS) { | |
return; | |
} | |
if (m_pCS == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) { | |
if (m_pBuffer) { | |
FX_Free(m_pBuffer); | |
} | |
m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN); | |
m_pBuffer = m_pCS->CreateBuf(); | |
} | |
CPDF_DocPageData* pDocPageData = NULL; | |
PatternValue* pvalue = (PatternValue*)m_pBuffer; | |
if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) { | |
pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData(); | |
pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj); | |
} | |
pvalue->m_nComps = ncomps; | |
pvalue->m_pPattern = pPattern; | |
if (ncomps) { | |
FXSYS_memcpy32(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT)); | |
} | |
} | |
void CPDF_Color::Copy(const CPDF_Color* pSrc) | |
{ | |
ReleaseBuffer(); | |
ReleaseColorSpace(); | |
m_pCS = pSrc->m_pCS; | |
if (m_pCS && m_pCS->m_pDocument) { | |
CPDF_Array* pArray = m_pCS->GetArray(); | |
if (pArray) { | |
m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray); | |
} | |
} | |
if (m_pCS == NULL) { | |
return; | |
} | |
m_pBuffer = m_pCS->CreateBuf(); | |
FXSYS_memcpy32(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize()); | |
if (m_pCS->GetFamily() == PDFCS_PATTERN) { | |
PatternValue* pvalue = (PatternValue*)m_pBuffer; | |
if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) { | |
pvalue->m_pPattern = pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(pvalue->m_pPattern->m_pPatternObj, FALSE, &pvalue->m_pPattern->m_ParentMatrix); | |
} | |
} | |
} | |
FX_BOOL CPDF_Color::GetRGB(int& R, int& G, int& B) const | |
{ | |
if (m_pCS == NULL || m_pBuffer == NULL) { | |
return FALSE; | |
} | |
FX_FLOAT r, g, b; | |
if (!m_pCS->GetRGB(m_pBuffer, r, g, b)) { | |
return FALSE; | |
} | |
R = (FX_INT32)(r * 255 + 0.5f); | |
G = (FX_INT32)(g * 255 + 0.5f); | |
B = (FX_INT32)(b * 255 + 0.5f); | |
return TRUE; | |
} | |
CPDF_Pattern* CPDF_Color::GetPattern() const | |
{ | |
if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) { | |
return NULL; | |
} | |
PatternValue* pvalue = (PatternValue*)m_pBuffer; | |
return pvalue->m_pPattern; | |
} | |
CPDF_ColorSpace* CPDF_Color::GetPatternCS() const | |
{ | |
if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) { | |
return NULL; | |
} | |
return m_pCS->GetBaseCS(); | |
} | |
FX_FLOAT* CPDF_Color::GetPatternColor() const | |
{ | |
if (m_pBuffer == NULL || m_pCS->GetFamily() != PDFCS_PATTERN) { | |
return NULL; | |
} | |
PatternValue* pvalue = (PatternValue*)m_pBuffer; | |
return pvalue->m_nComps ? pvalue->m_Comps : NULL; | |
} | |
FX_BOOL CPDF_Color::IsEqual(const CPDF_Color& other) const | |
{ | |
if (m_pCS != other.m_pCS || m_pCS == NULL) { | |
return FALSE; | |
} | |
return FXSYS_memcmp32(m_pBuffer, other.m_pBuffer, m_pCS->GetBufSize()) == 0; | |
} |