Earlier, I wrote:

> I'll grab the sources and check out a few ideas re packaging etc.

After reading the code I think de-Qt-izing it will indeed be the best
choice. I've mostly done that now, but have a few bits left and no doubt
some testing required.

I've included a few cleanups along the way, primarily switching to the
use of C++ streams for the generation of PDF content streams rather than
assembling them by concatenating strings.

An initial diff is attached. It builds and runs a couple of test files,
but isn't fully checked yet. No memory debugger run has been done and I
haven't tested with a debug STL yet. Basic output matches, though, and
no Qt is required.

The CMakeLists.txt has hard-coded paths to my podofo include directory
and library. It's just a quick and dirty one I put together to get
things going, since we'll probably want to include this in tools/ in
podofo anyway.

I might've been a little heavy handed with the conversion in a few
places, but there are some cleanups too, so it should balance out ;-)

--
Craig Ringer
Index: charpainter.cpp
===================================================================
--- charpainter.cpp     (revision 33)
+++ charpainter.cpp     (working copy)
@@ -19,77 +19,70 @@
  ***************************************************************************/
 #include "charpainter.h"
 
-CharPainter::CharPainter()
-{
-}
+#include <vector>
+using std::vector;
+using std::ostream;
+using std::string;
 
+namespace {
 
-CharPainter::~CharPainter()
-{
-}
+    // write the digits of `n' to `d'. The digits are ordered by increasing
+    // place value.
+    void digits(int n, vector<int> & d)
+    {
+        while ( n > 0 )
+        {
+            d.push_back(n % 10);
+            n = n / 10;
+        }
+    }
 
+}; // end anon namespace
 
-
-
-QString CharPainter::paint(QChar c, double size)
+using namespace std;
+void CharPainter::paint(ostream & s, int n, double size, double x, double y)
 {
-       //todo
-       
-}
+    // update working variables used by topleft() etc
+    m_y = y;
+    m_x = x;
+    m_size = size;
+    m_sh = m_size + m_y;
+    m_midh = (m_size /2.0) + m_y;
+    m_sw = (m_size /2.0) + m_x;
 
