From: Francesco Pretto <cez...@gmail.com>

Added mechanism to automatic set PdfObject ownership, removing public
access to manual setting. To perform this a PdfOwnedDataType is added
and PdfArray, PdfDictionary now inherits this class, propagating ownership
when objects are added to these collections:

Also added methods:
     PdfArray::FindAt(idx)
     PdfDictionary::FindKey(key)
     PdfDictionary::FindKeyParent(key)

Also in PdfObject commented out the attempt to copy the stream from objects
in copy constructor and assignment operator since:
1) As of r1957 it's already broken since PdfVecObjects::CreateStream( const 
PdfStream & )
     just returns NULL
2) Stream should be copyable also when m_pOwner is NULL
---
  CMakeLists.txt                 |   2 +-
  podofo/base/PdfOwnedDataType.h |  12 ++++
  src/CMakeLists.txt             |   2 +
  src/base/PdfArray.cpp          |  94 ++++++++++++++++++++++++---
  src/base/PdfArray.h            | 114 +++++++++++++++------------------
  src/base/PdfDictionary.cpp     |  75 +++++++++++++++++-----
  src/base/PdfDictionary.h       |  92 ++++++++++++++++++++++++--
  src/base/PdfObject.cpp         |  84 ++++++++++++++++--------
  src/base/PdfObject.h           |  35 +++++-----
  src/base/PdfOwnedDataType.cpp  |  78 ++++++++++++++++++++++
  src/base/PdfOwnedDataType.h    |  84 ++++++++++++++++++++++++
  src/base/PdfVariant.h          |  15 +++++
  src/doc/PdfPage.cpp            |   6 +-
  src/doc/PdfShadingPattern.cpp  |   1 -
  14 files changed, 552 insertions(+), 142 deletions(-)
  create mode 100644 podofo/base/PdfOwnedDataType.h
  create mode 100644 src/base/PdfOwnedDataType.cpp
  create mode 100644 src/base/PdfOwnedDataType.h



diff --git a/CMakeLists.txt b/CMakeLists.txt
index f23dd5a..7b88aa6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -290,7 +290,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
 
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Woverloaded-virtual -Wswitch-enum -Wcast-qual -Wwrite-strings -Wredundant-decls -Wreorder -Wno-deprecated-declarations")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Woverloaded-virtual -Wswitch -Wcast-qual -Wwrite-strings -Wredundant-decls -Wreorder -Wno-deprecated-declarations")
 
     #
     # Note that we do not need debug definitions here. Set
diff --git a/podofo/base/PdfOwnedDataType.h b/podofo/base/PdfOwnedDataType.h
new file mode 100644
index 0000000..dd35fa0
--- /dev/null
+++ b/podofo/base/PdfOwnedDataType.h
@@ -0,0 +1,12 @@
+
+#ifndef PODOFO_WRAPPER_PDFOWNEDDATATYPEH
+#define PODOFO_WRAPPER_PDFOWNEDDATATYPEH
+/*
+ * This is a simple wrapper include file that lets you include
+ * <podofo/base/PdfOwnedDataType.h> when building against a podofo build directory
+ * rather than an installed copy of podofo. You'll probably need
+ * this if you're including your own (probably static) copy of podofo
+ * using a mechanism like svn:externals .
+ */
+#include "../../src/base/PdfOwnedDataType.h"
+#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 72bbd97..bba6b5f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -16,6 +16,7 @@ SET(PODOFO_BASE_SOURCES
   base/PdfContentsTokenizer.cpp
   base/PdfData.cpp
   base/PdfDataType.cpp
+  base/PdfOwnedDataType.cpp
   base/PdfDate.cpp
   base/PdfDictionary.cpp
   base/PdfEncoding.cpp
