Convert CPDF_FontMap to std::map.
[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
13 class CPDF_PageModule : public CPDF_PageModuleDef
14 {
15 public:
16     CPDF_PageModule() : m_StockGrayCS(PDFCS_DEVICEGRAY), m_StockRGBCS(PDFCS_DEVICERGB),
17         m_StockCMYKCS(PDFCS_DEVICECMYK) {}
18     virtual ~CPDF_PageModule() {}
19     virtual FX_BOOL             Installed()
20     {
21         return TRUE;
22     }
23     virtual CPDF_DocPageData*   CreateDocData(CPDF_Document* pDoc)
24     {
25         return new CPDF_DocPageData(pDoc);
26     }
27     virtual void                ReleaseDoc(CPDF_Document* pDoc);
28     virtual void                ClearDoc(CPDF_Document* pDoc);
29     virtual CPDF_FontGlobals*   GetFontGlobals()
30     {
31         return &m_FontGlobals;
32     }
33     virtual void                                ClearStockFont(CPDF_Document* pDoc)
34     {
35         m_FontGlobals.Clear(pDoc);
36     }
37     virtual CPDF_ColorSpace*    GetStockCS(int family);
38     virtual void                NotifyCJKAvailable();
39     CPDF_FontGlobals    m_FontGlobals;
40     CPDF_DeviceCS               m_StockGrayCS;
41     CPDF_DeviceCS               m_StockRGBCS;
42     CPDF_DeviceCS               m_StockCMYKCS;
43     CPDF_PatternCS              m_StockPatternCS;
44 };
45 CPDF_ColorSpace* CPDF_PageModule::GetStockCS(int family)
46 {
47     if (family == PDFCS_DEVICEGRAY) {
48         return &m_StockGrayCS;
49     }
50     if (family == PDFCS_DEVICERGB) {
51         return &m_StockRGBCS;
52     }
53     if (family == PDFCS_DEVICECMYK) {
54         return &m_StockCMYKCS;
55     }
56     if (family == PDFCS_PATTERN) {
57         return &m_StockPatternCS;
58     }
59     return NULL;
60 }
61 void CPDF_ModuleMgr::InitPageModule()
62 {
63     delete m_pPageModule;
64     m_pPageModule = new CPDF_PageModule;
65 }
66 void CPDF_PageModule::ReleaseDoc(CPDF_Document* pDoc)
67 {
68     delete pDoc->GetPageData();
69 }
70 void CPDF_PageModule::ClearDoc(CPDF_Document* pDoc)
71 {
72     pDoc->GetPageData()->Clear(FALSE);
73 }
74 void CPDF_PageModule::NotifyCJKAvailable()
75 {
76     m_FontGlobals.m_CMapManager.ReloadAll();
77 }
78 CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict)
79 {
80     if (!pFontDict) {
81         return NULL;
82     }
83     return GetValidatePageData()->GetFont(pFontDict, FALSE);
84 }
85 CPDF_Font* CPDF_Document::FindFont(CPDF_Dictionary* pFontDict)
86 {
87     if (!pFontDict) {
88         return NULL;
89     }
90     return GetValidatePageData()->GetFont(pFontDict, TRUE);
91 }
92 CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream)
93 {
94     if (pStream == NULL) {
95         return NULL;
96     }
97     return GetValidatePageData()->GetFontFileStreamAcc(pStream);
98 }
99 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name);
100 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
101 {
102     return GetValidatePageData()->GetColorSpace(pCSObj, pResources);
103 }
104 CPDF_Pattern* CPDF_Document::LoadPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)
105 {
106     return GetValidatePageData()->GetPattern(pPatternObj, bShading, matrix);
107 }
108 CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream)
109 {
110     return GetValidatePageData()->GetIccProfile(pStream);
111 }
112 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj)
113 {
114     if (!pObj) {
115         return NULL;
116     }
117     FXSYS_assert(pObj->GetObjNum());
118     return GetValidatePageData()->GetImage(pObj);
119 }
120 void CPDF_Document::RemoveColorSpaceFromPageData(CPDF_Object* pCSObj)
121 {
122     if (!pCSObj) {
123         return;
124     }
125     GetPageData()->ReleaseColorSpace(pCSObj);
126 }
127 CPDF_DocPageData::CPDF_DocPageData(CPDF_Document *pPDFDoc)
128     : m_pPDFDoc(pPDFDoc),
129       m_ColorSpaceMap(),
130       m_PatternMap(),
131       m_ImageMap(),
132       m_IccProfileMap(),
133       m_FontFileMap(),
134       m_bForceClear(FALSE)
135 {
136     m_ColorSpaceMap.InitHashTable(32);
137     m_PatternMap.InitHashTable(16);
138     m_ImageMap.InitHashTable(64);
139     m_IccProfileMap.InitHashTable(16);
140     m_FontFileMap.InitHashTable(32);
141 }
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
157     for (auto& it : m_FontMap)
158         delete it.second;
159     m_FontMap.clear();
160
161     pos = m_ColorSpaceMap.GetStartPosition();
162     while (pos)
163     {
164         CPDF_Object* csKey;
165         CPDF_CountedObject<CPDF_ColorSpace*>* csData;
166         m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);
167         delete csData;
168     }
169     m_ColorSpaceMap.RemoveAll();
170 }
171
172 void CPDF_DocPageData::Clear(FX_BOOL bForceRelease)
173 {
174     FX_POSITION pos;
175     m_bForceClear = bForceRelease;
176     pos = m_PatternMap.GetStartPosition();
177     while (pos) {
178         CPDF_Object* ptObj;
179         CPDF_CountedObject<CPDF_Pattern*>* ptData;
180         m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
181         if (!ptData->m_Obj) {
182             continue;
183         }
184         if (bForceRelease || ptData->m_nCount < 2) {
185             ptData->m_Obj->SetForceClear(bForceRelease);
186             delete ptData->m_Obj;
187             ptData->m_Obj = NULL;
188         }
189     }
190
191     for (auto& it : m_FontMap) {
192         CPDF_CountedFont* fontData = it.second;
193         if (!fontData->m_Obj)
194             continue;
195
196         if (bForceRelease || fontData->m_nCount < 2) {
197             delete fontData->m_Obj;
198             fontData->m_Obj = nullptr;
199         }
200     }
201
202     pos = m_ColorSpaceMap.GetStartPosition();
203     while (pos) {
204         CPDF_Object* csKey;
205         CPDF_CountedObject<CPDF_ColorSpace*>* csData;
206         m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);
207         if (!csData->m_Obj) {
208             continue;
209         }
210         if (bForceRelease || csData->m_nCount < 2) {
211             // csData->m_Obj is deleted in the function of ReleaseCS().
212             csData->m_Obj->ReleaseCS();
213             csData->m_Obj = NULL;
214         }
215     }
216     pos = m_IccProfileMap.GetStartPosition();
217     while (pos) {
218         CPDF_Stream* ipKey;
219         CPDF_CountedObject<CPDF_IccProfile*>* ipData;
220         m_IccProfileMap.GetNextAssoc(pos, ipKey, ipData);
221         if (!ipData->m_Obj) {
222             continue;
223         }
224         if (bForceRelease || ipData->m_nCount < 2) {
225             FX_POSITION pos2 = m_HashProfileMap.GetStartPosition();
226             while (pos2) {
227                 CFX_ByteString bsKey;
228                 CPDF_Stream* pFindStream = NULL;
229                 m_HashProfileMap.GetNextAssoc(pos2, bsKey, (void*&)pFindStream);
230                 if (ipKey == pFindStream) {
231                     m_HashProfileMap.RemoveKey(bsKey);
232                     break;
233                 }
234             }
235             delete ipData->m_Obj;
236             delete ipData;
237             m_IccProfileMap.RemoveKey(ipKey);
238         }
239     }
240     pos = m_FontFileMap.GetStartPosition();
241     while (pos) {
242         CPDF_Stream* ftKey;
243         CPDF_CountedObject<CPDF_StreamAcc*>* ftData;
244         m_FontFileMap.GetNextAssoc(pos, ftKey, ftData);
245         if (!ftData->m_Obj) {
246             continue;
247         }
248         if (bForceRelease || ftData->m_nCount < 2) {
249             delete ftData->m_Obj;
250             delete ftData;
251             m_FontFileMap.RemoveKey(ftKey);
252         }
253     }
254     pos = m_ImageMap.GetStartPosition();
255     while (pos) {
256         FX_DWORD objNum;
257         CPDF_CountedObject<CPDF_Image*>* imageData;
258         m_ImageMap.GetNextAssoc(pos, objNum, imageData);
259         if (!imageData->m_Obj) {
260             continue;
261         }
262         if (bForceRelease || imageData->m_nCount < 2) {
263             delete imageData->m_Obj;
264             delete imageData;
265             m_ImageMap.RemoveKey(objNum);
266         }
267     }
268 }
269
270 CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly)
271 {
272     if (!pFontDict) {
273         return NULL;
274     }
275     if (findOnly) {
276         auto it = m_FontMap.find(pFontDict);
277         if (it != m_FontMap.end()) {
278             CPDF_CountedFont* fontData = it->second;
279             if (!fontData->m_Obj)
280                 return nullptr;
281
282             fontData->m_nCount++;
283             return fontData->m_Obj;
284         }
285         return nullptr;
286     }
287
288     CPDF_CountedFont* fontData = nullptr;
289     auto it = m_FontMap.find(pFontDict);
290     if (it != m_FontMap.end()) {
291         fontData = it->second;
292         if (fontData->m_Obj) {
293             fontData->m_nCount++;
294             return fontData->m_Obj;
295         }
296     }
297
298     FX_BOOL bNew = FALSE;
299     if (!fontData) {
300         fontData = new CPDF_CountedFont;
301         bNew = TRUE;
302     }
303     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pFontDict);
304     if (!pFont) {
305         if (bNew)
306             delete fontData;
307         return nullptr;
308     }
309     fontData->m_nCount = 2;
310     fontData->m_Obj = pFont;
311     if (bNew)
312         m_FontMap[pFontDict] = fontData;
313     return pFont;
314 }
315
316 CPDF_Font* CPDF_DocPageData::GetStandardFont(FX_BSTR fontName, CPDF_FontEncoding* pEncoding)
317 {
318     if (fontName.IsEmpty())
319         return nullptr;
320
321     for (auto& it : m_FontMap) {
322         CPDF_CountedFont* fontData = it.second;
323         CPDF_Font* pFont = fontData->m_Obj;
324         if (!pFont)
325             continue;
326         if (pFont->GetBaseFont() != fontName)
327             continue;
328         if (pFont->IsEmbedded())
329             continue;
330         if (pFont->GetFontType() != PDFFONT_TYPE1)
331             continue;
332         if (pFont->GetFontDict()->KeyExist(FX_BSTRC("Widths")))
333             continue;
334
335         CPDF_Type1Font* pT1Font = pFont->GetType1Font();
336         if (pEncoding && !pT1Font->GetEncoding()->IsIdentical(pEncoding))
337             continue;
338
339         fontData->m_nCount++;
340         return pFont;
341     }
342
343     CPDF_Dictionary* pDict = new CPDF_Dictionary;
344     pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Font"));
345     pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Type1"));
346     pDict->SetAtName(FX_BSTRC("BaseFont"), fontName);
347     if (pEncoding) {
348         pDict->SetAt(FX_BSTRC("Encoding"), pEncoding->Realize());
349     }
350     m_pPDFDoc->AddIndirectObject(pDict);
351     CPDF_CountedFont* fontData = new CPDF_CountedFont;
352     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pDict);
353     if (!pFont) {
354         delete fontData;
355         return nullptr;
356     }
357     fontData->m_nCount = 2;
358     fontData->m_Obj = pFont;
359     m_FontMap[pDict] = fontData;
360     return pFont;
361 }
362
363 void CPDF_DocPageData::ReleaseFont(CPDF_Dictionary* pFontDict)
364 {
365     if (!pFontDict)
366         return;
367
368     auto it = m_FontMap.find(pFontDict);
369     if (it == m_FontMap.end())
370         return;
371
372     CPDF_CountedFont* fontData = it->second;
373     if (fontData->m_Obj && --fontData->m_nCount == 0) {
374         delete fontData->m_Obj;
375         fontData->m_Obj = nullptr;
376     }
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     uint8_t 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     int32_t 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 }