moved pdf merger file into src directory.

preferencesAboutTextFull
Claudio Valerio 13 years ago
parent 97cee1b6b0
commit 7564a8badf
  1. 212
      src/pdf-merger/ASCII85Decode.cpp
  2. 48
      src/pdf-merger/ASCII85Decode.h
  3. 122
      src/pdf-merger/ASCIIHexDecode.cpp
  4. 44
      src/pdf-merger/ASCIIHexDecode.h
  5. 118
      src/pdf-merger/AbstractBoxElementHandler.h
  6. 0
      src/pdf-merger/AnnotsHandler.cpp
  7. 66
      src/pdf-merger/AnnotsHandler.h
  8. 42
      src/pdf-merger/CCITTFaxDecode.h
  9. 0
      src/pdf-merger/Config.h
  10. 146
      src/pdf-merger/ContentHandler.cpp
  11. 92
      src/pdf-merger/ContentHandler.h
  12. 104
      src/pdf-merger/CropBoxElementHandler.h
  13. 44
      src/pdf-merger/DCTDecode.h
  14. 50
      src/pdf-merger/Decoder.h
  15. 0
      src/pdf-merger/Document.cpp
  16. 0
      src/pdf-merger/Document.h
  17. 72
      src/pdf-merger/Exception.h
  18. 38
      src/pdf-merger/FileIsAbsentException.h
  19. 0
      src/pdf-merger/Filter.cpp
  20. 0
      src/pdf-merger/Filter.h
  21. 528
      src/pdf-merger/FilterPredictor.cpp
  22. 88
      src/pdf-merger/FilterPredictor.h
  23. 404
      src/pdf-merger/FlateDecode.cpp
  24. 52
      src/pdf-merger/FlateDecode.h
  25. 44
      src/pdf-merger/JBIG2Decode.h
  26. 386
      src/pdf-merger/LZWDecode.cpp
  27. 82
      src/pdf-merger/LZWDecode.h
  28. 104
      src/pdf-merger/MediaBoxElementHandler.h
  29. 194
      src/pdf-merger/MergePageDescription.h
  30. 230
      src/pdf-merger/Merger.cpp
  31. 84
      src/pdf-merger/Merger.h
  32. 0
      src/pdf-merger/Object.cpp
  33. 298
      src/pdf-merger/Object.h
  34. 288
      src/pdf-merger/OverlayDocumentParser.cpp
  35. 80
      src/pdf-merger/OverlayDocumentParser.h
  36. 1104
      src/pdf-merger/Page.cpp
  37. 128
      src/pdf-merger/Page.h
  38. 148
      src/pdf-merger/PageElementHandler.cpp
  39. 168
      src/pdf-merger/PageElementHandler.h
  40. 82
      src/pdf-merger/PageParser.h
  41. 0
      src/pdf-merger/Parser.cpp
  42. 152
      src/pdf-merger/Parser.h
  43. 248
      src/pdf-merger/Rectangle.cpp
  44. 78
      src/pdf-merger/Rectangle.h
  45. 50
      src/pdf-merger/RemoveHimSelfHandler.h
  46. 28
      src/pdf-merger/RemoveHimselfHandler.cpp
  47. 102
      src/pdf-merger/RotationHandler.h
  48. 84
      src/pdf-merger/RunLengthDecode.cpp
  49. 44
      src/pdf-merger/RunLengthDecode.h
  50. 662
      src/pdf-merger/Transformation.h
  51. 60
      src/pdf-merger/TypeElementHandler.h
  52. 394
      src/pdf-merger/Utils.cpp
  53. 64
      src/pdf-merger/Utils.h
  54. 0
      src/pdf-merger/doc/PDF Merge Library Description.doc
  55. 111
      src/pdf-merger/pdfMerger.pri

@ -1,106 +1,106 @@
#include <iostream>
#include "ASCII85Decode.h"
using namespace merge_lib;
static const unsigned long pow85[] = {
85*85*85*85, 85*85*85, 85*85, 85, 1
};
void ASCII85Decode::_wput(std::string &cur,unsigned long tuple, int len)
{
switch (len)
{
case 4:
cur+=static_cast<char>(tuple >> 24);
cur+=static_cast<char>(tuple >> 16);
cur+=static_cast<char>(tuple >> 8);
cur+=static_cast<char>(tuple);
break;
case 3:
cur+=static_cast<char>(tuple >> 24);
cur+=static_cast<char>(tuple >> 16);
cur+=static_cast<char>(tuple >> 8);
break;
case 2:
cur+=static_cast<char>(tuple >> 24);
cur+=static_cast<char>(tuple >> 16);
break;
case 1:
cur+=static_cast<char>(tuple >> 24);
break;
default:
std::cerr<<"Asci85Filter - unexpected len = "<<len<<"\n";
break;
}
}
bool ASCII85Decode::decode(std::string &encoded)
{
unsigned long tuple = 0;
std::string decoded = "";
int count = 0;
int size = encoded.size();
int i = 0;
bool found = false;
for(;size;)
{
char ch = encoded[i++];
// sometimes <~ can present.
switch(ch)
{
default:
if( ch < '!' || ch > 'u' )
{
std::cerr<<"bag character in ascii85 block["<<ch<<"]\n";
return false;
}
tuple += (unsigned long)(ch - '!') * pow85[count++];
if( count == 5)
{
_wput(decoded,tuple,4);
count = 0;
tuple = 0;
}
break;
case 'z':
if( count != 0 )
{
std::cerr<<"Z inside of acii85 5-tuple!\n";
return false;
}
decoded += "\0\0\0\0";
break;
case '~':
if( --size )
{
ch = encoded[i++];
if( ch == '>')
{
if( count > 0 )
{
count --;
tuple += pow85[count];
_wput(decoded,tuple,count);
}
}
encoded = decoded;
return true;
}
std::cerr<<"~ without > in ascii85 stream!\n = ["<<ch<<"]\n";
encoded = decoded;
return false;
break;
case '\n':
case '\r':
case '\t':
case ' ':
case '\0':
case '\f':
case '\b':
case 0177:
break;
}
--size;
}
return true;
}
#include <iostream>
#include "ASCII85Decode.h"
using namespace merge_lib;
static const unsigned long pow85[] = {
85*85*85*85, 85*85*85, 85*85, 85, 1
};
void ASCII85Decode::_wput(std::string &cur,unsigned long tuple, int len)
{
switch (len)
{
case 4:
cur+=static_cast<char>(tuple >> 24);
cur+=static_cast<char>(tuple >> 16);
cur+=static_cast<char>(tuple >> 8);
cur+=static_cast<char>(tuple);
break;
case 3:
cur+=static_cast<char>(tuple >> 24);
cur+=static_cast<char>(tuple >> 16);
cur+=static_cast<char>(tuple >> 8);
break;
case 2:
cur+=static_cast<char>(tuple >> 24);
cur+=static_cast<char>(tuple >> 16);
break;
case 1:
cur+=static_cast<char>(tuple >> 24);
break;
default:
std::cerr<<"Asci85Filter - unexpected len = "<<len<<"\n";
break;
}
}
bool ASCII85Decode::decode(std::string &encoded)
{
unsigned long tuple = 0;
std::string decoded = "";
int count = 0;
int size = encoded.size();
int i = 0;
bool found = false;
for(;size;)
{
char ch = encoded[i++];
// sometimes <~ can present.
switch(ch)
{
default:
if( ch < '!' || ch > 'u' )
{
std::cerr<<"bag character in ascii85 block["<<ch<<"]\n";
return false;
}
tuple += (unsigned long)(ch - '!') * pow85[count++];
if( count == 5)
{
_wput(decoded,tuple,4);
count = 0;
tuple = 0;
}
break;
case 'z':
if( count != 0 )
{
std::cerr<<"Z inside of acii85 5-tuple!\n";
return false;
}
decoded += "\0\0\0\0";
break;
case '~':
if( --size )
{
ch = encoded[i++];
if( ch == '>')
{
if( count > 0 )
{
count --;
tuple += pow85[count];
_wput(decoded,tuple,count);
}
}
encoded = decoded;
return true;
}
std::cerr<<"~ without > in ascii85 stream!\n = ["<<ch<<"]\n";
encoded = decoded;
return false;
break;
case '\n':
case '\r':
case '\t':
case ' ':
case '\0':
case '\f':
case '\b':
case 0177:
break;
}
--size;
}
return true;
}

@ -1,24 +1,24 @@
#ifndef ASCII85Decode_H
#define ASCII85Decode_H
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class ASCII85Decode : public Decoder
{
public:
ASCII85Decode(){};
virtual ~ASCII85Decode(){};
bool encode(std::string & decoded) {return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStram){};
private:
void _wput(std::string &cur,unsigned long tuple, int len);
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef ASCII85Decode_H
#define ASCII85Decode_H
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class ASCII85Decode : public Decoder
{
public:
ASCII85Decode(){};
virtual ~ASCII85Decode(){};
bool encode(std::string & decoded) {return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStram){};
private:
void _wput(std::string &cur,unsigned long tuple, int len);
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,61 +1,61 @@
#include "ASCIIHexDecode.h"
#include <string>
#include "Utils.h"
using namespace merge_lib;
const std::string WHITESPACES(" \t\f\v\n\r");
#define HEX_TO_VAL(char_c) (char_c)>9?'A'+(char_c)-10:'0'+(char_c);
static unsigned int convertHexVal(unsigned char c)
{
if(c >= '0' && c <= '9')
{
return (c - '0');
}
if(c >= 'A' && c <= 'F')
{
return (c - 'A' + 10);
}
if(c >= 'a' && c <= 'f')
{
return (c - 'a' + 10);
}
return 0;
}
bool ASCIIHexDecode::decode(std::string & encoded)
{
bool isLow = true;
unsigned char decodedChar = '\0';
int len = encoded.size();
std::string decoded ="";
for(int i = 0;i<len;i++)
{
unsigned char ch = encoded[i];
if( WHITESPACES.find(ch) != std::string::npos )
{
continue;
}
if( ch == '>' )
{
continue; // EOD found
}
ch = convertHexVal(ch);
if( isLow )
{
decodedChar = (ch & 0x0F);
isLow = false;
}
else
{
decodedChar = ((decodedChar << 4) | ch);
isLow = true;
decoded += decodedChar;
}
}
encoded = decoded;
return true;
}
#include "ASCIIHexDecode.h"
#include <string>
#include "Utils.h"
using namespace merge_lib;
const std::string WHITESPACES(" \t\f\v\n\r");
#define HEX_TO_VAL(char_c) (char_c)>9?'A'+(char_c)-10:'0'+(char_c);
static unsigned int convertHexVal(unsigned char c)
{
if(c >= '0' && c <= '9')
{
return (c - '0');
}
if(c >= 'A' && c <= 'F')
{
return (c - 'A' + 10);
}
if(c >= 'a' && c <= 'f')
{
return (c - 'a' + 10);
}
return 0;
}
bool ASCIIHexDecode::decode(std::string & encoded)
{
bool isLow = true;
unsigned char decodedChar = '\0';
int len = encoded.size();
std::string decoded ="";
for(int i = 0;i<len;i++)
{
unsigned char ch = encoded[i];
if( WHITESPACES.find(ch) != std::string::npos )
{
continue;
}
if( ch == '>' )
{
continue; // EOD found
}
ch = convertHexVal(ch);
if( isLow )
{
decodedChar = (ch & 0x0F);
isLow = false;
}
else
{
decodedChar = ((decodedChar << 4) | ch);
isLow = true;
decoded += decodedChar;
}
}
encoded = decoded;
return true;
}

@ -1,22 +1,22 @@
#ifndef ASCIIHexDecode_h
#define ASCIIHexDecode_h
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this class provides method for ASCIIHEX encoding and decoding
class ASCIIHexDecode : public Decoder
{
public:
ASCIIHexDecode(){};
virtual ~ASCIIHexDecode(){};
bool encode(std::string & decoded){return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef ASCIIHexDecode_h
#define ASCIIHexDecode_h
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this class provides method for ASCIIHEX encoding and decoding
class ASCIIHexDecode : public Decoder
{
public:
ASCIIHexDecode(){};
virtual ~ASCIIHexDecode(){};
bool encode(std::string & decoded){return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,59 +1,59 @@
#if !defined AbstractBoxElementHandler_h
#define AbstractBoxElementHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
//class for processing MediaBox field of Page object
class AbstractBoxElementHandler: public PageElementHandler
{
public:
AbstractBoxElementHandler(Object * page): PageElementHandler(page)
{
}
virtual ~AbstractBoxElementHandler()
{
}
protected:
void _retrieveBoxFromParent()
{
std::string content = _page->getObjectContent();
std::string mediaBox;
Object * parent = _page;
while(1)
{
unsigned int startOfParent = content.find("/Parent");
unsigned int endOfParent = content.find(" R", startOfParent);
if(startOfParent == std::string::npos)
break;
std::vector <Object *> parents = parent->getChildrenByBounds(startOfParent, endOfParent);
if(parents.size() != 1)
break;
parent = parents[0];
std::string parentContent = parent->getObjectContent();
unsigned int startOfMediaBox = parentContent.find(_handlerName);
if(startOfMediaBox == std::string::npos)
{
content = parentContent;
continue;
}
unsigned int endOfMediaBox = parentContent.find("]", startOfMediaBox);
mediaBox = parentContent.substr(startOfMediaBox, endOfMediaBox - startOfMediaBox + 1);
break;
}
if(!mediaBox.empty())
{
unsigned int startOfMediaBox = _page->getObjectContent().rfind(">>");
_page->insertToContent(startOfMediaBox, mediaBox);
_changeObjectContent(startOfMediaBox);
}
}
private:
virtual void _changeObjectContent(unsigned int startOfPageElement) = 0;
};
}
#endif
#if !defined AbstractBoxElementHandler_h
#define AbstractBoxElementHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
//class for processing MediaBox field of Page object
class AbstractBoxElementHandler: public PageElementHandler
{
public:
AbstractBoxElementHandler(Object * page): PageElementHandler(page)
{
}
virtual ~AbstractBoxElementHandler()
{
}
protected:
void _retrieveBoxFromParent()
{
std::string content = _page->getObjectContent();
std::string mediaBox;
Object * parent = _page;
while(1)
{
unsigned int startOfParent = content.find("/Parent");
unsigned int endOfParent = content.find(" R", startOfParent);
if(startOfParent == std::string::npos)
break;
std::vector <Object *> parents = parent->getChildrenByBounds(startOfParent, endOfParent);
if(parents.size() != 1)
break;
parent = parents[0];
std::string parentContent = parent->getObjectContent();
unsigned int startOfMediaBox = parentContent.find(_handlerName);
if(startOfMediaBox == std::string::npos)
{
content = parentContent;
continue;
}
unsigned int endOfMediaBox = parentContent.find("]", startOfMediaBox);
mediaBox = parentContent.substr(startOfMediaBox, endOfMediaBox - startOfMediaBox + 1);
break;
}
if(!mediaBox.empty())
{
unsigned int startOfMediaBox = _page->getObjectContent().rfind(">>");
_page->insertToContent(startOfMediaBox, mediaBox);
_changeObjectContent(startOfMediaBox);
}
}
private:
virtual void _changeObjectContent(unsigned int startOfPageElement) = 0;
};
}
#endif

@ -1,33 +1,33 @@
#if !defined AnnotsHandler_h
#define AnnotsHandler_h
#include "RemoveHimSelfHandler.h"
//this class is needed to process "Annots" field
//AnnotsHandler parses Annots field of Page object and fills
//annots container with Annots objects
namespace merge_lib
{
class AnnotsHandler: public RemoveHimselfHandler
{
public:
AnnotsHandler(Object * page, const std::string & handlerName, std::vector<Object *> & annots):
RemoveHimselfHandler(page, handlerName),
_annotations(annots)
{
_setHandlerName(handlerName);
}
private:
//methods
void _processObjectContent(unsigned int startOfPageElement);
//memebers
std::vector<Object *> & _annotations;
};
}
#endif
#if !defined AnnotsHandler_h
#define AnnotsHandler_h
#include "RemoveHimSelfHandler.h"
//this class is needed to process "Annots" field
//AnnotsHandler parses Annots field of Page object and fills
//annots container with Annots objects
namespace merge_lib
{
class AnnotsHandler: public RemoveHimselfHandler
{
public:
AnnotsHandler(Object * page, const std::string & handlerName, std::vector<Object *> & annots):
RemoveHimselfHandler(page, handlerName),
_annotations(annots)
{
_setHandlerName(handlerName);
}
private:
//methods
void _processObjectContent(unsigned int startOfPageElement);
//memebers
std::vector<Object *> & _annotations;
};
}
#endif

@ -1,21 +1,21 @@
#ifndef CCITTFaxDecode_H
#define CCITTFaxDecode_H
#include <string>
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class CCITTFaxDecode : public Decoder
{
public:
CCITTFaxDecode(){};
virtual ~CCITTFaxDecode(){};
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded) {return true;};
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef CCITTFaxDecode_H
#define CCITTFaxDecode_H
#include <string>
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class CCITTFaxDecode : public Decoder
{
public:
CCITTFaxDecode(){};
virtual ~CCITTFaxDecode(){};
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded) {return true;};
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,73 +1,73 @@
#include "ContentHandler.h"
#include "Filter.h"
#include "FlateDecode.h"
#include <iostream>
#include <string>
#include <string.h>
using namespace merge_lib;
using namespace std;
//concatenate stream of all objects which contain Content of Page
void ContentHandler::_processObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfPage = _findEndOfElementContent(startOfPageElement);
_concatenatedStream = _retrieveStreamContent(_page, startOfPageElement, endOfPage);
FlateDecode flate;
flate.encode(_concatenatedStream);
}
//write concatenated stream to Page object
void ContentHandler::_changeObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfPage = _findEndOfElementContent(startOfPageElement);
_page->forgetAboutChildren(startOfPageElement, endOfPage);
_page->eraseContent(startOfPageElement, endOfPage - startOfPageElement);
unsigned int endOfObjectDescription = _pageContent.rfind(">>");
const char * length = "/Filter /FlateDecode\n/Length ";
unsigned int sizeOfLength = strlen(length);
_page->insertToContent(endOfObjectDescription, length, sizeOfLength);
_page->insertToContent(endOfObjectDescription + sizeOfLength, Utils::uIntToStr(_concatenatedStream.size()).c_str());
_page->appendContent("\nstream\n");
_page->appendContent(_concatenatedStream);
_page->appendContent("endstream\n");
_page->forgetStreamInFile();
}
//get content of stream
// object - object with stream
//leftBound - left bound of object's content
//rightBound - right bound of object's content
string ContentHandler::_retrieveStreamContent(merge_lib::Object * object, unsigned int leftBound, unsigned int rightBound)
{
return (object->hasStream()) ?
_getStreamFromContent(object) :
_getStreamFromReferencies(object, leftBound, rightBound);
}
//get stream from Array elements
string ContentHandler::_getStreamFromReferencies(merge_lib::Object * objectWithArray, unsigned int leftBound, unsigned int rightBound)
{
std::string result;
std::vector<Object *> referencies = objectWithArray->getSortedByPositionChildren(leftBound, rightBound);
for(size_t i = 0; i < referencies.size(); ++i)
{
result.append(_retrieveStreamContent(referencies[i], 0, referencies[i]->getObjectContent().size()));
}
objectWithArray->forgetAboutChildren(leftBound,rightBound);
return result;
}
//get stream from Object
string ContentHandler::_getStreamFromContent(merge_lib::Object * objectWithStream)
{
Filter filter(objectWithStream);
string decodedStream;
filter.getDecodedStream(decodedStream);
return decodedStream;
}
#include "ContentHandler.h"
#include "Filter.h"
#include "FlateDecode.h"
#include <iostream>
#include <string>
#include <string.h>
using namespace merge_lib;
using namespace std;
//concatenate stream of all objects which contain Content of Page
void ContentHandler::_processObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfPage = _findEndOfElementContent(startOfPageElement);
_concatenatedStream = _retrieveStreamContent(_page, startOfPageElement, endOfPage);
FlateDecode flate;
flate.encode(_concatenatedStream);
}
//write concatenated stream to Page object
void ContentHandler::_changeObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfPage = _findEndOfElementContent(startOfPageElement);
_page->forgetAboutChildren(startOfPageElement, endOfPage);
_page->eraseContent(startOfPageElement, endOfPage - startOfPageElement);
unsigned int endOfObjectDescription = _pageContent.rfind(">>");
const char * length = "/Filter /FlateDecode\n/Length ";
unsigned int sizeOfLength = strlen(length);
_page->insertToContent(endOfObjectDescription, length, sizeOfLength);
_page->insertToContent(endOfObjectDescription + sizeOfLength, Utils::uIntToStr(_concatenatedStream.size()).c_str());
_page->appendContent("\nstream\n");
_page->appendContent(_concatenatedStream);
_page->appendContent("endstream\n");
_page->forgetStreamInFile();
}
//get content of stream
// object - object with stream
//leftBound - left bound of object's content
//rightBound - right bound of object's content
string ContentHandler::_retrieveStreamContent(merge_lib::Object * object, unsigned int leftBound, unsigned int rightBound)
{
return (object->hasStream()) ?
_getStreamFromContent(object) :
_getStreamFromReferencies(object, leftBound, rightBound);
}
//get stream from Array elements
string ContentHandler::_getStreamFromReferencies(merge_lib::Object * objectWithArray, unsigned int leftBound, unsigned int rightBound)
{
std::string result;
std::vector<Object *> referencies = objectWithArray->getSortedByPositionChildren(leftBound, rightBound);
for(size_t i = 0; i < referencies.size(); ++i)
{
result.append(_retrieveStreamContent(referencies[i], 0, referencies[i]->getObjectContent().size()));
}
objectWithArray->forgetAboutChildren(leftBound,rightBound);
return result;
}
//get stream from Object
string ContentHandler::_getStreamFromContent(merge_lib::Object * objectWithStream)
{
Filter filter(objectWithStream);
string decodedStream;
filter.getDecodedStream(decodedStream);
return decodedStream;
}