@@ -124,6 +125,7 @@ SET(PODOFO_BASE_HEADERS
    base/PdfContentsTokenizer.h
    base/PdfData.h
    base/PdfDataType.h
+   base/PdfOwnedDataType.h
    base/PdfDate.h
    base/PdfDefines.h
    base/PdfDefinesPrivate.h
diff --git a/src/base/PdfArray.cpp b/src/base/PdfArray.cpp
index f44b64b..508daf9 100644
--- a/src/base/PdfArray.cpp
+++ b/src/base/PdfArray.cpp
@@ -41,7 +41,18 @@
 namespace PoDoFo {
 
 PdfArray::PdfArray()
-    : PdfDataType(), m_bDirty( false )
+    : m_bDirty( false )
+{
+}
+
+PdfArray::PdfArray( const PdfObject &var )
+    : m_bDirty( false )
+{
+    this->push_back( var );
+}
+
+PdfArray::PdfArray(const PdfArray & rhs)
+    : PdfOwnedDataType( rhs ), m_bDirty( rhs.m_bDirty ), m_objects( rhs.m_objects )
 {
 }
 
@@ -49,25 +60,60 @@ PdfArray::~PdfArray()
 {
 }
 
-PdfArray::PdfArray( const PdfObject & var )
-    : PdfDataType(), m_bDirty( false )
+PdfObject * PdfArray::findAt( size_type idx ) const
+{
+    PdfObject *obj = &const_cast<PdfArray *>( this )->m_objects[idx];
+    if ( obj->IsReference() )
+        return GetIndirectObject( obj->GetReference() );
+    else
+        return obj;
+}
+
+void PdfArray::clear()
 {
-    this->push_back( var );
+    AssertMutable();
+    if ( m_objects.size() == 0 )
+        return;
+
+    m_objects.clear();
+    m_bDirty = true;
+}
+
+PdfArray::iterator PdfArray::insert( const iterator &pos, const PdfObject &val )
+{
+    AssertMutable();
+
+    m_bDirty = true;
+    iterator ret = m_objects.insert( pos, val );
+    PdfVecObjects *pOwner = GetObjectOwner();
+    if ( pOwner != NULL )
+        ret->SetOwner( pOwner );
+    return ret;
 }
 
-PdfArray::PdfArray( const PdfArray & rhs )
-    : PdfDataType( rhs ), m_bDirty( rhs.m_bDirty ), m_objects( rhs.m_objects )
+void PdfArray::erase( const iterator &pos )
 {
-    this->operator=( rhs );
+    AssertMutable();
+
+    m_objects.erase( pos );
+    m_bDirty = true;
 }
 
+void PdfArray::erase( const iterator &first, const iterator &last )
+{
+    AssertMutable();
+
+    m_objects.erase( first, last );
+    m_bDirty = true;
+}
  
-PdfArray& PdfArray::operator=(const PdfArray& rhs)
+PdfArray& PdfArray::operator=( const PdfArray &rhs )
 {
     if (this != &rhs)
     {
         m_bDirty = rhs.m_bDirty;
         m_objects = rhs.m_objects;
+        this->PdfOwnedDataType::operator=( rhs );
     }
     else
     {
@@ -77,6 +123,22 @@ PdfArray& PdfArray::operator=(const PdfArray& rhs)
     return *this;
 }
 
+void PdfArray::resize( size_t count, value_type val )
+{
+    AssertMutable();
+
+    size_t currentSize = size();
+    m_objects.resize( count, val );
+    PdfVecObjects *pOwner = GetObjectOwner();
+    if ( pOwner != NULL )
+    {
+        for ( size_t i = currentSize; i < count; i++ )
+            m_objects[i].SetOwner( pOwner );
+    }
+
+    m_bDirty = currentSize != count;
+}
+
 void PdfArray::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, 
                       const PdfEncrypt* pEncrypt ) const
 {
@@ -181,6 +243,20 @@ void PdfArray::SetDirty( bool bDirty )
             ++it;
         }
     }
+}
+
+void PdfArray::SetOwner( PdfObject *pOwner )
+{
+    PdfOwnedDataType::SetOwner( pOwner );
+    PdfVecObjects *pVecOwner = pOwner->GetOwner();
+    if ( pVecOwner != NULL )
+    {
+        // Set owmership for all children
+        PdfArray::iterator it = this->begin();
+        PdfArray::iterator end = this->end();
+        for ( ; it != end; it++ )
+            it->SetOwner( pVecOwner );
+    }
 }
-
+
 };
diff --git a/src/base/PdfArray.h b/src/base/PdfArray.h
index ce4d177..d791c3a 100644
--- a/src/base/PdfArray.h
+++ b/src/base/PdfArray.h
@@ -42,7 +42,7 @@
 #endif // _WIN32
 
 #include "PdfDefines.h"
