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