-QString CharPainter::paint(int n, double size, double x, double y)
-{
-       double sh = size + y;
-       double midh = (size /2.0) + y;
-       double sw = (size /2.0) + x;
-       QString ret;
-       QString top(QString("%3 %1 m\n%2 %1 l\n").arg(sh).arg(sw).arg(x));
-       
-       QString topright(QString("%2 %1 m\n%2 %3 
l\n").arg(sh).arg(sw).arg(midh));
-       QString bottomright(QString("%1 %2 m\n%1 %3 
l\n").arg(sw).arg(midh).arg(y));
-       
-       QString bottom(QString("%2 %3 m\n%1 %3 l\n").arg(sw).arg(x).arg(y));
-       
-       QString bottomleft(QString("%1 %2 m\n%1 %3 
l\n").arg(x).arg(y).arg(midh));
-       QString topleft(QString("%2 %3 m\n%2 %1 l\n").arg(sh).arg(x).arg(midh));
-       
-       QString center(QString("%2 %3 m\n%1 %3 l\n").arg(sw).arg(x).arg(midh));
-       switch(n)
-       {
-               case 1 : ret = topright + bottomright;
-               break;
-               case 2 : ret = top + topright + center + bottomleft + bottom;
-               break;
-               case 3 : ret = top + topright + bottomright + bottom + center;
-               break;
-               case 4 : ret = topleft + center + bottomright + topright;
-               break;
-               case 5 : ret = top + topleft + center + bottomright + bottom;
-               break;
-               case 6 : ret =  top + topleft + center + bottomright + bottom + 
bottomleft;
-               break ;
-               case 7 : ret = top + topright + bottomright;
-               break;
-               case 8 : ret = top + topleft + center + bottomright + bottom + 
bottomleft + topright ;
-               break;
-               case 9 : ret =top + topleft + center + bottomright + bottom + 
topright ;
-               break;
-               case 0 : ret =  top + topleft +  bottomright + bottom + 
bottomleft + topright ;
-       }
-       
-       ret += "S\n";
-       return ret;
+    switch(n)
+    {
+        case 1 :  topright(s); bottomright(s);
+                  break;
+        case 2 :  top(s); topright(s); center(s); bottomleft(s); bottom(s);
+                  break;
+        case 3 :  top(s); topright(s); bottomright(s); bottom(s); center(s);
+                  break;
+        case 4 :  topleft(s); center(s); bottomright(s); topright(s);
+                  break;
+        case 5 :  top(s); topleft(s); center(s); bottomright(s); bottom(s);
+                  break;
+        case 6 :  top(s); topleft(s); center(s); bottomright(s); bottom(s); 
bottomleft(s);
+                  break;
+        case 7 :  top(s); topright(s); bottomright(s);
+                  break;
+        case 8 :  top(s); topleft(s); center(s); bottomright(s); bottom(s); 
bottomleft(s); topright(s);
+                  break;
+        case 9 :  top(s); topleft(s); center(s); bottomright(s); bottom(s); 
topright(s);
+                  break;
+        case 0 :  top(s); topleft(s);  bottomright(s); bottom(s); 
bottomleft(s); topright(s);
+                  break;
+    }
+    s << "S\n";
 }
 
-QString CharPainter::multipaint(int n, double size ,double x, double y)
+void CharPainter::multipaint(ostream& s, int n, double size, double x, double 
y)
 {
-       QString s = QString("%1").arg(n);
-       QString ret;
-       for(int i = 0; i < s.count(); ++i)
-       {
-               ret += paint(s.mid(i,1).toInt(), size, x + (size * i / 1.6), y);
-       }
-//     qDebug(ret.toAscii());
-       return ret;
-       
-}
\ No newline at end of file
+    vector<int> d;
+    digits(n, d);
+
+    vector<int>::const_reverse_iterator itEnd = d.rend();
+    int i = d.size() - 1;
+    for ( vector<int>::const_reverse_iterator it = d.rbegin(); it != itEnd; 
++it, --i )
+        paint(s, *it, size, x + (size * i / 1.6), y );
+}
Index: pdftranslator.cpp
===================================================================
--- pdftranslator.cpp   (revision 33)
+++ pdftranslator.cpp   (working copy)
@@ -20,296 +20,326 @@
 #include "pdftranslator.h"
 #include "charpainter.h"
 
-#include <QFile>
-#include <QTextStream>
-#include <QStringList>
-#include <QDebug>
-#include <QByteArray>
-#include <QDataStream>
-#include <QFile>
-#include <math.h>
+#include <fstream>
+#include <stdexcept>
+#include <algorithm>
+#include <cmath>
+#include <istream>
+#include <ostream>
+using std::ostringstream;
+using std::map;
+using std::vector;
+using std::string;
+using std::ifstream;
+using std::istream;
+using std::ostream;
+using std::endl;
+using std::runtime_error;
 
-PdfTranslator::PdfTranslator(double sp)
+#include <iostream> //XXX
+
+PageRecord::PageRecord ( int s,int d,double r, double tx, double ty )
+    : sourcePage ( s ),
+    destPage ( d ),
+    rotate ( r ),
+    transX ( tx ),
+    transY ( ty )
 {
-       sourceDoc = 0;
-       targetDoc = 0;
-       extraSpace = sp;
+};
 
+PageRecord::PageRecord()
+    : sourcePage(0),
+    destPage(0),
+    rotate(0),
+    transX(0),
+    transY(0)
+{};
+
+istream & operator>>(istream& s, PageRecord& r)
+{
+    s >> r.sourcePage >> r.destPage >> r.rotate >> r.transX >> r.transY;
+    // TODO: set invalid if stream state bad
+    return s;
 }
 
+ostream & operator<<(ostream& s, const PageRecord& r)
+{
+    return s << r.sourcePage << r.destPage << r.rotate << r.transX << r.transY 
<< endl;
+}
 
-PdfTranslator::~PdfTranslator()
-{}
+bool PageRecord::isValid() const
+{
+    //TODO
+    return true;
+}
 
-void PdfTranslator::setSource ( QString source )
+
+
+
+PdfTranslator::PdfTranslator(double sp)
 {
-       qDebug() << "setSource "<< source;
-       sourceDoc = new PdfMemDocument ( source.toLocal8Bit () );
-       input = source;
-       qDebug() <<"setSource completed";
+    sourceDoc = 0;
+    targetDoc = 0;
+    extraSpace = sp;
 }
 
-void PdfTranslator::setTarget ( QString target )
+void PdfTranslator::setSource ( const std::string & source )
 {
-       qDebug() << "setTarget " << target ;
-       if ( !sourceDoc )
-               return;
+    inFilePath = source;
+    sourceDoc = new PdfMemDocument ( inFilePath.c_str() ); // must succeed or 
throw
+}
 
-       targetDoc = new PdfMemDocument ( input.toLocal8Bit () );
-       output  = target;
-       pcount = targetDoc->GetPageCount();
+void PdfTranslator::setTarget ( const std::string & target )
+{
+    if ( !sourceDoc )
+        throw std::logic_error("setTarget() called before setSource()");
 
-//     PdfFont *f = targetDoc->CreateFont( "Sans-serif" , false);
-//     
-//     useFont = f->GetIdentifier().GetName().c_str();
-//     useFontRef = f->GetObject()->Reference();
-//     
+    // DOCUMENT: Setting `targetDoc' to the input path will be confusing when 
reading the code.
+    targetDoc = new PdfMemDocument ( inFilePath.c_str() );
+    outFilePath  = target;
+    pcount = targetDoc->GetPageCount();
 
+    for ( int i = 0; i < pcount ; ++i )
+    {
+        PdfPage * page = targetDoc->GetPage ( i );
+        PdfMemoryOutputStream outMemStream ( 1 );
 
-       for ( int i = 0; i < pcount ; ++i )
-       {
-               PdfPage * page = targetDoc->GetPage ( i );
-               PdfMemoryOutputStream outMemStream ( 1 );
+        PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc );
+        page->GetContents()->GetStream()->GetFilteredCopy ( &outMemStream );
+        outMemStream.Close();
 
-               PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), 
targetDoc );
-               page->GetContents()->GetStream()->GetFilteredCopy ( 
&outMemStream );
-               outMemStream.Close();
+        PdfMemoryInputStream inStream ( 
outMemStream.TakeBuffer(),outMemStream.GetLength() );
+        xobj->GetContents()->GetStream()->Set ( &inStream );
 
-               PdfMemoryInputStream inStream ( 
outMemStream.TakeBuffer(),outMemStream.GetLength() );
-               xobj->GetContents()->GetStream()->Set ( &inStream );
+        // I should get /Ressource dict...
 
-               // I should get /Ressource dict...
+        // Getting resources from Pages node this way is suitable for Scribus 
PDF, that's it.
+        PdfObject *rparent = page->GetObject()->GetDictionary().GetKey ( 
PdfName ( "Parent" ) );
+        if ( rparent )
+        {
+            PdfReference ref = rparent->GetReference();
+            //qDebug() << "has Parent ref";
+            PdfVecObjects objs = targetDoc->GetObjects();
+            //qDebug() << "get obj Parent";
+            PdfObject *parent = objs.GetObject ( ref );
+            PdfObject *gres = parent->GetDictionary().GetKey ( "Resources" );
+            if(gres)
+                globalResRef = gres->GetReference();
+        }
+        else
+        {
+            //qDebug() << "This page has no parent ?";
+            TKeyMap rkeys = page->GetObject()->GetDictionary().GetKeys();
+            TCIKeyMap itk = rkeys.begin();
+            while ( itk != rkeys.end() )
+            {
+                //qDebug() << itk->first.GetName().c_str() ;
+                ++itk;
+            }
+        }
 
-               qDebug() << "get Parent";
-               // Getting resources from Pages node this way is suitable for 
Scribus PDF, that's it.
-               PdfObject *rparent = page->GetObject()->GetDictionary().GetKey 
( PdfName ( "Parent" ) );
-               if ( rparent )
-               {
-                       PdfReference ref = rparent->GetReference();
-                       qDebug() << "has Parent ref";
-                       PdfVecObjects objs = targetDoc->GetObjects();
-                       qDebug() << "get obj Parent";
-                       PdfObject *parent = objs.GetObject ( ref );
-                       PdfObject *gres = parent->GetDictionary().GetKey ( 
"Resources" );
-                       if(gres)
-                               globalResRef = gres->GetReference();
-               }
-               else
-               {
-                       qDebug() << "This page has no parent ?";
-                       TKeyMap rkeys = 
page->GetObject()->GetDictionary().GetKeys();
-                       TCIKeyMap itk = rkeys.begin();
-                       while ( itk != rkeys.end() )
-                       {
-                               qDebug() << itk->first.GetName().c_str() ;
-                               ++itk;
-                       }
-               }
-//
-               xobjects.insert ( i + 1, xobj );
-               trimRect.insert(i + 1, page->GetTrimBox());
-               bleedRect.insert(i + 1,page->GetBleedBox());
-       }
-       qDebug() <<"setTarget completed";
+        xobjects[i+1] = xobj;
+        trimRect[i+1] = page->GetTrimBox();
+        bleedRect[i+1] = page->GetBleedBox();
+    }
 }
 
-void PdfTranslator::loadPlan ( QString plan )
+void PdfTranslator::loadPlan ( const std::string & plan )
 {
-       qDebug() << "loadPlan " << plan;
-       // headline must be :
-       // "target page width" "target page height"
-       // pagerecord must be :
-       // "source page" "dest page" "rotation" "horiz. translation" "vert. 
translation"
-       // ex.: 1 2 90 500 0 <newline>
+    // headline must be :
+    // "target page width" "target page height"
+    // pagerecord must be :
+    // "source page" "dest page" "rotation" "horiz. translation" "vert. 
translation"
+    // ex.: 1 2 90 500 0 <newline>
 
-       QFile file ( plan );
-       if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
-               return;
+    ifstream in ( plan.c_str(), ifstream::in );
+    if (!in.good())
+        throw runtime_error("Failed to open plan file");
 
-       QTextStream in ( &file );
-       bool first = true;
-       int dup = 40000;
-       QString line;
-       do
-       {
-               line = in.readLine();
-               qDebug ( line.toAscii() );
-               if ( first )
-               {
-                       QStringList list = line.split ( ' ' );
-                       destWidth = list[0].toDouble();
-                       destHeight = list[1].toDouble();
-                       first = false;
-                       continue;
-               }
-               QStringList list = line.split ( ' ' );
-               if ( list.count() != 5 )
-               {
-                       break;
-               }
-               PageRecord p ( list[0].toInt(), list[1].toInt(), 
list[2].toDouble(), list[3].toDouble(),list[4].toDouble() );
-               maxPageDest = qMax ( maxPageDest, list[1].toInt() );
-               if(pagesIndex.contains(p.sourcePage))
-               {
-                       qDebug() << "duplicate "<< p.sourcePage << " in " << 
dup;
-                       
-                       PdfXObject *xobj = new 
PdfXObject(targetDoc->GetPage(p.sourcePage - 1)->GetMediaBox(), targetDoc );
-                       PdfMemoryOutputStream outMemStream ( 1 );
-                       
xobjects[p.sourcePage]->GetContents()->GetStream()->GetFilteredCopy ( 
&outMemStream );
-                       outMemStream.Close();
-                       PdfMemoryInputStream inStream ( 
outMemStream.TakeBuffer(),outMemStream.GetLength() );
-                       xobj->GetContents()->GetStream()->Set(&inStream);
-                       
-                       xobjects.insert(dup, xobj);
-                       trimRect.insert(dup, targetDoc->GetPage(p.sourcePage - 
1)->GetTrimBox());
-                       bleedRect.insert(dup, targetDoc->GetPage(p.sourcePage - 
1)->GetBleedBox());
-                       p.sourcePage = dup;
-                       ++dup;
-               }
-               planImposition.append ( p );
-               pagesIndex.insert ( p.sourcePage, planImposition.count() - 1 );
+    bool first = true;
+    int dup = 40000;
+    std::string line;
+    do
+    {
+        if ( first )
+        {
+            in >> destWidth;
+            in >> destHeight;
+            if (!in.good())
+                throw runtime_error("Bad plan file header");
+            first = false;
+            continue;
+        }
+        int sourcePage;
 
-       }
-       while ( !line.isNull() );
-       qDebug() <<"loadPlan completed";
+        PageRecord p;
+        in >> p;
+        if (in.eof())
+            break;
+        if (!p.isValid())
+            throw runtime_error("Bad plan file record");
+
+        maxPageDest = std::max ( maxPageDest, p.destPage );
+        if( pagesIndex.find( p.sourcePage ) != pagesIndex.end() )
+        {
+            //qDebug() << "duplicate "<< p.sourcePage << " in " << dup;
+
+            PdfXObject *xobj = new PdfXObject(targetDoc->GetPage(p.sourcePage 
- 1)->GetMediaBox(), targetDoc );
+            PdfMemoryOutputStream outMemStream ( 1 );
+            
xobjects[p.sourcePage]->GetContents()->GetStream()->GetFilteredCopy ( 
&outMemStream );
+            outMemStream.Close();
+            PdfMemoryInputStream inStream ( 
outMemStream.TakeBuffer(),outMemStream.GetLength() );
+            xobj->GetContents()->GetStream()->Set(&inStream);
+
+            xobjects[dup] = xobj;
+            trimRect[dup] = targetDoc->GetPage(p.sourcePage - 1)->GetTrimBox();
+            bleedRect[dup] = targetDoc->GetPage(p.sourcePage - 
1)->GetBleedBox();
+            p.sourcePage = dup;
+            ++dup;
+        }
+        planImposition.push_back ( p );
+        pagesIndex[p.sourcePage] = planImposition.size() - 1;
+    }
+    while ( !in.eof() );
 }
 
 void PdfTranslator::impose()
 {
-       qDebug ( "impose" );
-       if ( !sourceDoc )
-               return;
-       if ( !targetDoc )
-               return;
-       
-       PdfDictionary globalRes ;
+    if ( ! (sourceDoc && targetDoc) )
+        throw std::invalid_argument("impose() called with empty source or 
destination path");
 
-       double  pw = destWidth + (2.0 * extraSpace) ;
-       double  ph = destHeight  + (2.0 * extraSpace);
-       
-       PdfObject trimbox;
-       PdfRect trim(extraSpace, extraSpace, destWidth, destHeight);
-       trim.ToVariant(trimbox);
-       
-       QMap<int, QList<int> > groups;
-       for ( int i = 0; i < planImposition.count(); ++i )
-       {
-               groups[planImposition[i].destPage].append ( 
planImposition[i].sourcePage );
-       }
+    PdfDictionary globalRes;
 
-       QMap<int, QList<int> >::iterator  git = groups.begin();
-       while ( git != groups.end() )
-       {
-               qDebug() << "Perform destination page " << git.key() << 
git.value();
-               PdfPage * newpage = targetDoc->CreatePage ( PdfRect ( 0.0, 
0.0,pw ,ph ) );
-               newpage->GetObject()->GetDictionary().AddKey( 
PdfName("TrimBox"), trimbox);
-               PdfDictionary xdict;
+    double pw = destWidth + (2.0 * extraSpace) ;
+    double ph = destHeight  + (2.0 * extraSpace);
 
-//             PdfMemoryOutputStream outMemStream ( 1 );
-               QByteArray buffer;
-               QString doBuffer;
-//             doBuffer.append ( QString ( "1 0 0 1 %1 %1 cm\n" ).arg ( 
extraSpace));
-               for ( int i = 0; i < git.value().count(); ++i )
-               {
+    PdfObject trimbox;
+    PdfRect trim(extraSpace, extraSpace, destWidth, destHeight);
+    trim.ToVariant(trimbox);
 
-                       int curPage = git.value()[i]; 
-//                     int rec = curPage;
-//                     if( curPage > 39999)
-//                     {
-//                             curPage =  virtualMap.value(git.value()[i]) ;
-//                     }
-                       
-                       int index = pagesIndex.value ( curPage );
-                       PdfRect rect = trimRect.value(curPage);
-                       PdfRect bleed = bleedRect.value(curPage);
-                       qDebug() << "Perform source page " << curPage << index;
+    typedef map<int, vector<int> > groups_t;
+    groups_t groups;
+    for ( int i = 0; i < planImposition.size(); ++i )
+    {
+        groups[planImposition[i].destPage].push_back ( 
planImposition[i].sourcePage );
+    }
 
-                       PdfArray matrix;
-                       
-                               double cosR = cos ( 
planImposition[index].rotate  *  3.14159 / 180 );
-                               double sinR = sin ( 
planImposition[index].rotate  *  3.14159 / 180 );
-                               double tx = planImposition[index].transX + 
extraSpace;
-                               double ty = planImposition[index].transY + 
extraSpace;
-                               
-                               matrix.insert ( matrix.end(), PdfObject ( cosR 
) );
-                               matrix.insert ( matrix.end(), PdfObject ( sinR 
) );
-                               matrix.insert ( matrix.end(), PdfObject ( -sinR 
) );
-                               matrix.insert ( matrix.end(), PdfObject ( cosR 
) );
-                               matrix.insert ( matrix.end(), PdfObject ( tx ) 
);
-                               matrix.insert ( matrix.end(), PdfObject ( ty ) 
);
+    groups_t::const_iterator  git = groups.begin();
+    const groups_t::const_iterator gitEnd = groups.end();
+    while ( git != gitEnd )
+    {
+        //qDebug() << "Perform destination page " << git.key() << git.value();
+        PdfPage * newpage = targetDoc->CreatePage ( PdfRect ( 0.0, 0.0, pw, ph 
) );
+        newpage->GetObject()->GetDictionary().AddKey( PdfName("TrimBox"), 
trimbox);
+        PdfDictionary xdict;
 
-                       
-                       PdfName mname ( "Matrix" );
-                       PdfXObject *xo = xobjects.value ( curPage );
-                       PdfName xname ( QString ( "OriginalPage%1 " ).arg ( 
curPage ).toAscii() );
-                       xdict.AddKey ( xname, xo->GetObjectReference() );
-                       xo->GetContents()->GetDictionary().AddKey ( mname, 
PdfObject ( matrix ) );
-                       xo->GetContents()->GetDictionary().AddKey ( PdfName ( 
"Resources" ), globalResRef );
-                       doBuffer.append ( QString ( "/OriginalPage%1 Do\n" 
).arg ( curPage ));
-                       
-                       double top = rect.GetHeight() + rect.GetBottom() + ty ;
-                       double bottom = rect.GetBottom() + ty;
-                       double left = rect.GetLeft() + tx;
-                       double right = rect.GetWidth() + rect.GetLeft() + tx;
-                       
-                       double btop = bleed.GetHeight() + bleed.GetBottom() + 
ty ;
-                       double bbottom = bleed.GetBottom() + ty;
-                       double bleft = bleed.GetLeft() + tx;
-                       double bright = bleed.GetWidth() + bleed.GetLeft() + tx;
-                       
-                       
-                       drawLine(0,top ,bleft, top , &buffer);
-                       drawLine(0, bottom , bleft, bottom, &buffer);
-                       
-                       drawLine(pw , top , bright , top, &buffer);
-                       drawLine(pw, bottom , bright ,bottom, &buffer);
-                       
-                       drawLine(left,0, left , bbottom,  &buffer);
-                       drawLine(right, 0 ,right, bbottom, &buffer);
-                       
-                       drawLine(left , ph ,left ,btop, &buffer);
-                       drawLine(right, ph ,right, btop, &buffer);
-                       
-                       
-                       
-               }
-               
-               
-               signature(extraSpace / 2.0 , extraSpace / 10.0, git.key(), 
git.value(),&buffer);
-               buffer.append(doBuffer);
-               newpage->GetContentsForAppending()->GetStream()->Set ( 
buffer.constData(),buffer.size() );
-               PdfName dname ( "XObject" );
-               newpage->GetResources()->GetDictionary().AddKey ( dname, xdict 
);
-               ++git;
-       }
-       targetDoc->DeletePages ( 0,pcount );
-       qDebug() << output <<" has " << targetDoc->GetPageCount() << " pages.";
-       targetDoc->Write ( output.toAscii() );
+        ostringstream buffer;
+        vector<int> pages;
+        for ( int i = 0; i < (*git).second.size(); ++i )
+        {
 
+            int curPage = (*git).second[i]; 
+            //                         int rec = curPage;
+            //                         if( curPage > 39999)
+            //                         {
+            //                                 curPage =  
virtualMap.value(git.value()[i]) ;
+            //                         }
+
+            int index = pagesIndex[curPage];
+            PdfRect rect = trimRect[curPage];
+            PdfRect bleed = bleedRect[curPage];
+            //qDebug() << "Perform source page " << curPage << index;
+
+            PdfArray matrix;
+
+            double cosR = cos ( planImposition[index].rotate  *  3.14159 / 180 
);
+            double sinR = sin ( planImposition[index].rotate  *  3.14159 / 180 
);
+            double tx = planImposition[index].transX + extraSpace;
+            double ty = planImposition[index].transY + extraSpace;
+
+            matrix.insert ( matrix.end(), PdfObject ( cosR ) );
+            matrix.insert ( matrix.end(), PdfObject ( sinR ) );
+            matrix.insert ( matrix.end(), PdfObject ( -sinR ) );
+            matrix.insert ( matrix.end(), PdfObject ( cosR ) );
+            matrix.insert ( matrix.end(), PdfObject ( tx ) );
+            matrix.insert ( matrix.end(), PdfObject ( ty ) );
+
+
+            PdfName mname ( "Matrix" );
+            PdfXObject *xo = xobjects[curPage];
+            ostringstream op;
+            op << "OriginalPage" << curPage;
+            PdfName xname ( op.str() );
+            xdict.AddKey ( xname, xo->GetObjectReference() );
+            xo->GetContents()->GetDictionary().AddKey ( mname, PdfObject ( 
matrix ) );
+            xo->GetContents()->GetDictionary().AddKey ( PdfName ( "Resources" 
), globalResRef );
+            pages.push_back( curPage );
+
+            double top = rect.GetHeight() + rect.GetBottom() + ty ;
+            double bottom = rect.GetBottom() + ty;
+            double left = rect.GetLeft() + tx;
+            double right = rect.GetWidth() + rect.GetLeft() + tx;
+
+            double btop = bleed.GetHeight() + bleed.GetBottom() + ty ;
+            double bbottom = bleed.GetBottom() + ty;
+            double bleft = bleed.GetLeft() + tx;
+            double bright = bleed.GetWidth() + bleed.GetLeft() + tx;
+
+
+            drawLine(0,top ,bleft, top , buffer);
+            drawLine(0, bottom , bleft, bottom, buffer);
+
+            drawLine(pw , top , bright , top, buffer);
+            drawLine(pw, bottom , bright ,bottom, buffer);
+
+            drawLine(left,0, left , bbottom,  buffer);
+            drawLine(right, 0 ,right, bbottom, buffer);
+
+            drawLine(left , ph ,left ,btop, buffer);
+            drawLine(right, ph ,right, btop, buffer);
+        }
+
+
+        signature(extraSpace / 2.0 , extraSpace / 10.0, (*git).first, 
(*git).second, buffer);
+        for ( vector<int>::const_iterator it = pages.begin(); it != 
pages.end(); ++it)
+            buffer << "/OriginalPage" << *it << " Do\n";
+        string bufStr = buffer.str();
+        newpage->GetContentsForAppending()->GetStream()->Set ( bufStr.data(), 
bufStr.size() );
+        PdfName dname ( "XObject" );
+        newpage->GetResources()->GetDictionary().AddKey ( dname, xdict );
+        ++git;
+    }
+    targetDoc->DeletePages ( 0,pcount );
+    //qDebug() << outFilePath <<" has " << targetDoc->GetPageCount() << " 
pages.";
+    targetDoc->Write ( outFilePath.c_str() );
+
 }
 
-void PdfTranslator::drawLine(double x, double y, double xx, double yy, 
QByteArray * a)
+void PdfTranslator::drawLine(double x, double y, double xx, double yy, 
ostringstream & s)
 {
-       a->append(QString("q\n0.5 w\n1 0 0 1 0 0 cm\n%1 %2 m\n%3 %4 l\nS\nQ\n")
-                       .arg(x)
-                       .arg(y)
-                       .arg(xx)
-                       .arg(yy));
+    //TODO: ensure safe double formatting for PDF
+    s << "q\n"
+         "0.5 w\n"
+         "1 0 0 1 0 0 cm\n"
+      << x << ' ' << y << " m\n"
+      << xx << ' ' << yy << " l\n"
+         "S\n"
+         "Q\n";
 }
 
-void PdfTranslator::signature(double x, double y, int sheet, QList< int > 
pages, QByteArray * a)
+void PdfTranslator::signature(double x, double y, int sheet, const vector< int 
> & pages, ostringstream & s)
 {
-       CharPainter painter;
-       QString p;
-       p  = "q\n 1 0 0 1 0 0 cm\n";
-       p += painter.multipaint(sheet, extraSpace / 2.0 , x  , y);
-//     for(int i = 0;i < pages.count(); ++i)
-//     {
-//             p.append(painter.multipaint(pages[i], extraSpace /3.0 , x + 
extraSpace + (i * extraSpace / 2.0),y ));
-//     }
-//     
-       a->append(p + "Q\n");
-       
+    CharPainter painter;
+    s << "q\n"
+         "1 0 0 1 0 0 cm\n";
+    painter.multipaint(s, sheet, extraSpace / 2.0 , x  , y);
+    //         for(int i = 0;i < pages.count(); ++i)
+    //         {
+    //                 s << painter.multipaint(pages[i], extraSpace /3.0 , x + 
extraSpace + (i * extraSpace / 2.0),y );
+    //         }
+    //         
+    s << "Q\n";
+
 }
 
 