-#include "PdfDataType.h"
+#include "PdfOwnedDataType.h"
 #include "PdfObject.h"
 
 namespace PoDoFo {
@@ -54,7 +54,7 @@ namespace PoDoFo {
  *
  *  \see PdfVariant
  */
-class PODOFO_API PdfArray : public PdfDataType {
+class PODOFO_API PdfArray : public PdfOwnedDataType {
  public:
     typedef size_t                                          size_type;
     typedef PdfObject                                       value_type;
@@ -126,6 +126,18 @@ class PODOFO_API PdfArray : public PdfDataType {
      */
     size_t GetStringIndex( const std::string& cmpString ) const;
 
+    /** Get the object at the given index out of the array.
+     *
+     * Lookup in the indirect objects as well, if the shallow object was a reference.
+     * The returned value is a pointer to the internal object in the dictionary
+     * so it MUST not be deleted.
+     *
+     *  \param idx
+     *  \returns pointer to the found value. NULL if the index was out of the boundaries
+     */
+    inline const PdfObject * FindAt( size_type idx ) const;
+    inline PdfObject * FindAt( size_type idx );
+
     /** Adds a PdfObject to the array
      *
      *  \param var add a PdfObject to the array
@@ -137,7 +149,7 @@ class PODOFO_API PdfArray : public PdfDataType {
 
     /** Remove all elements from the array
      */
-    inline void clear();
+    void clear();
 
     /** 
      *  \returns the size of the array
@@ -154,9 +166,10 @@ class PODOFO_API PdfArray : public PdfDataType {
 
     /**
      * Resize the internal vector.
-     * \param __n new size
+     * \param count new size
+     * \param value refernce value
      */
-    inline void resize(size_t __n, value_type __x = value_type());
+    void resize( size_t count, value_type val = value_type() );
     
     /**
      *  Returns a read/write iterator that points to the first
@@ -225,10 +238,10 @@ class PODOFO_API PdfArray : public PdfDataType {
                     const _InputIterator& __last);
 #endif
 
-    inline PdfArray::iterator insert(const iterator& __position, const PdfObject & val );
+    iterator insert( const iterator &pos, const PdfObject &val );
 
-    inline void erase( const iterator& pos );
-    inline void erase( const iterator& first, const iterator& last );
+    void erase( const iterator& pos );
+    void erase( const iterator& first, const iterator& last );
 
     inline void reserve(size_type __n);
 
@@ -281,19 +294,31 @@ class PODOFO_API PdfArray : public PdfDataType {
      */
     virtual void SetDirty( bool bDirty );
 
+ protected:
+     void SetOwner( PdfObject* pOwner );
+
+ private:
+    PdfObject * findAt(size_type idx) const;
+
  private:
     bool         m_bDirty; ///< Indicates if this object was modified after construction
     std::vector<PdfObject> m_objects;
 };
 
 // -----------------------------------------------------
-// 
+//
 // -----------------------------------------------------
-void PdfArray::Clear() 
-{
-    AssertMutable();
+inline const PdfObject * PdfArray::FindAt( size_type idx ) const
+{
+    return const_cast<PdfArray &>( *this ).FindAt( idx );
+}
 
-    m_objects.clear();
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline PdfObject * PdfArray::FindAt( size_type idx )
+{
+    return const_cast<PdfArray &>( *this ).FindAt( idx );
 }
 
 // -----------------------------------------------------
@@ -301,7 +326,7 @@ void PdfArray::Clear()
 // -----------------------------------------------------
 size_t PdfArray::GetSize() const
 {
-    return this->size();
+    return m_objects.size();
 }
 
 // -----------------------------------------------------
@@ -309,20 +334,15 @@ size_t PdfArray::GetSize() const
 // -----------------------------------------------------
 void PdfArray::push_back( const PdfObject & var )
 {
-    AssertMutable();
-
-    m_objects.push_back( var );
-    m_bDirty = true;
+    insert( end(), var );
 }
 
 // -----------------------------------------------------
 // 
 // -----------------------------------------------------
-void PdfArray::clear()
+void PdfArray::Clear()
 {
-    AssertMutable();
-
-    m_objects.clear();
+    clear();
 }
 
 // -----------------------------------------------------
@@ -359,14 +379,6 @@ const PdfObject& PdfArray::operator[](size_type __n) const
     return m_objects[__n];
 }
 
-// -----------------------------------------------------
-// 
-// -----------------------------------------------------
-void PdfArray::resize(size_t __n, value_type __x)
-{
-    m_objects.resize(__n, __x);
-}
-
 // -----------------------------------------------------
 // 
 // -----------------------------------------------------
@@ -447,48 +459,26 @@ void PdfArray::insert(const PdfArray::iterator& __position,
 {
     AssertMutable();
 
-    m_objects.insert( __position, __first, __last );
-    m_bDirty = true;
-}
-
-// -----------------------------------------------------
-// 
-// -----------------------------------------------------
-PdfArray::iterator PdfArray::insert(const iterator& __position, const PdfObject & val )
-{
-    AssertMutable();
-
-    m_bDirty = true;
-    return m_objects.insert( __position, val );
-}
-
-// -----------------------------------------------------
-// 
-// -----------------------------------------------------
-void PdfArray::erase( const iterator& pos )
-{
-    AssertMutable();
+    PdfVecObjects *pOwner = GetObjectOwner();
+    iterator it1 = __first;
+    iterator it2 = __position;
+    for ( ; it1 != __last; it1++, it2++ )
+    {
+        it2 = m_objects.insert( it2, *it1 );
+        if ( pOwner != NULL )
+            it2->SetOwner( pOwner );
+    }
 
-    m_objects.erase( pos );
     m_bDirty = true;
 }
 
 // -----------------------------------------------------
 // 
 // -----------------------------------------------------
-void PdfArray::erase( const iterator& first, const iterator& last )
+void PdfArray::reserve( size_type __n )
 {
     AssertMutable();
 
-    m_objects.erase( first, last );
-    m_bDirty = true;
-}
-
-// -----------------------------------------------------
-// 
-// -----------------------------------------------------
-void PdfArray::reserve(size_type __n)
-{
     m_objects.reserve( __n );
 }
 
diff --git a/src/base/PdfDictionary.cpp b/src/base/PdfDictionary.cpp
index df67c92..d43b211 100644
--- a/src/base/PdfDictionary.cpp
+++ b/src/base/PdfDictionary.cpp
@@ -44,9 +44,9 @@ PdfDictionary::PdfDictionary()
 }
 
 PdfDictionary::PdfDictionary( const PdfDictionary & rhs )
-    : PdfDataType()
+    : PdfOwnedDataType()
 {
-    this->operator=( rhs );
+    this->operator=( rhs );
     m_bDirty = false;
 }
 
@@ -68,7 +68,8 @@ const PdfDictionary & PdfDictionary::operator=( const PdfDictionary & rhs )
         m_mapKeys[(*it).first] = new PdfObject( *(*it).second );
         ++it;
     }
-    
+
+    PdfOwnedDataType::operator=( rhs );
     m_bDirty = true;
     return *this;
 }
@@ -147,6 +148,9 @@ void PdfDictionary::AddKey( const PdfName & identifier, const PdfObject & rObjec
         inserted.first->second = objToInsert;
     }
 
+    PdfVecObjects *pOwner = GetObjectOwner();
+    if ( pOwner != NULL )
+        inserted.first->second->SetOwner( pOwner );
     m_bDirty = true;
 }
 
@@ -155,7 +159,7 @@ void PdfDictionary::AddKey( const PdfName & identifier, const PdfObject* pObject
     this->AddKey( identifier, *pObject );
 }
 
-const PdfObject* PdfDictionary::GetKey( const PdfName & key ) const
+PdfObject * PdfDictionary::getKey( const PdfName & key ) const
 {
     if( !key.GetLength() )
         return NULL;
@@ -170,20 +174,43 @@ const PdfObject* PdfDictionary::GetKey( const PdfName & key ) const
     return (*it).second;
 }
 
-PdfObject* PdfDictionary::GetKey( const PdfName & key )
+PdfObject * PdfDictionary::findKey( const PdfName &key ) const
 {
-    if( !key.GetLength() )
-        return NULL;
-
-    TIKeyMap it;
-
-    it = m_mapKeys.find( key );
-
-    if( it == m_mapKeys.end() )
-        return NULL;
-
-    return (*it).second;
-}
+    PdfObject *obj = getKey( key );
+    if ( obj != NULL )
+    {
+        if ( obj->IsReference() )
+            return GetIndirectObject( obj->GetReference() );
+        else
+            return obj;
+    }
+
+    return NULL;
+}
+
+PdfObject * PdfDictionary::findKeyParent( const PdfName & key ) const
+{
+    PdfObject *obj = findKey( key );
+    if (obj == NULL)
+    {
+        PdfObject *parent = findKey( "Parent" );
+        if ( parent == NULL )
+        {
+            return NULL;
+        }
+        else
+        {
+            if ( parent->IsDictionary() )
+                return parent->GetDictionary().findKeyParent( key );
+            else
+                return NULL;
+        }
+    }
+    else
+    {
+        return obj;
+    }
+}
 
 pdf_int64 PdfDictionary::GetKeyAsLong( const PdfName & key, pdf_int64 lDefault ) const
 {
@@ -366,4 +393,18 @@ TCIKeyMap PdfDictionary::end() const
     return m_mapKeys.end();
 }
 
