Replace FX_NEW with new, remove tests from fpdfapi
[pdfium.git] / core / src / fpdfapi / fpdf_page / fpdf_page_doc.cpp
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 }