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