unsigned int PdfPage::GetPageNumber() const { unsigned int nPageNumber = 0; PdfObject* pParent = m_pObject->GetIndirectKey( "Parent" ); PdfReference ref = m_pObject->Reference(); while( pParent ) { const PdfArray& kids = pParent->GetIndirectKey( "Kids" )->GetArray(); PdfArray::const_iterator it = kids.begin(); while( it != kids.end() && (*it).GetReference() != ref ) { PdfObject* pNode = m_pObject->GetOwner()->GetObject( (*it).GetReference() ); if( pNode->GetDictionary().GetKey( PdfName::KeyType )->GetName() == PdfName( "Pages" ) ) nPageNumber += static_cast<int>(pNode->GetDictionary().GetKey( "Count" )->GetNumber()); else // if we do not have a page tree node, // we most likely have a page object: // so the page count is 1 ++nPageNumber; ++it; } ref = pParent->Reference(); pParent = pParent->GetIndirectKey( "Parent" ); } return ++nPageNumber; }
void PagesTreeTest::CreateTestTreeCustom( PoDoFo::PdfMemDocument & rDoc ) { const int COUNT = PODOFO_TEST_NUM_PAGES / 10; PdfObject* pRoot = rDoc.GetPagesTree()->GetObject(); PdfArray rootKids; for(int z=0; z<COUNT; z++) { PdfObject* pNode = rDoc.GetObjects().CreateObject("Pages"); PdfArray nodeKids; for(int i=0; i<COUNT; i++) { PdfPage* pPage = new PdfPage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ), &(rDoc.GetObjects()) ); pPage->GetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY, static_cast<long long>(z * COUNT + i) ); //printf("Creating page %i z=%i i=%i\n", z * COUNT + i, z, i ); nodeKids.push_back( pPage->GetObject()->Reference() ); } pNode->GetDictionary().AddKey( PdfName("Kids"), nodeKids ); pNode->GetDictionary().AddKey( PdfName("Count"), static_cast<long long>(COUNT) ); rootKids.push_back( pNode->Reference() ); } pRoot->GetDictionary().AddKey( PdfName("Kids"), rootKids ); pRoot->GetDictionary().AddKey( PdfName("Count"), static_cast<long long>(PODOFO_TEST_NUM_PAGES) ); }
PdfObject* PdfPagesTree::GetPageNodeFromArray( int nPageNum, const PdfArray & rKidsArray, PdfObjectList & rLstParents ) { if( static_cast<size_t>(nPageNum) >= rKidsArray.GetSize() ) { PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i from array of size %i\n", nPageNum, rKidsArray.size() ); return NULL; } // TODO: Fill cache immediately with all pages // in this kids array PdfVariant rVar = rKidsArray[nPageNum]; while( true ) { if( rVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays return GetPageNodeFromArray( 0, rVar.GetArray(), rLstParents ); } else if( !rVar.IsReference() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NotImplemented, "Cannot handle inline pages." ); } PdfObject* pgObject = GetRoot()->GetOwner()->GetObject( rVar.GetReference() ); if(pgObject==NULL) { PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "Invalid reference." ); } //printf("Reading %s\n", pgObject->Reference().ToString().c_str()); // make sure the object is a /Page and not a /Pages with a single kid if( this->IsTypePage(pgObject) ) { return pgObject; } // it's a /Pages with a single kid, so dereference and try again... if (this->IsTypePages(pgObject) ) { if( !pgObject->GetDictionary().HasKey( "Kids" ) ) return NULL; rLstParents.push_back( pgObject ); rVar = *(pgObject->GetDictionary().GetKey( "Kids" )); } else { // Reference to unexpected object PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "Reference to unexpected object." ); } } return NULL; }
PdfObject* PdfPage::GetFromResources( const PdfName & rType, const PdfName & rKey ) { if( m_pResources->GetDictionary().HasKey( rType ) ) { PdfObject* pType = m_pResources->GetDictionary().GetKey( rType ); if( pType->IsDictionary() && pType->GetDictionary().HasKey( rKey ) ) { const PdfReference & ref = pType->GetDictionary().GetKey( rKey )->GetReference(); return m_pObject->GetOwner()->GetObject( ref ); } } return NULL; }
void PdfTilingPattern::AddToResources(const PdfName &rIdentifier, const PdfReference &rRef, const PdfName &rName) { PdfObject* pResource = GetObject()->GetDictionary().GetKey( "Resources" ); if( !pResource ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !pResource->GetDictionary().HasKey( rName ) ) { pResource->GetDictionary().AddKey( rName, PdfDictionary() ); } if (ePdfDataType_Reference == pResource->GetDictionary().GetKey( rName )->GetDataType()) { PdfObject *directObject = pResource->GetOwner()->GetObject(pResource->GetDictionary().GetKey( rName )->GetReference()); if (0 == directObject) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } if( !directObject->GetDictionary().HasKey( rIdentifier ) ) directObject->GetDictionary().AddKey( rIdentifier, rRef ); }else { if( !pResource->GetDictionary().GetKey( rName )->GetDictionary().HasKey( rIdentifier ) ) pResource->GetDictionary().GetKey( rName )->GetDictionary().AddKey( rIdentifier, rRef ); } }
void PdfFontSimple::Init( bool bEmbed, const PdfName & rsSubType ) { PdfObject* pWidth; PdfObject* pDescriptor; PdfVariant var; PdfArray array; pWidth = this->GetObject()->GetOwner()->CreateObject(); if( !pWidth ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pMetrics->GetWidthArray( *pWidth, m_pEncoding->GetFirstChar(), m_pEncoding->GetLastChar(), m_pEncoding ); pDescriptor = this->GetObject()->GetOwner()->CreateObject( "FontDescriptor" ); if( !pDescriptor ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } std::string name; if ( m_bIsSubsetting ) name = this->GetObject()->GetOwner()->GetNextSubsetPrefix(); name += this->GetBaseFont().GetName(); this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, rsSubType ); this->GetObject()->GetDictionary().AddKey("BaseFont", PdfName( name ) ); this->GetObject()->GetDictionary().AddKey("FirstChar", PdfVariant( static_cast<pdf_int64>(m_pEncoding->GetFirstChar()) ) ); this->GetObject()->GetDictionary().AddKey("LastChar", PdfVariant( static_cast<pdf_int64>(m_pEncoding->GetLastChar()) ) ); m_pEncoding->AddToDictionary( this->GetObject()->GetDictionary() ); // Add encoding key this->GetObject()->GetDictionary().AddKey("Widths", pWidth->Reference() ); this->GetObject()->GetDictionary().AddKey( "FontDescriptor", pDescriptor->Reference() ); m_pMetrics->GetBoundingBox( array ); pDescriptor->GetDictionary().AddKey( "FontName", PdfName( name ) ); //pDescriptor->GetDictionary().AddKey( "FontWeight", (long)m_pMetrics->Weight() ); pDescriptor->GetDictionary().AddKey( PdfName::KeyFlags, PdfVariant( static_cast<pdf_int64>(PODOFO_LL_LITERAL(32)) ) ); // TODO: 0 ???? pDescriptor->GetDictionary().AddKey( "FontBBox", array ); pDescriptor->GetDictionary().AddKey( "ItalicAngle", PdfVariant( static_cast<pdf_int64>(m_pMetrics->GetItalicAngle()) ) ); pDescriptor->GetDictionary().AddKey( "Ascent", m_pMetrics->GetPdfAscent() ); pDescriptor->GetDictionary().AddKey( "Descent", m_pMetrics->GetPdfDescent() ); pDescriptor->GetDictionary().AddKey( "CapHeight", m_pMetrics->GetPdfAscent() ); // m_pMetrics->CapHeight() ); pDescriptor->GetDictionary().AddKey( "StemV", PdfVariant( static_cast<pdf_int64>(PODOFO_LL_LITERAL(1)) ) ); // m_pMetrics->StemV() ); // Peter Petrov 24 September 2008 m_pDescriptor = pDescriptor; if( bEmbed ) { this->EmbedFontFile( pDescriptor ); m_bWasEmbedded = true; } }
void EncryptTest::testEnableAlgorithms() { int nDefault = PdfEncrypt::GetEnabledEncryptionAlgorithms(); // By default every algorithms should be enabled CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 ) ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 ) ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_AESV2 ) ); CPPUNIT_ASSERT_EQUAL( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 | PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 | PdfEncrypt::ePdfEncryptAlgorithm_AESV2, PdfEncrypt::GetEnabledEncryptionAlgorithms() ); // Disable AES PdfEncrypt::SetEnabledEncryptionAlgorithms( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 | PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 ) ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 ) ); CPPUNIT_ASSERT( !PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_AESV2 ) ); CPPUNIT_ASSERT_EQUAL( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 | PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::GetEnabledEncryptionAlgorithms() ); PdfObject object; object.GetDictionary().AddKey(PdfName("Filter"), PdfName("Standard")); object.GetDictionary().AddKey(PdfName("V"), static_cast<pdf_int64>(4L)); object.GetDictionary().AddKey(PdfName("R"), static_cast<pdf_int64>(4L)); object.GetDictionary().AddKey(PdfName("P"), static_cast<pdf_int64>(1L)); object.GetDictionary().AddKey(PdfName("O"), PdfString("")); object.GetDictionary().AddKey(PdfName("U"), PdfString("")); try { (void)PdfEncrypt::CreatePdfEncrypt( &object ); CPPUNIT_ASSERT( false ); } catch( PdfError & rError ) { CPPUNIT_ASSERT_EQUAL( rError.GetError(), ePdfError_UnsupportedFilter ); } // Restore default PdfEncrypt::SetEnabledEncryptionAlgorithms( nDefault ); }
void PdfFontTrueType::EmbedFontFile( PdfObject* pDescriptor ) { PdfObject* pContents; pdf_long lSize = 0; m_bWasEmbedded = true; pContents = this->GetObject()->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pDescriptor->GetDictionary().AddKey( "FontFile2", pContents->Reference() ); // if the data was loaded from memory - use it from there // otherwise, load from disk if ( m_pMetrics->GetFontDataLen() && m_pMetrics->GetFontData() ) { // FIXME const_cast<char*> is dangerous if string literals may ever be passed char* pBuffer = const_cast<char*>( m_pMetrics->GetFontData() ); lSize = m_pMetrics->GetFontDataLen(); // Set Length1 before creating the stream // as PdfStreamedDocument does not allow // adding keys to an object after a stream was written pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast<pdf_int64>(lSize) ) ); pContents->GetStream()->Set( pBuffer, lSize ); } else { PdfFileInputStream stream( m_pMetrics->GetFilename() ); lSize = stream.GetFileLength(); // Set Length1 before creating the stream // as PdfStreamedDocument does not allow // adding keys to an object after a stream was written pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast<pdf_int64>(lSize) ) ); pContents->GetStream()->Set( &stream ); } }
void PdfAcroForm::Init( EPdfAcroFormDefaulAppearance eDefaultAppearance ) { // Add default appearance: black text, 12pt times // -> only if we do not have a DA key yet // Peter Petrov 27 April 2008 //this->GetObject()->GetDictionary().AddKey( PdfName("NeedAppearances"), PdfVariant(true) ); if( !this->GetObject()->GetDictionary().HasKey("DA") && eDefaultAppearance == ePdfAcroFormDefaultAppearance_BlackText12pt ) { //PdfFont* pFont = pParent->GetDocument()->CreateFont( "Helvetica", false ); // TODO: It is no good idea to always embedd arial // but handling of non embedded helvetica is currently broken PdfFont* pFont = m_pDocument->CreateFont( "Arial" ); // embedd is default true PdfObject* pResource; PdfObject* pFontDict; // Create DR key if( !this->GetObject()->GetDictionary().HasKey( PdfName("DR") ) ) this->GetObject()->GetDictionary().AddKey( PdfName("DR"), PdfDictionary() ); pResource = this->GetObject()->GetDictionary().GetKey( PdfName("DR") ); if( !pResource->GetDictionary().HasKey( PdfName("Font") ) ) pResource->GetDictionary().AddKey( PdfName("Font"), PdfDictionary() ); pFontDict = pResource->GetDictionary().GetKey( PdfName("Font") ); pFontDict->GetDictionary().AddKey( pFont->GetIdentifier(), pFont->GetObject()->Reference() ); // Create DA key std::ostringstream oss; PdfLocaleImbue(oss); oss << "0 0 0 rg /" << pFont->GetIdentifier().GetName() << " 12 Tf"; this->GetObject()->GetDictionary().AddKey( PdfName("DA"), PdfString( oss.str() ) ); } }
void PdfDestination::Init( PdfObject* pObject, PdfDocument* pDocument ) { bool bValueExpected = false; PdfObject* pValue = NULL; if ( pObject->GetDataType() == ePdfDataType_Array ) { m_array = pObject->GetArray(); m_pObject = pObject; } else if( pObject->GetDataType() == ePdfDataType_String ) { PdfNamesTree* pNames = pDocument->GetNamesTree( ePdfDontCreateObject ); if( !pNames ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } pValue = pNames->GetValue( "Dests", pObject->GetString() ); bValueExpected = true; } else if( pObject->GetDataType() == ePdfDataType_Name ) { PdfMemDocument* pMemDoc = dynamic_cast<PdfMemDocument*>(pDocument); if ( !pMemDoc ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "For reading from a document, only use PdfMemDocument." ); } PdfObject* pCatalog = pMemDoc->GetCatalog(); if ( !pCatalog ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } PdfObject* pDests = pCatalog->GetIndirectKey( PdfName( "Dests" ) ); if( !pDests ) { // The error code has been chosen for its distinguishability. PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidKey, "No PDF-1.1-compatible destination dictionary found." ); } pValue = pDests->GetIndirectKey( pObject->GetName() ); bValueExpected = true; } else { PdfError::LogMessage( eLogSeverity_Error, "Unsupported object given to" " PdfDestination::Init of type %s", pObject->GetDataTypeString() ); m_array = PdfArray(); // needed to prevent crash on method calls // needed for GetObject() use w/o checking its return value for NULL m_pObject = pDocument->GetObjects()->CreateObject( m_array ); } if ( bValueExpected ) { if( !pValue ) { PODOFO_RAISE_ERROR( ePdfError_InvalidName ); } if( pValue->IsArray() ) m_array = pValue->GetArray(); else if( pValue->IsDictionary() ) m_array = pValue->GetDictionary().GetKey( "D" )->GetArray(); m_pObject = pValue; } }
void PdfFontCID::Init( bool bEmbed ) { PdfObject* pDescriptor; PdfObject* pDescendantFonts; PdfObject* pCIDSystemInfo; PdfObject* pUnicode; PdfVariant var; PdfArray array; // The descendant font is a CIDFont: pDescendantFonts = this->GetObject()->GetOwner()->CreateObject("Font"); pCIDSystemInfo = this->GetObject()->GetOwner()->CreateObject(); pDescriptor = this->GetObject()->GetOwner()->CreateObject("FontDescriptor"); pUnicode = this->GetObject()->GetOwner()->CreateObject(); // The ToUnicode CMap // Now setting each of the entries of the font this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("Type0") ); this->GetObject()->GetDictionary().AddKey( "BaseFont", this->GetBaseFont() ); this->GetObject()->GetDictionary().AddKey( "ToUnicode", pUnicode->Reference() ); // The encoding is here usually a (Predefined) CMap from PdfIdentityEncoding: m_pEncoding->AddToDictionary( this->GetObject()->GetDictionary() ); // The DecendantFonts, should be an indirect object: array.push_back( pDescendantFonts->Reference() ); this->GetObject()->GetDictionary().AddKey( "DescendantFonts", array ); // Setting the DescendantFonts paras // This is a type2 CIDFont, which is also known as TrueType: pDescendantFonts->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("CIDFontType2") ); // Same base font as the owner font: pDescendantFonts->GetDictionary().AddKey( "BaseFont", this->GetBaseFont() ); // The CIDSystemInfo, should be an indirect object: pDescendantFonts->GetDictionary().AddKey( "CIDSystemInfo", pCIDSystemInfo->Reference() ); // The FontDescriptor, should be an indirect object: pDescendantFonts->GetDictionary().AddKey( "FontDescriptor", pDescriptor->Reference() ); pDescendantFonts->GetDictionary().AddKey( "CIDToGIDMap", PdfName("Identity") ); // Add the width keys this->CreateWidth( pDescendantFonts ); // Create the ToUnicode CMap this->CreateCMap( pUnicode ); // Setting the CIDSystemInfo paras: pCIDSystemInfo->GetDictionary().AddKey( "Registry", PdfString("Adobe") ); pCIDSystemInfo->GetDictionary().AddKey( "Ordering", PdfString("Identity") ); pCIDSystemInfo->GetDictionary().AddKey( "Supplement", PdfVariant(static_cast<pdf_int64>(0LL)) ); // Setting the FontDescriptor paras: array.Clear(); m_pMetrics->GetBoundingBox( array ); pDescriptor->GetDictionary().AddKey( "FontName", this->GetBaseFont() ); pDescriptor->GetDictionary().AddKey( PdfName::KeyFlags, PdfVariant( static_cast<pdf_int64>(32LL) ) ); // TODO: 0 ???? pDescriptor->GetDictionary().AddKey( "FontBBox", array ); pDescriptor->GetDictionary().AddKey( "ItalicAngle", PdfVariant( static_cast<pdf_int64>(m_pMetrics->GetItalicAngle()) ) ); pDescriptor->GetDictionary().AddKey( "Ascent", m_pMetrics->GetPdfAscent() ); pDescriptor->GetDictionary().AddKey( "Descent", m_pMetrics->GetPdfDescent() ); pDescriptor->GetDictionary().AddKey( "CapHeight", m_pMetrics->GetPdfAscent() ); // m_pMetrics->CapHeight() ); pDescriptor->GetDictionary().AddKey( "StemV", PdfVariant( static_cast<pdf_int64>(1LL) ) ); // m_pMetrics->StemV() ); // Peter Petrov 24 September 2008 m_pDescriptor = pDescriptor; if( bEmbed ) { this->EmbedFont( pDescriptor ); m_bWasEmbedded = true; } }
void PdfSigIncWriter::Write( PdfOutputDevice* pDevice, pdf_int64 prevOffset) { //CreateFileIdentifier( m_identifier, m_pTrailer ); if( m_pTrailer->GetDictionary().HasKey( "ID" ) ) { PdfObject *idObj = m_pTrailer->GetDictionary().GetKey("ID"); TCIVariantList it = idObj->GetArray().begin(); while( it != idObj->GetArray().end() ) { if( (*it).GetDataType() == ePdfDataType_HexString ) { PdfVariant var = (*it); m_identifier = var.GetString(); } ++it; } } else { PdfDate date; PdfString dateString; PdfObject* pInfo; PdfOutputDevice length; date.ToString( dateString ); pInfo = new PdfObject(); pInfo->GetDictionary().AddKey( "CreationDate", dateString ); pInfo->GetDictionary().AddKey( "Creator", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Producer", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Location", PdfString("SOMEFILENAME") ); pInfo->WriteObject( &length, ePdfWriteMode_Clean, NULL ); char *pBuffer = static_cast<char*>(podofo_calloc( length.GetLength(), sizeof(char) )); if( !pBuffer ) { delete pInfo; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } PdfOutputDevice device( pBuffer, length.GetLength() ); pInfo->WriteObject( &device, ePdfWriteMode_Clean, NULL ); // calculate the MD5 Sum m_identifier = PdfEncryptMD5Base::GetMD5String( reinterpret_cast<unsigned char*>(pBuffer), static_cast<unsigned int>(length.GetLength()) ); podofo_free( pBuffer ); delete pInfo; } if( !pDevice ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // setup encrypt dictionary if( m_pEncrypt ) { m_pEncrypt->GenerateEncryptionKey( m_identifier ); // Add our own Encryption dictionary m_pEncryptObj = m_vecObjects->CreateObject(); m_pEncrypt->CreateEncryptionDictionary( m_pEncryptObj->GetDictionary() ); } if( GetLinearized() ) { this->WriteLinearized( pDevice ); } else { PdfXRef* pXRef = m_bXRefStream ? new PdfXRefStream( m_vecObjects, this ) : new PdfXRef(); try { // WritePdfHeader ( pDevice ); WritePdfObjects ( pDevice, *m_vecObjects, pXRef ); pXRef->SetFirstEmptyBlock(); pXRef->Write( pDevice ); // XRef streams contain the trailer in the XRef if( !m_bXRefStream ) { PdfObject trailer; // if we have a dummy offset we write also a prev entry to the trailer FillTrailerObject( &trailer, pXRef->GetSize(), false, false ); PdfObject prevOffsetObj(prevOffset); trailer.GetDictionary().AddKey( "Prev", prevOffsetObj); pDevice->Print("trailer\n"); trailer.WriteObject( pDevice, ePdfWriteMode_Clean, NULL ); // Do not encrypt the trailer dicionary!!! } pDevice->Print( "startxref\n%li\n%%%%EOF\n", pXRef->GetOffset()); delete pXRef; } catch( PdfError & e ) { // Make sure pXRef is always deleted delete pXRef; e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } }
void PdfFontType1::EmbedFontFile( PdfObject* pDescriptor ) { pdf_long lSize = 0; pdf_long lLength1 = 0L; pdf_long lLength2 = 0L; pdf_long lLength3 = 0L; PdfObject* pContents; const char* pBuffer; char* pAllocated = NULL; m_bWasEmbedded = true; pContents = m_pObject->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pDescriptor->GetDictionary().AddKey( "FontFile", pContents->Reference() ); // if the data was loaded from memory - use it from there // otherwise, load from disk if ( m_pMetrics->GetFontDataLen() && m_pMetrics->GetFontData() ) { pBuffer = m_pMetrics->GetFontData(); lSize = m_pMetrics->GetFontDataLen(); } else { FILE* hFile = fopen( m_pMetrics->GetFilename(), "rb" ); if( !hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, m_pMetrics->GetFilename() ); } fseek( hFile, 0L, SEEK_END ); lSize = ftell( hFile ); fseek( hFile, 0L, SEEK_SET ); pAllocated = static_cast<char*>(malloc( sizeof(char) * lSize )); if( !pAllocated ) { fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } fread( pAllocated, sizeof(char), lSize, hFile ); fclose( hFile ); pBuffer = pAllocated; } // Remove binary segment headers from pfb unsigned char *pBinary = reinterpret_cast<unsigned char*>(const_cast<char*>(pBuffer)); while( *pBinary == 0x80 ) // binary segment header { const int cHeaderLength = 6; int iSegmentType = pBinary[1]; // binary segment type long lSegmentLength = 0L; long lSegmentDelta = static_cast<long>(&pBuffer[lSize] - reinterpret_cast<const char*>(pBinary) ); switch( iSegmentType ) { case 1: // ASCII text lSegmentLength = pBinary[2] + // little endian pBinary[3] * 256L + pBinary[4] * 65536L + pBinary[5] * 16777216L; if( lLength1 == 0L ) lLength1 = lSegmentLength; else lLength3 = lSegmentLength; lSize -= cHeaderLength; memmove( pBinary, &pBinary[cHeaderLength], lSegmentDelta ); pBinary = &pBinary[lSegmentLength]; break; case 2: // binary data lSegmentLength = pBinary[2] + // little endian pBinary[3] * 256L + pBinary[4] * 65536L + pBinary[5] * 16777216L; lLength2 = lSegmentLength; lSize -= cHeaderLength; memmove( pBinary, &pBinary[cHeaderLength], lSegmentDelta ); pBinary = &pBinary[lSegmentLength]; break; case 3: // end-of-file pContents->GetStream()->Set( pBuffer, lSize - 2L ); if( pAllocated ) free( pAllocated ); pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast<long long>(lLength1) ) ); pContents->GetDictionary().AddKey( "Length2", PdfVariant( static_cast<long long>(lLength2) ) ); pContents->GetDictionary().AddKey( "Length3", PdfVariant( static_cast<long long>(lLength3) ) ); return; default: break; } } // Parse the font data buffer to get the values for length1, length2 and length3 lLength1 = FindInBuffer( "eexec", pBuffer, lSize ); if( lLength1 > 0 ) lLength1 += 6; // 6 == eexec + lf else lLength1 = 0; if( lLength1 ) { lLength2 = FindInBuffer( "cleartomark", pBuffer, lSize ); if( lLength2 > 0 ) lLength2 = lSize - lLength1 - 520; // 520 == 512 + strlen(cleartomark) else lLength1 = 0; } lLength3 = lSize - lLength2 - lLength1; // TODO: Pdf Supports only Type1 fonts with binary encrypted sections and not the hex format pContents->GetStream()->Set( pBuffer, lSize ); if( pAllocated ) free( pAllocated ); pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast<long long>(lLength1) ) ); pContents->GetDictionary().AddKey( "Length2", PdfVariant( static_cast<long long>(lLength2) ) ); pContents->GetDictionary().AddKey( "Length3", PdfVariant( static_cast<long long>(lLength3) ) ); }
PdfFont* PdfFontFactory::CreateFont( FT_Library*, PdfObject* pObject ) { PdfFontMetrics* pMetrics = NULL; PdfFont* pFont = NULL; PdfObject* pDescriptor = NULL; PdfObject* pEncoding = NULL; if( pObject->GetDictionary().GetKey( PdfName::KeyType )->GetName() != PdfName("Font") ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } const PdfName & rSubType = pObject->GetDictionary().GetKey( PdfName::KeySubtype )->GetName(); if( rSubType == PdfName("Type0") ) { // The PDF reference states that DescendantFonts must be an array, // some applications (e.g. MS Word) put the array into an indirect object though. const PdfArray & descendant = pObject->GetIndirectKey( "DescendantFonts" )->GetArray(); PdfObject* pFontObject = pObject->GetOwner()->GetObject( descendant[0].GetReference() ); pDescriptor = pFontObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); // OC 15.08.2010 BugFix: Parameter pFontObject added: TODO: untested pMetrics = new PdfFontMetricsObject( pFontObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontCID( pMetrics, pPdfEncoding, pObject, false ); } } else if( rSubType == PdfName("Type1") ) { // TODO: Old documents do not have a FontDescriptor for // the 14 standard fonts. This suggestions is // deprecated now, but give us problems with old documents. pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); // OC 13.08.2010: Handle missing FontDescriptor for the 14 standard fonts: if( !pDescriptor ) { // Check if its a PdfFontType1Base14 PdfObject* pBaseFont = NULL; pBaseFont = pObject->GetIndirectKey( "BaseFont" ); const char* pszBaseFontName = pBaseFont->GetName().GetName().c_str(); PdfFontMetricsBase14* pMetrics = PODOFO_Base14FontDef_FindBuiltinData(pszBaseFontName); if ( pMetrics != NULL ) { // pEncoding may be undefined, found a valid pdf with // 20 0 obj // << // /Type /Font // /BaseFont /ZapfDingbats // /Subtype /Type1 // >> // endobj // If pEncoding is null then // use StandardEncoding for Courier, Times, Helvetica font families // and special encodings for Symbol and ZapfDingbats const PdfEncoding* pPdfEncoding = NULL; if ( pEncoding!= NULL ) pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); else if ( !pMetrics->IsSymbol() ) pPdfEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); else if ( strcmp(pszBaseFontName, "Symbol") == 0 ) pPdfEncoding = PdfEncodingFactory::GlobalSymbolEncodingInstance(); else if ( strcmp(pszBaseFontName, "ZapfDingbats") == 0 ) pPdfEncoding = PdfEncodingFactory::GlobalZapfDingbatsEncodingInstance(); return new PdfFontType1Base14(pMetrics, pPdfEncoding, pObject); } } const PdfEncoding* pPdfEncoding = NULL; if ( pEncoding != NULL ) pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); else if ( pDescriptor ) { // OC 18.08.2010 TODO: Encoding has to be taken from the font's built-in encoding // Its extremely complicated to interpret the type1 font programs // so i try to determine if its a symbolic font by reading the FontDescriptor Flags // Flags & 4 --> Symbolic, Flags & 32 --> Nonsymbolic pdf_int32 lFlags = static_cast<pdf_int32>(pDescriptor->GetDictionary().GetKeyAsLong( "Flags", 0L )); if ( lFlags & 32 ) // Nonsymbolic, otherwise pEncoding remains NULL pPdfEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); } if ( pPdfEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { // OC 15.08.2010 BugFix: Parameter pObject added: pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontType1( pMetrics, pPdfEncoding, pObject ); } } else if( rSubType == PdfName("TrueType") ) { pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); // OC 15.08.2010 BugFix: Parameter pObject added: pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontTrueType( pMetrics, pPdfEncoding, pObject ); } } return pFont; }