void PdfPagesTree::InsertPageIntoNode( PdfObject* pParent, const PdfObjectList & rlstParents, int nIndex, PdfObject* pPage ) { if( !pParent || !pPage ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // 1. Add the reference of the new page to the kids array of pParent // 2. Increase count of every node in lstParents (which also includes pParent) // 3. Add Parent key to the page // 1. Add reference const PdfArray oldKids = pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); PdfArray::const_iterator it = oldKids.begin(); PdfArray newKids; newKids.reserve( oldKids.GetSize() + 1 ); if( nIndex < 0 ) { newKids.push_back( pPage->Reference() ); } int i = 0; while( it != oldKids.end() ) { newKids.push_back( *it ); if( i == nIndex ) newKids.push_back( pPage->Reference() ); ++i; ++it; } /* PdfVariant var2( newKids ); std::string str2; var2.ToString(str2); printf("newKids= %s\n", str2.c_str() ); */ pParent->GetDictionary().AddKey( PdfName("Kids"), newKids ); // 2. increase count PdfObjectList::const_reverse_iterator itParents = rlstParents.rbegin(); while( itParents != rlstParents.rend() ) { this->ChangePagesCount( *itParents, 1 ); ++itParents; } // 3. add parent key to the page pPage->GetDictionary().AddKey( PdfName("Parent"), pParent->Reference() ); }
void PdfPagesTree::InsertPagesIntoNode( PdfObject* pParent, const PdfObjectList & rlstParents, int nIndex, const std::vector<PdfObject*>& vecPages ) { if( !pParent || !vecPages.size() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // 1. Add the reference of the new page to the kids array of pParent // 2. Increase count of every node in lstParents (which also includes pParent) // 3. Add Parent key to the page // 1. Add reference const PdfArray oldKids = pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); PdfArray newKids; newKids.reserve( oldKids.GetSize() + vecPages.size() ); bool bIsPushedIn = false; int i=0; for (PdfArray::const_iterator it=oldKids.begin(); it!=oldKids.end(); ++it, ++i ) { if ( !bIsPushedIn && (nIndex < i) ) // Pushing before { for (std::vector<PdfObject*>::const_iterator itPages=vecPages.begin(); itPages!=vecPages.end(); ++itPages) { newKids.push_back( (*itPages)->Reference() ); // Push all new kids at once } bIsPushedIn = true; } newKids.push_back( *it ); // Push in the old kids } // If new kids are still not pushed in then they may be appending to the end if ( !bIsPushedIn && ( (nIndex + 1) == static_cast<int>(oldKids.size())) ) { for (std::vector<PdfObject*>::const_iterator itPages=vecPages.begin(); itPages!=vecPages.end(); ++itPages) { newKids.push_back( (*itPages)->Reference() ); // Push all new kids at once } bIsPushedIn = true; } pParent->GetDictionary().AddKey( PdfName("Kids"), newKids ); // 2. increase count for ( PdfObjectList::const_reverse_iterator itParents = rlstParents.rbegin(); itParents != rlstParents.rend(); ++itParents ) { this->ChangePagesCount( *itParents, vecPages.size() ); } // 3. add parent key to each of the pages for (std::vector<PdfObject*>::const_iterator itPages=vecPages.begin(); itPages!=vecPages.end(); ++itPages) { (*itPages)->GetDictionary().AddKey( PdfName("Parent"), pParent->Reference() ); } }
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 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; } }
bool PdfPagesTree::IsTypePages(const PdfObject* pObject) const { if( !pObject ) return false; if( pObject->GetDictionary().GetKeyAsName( PdfName( "Type" ) ) == PdfName( "Pages" ) ) return true; return false; }
bool PdfPagesTree::IsEmptyPageNode( PdfObject* pPageNode ) { long lCount = GetChildCount( pPageNode ); bool bKidsEmpty = true; if( pPageNode->GetDictionary().HasKey( PdfName("Kids") ) ) { bKidsEmpty = pPageNode->GetDictionary().GetKey( PdfName("Kids") )->GetArray().empty(); } return ( lCount == 0L || bKidsEmpty ); }
PdfXObject::PdfXObject( const char* pszSubType, PdfVecObjects* pParent ) : PdfElement( "XObject", pParent ) { ostringstream out; PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. out << "XOb" << m_pObject->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); m_Reference = m_pObject->Reference(); m_pObject->GetDictionary().AddKey( PdfName::KeySubtype, PdfName( pszSubType ) ); }
unsigned int PdfPage::GetPageNumber() const { unsigned int nPageNumber = 0; PdfObject* pParent = m_pObject->GetIndirectKey( "Parent" ); PdfReference ref = m_pObject->Reference(); while( pParent ) { const PdfArray& kids = pParent->GetIndirectKey( "Kids" )->GetArray(); PdfArray::const_iterator it = kids.begin(); while( it != kids.end() && (*it).GetReference() != ref ) { PdfObject* pNode = m_pObject->GetOwner()->GetObject( (*it).GetReference() ); if( pNode->GetDictionary().GetKey( PdfName::KeyType )->GetName() == PdfName( "Pages" ) ) nPageNumber += static_cast<int>(pNode->GetDictionary().GetKey( "Count" )->GetNumber()); else // if we do not have a page tree node, // we most likely have a page object: // so the page count is 1 ++nPageNumber; ++it; } ref = pParent->Reference(); pParent = pParent->GetIndirectKey( "Parent" ); } return ++nPageNumber; }
void PdfInfo::SetTrapped(const PdfName & sTrapped) { if((sTrapped.GetEscapedName() == "True" ) || (sTrapped.GetEscapedName() == "False" )) this->GetObject()->GetDictionary().AddKey( "Trapped", sTrapped ); else this->GetObject()->GetDictionary().AddKey( "Trapped", PdfName( "Unknown" ) ); }
/* kausik : April 12th 2010 This is the font dictionary. It gets added to the page resources dictionary of the pdf. */ void PdfFontType1Base14::InitBase14Font( ) { PdfVariant var; this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("Type1")); this->GetObject()->GetDictionary().AddKey("BaseFont", this->GetBaseFont() ); m_pEncoding->AddToDictionary( this->GetObject()->GetDictionary() ); // Add encoding key // pDescriptor->GetDictionary().AddKey( "FontName", this->GetBaseFont() ); //pDescriptor->GetDictionary().AddKey( "FontWeight", (long)m_pMetrics->Weight() ); // 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; }
int PdfPagesTree::GetPosInKids( PdfObject* pPageObj, PdfObject* pPageParent ) { if( !pPageParent ) { //printf("pPageParent=%p\n", pPageParent ); return -1; } const PdfArray & rKids = pPageParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); PdfArray::const_iterator it = rKids.begin(); int index = 0; while( it != rKids.end() ) { if( (*it).GetReference() == pPageObj->Reference() ) { //printf("Found at: %i \n", index ); return index; } ++index; ++it; } //printf("Not found %i 0 R in %i 0 R\n", pPageObj->Reference().ObjectNumber(), // pPageParent->Reference().ObjectNumber()); return -1; }
/* We use NULL for the PdfElement name, since the AcroForm dict does NOT have a /Type key! */ PdfAcroForm::PdfAcroForm( PdfDocument* pDoc, EPdfAcroFormDefaulAppearance eDefaultAppearance ) : PdfElement( NULL, pDoc ), m_pDocument( pDoc ) { // Initialize with an empty fields array this->GetObject()->GetDictionary().AddKey( PdfName("Fields"), PdfArray() ); Init( eDefaultAppearance ); }
void PdfStitchingFunction::Init( const PdfFunction::List & rlstFunctions, const PdfArray & rBounds, const PdfArray & rEncode ) { PdfArray functions; PdfFunction::List::const_iterator it = rlstFunctions.begin(); functions.reserve( rlstFunctions.size() ); while( it != rlstFunctions.end() ) { functions.push_back( (*it).GetObject()->Reference() ); ++it; } this->GetObject()->GetDictionary().AddKey( PdfName("Functions"), functions ); this->GetObject()->GetDictionary().AddKey( PdfName("Bounds"), rBounds ); this->GetObject()->GetDictionary().AddKey( PdfName("Encode"), rEncode ); }
PdfDestination::PdfDestination( const PdfPage* pPage, double dLeft, double dTop, double dZoom ) { m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( PdfName("XYZ") ); m_array.push_back( dLeft ); m_array.push_back( dTop ); m_array.push_back( dZoom ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); }
void PdfExtGState::SetFrequency( double frequency ) { PdfDictionary halftoneDict; halftoneDict.AddKey( "HalftoneType", PdfVariant( 1LL ) ); halftoneDict.AddKey( "Frequency", PdfVariant( frequency ) ); halftoneDict.AddKey( "Angle", PdfVariant( 45.0 ) ); halftoneDict.AddKey( "SpotFunction", PdfName( "SimpleDot" ) ); m_pObject->GetDictionary().AddKey( "HT", halftoneDict); }
PdfDestination::PdfDestination( const PdfPage* pPage, EPdfDestinationFit eFit ) { PdfName type = PdfName("Fit"); if( eFit == ePdfDestinationFit_Fit ) type = PdfName("Fit"); else if( eFit == ePdfDestinationFit_FitB ) type = PdfName("FitB"); else { // Peter Petrov 6 June 2008 // silent mode //PODOFO_RAISE_ERROR( ePdfError_InvalidKey ); } m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( type ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); }
void PdfExtGState::SetFrequency( double frequency ) { PdfDictionary halftoneDict; halftoneDict.AddKey( "HalftoneType", PdfVariant( static_cast<pdf_int64>(PODOFO_LL_LITERAL(1)) ) ); halftoneDict.AddKey( "Frequency", PdfVariant( frequency ) ); halftoneDict.AddKey( "Angle", PdfVariant( 45.0 ) ); halftoneDict.AddKey( "SpotFunction", PdfName( "SimpleDot" ) ); this->GetObject()->GetDictionary().AddKey( "HT", halftoneDict); }
PdfDestination::PdfDestination( const PdfPage* pPage, const PdfRect & rRect ) { PdfVariant var; rRect.ToVariant( var ); m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( PdfName("FitR") ); m_array.insert( m_array.end(), var.GetArray().begin(), var.GetArray().end() ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); }
void PdfSampledFunction::Init( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples ) { PdfArray Size; for( unsigned i = 0; i < rDomain.GetSize() / 2; i++ ) Size.push_back( PdfObject( (long long) (rDomain.GetSize()) / 2L ) ); this->GetObject()->GetDictionary().AddKey( PdfName("Domain"), rDomain ); this->GetObject()->GetDictionary().AddKey( PdfName("Range"), rRange ); this->GetObject()->GetDictionary().AddKey( PdfName("Size"), Size ); this->GetObject()->GetDictionary().AddKey( PdfName("Order"), PdfObject( 1LL ) ); this->GetObject()->GetDictionary().AddKey( PdfName("BitsPerSample"), PdfObject( 8LL ) ); this->GetObject()->GetStream()->BeginAppend(); PdfFunction::Sample::const_iterator it = rlstSamples.begin(); while( it != rlstSamples.end() ) { this->GetObject()->GetStream()->Append( & ( *it ), 1 ); ++it; } this->GetObject()->GetStream()->EndAppend(); }
PdfName PdfDictionary::GetKeyAsName( const PdfName & key ) const { const PdfObject* pObject = GetKey( key ); if( pObject && pObject->GetDataType() == ePdfDataType_Name ) { return pObject->GetName(); } return PdfName(""); // return an empty name }
PdfAction::PdfAction( EPdfAction eAction, PdfDocument* pParent ) : PdfElement( "Action", pParent ), m_eType( eAction ) { const PdfName type = PdfName( TypeNameForIndex( eAction, s_names, s_lNumActions ) ); if( !type.GetLength() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } this->GetObject()->GetDictionary().AddKey( "S", type ); }
PdfDestination::PdfDestination( const PdfPage* pPage, EPdfDestinationFit eFit, double dValue ) { PdfName type; if( eFit == ePdfDestinationFit_FitH ) type = PdfName("FitH"); else if( eFit == ePdfDestinationFit_FitV ) type = PdfName("FitV"); else if( eFit == ePdfDestinationFit_FitBH ) type = PdfName("FitBH"); else if( eFit == ePdfDestinationFit_FitBV ) type = PdfName("FitBV"); else { PODOFO_RAISE_ERROR( ePdfError_InvalidKey ); } m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( type ); m_array.push_back( dValue ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); }
void PdfFont::InitVars() { ostringstream out; PdfLocaleImbue(out); m_pMetrics->SetFontSize( 12.0 ); m_pMetrics->SetFontScale( 100.0 ); m_pMetrics->SetFontCharSpace( 0.0 ); // Peter Petrov 24 Spetember 2008 m_bWasEmbedded = false; m_bUnderlined = false; m_bStrikedOut = false; // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "Ft" << m_pObject->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); // replace all spaces in the base font name as suggested in // the PDF reference section 5.5.2# int curPos = 0; std::string sTmp = m_pMetrics->GetFontname(); const char* pszPrefix = m_pMetrics->GetSubsetFontnamePrefix(); if( pszPrefix ) { std::string sPrefix = pszPrefix; sTmp = sPrefix + sTmp; } for(unsigned int i = 0; i < sTmp.size(); i++) { if(sTmp[i] != ' ') sTmp[curPos++] = sTmp[i]; } sTmp.resize(curPos); m_BaseFont = PdfName( sTmp.c_str() ); }
void PdfXObject::InitXObject( const PdfRect & rRect, const char* pszPrefix ) { PdfVariant var; ostringstream out; PdfLocaleImbue(out); // Initialize static data if( s_matrix.empty() ) { // This matrix is the same for all PdfXObjects so cache it s_matrix.push_back( PdfVariant( 1LL ) ); s_matrix.push_back( PdfVariant( 0LL ) ); s_matrix.push_back( PdfVariant( 0LL ) ); s_matrix.push_back( PdfVariant( 1LL ) ); s_matrix.push_back( PdfVariant( 0LL ) ); s_matrix.push_back( PdfVariant( 0LL ) ); } rRect.ToVariant( var ); m_pObject->GetDictionary().AddKey( "BBox", var ); m_pObject->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("Form") ); m_pObject->GetDictionary().AddKey( "FormType", PdfVariant( 1LL ) ); // only 1 is only defined in the specification. m_pObject->GetDictionary().AddKey( "Matrix", s_matrix ); // The PDF specification suggests that we send all available PDF Procedure sets m_pObject->GetDictionary().AddKey( "Resources", PdfObject( PdfDictionary() ) ); m_pResources = m_pObject->GetDictionary().GetKey( "Resources" ); m_pResources->GetDictionary().AddKey( "ProcSet", PdfCanvas::GetProcSet() ); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. if ( pszPrefix == NULL ) out << "XOb" << m_pObject->Reference().ObjectNumber(); else out << pszPrefix << m_pObject->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); m_Reference = m_pObject->Reference(); }
bool PdfParser::QuickEncryptedCheck( const char* pszFilename ) { bool bEncryptStatus = false; bool bOldLoadOnDemand = m_bLoadOnDemand; Init(); Clear(); m_bLoadOnDemand = true; // maybe will be quicker if true? if( !pszFilename || !pszFilename[0] ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_device = PdfRefCountedInputDevice( pszFilename, "rb" ); if( !m_device.Device() ) { //PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); // If we can not open PDF file // then file does not exist return false; } if( !IsPdfFile() ) { //PODOFO_RAISE_ERROR( ePdfError_NoPdfFile ); return false; } ReadDocumentStructure(); try { m_vecObjects->Reserve( m_nNumObjects ); // Check for encryption and make sure that the encryption object // is loaded before all other objects if( m_pTrailer->GetDictionary().HasKey( PdfName("Encrypt") ) ) { bEncryptStatus = true; } } catch( PdfError & e ) { m_bLoadOnDemand = bOldLoadOnDemand; // Restore load on demand behaviour e.AddToCallstack( __FILE__, __LINE__, "Unable to load objects from file." ); throw e; } m_bLoadOnDemand = bOldLoadOnDemand; // Restore load on demand behaviour return bEncryptStatus; }
void PdfDestination::AddToDictionary( PdfDictionary & dictionary ) const { // Do not add empty destinations if( !m_array.size() ) return; // since we can only have EITHER a Dest OR an Action // we check for an Action, and if already present, we throw if ( dictionary.HasKey( PdfName( "A" ) ) ) PODOFO_RAISE_ERROR( ePdfError_ActionAlreadyPresent ); dictionary.RemoveKey( "Dest" ); dictionary.AddKey( "Dest", m_pObject ); }
PdfExtGState::PdfExtGState( PdfDocument* pParent ) : PdfElement( "ExtGState", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "ExtGS" << m_pObject->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init(); }
PdfFontType1::PdfFontType1( PdfFontType1* pFont, PdfFontMetrics* pMetrics, const char *pszSuffix, PdfVecObjects* pParent ) : PdfFontSimple( pMetrics, pFont->m_pEncoding, pParent ) { // don't embedd font Init( false, PdfName("Type1") ); // set identifier std::string id = pFont->GetIdentifier().GetName(); id += pszSuffix; m_Identifier = id; // remove new FontDescriptor and use FontDescriptor of source font instead pParent->RemoveObject( GetObject()->GetIndirectKey( "FontDescriptor" )->Reference() ); GetObject()->GetDictionary().AddKey( "FontDescriptor", pFont->GetObject()->GetDictionary().GetKey( "FontDescriptor" ) ); }
PdfXObject::PdfXObject( PdfObject* pObject ) : PdfElement( "XObject", pObject ), PdfCanvas() { ostringstream out; PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. out << "XOb" << m_pObject->Reference().ObjectNumber(); m_pResources = pObject->GetIndirectKey( "Resources" ); m_Identifier = PdfName( out.str().c_str() ); m_rRect = PdfRect( m_pObject->GetIndirectKey( "BBox" )->GetArray() ); m_Reference = m_pObject->Reference(); }
int PdfPage::GetNumFields() const { int nCount = 0; int nAnnots = this->GetNumAnnots(); const PdfAnnotation* pAnnot = NULL; for( int i=0;i<nAnnots;i++ ) { pAnnot = const_cast<PdfPage*>(this)->GetAnnotation( i ); // Count every widget annotation with a FieldType as PdfField if( pAnnot->GetType() == ePdfAnnotation_Widget && pAnnot->GetObject()->GetDictionary().HasKey( PdfName("FT") ) ) ++nCount; } return nCount; }