@ -1,46 +1,46 @@
#if !defined ContentHandler_h
#define ContentHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
//this class is needed to process "Content" field of Page object
class ContentHandler: public PageElementHandler
{
public:
ContentHandler(Object * page, const std::string & handlerName):
PageElementHandler(page)
{
_setHandlerName(handlerName);
}
virtual ~ContentHandler(){};
private:
//methods
//concatedate stream of all objects which contains Content of Page
void _processObjectContent(unsigned int startOfPageElement);
//write concatenated stream to Page object
void _changeObjectContent(unsigned int startOfPageElement);
//get content of stream
// object - object with stream
//leftBound - left bound of object's content
//rightBound - right bound of object's content
std::string _retrieveStreamContent(Object * object, unsigned int leftBound, unsigned int rightBound);
//get stream from Arrey elemetns
std::string _getStreamFromReferencies(Object * objectWithArray, unsigned int leftBound, unsigned int rightBound);
//get stream from Object
std::string _getStreamFromContent(Object * objectWithStream);
//memebers
std::string _concatenatedStream;
};
}
#endif
#if !defined ContentHandler_h
#define ContentHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
//this class is needed to process "Content" field of Page object
class ContentHandler: public PageElementHandler
{
public:
ContentHandler(Object * page, const std::string & handlerName):
PageElementHandler(page)
{
_setHandlerName(handlerName);
}
virtual ~ContentHandler(){};
private:
//methods
//concatedate stream of all objects which contains Content of Page
void _processObjectContent(unsigned int startOfPageElement);
//write concatenated stream to Page object
void _changeObjectContent(unsigned int startOfPageElement);
//get content of stream
// object - object with stream
//leftBound - left bound of object's content
//rightBound - right bound of object's content
std::string _retrieveStreamContent(Object * object, unsigned int leftBound, unsigned int rightBound);
//get stream from Arrey elemetns
std::string _getStreamFromReferencies(Object * objectWithArray, unsigned int leftBound, unsigned int rightBound);
//get stream from Object
std::string _getStreamFromContent(Object * objectWithStream);
//memebers
std::string _concatenatedStream;
};
}
#endif

@ -1,52 +1,52 @@
#ifndef CROPBOX_ELEMENT_HANDLER_H
#define CROPBOX_ELEMENT_HANDLER_H
#include "AbstractBoxElementHandler.h"
#include "Rectangle.h"
namespace merge_lib
{
//class for processing CropBox field of Page object
class CropBoxElementHandler: public AbstractBoxElementHandler
{
public:
CropBoxElementHandler(Object * page): AbstractBoxElementHandler(page)
{
_setHandlerName("/CropBox");
}
virtual ~CropBoxElementHandler()
{
}
private:
//replace CropBox with BBox
virtual void _changeObjectContent(unsigned int startOfPageElement)
{
Rectangle mediaBox("/CropBox", _page->getObjectContent());
double shiftX = Utils::doubleEquals(mediaBox.x1,0)?0:-mediaBox.x1;
double shiftY = Utils::doubleEquals(mediaBox.y1,0)?0:-mediaBox.y1;
mediaBox.setNewRectangleName("/BBox");
unsigned int endOfElement = _findEndOfElementContent(startOfPageElement);
_page->forgetAboutChildren(startOfPageElement,endOfElement);
_page->eraseContent(startOfPageElement,endOfElement-startOfPageElement);
std::string newContent;
mediaBox.appendRectangleToString(newContent," ");
_page->insertToContent(startOfPageElement, newContent);
std::stringstream matrix;
matrix<<"/Matrix [ 1 0 0 1 "<<shiftX<<" "<< shiftY<<" ]\n";
_page->insertToContent(startOfPageElement, matrix.str());
}
void _pageElementNotFound()
{
_retrieveBoxFromParent();
}
};
}
#endif // CROPBOX_ELEMENT_HANDLER_H
#ifndef CROPBOX_ELEMENT_HANDLER_H
#define CROPBOX_ELEMENT_HANDLER_H
#include "AbstractBoxElementHandler.h"
#include "Rectangle.h"
namespace merge_lib
{
//class for processing CropBox field of Page object
class CropBoxElementHandler: public AbstractBoxElementHandler
{
public:
CropBoxElementHandler(Object * page): AbstractBoxElementHandler(page)
{
_setHandlerName("/CropBox");
}
virtual ~CropBoxElementHandler()
{
}
private:
//replace CropBox with BBox
virtual void _changeObjectContent(unsigned int startOfPageElement)
{
Rectangle mediaBox("/CropBox", _page->getObjectContent());
double shiftX = Utils::doubleEquals(mediaBox.x1,0)?0:-mediaBox.x1;
double shiftY = Utils::doubleEquals(mediaBox.y1,0)?0:-mediaBox.y1;
mediaBox.setNewRectangleName("/BBox");
unsigned int endOfElement = _findEndOfElementContent(startOfPageElement);
_page->forgetAboutChildren(startOfPageElement,endOfElement);
_page->eraseContent(startOfPageElement,endOfElement-startOfPageElement);
std::string newContent;
mediaBox.appendRectangleToString(newContent," ");
_page->insertToContent(startOfPageElement, newContent);
std::stringstream matrix;
matrix<<"/Matrix [ 1 0 0 1 "<<shiftX<<" "<< shiftY<<" ]\n";
_page->insertToContent(startOfPageElement, matrix.str());
}
void _pageElementNotFound()
{
_retrieveBoxFromParent();
}
};
}
#endif // CROPBOX_ELEMENT_HANDLER_H

@ -1,22 +1,22 @@
#ifndef DCTDecode_H
#define DCTDecode_H
#include <string>
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class DCTDecode : public Decoder
{
public:
DCTDecode(){};
virtual ~DCTDecode(){};
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded) {return true;};
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef DCTDecode_H
#define DCTDecode_H
#include <string>
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class DCTDecode : public Decoder
{
public:
DCTDecode(){};
virtual ~DCTDecode(){};
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded) {return true;};
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,25 +1,25 @@
#ifndef DECODER_H
#define DECODER_H
#include <string>
#include "Object.h"
namespace merge_lib
{
// base class 4 all decoders
class Decoder
{
public:
Decoder(){};
virtual ~Decoder(){};
virtual bool encode(std::string &decoded) = 0;
virtual bool decode(std::string &encoded) = 0;
//read fields of objectWithStream and initialize internal parameters
//of decoder
virtual void initialize(Object * objectWithStram) = 0;
};
}
#endif // DECODER_H
#ifndef DECODER_H
#define DECODER_H
#include <string>
#include "Object.h"
namespace merge_lib
{
// base class 4 all decoders
class Decoder
{
public:
Decoder(){};
virtual ~Decoder(){};
virtual bool encode(std::string &decoded) = 0;
virtual bool decode(std::string &encoded) = 0;
//read fields of objectWithStream and initialize internal parameters
//of decoder
virtual void initialize(Object * objectWithStram) = 0;
};
}
#endif // DECODER_H

@ -1,36 +1,36 @@
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include <exception>
#include <string>
#include <sstream>
#include <iostream>
namespace merge_lib
{
class Exception : public std::exception
{
public:
Exception() {}
Exception(const char * message) : _message(message) {}
Exception(std::string & message) : _message(message) {}
Exception(std::stringstream & message) : _message(message.str()) {}
Exception(const std::string & message) : _message(message) {}
virtual ~Exception() throw () {}
virtual const char * what() const throw() { return _message.c_str(); }
void show() const {}
protected:
std::string _message;
};
}
#endif // EXCEPTION_HH
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include <exception>
#include <string>
#include <sstream>
#include <iostream>
namespace merge_lib
{
class Exception : public std::exception
{
public:
Exception() {}
Exception(const char * message) : _message(message) {}
Exception(std::string & message) : _message(message) {}
Exception(std::stringstream & message) : _message(message.str()) {}
Exception(const std::string & message) : _message(message) {}
virtual ~Exception() throw () {}
virtual const char * what() const throw() { return _message.c_str(); }
void show() const {}
protected:
std::string _message;
};
}
#endif // EXCEPTION_HH

@ -1,19 +1,19 @@
#if !defined FileIsAbsentException_h
#define FileIsAbsentException_h
#include <string>
class FileIsAbsentException
{
public:
FileIsAbsentException(const char * fileName):
_fileName(fileName){};
const char * getFileName()
{
return _fileName.c_str();
}
private:
std::string _fileName;
};
#endif
#if !defined FileIsAbsentException_h
#define FileIsAbsentException_h
#include <string>
class FileIsAbsentException
{
public:
FileIsAbsentException(const char * fileName):
_fileName(fileName){};
const char * getFileName()
{
return _fileName.c_str();
}
private:
std::string _fileName;
};
#endif

@ -1,264 +1,264 @@
#include "Config.h"
#include <iostream>
#include <map>
#include "FilterPredictor.h"
#include "Utils.h"
#include "Object.h"
#include "Parser.h"
using namespace merge_lib;
const std::string FilterPredictor::PREDICTOR_TOKEN = "/Predictor";
const std::string FilterPredictor::DECODE_PARAM_TOKEN = "/DecodeParms";
const std::string COLUMNS_TOKEN = "/Columns";
const std::string COLORS_TOKEN = "/Colors";
const std::string BITS_TOKEN = "/BitsPerComponent";
const std::string EARLY_TOKEN = "/EarlyChange";
const std::string DICT_START_TOKEN = "<<";
const std::string DICT_END_TOKEN = ">>";
FilterPredictor::FilterPredictor():
_predictor(1),
_colors(1),
_bits(8),
_columns(1),
_earlyChange(1)
{
}
FilterPredictor::~FilterPredictor()
{
}
std::string FilterPredictor::getDictionaryContentStr(std::string & in, size_t &pos )
{
size_t beg = in.find(DICT_START_TOKEN,pos);
if( beg == std::string::npos )
{
return "";
}
beg += DICT_START_TOKEN.size();
size_t end = in.find(DICT_END_TOKEN,beg);
if( end == std::string::npos )
{
return "";
}
return in.substr(beg,end-beg);
}
void FilterPredictor::obtainDecodeParams(Object *objectWithStream, std::string &dictStr)
{
typedef std::map< std::string, int> DecodeParams;
DecodeParams params;
// set some initiaial values
params[PREDICTOR_TOKEN] = _predictor;
params[COLUMNS_TOKEN] = _columns;
params[COLORS_TOKEN] = _colors;
params[BITS_TOKEN] = _bits;
params[EARLY_TOKEN] = _earlyChange;
// lets parse the content of dictionary and set actual values into the map
DecodeParams::iterator it = params.begin();
for(; it != params.end();it++)
{
size_t pos = dictStr.find((*it).first);
if( pos != std::string::npos )
{
pos += (*it).first.size();
// we assume the following pattern "/Colors 8"
std::string numstr = objectWithStream->getNameSimpleValue(dictStr,(*it).first);
if( numstr.empty() )
{
std::cerr<<"Wrong value of "<<(*it).first<<"defined as "<<dictStr<<"\n";
}
int number = Utils::stringToInt(numstr);
//trace("Object number with length = %d",number);
params[(*it).first] = number;
}
}
// refresh the values after reading
_predictor = params[PREDICTOR_TOKEN];
_columns = params[COLUMNS_TOKEN];
_colors = params[COLORS_TOKEN];
_bits = params[BITS_TOKEN];
_earlyChange = params[EARLY_TOKEN];
}
void FilterPredictor::initialize(Object *objectWithStream)
{
if( objectWithStream )
{
std::string content;
objectWithStream->getHeader(content);
// we need to parse the header of file to obtain the decoder parameter
size_t position = content.find(DECODE_PARAM_TOKEN);
if( position != std::string::npos)
{
position += DECODE_PARAM_TOKEN.size();
std::string dictStr = getDictionaryContentStr(content,position);
// trace_hex(dictStr.data(),dictStr.size());
obtainDecodeParams(objectWithStream,dictStr);
}
}
}
//-----------------------------
// Function perorms decoding of one row of data.
//-----------------------------
bool FilterPredictor::decodeRow(const char *in,std::string & out,const std::string &prev,int curPrediction)
{
std::string dec(_bytesPerPixel,'\0');
dec.append(in,_rowLen); // the buffer to decode
int start = _bytesPerPixel;
int end = _bytesPerPixel + _rowLen;
switch(curPrediction)
{
case 2: // TIFF predictor
// to do, implement TIFF predictor
std::cerr<<"TIFF predictor not yet implemented!\n";
return false;
break;
case 1:
case 10: // PNG NONE prediction
// nothing to do, take as is
break;
case 11: // PNG SUB on all raws
for(int i = start;i<end;i++)
{
dec[i] += dec[ i - _bytesPerPixel ];
}
break;
case 12: // PNG UP on all raws
for(int i = start;i<end;i++)
{
dec[i] += prev[i];
}
break;
case 13: // PNG average on all raws
//Average(x) + floor((Raw(x-bpp)+Prior(x))/2)
for(int i = start;i<end;i++)
{
int leftV = int(dec[i - _bytesPerPixel])&0xFF;
int aboveV = int(prev[i - _bytesPerPixel])&0xFF;
unsigned char average = (unsigned char)( (((leftV+aboveV)>>1)&0xFF));
dec[i] += average;
}
break;
case 14: //PNG PAETH on all rows
/*function PaethPredictor (a, b, c)
; a = left, b = above, c = upper left
p := a + b - c ; initial estimate
pa := abs(p - a) ; distances to a, b, c
pb := abs(p - b)
pc := abs(p - c)
; return nearest of a,b,c,
; breaking ties in order a,b,c.
if pa <= pb AND pa <= pc then return a
else if pb <= pc then return b
else return c
Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp))
*/
for(int i = start;i<end;i++)
{
int left = int( dec[i - _bytesPerPixel]) & 0xFF;
int upperLeft = int( prev[i - _bytesPerPixel]) & 0xFF;
int above = int( prev[i]) & 0xFF;
int p = left + above - upperLeft;
int pLeft = abs(p - left);
int pAbove = abs(p - above);
int pUpperLeft = abs(p - upperLeft);
int paeth = 0;
if( pLeft <= pAbove && pLeft <=pUpperLeft )
{
paeth = left;
}
else if( pAbove <= pUpperLeft )
{
paeth = above;
}
else
{
paeth = upperLeft;
}
dec[i] += char (paeth & 0xFF);
}
break;
default:
break;
}
out = dec;
return true;
}
// method performs prediction decoding
bool FilterPredictor::decode(std::string &content)
{
bool isPNG = _predictor >= 10?true:false;
int rowBits = _columns*_colors*_bits;
_rowLen = (rowBits>>3) + (rowBits&7);
_bytesPerPixel = (_colors * _bits + 7) >> 3;
int rows = 0;
if( isPNG )
{
rows = content.size()/(_rowLen+1) + (content.size()% (_rowLen+1));
}
else
{
rows = content.size()/(_rowLen) + (content.size()% (_rowLen) );
}
int inSize = content.size();
std::string out = "";
if( inSize%(isPNG?_rowLen+1:_rowLen) != 0 )
{
std::cerr<<"Warning : wrong PNG identation inSize "<<inSize<<" rowLen = "<<_rowLen<<" isPNG = "<<isPNG<<"\n";
content = out;
return false;
}
const char *curRow = NULL;
std::string prev(_bytesPerPixel+_rowLen,'\0'); //"previous" line
int curPredictor = 1;
for(int i = 0;i<rows;i++)
{
curRow = content.data() + (i* (_rowLen + (isPNG?1:0)) );
if( isPNG )
{
// this is PNG predictor!
curPredictor = *curRow++;
curPredictor +=10;
}
else
{
curPredictor = _predictor; // default NONE predictor
}
std::string dec;
if( !decodeRow(curRow,dec,prev,curPredictor) )
{
std::cerr<<"Unable to process prediction"<<curPredictor<<"!\n";
content = out;
return false;
}
//trace_hex(dec.data()+_bytesPerPixel,_rowLen);
prev = dec;
out += std::string(dec.data()+_bytesPerPixel,_rowLen);
}
content = out;
return true;
}
#include "Config.h"
#include <iostream>
#include <map>
#include "FilterPredictor.h"
#include "Utils.h"
#include "Object.h"
#include "Parser.h"
using namespace merge_lib;
const std::string FilterPredictor::PREDICTOR_TOKEN = "/Predictor";
const std::string FilterPredictor::DECODE_PARAM_TOKEN = "/DecodeParms";
const std::string COLUMNS_TOKEN = "/Columns";
const std::string COLORS_TOKEN = "/Colors";
const std::string BITS_TOKEN = "/BitsPerComponent";
const std::string EARLY_TOKEN = "/EarlyChange";
const std::string DICT_START_TOKEN = "<<";
const std::string DICT_END_TOKEN = ">>";
FilterPredictor::FilterPredictor():
_predictor(1),
_colors(1),
_bits(8),
_columns(1),
_earlyChange(1)
{
}
FilterPredictor::~FilterPredictor()
{
}
std::string FilterPredictor::getDictionaryContentStr(std::string & in, size_t &pos )
{
size_t beg = in.find(DICT_START_TOKEN,pos);
if( beg == std::string::npos )
{
return "";
}
beg += DICT_START_TOKEN.size();
size_t end = in.find(DICT_END_TOKEN,beg);
if( end == std::string::npos )
{
return "";
}
return in.substr(beg,end-beg);
}
void FilterPredictor::obtainDecodeParams(Object *objectWithStream, std::string &dictStr)
{
typedef std::map< std::string, int> DecodeParams;
DecodeParams params;
// set some initiaial values
params[PREDICTOR_TOKEN] = _predictor;
params[COLUMNS_TOKEN] = _columns;
params[COLORS_TOKEN] = _colors;
params[BITS_TOKEN] = _bits;
params[EARLY_TOKEN] = _earlyChange;
// lets parse the content of dictionary and set actual values into the map
DecodeParams::iterator it = params.begin();
for(; it != params.end();it++)
{
size_t pos = dictStr.find((*it).first);
if( pos != std::string::npos )
{
pos += (*it).first.size();
// we assume the following pattern "/Colors 8"
std::string numstr = objectWithStream->getNameSimpleValue(dictStr,(*it).first);
if( numstr.empty() )
{
std::cerr<<"Wrong value of "<<(*it).first<<"defined as "<<dictStr<<"\n";
}
int number = Utils::stringToInt(numstr);
//trace("Object number with length = %d",number);
params[(*it).first] = number;
}
}
// refresh the values after reading
_predictor = params[PREDICTOR_TOKEN];
_columns = params[COLUMNS_TOKEN];
_colors = params[COLORS_TOKEN];
_bits = params[BITS_TOKEN];
_earlyChange = params[EARLY_TOKEN];
}
void FilterPredictor::initialize(Object *objectWithStream)
{
if( objectWithStream )
{
std::string content;
objectWithStream->getHeader(content);
// we need to parse the header of file to obtain the decoder parameter
size_t position = content.find(DECODE_PARAM_TOKEN);
if( position != std::string::npos)
{
position += DECODE_PARAM_TOKEN.size();
std::string dictStr = getDictionaryContentStr(content,position);
// trace_hex(dictStr.data(),dictStr.size());
obtainDecodeParams(objectWithStream,dictStr);
}
}
}
//-----------------------------
// Function perorms decoding of one row of data.
//-----------------------------
bool FilterPredictor::decodeRow(const char *in,std::string & out,const std::string &prev,int curPrediction)
{
std::string dec(_bytesPerPixel,'\0');
dec.append(in,_rowLen); // the buffer to decode
int start = _bytesPerPixel;
int end = _bytesPerPixel + _rowLen;
switch(curPrediction)
{
case 2: // TIFF predictor
// to do, implement TIFF predictor
std::cerr<<"TIFF predictor not yet implemented!\n";
return false;
break;
case 1:
case 10: // PNG NONE prediction
// nothing to do, take as is
break;
case 11: // PNG SUB on all raws
for(int i = start;i<end;i++)
{
dec[i] += dec[ i - _bytesPerPixel ];
}
break;
case 12: // PNG UP on all raws
for(int i = start;i<end;i++)
{
dec[i] += prev[i];
}
break;
case 13: // PNG average on all raws
//Average(x) + floor((Raw(x-bpp)+Prior(x))/2)
for(int i = start;i<end;i++)
{
int leftV = int(dec[i - _bytesPerPixel])&0xFF;
int aboveV = int(prev[i - _bytesPerPixel])&0xFF;
unsigned char average = (unsigned char)( (((leftV+aboveV)>>1)&0xFF));
dec[i] += average;
}
break;
case 14: //PNG PAETH on all rows
/*function PaethPredictor (a, b, c)
; a = left, b = above, c = upper left
p := a + b - c ; initial estimate
pa := abs(p - a) ; distances to a, b, c
pb := abs(p - b)
pc := abs(p - c)
; return nearest of a,b,c,
; breaking ties in order a,b,c.
if pa <= pb AND pa <= pc then return a
else if pb <= pc then return b
else return c
Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp))
*/
for(int i = start;i<end;i++)
{
int left = int( dec[i - _bytesPerPixel]) & 0xFF;
int upperLeft = int( prev[i - _bytesPerPixel]) & 0xFF;
int above = int( prev[i]) & 0xFF;
int p = left + above - upperLeft;
int pLeft = abs(p - left);
int pAbove = abs(p - above);
int pUpperLeft = abs(p - upperLeft);
int paeth = 0;
if( pLeft <= pAbove && pLeft <=pUpperLeft )
{
paeth = left;
}
else if( pAbove <= pUpperLeft )
{
paeth = above;
}
else
{
paeth = upperLeft;
}
dec[i] += char (paeth & 0xFF);
}
break;
default:
break;
}
out = dec;
return true;
}
// method performs prediction decoding
bool FilterPredictor::decode(std::string &content)
{
bool isPNG = _predictor >= 10?true:false;
int rowBits = _columns*_colors*_bits;
_rowLen = (rowBits>>3) + (rowBits&7);
_bytesPerPixel = (_colors * _bits + 7) >> 3;
int rows = 0;
if( isPNG )
{
rows = content.size()/(_rowLen+1) + (content.size()% (_rowLen+1));
}
else
{
rows = content.size()/(_rowLen) + (content.size()% (_rowLen) );
}
int inSize = content.size();
std::string out = "";
if( inSize%(isPNG?_rowLen+1:_rowLen) != 0 )
{
std::cerr<<"Warning : wrong PNG identation inSize "<<inSize<<" rowLen = "<<_rowLen<<" isPNG = "<<isPNG<<"\n";
content = out;
return false;
}
const char *curRow = NULL;
std::string prev(_bytesPerPixel+_rowLen,'\0'); //"previous" line
int curPredictor = 1;
for(int i = 0;i<rows;i++)
{
curRow = content.data() + (i* (_rowLen + (isPNG?1:0)) );
if( isPNG )
{
// this is PNG predictor!
curPredictor = *curRow++;
curPredictor +=10;
}
else
{
curPredictor = _predictor; // default NONE predictor
}
std::string dec;
if( !decodeRow(curRow,dec,prev,curPredictor) )
{
std::cerr<<"Unable to process prediction"<<curPredictor<<"!\n";
content = out;
return false;
}
//trace_hex(dec.data()+_bytesPerPixel,_rowLen);
prev = dec;
out += std::string(dec.data()+_bytesPerPixel,_rowLen);
}
content = out;
return true;
}

