Example #1
0
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;
}
Example #2
0
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) );
}
Example #3
0
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;
}
Example #4
0
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 );
	}
}
Example #6
0
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;
    }
}
Example #11
0
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;
    }
}
Example #12
0
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;
        }
    }
}
Example #13
0
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) ) );
}
Example #14
0
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;
}