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