Initial commit.
[pdfium.git] / core / src / fpdfapi / fpdf_page / fpdf_page_doc.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../include/fpdfapi/fpdf_page.h"\r
8 #include "../../../include/fpdfapi/fpdf_module.h"\r
9 #include "../../../include/fdrm/fx_crypt.h"\r
10 #include "../fpdf_font/font_int.h"\r
11 #include "pageint.h"\r
12 class CPDF_PageModule : public CPDF_PageModuleDef\r
13 {\r
14 public:\r
15     CPDF_PageModule() : m_StockGrayCS(PDFCS_DEVICEGRAY), m_StockRGBCS(PDFCS_DEVICERGB),\r
16         m_StockCMYKCS(PDFCS_DEVICECMYK) {}\r
17     virtual ~CPDF_PageModule() {}\r
18     virtual FX_BOOL             Installed()\r
19     {\r
20         return TRUE;\r
21     }\r
22     virtual CPDF_DocPageData*   CreateDocData(CPDF_Document* pDoc)\r
23     {\r
24         return FX_NEW CPDF_DocPageData(pDoc);\r
25     }\r
26     virtual void                ReleaseDoc(CPDF_Document* pDoc);\r
27     virtual void                ClearDoc(CPDF_Document* pDoc);\r
28     virtual CPDF_FontGlobals*   GetFontGlobals()\r
29     {\r
30         return &m_FontGlobals;\r
31     }\r
32     virtual void                                ClearStockFont(CPDF_Document* pDoc)\r
33     {\r
34         m_FontGlobals.Clear(pDoc);\r
35     }\r
36     virtual CPDF_ColorSpace*    GetStockCS(int family);\r
37     virtual void                NotifyCJKAvailable();\r
38     CPDF_FontGlobals    m_FontGlobals;\r
39     CPDF_DeviceCS               m_StockGrayCS;\r
40     CPDF_DeviceCS               m_StockRGBCS;\r
41     CPDF_DeviceCS               m_StockCMYKCS;\r
42     CPDF_PatternCS              m_StockPatternCS;\r
43 };\r
44 CPDF_ColorSpace* CPDF_PageModule::GetStockCS(int family)\r
45 {\r
46     if (family == PDFCS_DEVICEGRAY) {\r
47         return &m_StockGrayCS;\r
48     }\r
49     if (family == PDFCS_DEVICERGB) {\r
50         return &m_StockRGBCS;\r
51     }\r
52     if (family == PDFCS_DEVICECMYK) {\r
53         return &m_StockCMYKCS;\r
54     }\r
55     if (family == PDFCS_PATTERN) {\r
56         return &m_StockPatternCS;\r
57     }\r
58     return NULL;\r
59 }\r
60 void CPDF_ModuleMgr::InitPageModule()\r
61 {\r
62     if (m_pPageModule) {\r
63         delete m_pPageModule;\r
64     }\r
65     CPDF_PageModule* pPageModule = FX_NEW CPDF_PageModule;\r
66     m_pPageModule = pPageModule;\r
67 }\r
68 void CPDF_PageModule::ReleaseDoc(CPDF_Document* pDoc)\r
69 {\r
70     delete pDoc->GetPageData();\r
71 }\r
72 void CPDF_PageModule::ClearDoc(CPDF_Document* pDoc)\r
73 {\r
74     pDoc->GetPageData()->Clear(FALSE);\r
75 }\r
76 void CPDF_PageModule::NotifyCJKAvailable()\r
77 {\r
78     m_FontGlobals.m_CMapManager.ReloadAll();\r
79 }\r
80 CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict)\r
81 {\r
82     if (!pFontDict) {\r
83         return NULL;\r
84     }\r
85     return GetValidatePageData()->GetFont(pFontDict, FALSE);\r
86 }\r
87 CPDF_Font* CPDF_Document::FindFont(CPDF_Dictionary* pFontDict)\r
88 {\r
89     if (!pFontDict) {\r
90         return NULL;\r
91     }\r
92     return GetValidatePageData()->GetFont(pFontDict, TRUE);\r
93 }\r
94 CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream)\r
95 {\r
96     if (pStream == NULL) {\r
97         return NULL;\r
98     }\r
99     return GetValidatePageData()->GetFontFileStreamAcc(pStream);\r
100 }\r
101 CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name);\r
102 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)\r
103 {\r
104     return GetValidatePageData()->GetColorSpace(pCSObj, pResources);\r
105 }\r
106 CPDF_Pattern* CPDF_Document::LoadPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)\r
107 {\r
108     return GetValidatePageData()->GetPattern(pPatternObj, bShading, matrix);\r
109 }\r
110 CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream, int nComponents)\r
111 {\r
112     return GetValidatePageData()->GetIccProfile(pStream, nComponents);\r
113 }\r
114 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj)\r
115 {\r
116     if (!pObj) {\r
117         return NULL;\r
118     }\r
119     FXSYS_assert(pObj->GetObjNum());\r
120     return GetValidatePageData()->GetImage(pObj);\r
121 }\r
122 void CPDF_Document::RemoveColorSpaceFromPageData(CPDF_Object* pCSObj)\r
123 {\r
124     if (!pCSObj) {\r
125         return;\r
126     }\r
127     GetPageData()->ReleaseColorSpace(pCSObj);\r
128 }\r
129 CPDF_DocPageData::CPDF_DocPageData(CPDF_Document *pPDFDoc)\r
130     : m_pPDFDoc(pPDFDoc)\r
131     , m_FontMap()\r
132     , m_ColorSpaceMap()\r
133     , m_PatternMap()\r
134     , m_ImageMap()\r
135     , m_IccProfileMap()\r
136     , m_FontFileMap()\r
137 {\r
138     m_FontMap.InitHashTable(64);\r
139     m_ColorSpaceMap.InitHashTable(32);\r
140     m_PatternMap.InitHashTable(16);\r
141     m_ImageMap.InitHashTable(64);\r
142     m_IccProfileMap.InitHashTable(16);\r
143     m_FontFileMap.InitHashTable(32);\r
144 }\r
145 CPDF_DocPageData::~CPDF_DocPageData()\r
146 {\r
147     Clear(FALSE);\r
148     Clear(TRUE);\r
149     FX_POSITION pos = NULL;\r
150 }\r
151 void CPDF_DocPageData::Clear(FX_BOOL bRelease)\r
152 {\r
153     FX_POSITION pos;\r
154     FX_DWORD    nCount;\r
155     {\r
156         pos = m_PatternMap.GetStartPosition();\r
157         while (pos) {\r
158             CPDF_Object* ptObj;\r
159             CPDF_CountedObject<CPDF_Pattern*>* ptData;\r
160             m_PatternMap.GetNextAssoc(pos, ptObj, ptData);\r
161             nCount = ptData->m_nCount;\r
162             if (bRelease || nCount < 2) {\r
163                 delete ptData->m_Obj;\r
164                 ptData->m_Obj = NULL;\r
165             }\r
166         }\r
167     }\r
168     {\r
169         pos = m_FontMap.GetStartPosition();\r
170         while (pos) {\r
171             CPDF_Dictionary* fontDict;\r
172             CPDF_CountedObject<CPDF_Font*>* fontData;\r
173             m_FontMap.GetNextAssoc(pos, fontDict, fontData);\r
174             nCount = fontData->m_nCount;\r
175             if (bRelease || nCount < 2) {\r
176                 delete fontData->m_Obj;\r
177                 fontData->m_Obj = NULL;\r
178             }\r
179         }\r
180     }\r
181     {\r
182         pos = m_ImageMap.GetStartPosition();\r
183         while (pos) {\r
184             FX_DWORD objNum;\r
185             CPDF_CountedObject<CPDF_Image*>* imageData;\r
186             m_ImageMap.GetNextAssoc(pos, objNum, imageData);\r
187             nCount = imageData->m_nCount;\r
188             if (bRelease || nCount < 2) {\r
189                 delete imageData->m_Obj;\r
190                 delete imageData;\r
191                 m_ImageMap.RemoveKey(objNum);\r
192             }\r
193         }\r
194     }\r
195     {\r
196         pos = m_ColorSpaceMap.GetStartPosition();\r
197         while (pos) {\r
198             CPDF_Object* csKey;\r
199             CPDF_CountedObject<CPDF_ColorSpace*>* csData;\r
200             m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);\r
201             nCount = csData->m_nCount;\r
202             if (bRelease || nCount < 2) {\r
203                 csData->m_Obj->ReleaseCS();\r
204                 csData->m_Obj = NULL;\r
205             }\r
206         }\r
207     }\r
208     {\r
209         pos = m_IccProfileMap.GetStartPosition();\r
210         while (pos) {\r
211             CPDF_Stream* ipKey;\r
212             CPDF_CountedObject<CPDF_IccProfile*>* ipData;\r
213             m_IccProfileMap.GetNextAssoc(pos, ipKey, ipData);\r
214             nCount = ipData->m_nCount;\r
215             if (bRelease || nCount < 2) {\r
216                 FX_POSITION pos2 = m_HashProfileMap.GetStartPosition();\r
217                 while (pos2) {\r
218                     CFX_ByteString bsKey;\r
219                     CPDF_Stream* pFindStream = NULL;\r
220                     m_HashProfileMap.GetNextAssoc(pos2, bsKey, (void*&)pFindStream);\r
221                     if (ipKey == pFindStream) {\r
222                         m_HashProfileMap.RemoveKey(bsKey);\r
223                         break;\r
224                     }\r
225                 }\r
226                 delete ipData->m_Obj;\r
227                 delete ipData;\r
228                 m_IccProfileMap.RemoveKey(ipKey);\r
229             }\r
230         }\r
231     }\r
232     {\r
233         pos = m_FontFileMap.GetStartPosition();\r
234         while (pos) {\r
235             CPDF_Stream* ftKey;\r
236             CPDF_CountedObject<CPDF_StreamAcc*>* ftData;\r
237             m_FontFileMap.GetNextAssoc(pos, ftKey, ftData);\r
238             nCount = ftData->m_nCount;\r
239             if (bRelease || nCount < 2) {\r
240                 delete ftData->m_Obj;\r
241                 delete ftData;\r
242                 m_FontFileMap.RemoveKey(ftKey);\r
243             }\r
244         }\r
245     }\r
246 }\r
247 CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly)\r
248 {\r
249     if (!pFontDict) {\r
250         return NULL;\r
251     }\r
252     if (findOnly) {\r
253         CPDF_CountedObject<CPDF_Font*>* fontData;\r
254         if (m_FontMap.Lookup(pFontDict, fontData)) {\r
255             if (!fontData->m_Obj) {\r
256                 return NULL;\r
257             }\r
258             fontData->m_nCount ++;\r
259             return fontData->m_Obj;\r
260         }\r
261         return NULL;\r
262     }\r
263     CPDF_CountedObject<CPDF_Font*>* fontData = NULL;\r
264     if (m_FontMap.Lookup(pFontDict, fontData)) {\r
265         if (fontData->m_Obj) {\r
266             fontData->m_nCount ++;\r
267             return fontData->m_Obj;\r
268         }\r
269     }\r
270     FX_BOOL bNew = FALSE;\r
271     if (!fontData) {\r
272         fontData = FX_NEW CPDF_CountedObject<CPDF_Font*>;\r
273         bNew = TRUE;\r
274         if (!fontData) {\r
275             return NULL;\r
276         }\r
277     }\r
278     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pFontDict);\r
279     if (!pFont) {\r
280         if (bNew) {\r
281             delete fontData;\r
282         }\r
283         return NULL;\r
284     }\r
285     fontData->m_nCount = 2;\r
286     fontData->m_Obj = pFont;\r
287     m_FontMap.SetAt(pFontDict, fontData);\r
288     return pFont;\r
289 }\r
290 CPDF_Font* CPDF_DocPageData::GetStandardFont(FX_BSTR fontName, CPDF_FontEncoding* pEncoding)\r
291 {\r
292     if (fontName.IsEmpty()) {\r
293         return NULL;\r
294     }\r
295     FX_POSITION pos = m_FontMap.GetStartPosition();\r
296     while (pos) {\r
297         CPDF_Dictionary* fontDict;\r
298         CPDF_CountedObject<CPDF_Font*>* fontData;\r
299         m_FontMap.GetNextAssoc(pos, fontDict, fontData);\r
300         CPDF_Font* pFont = fontData->m_Obj;\r
301         if (!pFont) {\r
302             continue;\r
303         }\r
304         if (pFont->GetBaseFont() != fontName) {\r
305             continue;\r
306         }\r
307         if (pFont->IsEmbedded()) {\r
308             continue;\r
309         }\r
310         if (pFont->GetFontType() != PDFFONT_TYPE1) {\r
311             continue;\r
312         }\r
313         if (pFont->GetFontDict()->KeyExist(FX_BSTRC("Widths"))) {\r
314             continue;\r
315         }\r
316         CPDF_Type1Font* pT1Font = pFont->GetType1Font();\r
317         if (pEncoding && !pT1Font->GetEncoding()->IsIdentical(pEncoding)) {\r
318             continue;\r
319         }\r
320         fontData->m_nCount ++;\r
321         return pFont;\r
322     }\r
323     CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;\r
324     pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Font"));\r
325     pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Type1"));\r
326     pDict->SetAtName(FX_BSTRC("BaseFont"), fontName);\r
327     if (pEncoding) {\r
328         pDict->SetAt(FX_BSTRC("Encoding"), pEncoding->Realize());\r
329     }\r
330     m_pPDFDoc->AddIndirectObject(pDict);\r
331     CPDF_CountedObject<CPDF_Font*>* fontData = FX_NEW CPDF_CountedObject<CPDF_Font*>;\r
332     if (!fontData) {\r
333         return NULL;\r
334     }\r
335     CPDF_Font* pFont = CPDF_Font::CreateFontF(m_pPDFDoc, pDict);\r
336     if (!pFont) {\r
337         delete fontData;\r
338         return NULL;\r
339     }\r
340     fontData->m_nCount = 2;\r
341     fontData->m_Obj = pFont;\r
342     m_FontMap.SetAt(pDict, fontData);\r
343     return pFont;\r
344 }\r
345 void CPDF_DocPageData::ReleaseFont(CPDF_Dictionary* pFontDict)\r
346 {\r
347     if (!pFontDict) {\r
348         return;\r
349     }\r
350     CPDF_CountedObject<CPDF_Font*>* fontData;\r
351     if (!m_FontMap.Lookup(pFontDict, fontData)) {\r
352         return;\r
353     }\r
354     if (fontData->m_Obj && --fontData->m_nCount == 0) {\r
355         delete fontData->m_Obj;\r
356         fontData->m_Obj = NULL;\r
357     }\r
358 }\r
359 CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)\r
360 {\r
361     if (!pCSObj) {\r
362         return NULL;\r
363     }\r
364     if (pCSObj->GetType() == PDFOBJ_NAME) {\r
365         CFX_ByteString name = pCSObj->GetConstString();\r
366         CPDF_ColorSpace* pCS = _CSFromName(name);\r
367         if (!pCS && pResources) {\r
368             CPDF_Dictionary* pList = pResources->GetDict(FX_BSTRC("ColorSpace"));\r
369             if (pList) {\r
370                 pCSObj = pList->GetElementValue(name);\r
371                 return GetColorSpace(pCSObj, NULL);\r
372             }\r
373         }\r
374         if (pCS == NULL || pResources == NULL) {\r
375             return pCS;\r
376         }\r
377         CPDF_Dictionary* pColorSpaces = pResources->GetDict(FX_BSTRC("ColorSpace"));\r
378         if (pColorSpaces == NULL) {\r
379             return pCS;\r
380         }\r
381         CPDF_Object* pDefaultCS = NULL;\r
382         switch (pCS->GetFamily()) {\r
383             case PDFCS_DEVICERGB:\r
384                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultRGB"));\r
385                 break;\r
386             case PDFCS_DEVICEGRAY:\r
387                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultGray"));\r
388                 break;\r
389             case PDFCS_DEVICECMYK:\r
390                 pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultCMYK"));\r
391                 break;\r
392         }\r
393         if (pDefaultCS == NULL) {\r
394             return pCS;\r
395         }\r
396         return GetColorSpace(pDefaultCS, NULL);\r
397     }\r
398     if (pCSObj->GetType() != PDFOBJ_ARRAY) {\r
399         return NULL;\r
400     }\r
401     CPDF_Array* pArray = (CPDF_Array*)pCSObj;\r
402     if (pArray->GetCount() == 0) {\r
403         return NULL;\r
404     }\r
405     if (pArray->GetCount() == 1) {\r
406         return GetColorSpace(pArray->GetElementValue(0), pResources);\r
407     }\r
408     CPDF_CountedObject<CPDF_ColorSpace*>* csData = NULL;\r
409     if (m_ColorSpaceMap.Lookup(pCSObj, csData)) {\r
410         if (csData->m_Obj) {\r
411             csData->m_nCount++;\r
412             return csData->m_Obj;\r
413         }\r
414     }\r
415     FX_BOOL bNew = FALSE;\r
416     if (!csData) {\r
417         csData = FX_NEW CPDF_CountedObject<CPDF_ColorSpace*>;\r
418         if (!csData) {\r
419             return NULL;\r
420         }\r
421         bNew = TRUE;\r
422     }\r
423     CPDF_ColorSpace* pCS = CPDF_ColorSpace::Load(m_pPDFDoc, pArray);\r
424     if (!pCS) {\r
425         if (bNew) {\r
426             delete csData;\r
427         }\r
428         return NULL;\r
429     }\r
430     csData->m_nCount = 2;\r
431     csData->m_Obj = pCS;\r
432     m_ColorSpaceMap.SetAt(pCSObj, csData);\r
433     return pCS;\r
434 }\r
435 CPDF_ColorSpace* CPDF_DocPageData::GetCopiedColorSpace(CPDF_Object* pCSObj)\r
436 {\r
437     if (!pCSObj) {\r
438         return NULL;\r
439     }\r
440     CPDF_CountedObject<CPDF_ColorSpace*>* csData;\r
441     if (!m_ColorSpaceMap.Lookup(pCSObj, csData)) {\r
442         return NULL;\r
443     }\r
444     if (!csData->m_Obj) {\r
445         return NULL;\r
446     }\r
447     csData->m_nCount ++;\r
448     return csData->m_Obj;\r
449 }\r
450 void CPDF_DocPageData::ReleaseColorSpace(CPDF_Object* pColorSpace)\r
451 {\r
452     if (!pColorSpace) {\r
453         return;\r
454     }\r
455     CPDF_CountedObject<CPDF_ColorSpace*>* csData;\r
456     if (!m_ColorSpaceMap.Lookup(pColorSpace, csData)) {\r
457         return;\r
458     }\r
459     if (csData->m_Obj && --csData->m_nCount == 0) {\r
460         csData->m_Obj->ReleaseCS();\r
461         csData->m_Obj = NULL;\r
462     }\r
463 }\r
464 CPDF_Pattern* CPDF_DocPageData::GetPattern(CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* matrix)\r
465 {\r
466     if (!pPatternObj) {\r
467         return NULL;\r
468     }\r
469     CPDF_CountedObject<CPDF_Pattern*>* ptData = NULL;\r
470     if (m_PatternMap.Lookup(pPatternObj, ptData)) {\r
471         if (ptData->m_Obj) {\r
472             ptData->m_nCount++;\r
473             return ptData->m_Obj;\r
474         }\r
475     }\r
476     FX_BOOL bNew = FALSE;\r
477     if (!ptData) {\r
478         ptData = FX_NEW CPDF_CountedObject<CPDF_Pattern*>;\r
479         bNew = TRUE;\r
480         if (!ptData) {\r
481             return NULL;\r
482         }\r
483     }\r
484     CPDF_Pattern* pPattern = NULL;\r
485     if (bShading) {\r
486         pPattern = FX_NEW CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, bShading, matrix);\r
487     } else {\r
488         CPDF_Dictionary* pDict = pPatternObj->GetDict();\r
489         if (pDict) {\r
490             int type = pDict->GetInteger(FX_BSTRC("PatternType"));\r
491             if (type == 1) {\r
492                 pPattern = FX_NEW CPDF_TilingPattern(m_pPDFDoc, pPatternObj, matrix);\r
493             } else if (type == 2) {\r
494                 pPattern = FX_NEW CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, FALSE, matrix);\r
495             }\r
496         }\r
497     }\r
498     if (!pPattern) {\r
499         if (bNew) {\r
500             delete ptData;\r
501         }\r
502         return NULL;\r
503     }\r
504     ptData->m_nCount = 2;\r
505     ptData->m_Obj = pPattern;\r
506     m_PatternMap.SetAt(pPatternObj, ptData);\r
507     return pPattern;\r
508 }\r
509 void CPDF_DocPageData::ReleasePattern(CPDF_Object* pPatternObj)\r
510 {\r
511     if (!pPatternObj) {\r
512         return;\r
513     }\r
514     CPDF_CountedObject<CPDF_Pattern*>* ptData;\r
515     if (!m_PatternMap.Lookup(pPatternObj, ptData)) {\r
516         return;\r
517     }\r
518     if (ptData->m_Obj && --ptData->m_nCount == 0) {\r
519         delete ptData->m_Obj;\r
520         ptData->m_Obj = NULL;\r
521     }\r
522 }\r
523 CPDF_Image* CPDF_DocPageData::GetImage(CPDF_Object* pImageStream)\r
524 {\r
525     if (!pImageStream) {\r
526         return NULL;\r
527     }\r
528     FX_DWORD dwImageObjNum = pImageStream->GetObjNum();\r
529     CPDF_CountedObject<CPDF_Image*>* imageData;\r
530     if (m_ImageMap.Lookup(dwImageObjNum, imageData)) {\r
531         imageData->m_nCount ++;\r
532         return imageData->m_Obj;\r
533     }\r
534     imageData = FX_NEW CPDF_CountedObject<CPDF_Image*>;\r
535     if (!imageData) {\r
536         return NULL;\r
537     }\r
538     CPDF_Image* pImage = FX_NEW CPDF_Image(m_pPDFDoc);\r
539     if (!pImage) {\r
540         delete imageData;\r
541         return NULL;\r
542     }\r
543     pImage->LoadImageF((CPDF_Stream*)pImageStream, FALSE);\r
544     imageData->m_nCount = 2;\r
545     imageData->m_Obj = pImage;\r
546     m_ImageMap.SetAt(dwImageObjNum, imageData);\r
547     return pImage;\r
548 }\r
549 void CPDF_DocPageData::ReleaseImage(CPDF_Object* pImageStream)\r
550 {\r
551     if (!pImageStream) {\r
552         return;\r
553     }\r
554     PDF_DocPageData_Release<FX_DWORD, CPDF_Image*>(m_ImageMap, pImageStream->GetObjNum(), NULL);\r
555 }\r
556 CPDF_IccProfile* CPDF_DocPageData::GetIccProfile(CPDF_Stream* pIccProfileStream, FX_INT32 nComponents)\r
557 {\r
558     if (!pIccProfileStream) {\r
559         return NULL;\r
560     }\r
561     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;\r
562     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData)) {\r
563         ipData->m_nCount++;\r
564         return ipData->m_Obj;\r
565     }\r
566     CPDF_StreamAcc stream;\r
567     stream.LoadAllData(pIccProfileStream, FALSE);\r
568     FX_BYTE digest[20];\r
569     CPDF_Stream* pCopiedStream = NULL;\r
570     CRYPT_SHA1Generate(stream.GetData(), stream.GetSize(), digest);\r
571     if (m_HashProfileMap.Lookup(CFX_ByteStringC(digest, 20), (void*&)pCopiedStream)) {\r
572         m_IccProfileMap.Lookup(pCopiedStream, ipData);\r
573         ipData->m_nCount++;\r
574         return ipData->m_Obj;\r
575     }\r
576     CPDF_IccProfile* pProfile = FX_NEW CPDF_IccProfile(stream.GetData(), stream.GetSize(), nComponents);\r
577     if (!pProfile) {\r
578         return NULL;\r
579     }\r
580     ipData = FX_NEW CPDF_CountedObject<CPDF_IccProfile*>;\r
581     if (!ipData) {\r
582         delete pProfile;\r
583         return NULL;\r
584     }\r
585     ipData->m_nCount = 2;\r
586     ipData->m_Obj = pProfile;\r
587     m_IccProfileMap.SetAt(pIccProfileStream, ipData);\r
588     m_HashProfileMap.SetAt(CFX_ByteStringC(digest, 20), pIccProfileStream);\r
589     return pProfile;\r
590 }\r
591 void CPDF_DocPageData::ReleaseIccProfile(CPDF_Stream* pIccProfileStream, CPDF_IccProfile* pIccProfile)\r
592 {\r
593     if (!pIccProfileStream && !pIccProfile) {\r
594         return;\r
595     }\r
596     CPDF_CountedObject<CPDF_IccProfile*>* ipData = NULL;\r
597     if (m_IccProfileMap.Lookup(pIccProfileStream, ipData) && ipData->m_nCount < 2) {\r
598         FX_POSITION pos = m_HashProfileMap.GetStartPosition();\r
599         while (pos) {\r
600             CFX_ByteString key;\r
601             CPDF_Stream* pFindStream = NULL;\r
602             m_HashProfileMap.GetNextAssoc(pos, key, (void*&)pFindStream);\r
603             if (pIccProfileStream == pFindStream) {\r
604                 m_HashProfileMap.RemoveKey(key);\r
605                 break;\r
606             }\r
607         }\r
608     }\r
609     PDF_DocPageData_Release<CPDF_Stream*, CPDF_IccProfile*>(m_IccProfileMap, pIccProfileStream, pIccProfile);\r
610 }\r
611 CPDF_StreamAcc* CPDF_DocPageData::GetFontFileStreamAcc(CPDF_Stream* pFontStream)\r
612 {\r
613     if (!pFontStream) {\r
614         return NULL;\r
615     }\r
616     CPDF_CountedObject<CPDF_StreamAcc*>* ftData;\r
617     if (m_FontFileMap.Lookup(pFontStream, ftData)) {\r
618         ftData->m_nCount ++;\r
619         return ftData->m_Obj;\r
620     }\r
621     ftData = FX_NEW CPDF_CountedObject<CPDF_StreamAcc*>;\r
622     if (!ftData) {\r
623         return NULL;\r
624     }\r
625     CPDF_StreamAcc* pFontFile = FX_NEW CPDF_StreamAcc;\r
626     if (!pFontFile) {\r
627         delete ftData;\r
628         return NULL;\r
629     }\r
630     CPDF_Dictionary* pFontDict = pFontStream->GetDict();\r
631     FX_INT32 org_size = pFontDict->GetInteger(FX_BSTRC("Length1")) + pFontDict->GetInteger(FX_BSTRC("Length2")) + pFontDict->GetInteger(FX_BSTRC("Length3"));\r
632     if (org_size < 0) {\r
633         org_size = 0;\r
634     }\r
635     pFontFile->LoadAllData(pFontStream, FALSE, org_size);\r
636     ftData->m_nCount = 2;\r
637     ftData->m_Obj = pFontFile;\r
638     m_FontFileMap.SetAt(pFontStream, ftData);\r
639     return pFontFile;\r
640 }\r
641 void CPDF_DocPageData::ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream, FX_BOOL bForce)\r
642 {\r
643     if (!pFontStream) {\r
644         return;\r
645     }\r
646     PDF_DocPageData_Release<CPDF_Stream*, CPDF_StreamAcc*>(m_FontFileMap, pFontStream, NULL, bForce);\r
647 }\r