Index: main.cpp
===================================================================
--- main.cpp    (revision 33)
+++ main.cpp    (working copy)
@@ -20,30 +20,86 @@
 
 #include "pdftranslator.h"
 
-#include <QCoreApplication>
-#include <QStringList>
-#include <QDebug>
+#include <cstdlib>
+#include <iostream>
+#include <string>
 
-int main(int argc, char *argv[])
+using std::cerr;
+using std::endl;
+using std::strtod;
+using std::string;
+
+struct _params {
+    string executablePath;
+    string inFilePath;
+    string outFilePath;
+    string planFilePath;
+    double sheetMargin;
+} params;
+
+void usage()
 {
-      QCoreApplication app(argc, argv);     
-      if(app.arguments().count() !=  5)
+     cerr << "Usage : " << params.executablePath << " input output plan 
sheetMargin" << endl;
+     cerr << "\tinput is a PDF file" << endl;
+     cerr << "\toutput will be a PDF file" << endl;
+     cerr << "\tplan is an imposition plan file.\n\tFormat is simple, the 
first line indicates width and height of final page size (MediaBox), and 
follows a list of records of form :\n\tsourcePage destinationPage 
rotation(counterclokwise & with axis 0.0) Xcoordinate Ycoordinate" << endl;
+     cerr << "\tsheetMargin is the size of the margins where cut marks will be 
drawn" << endl;
+     cerr << "\nAll sizes are in point and user space as defined in PDF 
(origine is bottom left). " << endl;
+}
+
+int parseCommandLine(int argc, char* argv[])
+{
+      if(argc !=  5)
       {
-             qDebug() << "Usage : " << app.arguments().at(0) << " input output 
plan sheetMargin";
-             qDebug() << "\tinput is a PDF file";
-             qDebug() << "\toutput will be a PDF file";
-             qDebug() << "\tplan is an imposition plan file.\n\tFormat is 
simple, the first line indicates width and height of final page size 
(MediaBox), and follows a list of records of form :\n\tsourcePage 
destinationPage rotation(counterclokwise & with axis 0.0) Xcoordinate 
Ycoordinate"; 
-             qDebug() << "\tsheetMargin is the size of the margins where cut 
marks will be drawn";
-             qDebug() << "\nAll sizes are in point and user space as defined 
in PDF (origine is bottom left). ";
-             return 0;
+          usage();
+          return 1;
       }
-      qDebug("create  translator");
-      PdfTranslator *translator = new 
PdfTranslator(app.arguments().at(4).toDouble());
-      qDebug("translator created");
-      translator->setSource(app.arguments().at(1));
-      translator->setTarget(app.arguments().at(2));
-      translator->loadPlan(app.arguments().at(3));
-      translator->impose();
+
+      params.executablePath = argv[0];
+      params.inFilePath = argv[1];
+      params.outFilePath = argv[2];
+      params.planFilePath = argv[3];
+
+      char * endptr = 0;
+      params.sheetMargin = strtod(argv[4], &endptr);
+      if (!endptr)
+      {
+          cerr << "Cannot parse '" << argv[4] << "' as decimal for sheetMargin 
argument" << endl;
+          usage();
+          return 1;
+      }
       return 0;
 }
 
