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