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