void PdfInputDevice::Seek( std::streamoff off, std::ios_base::seekdir dir ) { if (m_bIsSeekable) { if (m_pStream) { m_pStream->seekg( off, dir ); } if (m_pFile) { int whence; switch( dir ) { default: case std::ios_base::beg: whence = SEEK_SET; break; case std::ios_base::end: whence = SEEK_END; break; case std::ios_base::cur: whence = SEEK_CUR; break; } if( fseeko( m_pFile, off, whence ) == -1) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to seek to given position in the file" ); } } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Tried to seek an unseekable input device." ); } }
PdfContentsTokenizer::PdfContentsTokenizer( PdfCanvas* pCanvas ) : PdfTokenizer() { PdfObject* pContents = pCanvas->GetContents(); if( pContents && pContents->IsArray() ) { PdfArray& a = pContents->GetArray(); for ( PdfArray::iterator it = a.begin(); it != a.end() ; ++it ) { if ( !(*it).IsReference() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "/Contents array contained non-references" ); } m_lstContents.push_back( pContents->GetOwner()->GetObject( (*it).GetReference() ) ); } } else if ( pContents && pContents->HasStream() ) { m_lstContents.push_back( pContents ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Page /Contents not stream or array of streams" ); } if( m_lstContents.size() ) { SetCurrentContentsStream( m_lstContents.front() ); m_lstContents.pop_front(); } }
TVecFilters PdfFilterFactory::CreateFilterList( const PdfObject* pObject ) { TVecFilters filters; const PdfObject* pObj = NULL; if( pObject->IsDictionary() && pObject->GetDictionary().HasKey( "Filter" ) ) pObj = pObject->GetDictionary().GetKey( "Filter" ); else if( pObject->IsArray() ) pObj = pObject; else if( pObject->IsName() ) pObj = pObject; if (!pObj) // Object had no /Filter key . Return a null filter list. return filters; if( pObj->IsName() ) filters.push_back( PdfFilterFactory::FilterNameToType( pObj->GetName() ) ); else if( pObj->IsArray() ) { TCIVariantList it = pObj->GetArray().begin(); while( it != pObj->GetArray().end() ) { if ( (*it).IsName() ) { filters.push_back( PdfFilterFactory::FilterNameToType( (*it).GetName() ) ); } else if ( (*it).IsReference() ) { PdfObject* pFilter = pObject->GetOwner()->GetObject( (*it).GetReference() ); if( pFilter == NULL ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Filter array contained unexpected reference" ); } filters.push_back( PdfFilterFactory::FilterNameToType( pFilter->GetName() ) ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Filter array contained unexpected non-name type" ); } ++it; } } return filters; }
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; }
const PdfContentsGraph::KWInfo& PdfContentsGraph::findKwById(PdfContentStreamKeyword kw) { if ( kw == KW_RootNode ) { PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidEnumValue, "Cannot get KWInfo for root node"); } static const map<PdfContentStreamKeyword,const KWInfo*>::const_iterator itEnd = kwIdMap.end(); map<PdfContentStreamKeyword,const KWInfo*>::const_iterator it = kwIdMap.find(kw); if ( it == itEnd) { PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidEnumValue, "Bad keyword ID"); } return *((*it).second); }
void PdfFontMetricsFreetype::InitFontSizes() { FT_Error ftErr; if( !m_pFace ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot set font size on invalid font!" ); } float fSize = 1.0f; // TODO: Maybe we have to set this for charwidth!!! ftErr = FT_Set_Char_Size( m_pFace, static_cast<int>(fSize*64.0), 0, 72, 72 ); // calculate the line spacing now, as it changes only with the font size m_dLineSpacing = (static_cast<double>(m_pFace->height) / m_pFace->units_per_EM); m_dUnderlineThickness = (static_cast<double>(m_pFace->underline_thickness) / m_pFace->units_per_EM); m_dUnderlinePosition = (static_cast<double>(m_pFace->underline_position) / m_pFace->units_per_EM); m_dAscent = static_cast<double>(m_pFace->ascender) / m_pFace->units_per_EM; m_dDescent = static_cast<double>(m_pFace->descender) / m_pFace->units_per_EM; // Set default values for strikeout, in case the font has no direct values m_dStrikeOutPosition = m_dAscent / 2.0; m_dStrikeOutThickness = m_dUnderlineThickness; TT_OS2* pOs2Table = static_cast<TT_OS2*>(FT_Get_Sfnt_Table( m_pFace, ft_sfnt_os2 )); if( pOs2Table ) { m_dStrikeOutPosition = static_cast<double>(pOs2Table->yStrikeoutPosition) / m_pFace->units_per_EM; m_dStrikeOutThickness = static_cast<double>(pOs2Table->yStrikeoutSize) / m_pFace->units_per_EM; } }
PdfOutputDevice::PdfOutputDevice( const wchar_t* pszFilename, bool bTruncate ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_hFile = _wfopen( pszFilename, bTruncate ? L"w+b" : L"r+b" ); if( !m_hFile ) { PdfError e( ePdfError_FileNotFound, __FILE__, __LINE__ ); e.SetErrorInformation( pszFilename ); throw e; } if( !bTruncate ) { if( fseeko( m_hFile, 0, SEEK_END ) == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "Failed to seek to the end of the file" ); } m_ulPosition = ftello( m_hFile ); m_ulLength = m_ulPosition; } }
PdfOutputDevice::PdfOutputDevice( const char* pszFilename, bool bTruncate ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } std::ios_base::openmode openmode = std::fstream::binary | std::ios_base::in | std::ios_base::out; if( bTruncate ) openmode |= std::ios_base::trunc; std::fstream *pStream = new std::fstream( pszFilename, openmode ); if( pStream->fail() ) { delete pStream; PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } m_pStream = pStream; m_pReadStream = pStream; PdfLocaleImbue( *m_pStream ); if( !bTruncate ) { m_pStream->seekp( 0, std::ios_base::end ); m_ulPosition = m_pStream->tellp(); m_ulLength = m_ulPosition; } }
void PdfOutputDevice::Write( const char* pBuffer, size_t lLen ) { if( m_hFile ) { if( fwrite( pBuffer, sizeof(char), lLen, m_hFile ) != static_cast<size_t>(lLen) ) { PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } } else if( m_pBuffer ) { if( m_ulPosition + lLen <= m_lBufferLen ) { memcpy( m_pBuffer + m_ulPosition, pBuffer, lLen ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_OutOfMemory, "Allocated buffer to small for PdfOutputDevice. Cannot write!" ); } } else if( m_pStream ) { m_pStream->write( pBuffer, lLen ); } else if( m_pRefCountedBuffer ) { if( m_ulPosition + lLen > m_pRefCountedBuffer->GetSize() ) m_pRefCountedBuffer->Resize( m_ulPosition + lLen ); memcpy( m_pRefCountedBuffer->GetBuffer() + m_ulPosition, pBuffer, lLen ); } m_ulPosition += static_cast<size_t>(lLen); if(m_ulPosition>m_ulLength) m_ulLength = m_ulPosition; }
void PdfeFontType3::initGlyphs( const PdfObject* pFont ) { // CharProcs and Resources objects. PdfObject* pCharProcs = pFont->GetIndirectKey( "CharProcs" ); PdfObject* pResources = pFont->GetIndirectKey( "Resources" ); // No CharProcs: exception raised. if( !pCharProcs || !pCharProcs->IsDictionary() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Entries missing in the Type 3 font dictionary." ); } // Resize space vectors. m_mapCIDToGID.resize( m_lastCID-m_firstCID+1, 0 ); m_glyphs.resize( m_lastCID-m_firstCID+1, PdfeGlyphType3() ); // Look at each character. PdfName cname; PdfObject* pGlyph; for( pdfe_cid c = m_firstCID ; c <= m_lastCID ; ++c ) { // Get character name and search it in CharProcs. cname = this->fromCIDToName( c ); pGlyph = pCharProcs->GetIndirectKey( cname ); // If found, set GID to c-m_firstCID+1 and create glyph. if( pGlyph ) { m_mapCIDToGID[c-m_firstCID] = c-m_firstCID+1; m_glyphs[c-m_firstCID] = PdfeGlyphType3( cname, pGlyph, pResources ); } } }
EPdfFilter PdfFilterFactory::FilterNameToType( const PdfName & name, bool bSupportShortNames ) { int i = 0; while( aszFilters[i] ) { if( name == aszFilters[i] ) return static_cast<EPdfFilter>(i); ++i; } if( bSupportShortNames ) { i = 0; while( aszShortFilters[i] ) { if( name == aszShortFilters[i] ) return static_cast<EPdfFilter>(i); ++i; } } PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFilter, name.GetName().c_str() ); }
void PdfFont::WriteStringToStream( const PdfString & rsString, PdfStream* pStream ) { if( !m_pEncoding ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfString sEncoded = m_pEncoding->ConvertToEncoding( rsString, this ); if( sEncoded.IsUnicode() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "ConvertToEncoding must not return a unicode string" ); } pdf_long lLen = 0; char* pBuffer = NULL; std::auto_ptr<PdfFilter> pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); pFilter->Encode( sEncoded.GetString(), sEncoded.GetLength(), &pBuffer, &lLen ); pStream->Append( "<", 1 ); pStream->Append( pBuffer, lLen ); pStream->Append( ">", 1 ); free( pBuffer ); }
void PdfAnnotation::SetQuadPoints( const PdfArray & rQuadPoints ) { if ( m_eAnnotation != ePdfAnnotation_Highlight ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Must be a highlight annotation to set quad points" ); m_pObject->GetDictionary().AddKey( "QuadPoints", rQuadPoints ); }
PdfFileInputStream::PdfFileInputStream( const char* pszFilename ) { m_hFile = fopen( pszFilename, "rb" ); if( !m_hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } }
void PdfParser::ReadObjectFromStream( int nObjNo, int ) { // check if we already have read all objects // from this stream if( m_setObjectStreams.find( nObjNo ) != m_setObjectStreams.end() ) { return; } else m_setObjectStreams.insert( nObjNo ); // generation number of object streams is always 0 PdfParserObject * const pStream = dynamic_cast<PdfParserObject*>(m_vecObjects->GetObject( PdfReference( nObjNo, 0 ) ) ); if( !pStream ) { std::ostringstream oss; oss << "Loading of object " << nObjNo << " 0 R failed!" << std::endl; PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, oss.str().c_str() ); } long long lNum = pStream->GetDictionary().GetKeyAsLong( "N", 0 ); long long lFirst = pStream->GetDictionary().GetKeyAsLong( "First", 0 ); char * pBuffer; pdf_long lBufferLen; pStream->GetStream()->GetFilteredCopy( &pBuffer, &lBufferLen ); // the object stream is not needed anymore in the final PDF delete m_vecObjects->RemoveObject( pStream->Reference() ); PdfRefCountedInputDevice device( pBuffer, lBufferLen ); PdfTokenizer tokenizer( device, m_buffer ); PdfVariant var; int i = 0; while( static_cast<long long>(i) < lNum ) { const long long lObj = tokenizer.GetNextNumber(); const long long lOff = tokenizer.GetNextNumber(); const std::streamoff pos = device.Device()->Tell(); // move to the position of the object in the stream device.Device()->Seek( static_cast<std::streamoff>(lFirst + lOff) ); tokenizer.GetNextVariant( var, m_pEncrypt ); m_vecObjects->push_back( new PdfObject( PdfReference( static_cast<int>(lObj), 0LL ), var ) ); // move back to the position inside of the table of contents device.Device()->Seek( pos ); ++i; } free( pBuffer ); }
const PdfString & PdfParser::GetDocumentId() { if( !m_pTrailer->GetDictionary().HasKey( PdfName("ID") ) ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidEncryptionDict, "No document ID found in trailer."); } return m_pTrailer->GetDictionary().GetKey( PdfName("ID") )->GetArray()[0].GetString(); }
void PdfParser::SetPassword( const std::string & sPassword ) { if( !m_pEncrypt ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Cannot set password for unencrypted PDF." ); } bool bAuthenticate = m_pEncrypt->Authenticate( sPassword, this->GetDocumentId() ); if( !bAuthenticate ) { #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Authentication with user password failed\n" ); #endif // PODOFO_VERBOSE_DEBUG PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidPassword, "Authentication with user specified password failed."); } ReadObjectsInternal(); }
void PdfAnnotation::SetQuadPoints( const PdfArray & rQuadPoints ) { if ( m_eAnnotation != ePdfAnnotation_Highlight && m_eAnnotation != ePdfAnnotation_Underline && m_eAnnotation != ePdfAnnotation_Squiggly && m_eAnnotation != ePdfAnnotation_StrikeOut ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Must be a text markup annotation (hilight, underline, squiggly or strikeout) to set quad points" ); this->GetObject()->GetDictionary().AddKey( "QuadPoints", rQuadPoints ); }
PdfPage* PdfDestination::GetPage( PdfVecObjects* pVecObjects ) { PdfDocument* pDoc = pVecObjects->GetParentDocument(); if( !pDoc ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "PdfVecObjects needs a parent PdfDocument to resolve pages." ); } return this->GetPage( pDoc ); }
pdf_long PdfFileInputStream::GetFileLength() { pdf_long lOffset = ftello( m_hFile ); pdf_long lLen; if( lOffset == -1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to read current position in the file" ); if( fseeko( m_hFile, 0L, SEEK_END ) == -1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to seek at the end of the file" ); lLen = ftello( m_hFile ); if( lLen == -1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to read file length" ); if( fseeko( m_hFile, lOffset, SEEK_SET ) == -1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to seek back to the previous position of the file" ); return lLen; }
int PdfInputDevice::Look() const { if (m_pStream) return m_pStream->peek(); if (m_pFile) { pdf_long lOffset = ftello( m_pFile ); if( lOffset == -1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to read the current file position" ); int ch = GetChar(); if( fseeko( m_pFile, lOffset, SEEK_SET ) == -1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Failed to seek back to the previous position" ); return ch; } return 0; }
PdfParser::PdfParser( PdfVecObjects* pVecObjects, const PdfRefCountedInputDevice & rDevice, bool bLoadOnDemand ) : PdfTokenizer(), m_vecObjects( pVecObjects ) { this->Init(); if( !rDevice.Device() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot create PdfRefCountedInputDevice." ); } this->ParseFile( rDevice, bLoadOnDemand ); }
void PdfParser::ParseFile( const char* pszFilename, bool bLoadOnDemand ) { if( !pszFilename || !pszFilename[0] ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRefCountedInputDevice device( pszFilename, "rb" ); if( !device.Device() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } this->ParseFile( device, bLoadOnDemand ); }
void PdfParser::ParseFile( const char* pBuffer, long lLen, bool bLoadOnDemand ) { if( !pBuffer || !lLen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRefCountedInputDevice device( pBuffer, lLen ); if( !device.Device() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot create PdfParser from buffer." ); } this->ParseFile( device, bLoadOnDemand ); }
PdfeGlyphType3::PdfeGlyphType3( const PdfName& glyphName, PdfObject* glyphStream, PdfObject* fontResources ) : PdfeCanvasAnalysis(), PdfCanvas(), m_name( glyphName ), m_pStream( glyphStream ), m_pResources( fontResources ), m_isBBoxComputed( false ), m_bboxD1( 0,0,0,0 ), m_cbox( 0,0,0,0 ) { // Not stream in the object... if( !m_pStream->HasStream() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "The glyph description object does not contain a stream." ); } // Compute glyph bounding box. this->computeBBox(); }
PdfInputDevice::PdfInputDevice( const char* pszFilename ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } try { m_pFile = fopen(pszFilename, "rb"); //m_pStream = new std::ifstream( pszFilename, std::ios::binary ); if( !m_pFile) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } m_StreamOwned = true; } catch(...) { // should probably check the exact error, but for now it's a good error PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } //PdfLocaleImbue(*m_pStream); }
void PdfLocaleImbue(std::ios_base& s) { #if USE_CXX_LOCALE static const std::locale cachedLocale( PdfIOLocale ); try { s.imbue( cachedLocale ); } catch (const std::runtime_error & e) { std::ostringstream s; s << "Failed to set safe locale on stream being used for PDF I/O."; s << "Locale set was: \"" << PdfIOLocale << "\"."; s << "Error reported by STL std::locale: \"" << e.what() << "\""; // The info string is copied by PdfError so we're ok to just: PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, s.str().c_str() ); } #endif }
void PdfInputDevice::Seek( std::streamoff off, std::ios_base::seekdir dir ) { if (m_bIsSeekable) { if (m_pStream) { m_pStream->seekg( off, dir ); } if (m_pFile) { fseeko( m_pFile, off, dir ); } } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Tried to seek an unseekable input device." ); } }
void PdfParser::FindToken( const char* pszToken, const long lRange ) { m_device.Device()->Seek( 0, std::ios_base::end ); std::streamoff nFileSize = m_device.Device()->Tell(); if (nFileSize == -1) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Failed to seek to EOF when looking for xref"); } pdf_long lXRefBuf = PDF_MIN( nFileSize, lRange ); size_t nTokenLen = strlen( pszToken ); m_device.Device()->Seek( -lXRefBuf, std::ios_base::cur ); if( m_device.Device()->Read( m_buffer.GetBuffer(), lXRefBuf ) != lXRefBuf && !m_device.Device()->Eof() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } m_buffer.GetBuffer()[lXRefBuf] = '\0'; int i; // Do not make this unsigned, this will cause infinte loops in files without trailer // search backwards in the buffer in case the buffer contains null bytes // because it is right after a stream (can't use strstr for this reason) for( i = lXRefBuf - nTokenLen; i >= 0; i-- ) { if( strncmp( m_buffer.GetBuffer()+i, pszToken, nTokenLen ) == 0 ) { break; } } if( !i ) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } m_device.Device()->Seek( (lXRefBuf-i)*-1, std::ios_base::end ); }
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; } }