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 FX_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     if (m_pPageModule) {
     63         delete m_pPageModule;
     64     }
     65     CPDF_PageModule* pPageModule = FX_NEW CPDF_PageModule;
     66     m_pPageModule = pPageModule;
     67 }
     68 void CPDF_PageModule::ReleaseDoc(CPDF_Document* pDoc)
     69 {
     70     delete pDoc->GetPageData();
     71 }
     72 void CPDF_PageModule::ClearDoc(CPDF_Document* pDoc)
     73 {
     74     pDoc->GetPageData()->Clear(FALSE);
     75 }
     76 void CPDF_PageModule::NotifyCJKAvailable()
     77 {
     78     m_FontGlobals.m_CMapManager.ReloadAll();
     79 }
     80 CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict)
     81 {
     82     if (!pFontDict) {
     83         return NULL;
     84     }
     85     return GetValidatePageData()->GetFont(pFontDict, FALSE);
     86 }
     87 CPDF_Font* CPDF_Document::FindFont(CPDF_Dictionary* pFontDict)
     88 {
     89     if (!pFontDict) {
     90         return NULL;
     91     }
     92     return GetValidatePageData()->GetFont(pFontDict, TRUE);
     93 }
     94 CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream)
     95 {
     96     if (pStream == NULL) {
     97         return NULL;
     98     }
     99     return GetValidatePageData()->GetFontFileStreamAcc(pStream);
    100 }
    101 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name);
    102 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
    103 {
    104     return GetValidatePageData()->GetColorSpace(pCSObj, pResources);
    105 }
    106 CPDF_Pattern* CPDF_Document::LoadPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)
    107 {
    108     return GetValidatePageData()->GetPattern(pPatternObj, bShading, matrix);
    109 }
    110 CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream, int nComponents)
    111 {
    112     return GetValidatePageData()->GetIccProfile(pStream, nComponents);
    113 }
    114 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj)
    115 {
    116     if (!pObj) {
    117         return NULL;
    118     }
    119     FXSYS_assert(pObj->GetObjNum());
    120     return GetValidatePageData()->GetImage(pObj);
    121 }
    122 void CPDF_Document::RemoveColorSpaceFromPageData(CPDF_Object* pCSObj)
    123 {
    124     if (!pCSObj) {
    125         return;
    126     }
    127     GetPageData()->ReleaseColorSpace(pCSObj);
    128 }
    129 CPDF_DocPageData::CPDF_DocPageData(CPDF_Document *pPDFDoc)
    130     : m_pPDFDoc(pPDFDoc)
    131     , m_FontMap()
    132     , m_ColorSpaceMap()
    133     , m_PatternMap()
    134     , m_ImageMap()
    135     , m_IccProfileMap()
    136     , m_FontFileMap()
    137 {
    138     m_FontMap.InitHashTable(64);
    139     m_ColorSpaceMap.InitHashTable(32);
    140     m_PatternMap.InitHashTable(16);
    141     m_ImageMap.InitHashTable(64);
    142     m_IccProfileMap.InitHashTable(16);
    143     m_FontFileMap.InitHashTable(32);
    144 }
    145 CPDF_DocPageData::~CPDF_DocPageData()
    146 {
    147     Clear(FALSE);
    148     Clear(TRUE);
    149     FX_POSITION pos = NULL;
    150 }
    151 void CPDF_DocPageData::Clear(FX_BOOL bRelease)
    152 {
    153     FX_POSITION pos;
    154     FX_DWORD	nCount;
    155     {
    156         pos = m_PatternMap.GetStartPosition();
    157         while (pos) {
    158             CPDF_Object* ptObj;
    159             CPDF_CountedObject<CPDF_Pattern*>* ptData;
    160             m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
    161             nCount = ptData->m_nCount;
    162             if (bRelease || nCount < 2) {
    163                 delete ptData->m_Obj;
    164                 ptData->m_Obj = NULL;
    165             }
    166         }
    167     }
    168     {
    169         pos = m_FontMap.GetStartPosition();
    170         while (pos) {
    171             CPDF_Dictionary* fontDict;
    172             CPDF_CountedObject<CPDF_Font*>* fontData;
    173             m_FontMap.GetNextAssoc(pos, fontDict, fontData);
    174             nCount = fontData->m_nCount;
    175             if (bRelease || nCount < 2) {
    176                 delete fontData->m_Obj;
    177                 fontData->m_Obj = NULL;
    178             }
    179         }
    180     }
    181     {
    182         pos = m_ImageMap.GetStartPosition();
    183         while (pos) {
    184             FX_DWORD objNum;
    185             CPDF_CountedObject<CPDF_Image*>* imageData;
    186             m_ImageMap.GetNextAssoc(pos, objNum, imageData);
    187             nCount = imageData->m_nCount;
    188             if (bRelease || nCount < 2) {
    189                 delete imageData->m_Obj;
    190                 delete imageData;
    191                 m_ImageMap.RemoveKey(objNum);
    192             }
    193         }
    194     }
    195     {
    196         pos = m_ColorSpaceMap.GetStartPosition();
    197         while (pos) {
    198             CPDF_Object* csKey;
    199             CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    200             m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);
    201             nCount = csData->m_nCount;
    202             if (bRelease || nCount < 2) {
    203                 csData->m_Obj->ReleaseCS();
    204                 csData->m_Obj = NULL;
    205             }
    206         }
    207     }
    208     {
    209         pos = m_IccProfileMap.GetStartPosition();
    210         while (pos) {
    211             CPDF_Stream* ipKey;
    212             CPDF_CountedObject<CPDF_IccProfile*>* ipData;
    213             m_IccProfileMap.GetNextAssoc(pos, ipKey, ipData);
    214             nCount = ipData->m_nCount;
    215             if (bRelease || nCount < 2) {
    216                 FX_POSITION pos2 = m_HashProfileMap.GetStartPosition();
    217                 while (pos2) {
    218                     CFX_ByteString bsKey;
    219                     CPDF_Stream* pFindStream = NULL;
    220                     m_HashProfileMap.GetNextAssoc(pos2, bsKey, (void*&)pFindStream);
    221                     if (ipKey == pFindStream) {
    222                         m_HashProfileMap.RemoveKey(bsKey);
    223                         break;
    224                     }
    225                 }
    226                 delete ipData->m_Obj;
    227                 delete ipData;
    228                 m_IccProfileMap.RemoveKey(ipKey);
    229             }
    230         }
    231     }
    232     {
    233         pos = m_FontFileMap.GetStartPosition();
    234         while (pos) {
    235             CPDF_Stream* ftKey;
    236             CPDF_CountedObject<CPDF_StreamAcc*>* ftData;
    237             m_FontFileMap.GetNextAssoc(pos, ftKey, ftData);
    238             nCount = ftData->m_nCount;
    239             if (bRelease || nCount < 2) {
    240                 delete ftData->m_Obj;
    241                 delete ftData;
    242                 m_FontFileMap.RemoveKey(ftKey);
    243             }
    244         }
    245     }
    246 }
    247 CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly)
    248 {
    249     if (!pFontDict) {
    250         return NULL;
    251     }
    252     if (findOnly) {
    253         CPDF_CountedObject<CPDF_Font*>* fontData;
    254         if (m_FontMap.Lookup(pFontDict, fontData)) {
    255             if (!fontData->m_Obj) {
    256                 return NULL;
    257             }
    258             fontData->m_nCount ++;
    259             return fontData->m_Obj;
    260         }
    261         return NULL;
    262     }
    263     CPDF_CountedObject<CPDF_Font*>* fontData = NULL;
    264     if (m_FontMap.Lookup(pFontDict, fontData)) {
    265         if (fontData->m_Obj) {
    266             fontData->m_nCount ++;
    267             return fontData->m_Obj;
    268         }
    269     }
    270     FX_BOOL bNew = FALSE;
    271     if (!fontData) {
    272         fontData = FX_NEW CPDF_CountedObject<CPDF_Font*>;
    273         bNew = TRUE;
    274         if (!fontData) {
    275             return NULL;
    276         }
    277     }
    278     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pFontDict);
    279     if (!pFont) {
    280         if (bNew) {
    281             delete fontData;
    282         }
    283         return NULL;
    284     }
    285     fontData->m_nCount = 2;
    286     fontData->m_Obj = pFont;
    287     m_FontMap.SetAt(pFontDict, fontData);
    288     return pFont;
    289 }
    290 CPDF_Font* CPDF_DocPageData::GetStandardFont(FX_BSTR fontName, CPDF_FontEncoding* pEncoding)
    291 {
    292     if (fontName.IsEmpty()) {
    293         return NULL;
    294     }
    295     FX_POSITION pos = m_FontMap.GetStartPosition();
    296     while (pos) {
    297         CPDF_Dictionary* fontDict;
    298         CPDF_CountedObject<CPDF_Font*>* fontData;
    299         m_FontMap.GetNextAssoc(pos, fontDict, fontData);
    300         CPDF_Font* pFont = fontData->m_Obj;
    301         if (!pFont) {
    302             continue;
    303         }
    304         if (pFont->GetBaseFont() != fontName) {
    305             continue;
    306         }
    307         if (pFont->IsEmbedded()) {
    308             continue;
    309         }
    310         if (pFont->GetFontType() != PDFFONT_TYPE1) {
    311             continue;
    312         }
    313         if (pFont->GetFontDict()->KeyExist(FX_BSTRC("Widths"))) {
    314             continue;
    315         }
    316         CPDF_Type1Font* pT1Font = pFont->GetType1Font();
    317         if (pEncoding && !pT1Font->GetEncoding()->IsIdentical(pEncoding)) {
    318             continue;
    319         }
    320         fontData->m_nCount ++;
    321         return pFont;
    322     }
    323     CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;
    324     pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Font"));
    325     pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Type1"));
    326     pDict->SetAtName(FX_BSTRC("BaseFont"), fontName);
    327     if (pEncoding) {
    328         pDict->SetAt(FX_BSTRC("Encoding"), pEncoding->Realize());
    329     }
    330     m_pPDFDoc->AddIndirectObject(pDict);
    331     CPDF_CountedObject<CPDF_Font*>* fontData = FX_NEW CPDF_CountedObject<CPDF_Font*>;
    332     if (!fontData) {
    333         return NULL;
    334     }
    335     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pDict);
    336     if (!pFont) {
    337         delete fontData;
    338         return NULL;
    339     }
    340     fontData->m_nCount = 2;
    341     fontData->m_Obj = pFont;
    342     m_FontMap.SetAt(pDict, fontData);
    343     return pFont;
    344 }
    345 void CPDF_DocPageData::ReleaseFont(CPDF_Dictionary* pFontDict)
    346 {
    347     if (!pFontDict) {
    348         return;
    349     }
    350     CPDF_CountedObject<CPDF_Font*>* fontData;
    351     if (!m_FontMap.Lookup(pFontDict, fontData)) {
    352         return;
    353     }
    354     if (fontData->m_Obj && --fontData->m_nCount == 0) {
    355         delete fontData->m_Obj;
    356         fontData->m_Obj = NULL;
    357     }
    358 }
    359 CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
    360 {
    361     if (!pCSObj) {
    362         return NULL;
    363     }
    364     if (pCSObj->GetType() == PDFOBJ_NAME) {
    365         CFX_ByteString name = pCSObj->GetConstString();
    366         CPDF_ColorSpace* pCS = _CSFromName(name);
    367         if (!pCS && pResources) {
    368             CPDF_Dictionary* pList = pResources->GetDict(FX_BSTRC("ColorSpace"));
    369             if (pList) {
    370                 pCSObj = pList->GetElementValue(name);
    371                 return GetColorSpace(pCSObj, NULL);
    372             }
    373         }
    374         if (pCS == NULL || pResources == NULL) {
    375             return pCS;
    376         }
    377         CPDF_Dictionary* pColorSpaces = pResources->GetDict(FX_BSTRC("ColorSpace"));
    378         if (pColorSpaces == NULL) {
    379             return pCS;
    380         }
    381         CPDF_Object* pDefaultCS = NULL;
    382         switch (pCS->GetFamily()) {
    383             case PDFCS_DEVICERGB:
    384                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultRGB"));
    385                 break;
    386             case PDFCS_DEVICEGRAY:
    387                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultGray"));
    388                 break;
    389             case PDFCS_DEVICECMYK:
    390                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultCMYK"));
    391                 break;
    392         }
    393         if (pDefaultCS == NULL) {
    394             return pCS;
    395         }
    396         return GetColorSpace(pDefaultCS, NULL);
    397     }
    398     if (pCSObj->GetType() != PDFOBJ_ARRAY) {
    399         return NULL;
    400     }
    401     CPDF_Array* pArray = (CPDF_Array*)pCSObj;
    402     if (pArray->GetCount() == 0) {
    403         return NULL;
    404     }
    405     if (pArray->GetCount() == 1) {
    406         return GetColorSpace(pArray->GetElementValue(0), pResources);
    407     }
    408     CPDF_CountedObject<CPDF_ColorSpace*>* csData = NULL;
    409     if (m_ColorSpaceMap.Lookup(pCSObj, csData)) {
    410         if (csData->m_Obj) {
    411             csData->m_nCount++;
    412             return csData->m_Obj;
    413         }
    414     }
    415     FX_BOOL bNew = FALSE;
    416     if (!csData) {
    417         csData = FX_NEW CPDF_CountedObject<CPDF_ColorSpace*>;
    418         if (!csData) {
    419             return NULL;
    420         }
    421         bNew = TRUE;
    422     }
    423     CPDF_ColorSpace* pCS = CPDF_ColorSpace::Load(m_pPDFDoc, pArray);
    424     if (!pCS) {
    425         if (bNew) {
    426             delete csData;
    427         }
    428         return NULL;
    429     }
    430     csData->m_nCount = 2;
    431     csData->m_Obj = pCS;
    432     m_ColorSpaceMap.SetAt(pCSObj, csData);
    433     return pCS;
    434 }
    435 CPDF_ColorSpace* CPDF_DocPageData::GetCopiedColorSpace(CPDF_Object* pCSObj)
    436 {
    437     if (!pCSObj) {
    438         return NULL;
    439     }
    440     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    441     if (!m_ColorSpaceMap.Lookup(pCSObj, csData)) {
    442         return NULL;
    443     }
    444     if (!csData->m_Obj) {
    445         return NULL;
    446     }
    447     csData->m_nCount ++;
    448     return csData->m_Obj;
    449 }
    450 void CPDF_DocPageData::ReleaseColorSpace(CPDF_Object* pColorSpace)
    451 {
    452     if (!pColorSpace) {
    453         return;
    454     }
    455     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
    456     if (!m_ColorSpaceMap.Lookup(pColorSpace, csData)) {
    457         return;
    458     }
    459     if (csData->m_Obj && --csData->m_nCount == 0) {
    460         csData->m_Obj->ReleaseCS();
    461         csData->m_Obj = NULL;
    462     }
    463 }
    464 CPDF_Pattern* CPDF_DocPageData::GetPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)
    465 {
    466     if (!pPatternObj) {
    467         return NULL;
    468     }
    469     CPDF_CountedObject<CPDF_Pattern*>* ptData = NULL;
    470     if (m_PatternMap.Lookup(pPatternObj, ptData)) {
    471         if (ptData->m_Obj) {
    472             ptData->m_nCount++;
    473             return ptData->m_Obj;
    474         }
    475     }
    476     FX_BOOL bNew = FALSE;
    477     if (!ptData) {
    478         ptData = FX_NEW CPDF_CountedObject<CPDF_Pattern*>;
    479         bNew = TRUE;
    480         if (!ptData) {
    481             return NULL;
    482         }
    483     }
    484     CPDF_Pattern* pPattern = NULL;
    485     if (bShading) {
    486         pPattern = FX_NEW CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, bShading, matrix);
    487     } else {
    488         CPDF_Dictionary* pDict = pPatternObj->GetDict();
    489         if (pDict) {
    490             int type = pDict->GetInteger(FX_BSTRC("PatternType"));
    491             if (type == 1) {
    492                 pPattern = FX_NEW CPDF_TilingPattern(m_pPDFDoc, pPatternObj, matrix);
    493             } else if (type == 2) {
    494                 pPattern = FX_NEW CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, FALSE, matrix);
    495             }
    496         }
    497     }
    498     if (!pPattern) {
    499         if (bNew) {
    500             delete ptData;
    501         }
    502         return NULL;
    503     }
    504     ptData->m_nCount = 2;
    505     ptData->m_Obj = pPattern;
    506     m_PatternMap.SetAt(pPatternObj, ptData);
    507     return pPattern;
    508 }
    509 void CPDF_DocPageData::ReleasePattern(CPDF_Object* pPatternObj)
    510 {
    511     if (!pPatternObj) {
    512         return;
    513     }
    514     CPDF_CountedObject<CPDF_Pattern*>* ptData;
    515     if (!m_PatternMap.Lookup(pPatternObj, ptData)) {
    516         return;
    517     }
    518     if (ptData->m_Obj && --ptData->m_nCount == 0) {
    519         delete ptData->m_Obj;
    520         ptData->m_Obj = NULL;
    521     }
    522 }
    523 CPDF_Image* CPDF_DocPageData::GetImage(CPDF_Object* pImageStream)
    524 {
    525     if (!pImageStream) {
    526         return NULL;
    527     }
    528     FX_DWORD dwImageObjNum = pImageStream->GetObjNum();
    529     CPDF_CountedObject<CPDF_Image*>* imageData;
    530     if (m_ImageMap.Lookup(dwImageObjNum, imageData)) {
    531         imageData->m_nCount ++;
    532         return imageData->m_Obj;
    533     }
    534     imageData = FX_NEW CPDF_CountedObject<CPDF_Image*>;
    535     if (!imageData) {
    536         return NULL;
    537     }
    538     CPDF_Image* pImage = FX_NEW CPDF_Image(m_pPDFDoc);
    539     if (!pImage) {
    540         delete imageData;
    541         return NULL;
    542     }
    543     pImage->LoadImageF((CPDF_Stream*)pImageStream, FALSE);
    544     imageData->m_nCount = 2;
    545     imageData->m_Obj = pImage;
    546     m_ImageMap.SetAt(dwImageObjNum, imageData);
    547     return pImage;
    548 }
    549 void CPDF_DocPageData::ReleaseImage(CPDF_Object* pImageStream)
    550 {
    551     if (!pImageStream) {
    552         return;
    553     }
    554     PDF_DocPageData_Release<FX_DWORD, CPDF_Image*>(m_ImageMap, pImageStream->GetObjNum(), NULL);
    555 }
    556 CPDF_IccProfile* CPDF_DocPageData::GetIccProfile(CPDF_Stream* pIccProfileStream, FX_INT32 nComponents)
    557 {
    558     if (!pIccProfileStream) {
    559         return NULL;
    560     }
    561     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;
    562     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData)) {
    563         ipData->m_nCount++;
    564         return ipData->m_Obj;
    565     }
    566     CPDF_StreamAcc stream;
    567     stream.LoadAllData(pIccProfileStream, FALSE);
    568     FX_BYTE digest[20];
    569     CPDF_Stream* pCopiedStream = NULL;
    570     CRYPT_SHA1Generate(stream.GetData(), stream.GetSize(), digest);
    571     if (m_HashProfileMap.Lookup(CFX_ByteStringC(digest, 20), (void*&)pCopiedStream)) {
    572         m_IccProfileMap.Lookup(pCopiedStream, ipData);
    573         ipData->m_nCount++;
    574         return ipData->m_Obj;
    575     }
    576     CPDF_IccProfile* pProfile = FX_NEW CPDF_IccProfile(stream.GetData(), stream.GetSize(), nComponents);
    577     if (!pProfile) {
    578         return NULL;
    579     }
    580     ipData = FX_NEW CPDF_CountedObject<CPDF_IccProfile*>;
    581     if (!ipData) {
    582         delete pProfile;
    583         return NULL;
    584     }
    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 = FX_NEW CPDF_CountedObject<CPDF_StreamAcc*>;
    622     if (!ftData) {
    623         return NULL;
    624     }
    625     CPDF_StreamAcc* pFontFile = FX_NEW CPDF_StreamAcc;
    626     if (!pFontFile) {
    627         delete ftData;
    628         return NULL;
    629     }
    630     CPDF_Dictionary* pFontDict = pFontStream->GetDict();
    631     FX_INT32 org_size = pFontDict->GetInteger(FX_BSTRC("Length1")) + pFontDict->GetInteger(FX_BSTRC("Length2")) + pFontDict->GetInteger(FX_BSTRC("Length3"));
    632     if (org_size < 0) {
    633         org_size = 0;
    634     }
    635     pFontFile->LoadAllData(pFontStream, FALSE, org_size);
    636     ftData->m_nCount = 2;
    637     ftData->m_Obj = pFontFile;
    638     m_FontFileMap.SetAt(pFontStream, ftData);
    639     return pFontFile;
    640 }
    641 void CPDF_DocPageData::ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream, FX_BOOL bForce)
    642 {
    643     if (!pFontStream) {
    644         return;
    645     }
    646     PDF_DocPageData_Release<CPDF_Stream*, CPDF_StreamAcc*>(m_FontFileMap, pFontStream, NULL, bForce);
    647 }
    648