@ -1,44 +1,44 @@
#ifndef FILTER_PREDICTOR_H
#define FILTER_PREDICTOR_H
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this method performs filter prediction processing.
class FilterPredictor:public Decoder
{
public:
FilterPredictor();
virtual ~FilterPredictor();
bool encode(std::string & decoded){return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStream);
static const std::string PREDICTOR_TOKEN;
static const std::string DECODE_PARAM_TOKEN;
int getEarlyChange() const { return _earlyChange;}
private:
bool decodeRow(const char *input, std::string &out,const std::string &prev,int curPrediction);
void obtainDecodeParams(Object*objectWithStream,std::string &dictStr);
std::string getDictionaryContentStr(std::string & in, size_t &pos );
int _predictor;
int _colors;
int _bits;
int _columns;
int _earlyChange;
int _rowLen;
int _bytesPerPixel;
};
}
#endif
#ifndef FILTER_PREDICTOR_H
#define FILTER_PREDICTOR_H
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this method performs filter prediction processing.
class FilterPredictor:public Decoder
{
public:
FilterPredictor();
virtual ~FilterPredictor();
bool encode(std::string & decoded){return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStream);
static const std::string PREDICTOR_TOKEN;
static const std::string DECODE_PARAM_TOKEN;
int getEarlyChange() const { return _earlyChange;}
private:
bool decodeRow(const char *input, std::string &out,const std::string &prev,int curPrediction);
void obtainDecodeParams(Object*objectWithStream,std::string &dictStr);
std::string getDictionaryContentStr(std::string & in, size_t &pos );
int _predictor;
int _colors;
int _bits;
int _columns;
int _earlyChange;
int _rowLen;
int _bytesPerPixel;
};
}
#endif

@ -1,202 +1,202 @@
#include <iostream>
#include "FlateDecode.h"
#include "zlib.h"
#include "Utils.h"
#include <string.h>
using namespace merge_lib;
#define ZLIB_MEM_DELTA 65535
#define ZLIB_CHECK_ERR(err,msg) \
if( err != Z_OK) {\
std::cout<<msg<<" ZLIB error:"<<err<<std::endl; \
}\
FlateDecode::FlateDecode():_predict(NULL)
{
}
FlateDecode::~FlateDecode()
{
if( _predict )
{
delete _predict;
}
}
void FlateDecode::initialize(Object * objectWithStream)
{
if( objectWithStream )
{
std::string head;
objectWithStream->getHeader(head);
if( head.find(FilterPredictor::DECODE_PARAM_TOKEN) != std::string::npos )
{
_predict = new FilterPredictor();
_predict->initialize(objectWithStream);
}
}
}
/** @brief encode
*
* @todo:
document this function
*/
bool FlateDecode::encode(std::string &decoded)
{
z_stream stream;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
size_t out_len = 0;
unsigned char *out_p = NULL;
stream.next_out = out_p;
stream.avail_out = (uInt)out_len;
stream.next_in = (unsigned char*)decoded.c_str();
stream.avail_in = (uInt)decoded.size();
int err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
ZLIB_CHECK_ERR(err, "deflateInit");
if ( err != Z_OK )
{
return false;
}
bool toContinue = false;
int flush = Z_NO_FLUSH;
do
{
toContinue = false;
flush = (stream.avail_in == 0)?Z_FINISH:Z_NO_FLUSH;
if ( !stream.avail_out )
{
// increase the space
out_p = (unsigned char*)realloc(out_p,out_len + ZLIB_MEM_DELTA);
// init new memory
unsigned char *new_out_start = out_p + out_len;
memset(new_out_start,0,ZLIB_MEM_DELTA);
// Point next_out to the next unused byte
stream.next_out = new_out_start;
// Update the size of the buffer
stream.avail_out = (uInt)ZLIB_MEM_DELTA;
out_len += ZLIB_MEM_DELTA;
}
err = deflate(&stream,flush);
if ( err == Z_OK && stream.avail_out == 0 )
{
toContinue = true;
}
}
while ( toContinue || flush == Z_NO_FLUSH );
err = deflateEnd(&stream);
ZLIB_CHECK_ERR(err, "deflateEnd");
if( err != Z_OK )
{
free(out_p);
return false;
}
decoded = std::string((char*)out_p,stream.total_out);
free(out_p);
return true;
}
/** @brief decode
*
* @todo: document this function
*/
bool FlateDecode::decode(std::string & encoded)
{
z_stream stream;
//some initialization of ZLIB stuff
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
//trace_hex((char*)encoded.c_str(),encoded.size());
stream.next_in = (unsigned char*)encoded.c_str();
stream.avail_in = (uInt)encoded.size();
int err = inflateInit(&stream);
ZLIB_CHECK_ERR(err,"InflateInit");
if ( err != Z_OK )
{
return false;
}
unsigned char *out_p = NULL;
int out_len = 0;
stream.next_out = out_p;
stream.avail_out = out_len;
for (;;)
{
if ( !stream.avail_out)
{
// there is no more space for deallocation - increase the space
out_p = (unsigned char*)realloc(out_p,out_len + ZLIB_MEM_DELTA);
// init new memory
unsigned char *new_out_start = out_p + out_len;
memset(new_out_start,0,ZLIB_MEM_DELTA);
// Point next_out to the next unused byte
stream.next_out = new_out_start;
// Update the size of the uncompressed buffer
stream.avail_out = (uInt)ZLIB_MEM_DELTA;
out_len += ZLIB_MEM_DELTA;
}
err = inflate(&stream,Z_NO_FLUSH);
if ( err == Z_STREAM_END)
{
break;
}
ZLIB_CHECK_ERR(err,"Deflate");
if ( err != Z_OK )
{
if( out_p )
{
free(out_p);
}
return false;
}
}
err = inflateEnd(&stream);
ZLIB_CHECK_ERR(err,"InflateEnd");
if( err != Z_OK )
{
if( out_p )
{
free(out_p);
}
return false;
}
encoded = std::string((char*)out_p,stream.total_out);
free(out_p);
// trace_hex((char*)encoded.c_str(),encoded.size());
// if predictor exists for that object, then lets decode it
if( _predict )
{
_predict->decode(encoded);
}
return true;
}
#include <iostream>
#include "FlateDecode.h"
#include "zlib.h"
#include "Utils.h"
#include <string.h>
using namespace merge_lib;
#define ZLIB_MEM_DELTA 65535
#define ZLIB_CHECK_ERR(err,msg) \
if( err != Z_OK) {\
std::cout<<msg<<" ZLIB error:"<<err<<std::endl; \
}\
FlateDecode::FlateDecode():_predict(NULL)
{
}
FlateDecode::~FlateDecode()
{
if( _predict )
{
delete _predict;
}
}
void FlateDecode::initialize(Object * objectWithStream)
{
if( objectWithStream )
{
std::string head;
objectWithStream->getHeader(head);
if( head.find(FilterPredictor::DECODE_PARAM_TOKEN) != std::string::npos )
{
_predict = new FilterPredictor();
_predict->initialize(objectWithStream);
}
}
}
/** @brief encode
*
* @todo:
document this function
*/
bool FlateDecode::encode(std::string &decoded)
{
z_stream stream;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
size_t out_len = 0;
unsigned char *out_p = NULL;
stream.next_out = out_p;
stream.avail_out = (uInt)out_len;
stream.next_in = (unsigned char*)decoded.c_str();
stream.avail_in = (uInt)decoded.size();
int err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
ZLIB_CHECK_ERR(err, "deflateInit");
if ( err != Z_OK )
{
return false;
}
bool toContinue = false;
int flush = Z_NO_FLUSH;
do
{
toContinue = false;
flush = (stream.avail_in == 0)?Z_FINISH:Z_NO_FLUSH;
if ( !stream.avail_out )
{
// increase the space
out_p = (unsigned char*)realloc(out_p,out_len + ZLIB_MEM_DELTA);
// init new memory
unsigned char *new_out_start = out_p + out_len;
memset(new_out_start,0,ZLIB_MEM_DELTA);
// Point next_out to the next unused byte
stream.next_out = new_out_start;
// Update the size of the buffer
stream.avail_out = (uInt)ZLIB_MEM_DELTA;
out_len += ZLIB_MEM_DELTA;
}
err = deflate(&stream,flush);
if ( err == Z_OK && stream.avail_out == 0 )
{
toContinue = true;
}
}
while ( toContinue || flush == Z_NO_FLUSH );
err = deflateEnd(&stream);
ZLIB_CHECK_ERR(err, "deflateEnd");
if( err != Z_OK )
{
free(out_p);
return false;
}
decoded = std::string((char*)out_p,stream.total_out);
free(out_p);
return true;
}
/** @brief decode
*
* @todo: document this function
*/
bool FlateDecode::decode(std::string & encoded)
{
z_stream stream;
//some initialization of ZLIB stuff
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
//trace_hex((char*)encoded.c_str(),encoded.size());
stream.next_in = (unsigned char*)encoded.c_str();
stream.avail_in = (uInt)encoded.size();
int err = inflateInit(&stream);
ZLIB_CHECK_ERR(err,"InflateInit");
if ( err != Z_OK )
{
return false;
}
unsigned char *out_p = NULL;
int out_len = 0;
stream.next_out = out_p;
stream.avail_out = out_len;
for (;;)
{
if ( !stream.avail_out)
{
// there is no more space for deallocation - increase the space
out_p = (unsigned char*)realloc(out_p,out_len + ZLIB_MEM_DELTA);
// init new memory
unsigned char *new_out_start = out_p + out_len;
memset(new_out_start,0,ZLIB_MEM_DELTA);
// Point next_out to the next unused byte
stream.next_out = new_out_start;
// Update the size of the uncompressed buffer
stream.avail_out = (uInt)ZLIB_MEM_DELTA;
out_len += ZLIB_MEM_DELTA;
}
err = inflate(&stream,Z_NO_FLUSH);
if ( err == Z_STREAM_END)
{
break;
}
ZLIB_CHECK_ERR(err,"Deflate");
if ( err != Z_OK )
{
if( out_p )
{
free(out_p);
}
return false;
}
}
err = inflateEnd(&stream);
ZLIB_CHECK_ERR(err,"InflateEnd");
if( err != Z_OK )
{
if( out_p )
{
free(out_p);
}
return false;
}
encoded = std::string((char*)out_p,stream.total_out);
free(out_p);
// trace_hex((char*)encoded.c_str(),encoded.size());
// if predictor exists for that object, then lets decode it
if( _predict )
{
_predict->decode(encoded);
}
return true;
}

@ -1,26 +1,26 @@
#ifndef FLATEDECODE_H_INCLUDED
#define FLATEDECODE_H_INCLUDED
#include "Decoder.h"
#include <string>
#include "Decoder.h"
#include "FilterPredictor.h"
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class FlateDecode : public Decoder
{
public:
FlateDecode();
virtual ~FlateDecode();
bool encode(std::string & decoded);
bool decode(std::string & encoded);
void initialize(Object * objectWithStream);
private:
FilterPredictor *_predict;
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef FLATEDECODE_H_INCLUDED
#define FLATEDECODE_H_INCLUDED
#include "Decoder.h"
#include <string>
#include "Decoder.h"
#include "FilterPredictor.h"
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class FlateDecode : public Decoder
{
public:
FlateDecode();
virtual ~FlateDecode();
bool encode(std::string & decoded);
bool decode(std::string & encoded);
void initialize(Object * objectWithStream);
private:
FilterPredictor *_predict;
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,22 +1,22 @@
#ifndef JBIG2Decode_H
#define JBIG2Decode_H
#include <string>
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class JBIG2Decode : public Decoder
{
public:
JBIG2Decode(){};
virtual ~JBIG2Decode(){};
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded) {return true;};
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef JBIG2Decode_H
#define JBIG2Decode_H
#include <string>
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class JBIG2Decode : public Decoder
{
public:
JBIG2Decode(){};
virtual ~JBIG2Decode(){};
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded) {return true;};
void initialize(Object * objectWithStram){};
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,193 +1,193 @@
#include <iostream>
#include "LZWDecode.h"
#include "FilterPredictor.h"
// method performs decoding
using namespace merge_lib;
LZWDecode::LZWDecode():
_predict(NULL),
_dummy(""),
_encoded(_dummy),
_curSymbolIndex(0),
_earlyChange(1),
_readBuf(0),
_readBits(0),
_nextCode(0),
_bitsToRead(0),
_curSequenceLength(0),
_first(true)
{
clearTable();
}
LZWDecode::~LZWDecode()
{
if( _predict )
{
delete _predict;
}
}
void LZWDecode::initialize(Object * objectWithStream)
{
if( objectWithStream )
{
std::string head;
objectWithStream->getHeader(head);
if( head.find(FilterPredictor::DECODE_PARAM_TOKEN) != std::string::npos )
{
_predict = new FilterPredictor();
_predict->initialize(objectWithStream);
_earlyChange = _predict->getEarlyChange();
}
_readBits = 0;
_readBuf = 0;
clearTable();
}
}
void LZWDecode::clearTable()
{
_nextCode = 258;
_bitsToRead = 9;
_curSequenceLength = 0;
_first = true;
}
int LZWDecode::getCode()
{
int c = 0;
int code = 0;
while (_readBits < _bitsToRead)
{
if( _curSymbolIndex < _encoded.size() )
{
c = _encoded[_curSymbolIndex++];
}
else
{
return EOF;
}
_readBuf = (_readBuf << 8) | (c & 0xff);
_readBits += 8;
}
code = (_readBuf >> (_readBits - _bitsToRead)) & ((1 << _bitsToRead) - 1);
_readBits -= _bitsToRead;
return code;
}
// Method performs LZW decoding
bool LZWDecode::decode(std::string & encoded)
{
_curSymbolIndex = 0;
_encoded = encoded;
// LZW decoding
std::string decoded;
struct DecodingTable
{
int length;
int head;
unsigned tail;
} decTable[4097];
int prevCode = 0;
int newChar = 0;
unsigned curSequence[4097];
int nextLength = 0;
clearTable();
while(1)
{
int code = getCode();
if( code == EOF || code == 257 )
{
// finish
break;
}
if( code == 256 )
{
clearTable();
continue;
}
if( _nextCode >= 4997 )
{
std::cout<<"Bad LZW stream - unexpected clearTable\n";
clearTable();
continue;
}
nextLength = _curSequenceLength + 1;
if( code < 256 )
{
curSequence[ 0 ] = code;
_curSequenceLength = 1;
}
else if( code < _nextCode )
{
//lets take sequence from table
_curSequenceLength = decTable[code].length;
int j = code;
for( int i = _curSequenceLength - 1; i > 0; i--)
{
curSequence[ i ] = decTable[j].tail;
j = decTable[ j ].head;
}
curSequence[0] = j;
}
else if( code == _nextCode )
{
curSequence[ _curSequenceLength ] = newChar;
++_curSequenceLength;
}
else
{
std::cout<<"Bad LZW stream - unexpected code "<<code<<"\n";
break;
}
newChar = curSequence[0];
if( _first )
{
_first = false;
}
else
{
// lets build decoding table
decTable[ _nextCode ].length = nextLength;
decTable[ _nextCode ].head = prevCode;
decTable[ _nextCode ].tail = newChar;
++ _nextCode;
// processing of PDF LZW parameter
if (_nextCode + _earlyChange == 512)
{
_bitsToRead = 10;
}
else if (_nextCode + _earlyChange == 1024)
{
_bitsToRead = 11;
}
else if (_nextCode + _earlyChange == 2048)
{
_bitsToRead = 12;
}
}
prevCode = code;
// put current sequence to output stream
for(int i = 0;i < _curSequenceLength;i++)
{
decoded += (char)curSequence[ i ];
}
}
encoded = decoded;
// if predictor exists for that object, then lets decode it
if( _predict )
{
_predict->decode(encoded);
}
return true;
}
#include <iostream>
#include "LZWDecode.h"
#include "FilterPredictor.h"
// method performs decoding
using namespace merge_lib;
LZWDecode::LZWDecode():
_predict(NULL),
_dummy(""),
_encoded(_dummy),
_curSymbolIndex(0),
_earlyChange(1),
_readBuf(0),
_readBits(0),
_nextCode(0),
_bitsToRead(0),
_curSequenceLength(0),
_first(true)
{
clearTable();
}
LZWDecode::~LZWDecode()
{
if( _predict )
{
delete _predict;
}
}
void LZWDecode::initialize(Object * objectWithStream)
{
if( objectWithStream )
{
std::string head;
objectWithStream->getHeader(head);
if( head.find(FilterPredictor::DECODE_PARAM_TOKEN) != std::string::npos )
{
_predict = new FilterPredictor();
_predict->initialize(objectWithStream);
_earlyChange = _predict->getEarlyChange();
}
_readBits = 0;
_readBuf = 0;
clearTable();
}
}
void LZWDecode::clearTable()
{
_nextCode = 258;
_bitsToRead = 9;
_curSequenceLength = 0;
_first = true;
}
int LZWDecode::getCode()
{
int c = 0;
int code = 0;
while (_readBits < _bitsToRead)
{
if( _curSymbolIndex < _encoded.size() )
{
c = _encoded[_curSymbolIndex++];
}
else
{
return EOF;
}
_readBuf = (_readBuf << 8) | (c & 0xff);
_readBits += 8;
}
code = (_readBuf >> (_readBits - _bitsToRead)) & ((1 << _bitsToRead) - 1);
_readBits -= _bitsToRead;
return code;
}
// Method performs LZW decoding
bool LZWDecode::decode(std::string & encoded)
{
_curSymbolIndex = 0;
_encoded = encoded;
// LZW decoding
std::string decoded;
struct DecodingTable
{
int length;
int head;
unsigned tail;
} decTable[4097];
int prevCode = 0;
int newChar = 0;
unsigned curSequence[4097];
int nextLength = 0;
clearTable();
while(1)
{
int code = getCode();
if( code == EOF || code == 257 )
{
// finish
break;
}
if( code == 256 )
{
clearTable();
continue;
}
if( _nextCode >= 4997 )
{
std::cout<<"Bad LZW stream - unexpected clearTable\n";
clearTable();
continue;
}
nextLength = _curSequenceLength + 1;
if( code < 256 )
{
curSequence[ 0 ] = code;
_curSequenceLength = 1;
}
else if( code < _nextCode )
{
//lets take sequence from table
_curSequenceLength = decTable[code].length;
int j = code;
for( int i = _curSequenceLength - 1; i > 0; i--)
{
curSequence[ i ] = decTable[j].tail;
j = decTable[ j ].head;
}
curSequence[0] = j;
}
else if( code == _nextCode )
{
curSequence[ _curSequenceLength ] = newChar;
++_curSequenceLength;
}
else
{
std::cout<<"Bad LZW stream - unexpected code "<<code<<"\n";
break;
}
newChar = curSequence[0];
if( _first )
{
_first = false;
}
else
{
// lets build decoding table
decTable[ _nextCode ].length = nextLength;
decTable[ _nextCode ].head = prevCode;
decTable[ _nextCode ].tail = newChar;
++ _nextCode;
// processing of PDF LZW parameter
if (_nextCode + _earlyChange == 512)
{
_bitsToRead = 10;
}
else if (_nextCode + _earlyChange == 1024)
{
_bitsToRead = 11;
}
else if (_nextCode + _earlyChange == 2048)
{
_bitsToRead = 12;
}
}
prevCode = code;
// put current sequence to output stream
for(int i = 0;i < _curSequenceLength;i++)
{
decoded += (char)curSequence[ i ];
}
}
encoded = decoded;
// if predictor exists for that object, then lets decode it
if( _predict )
{
_predict->decode(encoded);
}
return true;
}

@ -1,41 +1,41 @@
#ifndef LZWDecode_H
#define LZWDecode_H
#include <string>
#include "Decoder.h"
#include "FilterPredictor.h"
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class LZWDecode : public Decoder
{
public:
LZWDecode();
virtual ~LZWDecode();
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded);
void initialize(Object * objectWithStram);
private:
FilterPredictor *_predict;
void clearTable();
int getCode();
std::string &_encoded;
std::string _dummy;
size_t _curSymbolIndex;
int _earlyChange; // early parameter
int _readBuf;
int _readBits;
int _nextCode;
int _bitsToRead;
bool _first;
int _curSequenceLength;
};
}
#endif // LZW_DECODE_H_INCLUDED
#ifndef LZWDecode_H
#define LZWDecode_H
#include <string>
#include "Decoder.h"
#include "FilterPredictor.h"
namespace merge_lib
{
// this class provides method for FlateDecode encoding and decoding
class LZWDecode : public Decoder
{
public:
LZWDecode();
virtual ~LZWDecode();
bool encode(std::string & decoded) {return true;};
bool decode(std::string & encoded);
void initialize(Object * objectWithStram);
private:
FilterPredictor *_predict;
void clearTable();
int getCode();
std::string &_encoded;
std::string _dummy;
size_t _curSymbolIndex;
int _earlyChange; // early parameter
int _readBuf;
int _readBits;
int _nextCode;
int _bitsToRead;
bool _first;
int _curSequenceLength;
};
}
#endif // LZW_DECODE_H_INCLUDED