+void PdfDictionary::SetOwner( PdfObject *pOwner )
+{
+    PdfOwnedDataType::SetOwner( pOwner );
+    PdfVecObjects *pVecOwner = pOwner->GetOwner();
+    if ( pVecOwner != NULL )
+    {
+        // Set owmership for all children
+        TCIKeyMap it = this->begin();
+        TCIKeyMap end = this->end();
+        for ( ; it != end; it++ )
+            it->second->SetOwner( pVecOwner );
+    }
+}
+
 };
diff --git a/src/base/PdfDictionary.h b/src/base/PdfDictionary.h
index 342d4fc..c2163a2 100644
--- a/src/base/PdfDictionary.h
+++ b/src/base/PdfDictionary.h
@@ -35,7 +35,7 @@
 #define _PDF_DICTIONARY_H_
 
 #include "PdfDefines.h"
-#include "PdfDataType.h"
+#include "PdfOwnedDataType.h"
 
 #include "PdfName.h"
 #include "PdfObject.h"
@@ -86,7 +86,7 @@ class PdfOutputDevice;
 /** The PDF dictionary data type of PoDoFo (inherits from PdfDataType,
  *  the base class for such representations)
  */
-class PODOFO_API PdfDictionary : public PdfDataType {
+class PODOFO_API PdfDictionary : public PdfOwnedDataType {
  public:
     /** Create a new, empty dictionary
      */
@@ -165,7 +165,7 @@ class PODOFO_API PdfDictionary : public PdfDataType {
      * 
      *  \returns pointer to the found value, or 0 if the key was not found.
      */
-    const PdfObject* GetKey( const PdfName & key ) const;
+    inline const PdfObject* GetKey( const PdfName & key ) const;
 
     /** Get the key's value out of the dictionary.  This is an overloaded member
      * function.
@@ -178,7 +178,32 @@ class PODOFO_API PdfDictionary : public PdfDataType {
      * 
      *  \returns the found value, or 0 if the key was not found.
      */
-    PdfObject* GetKey( const PdfName & key );
+    inline PdfObject* GetKey( const PdfName & key );
+
+    /** Get the keys value out of the dictionary
+     *
+     * Lookup in the indirect objects as well, if the shallow object was a reference.
+     * The returned value is a pointer to the internal object in the dictionary
+     * so it MUST not be deleted.
+     *
+     *  \param key look for the key names pszKey in the dictionary
+     *  \returns pointer to the found value or 0 if the key was not found.
+     */
+    inline const PdfObject* FindKey( const PdfName & key ) const;
+    inline PdfObject* FindKey( const PdfName & key );
+
+    /** Get the keys value out of the dictionary
+     *
+     * Lookup in the indirect objects as well, if the shallow object was a reference.
+     * Also lookup the parent objects, if /Parent key is found in the dictionary.
+     * The returned value is a pointer to the internal object in the dictionary
+     * so it MUST not be deleted.
+     *
+     *  \param key look for the key names pszKey in the dictionary
+     *  \returns pointer to the found value or 0 if the key was not found.
+     */
+    inline const PdfObject* FindKeyParent( const PdfName & key ) const;
+    inline PdfObject* FindKeyParent( const PdfName & key );
 
     /** Get the key's value out of the dictionary.
      *
@@ -286,6 +311,14 @@ class PODOFO_API PdfDictionary : public PdfDataType {
      TCIKeyMap begin() const;
      TCIKeyMap end() const;
 
+ protected:
+     void SetOwner( PdfObject* pOwner );
+
+ private:
+     PdfObject * getKey(const PdfName & key) const;
+     PdfObject * findKey(const PdfName & key) const;
+     PdfObject * findKeyParent(const PdfName & key) const;
+
  private: 
     TKeyMap      m_mapKeys; 
 
@@ -296,6 +329,57 @@ typedef std::vector<PdfDictionary*>      TVecDictionaries;
 typedef	TVecDictionaries::iterator       TIVecDictionaries; 
 typedef	TVecDictionaries::const_iterator TCIVecDictionaries;
 
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline const PdfObject * PdfDictionary::GetKey( const PdfName &key ) const
+{
+    return getKey(key);
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline PdfObject * PdfDictionary::GetKey( const PdfName &key )
+{
+    return getKey(key);
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline const PdfObject * PdfDictionary::FindKey( const PdfName &key ) const
+{
+    return findKey(key);
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline PdfObject * PdfDictionary::FindKey( const PdfName &key )
+{
+    return findKey(key);
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline const PdfObject* PdfDictionary::FindKeyParent( const PdfName &key ) const
+{
+    return findKeyParent(key);
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
+inline PdfObject* PdfDictionary::FindKeyParent( const PdfName &key )
+{
+    return findKeyParent(key);
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
 size_t PdfDictionary::GetSize() const
 {
     return m_mapKeys.size();
diff --git a/src/base/PdfObject.cpp b/src/base/PdfObject.cpp
index 91e8aff..09a2663 100644
--- a/src/base/PdfObject.cpp
+++ b/src/base/PdfObject.cpp
@@ -126,6 +126,8 @@ PdfObject::PdfObject( const PdfDictionary & rDict )
     InitPdfObject();
 }
 
+// NOTE: Don't copy owner. Copied objects must be always detached.
+// Ownership will be set automatically elsewhere
 PdfObject::PdfObject( const PdfObject & rhs ) 
     : PdfVariant( rhs ), m_reference( rhs.m_reference )
 {
@@ -137,8 +139,12 @@ PdfObject::PdfObject( const PdfObject & rhs )
     const_cast<PdfObject*>(&rhs)->DelayedStreamLoad();
     m_bDelayedStreamLoadDone = rhs.DelayedStreamLoadDone();
 
-    if( rhs.m_pStream && m_pOwner )
-        m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) );
+    // FIXME:
+    // Copying stream is currently broken:
+    // 1) PdfVecObjects::CreateStream( const PdfStream & ) is broken as it just returns NULL
+    // 2) Stream should be copyable also when m_pOwner is NULL (which is the case for copy constructor)
+    //if( rhs.m_pStream && m_pOwner )
+    //    m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) );
 
 #if defined(PODOFO_EXTRA_CHECKS)
     // Must've been demand loaded or already done
@@ -153,12 +159,46 @@ PdfObject::~PdfObject()
     m_pStream = NULL;
 }
 
+void PdfObject::SetOwner( PdfVecObjects* pVecObjects )
+{
+    PODOFO_ASSERT( pVecObjects != NULL );
+    if ( m_pOwner == pVecObjects )
+    {
+        // The inner owner for variant data objects is guaranteed to be same
+        return;
+    }
+
+    m_pOwner = pVecObjects;
+    if ( DelayedLoadDone() )
+        SetVariantOwner( GetDataType() );
+}
+
+void PdfObject::AfterDelayedLoad( EPdfDataType eDataType )
+{
+    SetVariantOwner( eDataType );
+}
+
+void PdfObject::SetVariantOwner( EPdfDataType eDataType )
+{
+    switch ( eDataType )
+    {
+        case ePdfDataType_Dictionary:
+            static_cast<PdfOwnedDataType &>( GetDictionary_NoDL() ).SetOwner( this );
+            break;
+        case ePdfDataType_Array:
+            static_cast<PdfOwnedDataType &>( GetArray_NoDL() ).SetOwner( this );
+            break;
+        default:
+            break;
+    }
+}
+
 void PdfObject::InitPdfObject()
 {
     m_pStream                 = NULL;
     m_pOwner                  = NULL;
-
     m_bDelayedStreamLoadDone  = true;
+    SetVariantOwner( GetDataType() );
 
 #if defined(PODOFO_EXTRA_CHECKS)
     m_bDelayedStreamLoadInProgress = false;
@@ -221,26 +261,11 @@ void PdfObject::WriteObject( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode,
 
 PdfObject* PdfObject::GetIndirectKey( const PdfName & key ) const
 {
-    const PdfObject* pObj = NULL;
-
-    if( this->IsDictionary() && this->GetDictionary().HasKey( key ) )
-    {
-        pObj = this->GetDictionary().GetKey( key );
-        if( pObj->IsReference() ) 
-        {
-            if( !m_pOwner )
-            {
-                PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Object is a reference but does not have an owner!" );
-            }
-
-            pObj = m_pOwner->GetObject( pObj->GetReference() );
-        }
-        else
-            const_cast<PdfObject*>(pObj)->SetOwner( GetOwner() );// even directs might want an owner...
-    }
+    if ( !this->IsDictionary() )
+        return NULL;
 
     // DominikS: TODO Remove const on GetIndirectKey
-    return const_cast<PdfObject*>(pObj);
+    return const_cast<PdfObject*>( this->GetDictionary().FindKey( key ) );
 }
 
 pdf_long PdfObject::GetObjectLength( EPdfWriteMode eWriteMode )
@@ -314,15 +339,18 @@ const PdfObject & PdfObject::operator=( const PdfObject & rhs )
 
     const_cast<PdfObject*>(&rhs)->DelayedStreamLoad();
 
+    // NOTE: Don't copy owner. Objects being assigned always keep current ownership
+    PdfVariant::operator=(rhs);
     m_reference     = rhs.m_reference;
-    m_pOwner        = rhs.m_pOwner;
-
-    PdfVariant::operator=( rhs );
-
     m_bDelayedStreamLoadDone = rhs.DelayedStreamLoadDone();
-
-    if( rhs.m_pStream )
-        m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) );
+    SetVariantOwner( GetDataType() );
+
+    // FIXME:
+    // Copying stream is currently broken:
+    // 1) PdfVecObjects::CreateStream( const PdfStream & ) is broken as it just returns NULL
+    // 2) Stream should be copyable also when m_pOwner is NULL
+    //if( rhs.m_pStream )
+    //    m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) );
 
 #if defined(PODOFO_EXTRA_CHECKS)
     // Must've been demand loaded or already done
diff --git a/src/base/PdfObject.h b/src/base/PdfObject.h
index 8ed71a4..3ad042f 100644
--- a/src/base/PdfObject.h
+++ b/src/base/PdfObject.h
@@ -48,6 +48,9 @@ class PdfObject;
 class PdfOutputDevice;
 class PdfStream;
 class PdfVecObjects;
+class PdfDictionary;
+class PdfArray;
+class PdfDocument;
 
 /**
  * This class represents a PDF indirect Object in memory
@@ -63,6 +66,9 @@ class PdfVecObjects;
  */
 class PODOFO_API PdfObject : public PdfVariant {
     friend class PdfVecObjects;
+    friend class PdfArray;
+    friend class PdfDictionary;
+    friend class PdfDocument;
 
  public:
 
@@ -234,13 +240,6 @@ class PODOFO_API PdfObject : public PdfVariant {
      */
     PODOFO_NOTHROW inline bool operator==( const PdfObject & rhs ) const;
 
-    /** Set the owner of this object, i.e. the PdfVecObjects to which
-     *  this object belongs.
-     *
-     *  \param pVecObjects a vector of pdf objects
-     */
-    inline void SetOwner( PdfVecObjects* pVecObjects );
-
     /** Get the owner of this object.
      *  \return the creator of this object
      */
@@ -318,6 +317,20 @@ class PODOFO_API PdfObject : public PdfVariant {
      */
     PdfStream* GetStream_NoDL();
 
+    virtual void AfterDelayedLoad( EPdfDataType eDataType );
+
+    /** Set the owner of this object variant
+     */
+    void SetVariantOwner( EPdfDataType eDataType );
+
+ private:
+     /** Set the owner of this object, i.e. the PdfVecObjects to which
+      *  this object belongs.
+      *
+      *  \param pVecObjects a vector of pdf objects
+      */
+     void SetOwner(PdfVecObjects* pVecObjects);
+
  private:
     /* See PdfVariant.h for a detailed explanation of this member, which is
      * here to prevent accidental construction of a PdfObject of integer type
@@ -378,14 +391,6 @@ const PdfReference & PdfObject::Reference() const
     return m_reference;
 }
 
-// -----------------------------------------------------
-// 
-// -----------------------------------------------------
-inline void PdfObject::SetOwner( PdfVecObjects* pVecObjects )
-{
-    m_pOwner = pVecObjects;
-}
-
 // -----------------------------------------------------
 // 
 // -----------------------------------------------------
diff --git a/src/base/PdfOwnedDataType.cpp b/src/base/PdfOwnedDataType.cpp
new file mode 100644
index 0000000..81c7f63
--- /dev/null
+++ b/src/base/PdfOwnedDataType.cpp
@@ -0,0 +1,78 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominik Seichter                                *
+ *   domseich...@web.de                                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 2 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library General Public     *
+ *   License along with this program; if not, write to the                 *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                         *
+ *   In addition, as a special exception, the copyright holders give       *
+ *   permission to link the code of portions of this program with the      *
+ *   OpenSSL library under certain conditions as described in each         *
+ *   individual source file, and distribute linked combinations            *
+ *   including the two.                                                    *
+ *   You must obey the GNU General Public License in all respects          *
+ *   for all of the code used other than OpenSSL.  If you modify           *
+ *   file(s) with this exception, you may extend this exception to your    *
+ *   version of the file(s), but you are not obligated to do so.  If you   *
+ *   do not wish to do so, delete this exception statement from your       *
+ *   version.  If you delete this exception statement from all source      *
+ *   files in the program, then also delete it here.                       *
+ ***************************************************************************/
+
+#include "PdfOwnedDataType.h"
+#include "PdfObject.h"
+#include "PdfVecObjects.h"
+
+namespace PoDoFo {
+
+PdfOwnedDataType::PdfOwnedDataType()
+    : m_pOwner( NULL )
+{
+}
+
+// NOTE: Don't copy owner. Copied objects must be always detached.
+// Ownership will be set automatically elsewhere
+PdfOwnedDataType::PdfOwnedDataType( const PdfOwnedDataType &rhs )
+    : PdfDataType( rhs ), m_pOwner( NULL )
+{
+}
+
+PdfObject * PdfOwnedDataType::GetIndirectObject( const PdfReference &rReference ) const
+{
+    if ( m_pOwner == NULL )
+        PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Object is a reference but does not have an owner!" );
+
+    return m_pOwner->GetOwner()->GetObject( rReference );
+}
+
+void PdfOwnedDataType::SetOwner( PdfObject* pOwner )
+{
+    PODOFO_ASSERT( pOwner != NULL );
+    m_pOwner = pOwner;
+}
+
+PdfOwnedDataType & PdfOwnedDataType::operator=( const PdfOwnedDataType & rhs )
+{
+    // NOTE: Don't copy owner. Objects being assigned will keep current ownership
+    PdfDataType::operator=( rhs );
+    return *this;
+}
+
+PdfVecObjects * PdfOwnedDataType::GetObjectOwner()
+{
+    return m_pOwner == NULL ? NULL : m_pOwner->GetOwner();
+}
+
+};
diff --git a/src/base/PdfOwnedDataType.h b/src/base/PdfOwnedDataType.h
new file mode 100644
index 0000000..eeb3e8d
--- /dev/null
+++ b/src/base/PdfOwnedDataType.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominik Seichter                                *
+ *   domseich...@web.de                                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 2 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library General Public     *
+ *   License along with this program; if not, write to the                 *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                         *
+ *   In addition, as a special exception, the copyright holders give       *
+ *   permission to link the code of portions of this program with the      *
+ *   OpenSSL library under certain conditions as described in each         *
+ *   individual source file, and distribute linked combinations            *
+ *   including the two.                                                    *
+ *   You must obey the GNU General Public License in all respects          *
+ *   for all of the code used other than OpenSSL.  If you modify           *
+ *   file(s) with this exception, you may extend this exception to your    *
+ *   version of the file(s), but you are not obligated to do so.  If you   *
+ *   do not wish to do so, delete this exception statement from your       *
+ *   version.  If you delete this exception statement from all source      *
+ *   files in the program, then also delete it here.                       *
+ ***************************************************************************/
+
+#ifndef _PDF_OWNED_DATATYPE_H_
+#define _PDF_OWNED_DATATYPE_H_
+
+#include "PdfDataType.h"
+
+namespace PoDoFo {
+
+class PdfObject;
+class PdfVecObjects;
+class PdfReference;
+
+/**
+ * A PdfDataType object with PdfObject owner 
+ */
+class PODOFO_API PdfOwnedDataType : public PdfDataType {
+    friend class PdfObject;
+protected:
+    /** Create a new PdfDataOwnedType.
+     *  Can only be called by subclasses
+     */
+    PdfOwnedDataType();
+
+    PdfOwnedDataType( const PdfOwnedDataType &rhs );
+
+public:
+
+    /** \returns a pointer to a PdfVecObjects that is the
+     *           owner of this data type.
+     *           Might be NULL if the data type has no owner.
+     */
+    inline PdfObject* GetOwner() const;
+
+    PdfOwnedDataType & operator=( const PdfOwnedDataType &rhs );
+
+protected:
+    PdfObject * GetIndirectObject( const PdfReference &rReference ) const;
+    PdfVecObjects * GetObjectOwner();
+    virtual void SetOwner( PdfObject *pOwner );
+
+private:
+    PdfObject *m_pOwner;
+};
+
+inline PdfObject* PdfOwnedDataType::GetOwner() const
+{
+    return m_pOwner;
+}
+
+}; // namespace PoDoFo
+
+#endif /* _PDF_OWNED_DATATYPE_H_ */
diff --git a/src/base/PdfVariant.h b/src/base/PdfVariant.h
index 97e1745..32b455d 100644
--- a/src/base/PdfVariant.h
+++ b/src/base/PdfVariant.h
@@ -436,6 +436,11 @@ class PODOFO_API PdfVariant {
      */
     inline virtual void DelayedLoadImpl();
 
+    /** Called after delayed load
+     *  \param eDataType Detected data type
+     */
+    inline virtual void AfterDelayedLoad( EPdfDataType eDataType );
+
     /**
      * Returns true if delayed loading is disabled, or if it is enabled
      * and loading has completed. External callers should never need to
@@ -562,6 +567,7 @@ inline void PdfVariant::DelayedLoad() const
 #if defined(PODOFO_EXTRA_CHECKS)
         m_bDelayedLoadInProgress = false;
 #endif
+        const_cast<PdfVariant*>(this)->AfterDelayedLoad( m_eDataType );
     }
 }
 
@@ -940,6 +946,15 @@ void PdfVariant::DelayedLoadImpl()
     PODOFO_RAISE_ERROR( ePdfError_InternalLogic );
 }
 
+// -----------------------------------------------------
+// 
+// -----------------------------------------------------
+void PdfVariant::AfterDelayedLoad( EPdfDataType eDataType )
+{
+    ( void )eDataType;
+    // Do nothing
+}
+
 // -----------------------------------------------------
 // 
 // -----------------------------------------------------
diff --git a/src/doc/PdfPage.cpp b/src/doc/PdfPage.cpp
index f021ce7..0842e09 100644
--- a/src/doc/PdfPage.cpp
+++ b/src/doc/PdfPage.cpp
@@ -720,11 +720,7 @@ PdfObject* PdfPage::GetOwnAnnotationsArray( bool bCreate, PdfDocument *pDocument
             }
 
             pObj = pDocument->GetObjects()->GetObject( pObj->GetReference() );
-            if(pObj) {
-               pObj->SetOwner(this->GetObject()->GetOwner());
-            }
-         } else
-            pObj->SetOwner( this->GetObject()->GetOwner() );// even directs might want an owner...
+         }
       }
 
       if( pObj && pObj->IsArray() )
diff --git a/src/doc/PdfShadingPattern.cpp b/src/doc/PdfShadingPattern.cpp
index 9527511..8a91f4c 100644
--- a/src/doc/PdfShadingPattern.cpp
+++ b/src/doc/PdfShadingPattern.cpp
@@ -186,7 +186,6 @@ void PdfShadingPattern::Init( EPdfShadingPatternType eShadingType )
 	 } else {
 		 PdfObject *shadingObject = this->GetObject()->GetOwner()->CreateObject(shading);
 		 this->GetObject()->GetDictionary().AddKey(PdfName("Shading"), shadingObject->Reference());
-		 this->GetObject()->GetDictionary().GetKey(PdfName("Shading"))->SetOwner(this->GetObject()->GetOwner());
 	 }
 }
 


_______________________________________________
Podofo-users mailing list
Podofo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to