+/**
+ * Return values:
+ *
+ * 0 : success
+ * 1 : bad command line arguments
+ */
+int main(int argc, char *argv[])
+{
+    int ret = parseCommandLine(argc, argv);
+    if (ret)
+        return ret;
+
+    try {
+        PdfTranslator *translator = new PdfTranslator(params.sheetMargin);
+        translator->setSource(params.inFilePath);
+        translator->setTarget(params.outFilePath);
+        translator->loadPlan(params.planFilePath);
+        translator->impose();
+    }
+    catch ( PoDoFo::PdfError & e )
+    {
+        e.PrintErrorMsg();
+        return 3;
+    }
+    catch ( std::exception & e )
+    {
+        cerr << e.what() << endl;
+    }
+
+    return 0;
+}
+
Index: charpainter.h
===================================================================
--- charpainter.h       (revision 33)
+++ charpainter.h       (working copy)
@@ -20,21 +20,43 @@
 #ifndef CHARPAINTER_H
 #define CHARPAINTER_H
 
-#include <QChar>
-#include <QString>
 /**
        @author Pierre Marchand <[EMAIL PROTECTED]>
 */
+
+#include <ostream>
+
 class CharPainter{
 public:
-    CharPainter();
+    CharPainter() { }
+    ~CharPainter() { }
 
-    ~CharPainter();
-    
-    QString paint(QChar  c, double size);
-    QString paint(int n, double size,double x, double y);
-    QString multipaint(int n, double size,double x, double y);
+    void paint(std::ostream& s, int n, double size, double x, double y);
+    // call paint() for each digit in the number `n'
+    void multipaint(std::ostream& s, int n, double size, double x, double y);
+private:
+    // some simple helpers for writing points
+    // TODO: nothrow annotations
+    inline void wdir(std::ostream& s, double x1, double y1, double x2, double 
y2) const
+    {
+        s << x1 << ' ' << y1 << " m\n"
+          << x2 << ' ' << y2 << " l\n";
+    }
+    inline void top(std::ostream& s) const { wdir(s, m_x, m_sh, m_sw, m_x); }
+    inline void topright(std::ostream& s) const { wdir(s, m_sw, m_sh, m_sw, 
m_midh); }
+    inline void bottomright(std::ostream& s) const { wdir(s, m_sw, m_midh, 
m_sw, m_y); }
+    inline void bottom(std::ostream& s) const { wdir(s, m_x, m_y, m_sw, m_y); }
+    inline void bottomleft(std::ostream&s) const { wdir(s, m_x, m_y, m_x, 
m_midh); }
+    inline void topleft(std::ostream& s) const { wdir(s, m_x, m_midh, m_x, 
m_sh); }
+    inline void center(std::ostream& s) const { wdir(s, m_x, m_midh, m_sw, 
m_midh); }
 
+    // temporaries used by paint(...)
+    double m_size;
+    double m_x;
+    double m_y;
+    double m_sh;
+    double m_sw;
+    double m_midh;
 };
 
 #endif
