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