Home | History | Annotate | Download | only in fpdf_page
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fpdfapi/fpdf_page.h"
      8 #include "../../../include/fpdfapi/fpdf_module.h"
      9 #include "../../../include/fdrm/fx_crypt.h"
     10 #include "../fpdf_font/font_int.h"
     11 #include "pageint.h"
     12 class CPDF_PageModule : public CPDF_PageModuleDef
     13 {
     14 public:
     15     CPDF_PageModule() : m_StockGrayCS(PDFCS_DEVICEGRAY), m_StockRGBCS(PDFCS_DEVICERGB),
     16         m_StockCMYKCS(PDFCS_DEVICECMYK) {}
     17     virtual ~CPDF_PageModule() {}
     18     virtual FX_BOOL		Installed()
     19     {
     20         return TRUE;
     21     }
     22     virtual CPDF_DocPageData*	CreateDocData(CPDF_Document* pDoc)
     23     {
     24         return new CPDF_DocPageData(pDoc);
     25     }
     26     virtual void		ReleaseDoc(CPDF_Document* pDoc);
     27     virtual void		ClearDoc(CPDF_Document* pDoc);
     28     virtual CPDF_FontGlobals*	GetFontGlobals()
     29     {
     30         return &m_FontGlobals;
     31     }
     32     virtual void				ClearStockFont(CPDF_Document* pDoc)
     33     {
     34         m_FontGlobals.Clear(pDoc);
     35     }
     36     virtual CPDF_ColorSpace*	GetStockCS(int family);
     37     virtual void		NotifyCJKAvailable();
     38     CPDF_FontGlobals	m_FontGlobals;
     39     CPDF_DeviceCS		m_StockGrayCS;
     40     CPDF_DeviceCS		m_StockRGBCS;
     41     CPDF_DeviceCS		m_StockCMYKCS;
     42     CPDF_PatternCS		m_StockPatternCS;
     43 };
     44 CPDF_ColorSpace* CPDF_PageModule::GetStockCS(int family)
     45 {
     46     if (family == PDFCS_DEVICEGRAY) {
     47         return &m_StockGrayCS;
     48     }
     49     if (family == PDFCS_DEVICERGB) {
     50         return &m_StockRGBCS;
     51     }
     52     if (family == PDFCS_DEVICECMYK) {
     53         return &m_StockCMYKCS;
     54     }
     55     if (family == PDFCS_PATTERN) {
     56         return &m_StockPatternCS;
     57     }
     58     return NULL;
     59 }
     60 void CPDF_ModuleMgr::InitPageModule()
     61 {
     62     delete m_pPageModule;
     63     m_pPageModule = new CPDF_PageModule;
     64 }
     65 void CPDF_PageModule::ReleaseDoc(CPDF_Document* pDoc)
     66 {
     67     delete pDoc->GetPageData();
     68 }
     69 void CPDF_PageModule::ClearDoc(CPDF_Document* pDoc)
     70 {
     71     pDoc->GetPageData()->Clear(FALSE);
     72 }
     73 void CPDF_PageModule::NotifyCJKAvailable()
     74 {
     75     m_FontGlobals.m_CMapManager.ReloadAll();
     76 }
     77 CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict)
     78 {
     79     if (!pFontDict) {
     80         return NULL;
     81     }
     82     return GetValidatePageData()->GetFont(pFontDict, FALSE);
     83 }
     84 CPDF_Font* CPDF_Document::FindFont(CPDF_Dictionary* pFontDict)
     85 {
     86     if (!pFontDict) {
     87         return NULL;
     88     }
     89     return GetValidatePageData()->GetFont(pFontDict, TRUE);
     90 }
     91 CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream)
     92 {
     93     if (pStream == NULL) {
     94         return NULL;
     95     }
     96     return GetValidatePageData()->GetFontFileStreamAcc(pStream);
     97 }
     98 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name);
     99 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
    100 {
    101     return GetValidatePageData()->GetColorSpace(pCSObj, pResources);
    102 }
    103 CPDF_Pattern* CPDF_Document::LoadPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)
    104 {
    105     return GetValidatePageData()->GetPattern(pPatternObj, bShading, matrix);
    106 }
    107 CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream)
    108 {
    109     return GetValidatePageData()->GetIccProfile(pStream);
    110 }
    111 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj)
    112 {
    113     if (!pObj) {
    114         return NULL;
    115     }
    116     FXSYS_assert(pObj->GetObjNum());
    117     return GetValidatePageData()->GetImage(pObj);
    118 }
    119 void CPDF_Document::RemoveColorSpaceFromPageData(CPDF_Object* pCSObj)
    120 {
    121     if (!pCSObj) {
    122         return;
    123     }
    124     GetPageData()->ReleaseColorSpace(pCSObj);
    125 }
    126 CPDF_DocPageData::CPDF_DocPageData(CPDF_Document *pPDFDoc)
    127     : m_pPDFDoc(pPDFDoc)
    128     , m_FontMap()
    129     , m_ColorSpaceMap()
    130     , m_PatternMap()
    131     , m_ImageMap()
    132     , m_IccProfileMap()
    133     , m_FontFileMap()
    134     , m_bForceClear(FALSE)
    135 {
    136     m_FontMap.InitHashTable(64);
    137     m_ColorSpaceMap.InitHashTable(32);
    138     m_PatternMap.InitHashTable(16);
    139     m_ImageMap.InitHashTable(64);
    140     m_IccProfileMap.InitHashTable(16);
    141     m_FontFileMap.InitHashTable(32);
    142 }
    143 CPDF_DocPageData::~CPDF_DocPageData()
    144 {
    145     Clear(FALSE);
    146     Clear(TRUE);
    147     FX_POSITION pos = m_PatternMap.GetStartPosition();
    148     while (pos)
    149     {
    150         CPDF_Object* ptObj;
    151         CPDF_CountedObject<CPDF_Pattern*>* ptData;
    152         m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
    153         delete ptData;
    154     }
    155     m_PatternMap.RemoveAll();
    156     pos = m_FontMap.GetStartPosition();
    157     while (pos)
    158     {
    159         CPDF_Dictionary* fontDict;
    160         CPDF_CountedObject<CPDF_Font*>* fontData;
    161         m_FontMap.GetNextAssoc(pos, fontDict, fontData);
    162         delete fontData;
    163     }
    164     m_FontMap.RemoveAll();
    165     pos = m_ColorSpaceMap.GetStartPosition();
    166     while (pos)
    167     {
    168         CPDF_Object* csKey;
    169         CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    170         m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);
    171         delete csData;
    172     }
    173     m_ColorSpaceMap.RemoveAll();
    174 }
    175 void CPDF_DocPageData::Clear(FX_BOOL bForceRelease)
    176 {
    177     FX_POSITION pos;
    178     m_bForceClear = bForceRelease;
    179     pos = m_PatternMap.GetStartPosition();
    180     while (pos) {
    181         CPDF_Object* ptObj;
    182         CPDF_CountedObject<CPDF_Pattern*>* ptData;
    183         m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
    184         if (!ptData->m_Obj) {
    185             continue;
    186         }
    187         if (bForceRelease || ptData->m_nCount < 2) {
    188             ptData->m_Obj->SetForceClear(bForceRelease);
    189             delete ptData->m_Obj;
    190             ptData->m_Obj = NULL;
    191         }
    192     }
    193     pos = m_FontMap.GetStartPosition();
    194     while (pos) {
    195         CPDF_Dictionary* fontDict;
    196         CPDF_CountedObject<CPDF_Font*>* fontData;
    197         m_FontMap.GetNextAssoc(pos, fontDict, fontData);
    198         if (!fontData->m_Obj) {
    199             continue;
    200         }
    201         if (bForceRelease || fontData->m_nCount < 2) {
    202             delete fontData->m_Obj;
    203             fontData->m_Obj = NULL;
    204         }
    205     }
    206     pos = m_ColorSpaceMap.GetStartPosition();
    207     while (pos) {
    208         CPDF_Object* csKey;
    209         CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    210         m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);
    211         if (!csData->m_Obj) {
    212             continue;
    213         }
    214         if (bForceRelease || csData->m_nCount < 2) {
    215             // csData->m_Obj is deleted in the function of ReleaseCS().
    216             csData->m_Obj->ReleaseCS();
    217             csData->m_Obj = NULL;
    218         }
    219     }
    220     pos = m_IccProfileMap.GetStartPosition();
    221     while (pos) {
    222         CPDF_Stream* ipKey;
    223         CPDF_CountedObject<CPDF_IccProfile*>* ipData;
    224         m_IccProfileMap.GetNextAssoc(pos, ipKey, ipData);
    225         if (!ipData->m_Obj) {
    226             continue;
    227         }
    228         if (bForceRelease || ipData->m_nCount < 2) {
    229             FX_POSITION pos2 = m_HashProfileMap.GetStartPosition();
    230             while (pos2) {
    231                 CFX_ByteString bsKey;
    232                 CPDF_Stream* pFindStream = NULL;
    233                 m_HashProfileMap.GetNextAssoc(pos2, bsKey, (void*&)pFindStream);
    234                 if (ipKey == pFindStream) {
    235                     m_HashProfileMap.RemoveKey(bsKey);
    236                     break;
    237                 }
    238             }
    239             delete ipData->m_Obj;
    240             delete ipData;
    241             m_IccProfileMap.RemoveKey(ipKey);
    242         }
    243     }
    244     pos = m_FontFileMap.GetStartPosition();
    245     while (pos) {
    246         CPDF_Stream* ftKey;
    247         CPDF_CountedObject<CPDF_StreamAcc*>* ftData;
    248         m_FontFileMap.GetNextAssoc(pos, ftKey, ftData);
    249         if (!ftData->m_Obj) {
    250             continue;
    251         }
    252         if (bForceRelease || ftData->m_nCount < 2) {
    253             delete ftData->m_Obj;
    254             delete ftData;
    255             m_FontFileMap.RemoveKey(ftKey);
    256         }
    257     }
    258     pos = m_ImageMap.GetStartPosition();
    259     while (pos) {
    260         FX_DWORD objNum;
    261         CPDF_CountedObject<CPDF_Image*>* imageData;
    262         m_ImageMap.GetNextAssoc(pos, objNum, imageData);
    263         if (!imageData->m_Obj) {
    264             continue;
    265         }
    266         if (bForceRelease || imageData->m_nCount < 2) {
    267             delete imageData->m_Obj;
    268             delete imageData;
    269             m_ImageMap.RemoveKey(objNum);
    270         }
    271     }
    272 }
    273 CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly)
    274 {
    275     if (!pFontDict) {
    276         return NULL;
    277     }
    278     if (findOnly) {
    279         CPDF_CountedObject<CPDF_Font*>* fontData;
    280         if (m_FontMap.Lookup(pFontDict, fontData)) {
    281             if (!fontData->m_Obj) {
    282                 return NULL;
    283             }
    284             fontData->m_nCount ++;
    285             return fontData->m_Obj;
    286         }
    287         return NULL;
    288     }
    289     CPDF_CountedObject<CPDF_Font*>* fontData = NULL;
    290     if (m_FontMap.Lookup(pFontDict, fontData)) {
    291         if (fontData->m_Obj) {
    292             fontData->m_nCount ++;
    293             return fontData->m_Obj;
    294         }
    295     }
    296     FX_BOOL bNew = FALSE;
    297     if (!fontData) {
    298         fontData = new CPDF_CountedObject<CPDF_Font*>;
    299         bNew = TRUE;
    300     }
    301     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pFontDict);
    302     if (!pFont) {
    303         if (bNew) {
    304             delete fontData;
    305         }
    306         return NULL;
    307     }
    308     fontData->m_nCount = 2;
    309     fontData->m_Obj = pFont;
    310     m_FontMap.SetAt(pFontDict, fontData);
    311     return pFont;
    312 }
    313 CPDF_Font* CPDF_DocPageData::GetStandardFont(FX_BSTR fontName, CPDF_FontEncoding* pEncoding)
    314 {
    315     if (fontName.IsEmpty()) {
    316         return NULL;
    317     }
    318     FX_POSITION pos = m_FontMap.GetStartPosition();
    319     while (pos) {
    320         CPDF_Dictionary* fontDict;
    321         CPDF_CountedObject<CPDF_Font*>* fontData;
    322         m_FontMap.GetNextAssoc(pos, fontDict, fontData);
    323         CPDF_Font* pFont = fontData->m_Obj;
    324         if (!pFont) {
    325             continue;
    326         }
    327         if (pFont->GetBaseFont() != fontName) {
    328             continue;
    329         }
    330         if (pFont->IsEmbedded()) {
    331             continue;
    332         }
    333         if (pFont->GetFontType() != PDFFONT_TYPE1) {
    334             continue;
    335         }
    336         if (pFont->GetFontDict()->KeyExist(FX_BSTRC("Widths"))) {
    337             continue;
    338         }
    339         CPDF_Type1Font* pT1Font = pFont->GetType1Font();
    340         if (pEncoding && !pT1Font->GetEncoding()->IsIdentical(pEncoding)) {
    341             continue;
    342         }
    343         fontData->m_nCount ++;
    344         return pFont;
    345     }
    346     CPDF_Dictionary* pDict = new CPDF_Dictionary;
    347     pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Font"));
    348     pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Type1"));
    349     pDict->SetAtName(FX_BSTRC("BaseFont"), fontName);
    350     if (pEncoding) {
    351         pDict->SetAt(FX_BSTRC("Encoding"), pEncoding->Realize());
    352     }
    353     m_pPDFDoc->AddIndirectObject(pDict);
    354     CPDF_CountedObject<CPDF_Font*>* fontData = new CPDF_CountedObject<CPDF_Font*>;
    355     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pDict);
    356     if (!pFont) {
    357         delete fontData;
    358         return NULL;
    359     }
    360     fontData->m_nCount = 2;
    361     fontData->m_Obj = pFont;
    362     m_FontMap.SetAt(pDict, fontData);
    363     return pFont;
    364 }
    365 void CPDF_DocPageData::ReleaseFont(CPDF_Dictionary* pFontDict)
    366 {
    367     if (!pFontDict) {
    368         return;
    369     }
    370     CPDF_CountedObject<CPDF_Font*>* fontData;
    371     if (!m_FontMap.Lookup(pFontDict, fontData)) {
    372         return;
    373     }
    374     if (fontData->m_Obj && --fontData->m_nCount == 0) {
    375         delete fontData->m_Obj;
    376         fontData->m_Obj = NULL;
    377     }
    378 }
    379 CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
    380 {
    381     if (!pCSObj) {
    382         return NULL;
    383     }
    384     if (pCSObj->GetType() == PDFOBJ_NAME) {
    385         CFX_ByteString name = pCSObj->GetConstString();
    386         CPDF_ColorSpace* pCS = _CSFromName(name);
    387         if (!pCS && pResources) {
    388             CPDF_Dictionary* pList = pResources->GetDict(FX_BSTRC("ColorSpace"));
    389             if (pList) {
    390                 pCSObj = pList->GetElementValue(name);
    391                 return GetColorSpace(pCSObj, NULL);
    392             }
    393         }
    394         if (pCS == NULL || pResources == NULL) {
    395             return pCS;
    396         }
    397         CPDF_Dictionary* pColorSpaces = pResources->GetDict(FX_BSTRC("ColorSpace"));
    398         if (pColorSpaces == NULL) {
    399             return pCS;
    400         }
    401         CPDF_Object* pDefaultCS = NULL;
    402         switch (pCS->GetFamily()) {
    403             case PDFCS_DEVICERGB:
    404                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultRGB"));
    405                 break;
    406             case PDFCS_DEVICEGRAY:
    407                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultGray"));
    408                 break;
    409             case PDFCS_DEVICECMYK:
    410                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultCMYK"));
    411                 break;
    412         }
    413         if (pDefaultCS == NULL) {
    414             return pCS;
    415         }
    416         return GetColorSpace(pDefaultCS, NULL);
    417     }
    418     if (pCSObj->GetType() != PDFOBJ_ARRAY) {
    419         return NULL;
    420     }
    421     CPDF_Array* pArray = (CPDF_Array*)pCSObj;
    422     if (pArray->GetCount() == 0) {
    423         return NULL;
    424     }
    425     if (pArray->GetCount() == 1) {
    426         return GetColorSpace(pArray->GetElementValue(0), pResources);
    427     }
    428     CPDF_CountedObject<CPDF_ColorSpace*>* csData = NULL;
    429     if (m_ColorSpaceMap.Lookup(pCSObj, csData)) {
    430         if (csData->m_Obj) {
    431             csData->m_nCount++;
    432             return csData->m_Obj;
    433         }
    434     }
    435     FX_BOOL bNew = FALSE;
    436     if (!csData) {
    437         csData = new CPDF_CountedObject<CPDF_ColorSpace*>;
    438         bNew = TRUE;
    439     }
    440     CPDF_ColorSpace* pCS = CPDF_ColorSpace::Load(m_pPDFDoc, pArray);
    441     if (!pCS) {
    442         if (bNew) {
    443             delete csData;
    444         }
    445         return NULL;
    446     }
    447     csData->m_nCount = 2;
    448     csData->m_Obj = pCS;
    449     m_ColorSpaceMap.SetAt(pCSObj, csData);
    450     return pCS;
    451 }
    452 CPDF_ColorSpace* CPDF_DocPageData::GetCopiedColorSpace(CPDF_Object* pCSObj)
    453 {
    454     if (!pCSObj) {
    455         return NULL;
    456     }
    457     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    458     if (!m_ColorSpaceMap.Lookup(pCSObj, csData)) {
    459         return NULL;
    460     }
    461     if (!csData->m_Obj) {
    462         return NULL;
    463     }
    464     csData->m_nCount ++;
    465     return csData->m_Obj;
    466 }
    467 void CPDF_DocPageData::ReleaseColorSpace(CPDF_Object* pColorSpace)
    468 {
    469     if (!pColorSpace) {
    470         return;
    471     }
    472     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    473     if (!m_ColorSpaceMap.Lookup(pColorSpace, csData)) {
    474         return;
    475     }
    476     if (csData->m_Obj && --csData->m_nCount == 0) {
    477         csData->m_Obj->ReleaseCS();
    478         csData->m_Obj = NULL;
    479     }
    480 }
    481 CPDF_Pattern* CPDF_DocPageData::GetPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)
    482 {
    483     if (!pPatternObj) {
    484         return NULL;
    485     }
    486     CPDF_CountedObject<CPDF_Pattern*>* ptData = NULL;
    487     if (m_PatternMap.Lookup(pPatternObj, ptData)) {
    488         if (ptData->m_Obj) {
    489             ptData->m_nCount++;
    490             return ptData->m_Obj;
    491         }
    492     }
    493     FX_BOOL bNew = FALSE;
    494     if (!ptData) {
    495         ptData = new CPDF_CountedObject<CPDF_Pattern*>;
    496         bNew = TRUE;
    497     }
    498     CPDF_Pattern* pPattern = NULL;
    499     if (bShading) {
    500         pPattern = new CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, bShading, matrix);
    501     } else {
    502         CPDF_Dictionary* pDict = pPatternObj ? pPatternObj->GetDict() : NULL;
    503         if (pDict) {
    504             int type = pDict->GetInteger(FX_BSTRC("PatternType"));
    505             if (type == 1) {
    506                 pPattern = new CPDF_TilingPattern(m_pPDFDoc, pPatternObj, matrix);
    507             } else if (type == 2) {
    508                 pPattern = new CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, FALSE, matrix);
    509             }
    510         }
    511     }
    512     if (!pPattern) {
    513         if (bNew) {
    514             delete ptData;
    515         }
    516         return NULL;
    517     }
    518     ptData->m_nCount = 2;
    519     ptData->m_Obj = pPattern;
    520     m_PatternMap.SetAt(pPatternObj, ptData);
    521     return pPattern;
    522 }
    523 void CPDF_DocPageData::ReleasePattern(CPDF_Object* pPatternObj)
    524 {
    525     if (!pPatternObj) {
    526         return;
    527     }
    528     CPDF_CountedObject<CPDF_Pattern*>* ptData;
    529     if (!m_PatternMap.Lookup(pPatternObj, ptData)) {
    530         return;
    531     }
    532     if (ptData->m_Obj && --ptData->m_nCount == 0) {
    533         delete ptData->m_Obj;
    534         ptData->m_Obj = NULL;
    535     }
    536 }
    537 CPDF_Image* CPDF_DocPageData::GetImage(CPDF_Object* pImageStream)
    538 {
    539     if (!pImageStream) {
    540         return NULL;
    541     }
    542     FX_DWORD dwImageObjNum = pImageStream->GetObjNum();
    543     CPDF_CountedObject<CPDF_Image*>* imageData;
    544     if (m_ImageMap.Lookup(dwImageObjNum, imageData)) {
    545         imageData->m_nCount ++;
    546         return imageData->m_Obj;
    547     }
    548     imageData = new CPDF_CountedObject<CPDF_Image*>;
    549     CPDF_Image* pImage = new CPDF_Image(m_pPDFDoc);
    550     pImage->LoadImageF((CPDF_Stream*)pImageStream, FALSE);
    551     imageData->m_nCount = 2;
    552     imageData->m_Obj = pImage;
    553     m_ImageMap.SetAt(dwImageObjNum, imageData);
    554     return pImage;
    555 }
    556 void CPDF_DocPageData::ReleaseImage(CPDF_Object* pImageStream)
    557 {
    558     if (!pImageStream) {
    559         return;
    560     }
    561     PDF_DocPageData_Release<FX_DWORD, CPDF_Image*>(m_ImageMap, pImageStream->GetObjNum(), NULL);
    562 }
    563 CPDF_IccProfile* CPDF_DocPageData::GetIccProfile(CPDF_Stream* pIccProfileStream)
    564 {
    565     if (!pIccProfileStream) {
    566         return NULL;
    567     }
    568     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;
    569     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData)) {
    570         ipData->m_nCount++;
    571         return ipData->m_Obj;
    572     }
    573     CPDF_StreamAcc stream;
    574     stream.LoadAllData(pIccProfileStream, FALSE);
    575     FX_BYTE digest[20];
    576     CPDF_Stream* pCopiedStream = NULL;
    577     CRYPT_SHA1Generate(stream.GetData(), stream.GetSize(), digest);
    578     if (m_HashProfileMap.Lookup(CFX_ByteStringC(digest, 20), (void*&)pCopiedStream)) {
    579         m_IccProfileMap.Lookup(pCopiedStream, ipData);
    580         ipData->m_nCount++;
    581         return ipData->m_Obj;
    582     }
    583     CPDF_IccProfile* pProfile = new CPDF_IccProfile(stream.GetData(), stream.GetSize());
    584     ipData = new CPDF_CountedObject<CPDF_IccProfile*>;
    585     ipData->m_nCount = 2;
    586     ipData->m_Obj = pProfile;
    587     m_IccProfileMap.SetAt(pIccProfileStream, ipData);
    588     m_HashProfileMap.SetAt(CFX_ByteStringC(digest, 20), pIccProfileStream);
    589     return pProfile;
    590 }
    591 void CPDF_DocPageData::ReleaseIccProfile(CPDF_Stream* pIccProfileStream, CPDF_IccProfile* pIccProfile)
    592 {
    593     if (!pIccProfileStream && !pIccProfile) {
    594         return;
    595     }
    596     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;
    597     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData) && ipData->m_nCount < 2) {
    598         FX_POSITION pos = m_HashProfileMap.GetStartPosition();
    599         while (pos) {
    600             CFX_ByteString key;
    601             CPDF_Stream* pFindStream = NULL;
    602             m_HashProfileMap.GetNextAssoc(pos, key, (void*&)pFindStream);
    603             if (pIccProfileStream == pFindStream) {
    604                 m_HashProfileMap.RemoveKey(key);
    605                 break;
    606             }
    607         }
    608     }
    609     PDF_DocPageData_Release<CPDF_Stream*, CPDF_IccProfile*>(m_IccProfileMap, pIccProfileStream, pIccProfile);
    610 }
    611 CPDF_StreamAcc* CPDF_DocPageData::GetFontFileStreamAcc(CPDF_Stream* pFontStream)
    612 {
    613     if (!pFontStream) {
    614         return NULL;
    615     }
    616     CPDF_CountedObject<CPDF_StreamAcc*>* ftData;
    617     if (m_FontFileMap.Lookup(pFontStream, ftData)) {
    618         ftData->m_nCount ++;
    619         return ftData->m_Obj;
    620     }
    621     ftData = new CPDF_CountedObject<CPDF_StreamAcc*>;
    622     CPDF_StreamAcc* pFontFile = new CPDF_StreamAcc;
    623     CPDF_Dictionary* pFontDict = pFontStream->GetDict();
    624     FX_INT32 org_size = pFontDict->GetInteger(FX_BSTRC("Length1")) + pFontDict->GetInteger(FX_BSTRC("Length2")) + pFontDict->GetInteger(FX_BSTRC("Length3"));
    625     if (org_size < 0) {
    626         org_size = 0;
    627     }
    628     pFontFile->LoadAllData(pFontStream, FALSE, org_size);
    629     ftData->m_nCount = 2;
    630     ftData->m_Obj = pFontFile;
    631     m_FontFileMap.SetAt(pFontStream, ftData);
    632     return pFontFile;
    633 }
    634 void CPDF_DocPageData::ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream, FX_BOOL bForce)
    635 {
    636     if (!pFontStream) {
    637         return;
    638     }
    639     PDF_DocPageData_Release<CPDF_Stream*, CPDF_StreamAcc*>(m_FontFileMap, pFontStream, NULL, bForce);
    640 }
    641 CPDF_CountedColorSpace* CPDF_DocPageData::FindColorSpacePtr(CPDF_Object* pCSObj) const
    642 {
    643     if (!pCSObj) return NULL;
    644     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    645     if (m_ColorSpaceMap.Lookup(pCSObj, csData))
    646     {
    647         return csData;
    648     }
    649     return NULL;
    650 }
    651 CPDF_CountedPattern* CPDF_DocPageData::FindPatternPtr(CPDF_Object* pPatternObj) const
    652 {
    653     if (!pPatternObj) return NULL;
    654     CPDF_CountedObject<CPDF_Pattern*>* ptData;
    655     if (m_PatternMap.Lookup(pPatternObj, ptData))
    656     {
    657         return ptData;
    658     }
    659     return NULL;
    660 }
    661