@ -1,52 +1,52 @@
#if !defined MediaBoxElementHandler_h
#define MediaBoxElementHandler_h
#include "AbstractBoxElementHandler.h"
#include "RemoveHimSelfHandler.h"
#include <memory>
namespace merge_lib
{
//class for processing MediaBox field of Page object
class MediaBoxElementHandler: public AbstractBoxElementHandler
{
public:
MediaBoxElementHandler(Object * page): AbstractBoxElementHandler(page)
{
_setHandlerName("/MediaBox");
}
virtual ~MediaBoxElementHandler()
{
}
private:
//replace MediaBox with BBox
virtual void _changeObjectContent(unsigned int startOfPageElement)
{
if(_wasCropBoxHandlerCalled())
{
PageElementHandler * tempNextHandler = _nextHandler;
_nextHandler = new RemoveHimselfHandler(_page, _handlerName);
_nextHandler->addNextHandler(tempNextHandler);
return;
}
_page->eraseContent(startOfPageElement, _handlerName.size());
static std::string bbox("/BBox");
static std::string matrix("/Matrix [ 1 0 0 1 0 0 ]\n");
_page->insertToContent(startOfPageElement, bbox);
_page->insertToContent(startOfPageElement, matrix);
}
void _pageElementNotFound()
{
if(_wasCropBoxHandlerCalled())
return;
_retrieveBoxFromParent();
}
bool _wasCropBoxHandlerCalled()
{
return (_page->getObjectContent().find("/BBox") != std::string::npos) ? true : false;
}
};
}
#endif
#if !defined MediaBoxElementHandler_h
#define MediaBoxElementHandler_h
#include "AbstractBoxElementHandler.h"
#include "RemoveHimSelfHandler.h"
#include <memory>
namespace merge_lib
{
//class for processing MediaBox field of Page object
class MediaBoxElementHandler: public AbstractBoxElementHandler
{
public:
MediaBoxElementHandler(Object * page): AbstractBoxElementHandler(page)
{
_setHandlerName("/MediaBox");
}
virtual ~MediaBoxElementHandler()
{
}
private:
//replace MediaBox with BBox
virtual void _changeObjectContent(unsigned int startOfPageElement)
{
if(_wasCropBoxHandlerCalled())
{
PageElementHandler * tempNextHandler = _nextHandler;
_nextHandler = new RemoveHimselfHandler(_page, _handlerName);
_nextHandler->addNextHandler(tempNextHandler);
return;
}
_page->eraseContent(startOfPageElement, _handlerName.size());
static std::string bbox("/BBox");
static std::string matrix("/Matrix [ 1 0 0 1 0 0 ]\n");
_page->insertToContent(startOfPageElement, bbox);
_page->insertToContent(startOfPageElement, matrix);
}
void _pageElementNotFound()
{
if(_wasCropBoxHandlerCalled())
return;
_retrieveBoxFromParent();
}
bool _wasCropBoxHandlerCalled()
{
return (_page->getObjectContent().find("/BBox") != std::string::npos) ? true : false;
}
};
}
#endif

@ -1,97 +1,97 @@
#if !defined MergePageDescription_h
#define MergePageDescription_h
#include "Transformation.h"
#include <map>
#include <string>
namespace merge_lib
{
struct MergePageDescription
{
//members:
double outPageWidth; // output page width
double outPageHeight; // output page height
unsigned int basePageNumber;
std::string baseDocumentName;
TransformationDescription basePageTransformation;
unsigned int overlayPageNumber;
TransformationDescription overlayPageTransformation;
bool skipOverlayPage;
bool skipBasePage;
//methods:
//constructor
MergePageDescription(double outputPageWidth,
double outputPageHeight,
unsigned int basePageNum,
const char * baseDocName,
const TransformationDescription & baseTrans,
unsigned int overlayPageNum,
const TransformationDescription & overlayTrans,
bool omitOverlayPage = false,
bool omitBasePage = false
):
outPageWidth(outputPageWidth),
outPageHeight(outputPageHeight),
basePageNumber(basePageNum),
baseDocumentName(baseDocName),
basePageTransformation(baseTrans),
overlayPageNumber(overlayPageNum),
overlayPageTransformation(overlayTrans),
skipOverlayPage(omitOverlayPage),
skipBasePage(omitBasePage)
{
}
MergePageDescription(double outputPageWidth,
double outputPageHeight,
unsigned int basePageNum,
const char * baseDocName,
const TransformationDescription & baseTrans
):
outPageWidth(outputPageWidth),
outPageHeight(outputPageHeight),
basePageNumber(basePageNum),
baseDocumentName(baseDocName),
basePageTransformation(baseTrans),
overlayPageNumber(0),
overlayPageTransformation(),
skipOverlayPage(true),
skipBasePage(false)
{
}
MergePageDescription(const MergePageDescription & copy)
{
*this = copy;
}
MergePageDescription& operator = (const MergePageDescription &copy)
{
if( this != &copy )
{
baseDocumentName = copy.baseDocumentName;
basePageNumber = copy.basePageNumber;
skipBasePage = copy.skipBasePage;
skipOverlayPage = copy.skipOverlayPage;
outPageHeight = copy.outPageHeight;
outPageWidth = copy.outPageWidth;
basePageTransformation = copy.basePageTransformation;
overlayPageNumber = copy.overlayPageNumber;
overlayPageTransformation = copy.overlayPageTransformation;
}
return *this;
}
~MergePageDescription()
{
}
};
// array of merge descriptions - allows to merge selected pages
typedef std::vector<MergePageDescription> MergeDescription;
}
#endif
#if !defined MergePageDescription_h
#define MergePageDescription_h
#include "Transformation.h"
#include <map>
#include <string>
namespace merge_lib
{
struct MergePageDescription
{
//members:
double outPageWidth; // output page width
double outPageHeight; // output page height
unsigned int basePageNumber;
std::string baseDocumentName;
TransformationDescription basePageTransformation;
unsigned int overlayPageNumber;
TransformationDescription overlayPageTransformation;
bool skipOverlayPage;
bool skipBasePage;
//methods:
//constructor
MergePageDescription(double outputPageWidth,
double outputPageHeight,
unsigned int basePageNum,
const char * baseDocName,
const TransformationDescription & baseTrans,
unsigned int overlayPageNum,
const TransformationDescription & overlayTrans,
bool omitOverlayPage = false,
bool omitBasePage = false
):
outPageWidth(outputPageWidth),
outPageHeight(outputPageHeight),
basePageNumber(basePageNum),
baseDocumentName(baseDocName),
basePageTransformation(baseTrans),
overlayPageNumber(overlayPageNum),
overlayPageTransformation(overlayTrans),
skipOverlayPage(omitOverlayPage),
skipBasePage(omitBasePage)
{
}
MergePageDescription(double outputPageWidth,
double outputPageHeight,
unsigned int basePageNum,
const char * baseDocName,
const TransformationDescription & baseTrans
):
outPageWidth(outputPageWidth),
outPageHeight(outputPageHeight),
basePageNumber(basePageNum),
baseDocumentName(baseDocName),
basePageTransformation(baseTrans),
overlayPageNumber(0),
overlayPageTransformation(),
skipOverlayPage(true),
skipBasePage(false)
{
}
MergePageDescription(const MergePageDescription & copy)
{
*this = copy;
}
MergePageDescription& operator = (const MergePageDescription &copy)
{
if( this != &copy )
{
baseDocumentName = copy.baseDocumentName;
basePageNumber = copy.basePageNumber;
skipBasePage = copy.skipBasePage;
skipOverlayPage = copy.skipOverlayPage;
outPageHeight = copy.outPageHeight;
outPageWidth = copy.outPageWidth;
basePageTransformation = copy.basePageTransformation;
overlayPageNumber = copy.overlayPageNumber;
overlayPageTransformation = copy.overlayPageTransformation;
}
return *this;
}
~MergePageDescription()
{
}
};
// array of merge descriptions - allows to merge selected pages
typedef std::vector<MergePageDescription> MergeDescription;
}
#endif

@ -1,115 +1,115 @@
///////////////////////////////////////////////////////////
// Merger.cpp
// Implementation of the Class Merger
// Created on: 19-???-2009 12:27:54
///////////////////////////////////////////////////////////
#include "Merger.h"
#include "Parser.h"
#include "OverlayDocumentParser.h"
#include "Exception.h"
#include <map>
#include <iostream>
using namespace merge_lib;
Parser Merger::_parser;
Merger::Merger():_baseDocuments(),_overlayDocument(0)
{
}
Merger::~Merger()
{
std::map<std::string, Document *>::iterator docIterator = _baseDocuments.begin();
for(; docIterator != _baseDocuments.end(); ++docIterator)
{
delete (*docIterator).second;
}
if( _overlayDocument )
{
delete _overlayDocument;
_overlayDocument = 0;
}
_baseDocuments.clear();
}
void Merger::addBaseDocument(const char * docName)
{
//if docName has been already opened then do nothing
if(_baseDocuments.count(docName))
return;
Document * newBaseDoc = _parser.parseDocument(docName);
_baseDocuments.insert(std::pair<std::string, Document *>(docName, newBaseDoc));
}
void Merger::addOverlayDocument(const char * docName)
{
if( _overlayDocument )
{
delete _overlayDocument;
_overlayDocument = 0;
}
if( !_overlayDocument )
{
OverlayDocumentParser overlayDocParser;
_overlayDocument = overlayDocParser.parseDocument(docName);
if( !_overlayDocument )
{
throw Exception("Error loading overlay document!");
}
}
}
// The main method which performs the merge
void Merger::merge(const char * overlayDocName, const MergeDescription & pagesToMerge)
{
if( !_overlayDocument)
{
addOverlayDocument(overlayDocName);
if( !_overlayDocument )
{
throw Exception("Error loading overlay document!");
}
}
MergeDescription::const_iterator pageIterator = pagesToMerge.begin();
for(; pageIterator != pagesToMerge.end(); ++pageIterator )
{
Page * destinationPage = _overlayDocument->getPage( (*pageIterator).overlayPageNumber);
if( destinationPage == 0 )
{
std::stringstream error;
error << "There is no page with " << (*pageIterator).overlayPageNumber <<
" number in " << overlayDocName;
throw Exception(error);
}
Document * sourceDocument = _baseDocuments[(*pageIterator).baseDocumentName];
Page * sourcePage = (sourceDocument == 0)? 0 : sourceDocument->getPage((*pageIterator).basePageNumber);
bool isPageDuplicated = false;
if( sourcePage )
{
unsigned int howManyTimesPageFound(0);
for(size_t i = 0; i < pagesToMerge.size(); ++i)
{
if(pagesToMerge[i].basePageNumber == (*pageIterator).basePageNumber)
++howManyTimesPageFound;
if(howManyTimesPageFound == 2)
break;
}
isPageDuplicated = (2 == howManyTimesPageFound) ? true : false;
}
destinationPage->merge(sourcePage, _overlayDocument, const_cast<MergePageDescription&>((*pageIterator)), isPageDuplicated);
}
}
// Method performs saving of merged documents into selected file
void Merger::saveMergedDocumentsAs(const char * outDocumentName)
{
_overlayDocument->saveAs(outDocumentName);
}
///////////////////////////////////////////////////////////
// Merger.cpp
// Implementation of the Class Merger
// Created on: 19-???-2009 12:27:54
///////////////////////////////////////////////////////////
#include "Merger.h"
#include "Parser.h"
#include "OverlayDocumentParser.h"
#include "Exception.h"
#include <map>
#include <iostream>
using namespace merge_lib;
Parser Merger::_parser;
Merger::Merger():_baseDocuments(),_overlayDocument(0)
{
}
Merger::~Merger()
{
std::map<std::string, Document *>::iterator docIterator = _baseDocuments.begin();
for(; docIterator != _baseDocuments.end(); ++docIterator)
{
delete (*docIterator).second;
}
if( _overlayDocument )
{
delete _overlayDocument;
_overlayDocument = 0;
}
_baseDocuments.clear();
}
void Merger::addBaseDocument(const char * docName)
{
//if docName has been already opened then do nothing
if(_baseDocuments.count(docName))
return;
Document * newBaseDoc = _parser.parseDocument(docName);
_baseDocuments.insert(std::pair<std::string, Document *>(docName, newBaseDoc));
}
void Merger::addOverlayDocument(const char * docName)
{
if( _overlayDocument )
{
delete _overlayDocument;
_overlayDocument = 0;
}
if( !_overlayDocument )
{
OverlayDocumentParser overlayDocParser;
_overlayDocument = overlayDocParser.parseDocument(docName);
if( !_overlayDocument )
{
throw Exception("Error loading overlay document!");
}
}
}
// The main method which performs the merge
void Merger::merge(const char * overlayDocName, const MergeDescription & pagesToMerge)
{
if( !_overlayDocument)
{
addOverlayDocument(overlayDocName);
if( !_overlayDocument )
{
throw Exception("Error loading overlay document!");
}
}
MergeDescription::const_iterator pageIterator = pagesToMerge.begin();
for(; pageIterator != pagesToMerge.end(); ++pageIterator )
{
Page * destinationPage = _overlayDocument->getPage( (*pageIterator).overlayPageNumber);
if( destinationPage == 0 )
{
std::stringstream error;
error << "There is no page with " << (*pageIterator).overlayPageNumber <<
" number in " << overlayDocName;
throw Exception(error);
}
Document * sourceDocument = _baseDocuments[(*pageIterator).baseDocumentName];
Page * sourcePage = (sourceDocument == 0)? 0 : sourceDocument->getPage((*pageIterator).basePageNumber);
bool isPageDuplicated = false;
if( sourcePage )
{
unsigned int howManyTimesPageFound(0);
for(size_t i = 0; i < pagesToMerge.size(); ++i)
{
if(pagesToMerge[i].basePageNumber == (*pageIterator).basePageNumber)
++howManyTimesPageFound;
if(howManyTimesPageFound == 2)
break;
}
isPageDuplicated = (2 == howManyTimesPageFound) ? true : false;
}
destinationPage->merge(sourcePage, _overlayDocument, const_cast<MergePageDescription&>((*pageIterator)), isPageDuplicated);
}
}
// Method performs saving of merged documents into selected file
void Merger::saveMergedDocumentsAs(const char * outDocumentName)
{
_overlayDocument->saveAs(outDocumentName);
}

@ -1,42 +1,42 @@
///////////////////////////////////////////////////////////
// Merger.h
// Implementation of the Class Merger
// Created on: 19-èþí-2009 12:27:54
///////////////////////////////////////////////////////////
#if !defined Merger_h
#define Merger_h
#include "Document.h"
#include "Parser.h"
#include <map>
// structure defines parameter of merge
namespace merge_lib
{
class Document;
class Merger
{
public:
Merger();
~Merger();
//this method should be called every time the "Add" button is clicked
void addBaseDocument(const char *docName);
void addOverlayDocument(const char *docName);
void saveMergedDocumentsAs(const char *outDocumentName);
void merge(const char *overlayDocName, const MergeDescription & pagesToMerge);
private:
std::map<std::string, Document * > _baseDocuments;
static Parser _parser;
Document * _overlayDocument;
};
}
#endif //
///////////////////////////////////////////////////////////
// Merger.h
// Implementation of the Class Merger
// Created on: 19-èþí-2009 12:27:54
///////////////////////////////////////////////////////////
#if !defined Merger_h
#define Merger_h
#include "Document.h"
#include "Parser.h"
#include <map>
// structure defines parameter of merge
namespace merge_lib
{
class Document;
class Merger
{
public:
Merger();
~Merger();
//this method should be called every time the "Add" button is clicked
void addBaseDocument(const char *docName);
void addOverlayDocument(const char *docName);
void saveMergedDocumentsAs(const char *outDocumentName);
void merge(const char *overlayDocName, const MergeDescription & pagesToMerge);
private:
std::map<std::string, Document * > _baseDocuments;
static Parser _parser;
Document * _overlayDocument;
};
}
#endif //