Index: src.pro
===================================================================
--- src.pro     (revision 33)
+++ src.pro     (working copy)
@@ -1,17 +0,0 @@
-SOURCES += main.cpp \
-pdftranslator.cpp \
-charpainter.cpp
-TEMPLATE = app
-CONFIG += warn_on \
-         thread \
-          qt
-TARGET = ../bin/pdfimpose
-
-QT -= gui
-HEADERS += pdftranslator.h \
-charpainter.h
-
-INCLUDEPATH += /usr/local/include
-INCLUDEPATH += /usr/local/include/podofo
-LIBS += -L/usr/local/lib -lpodofo
-LIBS += -L/usr/lib -lm
Index: pdftranslator.h
===================================================================
--- pdftranslator.h     (revision 33)
+++ pdftranslator.h     (working copy)
@@ -22,82 +22,73 @@
 
 #include <podofo/podofo.h>
 
-#ifndef _PODOFO_H_
-#error "podofo.h not included"
-#endif
+#include <string>
+#include <map>
+#include <vector>
+#include <sstream>
+#include <istream>
 
-#ifdef _PODOFO_H_
-#warning "podofo.h successfully included"
-#endif
-
-#include <QString>
-#include <QList>
-#include <QMap>
-
 class QByteArray ;
 
 using namespace PoDoFo;
 
 /**
-       @author Pierre Marchand <[EMAIL PROTECTED]>
-*/
+  @author Pierre Marchand <[EMAIL PROTECTED]>
+  */
 struct PageRecord
 {
-       int sourcePage;
-       int xobjIndex;
-       int destPage;
-       double rotate;
-       double transX;
-       double transY;
-       PageRecord ( int s,int d,double r, double tx, double ty )
-                       : sourcePage ( s ),
-                       destPage ( d ),
-                       rotate ( r ),
-                       transX ( tx ),
-                       transY ( ty )
-       {};
+    int sourcePage;
+    int xobjIndex;
+    int destPage;
+    double rotate;
+    double transX;
+    double transY;
+    PageRecord ( int s,int d,double r, double tx, double ty );
+    PageRecord();
+    bool isValid() const;
+    friend std::istream & operator >> (std::istream&, PageRecord&);
+    friend std::ostream & operator << (std::ostream&, const PageRecord&);
 };
 
 class PdfTranslator
 {
-       public:
-               PdfTranslator(double sp);
+    public:
+        PdfTranslator(double sp);
 
-               ~PdfTranslator();
+        ~PdfTranslator() { }
 
-               PdfMemDocument *sourceDoc;
-               PdfMemDocument *targetDoc;
+        PdfMemDocument *sourceDoc;
+        PdfMemDocument *targetDoc;
 
-               void setSource ( QString source );
-               void setTarget ( QString target );
-               
-               QString input;
-               QString output;
-               int pcount;
+        void setSource ( const std::string & source );
+        void setTarget ( const std::string & target );
+        void loadPlan ( const std::string & plan );
+        void impose();
 
-               void loadPlan ( QString plan );
+    private:
+        std::string inFilePath;
+        std::string outFilePath;
+        int pcount;
 
-               PdfReference globalResRef;
+        PdfReference globalResRef;
 
-               QList<PageRecord> planImposition;
-               QMap<int, int> pagesIndex;
-               QMap<int, PdfXObject*> xobjects;
-               QMap<int, PdfRect> trimRect;
-               QMap<int,PdfRect> bleedRect;
-               QMap<int, PdfDictionary*> pDict;
-               QMap<int, int> virtualMap;
-               double destWidth;
-               double destHeight;
-               int maxPageDest;
+        std::vector<PageRecord> planImposition;
+        std::map<int, int> pagesIndex;
+        std::map<int, PdfXObject*> xobjects;
+        std::map<int, PdfRect> trimRect;
+        std::map<int,PdfRect> bleedRect;
+        std::map<int, PdfDictionary*> pDict;
+        std::map<int, int> virtualMap;
+        double destWidth;
+        double destHeight;
+        int maxPageDest;
 
-               void impose();
-               void drawLine(double x, double y, double xx, double yy, 
QByteArray *a );
-               void signature(double x , double y, int sheet, QList<int> pages 
, QByteArray *a );
-               
-               QString useFont;
-               PdfReference useFontRef;
-               double extraSpace;
+        void drawLine(double x, double y, double xx, double yy, 
std::ostringstream & a );
+        void signature(double x , double y, int sheet, const std::vector<int> 
& pages, std::ostringstream & a );
 
+        std::string useFont;
+        PdfReference useFontRef;
+        double extraSpace;
 };
 
 #endif
Index: ReadMe
===================================================================
--- ReadMe      (revision 33)
+++ ReadMe      (working copy)
@@ -1,11 +0,0 @@
-READ THIS IN ORDER TO COMPILE THE Qt4 TEMPLATE
-----------------------------------------------
-
-Before compiling, check the Qt Options, go to 
-Project->Project Options->C++ Support and open the Qt Options tab.
-
-Check that the Qt installation directory is correct for the Qt version you've 
chosen.
-
-------------------
-Andreas Pakulat
-July 2006
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt      (revision 0)
+++ CMakeLists.txt      (revision 0)
@@ -0,0 +1,19 @@
+PROJECT(pdfimpose)
+
+SET(PDFIMPOSE_SOURCES
+       charpainter.cpp
+       main.cpp
+       pdftranslator.cpp
+)
+
+ADD_EXECUTABLE(
+       pdfimpose
+       ${PDFIMPOSE_SOURCES}
+       )
+
+INCLUDE_DIRECTORIES(
+       /home/craig/podofo/podofo-debug/include
+)
+TARGET_LINK_LIBRARIES(pdfimpose
+       /home/craig/podofo/podofo-debug/lib/libpodofo.so
+)
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Podofo-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to