Adjust the order of clearing resource in CPDF_DocPageData::Clear
[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 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)
111 {
112     return GetValidatePageData()->GetIccProfile(pStream);
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     , m_bForceClear(FALSE)
138 {
139     m_FontMap.InitHashTable(64);
140     m_ColorSpaceMap.InitHashTable(32);
141     m_PatternMap.InitHashTable(16);
142     m_ImageMap.InitHashTable(64);
143     m_IccProfileMap.InitHashTable(16);
144     m_FontFileMap.InitHashTable(32);
145 }
146 CPDF_DocPageData::~CPDF_DocPageData()
147 {
148     Clear(FALSE);
149     Clear(TRUE);
150 }
151 void CPDF_DocPageData::Clear(FX_BOOL bForceRelease)
152 {
153     FX_POSITION pos;
154
155     m_bForceClear = bForceRelease;
156
157     // Release objects saved in the resource maps like font map and color space map.
158     // The compound objects shall be released before simple ones.
159     pos = m_FontMap.GetStartPosition();
160     while (pos) {
161         CPDF_Dictionary* fontDict;
162         CPDF_CountedObject<CPDF_Font*>* fontData;
163         m_FontMap.GetNextAssoc(pos, fontDict, fontData);
164         if (!fontData->m_Obj) {
165             continue;
166         }
167         if (bForceRelease || fontData->m_nCount < 2) {
168             delete fontData->m_Obj;
169             fontData->m_Obj = NULL;
170         }
171     }
172     pos = m_ColorSpaceMap.GetStartPosition();
173     while (pos) {
174         CPDF_Object* csKey;
175         CPDF_CountedObject<CPDF_ColorSpace*>* csData;
176         m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);
177         if (!csData->m_Obj) {
178             continue;
179         }
180         if (bForceRelease || csData->m_nCount < 2) {
181             // csData->m_Obj is deleted in the function of ReleaseCS().
182             csData->m_Obj->ReleaseCS();
183             csData->m_Obj = NULL;
184         }
185     }
186     pos = m_IccProfileMap.GetStartPosition();
187     while (pos) {
188         CPDF_Stream* ipKey;
189         CPDF_CountedObject<CPDF_IccProfile*>* ipData;
190         m_IccProfileMap.GetNextAssoc(pos, ipKey, ipData);
191         if (!ipData->m_Obj) {
192             continue;
193         }
194         if (bForceRelease || ipData->m_nCount < 2) {
195             FX_POSITION pos2 = m_HashProfileMap.GetStartPosition();
196             while (pos2) {
197                 CFX_ByteString bsKey;
198                 CPDF_Stream* pFindStream = NULL;
199                 m_HashProfileMap.GetNextAssoc(pos2, bsKey, (void*&)pFindStream);
200                 if (ipKey == pFindStream) {
201                     m_HashProfileMap.RemoveKey(bsKey);
202                     break;
203                 }
204             }
205             delete ipData->m_Obj;
206             ipData->m_Obj = NULL;
207             delete ipData;
208             m_IccProfileMap.RemoveKey(ipKey);
209         }
210     }
211     pos = m_FontFileMap.GetStartPosition();
212     while (pos) {
213         CPDF_Stream* ftKey;
214         CPDF_CountedObject<CPDF_StreamAcc*>* ftData;
215         m_FontFileMap.GetNextAssoc(pos, ftKey, ftData);
216         if (!ftData->m_Obj) {
217             continue;
218         }
219         if (bForceRelease || ftData->m_nCount < 2) {
220             delete ftData->m_Obj;
221             ftData->m_Obj = NULL;
222             delete ftData;
223             m_FontFileMap.RemoveKey(ftKey);
224         }
225     }
226     pos = m_PatternMap.GetStartPosition();
227     while (pos) {
228         CPDF_Object* ptObj;
229         CPDF_CountedObject<CPDF_Pattern*>* ptData;
230         m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
231         if (!ptData->m_Obj) {
232             continue;
233         }
234         if (bForceRelease || ptData->m_nCount < 2) {
235             ptData->m_Obj->SetForceClear(bForceRelease);
236             delete ptData->m_Obj;
237             ptData->m_Obj = NULL;
238         }
239     }
240     pos = m_ImageMap.GetStartPosition();
241     while (pos) {
242         FX_DWORD objNum;
243         CPDF_CountedObject<CPDF_Image*>* imageData;
244         m_ImageMap.GetNextAssoc(pos, objNum, imageData);
245         if (!imageData->m_Obj) {
246             continue;
247         }
248         if (bForceRelease || imageData->m_nCount < 2) {
249             delete imageData->m_Obj;
250             imageData->m_Obj = NULL;
251             delete imageData;
252             m_ImageMap.RemoveKey(objNum);
253         }
254     }
255 }
256 CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly)
257 {
258     if (!pFontDict) {
259         return NULL;
260     }
261     if (findOnly) {
262         CPDF_CountedObject<CPDF_Font*>* fontData;
263         if (m_FontMap.Lookup(pFontDict, fontData)) {
264             if (!fontData->m_Obj) {
265                 return NULL;
266             }
267             fontData->m_nCount ++;
268             return fontData->m_Obj;
269         }
270         return NULL;
271     }
272     CPDF_CountedObject<CPDF_Font*>* fontData = NULL;
273     if (m_FontMap.Lookup(pFontDict, fontData)) {
274         if (fontData->m_Obj) {
275             fontData->m_nCount ++;
276             return fontData->m_Obj;
277         }
278     }
279     FX_BOOL bNew = FALSE;
280     if (!fontData) {
281         fontData = FX_NEW CPDF_CountedObject<CPDF_Font*>;
282         bNew = TRUE;
283         if (!fontData) {
284             return NULL;
285         }
286     }
287     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pFontDict);
288     if (!pFont) {
289         if (bNew) {
290             delete fontData;
291         }
292         return NULL;
293     }
294     fontData->m_nCount = 2;
295     fontData->m_Obj = pFont;
296     m_FontMap.SetAt(pFontDict, fontData);
297     return pFont;
298 }
299 CPDF_Font* CPDF_DocPageData::GetStandardFont(FX_BSTR fontName, CPDF_FontEncoding* pEncoding)
300 {
301     if (fontName.IsEmpty()) {
302         return NULL;
303     }
304     FX_POSITION pos = m_FontMap.GetStartPosition();
305     while (pos) {
306         CPDF_Dictionary* fontDict;
307         CPDF_CountedObject<CPDF_Font*>* fontData;
308         m_FontMap.GetNextAssoc(pos, fontDict, fontData);
309         CPDF_Font* pFont = fontData->m_Obj;
310         if (!pFont) {
311             continue;
312         }
313         if (pFont->GetBaseFont() != fontName) {
314             continue;
315         }
316         if (pFont->IsEmbedded()) {
317             continue;
318         }
319         if (pFont->GetFontType() != PDFFONT_TYPE1) {
320             continue;
321         }
322         if (pFont->GetFontDict()->KeyExist(FX_BSTRC("Widths"))) {
323             continue;
324         }
325         CPDF_Type1Font* pT1Font = pFont->GetType1Font();
326         if (pEncoding && !pT1Font->GetEncoding()->IsIdentical(pEncoding)) {
327             continue;
328         }
329         fontData->m_nCount ++;
330         return pFont;
331     }
332     CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;
333     pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Font"));
334     pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Type1"));
335     pDict->SetAtName(FX_BSTRC("BaseFont"), fontName);
336     if (pEncoding) {
337         pDict->SetAt(FX_BSTRC("Encoding"), pEncoding->Realize());
338     }
339     m_pPDFDoc->AddIndirectObject(pDict);
340     CPDF_CountedObject<CPDF_Font*>* fontData = FX_NEW CPDF_CountedObject<CPDF_Font*>;
341     if (!fontData) {
342         return NULL;
343     }
344     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pDict);
345     if (!pFont) {
346         delete fontData;
347         return NULL;
348     }
349     fontData->m_nCount = 2;
350     fontData->m_Obj = pFont;
351     m_FontMap.SetAt(pDict, fontData);
352     return pFont;
353 }
354 void CPDF_DocPageData::ReleaseFont(CPDF_Dictionary* pFontDict)
355 {
356     if (!pFontDict) {
357         return;
358     }
359     CPDF_CountedObject<CPDF_Font*>* fontData;
360     if (!m_FontMap.Lookup(pFontDict, fontData)) {
361         return;
362     }
363     if (fontData->m_Obj && --fontData->m_nCount == 0) {
364         delete fontData->m_Obj;
365         fontData->m_Obj = NULL;
366     }
367 }
368 CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
369 {
370     if (!pCSObj) {
371         return NULL;
372     }
373     if (pCSObj->GetType() == PDFOBJ_NAME) {
374         CFX_ByteString name = pCSObj->GetConstString();
375         CPDF_ColorSpace* pCS = _CSFromName(name);
376         if (!pCS && pResources) {
377             CPDF_Dictionary* pList = pResources->GetDict(FX_BSTRC("ColorSpace"));
378             if (pList) {
379                 pCSObj = pList->GetElementValue(name);
380                 return GetColorSpace(pCSObj, NULL);
381             }
382         }
383         if (pCS == NULL || pResources == NULL) {
384             return pCS;
385         }
386         CPDF_Dictionary* pColorSpaces = pResources->GetDict(FX_BSTRC("ColorSpace"));
387         if (pColorSpaces == NULL) {
388             return pCS;
389         }
390         CPDF_Object* pDefaultCS = NULL;
391         switch (pCS->GetFamily()) {
392             case PDFCS_DEVICERGB:
393                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultRGB"));
394                 break;
395             case PDFCS_DEVICEGRAY:
396                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultGray"));
397                 break;
398             case PDFCS_DEVICECMYK:
399                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultCMYK"));
400                 break;
401         }
402         if (pDefaultCS == NULL) {
403             return pCS;
404         }
405         return GetColorSpace(pDefaultCS, NULL);
406     }
407     if (pCSObj->GetType() != PDFOBJ_ARRAY) {
408         return NULL;
409     }
410     CPDF_Array* pArray = (CPDF_Array*)pCSObj;
411     if (pArray->GetCount() == 0) {
412         return NULL;
413     }
414     if (pArray->GetCount() == 1) {
415         return GetColorSpace(pArray->GetElementValue(0), pResources);
416     }
417     CPDF_CountedObject<CPDF_ColorSpace*>* csData = NULL;
418     if (m_ColorSpaceMap.Lookup(pCSObj, csData)) {
419         if (csData->m_Obj) {
420             csData->m_nCount++;
421             return csData->m_Obj;
422         }
423     }
424     FX_BOOL bNew = FALSE;
425     if (!csData) {
426         csData = FX_NEW CPDF_CountedObject<CPDF_ColorSpace*>;
427         if (!csData) {
428             return NULL;
429         }
430         bNew = TRUE;
431     }
432     CPDF_ColorSpace* pCS = CPDF_ColorSpace::Load(m_pPDFDoc, pArray);
433     if (!pCS) {
434         if (bNew) {
435             delete csData;
436         }
437         return NULL;
438     }
439     csData->m_nCount = 2;
440     csData->m_Obj = pCS;
441     m_ColorSpaceMap.SetAt(pCSObj, csData);
442     return pCS;
443 }
444 CPDF_ColorSpace* CPDF_DocPageData::GetCopiedColorSpace(CPDF_Object* pCSObj)
445 {
446     if (!pCSObj) {
447         return NULL;
448     }
449     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
450     if (!m_ColorSpaceMap.Lookup(pCSObj, csData)) {
451         return NULL;
452     }
453     if (!csData->m_Obj) {
454         return NULL;
455     }
456     csData->m_nCount ++;
457     return csData->m_Obj;
458 }
459 void CPDF_DocPageData::ReleaseColorSpace(CPDF_Object* pColorSpace)
460 {
461     if (!pColorSpace) {
462         return;
463     }
464     CPDF_CountedObject<CPDF_ColorSpace*>* csData;
465     if (!m_ColorSpaceMap.Lookup(pColorSpace, csData)) {
466         return;
467     }
468     if (csData->m_Obj && --csData->m_nCount == 0) {
469         csData->m_Obj->ReleaseCS();
470         csData->m_Obj = NULL;
471     }
472 }
473 CPDF_Pattern* CPDF_DocPageData::GetPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)
474 {
475     if (!pPatternObj) {
476         return NULL;
477     }
478     CPDF_CountedObject<CPDF_Pattern*>* ptData = NULL;
479     if (m_PatternMap.Lookup(pPatternObj, ptData)) {
480         if (ptData->m_Obj) {
481             ptData->m_nCount++;
482             return ptData->m_Obj;
483         }
484     }
485     FX_BOOL bNew = FALSE;
486     if (!ptData) {
487         ptData = FX_NEW CPDF_CountedObject<CPDF_Pattern*>;
488         bNew = TRUE;
489         if (!ptData) {
490             return NULL;
491         }
492     }
493     CPDF_Pattern* pPattern = NULL;
494     if (bShading) {
495         pPattern = FX_NEW CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, bShading, matrix);
496     } else {
497         CPDF_Dictionary* pDict = pPatternObj ? pPatternObj->GetDict() : NULL;
498         if (pDict) {
499             int type = pDict->GetInteger(FX_BSTRC("PatternType"));
500             if (type == 1) {
501                 pPattern = FX_NEW CPDF_TilingPattern(m_pPDFDoc, pPatternObj, matrix);
502             } else if (type == 2) {
503                 pPattern = FX_NEW CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, FALSE, matrix);
504             }
505         }
506     }
507     if (!pPattern) {
508         if (bNew) {
509             delete ptData;
510         }
511         return NULL;
512     }
513     ptData->m_nCount = 2;
514     ptData->m_Obj = pPattern;
515     m_PatternMap.SetAt(pPatternObj, ptData);
516     return pPattern;
517 }
518 void CPDF_DocPageData::ReleasePattern(CPDF_Object* pPatternObj)
519 {
520     if (!pPatternObj) {
521         return;
522     }
523     CPDF_CountedObject<CPDF_Pattern*>* ptData;
524     if (!m_PatternMap.Lookup(pPatternObj, ptData)) {
525         return;
526     }
527     if (ptData->m_Obj && --ptData->m_nCount == 0) {
528         delete ptData->m_Obj;
529         ptData->m_Obj = NULL;
530     }
531 }
532 CPDF_Image* CPDF_DocPageData::GetImage(CPDF_Object* pImageStream)
533 {
534     if (!pImageStream) {
535         return NULL;
536     }
537     FX_DWORD dwImageObjNum = pImageStream->GetObjNum();
538     CPDF_CountedObject<CPDF_Image*>* imageData;
539     if (m_ImageMap.Lookup(dwImageObjNum, imageData)) {
540         imageData->m_nCount ++;
541         return imageData->m_Obj;
542     }
543     imageData = FX_NEW CPDF_CountedObject<CPDF_Image*>;
544     if (!imageData) {
545         return NULL;
546     }
547     CPDF_Image* pImage = FX_NEW CPDF_Image(m_pPDFDoc);
548     if (!pImage) {
549         delete imageData;
550         return NULL;
551     }
552     pImage->LoadImageF((CPDF_Stream*)pImageStream, FALSE);
553     imageData->m_nCount = 2;
554     imageData->m_Obj = pImage;
555     m_ImageMap.SetAt(dwImageObjNum, imageData);
556     return pImage;
557 }
558 void CPDF_DocPageData::ReleaseImage(CPDF_Object* pImageStream)
559 {
560     if (!pImageStream) {
561         return;
562     }
563     PDF_DocPageData_Release<FX_DWORD, CPDF_Image*>(m_ImageMap, pImageStream->GetObjNum(), NULL);
564 }
565 CPDF_IccProfile* CPDF_DocPageData::GetIccProfile(CPDF_Stream* pIccProfileStream)
566 {
567     if (!pIccProfileStream) {
568         return NULL;
569     }
570     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;
571     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData)) {
572         ipData->m_nCount++;
573         return ipData->m_Obj;
574     }
575     CPDF_StreamAcc stream;
576     stream.LoadAllData(pIccProfileStream, FALSE);
577     FX_BYTE digest[20];
578     CPDF_Stream* pCopiedStream = NULL;
579     CRYPT_SHA1Generate(stream.GetData(), stream.GetSize(), digest);
580     if (m_HashProfileMap.Lookup(CFX_ByteStringC(digest, 20), (void*&)pCopiedStream)) {
581         m_IccProfileMap.Lookup(pCopiedStream, ipData);
582         ipData->m_nCount++;
583         return ipData->m_Obj;
584     }
585     CPDF_IccProfile* pProfile = FX_NEW CPDF_IccProfile(stream.GetData(), stream.GetSize());
586     if (!pProfile) {
587         return NULL;
588     }
589     ipData = FX_NEW CPDF_CountedObject<CPDF_IccProfile*>;
590     if (!ipData) {
591         delete pProfile;
592         return NULL;
593     }
594     ipData->m_nCount = 2;
595     ipData->m_Obj = pProfile;
596     m_IccProfileMap.SetAt(pIccProfileStream, ipData);
597     m_HashProfileMap.SetAt(CFX_ByteStringC(digest, 20), pIccProfileStream);
598     return pProfile;
599 }
600 void CPDF_DocPageData::ReleaseIccProfile(CPDF_Stream* pIccProfileStream, CPDF_IccProfile* pIccProfile)
601 {
602     if (!pIccProfileStream && !pIccProfile) {
603         return;
604     }
605     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;
606     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData) && ipData->m_nCount < 2) {
607         FX_POSITION pos = m_HashProfileMap.GetStartPosition();
608         while (pos) {
609             CFX_ByteString key;
610             CPDF_Stream* pFindStream = NULL;
611             m_HashProfileMap.GetNextAssoc(pos, key, (void*&)pFindStream);
612             if (pIccProfileStream == pFindStream) {
613                 m_HashProfileMap.RemoveKey(key);
614                 break;
615             }
616         }
617     }
618     PDF_DocPageData_Release<CPDF_Stream*, CPDF_IccProfile*>(m_IccProfileMap, pIccProfileStream, pIccProfile);
619 }
620 CPDF_StreamAcc* CPDF_DocPageData::GetFontFileStreamAcc(CPDF_Stream* pFontStream)
621 {
622     if (!pFontStream) {
623         return NULL;
624     }
625     CPDF_CountedObject<CPDF_StreamAcc*>* ftData;
626     if (m_FontFileMap.Lookup(pFontStream, ftData)) {
627         ftData->m_nCount ++;
628         return ftData->m_Obj;
629     }
630     ftData = FX_NEW CPDF_CountedObject<CPDF_StreamAcc*>;
631     if (!ftData) {
632         return NULL;
633     }
634     CPDF_StreamAcc* pFontFile = FX_NEW CPDF_StreamAcc;
635     if (!pFontFile) {
636         delete ftData;
637         return NULL;
638     }
639     CPDF_Dictionary* pFontDict = pFontStream->GetDict();
640     FX_INT32 org_size = pFontDict->GetInteger(FX_BSTRC("Length1")) + pFontDict->GetInteger(FX_BSTRC("Length2")) + pFontDict->GetInteger(FX_BSTRC("Length3"));
641     if (org_size < 0) {
642         org_size = 0;
643     }
644     pFontFile->LoadAllData(pFontStream, FALSE, org_size);
645     ftData->m_nCount = 2;
646     ftData->m_Obj = pFontFile;
647     m_FontFileMap.SetAt(pFontStream, ftData);
648     return pFontFile;
649 }
650 void CPDF_DocPageData::ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream, FX_BOOL bForce)
651 {
652     if (!pFontStream) {
653         return;
654     }
655     PDF_DocPageData_Release<CPDF_Stream*, CPDF_StreamAcc*>(m_FontFileMap, pFontStream, NULL, bForce);
656 }