void PdfAnnotation::SetColor( double r, double g, double b ) { PdfArray c; c.push_back( PdfVariant( r ) ); c.push_back( PdfVariant( g ) ); c.push_back( PdfVariant( b ) ); m_pObject->GetDictionary().AddKey( "C", c ); }
void PdfFontMetricsFreetype::GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const { unsigned int i; PdfArray list; if( !m_pFace ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } for( i=nFirst;i<=nLast;i++ ) { if( i < PODOFO_WIDTH_CACHE_SIZE ) list.push_back( PdfVariant( m_vecWidth[i] ) ); else { if( !FT_Load_Char( m_pFace, i, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) // | FT_LOAD_NO_RENDER { //PODOFO_RAISE_ERROR( ePdfError_FreeType ); list.push_back( PdfVariant( 0.0 ) ); continue; } list.push_back( PdfVariant( m_pFace->glyph->metrics.horiAdvance * 1000.0 / m_pFace->units_per_EM ) ); } } var = PdfVariant( list ); }
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) ); }
void PdfSignOutputDevice::AdjustByteRange() { if(!m_bBeaconFound) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } // Get final position size_t sFileEnd = GetLength(); PdfArray arr; arr.push_back( PdfVariant(static_cast<pdf_int64>(0)) ); arr.push_back( PdfVariant(static_cast<pdf_int64>(m_sBeaconPos)) ); arr.push_back( PdfVariant(static_cast<pdf_int64>(m_sBeaconPos+m_pSignatureBeacon->data().size()+2) ) ); arr.push_back( PdfVariant(static_cast<pdf_int64>(sFileEnd-(m_sBeaconPos+m_pSignatureBeacon->data().size()+2)) ) ); std::string sPosition; PdfVariant(arr).ToString(sPosition, ePdfWriteMode_Compact); // Fill padding unsigned int sPosSize = sizeof("[ 0 1234567890 1234567890 1234567890]")-1; if(sPosition.size()<sPosSize) { // drop last ']' sPosition.resize(sPosition.size()-1); while(sPosition.size()<(sPosSize-1)) { sPosition+=' '; } sPosition+=']'; } m_pRealDevice->Seek(m_sBeaconPos-sPosition.size()-9); m_pRealDevice->Write(sPosition.c_str(), sPosition.size()); }
void PdfAnnotation::SetColor( double C, double M, double Y, double K ) { PdfArray c; c.push_back( PdfVariant( C ) ); c.push_back( PdfVariant( M ) ); c.push_back( PdfVariant( Y ) ); c.push_back( PdfVariant( K ) ); m_pObject->GetDictionary().AddKey( "C", c ); }
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() ); } }
void PdfOutlineItem::SetTextColor( double r, double g, double b ) { PdfArray color; color.push_back( r ); color.push_back( g ); color.push_back( b ); m_pObject->GetDictionary().AddKey( "C", color ); }
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 PdfFontMetricsFreetype::GetBoundingBox( PdfArray & array ) const { if( !m_pFace ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } array.Clear(); array.push_back( PdfVariant( m_pFace->bbox.xMin * 1000.0 / m_pFace->units_per_EM ) ); array.push_back( PdfVariant( m_pFace->bbox.yMin * 1000.0 / m_pFace->units_per_EM ) ); array.push_back( PdfVariant( m_pFace->bbox.xMax * 1000.0 / m_pFace->units_per_EM ) ); array.push_back( PdfVariant( m_pFace->bbox.yMax * 1000.0 / m_pFace->units_per_EM ) ); }
void PdfAnnotation::SetBorderStyle( double dHCorner, double dVCorner, double dWidth, const PdfArray & rStrokeStyle ) { // TODO : Support for Border style for PDF Vers > 1.0 PdfArray aValues; aValues.push_back(dHCorner); aValues.push_back(dVCorner); aValues.push_back(dWidth); if( rStrokeStyle.size() ) aValues.push_back(rStrokeStyle); m_pObject->GetDictionary().AddKey( "Border", aValues ); }
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 ); }
PdfXObject::PdfXObject( const PdfMemDocument & rDoc, int nPage, PdfDocument* pParent ) : PdfElement( "XObject", pParent ), PdfCanvas() { m_rRect = PdfRect(); InitXObject( m_rRect, "XObInd" ); // Implementation note: source document must be different from distination if ( pParent == reinterpret_cast<const PdfDocument*>(&rDoc) ) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } // After filling set correct BBox m_rRect = pParent->FillXObjectFromDocumentPage( this, rDoc, nPage ); PdfVariant var; m_rRect.ToVariant( var ); m_pObject->GetDictionary().AddKey( "BBox", var ); PdfArray matrix; matrix.push_back( PdfVariant( 1LL ) ); matrix.push_back( PdfVariant( 0LL ) ); matrix.push_back( PdfVariant( 0LL ) ); matrix.push_back( PdfVariant( 1LL ) ); if( m_rRect.GetLeft() != 0 ) matrix.push_back( PdfVariant( m_rRect.GetLeft() * (-1.0) ) ); else matrix.push_back( PdfVariant( 0LL ) ); if( m_rRect.GetBottom() != 0 ) matrix.push_back( PdfVariant( m_rRect.GetBottom() * (-1.0) ) ); else matrix.push_back( PdfVariant( 0LL ) ); m_pObject->GetDictionary().AddKey( "Matrix", matrix ); }
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(); }
void TextExtractor::ExtractText( PdfMemDocument* pDocument, PdfPage* pPage ) { const char* pszToken = NULL; PdfVariant var; EPdfContentsType eType; PdfContentsTokenizer tokenizer( pPage ); double dCurPosX = 0.0; double dCurPosY = 0.0; double dCurFontSize = 0.0; bool bTextBlock = false; PdfFont* pCurFont = NULL; std::stack<PdfVariant> stack; while( tokenizer.ReadNext( eType, pszToken, var ) ) { if( eType == ePdfContentsType_Keyword ) { // support 'l' and 'm' tokens if( strcmp( pszToken, "l" ) == 0 || strcmp( pszToken, "m" ) == 0 ) { dCurPosX = stack.top().GetReal(); stack.pop(); dCurPosY = stack.top().GetReal(); stack.pop(); } else if( strcmp( pszToken, "BT" ) == 0 ) { bTextBlock = true; // BT does not reset font // dCurFontSize = 0.0; // pCurFont = NULL; } else if( strcmp( pszToken, "ET" ) == 0 ) { if( !bTextBlock ) fprintf( stderr, "WARNING: Found ET without BT!\n" ); } if( bTextBlock ) { if( strcmp( pszToken, "Tf" ) == 0 ) { dCurFontSize = stack.top().GetReal(); stack.pop(); PdfName fontName = stack.top().GetName(); PdfObject* pFont = pPage->GetFromResources( PdfName("Font"), fontName ); if( !pFont ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot create font!" ); } pCurFont = pDocument->GetFont( pFont ); if( !pCurFont ) { fprintf( stderr, "WARNING: Unable to create font for object %i %i R\n", pFont->Reference().ObjectNumber(), pFont->Reference().GenerationNumber() ); } } else if( strcmp( pszToken, "Tj" ) == 0 || strcmp( pszToken, "'" ) == 0 ) { AddTextElement( dCurPosX, dCurPosY, pCurFont, stack.top().GetString() ); stack.pop(); } else if( strcmp( pszToken, "\"" ) == 0 ) { AddTextElement( dCurPosX, dCurPosY, pCurFont, stack.top().GetString() ); stack.pop(); stack.pop(); // remove char spacing from stack stack.pop(); // remove word spacing from stack } else if( strcmp( pszToken, "TJ" ) == 0 ) { PdfArray array = stack.top().GetArray(); stack.pop(); for( int i=0; i<static_cast<int>(array.GetSize()); i++ ) { if( array[i].IsString() ) AddTextElement( dCurPosX, dCurPosY, pCurFont, array[i].GetString() ); } } } } else if ( eType == ePdfContentsType_Variant ) { stack.push( var ); } else { // Impossible; type must be keyword or variant PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } } }
PdfFontMetricsObject::PdfFontMetricsObject( PdfObject* pFont, PdfObject* pDescriptor, const PdfEncoding* const pEncoding ) : PdfFontMetrics( ePdfFontType_Unknown, "", NULL ), m_pEncoding( pEncoding ), m_dDefWidth(0.0) { if( !pDescriptor ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } const PdfName & rSubType = pFont->GetDictionary().GetKey( PdfName::KeySubtype )->GetName(); // OC 15.08.2010 BugFix: /FirstChar /LastChar /Widths are in the Font dictionary and not in the FontDescriptor if ( rSubType == PdfName("Type1") || rSubType == PdfName("TrueType") ) { m_sName = pDescriptor->GetIndirectKey( "FontName" )->GetName(); m_bbox = pDescriptor->GetIndirectKey( "FontBBox" )->GetArray(); m_nFirst = static_cast<int>(pFont->GetDictionary().GetKeyAsLong( "FirstChar", 0L )); m_nLast = static_cast<int>(pFont->GetDictionary().GetKeyAsLong( "LastChar", 0L )); // OC 15.08.2010 BugFix: GetIndirectKey() instead of GetDictionary().GetKey() and "Widths" instead of "Width" PdfObject* widths = pFont->GetIndirectKey( "Widths" ); if( widths != NULL ) { m_width = widths->GetArray(); m_missingWidth = NULL; } else { widths = pDescriptor->GetDictionary().GetKey( "MissingWidth" ); if( widths == NULL ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, "Font object defines neither Widths, nor MissingWidth values!" ); m_missingWidth = widths; } } } else if ( rSubType == PdfName("CIDFontType0") || rSubType == PdfName("CIDFontType2") ) { PdfObject *pObj = pDescriptor->GetIndirectKey( "FontName" ); if (pObj) { m_sName = pObj->GetName(); } pObj = pDescriptor->GetIndirectKey( "FontBBox" ); if (pObj) { m_bbox = pObj->GetArray(); } m_nFirst = 0; m_nLast = 0; m_dDefWidth = static_cast<double>(pFont->GetDictionary().GetKeyAsLong( "DW", 1000L )); PdfVariant default_width(m_dDefWidth); PdfObject * pw = pFont->GetIndirectKey( "W" ); for (int i = m_nFirst; i <= m_nLast; ++i) { m_width.push_back(default_width); } if (pw) { PdfArray w = pw->GetArray(); int pos = 0; while (pos < static_cast<int>(w.GetSize())) { int start = static_cast<int>(w[pos++].GetNumber()); PODOFO_ASSERT (start >= 0); if (w[pos].IsArray()) { PdfArray widths = w[pos++].GetArray(); int length = start + static_cast<int>(widths.GetSize()); PODOFO_ASSERT (length >= start); if (length > static_cast<int>(m_width.GetSize())) { m_width.resize(length, default_width); } for (int i = 0; i < static_cast<int>(widths.GetSize()); ++i) { m_width[start + i] = widths[i]; } } else { int end = static_cast<int>(w[pos++].GetNumber()); int length = start + end; PODOFO_ASSERT (length >= start); if (length > static_cast<int>(m_width.GetSize())) { m_width.resize(length, default_width); } pdf_int64 width = w[pos++].GetNumber(); for (int i = start; i <= end; ++i) m_width[i] = PdfVariant(width); } } } m_nLast = m_width.GetSize() - 1; } else { PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFontFormat, rSubType.GetEscapedName().c_str() ); } m_nWeight = static_cast<unsigned int>(pDescriptor->GetDictionary().GetKeyAsLong( "FontWeight", 400L )); m_nItalicAngle = static_cast<int>(pDescriptor->GetDictionary().GetKeyAsLong( "ItalicAngle", 0L )); m_dPdfAscent = pDescriptor->GetDictionary().GetKeyAsReal( "Ascent", 0.0 ); m_dAscent = m_dPdfAscent / 1000.0; m_dPdfDescent = pDescriptor->GetDictionary().GetKeyAsReal( "Descent", 0.0 ); m_dDescent = m_dPdfDescent / 1000.0; m_dLineSpacing = m_dAscent + m_dDescent; // Try to fine some sensible values m_dUnderlineThickness = 1.0; m_dUnderlinePosition = 0.0; m_dStrikeOutThickness = m_dUnderlinePosition; m_dStrikeOutPosition = m_dAscent / 2.0; m_bSymbol = false; // TODO }
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; } }
void PdfFontCID::CreateWidth( PdfObject* pFontDict ) const { const int cAbsoluteMax = 0xffff; int nFirstChar = m_pEncoding->GetFirstChar(); int nLastChar = m_pEncoding->GetLastChar(); int i; // Allocate an initialize an array, large enough to // hold a width value for every possible glyph index double* pdWidth = static_cast<double*>(malloc( sizeof(double) * cAbsoluteMax ) ); if( !pdWidth ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } for( i=0;i<cAbsoluteMax;i++ ) pdWidth[i] = 0.0; // Load the width of all requested glyph indeces int nMin = 0xffff; int nMax = 0; long lGlyph = 0; for( i=nFirstChar;i<=nLastChar;i++ ) { lGlyph = m_pMetrics->GetGlyphId( i ); if( lGlyph ) { nMin = PDF_MIN( static_cast<long>(nMin), lGlyph ); nMax = PDF_MAX( static_cast<long>(nMax), lGlyph ); nMax = PDF_MIN( nMax, cAbsoluteMax ); if( lGlyph < cAbsoluteMax ) pdWidth[lGlyph] = m_pMetrics->GetGlyphWidth( lGlyph ); } } if (nMax >= nMin) { // Now compact the array std::ostringstream oss; PdfArray array; array.reserve( nMax - nMin + 1 ); i = nMin; double dCurWidth = pdWidth[i]; pdf_int64 lCurIndex = i++; pdf_int64 lCurLength = 1L; for( ;i<=nMax;i++ ) { if( static_cast<int>(pdWidth[i] - dCurWidth) == 0 ) ++lCurLength; else { if( lCurLength > 1 ) { array.push_back( lCurIndex ); pdf_int64 temp = lCurIndex + lCurLength - 1; array.push_back( temp ); array.push_back( dCurWidth ); } else { if( array.size() && array.back().IsArray() ) { array.back().GetArray().push_back( dCurWidth ); } else { PdfArray tmp; tmp.push_back( dCurWidth ); array.push_back( lCurIndex ); array.push_back( tmp ); } } lCurIndex = i; lCurLength = 1L; dCurWidth = pdWidth[i]; } } if (array.size() == 0) { array.push_back( lCurIndex = nMin ); array.push_back( lCurIndex = nMax ); array.push_back( dCurWidth ); } pFontDict->GetDictionary().AddKey( PdfName("W"), array ); } free( pdWidth ); }
void PdfAnnotation::SetColor( double gray ) { PdfArray c; c.push_back( PdfVariant( gray ) ); this->GetObject()->GetDictionary().AddKey( "C", c ); }
bool PDFAnalyzer::inspectCanvas(PdfCanvas* canvas, QList<PDFColorSpace> & usedColorSpaces, bool & hasTransparency, QList<PDFFont> & usedFonts, QList<PDFImage> & imgs) { // this method can be used to get used color spaces, detect transparency, and get used fonts in either PdfPage or PdfXObject PdfObject* colorSpaceRes; PdfObject* xObjects; PdfObject* transGroup; PdfObject* extGState; PdfObject* fontRes; QMap<PdfName, PDFColorSpace> processedNamedCS; QMap<PdfName, PDFFont> processedNamedFont; QList<PdfName> processedNamedXObj; QList<PdfName> processedNamedGS; try { // get hold of a PdfObject pointer of this canvas // needed for the finding resources code below to work PdfPage* page = dynamic_cast<PdfPage*>(canvas); PdfObject* canvasObject = page?(page->GetObject()):((dynamic_cast<PdfXObject*>(canvas))->GetObject()); // find a resource with ColorSpace entry PdfObject* resources = canvas->GetResources(); for (PdfObject* par = canvasObject; par && !resources; par = par->GetIndirectKey("Parent")) { resources = par->GetIndirectKey("Resources"); } colorSpaceRes = resources?resources->GetIndirectKey("ColorSpace"):NULL; xObjects = resources?resources->GetIndirectKey("XObject"):NULL; extGState = resources?resources->GetIndirectKey("ExtGState"):NULL; fontRes = resources?resources->GetIndirectKey("Font"):NULL; // getting the transparency group of this content stream (if available) transGroup = canvasObject?canvasObject->GetIndirectKey("Group"):NULL; if (transGroup) { PdfObject* subtype = transGroup->GetIndirectKey("S"); if (subtype && subtype->GetName() == "Transparency") { // having transparency group means there's transparency in the PDF hasTransparency = true; // reporting the color space used in transparency group (Section 7.5.5, PDF 1.6 Spec) PdfObject* cs = transGroup->GetIndirectKey("CS"); if (cs) { PDFColorSpace retval = getCSType(cs); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); } } } } catch (PdfError & e) { qDebug() << "Error in analyzing stream's resources."; e.PrintErrorMsg(); return false; } try { // start parsing the content stream PdfContentsTokenizer tokenizer(canvas); EPdfContentsType t; const char * kwText; PdfVariant var; bool readToken; int tokenNumber = 0; QList<PdfVariant> args; bool inlineImgDict = false; QStack<PDFGraphicState> gsStack; PDFGraphicState currGS; while ((readToken = tokenizer.ReadNext(t, kwText, var))) { ++tokenNumber; if (t == ePdfContentsType_Variant) { args.append(var); } else if (t == ePdfContentsType_Keyword) { QString kw(kwText); switch(kwNameMap.value(kw, KW_Undefined)) { case KW_q: gsStack.push(currGS); break; case KW_Q: currGS = gsStack.pop(); break; case KW_cm: { if (args.size() == 6) { double mt[6]; for (int i=0; i<6; ++i) { mt[i] = args[i].GetReal(); } QMatrix transMatrix(mt[0], mt[1], mt[2], mt[3], mt[4], mt[5]); currGS.ctm = transMatrix*currGS.ctm; } } break; case KW_w: currGS.lineWidth = args[0].GetReal(); break; case KW_J: currGS.lineCap = args[0].GetNumber(); break; case KW_j: currGS.lineJoin = args[0].GetNumber(); break; case KW_M: currGS.lineJoin = args[0].GetReal(); break; case KW_d: { currGS.dashPattern.first.clear(); PdfArray dashArr = args[0].GetArray(); for (int i=0; i<dashArr.size(); ++i) currGS.dashPattern.first.append(dashArr[i].GetNumber()); currGS.dashPattern.second = args[0].GetNumber(); } break; case KW_g: if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); currGS.fillCS = CS_DeviceGray; currGS.fillColor.clear(); currGS.fillColor.append(args[0].GetReal()); break; case KW_G: if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); currGS.strokeCS = CS_DeviceGray; currGS.strokeColor.clear(); currGS.strokeColor.append(args[0].GetReal()); break; case KW_rg: if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); currGS.fillCS = CS_DeviceRGB; currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) currGS.fillColor.append(args[i].GetReal()); break; case KW_RG: if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); currGS.strokeCS = CS_DeviceRGB; currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) currGS.strokeColor.append(args[i].GetReal()); break; case KW_k: if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); currGS.fillCS = CS_DeviceCMYK; currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) currGS.fillColor.append(args[i].GetReal()); break; case KW_K: if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); currGS.strokeCS = CS_DeviceCMYK; currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) currGS.strokeColor.append(args[i].GetReal()); break; case KW_cs: { if (args.size() == 1 && args[0].IsName()) { if (args[0].GetName() == "DeviceGray") { currGS.fillCS = CS_DeviceGray; currGS.fillColor.clear(); currGS.fillColor.append(0); if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); } else if (args[0].GetName() == "DeviceRGB") { currGS.fillCS = CS_DeviceRGB; currGS.fillColor.clear(); for (int i=0; i<3; ++i) currGS.fillColor.append(0); if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); } else if (args[0].GetName() == "DeviceCMYK") { currGS.fillCS = CS_DeviceCMYK; currGS.fillColor.clear(); for (int i=0; i<3; ++i) currGS.fillColor.append(0); currGS.fillColor.append(1); if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); } else if (args[0].GetName() == "Pattern") { currGS.fillCS = CS_Pattern; if (!usedColorSpaces.contains(CS_Pattern)) usedColorSpaces.append(CS_Pattern); } else { if (processedNamedCS.contains(args[0].GetName())) { currGS.fillCS = processedNamedCS.value(args[0].GetName()); } else { if (colorSpaceRes && colorSpaceRes->GetIndirectKey(args[0].GetName())) { PdfObject* csEntry = colorSpaceRes->GetIndirectKey(args[0].GetName()); PDFColorSpace retval = getCSType(csEntry); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); currGS.fillCS = retval; processedNamedCS.insert(args[0].GetName(), retval); } else { qDebug() << "Supplied colorspace is undefined!"; return false; } } } } else { qDebug() << "Wrong syntax in specifying color space!"; return false; } } break; case KW_CS: { if (args.size() == 1 && args[0].IsName()) { if (args[0].GetName() == "DeviceGray") { currGS.strokeCS = CS_DeviceGray; currGS.strokeColor.clear(); currGS.strokeColor.append(0); if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); } else if (args[0].GetName() == "DeviceRGB") { currGS.fillCS = CS_DeviceRGB; currGS.strokeColor.clear(); for (int i=0; i<3; ++i) currGS.strokeColor.append(0); if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); } else if (args[0].GetName() == "DeviceCMYK") { currGS.fillCS = CS_DeviceCMYK; currGS.strokeColor.clear(); for (int i=0; i<3; ++i) currGS.strokeColor.append(0); currGS.strokeColor.append(1); if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); } else if (args[0].GetName() == "Pattern") { currGS.fillCS = CS_Pattern; if (!usedColorSpaces.contains(CS_Pattern)) usedColorSpaces.append(CS_Pattern); } else { if (processedNamedCS.contains(args[0].GetName())) { currGS.strokeCS = processedNamedCS.value(args[0].GetName()); } else { if (colorSpaceRes && colorSpaceRes->GetIndirectKey(args[0].GetName())) { PdfObject* csEntry = colorSpaceRes->GetIndirectKey(args[0].GetName()); PDFColorSpace retval = getCSType(csEntry); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); currGS.strokeCS = retval; processedNamedCS.insert(args[0].GetName(), retval); } else { qDebug() << "Supplied colorspace is undefined!"; return false; } } } } else { qDebug() << "Wrong syntax in specifying color space!"; return false; } } break; case KW_sc: currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) currGS.fillColor.append(args[i].GetReal()); break; case KW_SC: currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) currGS.strokeColor.append(args[i].GetReal()); break; case KW_scn: currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) { if (args[i].IsReal() || args[i].IsNumber()) currGS.fillColor.append(args[i].GetReal()); } break; case KW_SCN: currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) { if (args[i].IsReal() || args[i].IsNumber()) currGS.strokeColor.append(args[i].GetReal()); } break; case KW_Do: // image or form XObject { if (!processedNamedXObj.contains(args[0].GetName())) { if (args.size() == 1 && args[0].IsName() && xObjects) { PdfObject* xObject = xObjects->GetIndirectKey(args[0].GetName()); PdfObject* subtypeObject = xObject?xObject->GetIndirectKey("Subtype"):NULL; if (subtypeObject && subtypeObject->IsName()) { if (subtypeObject->GetName() == "Image") { PdfObject* imgColorSpace = xObject->GetIndirectKey("ColorSpace"); if (imgColorSpace) { PDFColorSpace retval = getCSType(imgColorSpace); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); } PdfObject* sMaskObj = xObject->GetIndirectKey("SMask"); if (sMaskObj) hasTransparency = true; PDFImage img; img.imgName = args[0].GetName().GetEscapedName().c_str(); double width = xObject->GetIndirectKey("Width")->GetReal(); double height = xObject->GetIndirectKey("Height")->GetReal(); img.dpiX = qRound(width/(currGS.ctm.m11()/72)); img.dpiY = qRound(height/(currGS.ctm.m22()/72)); imgs.append(img); } else if (subtypeObject->GetName() == "Form") { PdfXObject xObj(xObject); inspectCanvas(&xObj, usedColorSpaces, hasTransparency, usedFonts, imgs); // recursive call } } else { qDebug() << "Supplied external object is undefined!"; return false; } processedNamedXObj.append(args[0].GetName()); } else { qDebug() << "Wrong syntax for Do operator or there's no XObject defined!"; return false; } } } break; case KW_BI: inlineImgDict = true; break; case KW_ID: if (inlineImgDict) { PdfName colorspace("ColorSpace"); PdfName cs("CS"); if (args.contains(colorspace) || args.contains(cs)) { int csIdx = args.contains(colorspace)?args.indexOf(colorspace):args.indexOf(cs); if (args[csIdx+1].IsName()) { PdfName csName = args[csIdx+1].GetName(); if ((csName == "G" || csName == "DeviceGray") && !usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); else if ((csName == "RGB" || csName == "DeviceRGB") && !usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); else if ((csName == "CMYK" || csName == "DeviceCMYK") && !usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); else if (!processedNamedCS.contains(csName)) { if (colorSpaceRes && colorSpaceRes->GetIndirectKey(csName)) { PdfObject* csEntry = colorSpaceRes->GetIndirectKey(csName); if (csEntry) { PDFColorSpace retval = getCSType(csEntry); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); processedNamedCS.insert(csName, retval); } } else { qDebug() << "Supplied colorspace for inline image is undefined!"; return false; } } } } PdfName height("Height"); PdfName h("H"); PdfName width("Width"); PdfName w("W"); if ((args.contains(height) || args.contains(h)) && (args.contains(width) || args.contains(w))) { int heightIdx = args.contains(height)?args.indexOf(height):args.indexOf(h); int widthIdx = args.contains(width)?args.indexOf(width):args.indexOf(w); double height = args[heightIdx+1].GetReal(); double width = args[widthIdx+1].GetReal(); PDFImage img; img.imgName = "Inline Image"; img.dpiX = qRound(width/(currGS.ctm.m11()/72)); img.dpiY = qRound(height/(currGS.ctm.m22()/72)); imgs.append(img); } inlineImgDict = false; } break; case KW_gs: { if (!processedNamedGS.contains(args[0].GetName())) { if (args.size() == 1 && args[0].IsName() && extGState) { PdfObject* extGStateObj = extGState->GetIndirectKey(args[0].GetName()); if (extGStateObj) { inspectExtGStateObj(extGStateObj, usedColorSpaces, hasTransparency, usedFonts, currGS); } else { qDebug() << "Named graphic state used with gs operator is undefined in current ExtGState"; return false; } processedNamedGS.append(args[0].GetName()); } else { qDebug() << "Wrong syntax in applying extended graphic state (gs operator) or there's no ExtGState defined!"; return false; } } } break; case KW_Tf: { if (processedNamedFont.contains(args[0].GetName())) { currGS.font.first = processedNamedFont.value(args[0].GetName()); currGS.font.second = args[1].GetReal(); } else { if (args.size() == 2 && args[0].IsName() && fontRes) { PdfObject* fontObj = fontRes->GetIndirectKey(args[0].GetName()); if (fontObj) { PDFFont retval = getFontInfo(fontObj); usedFonts.append(retval); processedNamedFont.insert(args[0].GetName(), retval); currGS.font.first = retval; currGS.font.second = args[1].GetReal(); } else { qDebug() << "The specified font cannot be found in current Resources!"; return false; } } else { qDebug() << "Wrong syntax in use of Tf operator or there's no Font defined in current Resources dictionary!"; return false; } } } break; case KW_Undefined: default: break; } args.clear(); } } } catch (PdfError & e) { qDebug() << "Error in parsing content stream"; e.PrintErrorMsg(); return false; } return true; }
void PdfPagesTree::DeletePageNode( PdfObject* pParent, int nIndex ) { PdfArray kids = pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); kids.erase( kids.begin() + nIndex ); pParent->GetDictionary().AddKey( PdfName("Kids"), kids ); }
void PDFAnalyzer::inspectExtGStateObj(PdfObject* extGStateObj, QList<PDFColorSpace> & usedColorSpaces, bool & hasTransparency, QList<PDFFont> & usedFonts, PDFGraphicState & currGS) { PdfObject* bmObj = extGStateObj->GetIndirectKey("BM"); if (bmObj && bmObj->IsName()) { currGS.blendModes.clear(); currGS.blendModes.append(bmObj->GetName().GetEscapedName().c_str()); if (!(bmObj->GetName() == "Normal" || bmObj->GetName() == "Compatible")) hasTransparency = true; } else if (bmObj && bmObj->IsArray()) { PdfArray arr = bmObj->GetArray(); currGS.blendModes.clear(); for(int i=0; i<arr.GetSize(); ++i) currGS.blendModes.append(arr[i].GetName().GetEscapedName().c_str()); if (arr[0].IsName() && !(arr[0].GetName() == "Normal" || arr[0].GetName() == "Compatible")) hasTransparency = true; } PdfObject* caObj = extGStateObj->GetIndirectKey("ca"); if (caObj && (caObj->IsReal() || caObj->IsNumber())) { currGS.fillAlphaConstant = caObj->GetReal(); if (caObj->GetReal() < 1) hasTransparency = true; } PdfObject* cAObj = extGStateObj->GetIndirectKey("CA"); if (cAObj && (cAObj->IsReal() || cAObj->IsNumber())) { if (cAObj->GetReal() < 1) hasTransparency = true; } PdfObject* sMaskObj = extGStateObj->GetIndirectKey("SMask"); if (sMaskObj && !(sMaskObj->IsName() && sMaskObj->GetName() == "None")) hasTransparency = true; PdfObject* fontObj = extGStateObj->GetIndirectKey("Font"); if (fontObj && fontObj->IsArray()) { PdfArray arr = fontObj->GetArray(); if (arr[0].IsReference()) { PdfReference ref = arr[0].GetReference(); PdfObject* fontObject = m_doc->GetObjects().GetObject(ref); if (fontObject) { PDFFont font = getFontInfo(fontObject); usedFonts.append(font); currGS.font.first = font; currGS.font.second = arr[1].GetReal(); } } } PdfObject* lwObj = extGStateObj->GetIndirectKey("LW"); if (lwObj) currGS.lineWidth = lwObj->GetReal(); PdfObject* lcObj = extGStateObj->GetIndirectKey("LC"); if (lcObj) currGS.lineCap = lcObj->GetNumber(); PdfObject* ljObj = extGStateObj->GetIndirectKey("LJ"); if (ljObj) currGS.lineJoin = ljObj->GetNumber(); PdfObject* mlObj = extGStateObj->GetIndirectKey("ML"); if (mlObj) currGS.miterLimit = mlObj->GetReal(); PdfObject* dObj = extGStateObj->GetIndirectKey("D"); if (dObj) { PdfArray dashArr = dObj->GetArray()[0]; currGS.dashPattern.first.clear(); for (int i=0; i<dashArr.GetSize(); ++i) currGS.dashPattern.first.append(dashArr[i].GetNumber()); currGS.dashPattern.second = dObj->GetArray()[1].GetNumber(); } }
void PdfMemStream::FlateCompress() { PdfObject* pObj; PdfVariant vFilter( PdfName("FlateDecode" ) ); PdfVariant vFilterList; PdfArray tFilters; PdfArray::const_iterator tciFilters; if( !m_lLength ) return; // ePdfError_ErrOk // TODO: Handle DecodeParms if( m_pParent->GetDictionary().HasKey( "Filter" ) ) { pObj = m_pParent->GetIndirectKey( "Filter" ); if( pObj->IsName() ) { if( pObj->GetName() != "DCTDecode" && pObj->GetName() != "FlateDecode" ) { tFilters.push_back( vFilter ); tFilters.push_back( *pObj ); } } else if( pObj->IsArray() ) { tciFilters = pObj->GetArray().begin(); while( tciFilters != pObj->GetArray().end() ) { if( (*tciFilters).IsName() ) { // do not compress DCTDecoded are already FlateDecoded streams again if( (*tciFilters).GetName() == "DCTDecode" || (*tciFilters).GetName() == "FlateDecode" ) { return; } } ++tciFilters; } tFilters.push_back( vFilter ); tciFilters = pObj->GetArray().begin(); while( tciFilters != pObj->GetArray().end() ) { tFilters.push_back( (*tciFilters) ); ++tciFilters; } } else return; vFilterList = PdfVariant( tFilters ); m_pParent->GetDictionary().AddKey( "Filter", vFilterList ); FlateCompressStreamData(); // throws an exception on error } else { m_pParent->GetDictionary().AddKey( "Filter", PdfName( "FlateDecode" ) ); FlateCompressStreamData(); } }
void PdfTilingPattern::Init( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage) { if (eTilingType == ePdfTilingPatternType_Image && pImage == NULL) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if (eTilingType != ePdfTilingPatternType_Image && pImage != NULL) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRect rRect; rRect.SetLeft(0); rRect.SetBottom(0); if (pImage) { rRect.SetWidth(pImage->GetWidth()); rRect.SetHeight(-pImage->GetHeight()); } else { rRect.SetWidth(8); rRect.SetHeight(8); } PdfVariant var; rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( PdfName("PatternType"), static_cast<pdf_int64>(1L) ); // Tiling pattern this->GetObject()->GetDictionary().AddKey( PdfName("PaintType"), static_cast<pdf_int64>(1L) ); // Colored this->GetObject()->GetDictionary().AddKey( PdfName("TilingType"), static_cast<pdf_int64>(1L) ); // Constant spacing this->GetObject()->GetDictionary().AddKey( PdfName("BBox"), var ); this->GetObject()->GetDictionary().AddKey( PdfName("XStep"), static_cast<pdf_int64>(rRect.GetWidth()) ); this->GetObject()->GetDictionary().AddKey( PdfName("YStep"), static_cast<pdf_int64>(rRect.GetHeight()) ); this->GetObject()->GetDictionary().AddKey( PdfName("Resources"), PdfObject( PdfDictionary() ) ); if (offsetX < -1e-9 || offsetX > 1e-9 || offsetY < -1e-9 || offsetY > 1e-9) { PdfArray array; array.push_back (static_cast<pdf_int64>(1)); array.push_back (static_cast<pdf_int64>(0)); array.push_back (static_cast<pdf_int64>(0)); array.push_back (static_cast<pdf_int64>(1)); array.push_back (offsetX); array.push_back (offsetY); this->GetObject()->GetDictionary().AddKey( PdfName("Matrix"), array ); } std::ostringstream out; out.flags( std::ios_base::fixed ); out.precision( 1L /* clPainterDefaultPrecision */ ); PdfLocaleImbue(out); if (pImage) { AddToResources(pImage->GetIdentifier(), pImage->GetObjectReference(), PdfName("XObject")); out << rRect.GetWidth() << " 0 0 " << rRect.GetHeight() << " " << rRect.GetLeft() << " " << rRect.GetBottom() << " cm" << std::endl; out << "/" << pImage->GetIdentifier().GetName() << " Do" << std::endl; } else { if (doFill) { out << fillR << " " << fillG << " " << fillB << " rg" << " "; out << rRect.GetLeft() << " " << rRect.GetBottom() << " " << rRect.GetWidth() << " " << rRect.GetHeight() << " re" << " "; out << "f" << " "; //fill rect } out << strokeR << " " << strokeG << " " << strokeB << " RG" << " "; out << "2 J" << " "; // line capability style out << "0.5 w" << " "; //line width double left, bottom, right, top, whalf, hhalf; left = rRect.GetLeft(); bottom = rRect.GetBottom(); right = left + rRect.GetWidth(); top = bottom + rRect.GetHeight(); whalf = rRect.GetWidth() / 2; hhalf = rRect.GetHeight() / 2; switch (eTilingType) { case ePdfTilingPatternType_BDiagonal: out << left << " " << bottom << " m " << right << " " << top << " l "; out << left - whalf << " " << top - hhalf << " m " << left + whalf << " " << top + hhalf << " l "; out << right - whalf << " " << bottom - hhalf << " m " << right + whalf << " " << bottom + hhalf << " l" << std::endl; break; case ePdfTilingPatternType_Cross: out << left << " " << bottom + hhalf << " m " << right << " " << bottom + hhalf << " l "; out << left + whalf << " " << bottom << " m " << left + whalf << " " << top << " l" << std::endl; break; case ePdfTilingPatternType_DiagCross: out << left << " " << bottom << " m " << right << " " << top << " l "; out << left << " " << top << " m " << right << " " << bottom << " l" << std::endl; break; case ePdfTilingPatternType_FDiagonal: out << left << " " << top << " m " << right << " " << bottom << " l "; out << left - whalf << " " << bottom + hhalf << " m " << left + whalf << " " << bottom - hhalf << " l "; out << right - whalf << " " << top + hhalf << " m " << right + whalf << " " << top - hhalf << " l" << std::endl; break; case ePdfTilingPatternType_Horizontal: out << left << " " << bottom + hhalf << " m " << right << " " << bottom + hhalf << " l "; break; case ePdfTilingPatternType_Vertical: out << left + whalf << " " << bottom << " m " << left + whalf << " " << top << " l" << std::endl; break; case ePdfTilingPatternType_Image: /* This is handled above, based on the 'pImage' variable */ default: PODOFO_RAISE_ERROR (ePdfError_InvalidEnumValue); break; } out << "S"; //stroke path } TVecFilters vecFlate; vecFlate.push_back( ePdfFilter_FlateDecode ); std::string str = out.str(); PdfMemoryInputStream stream(str.c_str(), str.length()); this->GetObject()->GetStream()->Set(&stream, vecFlate); }