@ -1,149 +1,149 @@
#if !defined Object_h
#define Object_h
#include "Utils.h"
#include <cmath>
#include <string>
#include <fstream>
#include <map>
#include <set>
#include <vector>
#include <utility>
namespace merge_lib
{
//This class represents pdf objects, and defines methods for performing
//all necessary operations on pdf objects
//Each object consists of two parts: content and object's number
//<object number> <number> obj
//<content>
//endobj
//Object can contain several links to other object. These objects has been named "children".
//Each reference (child object) should be kept with it position(s) in object's content.
//After each content modification, all references should be changed too.
//This convention lighten the recalculation object numbers work.
class Object
{
public:
friend class PageElementHandler;
typedef std::vector<unsigned int> ReferencePositionsInContent;
typedef std::pair<Object *, ReferencePositionsInContent > ChildAndItPositionInContent;
typedef std::map <unsigned int, ChildAndItPositionInContent> Children;
Object(unsigned int objectNumber, unsigned int generationNumber, const std::string & objectContent,
std::string fileName = "", std::pair<unsigned int, unsigned int> streamBounds = std::make_pair ((unsigned int)0,(unsigned int)0), bool hasStream = false
):
_number(objectNumber), _generationNumber(generationNumber), _oldNumber(objectNumber), _content(objectContent),_parents(),_children(),_isPassed(false),
_fileName(fileName), _streamBounds(streamBounds), _hasStream(hasStream), _hasStreamInContent(false)
{
}
virtual ~Object();
Object * getClone(std::vector<Object *> & clones);
void addChild(Object * child, const std::vector<unsigned int> childPositionsInContent);
void addChild(const Children & children);
ReferencePositionsInContent removeChild(Object * child);
void forgetAboutChildren(unsigned int leftBound, unsigned int rightBound);
Object * getChild(unsigned int objectNumber);
bool findObject(const std::string & token, Object* & foundObject, unsigned int & tokenPositionInContent);
std::vector<Object *> getChildrenByBounds(unsigned int leftBound, unsigned int rightBound);
std::vector<Object *> getSortedByPositionChildren(unsigned int leftBound, unsigned int rightBound);
void removeChildrenByBounds(unsigned int leftBound, unsigned int rightBound);
const Children & getChildren();
void removeHimself();
unsigned int getObjectNumber() const;
unsigned int getgenerationNumber() const;
std::string & getObjectContent();
void setObjectContent(const std::string & objectContent);
void appendContent(const std::string & addToContent);
void eraseContent(unsigned int from, unsigned int size);
void insertToContent(unsigned int position, const char * insertedStr, unsigned int length);
void insertToContent(unsigned int position, const std::string & insertedStr);
//vector <object number, its size>
void serialize(std::ofstream & out, std::map< unsigned int, std::pair<unsigned long long, unsigned int > > & sizesAndGenerationNumbers);
void recalculateObjectNumbers(unsigned int & newNumber);
bool isPassed()
{
return _isPassed;
}
void retrieveMaxObjectNumber(unsigned int & maxNumber);
void resetIsPassed()
{
if(_isPassed)
_isPassed = false;
Children::iterator it;
for ( it=_children.begin() ; it != _children.end(); it++ )
{
if((*it).second.first->isPassed())
(*it).second.first->resetIsPassed();
}
}
unsigned int getOldNumber()
{
return _oldNumber;
}
void setObjectNumber(unsigned int objNumber)
{
_number = objNumber;
_oldNumber = objNumber;
}
bool getStream(std::string &);
bool hasStream();
bool getHeader(std::string &content);
void forgetStreamInFile()
{
_hasStreamInContent = true;
_hasStream = true;
}
std::string getNameSimpleValue(const std::string &content, const std::string &patten, size_t pos = 0);
unsigned int getChildPosition(const Object * child); //throw (Exception)
const std::set<Object *> & getParents()
{
return _parents;
}
Object* findPatternInObjOrParents(const std::string &pattern);
private:
//methods
Object(const Object & copy);
Object * _getClone(std::map<unsigned int, Object *> & clones);
void _addChild(Object * child, const ReferencePositionsInContent & childPositionsInContent);
void _setObjectNumber(unsigned int objectNumber);
void _addParent(Object * child);
bool _findObject(const std::string & token, Object* & foundObject, unsigned int & tokenPositionInContent);
void _serialize(std::ofstream & out, const std::string & stream);
void _recalculateObjectNumbers(unsigned int & maxNumber);
void _recalculateReferencePositions(unsigned int changedReference, int displacement);
void _retrieveMaxObjectNumber(unsigned int & maxNumber);
void _serialize(std::ofstream & out, std::map<unsigned int, unsigned long long> & sizes);
bool _getStreamFromContent(std::string & stream);
//members
unsigned int _number;
unsigned int _generationNumber;
unsigned int _oldNumber;
std::string _content;
std::set <Object *> _parents;
Children _children;
bool _isPassed;
std::pair<unsigned int, unsigned int> _streamBounds;
std::string _fileName;
bool _hasStream;
bool _hasStreamInContent;
};
}
#endif
#if !defined Object_h
#define Object_h
#include "Utils.h"
#include <cmath>
#include <string>
#include <fstream>
#include <map>
#include <set>
#include <vector>
#include <utility>
namespace merge_lib
{
//This class represents pdf objects, and defines methods for performing
//all necessary operations on pdf objects
//Each object consists of two parts: content and object's number
//<object number> <number> obj
//<content>
//endobj
//Object can contain several links to other object. These objects has been named "children".
//Each reference (child object) should be kept with it position(s) in object's content.
//After each content modification, all references should be changed too.
//This convention lighten the recalculation object numbers work.
class Object
{
public:
friend class PageElementHandler;
typedef std::vector<unsigned int> ReferencePositionsInContent;
typedef std::pair<Object *, ReferencePositionsInContent > ChildAndItPositionInContent;
typedef std::map <unsigned int, ChildAndItPositionInContent> Children;
Object(unsigned int objectNumber, unsigned int generationNumber, const std::string & objectContent,
std::string fileName = "", std::pair<unsigned int, unsigned int> streamBounds = std::make_pair ((unsigned int)0,(unsigned int)0), bool hasStream = false
):
_number(objectNumber), _generationNumber(generationNumber), _oldNumber(objectNumber), _content(objectContent),_parents(),_children(),_isPassed(false),
_fileName(fileName), _streamBounds(streamBounds), _hasStream(hasStream), _hasStreamInContent(false)
{
}
virtual ~Object();
Object * getClone(std::vector<Object *> & clones);
void addChild(Object * child, const std::vector<unsigned int> childPositionsInContent);
void addChild(const Children & children);
ReferencePositionsInContent removeChild(Object * child);
void forgetAboutChildren(unsigned int leftBound, unsigned int rightBound);
Object * getChild(unsigned int objectNumber);
bool findObject(const std::string & token, Object* & foundObject, unsigned int & tokenPositionInContent);
std::vector<Object *> getChildrenByBounds(unsigned int leftBound, unsigned int rightBound);
std::vector<Object *> getSortedByPositionChildren(unsigned int leftBound, unsigned int rightBound);
void removeChildrenByBounds(unsigned int leftBound, unsigned int rightBound);
const Children & getChildren();
void removeHimself();
unsigned int getObjectNumber() const;
unsigned int getgenerationNumber() const;
std::string & getObjectContent();
void setObjectContent(const std::string & objectContent);
void appendContent(const std::string & addToContent);
void eraseContent(unsigned int from, unsigned int size);
void insertToContent(unsigned int position, const char * insertedStr, unsigned int length);
void insertToContent(unsigned int position, const std::string & insertedStr);
//vector <object number, its size>
void serialize(std::ofstream & out, std::map< unsigned int, std::pair<unsigned long long, unsigned int > > & sizesAndGenerationNumbers);
void recalculateObjectNumbers(unsigned int & newNumber);
bool isPassed()
{
return _isPassed;
}
void retrieveMaxObjectNumber(unsigned int & maxNumber);
void resetIsPassed()
{
if(_isPassed)
_isPassed = false;
Children::iterator it;
for ( it=_children.begin() ; it != _children.end(); it++ )
{
if((*it).second.first->isPassed())
(*it).second.first->resetIsPassed();
}
}
unsigned int getOldNumber()
{
return _oldNumber;
}
void setObjectNumber(unsigned int objNumber)
{
_number = objNumber;
_oldNumber = objNumber;
}
bool getStream(std::string &);
bool hasStream();
bool getHeader(std::string &content);
void forgetStreamInFile()
{
_hasStreamInContent = true;
_hasStream = true;
}
std::string getNameSimpleValue(const std::string &content, const std::string &patten, size_t pos = 0);
unsigned int getChildPosition(const Object * child); //throw (Exception)
const std::set<Object *> & getParents()
{
return _parents;
}
Object* findPatternInObjOrParents(const std::string &pattern);
private:
//methods
Object(const Object & copy);
Object * _getClone(std::map<unsigned int, Object *> & clones);
void _addChild(Object * child, const ReferencePositionsInContent & childPositionsInContent);
void _setObjectNumber(unsigned int objectNumber);
void _addParent(Object * child);
bool _findObject(const std::string & token, Object* & foundObject, unsigned int & tokenPositionInContent);
void _serialize(std::ofstream & out, const std::string & stream);
void _recalculateObjectNumbers(unsigned int & maxNumber);
void _recalculateReferencePositions(unsigned int changedReference, int displacement);
void _retrieveMaxObjectNumber(unsigned int & maxNumber);
void _serialize(std::ofstream & out, std::map<unsigned int, unsigned long long> & sizes);
bool _getStreamFromContent(std::string & stream);
//members
unsigned int _number;
unsigned int _generationNumber;
unsigned int _oldNumber;
std::string _content;
std::set <Object *> _parents;
Children _children;
bool _isPassed;
std::pair<unsigned int, unsigned int> _streamBounds;
std::string _fileName;
bool _hasStream;
bool _hasStreamInContent;
};
}
#endif

@ -1,144 +1,144 @@
#include "OverlayDocumentParser.h"
#include <fstream>
#include <string.h>
#include "Exception.h"
#include "Object.h"
using namespace merge_lib;
using namespace std;
int OverlayDocumentParser::DOC_PART_WITH_START_OF_XREF = 30;
unsigned int partSize = 10485760; // = 10 Mb
Document * OverlayDocumentParser::parseDocument(const char * fileName)
{
_fileName = fileName;
return Parser::parseDocument(fileName);
}
void OverlayDocumentParser::_readXRefAndCreateObjects()
{
std::map<unsigned int, unsigned long> objectsAndPositions;
_readXref(objectsAndPositions);
std::map<unsigned int, unsigned long> objectsAndSizes;
std::map<unsigned int, unsigned long>::iterator objAndSIter;
std::map<unsigned int, unsigned long>::iterator objAndPIter;
unsigned long fileSize = Utils::getFileSize(_fileName.c_str());
for(objAndSIter = objectsAndPositions.begin(); objAndSIter != objectsAndPositions.end(); ++objAndSIter)
{
unsigned int nextPosition = fileSize;
for(objAndPIter = objectsAndPositions.begin(); objAndPIter != objectsAndPositions.end(); ++objAndPIter)
{
if((objAndPIter->second > objAndSIter->second) && (objAndPIter->second < nextPosition))
nextPosition = objAndPIter->second;
}
objectsAndSizes[objAndSIter->first] = nextPosition - objAndSIter->second;
}
bool notEndOfFile = true;
do
{
unsigned long partStart = fileSize;
std::map<unsigned int, unsigned long>::iterator objIter;
for(objIter = objectsAndPositions.begin(); objIter != objectsAndPositions.end(); ++objIter)
{
if(objIter->second < partStart)
partStart = objIter->second;
}
unsigned long nextPartStart = partStart + partSize;
if((nextPartStart) < fileSize)
_getPartOfFileContent(partStart, partSize);
else
{
_getPartOfFileContent(partStart, fileSize - partStart);
nextPartStart = fileSize;
notEndOfFile = false;
}
unsigned long toReadAgain = 0;
for(objIter = objectsAndPositions.begin(); objIter != objectsAndPositions.end(); )
{
if((objectsAndSizes[objIter->first] + objIter->second <= nextPartStart) && (objIter->second >= partStart) && ((objIter->second < nextPartStart)))
{
std::pair<unsigned int, unsigned int> streamBounds;
unsigned int objectNumber;
unsigned int generationNumber;
bool hasObjectStream;
const std::string content = _getObjectContent(objIter->second - partStart, objectNumber, generationNumber, streamBounds, hasObjectStream);
streamBounds.first += partStart;
streamBounds.second += partStart;
Object * newObject = new Object(objectNumber, generationNumber, content, _document->_documentName ,streamBounds, hasObjectStream);
_objects[objectNumber] = newObject;
std::map<unsigned int, unsigned long>::iterator temp = objIter;
++objIter;
objectsAndPositions.erase(temp);
continue;
}
++objIter;
}
partStart = nextPartStart;
}
while(notEndOfFile);
}
void OverlayDocumentParser::_getPartOfFileContent(long startOfPart, unsigned int length)
{
ifstream pdfFile;
pdfFile.open (_fileName.c_str(), ios::binary );
if (pdfFile.fail())
{
stringstream errorMessage("File ");
errorMessage << _fileName << " is absent" << "\0";
throw Exception(errorMessage);
}
ios_base::seekdir dir;
if(startOfPart >= 0)
dir = ios_base::beg;
else
dir = ios_base::end;
pdfFile.seekg (startOfPart, dir);
_fileContent.resize(length);
pdfFile.read(&_fileContent[0], length);
pdfFile.close();
}
void OverlayDocumentParser::_readXref(std::map<unsigned int, unsigned long> & objectsAndSizes)
{
_getPartOfFileContent(- DOC_PART_WITH_START_OF_XREF, DOC_PART_WITH_START_OF_XREF);
unsigned int startOfStartxref = _fileContent.find("startxref");
unsigned int startOfNumber = _fileContent.find_first_of(Parser::NUMBERS, startOfStartxref);
unsigned int endOfNumber = _fileContent.find_first_not_of(Parser::NUMBERS, startOfNumber + 1);
std::string startXref = _fileContent.substr(startOfNumber, endOfNumber - startOfNumber);
unsigned int strtXref = Utils::stringToInt(startXref);
unsigned int sizeOfXref = Utils::getFileSize(_fileName.c_str()) - strtXref;
_getPartOfFileContent(strtXref, sizeOfXref);
unsigned int leftBoundOfObjectNumber = _fileContent.find("0 ") + strlen("0 ");
unsigned int rightBoundOfObjectNumber = _fileContent.find_first_not_of(Parser::NUMBERS, leftBoundOfObjectNumber);
std::string objectNuberStr = _fileContent.substr(leftBoundOfObjectNumber, rightBoundOfObjectNumber - leftBoundOfObjectNumber);
unsigned long objectNumber = Utils::stringToInt(objectNuberStr);
unsigned int startOfObjectPosition = _fileContent.find("0000000000 65535 f ") + strlen("0000000000 65535 f ");
for(unsigned long i = 1; i < objectNumber; ++i)
{
startOfObjectPosition = _fileContent.find_first_of(Parser::NUMBERS, startOfObjectPosition);
unsigned int endOfObjectPostion = _fileContent.find(" 00000 n", startOfObjectPosition);
std::string objectPostionStr = _fileContent.substr(startOfObjectPosition, endOfObjectPostion - startOfObjectPosition);
objectsAndSizes[i] = Utils::stringToInt(objectPostionStr);
startOfObjectPosition = endOfObjectPostion + strlen(" 00000 n");
}
}
unsigned int OverlayDocumentParser::_readTrailerAndReturnRoot()
{
_getPartOfFileContent(- (3*DOC_PART_WITH_START_OF_XREF), (3*DOC_PART_WITH_START_OF_XREF));
return Parser::_readTrailerAndReturnRoot();
}
unsigned int OverlayDocumentParser::_getStartOfXrefWithRoot()
{
return 0;
}
#include "OverlayDocumentParser.h"
#include <fstream>
#include <string.h>
#include "Exception.h"
#include "Object.h"
using namespace merge_lib;
using namespace std;
int OverlayDocumentParser::DOC_PART_WITH_START_OF_XREF = 30;
unsigned int partSize = 10485760; // = 10 Mb
Document * OverlayDocumentParser::parseDocument(const char * fileName)
{
_fileName = fileName;
return Parser::parseDocument(fileName);
}
void OverlayDocumentParser::_readXRefAndCreateObjects()
{
std::map<unsigned int, unsigned long> objectsAndPositions;
_readXref(objectsAndPositions);
std::map<unsigned int, unsigned long> objectsAndSizes;
std::map<unsigned int, unsigned long>::iterator objAndSIter;
std::map<unsigned int, unsigned long>::iterator objAndPIter;
unsigned long fileSize = Utils::getFileSize(_fileName.c_str());
for(objAndSIter = objectsAndPositions.begin(); objAndSIter != objectsAndPositions.end(); ++objAndSIter)
{
unsigned int nextPosition = fileSize;
for(objAndPIter = objectsAndPositions.begin(); objAndPIter != objectsAndPositions.end(); ++objAndPIter)
{
if((objAndPIter->second > objAndSIter->second) && (objAndPIter->second < nextPosition))
nextPosition = objAndPIter->second;
}
objectsAndSizes[objAndSIter->first] = nextPosition - objAndSIter->second;
}
bool notEndOfFile = true;
do
{
unsigned long partStart = fileSize;
std::map<unsigned int, unsigned long>::iterator objIter;
for(objIter = objectsAndPositions.begin(); objIter != objectsAndPositions.end(); ++objIter)
{
if(objIter->second < partStart)
partStart = objIter->second;
}
unsigned long nextPartStart = partStart + partSize;
if((nextPartStart) < fileSize)
_getPartOfFileContent(partStart, partSize);
else
{
_getPartOfFileContent(partStart, fileSize - partStart);
nextPartStart = fileSize;
notEndOfFile = false;
}
unsigned long toReadAgain = 0;
for(objIter = objectsAndPositions.begin(); objIter != objectsAndPositions.end(); )
{
if((objectsAndSizes[objIter->first] + objIter->second <= nextPartStart) && (objIter->second >= partStart) && ((objIter->second < nextPartStart)))
{
std::pair<unsigned int, unsigned int> streamBounds;
unsigned int objectNumber;
unsigned int generationNumber;
bool hasObjectStream;
const std::string content = _getObjectContent(objIter->second - partStart, objectNumber, generationNumber, streamBounds, hasObjectStream);
streamBounds.first += partStart;
streamBounds.second += partStart;
Object * newObject = new Object(objectNumber, generationNumber, content, _document->_documentName ,streamBounds, hasObjectStream);
_objects[objectNumber] = newObject;
std::map<unsigned int, unsigned long>::iterator temp = objIter;
++objIter;
objectsAndPositions.erase(temp);
continue;
}
++objIter;
}
partStart = nextPartStart;
}
while(notEndOfFile);
}
void OverlayDocumentParser::_getPartOfFileContent(long startOfPart, unsigned int length)
{
ifstream pdfFile;
pdfFile.open (_fileName.c_str(), ios::binary );
if (pdfFile.fail())
{
stringstream errorMessage("File ");
errorMessage << _fileName << " is absent" << "\0";
throw Exception(errorMessage);
}
ios_base::seekdir dir;
if(startOfPart >= 0)
dir = ios_base::beg;
else
dir = ios_base::end;
pdfFile.seekg (startOfPart, dir);
_fileContent.resize(length);
pdfFile.read(&_fileContent[0], length);
pdfFile.close();
}
void OverlayDocumentParser::_readXref(std::map<unsigned int, unsigned long> & objectsAndSizes)
{
_getPartOfFileContent(- DOC_PART_WITH_START_OF_XREF, DOC_PART_WITH_START_OF_XREF);
unsigned int startOfStartxref = _fileContent.find("startxref");
unsigned int startOfNumber = _fileContent.find_first_of(Parser::NUMBERS, startOfStartxref);
unsigned int endOfNumber = _fileContent.find_first_not_of(Parser::NUMBERS, startOfNumber + 1);
std::string startXref = _fileContent.substr(startOfNumber, endOfNumber - startOfNumber);
unsigned int strtXref = Utils::stringToInt(startXref);
unsigned int sizeOfXref = Utils::getFileSize(_fileName.c_str()) - strtXref;
_getPartOfFileContent(strtXref, sizeOfXref);
unsigned int leftBoundOfObjectNumber = _fileContent.find("0 ") + strlen("0 ");
unsigned int rightBoundOfObjectNumber = _fileContent.find_first_not_of(Parser::NUMBERS, leftBoundOfObjectNumber);
std::string objectNuberStr = _fileContent.substr(leftBoundOfObjectNumber, rightBoundOfObjectNumber - leftBoundOfObjectNumber);
unsigned long objectNumber = Utils::stringToInt(objectNuberStr);
unsigned int startOfObjectPosition = _fileContent.find("0000000000 65535 f ") + strlen("0000000000 65535 f ");
for(unsigned long i = 1; i < objectNumber; ++i)
{
startOfObjectPosition = _fileContent.find_first_of(Parser::NUMBERS, startOfObjectPosition);
unsigned int endOfObjectPostion = _fileContent.find(" 00000 n", startOfObjectPosition);
std::string objectPostionStr = _fileContent.substr(startOfObjectPosition, endOfObjectPostion - startOfObjectPosition);
objectsAndSizes[i] = Utils::stringToInt(objectPostionStr);
startOfObjectPosition = endOfObjectPostion + strlen(" 00000 n");
}
}
unsigned int OverlayDocumentParser::_readTrailerAndReturnRoot()
{
_getPartOfFileContent(- (3*DOC_PART_WITH_START_OF_XREF), (3*DOC_PART_WITH_START_OF_XREF));
return Parser::_readTrailerAndReturnRoot();
}
unsigned int OverlayDocumentParser::_getStartOfXrefWithRoot()
{
return 0;
}

@ -1,40 +1,40 @@
#if !defined OverlayDocumentParser_h
#define OverlayDocumentParser_h
#include "Object.h"
#include "Document.h"
#include "Page.h"
#include "Parser.h"
#include <map>
#include <iostream>
namespace merge_lib
{
class Document;
//This class parsed the pdf document and creates
//an Document object
class OverlayDocumentParser: private Parser
{
public:
OverlayDocumentParser(): Parser(), _fileName() {};
Document * parseDocument(const char * fileName);
protected:
unsigned int _readTrailerAndReturnRoot();
private:
//methods
void _getFileContent(const char * fileName){};
void _readXRefAndCreateObjects();
void _readXref(std::map<unsigned int, unsigned long> & objectsAndSizes);
void _getPartOfFileContent(long startOfPart, unsigned int length);
unsigned int _getStartOfXrefWithRoot();
//constants
static int DOC_PART_WITH_START_OF_XREF;
//members
std::string _fileName;
};
}
#endif
#if !defined OverlayDocumentParser_h
#define OverlayDocumentParser_h
#include "Object.h"
#include "Document.h"
#include "Page.h"
#include "Parser.h"
#include <map>
#include <iostream>
namespace merge_lib
{
class Document;
//This class parsed the pdf document and creates
//an Document object
class OverlayDocumentParser: private Parser
{
public:
OverlayDocumentParser(): Parser(), _fileName() {};
Document * parseDocument(const char * fileName);
protected:
unsigned int _readTrailerAndReturnRoot();
private:
//methods
void _getFileContent(const char * fileName){};
void _readXRefAndCreateObjects();
void _readXref(std::map<unsigned int, unsigned long> & objectsAndSizes);
void _getPartOfFileContent(long startOfPart, unsigned int length);
unsigned int _getStartOfXrefWithRoot();
//constants
static int DOC_PART_WITH_START_OF_XREF;
//members
std::string _fileName;
};
}
#endif

@ -1,64 +1,64 @@
///////////////////////////////////////////////////////////
// Page.h
// Implementation of the Class Page
// Created on: 19-èþí-2009 12:27:56
///////////////////////////////////////////////////////////
#if !defined Page_h
#define Page_h
#include <string>
#include "Object.h"
#include "MergePageDescription.h"
namespace merge_lib
{
class Document;
class Page
{
friend class Parser;
friend class PageElementsFactory;
public:
Page(unsigned int pageNumber);
~Page();
unsigned int getPageNumber()
{
return _pageNumber;
}
void merge(Page * sourcePage, Document * parentDocument, MergePageDescription & description, bool isPageDuplicated);
void recalculateObjectNumbers(unsigned int & newNumber);
std::string & getPageContent();
const Object::Children & getPageRefs();
Object * pageToXObject(std::vector<Object *> & allObjects, std::vector<Object *> & annots, bool isCloneNeeded);
void setRotation(int rotation)
{
_rotation = rotation;
}
private:
//methods
Object * _pageToXObject(Object *& page, std::vector<Object *> & annots);
std::string _getMergedPageContent( unsigned int & contentPosition,
unsigned int & parentPosition,
unsigned int & originalPage1Position,
unsigned int & originalPage2Position,
std::pair<unsigned int, unsigned int> originalPageNumbers,
const MergePageDescription & description,
Object * basePage,
const std::vector<Object *> & annots,
std::vector <Object::ChildAndItPositionInContent> & annotsPositions
);
//members
Object * _root;
unsigned int _pageNumber;
int _rotation;
};
}
#endif
///////////////////////////////////////////////////////////
// Page.h
// Implementation of the Class Page
// Created on: 19-èþí-2009 12:27:56
///////////////////////////////////////////////////////////
#if !defined Page_h
#define Page_h
#include <string>
#include "Object.h"
#include "MergePageDescription.h"
namespace merge_lib
{
class Document;
class Page
{
friend class Parser;
friend class PageElementsFactory;
public:
Page(unsigned int pageNumber);
~Page();
unsigned int getPageNumber()
{
return _pageNumber;
}
void merge(Page * sourcePage, Document * parentDocument, MergePageDescription & description, bool isPageDuplicated);
void recalculateObjectNumbers(unsigned int & newNumber);
std::string & getPageContent();
const Object::Children & getPageRefs();
Object * pageToXObject(std::vector<Object *> & allObjects, std::vector<Object *> & annots, bool isCloneNeeded);
void setRotation(int rotation)
{
_rotation = rotation;
}
private:
//methods
Object * _pageToXObject(Object *& page, std::vector<Object *> & annots);
std::string _getMergedPageContent( unsigned int & contentPosition,
unsigned int & parentPosition,
unsigned int & originalPage1Position,
unsigned int & originalPage2Position,
std::pair<unsigned int, unsigned int> originalPageNumbers,
const MergePageDescription & description,
Object * basePage,
const std::vector<Object *> & annots,
std::vector <Object::ChildAndItPositionInContent> & annotsPositions
);
//members
Object * _root;
unsigned int _pageNumber;
int _rotation;
};
}
#endif

