Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / pdfium / 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, 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 }