Example #1
0
bool PdfDictionary::operator==( const PdfDictionary& rhs ) const
{
    if (this == &rhs)
        return true;

    if ( m_mapKeys.size() != rhs.m_mapKeys.size() )
        return false;

    // It's not enough to test that our internal maps are equal, because
    // we store variants by pointer not value. However, since a dictionary's
    // keys are stored in a SORTED map, and there may be only one instance of
    // every key, we can do lockstep iteration and compare that way.

    const TCIKeyMap thisIt = m_mapKeys.begin();
    const TCIKeyMap thisEnd = m_mapKeys.end();
    const TCIKeyMap rhsIt = rhs.m_mapKeys.begin();
    const TCIKeyMap rhsEnd = rhs.m_mapKeys.end();
    while ( thisIt != thisEnd && rhsIt != rhsEnd )
    {
        if ( (*thisIt).first != (*rhsIt).first )
            // Name mismatch. Since the keys are sorted that means that there's a key present
            // in one dictionary but not the other.
            return false;
        if ( *(*thisIt).second != *(*rhsIt).second )
            // Value mismatch on same-named keys.
            return false;
    }
    // BOTH dictionaries must now be on their end iterators - since we checked that they were
    // the same size initially, we know they should run out of keys at the same time.
    PODOFO_RAISE_LOGIC_IF( thisIt != thisEnd || rhsIt != rhsEnd, "Dictionary compare error" );
    // We didn't find any mismatches
    return true;
}
void PdfContentsTokenizer::SetCurrentContentsStream( PdfObject* pObject )
{
    PODOFO_RAISE_LOGIC_IF( pObject == NULL, "Content stream object == NULL!" );

    PdfStream* pStream = pObject->GetStream();

    PdfBufferOutputStream stream( &m_curBuffer );
    pStream->GetFilteredCopy( &stream );

    m_device = PdfRefCountedInputDevice( m_curBuffer.GetBuffer(), m_curBuffer.GetSize() );
}
Example #3
0
PdfOutputStream* PdfFilterFactory::CreateEncodeStream( const TVecFilters & filters, PdfOutputStream* pStream ) 
{
    TVecFilters::const_iterator it = filters.begin();

    PODOFO_RAISE_LOGIC_IF( !filters.size(), "Cannot create an EncodeStream from an empty list of filters" );

    PdfFilteredEncodeStream* pFilter = new PdfFilteredEncodeStream( pStream, *it, false );
    ++it;

    while( it != filters.end() ) 
    {
        pFilter = new PdfFilteredEncodeStream( pFilter, *it, true );
        ++it;
    }

    return pFilter;
}
void PdfVecObjects::InsertOneReferenceIntoVector( const PdfObject* pObj, TVecReferencePointerList* pList )  
{
    size_t                        index;

    PODOFO_RAISE_LOGIC_IF( !m_bSorted, 
                           "PdfVecObjects must be sorted before calling PdfVecObjects::InsertOneReferenceIntoVector!" );
    
    // we asume that pObj is a reference - no checking here because of speed
    std::pair<TCIVecObjects,TCIVecObjects> it = 
        std::equal_range( m_vector.begin(), m_vector.end(), pObj, ObjectComparatorPredicate() );

    if( it.first != it.second )
    {
        // ignore this reference
        return;
        //PODOFO_RAISE_ERROR( ePdfError_NoObject );
    }
    
    index = (it.first - this->begin());
    (*pList)[index].push_back( const_cast<PdfReference*>(&(pObj->GetReference() )) );
}
Example #5
0
PdfOutputStream* PdfFilterFactory::CreateDecodeStream( const TVecFilters & filters, PdfOutputStream* pStream,
                                                       const PdfDictionary* pDictionary ) 
{
    TVecFilters::const_reverse_iterator it = filters.rbegin();

    PODOFO_RAISE_LOGIC_IF( !filters.size(), "Cannot create an DecodeStream from an empty list of filters" );

    // TODO: support arrays and indirect objects here and the short name /DP
    if( pDictionary && pDictionary->HasKey( "DecodeParms" ) && pDictionary->GetKey( "DecodeParms" )->IsDictionary() )
        pDictionary = &(pDictionary->GetKey( "DecodeParms" )->GetDictionary());

    PdfFilteredDecodeStream* pFilter = new PdfFilteredDecodeStream( pStream, *it, false, pDictionary );
    ++it;

    while( it != filters.rend() ) 
    {
        pFilter = new PdfFilteredDecodeStream( pFilter, *it, true, pDictionary );
        ++it;
    }

    return pFilter;
}
Example #6
0
PdfContentsGraph::PdfContentsGraph( PdfContentsTokenizer & contentsTokenizer )
    : m_graph()
{
    EPdfContentsType t;
    const char * kwText;
    PdfVariant var;
    bool readToken;

    // Keep a count of the number of tokens read so we can report errors
    // more usefully.
    int tokenNumber = 0;

    // Set up the node stack and initialize the root node
    stack<Vertex> parentage;
    parentage.push( add_vertex(m_graph) );
    m_graph[parentage.top()] = MakeNode(KW_RootNode,KW_RootNode);

    // Arguments to be associated with the next keyword found
    vector<PdfVariant> args;

    while ( ( readToken = contentsTokenizer.ReadNext(t, kwText, var) ) )
    {
        ++tokenNumber;
        if (t == ePdfContentsType_Variant)
        {
            // arguments come before operators, but we want to group them up before
            // their operator.
            args.push_back(var);
        }
        else if (t == ePdfContentsType_Keyword)
        {
            const KWInfo & ki ( findKwByName(kwText) );
            if (ki.kt != KT_Closing)
            {
                // We're going to need a new vertex, so make sure we have one ready.
                Vertex v = add_vertex( m_graph );
                // Switch any waiting arguments into the new node's data.
                m_graph[v].first.GetArgs().swap( args );
                assert(!args.size());

                if (ki.kw == KW_Unknown)
                {
                    // No idea what this keyword is. We have to assume it's an ordinary
                    // one, possibly with arguments, and just push it in as a node at the
                    // current level.
                    assert(!m_graph[v].first.IsDefined());
                    m_graph[v].first.SetKw( string(kwText) );
                    add_edge( parentage.top(), v, m_graph );
                    assert( m_graph[v].first.GetKwId() == ki.kw );
                    assert( m_graph[v].first.GetKwString() == kwText );
                }
                else if (ki.kt == KT_Standalone)
                {
                    // Plain operator, shove it in the newly reserved vertex (which might already contain
                    // arguments) and add an edge from the top to it.
                    assert(ki.kw != KW_Undefined && ki.kw != KW_Unknown && ki.kw != KW_RootNode );
                    assert(!m_graph[v].first.IsDefined());
                    m_graph[v].first.SetKw( ki.kw );
                    add_edge( parentage.top(), v, m_graph );
                    assert( m_graph[v].first.GetKwId() == ki.kw );
                    assert( m_graph[v].first.GetKwString() == kwText );
                }
                else if (ki.kt == KT_Opening)
                {
                    PrintStack(m_graph, parentage, "OS: ");
                    assert(ki.kw != KW_Undefined && ki.kw != KW_Unknown && ki.kw != KW_RootNode );
                    assert(!m_graph[v].first.IsDefined());
                    m_graph[v].first.SetKw( ki.kw );
                    // add an edge from the current top to it
                    add_edge( parentage.top(), v, m_graph );
                    // and push it to the top of the parentage stack
                    parentage.push( v );
                    assert( m_graph[v].first.GetKwId() == ki.kw );
                    assert( m_graph[v].first.GetKwString() == kwText );
                    PrintStack(m_graph, parentage, "OF: ");
                }
                else
                {
                    assert(false);
                }
            }
            else if (ki.kt == KT_Closing)
            {
                // This keyword closes a context. The top of the parentage tree should
                // be a node whose KWInstance is the matching opening keyword. We'll check
                // that, then set the second KWInstance appropriately.
                PrintStack(m_graph, parentage, "CS: ");
                assert(ki.kw != KW_Undefined && ki.kw != KW_Unknown && ki.kw != KW_RootNode );
                // Get a reference to the node data for the current parent
                NodeData & n ( m_graph[parentage.top()] );
                PODOFO_RAISE_LOGIC_IF( n.second.IsDefined(), "Closing already closed group" );
                // Ensure that the opening keyword therein is one that this closing keyword is
                // a valid match for
                PdfContentStreamKeyword expectedCloseKw = n.first.GetKwInfo().kwClose;
                // Ensure there aren't any args to the close kw
                assert(!args.size());
                // and handle the close matching
                if ( ki.kw != expectedCloseKw )
                {
                    // Some PDFs, even Adobe ones, place close operators
                    // in the wrong order. We'll do some lookahead to see
                    // if we can fix things up before we hit a non-close
                    // operator.
                    if ( !closeFixup( m_graph, parentage, contentsTokenizer, ki  ) )
                    {
                        string err = formatMismatchError(m_graph, parentage, tokenNumber, ki.kw, expectedCloseKw);
                        PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidContentStream, err.c_str() );
                    }
                }
                else
                {
                    n.second.SetKw( ki.kw );
                    // Our associated operator is now on the top of the
                    // parentage stack. Since its scope has ended, it should
                    // also be popped.
                    parentage.pop();
                }
                PrintStack(m_graph, parentage, "CF: ");
            }
            else
            {
                assert(false);
            }
        }
        else
        {
            assert(false);
        }
    }

    PODOFO_RAISE_LOGIC_IF( args.size(), "Stream ended with unconsumed arguments!" );

    PODOFO_RAISE_LOGIC_IF( parentage.size() != 1, "Stream failed to close all levels" );

}