parent
97cee1b6b0
commit
7564a8badf
@ -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 ©) |
||||
{ |
||||
if( this != © ) |
||||
{ |
||||
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 ©) |
||||
{ |
||||
if( this != © ) |
||||
{ |
||||
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 |
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 ©) |
||||
{ |
||||
if( this != © ) |
||||
{ |
||||
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 ©) |
||||
{ |
||||
if( this != © ) |
||||
{ |
||||
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…
Reference in new issue