@ -1,74 +1,74 @@
#include "PageElementHandler.h"
using namespace merge_lib;
std::set<std::string> PageElementHandler::_allPageFields;
void PageElementHandler::_createAllPageFieldsSet()
{
if(!_allPageFields.empty())
return;
_allPageFields.insert(std::string("Type"));
_allPageFields.insert(std::string("Parent"));
_allPageFields.insert(std::string("LastModified"));
_allPageFields.insert(std::string("Resources"));
_allPageFields.insert(std::string("MediaBox"));
_allPageFields.insert(std::string("CropBox"));
_allPageFields.insert(std::string("BleedBox"));
_allPageFields.insert(std::string("TrimBox"));
_allPageFields.insert(std::string("ArtBox"));
_allPageFields.insert(std::string("BoxColorInfo"));
_allPageFields.insert(std::string("Contents"));
_allPageFields.insert(std::string("Rotate"));
_allPageFields.insert(std::string("Group"));
_allPageFields.insert(std::string("Thumb"));
_allPageFields.insert(std::string("B"));
_allPageFields.insert(std::string("Dur"));
_allPageFields.insert(std::string("Trans"));
_allPageFields.insert(std::string("Annots"));
_allPageFields.insert(std::string("AA"));
_allPageFields.insert(std::string("Metadata"));
_allPageFields.insert(std::string("PieceInfo"));
_allPageFields.insert(std::string("StructParents"));
_allPageFields.insert(std::string("ID"));
_allPageFields.insert(std::string("PZ"));
_allPageFields.insert(std::string("SeparationInfo"));
_allPageFields.insert(std::string("Tabs"));
_allPageFields.insert(std::string("TemplateInstantiated"));
_allPageFields.insert(std::string("PresSteps"));
_allPageFields.insert(std::string("UserUnit"));
_allPageFields.insert(std::string("VP"));
//for correct search all fields of XObject should be present to
_allPageFields.insert(std::string("Subtype"));
_allPageFields.insert(std::string("FormType"));
_allPageFields.insert(std::string("BBox"));
_allPageFields.insert(std::string("Matrix"));
_allPageFields.insert(std::string("Ref"));
_allPageFields.insert(std::string("StructParent"));
_allPageFields.insert(std::string("OPI"));
_allPageFields.insert(std::string("OC"));
_allPageFields.insert(std::string("Name"));
}
unsigned int PageElementHandler::_findEndOfElementContent(unsigned int startOfPageElement)
{
static std::string whitespacesAndDelimeters(" \t\f\v\n\r<<[/");
unsigned int foundSlash = _pageContent.find("/", startOfPageElement + 1);
std::string fieldType;
while(foundSlash != std::string::npos)
{
unsigned int foundWhitespace = _pageContent.find_first_of(whitespacesAndDelimeters, foundSlash + 1);
if(foundWhitespace != std::string::npos)
fieldType = _pageContent.substr(foundSlash + 1, foundWhitespace - foundSlash - 1);
else
break;
//is this any page element between "/" and " "
if(_allPageFields.count(fieldType))
{
return foundSlash;
}
foundSlash = foundWhitespace;
}
return _pageContent.rfind(">>");
}
#include "PageElementHandler.h"
using namespace merge_lib;
std::set<std::string> PageElementHandler::_allPageFields;
void PageElementHandler::_createAllPageFieldsSet()
{
if(!_allPageFields.empty())
return;
_allPageFields.insert(std::string("Type"));
_allPageFields.insert(std::string("Parent"));
_allPageFields.insert(std::string("LastModified"));
_allPageFields.insert(std::string("Resources"));
_allPageFields.insert(std::string("MediaBox"));
_allPageFields.insert(std::string("CropBox"));
_allPageFields.insert(std::string("BleedBox"));
_allPageFields.insert(std::string("TrimBox"));
_allPageFields.insert(std::string("ArtBox"));
_allPageFields.insert(std::string("BoxColorInfo"));
_allPageFields.insert(std::string("Contents"));
_allPageFields.insert(std::string("Rotate"));
_allPageFields.insert(std::string("Group"));
_allPageFields.insert(std::string("Thumb"));
_allPageFields.insert(std::string("B"));
_allPageFields.insert(std::string("Dur"));
_allPageFields.insert(std::string("Trans"));
_allPageFields.insert(std::string("Annots"));
_allPageFields.insert(std::string("AA"));
_allPageFields.insert(std::string("Metadata"));
_allPageFields.insert(std::string("PieceInfo"));
_allPageFields.insert(std::string("StructParents"));
_allPageFields.insert(std::string("ID"));
_allPageFields.insert(std::string("PZ"));
_allPageFields.insert(std::string("SeparationInfo"));
_allPageFields.insert(std::string("Tabs"));
_allPageFields.insert(std::string("TemplateInstantiated"));
_allPageFields.insert(std::string("PresSteps"));
_allPageFields.insert(std::string("UserUnit"));
_allPageFields.insert(std::string("VP"));
//for correct search all fields of XObject should be present to
_allPageFields.insert(std::string("Subtype"));
_allPageFields.insert(std::string("FormType"));
_allPageFields.insert(std::string("BBox"));
_allPageFields.insert(std::string("Matrix"));
_allPageFields.insert(std::string("Ref"));
_allPageFields.insert(std::string("StructParent"));
_allPageFields.insert(std::string("OPI"));
_allPageFields.insert(std::string("OC"));
_allPageFields.insert(std::string("Name"));
}
unsigned int PageElementHandler::_findEndOfElementContent(unsigned int startOfPageElement)
{
static std::string whitespacesAndDelimeters(" \t\f\v\n\r<<[/");
unsigned int foundSlash = _pageContent.find("/", startOfPageElement + 1);
std::string fieldType;
while(foundSlash != std::string::npos)
{
unsigned int foundWhitespace = _pageContent.find_first_of(whitespacesAndDelimeters, foundSlash + 1);
if(foundWhitespace != std::string::npos)
fieldType = _pageContent.substr(foundSlash + 1, foundWhitespace - foundSlash - 1);
else
break;
//is this any page element between "/" and " "
if(_allPageFields.count(fieldType))
{
return foundSlash;
}
foundSlash = foundWhitespace;
}
return _pageContent.rfind(">>");
}

@ -1,84 +1,84 @@
#if !defined PageElementHandler_h
#define PageElementHandler_h
#include <string>
#include <set>
#include "Object.h"
#include "Parser.h"
namespace merge_lib
{
//base class for all elements handlers
//Handlers are needed to process Page fields during the merge
//this is the chain of responsibility pattern
class PageElementHandler
{
public:
PageElementHandler(Object * page): _page(page), _pageContent(page->_content), _nextHandler(0)
{
_createAllPageFieldsSet();
}
virtual ~PageElementHandler()
{
delete _nextHandler;
}
void addNextHandler(PageElementHandler * nextHandler)
{
_nextHandler = nextHandler;
}
void processObjectContent()
{
unsigned int startOfPageElement = _findStartOfPageElement();
if(startOfPageElement != std::string::npos)
_processObjectContent(startOfPageElement);
if(_nextHandler)
_nextHandler->processObjectContent();
}
void changeObjectContent()
{
unsigned int startOfPageElement = _findStartOfPageElement();
if(startOfPageElement != std::string::npos)
_changeObjectContent(startOfPageElement);
else
_pageElementNotFound();
if(_nextHandler)
_nextHandler->changeObjectContent();
}
protected:
//methods
void _setHandlerName(const std::string & handlerName)
{
_handlerName = handlerName;
}
unsigned int _findEndOfElementContent(unsigned int startOfPageElement);
void _createAllPageFieldsSet();
//members
std::string & _pageContent;
Object * _page;
std::string _handlerName;
PageElementHandler * _nextHandler;
private:
//methods
virtual void _processObjectContent(unsigned int startOfPageElement){};
virtual void _changeObjectContent(unsigned int startOfPageElement) = 0;
virtual void _pageElementNotFound() {};
unsigned int _findStartOfPageElement()
{
return Parser::findToken(_pageContent,_handlerName);
}
//members
static std::set<std::string> _allPageFields;
};
}
#endif
#if !defined PageElementHandler_h
#define PageElementHandler_h
#include <string>
#include <set>
#include "Object.h"
#include "Parser.h"
namespace merge_lib
{
//base class for all elements handlers
//Handlers are needed to process Page fields during the merge
//this is the chain of responsibility pattern
class PageElementHandler
{
public:
PageElementHandler(Object * page): _page(page), _pageContent(page->_content), _nextHandler(0)
{
_createAllPageFieldsSet();
}
virtual ~PageElementHandler()
{
delete _nextHandler;
}
void addNextHandler(PageElementHandler * nextHandler)
{
_nextHandler = nextHandler;
}
void processObjectContent()
{
unsigned int startOfPageElement = _findStartOfPageElement();
if(startOfPageElement != std::string::npos)
_processObjectContent(startOfPageElement);
if(_nextHandler)
_nextHandler->processObjectContent();
}
void changeObjectContent()
{
unsigned int startOfPageElement = _findStartOfPageElement();
if(startOfPageElement != std::string::npos)
_changeObjectContent(startOfPageElement);
else
_pageElementNotFound();
if(_nextHandler)
_nextHandler->changeObjectContent();
}
protected:
//methods
void _setHandlerName(const std::string & handlerName)
{
_handlerName = handlerName;
}
unsigned int _findEndOfElementContent(unsigned int startOfPageElement);
void _createAllPageFieldsSet();
//members
std::string & _pageContent;
Object * _page;
std::string _handlerName;
PageElementHandler * _nextHandler;
private:
//methods
virtual void _processObjectContent(unsigned int startOfPageElement){};
virtual void _changeObjectContent(unsigned int startOfPageElement) = 0;
virtual void _pageElementNotFound() {};
unsigned int _findStartOfPageElement()
{
return Parser::findToken(_pageContent,_handlerName);
}
//members
static std::set<std::string> _allPageFields;
};
}
#endif

@ -1,41 +1,41 @@
///////////////////////////////////////////////////////////
// Page.h
// Implementation of the Class Page
// Created on: 19-èþí-2009 12:27:56
///////////////////////////////////////////////////////////
#if !defined(EA_FF53E894_11D7_4c64_A409_DBC97C9EF3CF__INCLUDED_)
#define EA_FF53E894_11D7_4c64_A409_DBC97C9EF3CF__INCLUDED_
#include "Object.h"
#include <string>
class PageParser
{
friend class Parser;
public:
PageParser(const std::string & pageContent);
~PageParser();
unsigned int getPageNumber()
{
return _pageNumber;
}
void merge(const Page & sourcePage);
void recalculateObjectNumbers(unsigned int & newNumber);
std::string & getPageContent();
const std::map <unsigned int, Object *> & getPageRefs();
private:
//methods
//members
Object * _root;
unsigned int _pageNumber;
};
#endif // !defined(EA_FF53E894_11D7_4c64_A409_DBC97C9EF3CF__INCLUDED_)
///////////////////////////////////////////////////////////
// Page.h
// Implementation of the Class Page
// Created on: 19-èþí-2009 12:27:56
///////////////////////////////////////////////////////////
#if !defined(EA_FF53E894_11D7_4c64_A409_DBC97C9EF3CF__INCLUDED_)
#define EA_FF53E894_11D7_4c64_A409_DBC97C9EF3CF__INCLUDED_
#include "Object.h"
#include <string>
class PageParser
{
friend class Parser;
public:
PageParser(const std::string & pageContent);
~PageParser();
unsigned int getPageNumber()
{
return _pageNumber;
}
void merge(const Page & sourcePage);
void recalculateObjectNumbers(unsigned int & newNumber);
std::string & getPageContent();
const std::map <unsigned int, Object *> & getPageRefs();
private:
//methods
//members
Object * _root;
unsigned int _pageNumber;
};
#endif // !defined(EA_FF53E894_11D7_4c64_A409_DBC97C9EF3CF__INCLUDED_)

@ -1,76 +1,76 @@
#if !defined Parser_h
#define Parser_h
#include "Object.h"
#include "Document.h"
#include "Page.h"
#include <string>
#include <vector>
namespace merge_lib
{
class Document;
//This class parsed the pdf document and creates
//an Document object
class Parser
{
public:
Parser(): _root(0), _fileContent(), _objects(), _document(0) {};
Document * parseDocument(const char * fileName);
static const std::string WHITESPACES;
static const std::string DELIMETERS;
static const std::string NUMBERS;
static const std::string WHITESPACES_AND_DELIMETERS;
static bool getNextWord(std::string & out, const std::string &in, size_t &nextPosition,size_t *found = NULL);
static std::string getNextToken( const std::string &in, unsigned &position);
static void trim(std::string &str);
static std::string findTokenStr(const std::string &content, const std::string &pattern, size_t start,size_t &foundStart, size_t &foundEnd);
static size_t findToken(const std::string &content, const std::string &keyword,size_t start = 0);
static size_t findTokenName(const std::string &content, const std::string &keyword,size_t start = 0);
static unsigned int findEndOfElementContent(const std::string &content, unsigned int startOfPageElement);
static bool tokenIsAName(const std::string &content, size_t start );
protected:
const std::string & _getObjectContent(unsigned int objectPosition, unsigned int & objectNumber, unsigned int & generationNumber, std::pair<unsigned int, unsigned int> &, bool &);
virtual unsigned int _readTrailerAndReturnRoot();
private:
//methods
virtual void _getFileContent(const char * fileName);
bool _getNextObject(Object * object);
void _callObserver(std::string objectContent);
void _createObjectTree(const char * fileName);
void _retrieveAllPages(Object * objectWithKids);
void _fillOutObjects();
virtual void _readXRefAndCreateObjects();
unsigned int _getEndOfLineFromContent(unsigned int fromPosition);
const std::pair<unsigned int, unsigned int> & _getLineBounds(const std::string & str, unsigned int fromPosition);
const std::string & _getNextToken(unsigned int & fromPosition);
unsigned int _countTokens(unsigned int leftBound, unsigned int rightBount);
unsigned int _skipWhiteSpaces(const std::string & str);
unsigned int _skipWhiteSpacesFromContent(unsigned int fromPosition);
const std::map<unsigned int, Object::ReferencePositionsInContent> & _getReferences(const std::string & objectContent);
unsigned int _skipNumber(const std::string & str, unsigned int currentPosition);
unsigned int _skipWhiteSpaces(const std::string & str, unsigned int fromPosition);
void _createDocument(const char * docName);
virtual unsigned int _getStartOfXrefWithRoot();
unsigned int _readTrailerAndRterievePrev(const unsigned int startPositionForSearch, unsigned int & previosXref);
void _clearParser();
protected:
//members
Object * _root;
std::string _fileContent;
std::map<unsigned int, Object *> _objects;
Document * _document;
};
}
#endif
#if !defined Parser_h
#define Parser_h
#include "Object.h"
#include "Document.h"
#include "Page.h"
#include <string>
#include <vector>
namespace merge_lib
{
class Document;
//This class parsed the pdf document and creates
//an Document object
class Parser
{
public:
Parser(): _root(0), _fileContent(), _objects(), _document(0) {};
Document * parseDocument(const char * fileName);
static const std::string WHITESPACES;
static const std::string DELIMETERS;
static const std::string NUMBERS;
static const std::string WHITESPACES_AND_DELIMETERS;
static bool getNextWord(std::string & out, const std::string &in, size_t &nextPosition,size_t *found = NULL);
static std::string getNextToken( const std::string &in, unsigned &position);
static void trim(std::string &str);
static std::string findTokenStr(const std::string &content, const std::string &pattern, size_t start,size_t &foundStart, size_t &foundEnd);
static size_t findToken(const std::string &content, const std::string &keyword,size_t start = 0);
static size_t findTokenName(const std::string &content, const std::string &keyword,size_t start = 0);
static unsigned int findEndOfElementContent(const std::string &content, unsigned int startOfPageElement);
static bool tokenIsAName(const std::string &content, size_t start );
protected:
const std::string & _getObjectContent(unsigned int objectPosition, unsigned int & objectNumber, unsigned int & generationNumber, std::pair<unsigned int, unsigned int> &, bool &);
virtual unsigned int _readTrailerAndReturnRoot();
private:
//methods
virtual void _getFileContent(const char * fileName);
bool _getNextObject(Object * object);
void _callObserver(std::string objectContent);
void _createObjectTree(const char * fileName);
void _retrieveAllPages(Object * objectWithKids);
void _fillOutObjects();
virtual void _readXRefAndCreateObjects();
unsigned int _getEndOfLineFromContent(unsigned int fromPosition);
const std::pair<unsigned int, unsigned int> & _getLineBounds(const std::string & str, unsigned int fromPosition);
const std::string & _getNextToken(unsigned int & fromPosition);
unsigned int _countTokens(unsigned int leftBound, unsigned int rightBount);
unsigned int _skipWhiteSpaces(const std::string & str);
unsigned int _skipWhiteSpacesFromContent(unsigned int fromPosition);
const std::map<unsigned int, Object::ReferencePositionsInContent> & _getReferences(const std::string & objectContent);
unsigned int _skipNumber(const std::string & str, unsigned int currentPosition);
unsigned int _skipWhiteSpaces(const std::string & str, unsigned int fromPosition);
void _createDocument(const char * docName);
virtual unsigned int _getStartOfXrefWithRoot();
unsigned int _readTrailerAndRterievePrev(const unsigned int startPositionForSearch, unsigned int & previosXref);
void _clearParser();
protected:
//members
Object * _root;
std::string _fileContent;
std::map<unsigned int, Object *> _objects;
Document * _document;
};
}
#endif

@ -1,124 +1,124 @@
#include "Rectangle.h"
#include "Utils.h"
#include "Object.h"
#include "Parser.h"
#include <iostream>
using namespace merge_lib;
Rectangle::Rectangle(const char * rectangleName):
_rectangleName(rectangleName),
x1(0),
y1(0),
x2(0),
y2(0),
_tm()
{}
Rectangle::Rectangle(const char * rectangleName, const std::string content):
_rectangleName(rectangleName),
x1(0),
y1(0),
x2(0),
y2(0)
{
unsigned int rectanglePosition = Parser::findToken(content,rectangleName);
if( rectanglePosition == std::string::npos )
{
std::cerr<<"Unable to find rectangle name "<<rectangleName<<" in content\n";
}
size_t beg = content.find("[",rectanglePosition);
size_t end = content.find("]",rectanglePosition);
if( beg != std::string::npos && end != std::string::npos )
{
std::string arr = content.substr(beg+1,end-beg-1);
std::stringstream in;
in<<arr;
in>>x1>>y1>>x2>>y2;
}
}
void Rectangle::appendRectangleToString(std::string & content, const char * delimeter)
{
content.append(_getRectangleAsString(delimeter));
}
const std::string Rectangle::_getRectangleAsString(const char * delimeter)
{
std::string result(_rectangleName);
result.append(" [");
result.append(Utils::doubleToStr(x1));
result.append(delimeter);
result.append(Utils::doubleToStr(y1));
result.append(delimeter);
result.append(Utils::doubleToStr(x2));
result.append(delimeter);
result.append(Utils::doubleToStr(y2));
result.append(" ]\n");
return result;
}
void Rectangle::setNewRectangleName(const char * newName)
{
_rectangleName = newName;
}
void Rectangle::recalculateInternalRectangleCoordinates(const PageTransformations & transformations)
{
TransformationMatrix tempTm;
for(size_t i = 0; i < transformations.size(); ++i)
{
tempTm = transformations[i]->getMatrix();
tempTm.add(_tm);
_tm = tempTm;
}
_tm.recalculateCoordinates(x1, y1);
_tm.recalculateCoordinates(x2, y2);
}
void Rectangle::updateRectangle(Object * objectWithRectangle, const char * delimeter)
{
Object * foundObjectWithRectangle;
unsigned int fake;
objectWithRectangle->findObject(std::string(_rectangleName), foundObjectWithRectangle, fake);
std::string objectContent = foundObjectWithRectangle->getObjectContent();
unsigned int rectanglePosition = objectContent.find(_rectangleName);
unsigned int endOfRectangle = objectContent.find("]", rectanglePosition) + 1;
foundObjectWithRectangle->eraseContent(rectanglePosition, endOfRectangle - rectanglePosition);
foundObjectWithRectangle->insertToContent(rectanglePosition, _getRectangleAsString(delimeter));
// reread the objectContent, since it was changed just above;
objectContent = foundObjectWithRectangle->getObjectContent();
//update matrix
unsigned int startOfAP = Parser::findToken(objectContent,"/AP");
unsigned int endOfAP = objectContent.find(">>", startOfAP);
std::vector<Object *> aps = foundObjectWithRectangle->getChildrenByBounds(startOfAP, endOfAP);
for(size_t i = 0; i < aps.size(); ++i)
{
Object * objectWithMatrix = aps[i];
std::string objectContent = objectWithMatrix->getObjectContent();
unsigned int matrixPosition = Parser::findToken(objectContent,"/Matrix");
if(matrixPosition == std::string::npos)
continue;
unsigned int matrixValueLeftBound = objectContent.find("[", matrixPosition);
unsigned int matrixValueRightBound = objectContent.find("]", matrixValueLeftBound) + 1;
objectWithMatrix->eraseContent(matrixValueLeftBound, matrixValueRightBound - matrixValueLeftBound);
objectWithMatrix->insertToContent(matrixValueLeftBound, _tm.getValue());
}
}
double Rectangle::getWidth()
{
return x2 - x1;
}
double Rectangle::getHeight()
{
return y2 - y1;
}
#include "Rectangle.h"
#include "Utils.h"
#include "Object.h"
#include "Parser.h"
#include <iostream>
using namespace merge_lib;
Rectangle::Rectangle(const char * rectangleName):
_rectangleName(rectangleName),
x1(0),
y1(0),
x2(0),
y2(0),
_tm()
{}
Rectangle::Rectangle(const char * rectangleName, const std::string content):
_rectangleName(rectangleName),
x1(0),
y1(0),
x2(0),
y2(0)
{
unsigned int rectanglePosition = Parser::findToken(content,rectangleName);
if( rectanglePosition == std::string::npos )
{
std::cerr<<"Unable to find rectangle name "<<rectangleName<<" in content\n";
}
size_t beg = content.find("[",rectanglePosition);
size_t end = content.find("]",rectanglePosition);
if( beg != std::string::npos && end != std::string::npos )
{
std::string arr = content.substr(beg+1,end-beg-1);
std::stringstream in;
in<<arr;
in>>x1>>y1>>x2>>y2;
}
}
void Rectangle::appendRectangleToString(std::string & content, const char * delimeter)
{
content.append(_getRectangleAsString(delimeter));
}
const std::string Rectangle::_getRectangleAsString(const char * delimeter)
{
std::string result(_rectangleName);
result.append(" [");
result.append(Utils::doubleToStr(x1));
result.append(delimeter);
result.append(Utils::doubleToStr(y1));
result.append(delimeter);
result.append(Utils::doubleToStr(x2));
result.append(delimeter);
result.append(Utils::doubleToStr(y2));
result.append(" ]\n");
return result;
}
void Rectangle::setNewRectangleName(const char * newName)
{
_rectangleName = newName;
}
void Rectangle::recalculateInternalRectangleCoordinates(const PageTransformations & transformations)
{
TransformationMatrix tempTm;
for(size_t i = 0; i < transformations.size(); ++i)
{
tempTm = transformations[i]->getMatrix();
tempTm.add(_tm);
_tm = tempTm;
}
_tm.recalculateCoordinates(x1, y1);
_tm.recalculateCoordinates(x2, y2);
}
void Rectangle::updateRectangle(Object * objectWithRectangle, const char * delimeter)
{
Object * foundObjectWithRectangle;
unsigned int fake;
objectWithRectangle->findObject(std::string(_rectangleName), foundObjectWithRectangle, fake);
std::string objectContent = foundObjectWithRectangle->getObjectContent();
unsigned int rectanglePosition = objectContent.find(_rectangleName);
unsigned int endOfRectangle = objectContent.find("]", rectanglePosition) + 1;
foundObjectWithRectangle->eraseContent(rectanglePosition, endOfRectangle - rectanglePosition);
foundObjectWithRectangle->insertToContent(rectanglePosition, _getRectangleAsString(delimeter));
// reread the objectContent, since it was changed just above;
objectContent = foundObjectWithRectangle->getObjectContent();
//update matrix
unsigned int startOfAP = Parser::findToken(objectContent,"/AP");
unsigned int endOfAP = objectContent.find(">>", startOfAP);
std::vector<Object *> aps = foundObjectWithRectangle->getChildrenByBounds(startOfAP, endOfAP);
for(size_t i = 0; i < aps.size(); ++i)
{
Object * objectWithMatrix = aps[i];
std::string objectContent = objectWithMatrix->getObjectContent();
unsigned int matrixPosition = Parser::findToken(objectContent,"/Matrix");
if(matrixPosition == std::string::npos)
continue;
unsigned int matrixValueLeftBound = objectContent.find("[", matrixPosition);
unsigned int matrixValueRightBound = objectContent.find("]", matrixValueLeftBound) + 1;
objectWithMatrix->eraseContent(matrixValueLeftBound, matrixValueRightBound - matrixValueLeftBound);
objectWithMatrix->insertToContent(matrixValueLeftBound, _tm.getValue());
}
}
double Rectangle::getWidth()
{
return x2 - x1;
}
double Rectangle::getHeight()
{
return y2 - y1;
}

