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