@ -1,39 +1,39 @@
#if !defined Rectangle_h
#define Rectangle_h
#include "Transformation.h"
#include <vector>
#include <map>
namespace merge_lib
{
class Object;
class Rectangle
{
public:
Rectangle(const char * rectangleName);
Rectangle(const char * rectangleName, const std::string content);
void appendRectangleToString(std::string & content, const char * delimeter);
void updateRectangle(Object * objectWithRectangle, const char * delimeter);
void setNewRectangleName(const char * newName);
void recalculateInternalRectangleCoordinates(const PageTransformations & transformations);
double getWidth();
double getHeight();
//members
double x1, x2, y1, y2;
private:
//methods
const std::string _getRectangleAsString(const char * delimeter);
//members
const char * _rectangleName;
TransformationMatrix _tm;
};
}
#endif
#if !defined Rectangle_h
#define Rectangle_h
#include "Transformation.h"
#include <vector>
#include <map>
namespace merge_lib
{
class Object;
class Rectangle
{
public:
Rectangle(const char * rectangleName);
Rectangle(const char * rectangleName, const std::string content);
void appendRectangleToString(std::string & content, const char * delimeter);
void updateRectangle(Object * objectWithRectangle, const char * delimeter);
void setNewRectangleName(const char * newName);
void recalculateInternalRectangleCoordinates(const PageTransformations & transformations);
double getWidth();
double getHeight();
//members
double x1, x2, y1, y2;
private:
//methods
const std::string _getRectangleAsString(const char * delimeter);
//members
const char * _rectangleName;
TransformationMatrix _tm;
};
}
#endif

@ -1,25 +1,25 @@
#if !defined RemoveHimselfHandler_h
#define RemoveHimselfHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
//This class remove field from Page object's content.
class RemoveHimselfHandler: public PageElementHandler
{
public:
RemoveHimselfHandler(Object * page, const std::string & handlerName): PageElementHandler(page)
{
_setHandlerName(handlerName);
}
virtual ~RemoveHimselfHandler()
{
}
private:
//methods
virtual void _changeObjectContent(unsigned int startOfPageElement);
};
}
#endif
#if !defined RemoveHimselfHandler_h
#define RemoveHimselfHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
//This class remove field from Page object's content.
class RemoveHimselfHandler: public PageElementHandler
{
public:
RemoveHimselfHandler(Object * page, const std::string & handlerName): PageElementHandler(page)
{
_setHandlerName(handlerName);
}
virtual ~RemoveHimselfHandler()
{
}
private:
//methods
virtual void _changeObjectContent(unsigned int startOfPageElement);
};
}
#endif

@ -1,14 +1,14 @@
#include "RemoveHimSelfHandler.h"
using namespace merge_lib;
void RemoveHimselfHandler::_changeObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfElement = _findEndOfElementContent(startOfPageElement);
_page->forgetAboutChildren(startOfPageElement, endOfElement);
_page->eraseContent(startOfPageElement, endOfElement - startOfPageElement);
}
#include "RemoveHimSelfHandler.h"
using namespace merge_lib;
void RemoveHimselfHandler::_changeObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfElement = _findEndOfElementContent(startOfPageElement);
_page->forgetAboutChildren(startOfPageElement, endOfElement);
_page->eraseContent(startOfPageElement, endOfElement - startOfPageElement);
}

@ -1,51 +1,51 @@
#if !defined RotationHandler_h
#define RotationHandler_h
#include "PageElementHandler.h"
#include "Page.h"
namespace merge_lib
{
//This class remove field from Page object's content.
class RotationHandler: public PageElementHandler
{
public:
RotationHandler(Object * page, const std::string & handlerName, Page & basePage):
PageElementHandler(page),
_basePage(basePage)
{
_setHandlerName(handlerName);
}
virtual ~RotationHandler()
{
}
private:
//methods
virtual void _processObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfElement = _findEndOfElementContent(startOfPageElement);
std::string rotationField = _page->getObjectContent().substr(startOfPageElement, endOfElement - startOfPageElement);
std::string numbers("1234567890");
unsigned int startOfNumber = rotationField.find_first_of(numbers);
if( startOfNumber > 0 )
{
if( rotationField[startOfNumber-1] == '-' )
{
startOfNumber--; // negative number
}
}
unsigned int endOfNumber = rotationField.find_first_not_of(numbers, startOfNumber + 1);
std::string rotationStr = rotationField.substr(startOfNumber, endOfNumber - startOfNumber + 1);
int rotation = 0;
std::stringstream strin(rotationStr);
strin>>rotation;
_basePage.setRotation(rotation);
}
virtual void _changeObjectContent(unsigned int startOfPageElement) {};
//members
Page & _basePage;
};
}
#endif
#if !defined RotationHandler_h
#define RotationHandler_h
#include "PageElementHandler.h"
#include "Page.h"
namespace merge_lib
{
//This class remove field from Page object's content.
class RotationHandler: public PageElementHandler
{
public:
RotationHandler(Object * page, const std::string & handlerName, Page & basePage):
PageElementHandler(page),
_basePage(basePage)
{
_setHandlerName(handlerName);
}
virtual ~RotationHandler()
{
}
private:
//methods
virtual void _processObjectContent(unsigned int startOfPageElement)
{
unsigned int endOfElement = _findEndOfElementContent(startOfPageElement);
std::string rotationField = _page->getObjectContent().substr(startOfPageElement, endOfElement - startOfPageElement);
std::string numbers("1234567890");
unsigned int startOfNumber = rotationField.find_first_of(numbers);
if( startOfNumber > 0 )
{
if( rotationField[startOfNumber-1] == '-' )
{
startOfNumber--; // negative number
}
}
unsigned int endOfNumber = rotationField.find_first_not_of(numbers, startOfNumber + 1);
std::string rotationStr = rotationField.substr(startOfNumber, endOfNumber - startOfNumber + 1);
int rotation = 0;
std::stringstream strin(rotationStr);
strin>>rotation;
_basePage.setRotation(rotation);
}
virtual void _changeObjectContent(unsigned int startOfPageElement) {};
//members
Page & _basePage;
};
}
#endif

@ -1,43 +1,43 @@
#include "RunLengthDecode.h"
#include "RunLengthDecode.h"
using namespace merge_lib;
/* The encoded data is a sequence of
runs, where each run consists of a length byte followed by 1 to 128 bytes of data. If
the length byte is in the range 0 to 127, the following length + 1 (1 to 128) bytes
are copied literally during decompression. If length is in the range 129 to 255, the
following single byte is to be copied 257 - length (2 to 128) times during decom-
pression. A length value of 128 denotes EOD. */
// Function performs RunLength Decoder for PDF, very simple
bool RunLengthDecode::decode(std::string & encoded)
{
std::string decoded;
for(unsigned enci = 0;enci < encoded.size();)
{
unsigned char c = encoded[enci++];
if( c == 128 )
{
break; //EOD
}
else if( c < 128 )
{
for(int j = 0; j < (c+1);j++)
{
decoded.append(1,encoded[enci]);
}
enci++;
}
else
{
for(int j = 0; j < (257 - c);j++)
{
decoded.append(1,encoded[enci]);
}
enci++;
}
}
return true;
}
/* The encoded data is a sequence of
runs, where each run consists of a length byte followed by 1 to 128 bytes of data. If
the length byte is in the range 0 to 127, the following length + 1 (1 to 128) bytes
are copied literally during decompression. If length is in the range 129 to 255, the
following single byte is to be copied 257 - length (2 to 128) times during decom-
pression. A length value of 128 denotes EOD. */
// Function performs RunLength Decoder for PDF, very simple
bool RunLengthDecode::decode(std::string & encoded)
{
std::string decoded;
for(unsigned enci = 0;enci < encoded.size();)
{
unsigned char c = encoded[enci++];
if( c == 128 )
{
break; //EOD
}
else if( c < 128 )
{
for(int j = 0; j < (c+1);j++)
{
decoded.append(1,encoded[enci]);
}
enci++;
}
else
{
for(int j = 0; j < (257 - c);j++)
{
decoded.append(1,encoded[enci]);
}
enci++;
}
}
return true;
}

@ -1,22 +1,22 @@
#ifndef RunLengthDecode_H
#define RunLengthDecode_H
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this class provides method for RunLengthDecode aaaaaencoding and decoding
class RunLengthDecode : public Decoder
{
public:
RunLengthDecode(){};
virtual ~RunLengthDecode(){};
bool encode(std::string & decoded){return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStream){};
};
}
#endif // FLATEDECODE_H_INCLUDED
#ifndef RunLengthDecode_H
#define RunLengthDecode_H
#include <string>
#include "Decoder.h"
namespace merge_lib
{
// this class provides method for RunLengthDecode aaaaaencoding and decoding
class RunLengthDecode : public Decoder
{
public:
RunLengthDecode(){};
virtual ~RunLengthDecode(){};
bool encode(std::string & decoded){return false;}
bool decode(std::string & encoded);
void initialize(Object * objectWithStream){};
};
}
#endif // FLATEDECODE_H_INCLUDED

@ -1,331 +1,331 @@
/*
The file defines some classes for transformation of PDF content stream.
*/
#ifndef TRANSFORMATION_H
#define TRANSFORMATION_H
#include <sstream>
#include <string>
#include <math.h>
#include <vector>
#include <iostream>
#include "Utils.h"
namespace merge_lib
{
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
class TransformationMatrix
{
public:
TransformationMatrix(double a = 1, double b = 0, double c = 0, double d = 1, double e = 0, double f = 0):
_a(a), _b(b), _c(c), _d(d), _e(e), _f(f)
{}
TransformationMatrix(const TransformationMatrix & copy)
{
setParameters(copy._a, copy._b, copy._c, copy._d, copy._e, copy._f);
}
void setParameters(double a, double b, double c, double d, double e, double f)
{
_a = Utils::normalizeValue(a);
_b = Utils::normalizeValue(b);
_c = Utils::normalizeValue(c);
_d = Utils::normalizeValue(d);
_e = Utils::normalizeValue(e);
_f = Utils::normalizeValue(f);
}
void add(const TransformationMatrix & tm)
{
double newA = _a*tm._a + _b*tm._c;
double newB = _a*tm._b + _b*tm._d;
double newC = _c*tm._a + _d*tm._c;
double newD = _c*tm._b + _d*tm._d;
double newE = _e*tm._a + _f*tm._c + tm._e;
double newF = _e*tm._b + _f*tm._d + tm._f;
// we need to round the values to avoid not-needed transformation
// since 1.e-17 is not 0 from PDF point of view, while such double
// value really means 0.
_a = Utils::normalizeValue(newA);
_b = Utils::normalizeValue(newB);
_c = Utils::normalizeValue(newC);
_d = Utils::normalizeValue(newD);
_e = Utils::normalizeValue(newE);
_f = Utils::normalizeValue(newF);
}
std::string getValue()
{
std::ostringstream value;
value << "[ " << _a << " " << _b << " " << _c << " " << _d << " " << _e << " " << _f << " ]\n";
return value.str();
}
std::string getCMT()
{
std::ostringstream buf;
buf << std::fixed << _a <<" "<< _b <<" "<< _c <<" "<< _d << " "<< _e << " "<< _f << " cm\n";
return buf.str();
}
void recalculateCoordinates(double & x, double &y)
{
double inputX = x;
double inputY = y;
x = _a*inputX + _c*inputY + _e;
y = _b*inputX + _d*inputY + _f;
}
private:
double _a, _b, _c, _d, _e, _f;
};
// base class of transformation CMT
class Transformation
{
public:
Transformation(): _tm(){};
virtual Transformation * getClone() const = 0;
std::string getCMT()
{
return _tm.getCMT();
}
virtual ~Transformation() {};
const TransformationMatrix & getMatrix()
{
return _tm;
}
void addMatrix(const TransformationMatrix & tm)
{
_tm.add(tm);
}
protected:
TransformationMatrix _tm;
};
// rotation CMT
class Rotation: public Transformation
{
public:
Rotation(double angle):Transformation(),_angle(angle)
{
double cosValue = cos(_angle * (M_PI / 180));
double sinValue = sin(_angle * (M_PI / 180));
_tm.setParameters(cosValue, sinValue, -sinValue, cosValue, 0, 0);
};
virtual ~Rotation(){};
virtual Transformation * getClone() const
{
return new Rotation(_angle);
}
protected:
double _angle; // number of degrees to rotate
};
// translation CMT
class Translation: public Transformation
{
public:
Translation(double x, double y):Transformation(),_x(x),_y(y)
{
_tm.setParameters(1, 0, 0, 1, _x, _y);
};
virtual ~Translation(){};
virtual Transformation * getClone() const
{
return new Translation(_x, _y);
}
protected:
double _x;
double _y;
};
// scaling CMT
class Scaling: public Transformation
{
public:
Scaling(double x):Transformation(),_x(x)
{
_tm.setParameters(_x, 0, 0, _x, 0, 0);
};
virtual Transformation * getClone() const
{
return new Scaling(_x);
}
protected:
double _x; // the value to multiply the content
};
// transformation can consist of one or several
// operations like rotation, scaling, translation
typedef std::vector<Transformation *> PageTransformations;
// This is interface class for setting transformation parameters
//
class TransformationDescription
{
public:
TransformationDescription( double x = 0, // leftBottomX coordinate
double y = 0, // leftBottomY coordinate
double scale = 1, // scale (by default = 1 = NONE
int angel = 0): // rotation (0,90,180,270)
_x(x),_y(y),_scale(scale),_angel(angel)
{
if( _angel )
{
_transforms.push_back(new Rotation(_angel));
}
if( !Utils::doubleEquals(_scale,1) && !Utils::doubleEquals(_scale,0) )
{
_transforms.push_back(new Scaling(_scale));
}
}
virtual ~TransformationDescription()
{
for(size_t i = 0;i<_annotsTransforms.size();i++)
{
if( _annotsTransforms[i] )
{
delete _annotsTransforms[i];
_annotsTransforms[i] = 0;
}
_annotsTransforms.clear();
}
for(size_t i = 0;i<_transforms.size();i++)
{
if( _transforms[i] )
{
delete _transforms[i];
_transforms[i] = 0;
}
}
_transforms.clear();
}
void addRotation(int rotation)
{
if( rotation )
{
_angel = (_angel - rotation)%360;
// /Rotation rotate the object, while _angel rotate the coordinate system
// where object is located, that's why
// we should compensate that
_transforms.push_back(new Rotation(360-rotation));
}
}
const PageTransformations & getTransformations() const
{
return _transforms;
}
const PageTransformations getAnnotsTransformations() const
{
PageTransformations trans;
trans = _transforms;
for(size_t i = 0; i < _annotsTransforms.size(); ++i)
{
trans.push_back(_annotsTransforms[i]);
}
return trans;
}
void addAnnotsTransformation( Transformation & trans )
{
_annotsTransforms.push_back(trans.getClone());
}
// method recalculates the final translation in order to put
// object into needed x,y coordinates.
// Page is located from position 0,0
void recalculateTranslation(double width, double height)
{
double dx1 = 0;
double dy1 = 0;
double scaling = ( Utils::doubleEquals(_scale,0))?1:_scale;
switch(_angel)
{
case 0:
dx1 = _x/scaling;
dy1 = _y/scaling;
break;
case -270:
case 90:
dx1 = _y/scaling ;
dy1 = - _x /scaling - height;
break;
case 180:
case -180:
dx1 = - _x /scaling - width;
dy1 = - _y /scaling - height;
break;
case 270:
case -90:
dx1 = - _y/scaling - width;
dy1 = _x/scaling;
break;
default:
std::cerr<<"Unsupported rotation parameter"<<_angel<<std::endl;
break;
}
//std::cerr<< "dx1 = "<<dx1<<"dy1 = "<<dy1<<std::endl;
if( ! (Utils::doubleEquals(dx1,0) && Utils::doubleEquals(dy1,0)) )
{
// This translation is needed to put transformed content into
// desired coordinates
_transforms.push_back(new Translation(dx1,dy1));
}
}
TransformationDescription( const TransformationDescription & copy)
{
*this = copy;
}
TransformationDescription& operator = (const TransformationDescription &copy)
{
if( this != &copy )
{
for(size_t i = 0;i < copy._annotsTransforms.size();i++)
{
_annotsTransforms.push_back(copy._annotsTransforms[i]->getClone());
}
for(size_t i = 0; i < copy._transforms.size(); ++i)
{
_transforms.push_back(copy._transforms[i]->getClone());
}
_x = copy._x;
_y = copy._y;
_scale = copy._scale;
_angel = copy._angel;
}
return *this;
}
std::string getCMT()
{
std::stringstream content;
for(size_t i = 0;i<_transforms.size();i++)
{
content<<_transforms[i]->getCMT();
}
return content.str();
}
private:
double _x;
double _y;
double _scale;
int _angel;
PageTransformations _transforms;
PageTransformations _annotsTransforms;
};
}
#endif
/*
The file defines some classes for transformation of PDF content stream.
*/
#ifndef TRANSFORMATION_H
#define TRANSFORMATION_H
#include <sstream>
#include <string>
#include <math.h>
#include <vector>
#include <iostream>
#include "Utils.h"
namespace merge_lib
{
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
class TransformationMatrix
{
public:
TransformationMatrix(double a = 1, double b = 0, double c = 0, double d = 1, double e = 0, double f = 0):
_a(a), _b(b), _c(c), _d(d), _e(e), _f(f)
{}
TransformationMatrix(const TransformationMatrix & copy)
{
setParameters(copy._a, copy._b, copy._c, copy._d, copy._e, copy._f);
}
void setParameters(double a, double b, double c, double d, double e, double f)
{
_a = Utils::normalizeValue(a);
_b = Utils::normalizeValue(b);
_c = Utils::normalizeValue(c);
_d = Utils::normalizeValue(d);
_e = Utils::normalizeValue(e);
_f = Utils::normalizeValue(f);
}
void add(const TransformationMatrix & tm)
{
double newA = _a*tm._a + _b*tm._c;
double newB = _a*tm._b + _b*tm._d;
double newC = _c*tm._a + _d*tm._c;
double newD = _c*tm._b + _d*tm._d;
double newE = _e*tm._a + _f*tm._c + tm._e;
double newF = _e*tm._b + _f*tm._d + tm._f;
// we need to round the values to avoid not-needed transformation
// since 1.e-17 is not 0 from PDF point of view, while such double
// value really means 0.
_a = Utils::normalizeValue(newA);
_b = Utils::normalizeValue(newB);
_c = Utils::normalizeValue(newC);
_d = Utils::normalizeValue(newD);
_e = Utils::normalizeValue(newE);
_f = Utils::normalizeValue(newF);
}
std::string getValue()
{
std::ostringstream value;
value << "[ " << _a << " " << _b << " " << _c << " " << _d << " " << _e << " " << _f << " ]\n";
return value.str();
}
std::string getCMT()
{
std::ostringstream buf;
buf << std::fixed << _a <<" "<< _b <<" "<< _c <<" "<< _d << " "<< _e << " "<< _f << " cm\n";
return buf.str();
}
void recalculateCoordinates(double & x, double &y)
{
double inputX = x;
double inputY = y;
x = _a*inputX + _c*inputY + _e;
y = _b*inputX + _d*inputY + _f;
}
private:
double _a, _b, _c, _d, _e, _f;
};
// base class of transformation CMT
class Transformation
{
public:
Transformation(): _tm(){};
virtual Transformation * getClone() const = 0;
std::string getCMT()
{
return _tm.getCMT();
}
virtual ~Transformation() {};
const TransformationMatrix & getMatrix()
{
return _tm;
}
void addMatrix(const TransformationMatrix & tm)
{
_tm.add(tm);
}
protected:
TransformationMatrix _tm;
};
// rotation CMT
class Rotation: public Transformation
{
public:
Rotation(double angle):Transformation(),_angle(angle)
{
double cosValue = cos(_angle * (M_PI / 180));
double sinValue = sin(_angle * (M_PI / 180));
_tm.setParameters(cosValue, sinValue, -sinValue, cosValue, 0, 0);
};
virtual ~Rotation(){};
virtual Transformation * getClone() const
{
return new Rotation(_angle);
}
protected:
double _angle; // number of degrees to rotate
};
// translation CMT
class Translation: public Transformation
{
public:
Translation(double x, double y):Transformation(),_x(x),_y(y)
{
_tm.setParameters(1, 0, 0, 1, _x, _y);
};
virtual ~Translation(){};
virtual Transformation * getClone() const
{
return new Translation(_x, _y);
}
protected:
double _x;
double _y;
};
// scaling CMT
class Scaling: public Transformation
{
public:
Scaling(double x):Transformation(),_x(x)
{
_tm.setParameters(_x, 0, 0, _x, 0, 0);
};
virtual Transformation * getClone() const
{
return new Scaling(_x);
}
protected:
double _x; // the value to multiply the content
};
// transformation can consist of one or several
// operations like rotation, scaling, translation
typedef std::vector<Transformation *> PageTransformations;
// This is interface class for setting transformation parameters
//
class TransformationDescription
{
public:
TransformationDescription( double x = 0, // leftBottomX coordinate
double y = 0, // leftBottomY coordinate
double scale = 1, // scale (by default = 1 = NONE
int angel = 0): // rotation (0,90,180,270)
_x(x),_y(y),_scale(scale),_angel(angel)
{
if( _angel )
{
_transforms.push_back(new Rotation(_angel));
}
if( !Utils::doubleEquals(_scale,1) && !Utils::doubleEquals(_scale,0) )
{
_transforms.push_back(new Scaling(_scale));
}
}
virtual ~TransformationDescription()
{
for(size_t i = 0;i<_annotsTransforms.size();i++)
{
if( _annotsTransforms[i] )
{
delete _annotsTransforms[i];
_annotsTransforms[i] = 0;
}
_annotsTransforms.clear();
}
for(size_t i = 0;i<_transforms.size();i++)
{
if( _transforms[i] )
{
delete _transforms[i];
_transforms[i] = 0;
}
}
_transforms.clear();
}
void addRotation(int rotation)
{
if( rotation )
{
_angel = (_angel - rotation)%360;
// /Rotation rotate the object, while _angel rotate the coordinate system
// where object is located, that's why
// we should compensate that
_transforms.push_back(new Rotation(360-rotation));
}
}
const PageTransformations & getTransformations() const
{
return _transforms;
}
const PageTransformations getAnnotsTransformations() const
{
PageTransformations trans;
trans = _transforms;
for(size_t i = 0; i < _annotsTransforms.size(); ++i)
{
trans.push_back(_annotsTransforms[i]);
}
return trans;
}
void addAnnotsTransformation( Transformation & trans )
{
_annotsTransforms.push_back(trans.getClone());
}
// method recalculates the final translation in order to put
// object into needed x,y coordinates.
// Page is located from position 0,0
void recalculateTranslation(double width, double height)
{
double dx1 = 0;
double dy1 = 0;
double scaling = ( Utils::doubleEquals(_scale,0))?1:_scale;
switch(_angel)
{
case 0:
dx1 = _x/scaling;
dy1 = _y/scaling;
break;
case -270:
case 90:
dx1 = _y/scaling ;
dy1 = - _x /scaling - height;
break;
case 180:
case -180:
dx1 = - _x /scaling - width;
dy1 = - _y /scaling - height;
break;
case 270:
case -90:
dx1 = - _y/scaling - width;
dy1 = _x/scaling;
break;
default:
std::cerr<<"Unsupported rotation parameter"<<_angel<<std::endl;
break;
}
//std::cerr<< "dx1 = "<<dx1<<"dy1 = "<<dy1<<std::endl;
if( ! (Utils::doubleEquals(dx1,0) && Utils::doubleEquals(dy1,0)) )
{
// This translation is needed to put transformed content into
// desired coordinates
_transforms.push_back(new Translation(dx1,dy1));
}
}
TransformationDescription( const TransformationDescription & copy)
{
*this = copy;
}
TransformationDescription& operator = (const TransformationDescription &copy)
{
if( this != &copy )
{
for(size_t i = 0;i < copy._annotsTransforms.size();i++)
{
_annotsTransforms.push_back(copy._annotsTransforms[i]->getClone());
}
for(size_t i = 0; i < copy._transforms.size(); ++i)
{
_transforms.push_back(copy._transforms[i]->getClone());
}
_x = copy._x;
_y = copy._y;
_scale = copy._scale;
_angel = copy._angel;
}
return *this;
}
std::string getCMT()
{
std::stringstream content;
for(size_t i = 0;i<_transforms.size();i++)
{
content<<_transforms[i]->getCMT();
}
return content.str();
}
private:
double _x;
double _y;
double _scale;
int _angel;
PageTransformations _transforms;
PageTransformations _annotsTransforms;
};
}
#endif

@ -1,30 +1,30 @@
#if !defined TypeElementHandler_h
#define TypeElementHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
class TypeElementHandler: public PageElementHandler
{
public:
TypeElementHandler(Object * page): PageElementHandler(page)
{
_setHandlerName("/Type");
}
private:
virtual void _changeObjectContent(unsigned int startOfPageElement)
{
std::string searchPattern("/Page");
unsigned int startOfPage = _pageContent.find(searchPattern, startOfPageElement);
_page->eraseContent(startOfPage, searchPattern.size());
std::string xObject = " /XObject\n";
_page->insertToContent(startOfPage, xObject);
static std::string subtype("/Subtype /Form\n");
_page->insertToContent(startOfPage + xObject.size(), subtype);
}
};
}
#endif
#if !defined TypeElementHandler_h
#define TypeElementHandler_h
#include "PageElementHandler.h"
namespace merge_lib
{
class TypeElementHandler: public PageElementHandler
{
public:
TypeElementHandler(Object * page): PageElementHandler(page)
{
_setHandlerName("/Type");
}
private:
virtual void _changeObjectContent(unsigned int startOfPageElement)
{
std::string searchPattern("/Page");
unsigned int startOfPage = _pageContent.find(searchPattern, startOfPageElement);
_page->eraseContent(startOfPage, searchPattern.size());
std::string xObject = " /XObject\n";
_page->insertToContent(startOfPage, xObject);
static std::string subtype("/Subtype /Form\n");
_page->insertToContent(startOfPage + xObject.size(), subtype);
}
};
}
#endif

@ -1,197 +1,197 @@
#include "Config.h"
#include "Utils.h"
#include "Exception.h"
#include <iostream>
#include <cmath>
#include <sstream>
#include <fstream>
#include <string.h>
using namespace merge_lib;
int Utils::stringToInt(const std::string & str) //throw ConvertException
{
//skip zeros
unsigned int lastZero = 0;str.find_last_of("0");
while(str[lastZero++] == '0')
{
if(lastZero == str.size())
{
return 0;
}
}
//if lastZero = 1, then 0 is not first symbol
lastZero--;
if((str.size() > 1) && (lastZero != 0))
{
//all number is zero, for ex. 00000000
std::string copy = str;
const std::string & cutedStr = copy.erase(0, lastZero);
return _stringToInt(cutedStr) ;
}
else
{
return _stringToInt(str);
}
}
double Utils::stringToDouble(const std::string & s )
{
std::istringstream i(s);
double x;
if (!(i >> x))
//TODO or throw exception? Think about!
return 0;
return x;
}
std::string Utils::uIntToStr(unsigned int integer)
{
char str[10];
snprintf(str, sizeof(str), "%u", integer);
return std::string(str);
}
std::string Utils::doubleToStr(double doubleValue)
{
char str[16];
snprintf(str, sizeof(str), "%f", doubleValue);
return std::string(str);
}
int Utils::_stringToInt(const std::string & str) //throw ConvertException
{
int intValue = atoi(str.c_str());
if(((intValue == 0) && (str.size() > 1)) || // for ex string = xxx and integer = 0
((intValue == 0) && (str[0] != '0')))
{
throw Exception("Internal error");
}
if((intValue != 0) && (static_cast<unsigned int>(std::log10(static_cast<double>(intValue))) + 1) != str.size()) //for ex. string = 5x and integer = 5)
{
throw Exception("Internal error");
}
return intValue;
}
bool Utils::doubleEquals(const double left, const double right, const double epsilon)
{
return ( fabs (left - right) < epsilon);
}
double Utils::normalizeValue(double &val, const double epsilon )
{
if( Utils::doubleEquals(val,0))
{
val = 0;
}
return val;
}
unsigned long Utils::getFileSize(const char * fileName)
{
std::ifstream pdfFile;
pdfFile.open (fileName, std::ios::binary );
if (pdfFile.fail())
{
std::stringstream errorMessage("File ");
errorMessage << fileName << " is absent" << "\0";
throw Exception(errorMessage);
}
// get length of file:
pdfFile.seekg (0, std::ios::end);
unsigned long length = pdfFile.tellg();
pdfFile.close();
return length;
}
#ifdef DEBUG_VERBOSE
#define TO_HEX_CHAR(char_c) (char_c)>9?'A'+(char_c)-10:'0'+(char_c);
static void hex_dump_one_line(int numberChars_n,
const char *input_p,
char *output_p)
{
int i;
char* to_hex_p;
char* to_char_p;
char char_c;
/* Set pointer to the begining of hexadecimal area */
to_hex_p=output_p;
/* Set pointer to the begining of textual area */
to_char_p=output_p+56;
/* Write spaces between hexadecimal and textual areas */
memset(output_p+50,' ',6);
/* some kind of delimeter */
*(output_p+53) = '#';
/* Print out the hex area */
for (i = 0 ; i < 16 ; i++)
{
/* Two spaces beetwen "four columns" */
if (!(i&3))
{
*to_hex_p++=' ';
}
/* One space between columns */
*to_hex_p++=' ';
if (i < numberChars_n)
{
/* Print out byte in hexadecimal form */
*to_hex_p++=TO_HEX_CHAR((input_p[i]>>4)&0xF);
*to_hex_p++=TO_HEX_CHAR(input_p[i]&0xF);
/* Output the char */
char_c = input_p[i]&0xFF;
if ( char_c<0x20 || char_c>0x7E )
{
char_c = '.';
}
*to_char_p=char_c;
to_char_p++;
}
else
{
*to_hex_p++=' ';
*to_hex_p++=' ';
*to_char_p++=' ';
}
} /* for */
}
void trace_buffer(const void *buf, int len)
{
char dump[160];
int line_n = len/16;
int rest_n = len- line_n*16;
int i;
memset(dump,0,160);
printf(" length:%d\n",len);
for (i = 0;i<line_n;i++)
{
hex_dump_one_line(16,
(char*)buf+(i*16),
dump);
printf("%s\n",dump);;
}
if ( rest_n)
{
hex_dump_one_line(rest_n,
(char*)buf+(line_n*16),
dump);
printf("%s\n",dump);
}
}
#endif
#include "Config.h"
#include "Utils.h"
#include "Exception.h"
#include <iostream>
#include <cmath>
#include <sstream>
#include <fstream>
#include <string.h>
using namespace merge_lib;
int Utils::stringToInt(const std::string & str) //throw ConvertException
{
//skip zeros
unsigned int lastZero = 0;str.find_last_of("0");
while(str[lastZero++] == '0')
{
if(lastZero == str.size())
{
return 0;
}
}
//if lastZero = 1, then 0 is not first symbol
lastZero--;
if((str.size() > 1) && (lastZero != 0))
{
//all number is zero, for ex. 00000000
std::string copy = str;
const std::string & cutedStr = copy.erase(0, lastZero);
return _stringToInt(cutedStr) ;
}
else
{
return _stringToInt(str);
}
}
double Utils::stringToDouble(const std::string & s )
{
std::istringstream i(s);
double x;
if (!(i >> x))
//TODO or throw exception? Think about!
return 0;
return x;
}
std::string Utils::uIntToStr(unsigned int integer)
{
char str[10];
snprintf(str, sizeof(str), "%u", integer);
return std::string(str);
}
std::string Utils::doubleToStr(double doubleValue)
{
char str[16];
snprintf(str, sizeof(str), "%f", doubleValue);
return std::string(str);
}
int Utils::_stringToInt(const std::string & str) //throw ConvertException
{
int intValue = atoi(str.c_str());
if(((intValue == 0) && (str.size() > 1)) || // for ex string = xxx and integer = 0
((intValue == 0) && (str[0] != '0')))
{
throw Exception("Internal error");
}
if((intValue != 0) && (static_cast<unsigned int>(std::log10(static_cast<double>(intValue))) + 1) != str.size()) //for ex. string = 5x and integer = 5)
{
throw Exception("Internal error");
}
return intValue;
}
bool Utils::doubleEquals(const double left, const double right, const double epsilon)
{
return ( fabs (left - right) < epsilon);
}
double Utils::normalizeValue(double &val, const double epsilon )
{
if( Utils::doubleEquals(val,0))
{
val = 0;
}
return val;
}
unsigned long Utils::getFileSize(const char * fileName)
{
std::ifstream pdfFile;
pdfFile.open (fileName, std::ios::binary );
if (pdfFile.fail())
{
std::stringstream errorMessage("File ");
errorMessage << fileName << " is absent" << "\0";
throw Exception(errorMessage);
}
// get length of file:
pdfFile.seekg (0, std::ios::end);
unsigned long length = pdfFile.tellg();
pdfFile.close();
return length;
}
#ifdef DEBUG_VERBOSE
#define TO_HEX_CHAR(char_c) (char_c)>9?'A'+(char_c)-10:'0'+(char_c);
static void hex_dump_one_line(int numberChars_n,
const char *input_p,
char *output_p)
{
int i;
char* to_hex_p;
char* to_char_p;
char char_c;
/* Set pointer to the begining of hexadecimal area */
to_hex_p=output_p;
/* Set pointer to the begining of textual area */
to_char_p=output_p+56;
/* Write spaces between hexadecimal and textual areas */
memset(output_p+50,' ',6);
/* some kind of delimeter */
*(output_p+53) = '#';
/* Print out the hex area */
for (i = 0 ; i < 16 ; i++)
{
/* Two spaces beetwen "four columns" */
if (!(i&3))
{
*to_hex_p++=' ';
}
/* One space between columns */
*to_hex_p++=' ';
if (i < numberChars_n)
{
/* Print out byte in hexadecimal form */
*to_hex_p++=TO_HEX_CHAR((input_p[i]>>4)&0xF);
*to_hex_p++=TO_HEX_CHAR(input_p[i]&0xF);
/* Output the char */
char_c = input_p[i]&0xFF;
if ( char_c<0x20 || char_c>0x7E )
{
char_c = '.';
}
*to_char_p=char_c;
to_char_p++;
}
else
{
*to_hex_p++=' ';
*to_hex_p++=' ';
*to_char_p++=' ';
}
} /* for */
}
void trace_buffer(const void *buf, int len)
{
char dump[160];
int line_n = len/16;
int rest_n = len- line_n*16;
int i;
memset(dump,0,160);
printf(" length:%d\n",len);
for (i = 0;i<line_n;i++)
{
hex_dump_one_line(16,
(char*)buf+(i*16),
dump);
printf("%s\n",dump);;
}
if ( rest_n)
{
hex_dump_one_line(rest_n,
(char*)buf+(line_n*16),
dump);
printf("%s\n",dump);
}
}
#endif

@ -1,32 +1,32 @@
#if !defined Utils_h
#define Utils_h
#include "Config.h"
#include <stdlib.h>
#include <string>
#include <time.h>
#include <stdio.h>
namespace merge_lib
{
class Utils
{
public:
static int stringToInt(const std::string & str); //throw ConvertException
static std::string uIntToStr(unsigned int integer);
static std::string doubleToStr(double doubleValue);
static double stringToDouble(const std::string & s );
static bool doubleEquals(const double left,const double right, const double epsilon = +1.e-10);
static double normalizeValue(double &val,const double epsilon = +1.e-10);
static unsigned long getFileSize(const char * fileName);
private:
static int _stringToInt(const std::string & str); //throw ConvertException
static int _stringToInt(std::string & str); //throw ConvertException
};
}
#endif
#if !defined Utils_h
#define Utils_h
#include "Config.h"
#include <stdlib.h>
#include <string>
#include <time.h>
#include <stdio.h>
namespace merge_lib
{
class Utils
{
public:
static int stringToInt(const std::string & str); //throw ConvertException
static std::string uIntToStr(unsigned int integer);
static std::string doubleToStr(double doubleValue);
static double stringToDouble(const std::string & s );
static bool doubleEquals(const double left,const double right, const double epsilon = +1.e-10);
static double normalizeValue(double &val,const double epsilon = +1.e-10);
static unsigned long getFileSize(const char * fileName);
private:
static int _stringToInt(const std::string & str); //throw ConvertException
static int _stringToInt(std::string & str); //throw ConvertException
};
}
#endif

@ -1,63 +1,62 @@
INCLUDEPATH += "$$PWD/../../zlib/1.2.3/include"
HEADERS += \
AnnotsHandler.h \
ASCII85Decode.h \
ASCIIHexDecode.h \
CCITTFaxDecode.h \
Config.h \
ContentHandler.h \
DCTDecode.h \
Decoder.h \
Document.h \
Exception.h \
FileIsAbsentException.h \
Filter.h \
FilterPredictor.h \
FlateDecode.h \
JBIG2Decode.h \
LZWDecode.h \
MediaBoxElementHandler.h \
MergePageDescription.h \
Merger.h \
Object.h \
Page.h \
PageElementHandler.h \
PageParser.h \
Parser.h \
Rectangle.h \
RemoveHimSelfHandler.h \
RunLengthDecode.h \
Transformation.h \
TypeElementHandler.h \
Utils.h \
AbstractBoxElementHandler.h \
CropBoxElementHandler.h \
OverlayDocumentParser.h \
RotationHandler.h
AnnotsHandler.h \
ASCII85Decode.h \
ASCIIHexDecode.h \
CCITTFaxDecode.h \
Config.h \
ContentHandler.h \
DCTDecode.h \
Decoder.h \
Document.h \
Exception.h \
FileIsAbsentException.h \
Filter.h \
FilterPredictor.h \
FlateDecode.h \
JBIG2Decode.h \
LZWDecode.h \
MediaBoxElementHandler.h \
MergePageDescription.h \
Merger.h \
Object.h \
Page.h \
PageElementHandler.h \
PageParser.h \
Parser.h \
Rectangle.h \
RemoveHimSelfHandler.h \
RunLengthDecode.h \
Transformation.h \
TypeElementHandler.h \
Utils.h \
AbstractBoxElementHandler.h \
CropBoxElementHandler.h \
OverlayDocumentParser.h \
RotationHandler.h
SOURCES += \
AnnotsHandler.cpp \
ASCII85Decode.cpp \
ASCIIHexDecode.cpp \
ContentHandler.cpp \
Document.cpp \
Filter.cpp \
FilterPredictor.cpp \
FlateDecode.cpp \
LZWDecode.cpp \
Merger.cpp \
Object.cpp \
Page.cpp \
PageElementHandler.cpp \
Parser.cpp \
Rectangle.cpp \
RemoveHimselfHandler.cpp \
RunLengthDecode.cpp \
Utils.cpp \
OverlayDocumentParser.cpp
AnnotsHandler.cpp \
ASCII85Decode.cpp \
ASCIIHexDecode.cpp \
ContentHandler.cpp \
Document.cpp \
Filter.cpp \
FilterPredictor.cpp \
FlateDecode.cpp \
LZWDecode.cpp \
Merger.cpp \
Object.cpp \
Page.cpp \
PageElementHandler.cpp \
Parser.cpp \
Rectangle.cpp \
RemoveHimselfHandler.cpp \
RunLengthDecode.cpp \
Utils.cpp \
OverlayDocumentParser.cpp
macx {
LIBS += -lz
Loading…
Cancel
Save