Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpenBoard
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lifo
Nicolas Ollinger
OpenBoard
Commits
7564a8ba
Commit
7564a8ba
authored
May 19, 2011
by
Claudio Valerio
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
moved pdf merger file into src directory.
parent
97cee1b6
Changes
55
Hide whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
3883 additions
and
3884 deletions
+3883
-3884
ASCII85Decode.cpp
src/pdf-merger/ASCII85Decode.cpp
+106
-106
ASCII85Decode.h
src/pdf-merger/ASCII85Decode.h
+24
-24
ASCIIHexDecode.cpp
src/pdf-merger/ASCIIHexDecode.cpp
+61
-61
ASCIIHexDecode.h
src/pdf-merger/ASCIIHexDecode.h
+22
-22
AbstractBoxElementHandler.h
src/pdf-merger/AbstractBoxElementHandler.h
+59
-59
AnnotsHandler.cpp
src/pdf-merger/AnnotsHandler.cpp
+0
-0
AnnotsHandler.h
src/pdf-merger/AnnotsHandler.h
+33
-33
CCITTFaxDecode.h
src/pdf-merger/CCITTFaxDecode.h
+21
-21
Config.h
src/pdf-merger/Config.h
+0
-0
ContentHandler.cpp
src/pdf-merger/ContentHandler.cpp
+73
-73
ContentHandler.h
src/pdf-merger/ContentHandler.h
+46
-46
CropBoxElementHandler.h
src/pdf-merger/CropBoxElementHandler.h
+52
-52
DCTDecode.h
src/pdf-merger/DCTDecode.h
+22
-22
Decoder.h
src/pdf-merger/Decoder.h
+25
-25
Document.cpp
src/pdf-merger/Document.cpp
+0
-0
Document.h
src/pdf-merger/Document.h
+0
-0
Exception.h
src/pdf-merger/Exception.h
+36
-36
FileIsAbsentException.h
src/pdf-merger/FileIsAbsentException.h
+19
-19
Filter.cpp
src/pdf-merger/Filter.cpp
+0
-0
Filter.h
src/pdf-merger/Filter.h
+0
-0
FilterPredictor.cpp
src/pdf-merger/FilterPredictor.cpp
+264
-264
FilterPredictor.h
src/pdf-merger/FilterPredictor.h
+44
-44
FlateDecode.cpp
src/pdf-merger/FlateDecode.cpp
+202
-202
FlateDecode.h
src/pdf-merger/FlateDecode.h
+26
-26
JBIG2Decode.h
src/pdf-merger/JBIG2Decode.h
+22
-22
LZWDecode.cpp
src/pdf-merger/LZWDecode.cpp
+193
-193
LZWDecode.h
src/pdf-merger/LZWDecode.h
+41
-41
MediaBoxElementHandler.h
src/pdf-merger/MediaBoxElementHandler.h
+52
-52
MergePageDescription.h
src/pdf-merger/MergePageDescription.h
+97
-97
Merger.cpp
src/pdf-merger/Merger.cpp
+115
-115
Merger.h
src/pdf-merger/Merger.h
+42
-42
Object.cpp
src/pdf-merger/Object.cpp
+0
-0
Object.h
src/pdf-merger/Object.h
+149
-149
OverlayDocumentParser.cpp
src/pdf-merger/OverlayDocumentParser.cpp
+144
-144
OverlayDocumentParser.h
src/pdf-merger/OverlayDocumentParser.h
+40
-40
Page.cpp
src/pdf-merger/Page.cpp
+552
-552
Page.h
src/pdf-merger/Page.h
+64
-64
PageElementHandler.cpp
src/pdf-merger/PageElementHandler.cpp
+74
-74
PageElementHandler.h
src/pdf-merger/PageElementHandler.h
+84
-84
PageParser.h
src/pdf-merger/PageParser.h
+41
-41
Parser.cpp
src/pdf-merger/Parser.cpp
+0
-0
Parser.h
src/pdf-merger/Parser.h
+76
-76
Rectangle.cpp
src/pdf-merger/Rectangle.cpp
+124
-124
Rectangle.h
src/pdf-merger/Rectangle.h
+39
-39
RemoveHimSelfHandler.h
src/pdf-merger/RemoveHimSelfHandler.h
+25
-25
RemoveHimselfHandler.cpp
src/pdf-merger/RemoveHimselfHandler.cpp
+14
-14
RotationHandler.h
src/pdf-merger/RotationHandler.h
+51
-51
RunLengthDecode.cpp
src/pdf-merger/RunLengthDecode.cpp
+42
-42
RunLengthDecode.h
src/pdf-merger/RunLengthDecode.h
+22
-22
Transformation.h
src/pdf-merger/Transformation.h
+331
-331
TypeElementHandler.h
src/pdf-merger/TypeElementHandler.h
+30
-30
Utils.cpp
src/pdf-merger/Utils.cpp
+197
-197
Utils.h
src/pdf-merger/Utils.h
+32
-32
PDF Merge Library Description.doc
src/pdf-merger/doc/PDF Merge Library Description.doc
+0
-0
pdfMerger.pri
src/pdf-merger/pdfMerger.pri
+55
-56
No files found.
thirdparty/mera
/pdf-merger/ASCII85Decode.cpp
→
src
/pdf-merger/ASCII85Decode.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/ASCII85Decode.h
→
src
/pdf-merger/ASCII85Decode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/ASCIIHexDecode.cpp
→
src
/pdf-merger/ASCIIHexDecode.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/ASCIIHexDecode.h
→
src
/pdf-merger/ASCIIHexDecode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/AbstractBoxElementHandler.h
→
src
/pdf-merger/AbstractBoxElementHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/AnnotsHandler.cpp
→
src
/pdf-merger/AnnotsHandler.cpp
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/AnnotsHandler.h
→
src
/pdf-merger/AnnotsHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/CCITTFaxDecode.h
→
src
/pdf-merger/CCITTFaxDecode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Config.h
→
src
/pdf-merger/Config.h
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/ContentHandler.cpp
→
src
/pdf-merger/ContentHandler.cpp
View file @
7564a8ba
#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
(
"
\n
stream
\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
(
"
\n
stream
\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
;
}
thirdparty/mera
/pdf-merger/ContentHandler.h
→
src
/pdf-merger/ContentHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/CropBoxElementHandler.h
→
src
/pdf-merger/CropBoxElementHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/DCTDecode.h
→
src
/pdf-merger/DCTDecode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Decoder.h
→
src
/pdf-merger/Decoder.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Document.cpp
→
src
/pdf-merger/Document.cpp
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/Document.h
→
src
/pdf-merger/Document.h
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/Exception.h
→
src
/pdf-merger/Exception.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/FileIsAbsentException.h
→
src
/pdf-merger/FileIsAbsentException.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Filter.cpp
→
src
/pdf-merger/Filter.cpp
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/Filter.h
→
src
/pdf-merger/Filter.h
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/FilterPredictor.cpp
→
src
/pdf-merger/FilterPredictor.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/FilterPredictor.h
→
src
/pdf-merger/FilterPredictor.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/FlateDecode.cpp
→
src
/pdf-merger/FlateDecode.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/FlateDecode.h
→
src
/pdf-merger/FlateDecode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/JBIG2Decode.h
→
src
/pdf-merger/JBIG2Decode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/LZWDecode.cpp
→
src
/pdf-merger/LZWDecode.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/LZWDecode.h
→
src
/pdf-merger/LZWDecode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/MediaBoxElementHandler.h
→
src
/pdf-merger/MediaBoxElementHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/MergePageDescription.h
→
src
/pdf-merger/MergePageDescription.h
View file @
7564a8ba
#if !defined MergePageDescription_h
#define MergePageDescription_h
#include "Transformation.h"
#include <map>
#include <string>
namespace
merge_lib
{
struct
MergePageDescription
{
//members:
double
outPageWidth
;
// output page width
double
outPageHeight
;
// output page height
unsigned
int
basePageNumber
;
std
::
string
baseDocumentName
;
TransformationDescription
basePageTransformation
;
unsigned
int
overlayPageNumber
;
TransformationDescription
overlayPageTransformation
;
bool
skipOverlayPage
;
bool
skipBasePage
;
//methods:
//constructor
MergePageDescription
(
double
outputPageWidth
,
double
outputPageHeight
,
unsigned
int
basePageNum
,
const
char
*
baseDocName
,
const
TransformationDescription
&
baseTrans
,
unsigned
int
overlayPageNum
,
const
TransformationDescription
&
overlayTrans
,
bool
omitOverlayPage
=
false
,
bool
omitBasePage
=
false
)
:
outPageWidth
(
outputPageWidth
),
outPageHeight
(
outputPageHeight
),
basePageNumber
(
basePageNum
),
baseDocumentName
(
baseDocName
),
basePageTransformation
(
baseTrans
),
overlayPageNumber
(
overlayPageNum
),
overlayPageTransformation
(
overlayTrans
),
skipOverlayPage
(
omitOverlayPage
),
skipBasePage
(
omitBasePage
)
{
}
MergePageDescription
(
double
outputPageWidth
,
double
outputPageHeight
,
unsigned
int
basePageNum
,
const
char
*
baseDocName
,
const
TransformationDescription
&
baseTrans
)
:
outPageWidth
(
outputPageWidth
),
outPageHeight
(
outputPageHeight
),
basePageNumber
(
basePageNum
),
baseDocumentName
(
baseDocName
),
basePageTransformation
(
baseTrans
),
overlayPageNumber
(
0
),
overlayPageTransformation
(),
skipOverlayPage
(
true
),
skipBasePage
(
false
)
{
}
MergePageDescription
(
const
MergePageDescription
&
copy
)
{
*
this
=
copy
;
}
MergePageDescription
&
operator
=
(
const
MergePageDescription
&
copy
)
{
if
(
this
!=
&
copy
)
{
baseDocumentName
=
copy
.
baseDocumentName
;
basePageNumber
=
copy
.
basePageNumber
;
skipBasePage
=
copy
.
skipBasePage
;
skipOverlayPage
=
copy
.
skipOverlayPage
;
outPageHeight
=
copy
.
outPageHeight
;
outPageWidth
=
copy
.
outPageWidth
;
basePageTransformation
=
copy
.
basePageTransformation
;
overlayPageNumber
=
copy
.
overlayPageNumber
;
overlayPageTransformation
=
copy
.
overlayPageTransformation
;
}
return
*
this
;
}
~
MergePageDescription
()
{
}
};
// array of merge descriptions - allows to merge selected pages
typedef
std
::
vector
<
MergePageDescription
>
MergeDescription
;
}
#endif
#if !defined MergePageDescription_h
#define MergePageDescription_h
#include "Transformation.h"
#include <map>
#include <string>
namespace
merge_lib
{
struct
MergePageDescription
{
//members:
double
outPageWidth
;
// output page width
double
outPageHeight
;
// output page height
unsigned
int
basePageNumber
;
std
::
string
baseDocumentName
;
TransformationDescription
basePageTransformation
;
unsigned
int
overlayPageNumber
;
TransformationDescription
overlayPageTransformation
;
bool
skipOverlayPage
;
bool
skipBasePage
;
//methods:
//constructor
MergePageDescription
(
double
outputPageWidth
,
double
outputPageHeight
,
unsigned
int
basePageNum
,
const
char
*
baseDocName
,
const
TransformationDescription
&
baseTrans
,
unsigned
int
overlayPageNum
,
const
TransformationDescription
&
overlayTrans
,
bool
omitOverlayPage
=
false
,
bool
omitBasePage
=
false
)
:
outPageWidth
(
outputPageWidth
),
outPageHeight
(
outputPageHeight
),
basePageNumber
(
basePageNum
),
baseDocumentName
(
baseDocName
),
basePageTransformation
(
baseTrans
),
overlayPageNumber
(
overlayPageNum
),
overlayPageTransformation
(
overlayTrans
),
skipOverlayPage
(
omitOverlayPage
),
skipBasePage
(
omitBasePage
)
{
}
MergePageDescription
(
double
outputPageWidth
,
double
outputPageHeight
,
unsigned
int
basePageNum
,
const
char
*
baseDocName
,
const
TransformationDescription
&
baseTrans
)
:
outPageWidth
(
outputPageWidth
),
outPageHeight
(
outputPageHeight
),
basePageNumber
(
basePageNum
),
baseDocumentName
(
baseDocName
),
basePageTransformation
(
baseTrans
),
overlayPageNumber
(
0
),
overlayPageTransformation
(),
skipOverlayPage
(
true
),
skipBasePage
(
false
)
{
}
MergePageDescription
(
const
MergePageDescription
&
copy
)
{
*
this
=
copy
;
}
MergePageDescription
&
operator
=
(
const
MergePageDescription
&
copy
)
{
if
(
this
!=
&
copy
)
{
baseDocumentName
=
copy
.
baseDocumentName
;
basePageNumber
=
copy
.
basePageNumber
;
skipBasePage
=
copy
.
skipBasePage
;
skipOverlayPage
=
copy
.
skipOverlayPage
;
outPageHeight
=
copy
.
outPageHeight
;
outPageWidth
=
copy
.
outPageWidth
;
basePageTransformation
=
copy
.
basePageTransformation
;
overlayPageNumber
=
copy
.
overlayPageNumber
;
overlayPageTransformation
=
copy
.
overlayPageTransformation
;
}
return
*
this
;
}
~
MergePageDescription
()
{
}
};
// array of merge descriptions - allows to merge selected pages
typedef
std
::
vector
<
MergePageDescription
>
MergeDescription
;
}
#endif
thirdparty/mera
/pdf-merger/Merger.cpp
→
src
/pdf-merger/Merger.cpp
View file @
7564a8ba
///////////////////////////////////////////////////////////
// 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
);
}
thirdparty/mera
/pdf-merger/Merger.h
→
src
/pdf-merger/Merger.h
View file @
7564a8ba
///////////////////////////////////////////////////////////
// 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 //
thirdparty/mera
/pdf-merger/Object.cpp
→
src
/pdf-merger/Object.cpp
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/Object.h
→
src
/pdf-merger/Object.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/OverlayDocumentParser.cpp
→
src
/pdf-merger/OverlayDocumentParser.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/OverlayDocumentParser.h
→
src
/pdf-merger/OverlayDocumentParser.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Page.cpp
→
src
/pdf-merger/Page.cpp
View file @
7564a8ba
///////////////////////////////////////////////////////////
// Page.cpp
// Implementation of the Class Page
// Created on: 19-���-2009 12:27:56
///////////////////////////////////////////////////////////
#include "Page.h"
#include "Document.h"
#include "ContentHandler.h"
#include "Exception.h"
#include "MediaBoxElementHandler.h"
#include "CropBoxElementHandler.h"
#include "TypeElementHandler.h"
#include "RemoveHimSelfHandler.h"
#include "AnnotsHandler.h"
#include "RotationHandler.h"
#include "FlateDecode.h"
#include "Utils.h"
#include "Rectangle.h"
#include "Filter.h"
#include <iostream>
#include <string.h>
#include "Parser.h"
using
namespace
merge_lib
;
Page
::
Page
(
unsigned
int
pageNumber
)
:
_pageNumber
(
pageNumber
),
_root
(
NULL
),
_rotation
(
0
)
{
}
Page
::~
Page
()
{
}
std
::
string
&
Page
::
getPageContent
()
{
return
_root
->
getObjectContent
();
}
const
Object
::
Children
&
Page
::
getPageRefs
()
{
return
_root
->
getChildren
();
}
void
Page
::
recalculateObjectNumbers
(
unsigned
int
&
newNumber
)
{
_root
->
recalculateObjectNumbers
(
newNumber
);
}
Object
*
Page
::
pageToXObject
(
std
::
vector
<
Object
*>
&
allObjects
,
std
::
vector
<
Object
*>
&
annots
,
bool
isCloneNeeded
)
{
Object
*
xObject
=
(
isCloneNeeded
)
?
_root
->
getClone
(
allObjects
)
:
_root
;
return
_pageToXObject
(
xObject
,
annots
);
}
Object
*
Page
::
_pageToXObject
(
Object
*&
page
,
std
::
vector
<
Object
*>
&
annots
)
{
RemoveHimselfHandler
*
removeParent
=
new
RemoveHimselfHandler
(
page
,
"/Parent"
);
RemoveHimselfHandler
*
removeBleedBox
=
new
RemoveHimselfHandler
(
page
,
"/BleedBox"
);
RemoveHimselfHandler
*
removeTrimBox
=
new
RemoveHimselfHandler
(
page
,
"/TrimBox"
);
RemoveHimselfHandler
*
removeArtBox
=
new
RemoveHimselfHandler
(
page
,
"/ArtBox"
);
RemoveHimselfHandler
*
removeBoxColorInfo
=
new
RemoveHimselfHandler
(
page
,
"/BoxColorInfo"
);
RemoveHimselfHandler
*
removeRotate
=
new
RemoveHimselfHandler
(
page
,
"/Rotate"
);
RemoveHimselfHandler
*
removeThumb
=
new
RemoveHimselfHandler
(
page
,
"/Thumb"
);
RemoveHimselfHandler
*
removeB
=
new
RemoveHimselfHandler
(
page
,
"/B"
);
RemoveHimselfHandler
*
removeDur
=
new
RemoveHimselfHandler
(
page
,
"/Dur"
);
RemoveHimselfHandler
*
removeTrans
=
new
RemoveHimselfHandler
(
page
,
"/Trans"
);
AnnotsHandler
*
removeAnnots
=
new
AnnotsHandler
(
page
,
"/Annots"
,
annots
);
RemoveHimselfHandler
*
removeAA
=
new
RemoveHimselfHandler
(
page
,
"/AA"
);
RemoveHimselfHandler
*
removeID
=
new
RemoveHimselfHandler
(
page
,
"/ID"
);
RemoveHimselfHandler
*
removePZ
=
new
RemoveHimselfHandler
(
page
,
"/PZ"
);
RemoveHimselfHandler
*
removeSeparationInfo
=
new
RemoveHimselfHandler
(
page
,
"/SeparationInfo"
);
RemoveHimselfHandler
*
removeTabs
=
new
RemoveHimselfHandler
(
page
,
"/Tabs"
);
RemoveHimselfHandler
*
removeTemplateInstantiated
=
new
RemoveHimselfHandler
(
page
,
"/TemplateInstantiated"
);
RemoveHimselfHandler
*
removePresSteps
=
new
RemoveHimselfHandler
(
page
,
"/PresSteps"
);
RemoveHimselfHandler
*
removeUserUnit
=
new
RemoveHimselfHandler
(
page
,
"/UserUnit"
);
RemoveHimselfHandler
*
removeVP
=
new
RemoveHimselfHandler
(
page
,
"/VP"
);
ContentHandler
*
contentHandler
=
new
ContentHandler
(
page
,
"/Contents"
);
CropBoxElementHandler
*
cropBoxElementHandler
=
new
CropBoxElementHandler
(
page
);
MediaBoxElementHandler
*
mediaBoxElementHandler
=
new
MediaBoxElementHandler
(
page
);
TypeElementHandler
*
typeElementHandler
=
new
TypeElementHandler
(
page
);
cropBoxElementHandler
->
addNextHandler
(
mediaBoxElementHandler
);
mediaBoxElementHandler
->
addNextHandler
(
removeParent
);
removeParent
->
addNextHandler
(
removeBleedBox
);
removeBleedBox
->
addNextHandler
(
removeTrimBox
);
removeTrimBox
->
addNextHandler
(
removeArtBox
);
removeArtBox
->
addNextHandler
(
removeBoxColorInfo
);
removeBoxColorInfo
->
addNextHandler
(
removeRotate
);
removeRotate
->
addNextHandler
(
removeThumb
);
removeThumb
->
addNextHandler
(
removeB
);
removeB
->
addNextHandler
(
removeDur
);
removeDur
->
addNextHandler
(
removeTrans
);
removeTrans
->
addNextHandler
(
removeAnnots
);
removeAnnots
->
addNextHandler
(
removeAA
);
removeAA
->
addNextHandler
(
removeID
);
removeID
->
addNextHandler
(
removePZ
);
removePZ
->
addNextHandler
(
removeSeparationInfo
);
removeSeparationInfo
->
addNextHandler
(
removeTabs
);
removeTabs
->
addNextHandler
(
removeTemplateInstantiated
);
removeTemplateInstantiated
->
addNextHandler
(
removePresSteps
);
removePresSteps
->
addNextHandler
(
removeUserUnit
);
removeUserUnit
->
addNextHandler
(
removeVP
);
removeVP
->
addNextHandler
(
typeElementHandler
);
typeElementHandler
->
addNextHandler
(
contentHandler
);
cropBoxElementHandler
->
processObjectContent
();
cropBoxElementHandler
->
changeObjectContent
();
delete
cropBoxElementHandler
;
return
page
;
}
std
::
string
_getContentOfContentObject
(
MergePageDescription
&
description
)
{
std
::
string
content
(
"<<
\n
/Length "
);
std
::
string
stream
=
""
;
if
(
!
description
.
skipBasePage
)
{
stream
.
append
(
"1.000000 0 0 1.000000 0 0 cm
\n
"
"q
\n
"
);
stream
.
append
(
description
.
basePageTransformation
.
getCMT
());
stream
.
append
(
"/OriginalPage2 Do
\n
"
"Q
\n
"
);
}
if
(
!
description
.
skipOverlayPage
)
{
stream
.
append
(
"1.000000 0 0 1.000000 0 0 cm
\n
"
"q
\n
"
);
stream
.
append
(
description
.
overlayPageTransformation
.
getCMT
());
stream
.
append
(
"/OriginalPage1 Do
\n
"
"Q
\n
"
);
}
FlateDecode
encoder
;
encoder
.
encode
(
stream
);
content
.
append
(
Utils
::
uIntToStr
(
stream
.
size
()));
content
.
append
(
"
\n
/Filter /FlateDecode
\n
>>
\n
stream
\n
"
);
content
.
append
(
stream
);
content
.
append
(
"endstream
\n
"
);
return
content
;
}
void
_recalculateAnnotsCoordinates
(
Object
*
annotation
,
const
Rectangle
&
basePagesRectangle
,
const
Rectangle
&
outputPagesRectangle
,
const
MergePageDescription
&
description
)
{
std
::
string
annotsRectangleName
(
"/Rect"
);
Object
*
objectWithRectangle
;
unsigned
int
fake
;
annotation
->
findObject
(
annotsRectangleName
,
objectWithRectangle
,
fake
);
std
::
string
annotContent
=
objectWithRectangle
->
getObjectContent
();
Rectangle
annotsRectangle
(
annotsRectangleName
.
c_str
(),
annotContent
);
//we move annotation from base page to output page
//that's way annotation should be scaled before all transformations.
//Annotation's coordinates should be recalculated according to new
//page width and height
annotsRectangle
.
recalculateInternalRectangleCoordinates
(
description
.
basePageTransformation
.
getAnnotsTransformations
());
annotsRectangle
.
updateRectangle
(
annotation
,
" "
);
}
// function updates parent reference of annotation with new page object
static
void
_updateAnnotParentPage
(
Object
*
annotation
,
Object
*
newParentPage
)
{
if
(
annotation
)
{
std
::
string
strP
=
"/P"
;
std
::
string
&
annotContent
=
annotation
->
getObjectContent
();
size_t
startOfP
=
Parser
::
findTokenName
(
annotContent
,
strP
);
if
(
startOfP
==
std
::
string
::
npos
)
{
return
;
}
size_t
endOfP
=
Parser
::
findEndOfElementContent
(
annotContent
,
startOfP
+
strP
.
size
());
// lets find object with reference to parent
std
::
vector
<
Object
*>
children
=
annotation
->
getChildrenByBounds
(
startOfP
,
endOfP
);
if
(
children
.
size
()
==
0
)
{
return
;
}
Object
*
childWithP
=
children
[
0
];
if
(
childWithP
)
{
Object
::
ReferencePositionsInContent
pagePosition
=
annotation
->
removeChild
(
childWithP
);
annotation
->
eraseContent
(
startOfP
,
endOfP
-
startOfP
);
std
::
stringstream
strout
;
strout
<<
"/P "
<<
newParentPage
->
getObjectNumber
()
<<
" "
<<
newParentPage
->
getgenerationNumber
()
<<
" R
\n
"
;
// to compensate posible deviation
for
(
size_t
i
=
strout
.
str
().
size
();
i
<
endOfP
-
startOfP
;
i
++
)
{
strout
<<
" "
;
}
annotation
->
insertToContent
(
startOfP
,
strout
.
str
());
annotation
->
addChild
(
newParentPage
,
pagePosition
);
}
}
}
// function performs adjusting of some color parameters of annotation
// to avoid interference with overlay content
static
void
_updateAnnotFormColor
(
Object
*
annotation
)
{
std
::
string
&
objectContent
=
annotation
->
getObjectContent
();
if
(
objectContent
.
find
(
"/Widget"
)
==
std
::
string
::
npos
)
{
return
;
}
size_t
startOfAP
=
Parser
::
findTokenName
(
objectContent
,
"/AP"
);
if
(
startOfAP
==
std
::
string
::
npos
)
{
return
;
}
size_t
endOfAP
=
objectContent
.
find
(
">>"
,
startOfAP
);
std
::
vector
<
Object
*>
aps
=
annotation
->
getChildrenByBounds
(
startOfAP
,
endOfAP
);
for
(
size_t
i
=
0
;
i
<
aps
.
size
();
++
i
)
{
Object
*
childWithAP
=
aps
[
i
];
if
(
!
childWithAP
->
hasStream
()
)
{
continue
;
}
// first lets obtain and decode stream of Annotation appearrence stream
std
::
string
&
content
=
childWithAP
->
getObjectContent
();
Filter
filter
(
childWithAP
);
std
::
string
decodedStream
;
filter
.
getDecodedStream
(
decodedStream
);
// lets iterate over stream and find operator f and remove it!
size_t
beg
=
0
;
size_t
found
=
0
;
std
::
string
token
;
while
(
Parser
::
getNextWord
(
token
,
decodedStream
,
beg
,
&
found
))
{
if
(
token
==
"f"
||
token
==
"F"
)
{
if
(
found
!=
std
::
string
::
npos
)
{
decodedStream
[
found
]
=
' '
;
}
break
;
}
}
// Then we need to update Filter section (if any)
std
::
string
filterStr
=
"/Filter"
;
size_t
startOfFlate
=
Parser
::
findTokenName
(
content
,
filterStr
);
if
(
startOfFlate
!=
std
::
string
::
npos
)
{
size_t
endOfFlate
=
Parser
::
findEndOfElementContent
(
content
,
startOfFlate
+
filterStr
.
size
());
childWithAP
->
eraseContent
(
startOfFlate
,
endOfFlate
-
startOfFlate
);
//encode and put new stream to object content
childWithAP
->
insertToContent
(
startOfFlate
,
"/Filter /FlateDecode "
);
FlateDecode
flate
;
flate
.
encode
(
decodedStream
);
}
// update the length field
std
::
string
lengthStr
=
"/Length"
;
size_t
startOfLength
=
Parser
::
findTokenName
(
content
,
lengthStr
,
0
);
if
(
startOfLength
!=
std
::
string
::
npos
)
{
size_t
endOfLength
=
Parser
::
findEndOfElementContent
(
content
,
startOfLength
+
lengthStr
.
size
());
childWithAP
->
eraseContent
(
startOfLength
,
endOfLength
-
startOfLength
);
std
::
stringstream
ostr
;
ostr
<<
"/Length "
<<
decodedStream
.
size
()
<<
"
\n
"
;
childWithAP
->
insertToContent
(
startOfLength
,
ostr
.
str
());
// update the stream of object with new content
std
::
string
stream
(
"stream"
);
size_t
leftBoundOfContentStream
=
content
.
find
(
stream
);
if
(
leftBoundOfContentStream
!=
std
::
string
::
npos
)
{
size_t
rightBoundOfContentStream
=
content
.
find
(
"endstream"
,
leftBoundOfContentStream
);
if
(
rightBoundOfContentStream
==
std
::
string
::
npos
)
{
rightBoundOfContentStream
=
content
.
size
()
-
1
;
}
childWithAP
->
eraseContent
(
leftBoundOfContentStream
,
rightBoundOfContentStream
-
leftBoundOfContentStream
);
decodedStream
.
insert
(
0
,
"
\n
stream
\n
"
);
childWithAP
->
insertToContent
(
leftBoundOfContentStream
,
decodedStream
);
childWithAP
->
appendContent
(
"endstream
\n
"
);
childWithAP
->
forgetStreamInFile
();
}
}
}
}
// sometimes page object does not have resources,
// they are inherited from parent object
// this method processes such cases and insert resources from parent to page
// for correct X-Object transformation
static
void
processBasePageResources
(
Object
*
basePage
)
{
if
(
basePage
==
NULL
)
{
return
;
}
std
::
string
resourceToken
=
"/Resources"
;
if
(
Parser
::
findTokenName
(
basePage
->
getObjectContent
(),
resourceToken
)
==
std
::
string
::
npos
)
{
// it seems base page does not have resources, they can be located in parent!
Object
*
resource
=
basePage
->
findPatternInObjOrParents
(
resourceToken
);
if
(
resource
)
{
std
::
string
&
resContStr
=
resource
->
getObjectContent
();
size_t
startOfRes
=
Parser
::
findTokenName
(
resContStr
,
resourceToken
);
if
(
startOfRes
==
std
::
string
::
npos
)
{
// no resources at all
return
;
}
size_t
endOfRes
=
Parser
::
findEndOfElementContent
(
resContStr
,
startOfRes
+
resourceToken
.
size
());
if
(
endOfRes
==
std
::
string
::
npos
)
{
return
;
// broken resources
}
std
::
string
resourceContent
=
resContStr
.
substr
(
startOfRes
,
endOfRes
-
startOfRes
);
size_t
positionToInsert
=
basePage
->
getObjectContent
().
find
(
"<<"
);
if
(
positionToInsert
==
std
::
string
::
npos
)
{
positionToInsert
=
0
;
resourceContent
.
insert
(
0
,
"<<"
);
resourceContent
.
append
(
">>"
);
}
else
{
positionToInsert
+=
strlen
(
"<<"
);
}
// insert obtained resources to base page
basePage
->
insertToContent
(
positionToInsert
,
resourceContent
);
// if resource contains childs, then we need to add reference to them to current object
std
::
vector
<
Object
*>
resChilds
=
resource
->
getChildrenByBounds
(
startOfRes
,
endOfRes
);
std
::
vector
<
Object
*>::
const_iterator
objectIt
(
resChilds
.
begin
());
const
Object
::
Children
&
children
=
resource
->
getChildren
();
for
(;
objectIt
!=
resChilds
.
end
();
objectIt
++
)
{
Object
::
Children
::
const_iterator
childrenIt
=
children
.
find
(
(
*
objectIt
)
->
getObjectNumber
());
if
(
childrenIt
!=
children
.
end
()
)
{
Object
::
ReferencePositionsInContent
refPositionInCont
=
(
*
childrenIt
).
second
.
second
;
Object
::
ReferencePositionsInContent
::
iterator
positionIt
(
refPositionInCont
.
begin
());
Object
::
ReferencePositionsInContent
newPositions
;
for
(
;
positionIt
!=
refPositionInCont
.
end
();
positionIt
++
)
{
newPositions
.
push_back
(
(
*
positionIt
)
-
startOfRes
+
positionToInsert
);
}
basePage
->
addChild
(
(
*
objectIt
),
newPositions
);
}
}
}
}
}
std
::
string
Page
::
_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
)
{
std
::
string
content
(
"<<
\n
/Type /Page
\n
"
);
content
.
append
(
"/Contents "
);
contentPosition
=
content
.
size
();
//object number 1 will be recalculated during serialization
content
.
append
(
"1 0 R
\n
"
);
Rectangle
mediaBox
(
"/MediaBox"
);
mediaBox
.
x2
=
description
.
outPageWidth
;
mediaBox
.
y2
=
description
.
outPageHeight
;
mediaBox
.
appendRectangleToString
(
content
,
" "
);
content
.
append
(
"/Parent "
);
parentPosition
=
content
.
size
();
//object number 1 will be recalculated during serialization
content
.
append
(
"1 0 R
\n
"
);
content
.
append
(
"/Resources <<
\n
"
"/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
\n
"
"/XObject <<
\n
"
);
if
(
!
description
.
skipOverlayPage
)
{
content
.
append
(
"/OriginalPage1 "
);
originalPage1Position
=
content
.
size
();
content
.
append
(
Utils
::
uIntToStr
(
originalPageNumbers
.
first
));
content
.
append
(
" 0 R
\n
"
);
}
if
(
!
description
.
skipBasePage
)
{
content
.
append
(
"/OriginalPage2 "
);
originalPage2Position
=
content
.
size
();
content
.
append
(
Utils
::
uIntToStr
(
originalPageNumbers
.
second
));
content
.
append
(
" "
);
content
.
append
(
Utils
::
uIntToStr
(
basePage
->
getgenerationNumber
()));
content
.
append
(
" R
\n
"
);
}
content
.
append
(
">>
\n
>>
\n
"
);
content
.
append
(
"/Annots [ "
);
if
(
!
description
.
skipBasePage
)
{
Rectangle
basePageRectangle
(
"/BBox"
,
basePage
->
getObjectContent
());
for
(
size_t
i
=
0
;
i
<
annots
.
size
();
++
i
)
{
_updateAnnotFormColor
(
annots
[
i
]);
_recalculateAnnotsCoordinates
(
annots
[
i
],
basePageRectangle
,
mediaBox
,
description
);
Object
::
ReferencePositionsInContent
annotationPosition
;
annotationPosition
.
push_back
(
content
.
size
());
Object
::
ChildAndItPositionInContent
annotAndItPosition
(
annots
[
i
],
annotationPosition
);
annotsPositions
.
push_back
(
annotAndItPosition
);
content
.
append
(
Utils
::
uIntToStr
(
annots
[
i
]
->
getObjectNumber
()));
content
.
append
(
" "
);
content
.
append
(
Utils
::
uIntToStr
(
annots
[
i
]
->
getgenerationNumber
()));
content
.
append
(
" R "
);
}
}
content
.
append
(
"]
\n
>>
\n
"
);
return
content
;
}
void
Page
::
merge
(
Page
*
sourcePage
,
Document
*
parentDocument
,
MergePageDescription
&
description
,
bool
isPageDuplicated
)
{
if
(
sourcePage
==
NULL
)
{
description
.
skipBasePage
=
true
;
}
if
(
!
description
.
skipOverlayPage
)
{
// Lets recalculate final transformation of overlay page
// before it will be places into XObject
Rectangle
mediaBox
(
"/MediaBox"
,
_root
->
getObjectContent
());
description
.
overlayPageTransformation
.
recalculateTranslation
(
mediaBox
.
getWidth
(),
mediaBox
.
getHeight
());
std
::
vector
<
Object
*>
fake
;
_pageToXObject
(
_root
,
fake
);
}
std
::
vector
<
Object
*>
toAllObjects
;
std
::
vector
<
Object
*>
annotations
;
Object
*
sourcePageToXObject
=
0
;
if
(
!
description
.
skipBasePage
)
{
RotationHandler
rotationHandler
(
sourcePage
->
_root
,
"/Rotate"
,
*
this
);
rotationHandler
.
processObjectContent
();
description
.
basePageTransformation
.
addRotation
(
_rotation
);
if
(
sourcePage
->
_root
->
getObjectContent
().
find
(
"/Annots"
)
!=
std
::
string
::
npos
)
{
Object
*
crop
=
sourcePage
->
_root
->
findPatternInObjOrParents
(
"/CropBox"
);
if
(
crop
)
{
// we need to calculate special compensational shifting
// for annotations if cropbox is starting not from 0,0
Rectangle
mediaBox
(
"/CropBox"
,
crop
->
getObjectContent
());
if
(
!
Utils
::
doubleEquals
(
mediaBox
.
x1
,
0
)
||
!
Utils
::
doubleEquals
(
mediaBox
.
y1
,
0
)
)
{
double
shiftX
=
Utils
::
doubleEquals
(
mediaBox
.
x1
,
0
)
?
0
:-
mediaBox
.
x1
;
double
shiftY
=
Utils
::
doubleEquals
(
mediaBox
.
y1
,
0
)
?
0
:-
mediaBox
.
y1
;
Translation
compensation
(
shiftX
,
shiftY
);
description
.
basePageTransformation
.
addAnnotsTransformation
(
compensation
);
}
}
}
processBasePageResources
(
sourcePage
->
_root
);
sourcePageToXObject
=
sourcePage
->
pageToXObject
(
toAllObjects
,
annotations
,
isPageDuplicated
);
Rectangle
mediaBox
(
"/BBox"
,
sourcePageToXObject
->
getObjectContent
());
description
.
basePageTransformation
.
recalculateTranslation
(
mediaBox
.
getWidth
(),
mediaBox
.
getHeight
());
}
Object
*
catalog
=
0
;
unsigned
int
fake
;
if
(
!
parentDocument
->
getDocumentObject
()
->
findObject
(
std
::
string
(
"/Kids"
),
catalog
,
fake
))
{
std
::
string
error
(
"Wrong document "
);
error
.
append
(
"There is no object with Kids field"
);
throw
Exception
(
error
);
}
Object
::
ReferencePositionsInContent
pagePosition
=
catalog
->
removeChild
(
_root
);
//create merged Page
unsigned
int
contentPosition
,
parentPosition
,
originalPage1Position
,
originalPage2Position
;
std
::
pair
<
unsigned
int
,
unsigned
int
>
originalPageNumbers
(
_root
->
getObjectNumber
(),
0
);
if
(
!
description
.
skipBasePage
)
originalPageNumbers
.
second
=
sourcePageToXObject
->
getObjectNumber
();
std
::
vector
<
Object
::
ChildAndItPositionInContent
>
annotsAndItPositions
;
std
::
string
mergedPageContent
=
_getMergedPageContent
(
contentPosition
,
parentPosition
,
originalPage1Position
,
originalPage2Position
,
originalPageNumbers
,
description
,
sourcePageToXObject
,
annotations
,
annotsAndItPositions
);
Object
*
mergedPage
=
new
Object
(
_root
->
getObjectNumber
(),
_root
->
getgenerationNumber
(),
mergedPageContent
);
toAllObjects
.
push_back
(
mergedPage
);
std
::
vector
<
unsigned
int
>
contentPositionVec
,
parentPositionVec
,
originalPage1PositionVec
,
originalPage2PositionVec
;
contentPositionVec
.
push_back
(
contentPosition
);
parentPositionVec
.
push_back
(
parentPosition
);
originalPage1PositionVec
.
push_back
(
originalPage1Position
);
originalPage2PositionVec
.
push_back
(
originalPage2Position
);
Object
*
contentOfMergedPage
=
new
Object
(
1
,
0
,
_getContentOfContentObject
(
description
));
toAllObjects
.
push_back
(
contentOfMergedPage
);
parentDocument
->
addToAllObjects
(
toAllObjects
);
mergedPage
->
addChild
(
contentOfMergedPage
,
contentPositionVec
);
mergedPage
->
addChild
(
catalog
,
parentPositionVec
);
if
(
!
description
.
skipOverlayPage
)
mergedPage
->
addChild
(
_root
,
originalPage1PositionVec
);
if
(
!
description
.
skipBasePage
)
mergedPage
->
addChild
(
sourcePageToXObject
,
originalPage2PositionVec
);
// Annotation parent page should be changed, since we moved old page
// to Xobject
if
(
!
description
.
skipBasePage
)
{
for
(
size_t
i
=
0
;
i
<
annotations
.
size
();
i
++
)
{
_updateAnnotParentPage
(
annotations
[
i
],
mergedPage
);
}
}
for
(
size_t
i
=
0
;
i
<
annotsAndItPositions
.
size
();
++
i
)
{
mergedPage
->
addChild
(
annotsAndItPositions
[
i
].
first
,
annotsAndItPositions
[
i
].
second
);
}
catalog
->
addChild
(
mergedPage
,
pagePosition
);
_root
=
mergedPage
;
}
///////////////////////////////////////////////////////////
// Page.cpp
// Implementation of the Class Page
// Created on: 19-���-2009 12:27:56
///////////////////////////////////////////////////////////
#include "Page.h"
#include "Document.h"
#include "ContentHandler.h"
#include "Exception.h"
#include "MediaBoxElementHandler.h"
#include "CropBoxElementHandler.h"
#include "TypeElementHandler.h"
#include "RemoveHimSelfHandler.h"
#include "AnnotsHandler.h"
#include "RotationHandler.h"
#include "FlateDecode.h"
#include "Utils.h"
#include "Rectangle.h"
#include "Filter.h"
#include <iostream>
#include <string.h>
#include "Parser.h"
using
namespace
merge_lib
;
Page
::
Page
(
unsigned
int
pageNumber
)
:
_pageNumber
(
pageNumber
),
_root
(
NULL
),
_rotation
(
0
)
{
}
Page
::~
Page
()
{
}
std
::
string
&
Page
::
getPageContent
()
{
return
_root
->
getObjectContent
();
}
const
Object
::
Children
&
Page
::
getPageRefs
()
{
return
_root
->
getChildren
();
}
void
Page
::
recalculateObjectNumbers
(
unsigned
int
&
newNumber
)
{
_root
->
recalculateObjectNumbers
(
newNumber
);
}
Object
*
Page
::
pageToXObject
(
std
::
vector
<
Object
*>
&
allObjects
,
std
::
vector
<
Object
*>
&
annots
,
bool
isCloneNeeded
)
{
Object
*
xObject
=
(
isCloneNeeded
)
?
_root
->
getClone
(
allObjects
)
:
_root
;
return
_pageToXObject
(
xObject
,
annots
);
}
Object
*
Page
::
_pageToXObject
(
Object
*&
page
,
std
::
vector
<
Object
*>
&
annots
)
{
RemoveHimselfHandler
*
removeParent
=
new
RemoveHimselfHandler
(
page
,
"/Parent"
);
RemoveHimselfHandler
*
removeBleedBox
=
new
RemoveHimselfHandler
(
page
,
"/BleedBox"
);
RemoveHimselfHandler
*
removeTrimBox
=
new
RemoveHimselfHandler
(
page
,
"/TrimBox"
);
RemoveHimselfHandler
*
removeArtBox
=
new
RemoveHimselfHandler
(
page
,
"/ArtBox"
);
RemoveHimselfHandler
*
removeBoxColorInfo
=
new
RemoveHimselfHandler
(
page
,
"/BoxColorInfo"
);
RemoveHimselfHandler
*
removeRotate
=
new
RemoveHimselfHandler
(
page
,
"/Rotate"
);
RemoveHimselfHandler
*
removeThumb
=
new
RemoveHimselfHandler
(
page
,
"/Thumb"
);
RemoveHimselfHandler
*
removeB
=
new
RemoveHimselfHandler
(
page
,
"/B"
);
RemoveHimselfHandler
*
removeDur
=
new
RemoveHimselfHandler
(
page
,
"/Dur"
);
RemoveHimselfHandler
*
removeTrans
=
new
RemoveHimselfHandler
(
page
,
"/Trans"
);
AnnotsHandler
*
removeAnnots
=
new
AnnotsHandler
(
page
,
"/Annots"
,
annots
);
RemoveHimselfHandler
*
removeAA
=
new
RemoveHimselfHandler
(
page
,
"/AA"
);
RemoveHimselfHandler
*
removeID
=
new
RemoveHimselfHandler
(
page
,
"/ID"
);
RemoveHimselfHandler
*
removePZ
=
new
RemoveHimselfHandler
(
page
,
"/PZ"
);
RemoveHimselfHandler
*
removeSeparationInfo
=
new
RemoveHimselfHandler
(
page
,
"/SeparationInfo"
);
RemoveHimselfHandler
*
removeTabs
=
new
RemoveHimselfHandler
(
page
,
"/Tabs"
);
RemoveHimselfHandler
*
removeTemplateInstantiated
=
new
RemoveHimselfHandler
(
page
,
"/TemplateInstantiated"
);
RemoveHimselfHandler
*
removePresSteps
=
new
RemoveHimselfHandler
(
page
,
"/PresSteps"
);
RemoveHimselfHandler
*
removeUserUnit
=
new
RemoveHimselfHandler
(
page
,
"/UserUnit"
);
RemoveHimselfHandler
*
removeVP
=
new
RemoveHimselfHandler
(
page
,
"/VP"
);
ContentHandler
*
contentHandler
=
new
ContentHandler
(
page
,
"/Contents"
);
CropBoxElementHandler
*
cropBoxElementHandler
=
new
CropBoxElementHandler
(
page
);
MediaBoxElementHandler
*
mediaBoxElementHandler
=
new
MediaBoxElementHandler
(
page
);
TypeElementHandler
*
typeElementHandler
=
new
TypeElementHandler
(
page
);
cropBoxElementHandler
->
addNextHandler
(
mediaBoxElementHandler
);
mediaBoxElementHandler
->
addNextHandler
(
removeParent
);
removeParent
->
addNextHandler
(
removeBleedBox
);
removeBleedBox
->
addNextHandler
(
removeTrimBox
);
removeTrimBox
->
addNextHandler
(
removeArtBox
);
removeArtBox
->
addNextHandler
(
removeBoxColorInfo
);
removeBoxColorInfo
->
addNextHandler
(
removeRotate
);
removeRotate
->
addNextHandler
(
removeThumb
);
removeThumb
->
addNextHandler
(
removeB
);
removeB
->
addNextHandler
(
removeDur
);
removeDur
->
addNextHandler
(
removeTrans
);
removeTrans
->
addNextHandler
(
removeAnnots
);
removeAnnots
->
addNextHandler
(
removeAA
);
removeAA
->
addNextHandler
(
removeID
);
removeID
->
addNextHandler
(
removePZ
);
removePZ
->
addNextHandler
(
removeSeparationInfo
);
removeSeparationInfo
->
addNextHandler
(
removeTabs
);
removeTabs
->
addNextHandler
(
removeTemplateInstantiated
);
removeTemplateInstantiated
->
addNextHandler
(
removePresSteps
);
removePresSteps
->
addNextHandler
(
removeUserUnit
);
removeUserUnit
->
addNextHandler
(
removeVP
);
removeVP
->
addNextHandler
(
typeElementHandler
);
typeElementHandler
->
addNextHandler
(
contentHandler
);
cropBoxElementHandler
->
processObjectContent
();
cropBoxElementHandler
->
changeObjectContent
();
delete
cropBoxElementHandler
;
return
page
;
}
std
::
string
_getContentOfContentObject
(
MergePageDescription
&
description
)
{
std
::
string
content
(
"<<
\n
/Length "
);
std
::
string
stream
=
""
;
if
(
!
description
.
skipBasePage
)
{
stream
.
append
(
"1.000000 0 0 1.000000 0 0 cm
\n
"
"q
\n
"
);
stream
.
append
(
description
.
basePageTransformation
.
getCMT
());
stream
.
append
(
"/OriginalPage2 Do
\n
"
"Q
\n
"
);
}
if
(
!
description
.
skipOverlayPage
)
{
stream
.
append
(
"1.000000 0 0 1.000000 0 0 cm
\n
"
"q
\n
"
);
stream
.
append
(
description
.
overlayPageTransformation
.
getCMT
());
stream
.
append
(
"/OriginalPage1 Do
\n
"
"Q
\n
"
);
}
FlateDecode
encoder
;
encoder
.
encode
(
stream
);
content
.
append
(
Utils
::
uIntToStr
(
stream
.
size
()));
content
.
append
(
"
\n
/Filter /FlateDecode
\n
>>
\n
stream
\n
"
);
content
.
append
(
stream
);
content
.
append
(
"endstream
\n
"
);
return
content
;
}
void
_recalculateAnnotsCoordinates
(
Object
*
annotation
,
const
Rectangle
&
basePagesRectangle
,
const
Rectangle
&
outputPagesRectangle
,
const
MergePageDescription
&
description
)
{
std
::
string
annotsRectangleName
(
"/Rect"
);
Object
*
objectWithRectangle
;
unsigned
int
fake
;
annotation
->
findObject
(
annotsRectangleName
,
objectWithRectangle
,
fake
);
std
::
string
annotContent
=
objectWithRectangle
->
getObjectContent
();
Rectangle
annotsRectangle
(
annotsRectangleName
.
c_str
(),
annotContent
);
//we move annotation from base page to output page
//that's way annotation should be scaled before all transformations.
//Annotation's coordinates should be recalculated according to new
//page width and height
annotsRectangle
.
recalculateInternalRectangleCoordinates
(
description
.
basePageTransformation
.
getAnnotsTransformations
());
annotsRectangle
.
updateRectangle
(
annotation
,
" "
);
}
// function updates parent reference of annotation with new page object
static
void
_updateAnnotParentPage
(
Object
*
annotation
,
Object
*
newParentPage
)
{
if
(
annotation
)
{
std
::
string
strP
=
"/P"
;
std
::
string
&
annotContent
=
annotation
->
getObjectContent
();
size_t
startOfP
=
Parser
::
findTokenName
(
annotContent
,
strP
);
if
(
startOfP
==
std
::
string
::
npos
)
{
return
;
}
size_t
endOfP
=
Parser
::
findEndOfElementContent
(
annotContent
,
startOfP
+
strP
.
size
());
// lets find object with reference to parent
std
::
vector
<
Object
*>
children
=
annotation
->
getChildrenByBounds
(
startOfP
,
endOfP
);
if
(
children
.
size
()
==
0
)
{
return
;
}
Object
*
childWithP
=
children
[
0
];
if
(
childWithP
)
{
Object
::
ReferencePositionsInContent
pagePosition
=
annotation
->
removeChild
(
childWithP
);
annotation
->
eraseContent
(
startOfP
,
endOfP
-
startOfP
);
std
::
stringstream
strout
;
strout
<<
"/P "
<<
newParentPage
->
getObjectNumber
()
<<
" "
<<
newParentPage
->
getgenerationNumber
()
<<
" R
\n
"
;
// to compensate posible deviation
for
(
size_t
i
=
strout
.
str
().
size
();
i
<
endOfP
-
startOfP
;
i
++
)
{
strout
<<
" "
;
}
annotation
->
insertToContent
(
startOfP
,
strout
.
str
());
annotation
->
addChild
(
newParentPage
,
pagePosition
);
}
}
}
// function performs adjusting of some color parameters of annotation
// to avoid interference with overlay content
static
void
_updateAnnotFormColor
(
Object
*
annotation
)
{
std
::
string
&
objectContent
=
annotation
->
getObjectContent
();
if
(
objectContent
.
find
(
"/Widget"
)
==
std
::
string
::
npos
)
{
return
;
}
size_t
startOfAP
=
Parser
::
findTokenName
(
objectContent
,
"/AP"
);
if
(
startOfAP
==
std
::
string
::
npos
)
{
return
;
}
size_t
endOfAP
=
objectContent
.
find
(
">>"
,
startOfAP
);
std
::
vector
<
Object
*>
aps
=
annotation
->
getChildrenByBounds
(
startOfAP
,
endOfAP
);
for
(
size_t
i
=
0
;
i
<
aps
.
size
();
++
i
)
{
Object
*
childWithAP
=
aps
[
i
];
if
(
!
childWithAP
->
hasStream
()
)
{
continue
;
}
// first lets obtain and decode stream of Annotation appearrence stream
std
::
string
&
content
=
childWithAP
->
getObjectContent
();
Filter
filter
(
childWithAP
);
std
::
string
decodedStream
;
filter
.
getDecodedStream
(
decodedStream
);
// lets iterate over stream and find operator f and remove it!
size_t
beg
=
0
;
size_t
found
=
0
;
std
::
string
token
;
while
(
Parser
::
getNextWord
(
token
,
decodedStream
,
beg
,
&
found
))
{
if
(
token
==
"f"
||
token
==
"F"
)
{
if
(
found
!=
std
::
string
::
npos
)
{
decodedStream
[
found
]
=
' '
;
}
break
;
}
}
// Then we need to update Filter section (if any)
std
::
string
filterStr
=
"/Filter"
;
size_t
startOfFlate
=
Parser
::
findTokenName
(
content
,
filterStr
);
if
(
startOfFlate
!=
std
::
string
::
npos
)
{
size_t
endOfFlate
=
Parser
::
findEndOfElementContent
(
content
,
startOfFlate
+
filterStr
.
size
());
childWithAP
->
eraseContent
(
startOfFlate
,
endOfFlate
-
startOfFlate
);
//encode and put new stream to object content
childWithAP
->
insertToContent
(
startOfFlate
,
"/Filter /FlateDecode "
);
FlateDecode
flate
;
flate
.
encode
(
decodedStream
);
}
// update the length field
std
::
string
lengthStr
=
"/Length"
;
size_t
startOfLength
=
Parser
::
findTokenName
(
content
,
lengthStr
,
0
);
if
(
startOfLength
!=
std
::
string
::
npos
)
{
size_t
endOfLength
=
Parser
::
findEndOfElementContent
(
content
,
startOfLength
+
lengthStr
.
size
());
childWithAP
->
eraseContent
(
startOfLength
,
endOfLength
-
startOfLength
);
std
::
stringstream
ostr
;
ostr
<<
"/Length "
<<
decodedStream
.
size
()
<<
"
\n
"
;
childWithAP
->
insertToContent
(
startOfLength
,
ostr
.
str
());
// update the stream of object with new content
std
::
string
stream
(
"stream"
);
size_t
leftBoundOfContentStream
=
content
.
find
(
stream
);
if
(
leftBoundOfContentStream
!=
std
::
string
::
npos
)
{
size_t
rightBoundOfContentStream
=
content
.
find
(
"endstream"
,
leftBoundOfContentStream
);
if
(
rightBoundOfContentStream
==
std
::
string
::
npos
)
{
rightBoundOfContentStream
=
content
.
size
()
-
1
;
}
childWithAP
->
eraseContent
(
leftBoundOfContentStream
,
rightBoundOfContentStream
-
leftBoundOfContentStream
);
decodedStream
.
insert
(
0
,
"
\n
stream
\n
"
);
childWithAP
->
insertToContent
(
leftBoundOfContentStream
,
decodedStream
);
childWithAP
->
appendContent
(
"endstream
\n
"
);
childWithAP
->
forgetStreamInFile
();
}
}
}
}
// sometimes page object does not have resources,
// they are inherited from parent object
// this method processes such cases and insert resources from parent to page
// for correct X-Object transformation
static
void
processBasePageResources
(
Object
*
basePage
)
{
if
(
basePage
==
NULL
)
{
return
;
}
std
::
string
resourceToken
=
"/Resources"
;
if
(
Parser
::
findTokenName
(
basePage
->
getObjectContent
(),
resourceToken
)
==
std
::
string
::
npos
)
{
// it seems base page does not have resources, they can be located in parent!
Object
*
resource
=
basePage
->
findPatternInObjOrParents
(
resourceToken
);
if
(
resource
)
{
std
::
string
&
resContStr
=
resource
->
getObjectContent
();
size_t
startOfRes
=
Parser
::
findTokenName
(
resContStr
,
resourceToken
);
if
(
startOfRes
==
std
::
string
::
npos
)
{
// no resources at all
return
;
}
size_t
endOfRes
=
Parser
::
findEndOfElementContent
(
resContStr
,
startOfRes
+
resourceToken
.
size
());
if
(
endOfRes
==
std
::
string
::
npos
)
{
return
;
// broken resources
}
std
::
string
resourceContent
=
resContStr
.
substr
(
startOfRes
,
endOfRes
-
startOfRes
);
size_t
positionToInsert
=
basePage
->
getObjectContent
().
find
(
"<<"
);
if
(
positionToInsert
==
std
::
string
::
npos
)
{
positionToInsert
=
0
;
resourceContent
.
insert
(
0
,
"<<"
);
resourceContent
.
append
(
">>"
);
}
else
{
positionToInsert
+=
strlen
(
"<<"
);
}
// insert obtained resources to base page
basePage
->
insertToContent
(
positionToInsert
,
resourceContent
);
// if resource contains childs, then we need to add reference to them to current object
std
::
vector
<
Object
*>
resChilds
=
resource
->
getChildrenByBounds
(
startOfRes
,
endOfRes
);
std
::
vector
<
Object
*>::
const_iterator
objectIt
(
resChilds
.
begin
());
const
Object
::
Children
&
children
=
resource
->
getChildren
();
for
(;
objectIt
!=
resChilds
.
end
();
objectIt
++
)
{
Object
::
Children
::
const_iterator
childrenIt
=
children
.
find
(
(
*
objectIt
)
->
getObjectNumber
());
if
(
childrenIt
!=
children
.
end
()
)
{
Object
::
ReferencePositionsInContent
refPositionInCont
=
(
*
childrenIt
).
second
.
second
;
Object
::
ReferencePositionsInContent
::
iterator
positionIt
(
refPositionInCont
.
begin
());
Object
::
ReferencePositionsInContent
newPositions
;
for
(
;
positionIt
!=
refPositionInCont
.
end
();
positionIt
++
)
{
newPositions
.
push_back
(
(
*
positionIt
)
-
startOfRes
+
positionToInsert
);
}
basePage
->
addChild
(
(
*
objectIt
),
newPositions
);
}
}
}
}
}
std
::
string
Page
::
_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
)
{
std
::
string
content
(
"<<
\n
/Type /Page
\n
"
);
content
.
append
(
"/Contents "
);
contentPosition
=
content
.
size
();
//object number 1 will be recalculated during serialization
content
.
append
(
"1 0 R
\n
"
);
Rectangle
mediaBox
(
"/MediaBox"
);
mediaBox
.
x2
=
description
.
outPageWidth
;
mediaBox
.
y2
=
description
.
outPageHeight
;
mediaBox
.
appendRectangleToString
(
content
,
" "
);
content
.
append
(
"/Parent "
);
parentPosition
=
content
.
size
();
//object number 1 will be recalculated during serialization
content
.
append
(
"1 0 R
\n
"
);
content
.
append
(
"/Resources <<
\n
"
"/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
\n
"
"/XObject <<
\n
"
);
if
(
!
description
.
skipOverlayPage
)
{
content
.
append
(
"/OriginalPage1 "
);
originalPage1Position
=
content
.
size
();
content
.
append
(
Utils
::
uIntToStr
(
originalPageNumbers
.
first
));
content
.
append
(
" 0 R
\n
"
);
}
if
(
!
description
.
skipBasePage
)
{
content
.
append
(
"/OriginalPage2 "
);
originalPage2Position
=
content
.
size
();
content
.
append
(
Utils
::
uIntToStr
(
originalPageNumbers
.
second
));
content
.
append
(
" "
);
content
.
append
(
Utils
::
uIntToStr
(
basePage
->
getgenerationNumber
()));
content
.
append
(
" R
\n
"
);
}
content
.
append
(
">>
\n
>>
\n
"
);
content
.
append
(
"/Annots [ "
);
if
(
!
description
.
skipBasePage
)
{
Rectangle
basePageRectangle
(
"/BBox"
,
basePage
->
getObjectContent
());
for
(
size_t
i
=
0
;
i
<
annots
.
size
();
++
i
)
{
_updateAnnotFormColor
(
annots
[
i
]);
_recalculateAnnotsCoordinates
(
annots
[
i
],
basePageRectangle
,
mediaBox
,
description
);
Object
::
ReferencePositionsInContent
annotationPosition
;
annotationPosition
.
push_back
(
content
.
size
());
Object
::
ChildAndItPositionInContent
annotAndItPosition
(
annots
[
i
],
annotationPosition
);
annotsPositions
.
push_back
(
annotAndItPosition
);
content
.
append
(
Utils
::
uIntToStr
(
annots
[
i
]
->
getObjectNumber
()));
content
.
append
(
" "
);
content
.
append
(
Utils
::
uIntToStr
(
annots
[
i
]
->
getgenerationNumber
()));
content
.
append
(
" R "
);
}
}
content
.
append
(
"]
\n
>>
\n
"
);
return
content
;
}
void
Page
::
merge
(
Page
*
sourcePage
,
Document
*
parentDocument
,
MergePageDescription
&
description
,
bool
isPageDuplicated
)
{
if
(
sourcePage
==
NULL
)
{
description
.
skipBasePage
=
true
;
}
if
(
!
description
.
skipOverlayPage
)
{
// Lets recalculate final transformation of overlay page
// before it will be places into XObject
Rectangle
mediaBox
(
"/MediaBox"
,
_root
->
getObjectContent
());
description
.
overlayPageTransformation
.
recalculateTranslation
(
mediaBox
.
getWidth
(),
mediaBox
.
getHeight
());
std
::
vector
<
Object
*>
fake
;
_pageToXObject
(
_root
,
fake
);
}
std
::
vector
<
Object
*>
toAllObjects
;
std
::
vector
<
Object
*>
annotations
;
Object
*
sourcePageToXObject
=
0
;
if
(
!
description
.
skipBasePage
)
{
RotationHandler
rotationHandler
(
sourcePage
->
_root
,
"/Rotate"
,
*
this
);
rotationHandler
.
processObjectContent
();
description
.
basePageTransformation
.
addRotation
(
_rotation
);
if
(
sourcePage
->
_root
->
getObjectContent
().
find
(
"/Annots"
)
!=
std
::
string
::
npos
)
{
Object
*
crop
=
sourcePage
->
_root
->
findPatternInObjOrParents
(
"/CropBox"
);
if
(
crop
)
{
// we need to calculate special compensational shifting
// for annotations if cropbox is starting not from 0,0
Rectangle
mediaBox
(
"/CropBox"
,
crop
->
getObjectContent
());
if
(
!
Utils
::
doubleEquals
(
mediaBox
.
x1
,
0
)
||
!
Utils
::
doubleEquals
(
mediaBox
.
y1
,
0
)
)
{
double
shiftX
=
Utils
::
doubleEquals
(
mediaBox
.
x1
,
0
)
?
0
:-
mediaBox
.
x1
;
double
shiftY
=
Utils
::
doubleEquals
(
mediaBox
.
y1
,
0
)
?
0
:-
mediaBox
.
y1
;
Translation
compensation
(
shiftX
,
shiftY
);
description
.
basePageTransformation
.
addAnnotsTransformation
(
compensation
);
}
}
}
processBasePageResources
(
sourcePage
->
_root
);
sourcePageToXObject
=
sourcePage
->
pageToXObject
(
toAllObjects
,
annotations
,
isPageDuplicated
);
Rectangle
mediaBox
(
"/BBox"
,
sourcePageToXObject
->
getObjectContent
());
description
.
basePageTransformation
.
recalculateTranslation
(
mediaBox
.
getWidth
(),
mediaBox
.
getHeight
());
}
Object
*
catalog
=
0
;
unsigned
int
fake
;
if
(
!
parentDocument
->
getDocumentObject
()
->
findObject
(
std
::
string
(
"/Kids"
),
catalog
,
fake
))
{
std
::
string
error
(
"Wrong document "
);
error
.
append
(
"There is no object with Kids field"
);
throw
Exception
(
error
);
}
Object
::
ReferencePositionsInContent
pagePosition
=
catalog
->
removeChild
(
_root
);
//create merged Page
unsigned
int
contentPosition
,
parentPosition
,
originalPage1Position
,
originalPage2Position
;
std
::
pair
<
unsigned
int
,
unsigned
int
>
originalPageNumbers
(
_root
->
getObjectNumber
(),
0
);
if
(
!
description
.
skipBasePage
)
originalPageNumbers
.
second
=
sourcePageToXObject
->
getObjectNumber
();
std
::
vector
<
Object
::
ChildAndItPositionInContent
>
annotsAndItPositions
;
std
::
string
mergedPageContent
=
_getMergedPageContent
(
contentPosition
,
parentPosition
,
originalPage1Position
,
originalPage2Position
,
originalPageNumbers
,
description
,
sourcePageToXObject
,
annotations
,
annotsAndItPositions
);
Object
*
mergedPage
=
new
Object
(
_root
->
getObjectNumber
(),
_root
->
getgenerationNumber
(),
mergedPageContent
);
toAllObjects
.
push_back
(
mergedPage
);
std
::
vector
<
unsigned
int
>
contentPositionVec
,
parentPositionVec
,
originalPage1PositionVec
,
originalPage2PositionVec
;
contentPositionVec
.
push_back
(
contentPosition
);
parentPositionVec
.
push_back
(
parentPosition
);
originalPage1PositionVec
.
push_back
(
originalPage1Position
);
originalPage2PositionVec
.
push_back
(
originalPage2Position
);
Object
*
contentOfMergedPage
=
new
Object
(
1
,
0
,
_getContentOfContentObject
(
description
));
toAllObjects
.
push_back
(
contentOfMergedPage
);
parentDocument
->
addToAllObjects
(
toAllObjects
);
mergedPage
->
addChild
(
contentOfMergedPage
,
contentPositionVec
);
mergedPage
->
addChild
(
catalog
,
parentPositionVec
);
if
(
!
description
.
skipOverlayPage
)
mergedPage
->
addChild
(
_root
,
originalPage1PositionVec
);
if
(
!
description
.
skipBasePage
)
mergedPage
->
addChild
(
sourcePageToXObject
,
originalPage2PositionVec
);
// Annotation parent page should be changed, since we moved old page
// to Xobject
if
(
!
description
.
skipBasePage
)
{
for
(
size_t
i
=
0
;
i
<
annotations
.
size
();
i
++
)
{
_updateAnnotParentPage
(
annotations
[
i
],
mergedPage
);
}
}
for
(
size_t
i
=
0
;
i
<
annotsAndItPositions
.
size
();
++
i
)
{
mergedPage
->
addChild
(
annotsAndItPositions
[
i
].
first
,
annotsAndItPositions
[
i
].
second
);
}
catalog
->
addChild
(
mergedPage
,
pagePosition
);
_root
=
mergedPage
;
}
thirdparty/mera
/pdf-merger/Page.h
→
src
/pdf-merger/Page.h
View file @
7564a8ba
///////////////////////////////////////////////////////////
// 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
thirdparty/mera
/pdf-merger/PageElementHandler.cpp
→
src
/pdf-merger/PageElementHandler.cpp
View file @
7564a8ba
#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
(
">>"
);
}
thirdparty/mera
/pdf-merger/PageElementHandler.h
→
src
/pdf-merger/PageElementHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/PageParser.h
→
src
/pdf-merger/PageParser.h
View file @
7564a8ba
///////////////////////////////////////////////////////////
// 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_)
thirdparty/mera
/pdf-merger/Parser.cpp
→
src
/pdf-merger/Parser.cpp
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/Parser.h
→
src
/pdf-merger/Parser.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Rectangle.cpp
→
src
/pdf-merger/Rectangle.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/Rectangle.h
→
src
/pdf-merger/Rectangle.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/RemoveHimSelfHandler.h
→
src
/pdf-merger/RemoveHimSelfHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/RemoveHimselfHandler.cpp
→
src
/pdf-merger/RemoveHimselfHandler.cpp
View file @
7564a8ba
#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
);
}
thirdparty/mera
/pdf-merger/RotationHandler.h
→
src
/pdf-merger/RotationHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/RunLengthDecode.cpp
→
src
/pdf-merger/RunLengthDecode.cpp
View file @
7564a8ba
#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
;
}
thirdparty/mera
/pdf-merger/RunLengthDecode.h
→
src
/pdf-merger/RunLengthDecode.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Transformation.h
→
src
/pdf-merger/Transformation.h
View file @
7564a8ba
/*
The file defines some classes for transformation of PDF content stream.
*/
#ifndef TRANSFORMATION_H
#define TRANSFORMATION_H
#include <sstream>
#include <string>
#include <math.h>
#include <vector>
#include <iostream>
#include "Utils.h"
namespace
merge_lib
{
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
class
TransformationMatrix
{
public
:
TransformationMatrix
(
double
a
=
1
,
double
b
=
0
,
double
c
=
0
,
double
d
=
1
,
double
e
=
0
,
double
f
=
0
)
:
_a
(
a
),
_b
(
b
),
_c
(
c
),
_d
(
d
),
_e
(
e
),
_f
(
f
)
{}
TransformationMatrix
(
const
TransformationMatrix
&
copy
)
{
setParameters
(
copy
.
_a
,
copy
.
_b
,
copy
.
_c
,
copy
.
_d
,
copy
.
_e
,
copy
.
_f
);
}
void
setParameters
(
double
a
,
double
b
,
double
c
,
double
d
,
double
e
,
double
f
)
{
_a
=
Utils
::
normalizeValue
(
a
);
_b
=
Utils
::
normalizeValue
(
b
);
_c
=
Utils
::
normalizeValue
(
c
);
_d
=
Utils
::
normalizeValue
(
d
);
_e
=
Utils
::
normalizeValue
(
e
);
_f
=
Utils
::
normalizeValue
(
f
);
}
void
add
(
const
TransformationMatrix
&
tm
)
{
double
newA
=
_a
*
tm
.
_a
+
_b
*
tm
.
_c
;
double
newB
=
_a
*
tm
.
_b
+
_b
*
tm
.
_d
;
double
newC
=
_c
*
tm
.
_a
+
_d
*
tm
.
_c
;
double
newD
=
_c
*
tm
.
_b
+
_d
*
tm
.
_d
;
double
newE
=
_e
*
tm
.
_a
+
_f
*
tm
.
_c
+
tm
.
_e
;
double
newF
=
_e
*
tm
.
_b
+
_f
*
tm
.
_d
+
tm
.
_f
;
// we need to round the values to avoid not-needed transformation
// since 1.e-17 is not 0 from PDF point of view, while such double
// value really means 0.
_a
=
Utils
::
normalizeValue
(
newA
);
_b
=
Utils
::
normalizeValue
(
newB
);
_c
=
Utils
::
normalizeValue
(
newC
);
_d
=
Utils
::
normalizeValue
(
newD
);
_e
=
Utils
::
normalizeValue
(
newE
);
_f
=
Utils
::
normalizeValue
(
newF
);
}
std
::
string
getValue
()
{
std
::
ostringstream
value
;
value
<<
"[ "
<<
_a
<<
" "
<<
_b
<<
" "
<<
_c
<<
" "
<<
_d
<<
" "
<<
_e
<<
" "
<<
_f
<<
" ]
\n
"
;
return
value
.
str
();
}
std
::
string
getCMT
()
{
std
::
ostringstream
buf
;
buf
<<
std
::
fixed
<<
_a
<<
" "
<<
_b
<<
" "
<<
_c
<<
" "
<<
_d
<<
" "
<<
_e
<<
" "
<<
_f
<<
" cm
\n
"
;
return
buf
.
str
();
}
void
recalculateCoordinates
(
double
&
x
,
double
&
y
)
{
double
inputX
=
x
;
double
inputY
=
y
;
x
=
_a
*
inputX
+
_c
*
inputY
+
_e
;
y
=
_b
*
inputX
+
_d
*
inputY
+
_f
;
}
private
:
double
_a
,
_b
,
_c
,
_d
,
_e
,
_f
;
};
// base class of transformation CMT
class
Transformation
{
public
:
Transformation
()
:
_tm
(){};
virtual
Transformation
*
getClone
()
const
=
0
;
std
::
string
getCMT
()
{
return
_tm
.
getCMT
();
}
virtual
~
Transformation
()
{};
const
TransformationMatrix
&
getMatrix
()
{
return
_tm
;
}
void
addMatrix
(
const
TransformationMatrix
&
tm
)
{
_tm
.
add
(
tm
);
}
protected
:
TransformationMatrix
_tm
;
};
// rotation CMT
class
Rotation
:
public
Transformation
{
public
:
Rotation
(
double
angle
)
:
Transformation
(),
_angle
(
angle
)
{
double
cosValue
=
cos
(
_angle
*
(
M_PI
/
180
));
double
sinValue
=
sin
(
_angle
*
(
M_PI
/
180
));
_tm
.
setParameters
(
cosValue
,
sinValue
,
-
sinValue
,
cosValue
,
0
,
0
);
};
virtual
~
Rotation
(){};
virtual
Transformation
*
getClone
()
const
{
return
new
Rotation
(
_angle
);
}
protected
:
double
_angle
;
// number of degrees to rotate
};
// translation CMT
class
Translation
:
public
Transformation
{
public
:
Translation
(
double
x
,
double
y
)
:
Transformation
(),
_x
(
x
),
_y
(
y
)
{
_tm
.
setParameters
(
1
,
0
,
0
,
1
,
_x
,
_y
);
};
virtual
~
Translation
(){};
virtual
Transformation
*
getClone
()
const
{
return
new
Translation
(
_x
,
_y
);
}
protected
:
double
_x
;
double
_y
;
};
// scaling CMT
class
Scaling
:
public
Transformation
{
public
:
Scaling
(
double
x
)
:
Transformation
(),
_x
(
x
)
{
_tm
.
setParameters
(
_x
,
0
,
0
,
_x
,
0
,
0
);
};
virtual
Transformation
*
getClone
()
const
{
return
new
Scaling
(
_x
);
}
protected
:
double
_x
;
// the value to multiply the content
};
// transformation can consist of one or several
// operations like rotation, scaling, translation
typedef
std
::
vector
<
Transformation
*>
PageTransformations
;
// This is interface class for setting transformation parameters
//
class
TransformationDescription
{
public
:
TransformationDescription
(
double
x
=
0
,
// leftBottomX coordinate
double
y
=
0
,
// leftBottomY coordinate
double
scale
=
1
,
// scale (by default = 1 = NONE
int
angel
=
0
)
:
// rotation (0,90,180,270)
_x
(
x
),
_y
(
y
),
_scale
(
scale
),
_angel
(
angel
)
{
if
(
_angel
)
{
_transforms
.
push_back
(
new
Rotation
(
_angel
));
}
if
(
!
Utils
::
doubleEquals
(
_scale
,
1
)
&&
!
Utils
::
doubleEquals
(
_scale
,
0
)
)
{
_transforms
.
push_back
(
new
Scaling
(
_scale
));
}
}
virtual
~
TransformationDescription
()
{
for
(
size_t
i
=
0
;
i
<
_annotsTransforms
.
size
();
i
++
)
{
if
(
_annotsTransforms
[
i
]
)
{
delete
_annotsTransforms
[
i
];
_annotsTransforms
[
i
]
=
0
;
}
_annotsTransforms
.
clear
();
}
for
(
size_t
i
=
0
;
i
<
_transforms
.
size
();
i
++
)
{
if
(
_transforms
[
i
]
)
{
delete
_transforms
[
i
];
_transforms
[
i
]
=
0
;
}
}
_transforms
.
clear
();
}
void
addRotation
(
int
rotation
)
{
if
(
rotation
)
{
_angel
=
(
_angel
-
rotation
)
%
360
;
// /Rotation rotate the object, while _angel rotate the coordinate system
// where object is located, that's why
// we should compensate that
_transforms
.
push_back
(
new
Rotation
(
360
-
rotation
));
}
}
const
PageTransformations
&
getTransformations
()
const
{
return
_transforms
;
}
const
PageTransformations
getAnnotsTransformations
()
const
{
PageTransformations
trans
;
trans
=
_transforms
;
for
(
size_t
i
=
0
;
i
<
_annotsTransforms
.
size
();
++
i
)
{
trans
.
push_back
(
_annotsTransforms
[
i
]);
}
return
trans
;
}
void
addAnnotsTransformation
(
Transformation
&
trans
)
{
_annotsTransforms
.
push_back
(
trans
.
getClone
());
}
// method recalculates the final translation in order to put
// object into needed x,y coordinates.
// Page is located from position 0,0
void
recalculateTranslation
(
double
width
,
double
height
)
{
double
dx1
=
0
;
double
dy1
=
0
;
double
scaling
=
(
Utils
::
doubleEquals
(
_scale
,
0
))
?
1
:
_scale
;
switch
(
_angel
)
{
case
0
:
dx1
=
_x
/
scaling
;
dy1
=
_y
/
scaling
;
break
;
case
-
270
:
case
90
:
dx1
=
_y
/
scaling
;
dy1
=
-
_x
/
scaling
-
height
;
break
;
case
180
:
case
-
180
:
dx1
=
-
_x
/
scaling
-
width
;
dy1
=
-
_y
/
scaling
-
height
;
break
;
case
270
:
case
-
90
:
dx1
=
-
_y
/
scaling
-
width
;
dy1
=
_x
/
scaling
;
break
;
default
:
std
::
cerr
<<
"Unsupported rotation parameter"
<<
_angel
<<
std
::
endl
;
break
;
}
//std::cerr<< "dx1 = "<<dx1<<"dy1 = "<<dy1<<std::endl;
if
(
!
(
Utils
::
doubleEquals
(
dx1
,
0
)
&&
Utils
::
doubleEquals
(
dy1
,
0
))
)
{
// This translation is needed to put transformed content into
// desired coordinates
_transforms
.
push_back
(
new
Translation
(
dx1
,
dy1
));
}
}
TransformationDescription
(
const
TransformationDescription
&
copy
)
{
*
this
=
copy
;
}
TransformationDescription
&
operator
=
(
const
TransformationDescription
&
copy
)
{
if
(
this
!=
&
copy
)
{
for
(
size_t
i
=
0
;
i
<
copy
.
_annotsTransforms
.
size
();
i
++
)
{
_annotsTransforms
.
push_back
(
copy
.
_annotsTransforms
[
i
]
->
getClone
());
}
for
(
size_t
i
=
0
;
i
<
copy
.
_transforms
.
size
();
++
i
)
{
_transforms
.
push_back
(
copy
.
_transforms
[
i
]
->
getClone
());
}
_x
=
copy
.
_x
;
_y
=
copy
.
_y
;
_scale
=
copy
.
_scale
;
_angel
=
copy
.
_angel
;
}
return
*
this
;
}
std
::
string
getCMT
()
{
std
::
stringstream
content
;
for
(
size_t
i
=
0
;
i
<
_transforms
.
size
();
i
++
)
{
content
<<
_transforms
[
i
]
->
getCMT
();
}
return
content
.
str
();
}
private
:
double
_x
;
double
_y
;
double
_scale
;
int
_angel
;
PageTransformations
_transforms
;
PageTransformations
_annotsTransforms
;
};
}
#endif
/*
The file defines some classes for transformation of PDF content stream.
*/
#ifndef TRANSFORMATION_H
#define TRANSFORMATION_H
#include <sstream>
#include <string>
#include <math.h>
#include <vector>
#include <iostream>
#include "Utils.h"
namespace
merge_lib
{
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
class
TransformationMatrix
{
public
:
TransformationMatrix
(
double
a
=
1
,
double
b
=
0
,
double
c
=
0
,
double
d
=
1
,
double
e
=
0
,
double
f
=
0
)
:
_a
(
a
),
_b
(
b
),
_c
(
c
),
_d
(
d
),
_e
(
e
),
_f
(
f
)
{}
TransformationMatrix
(
const
TransformationMatrix
&
copy
)
{
setParameters
(
copy
.
_a
,
copy
.
_b
,
copy
.
_c
,
copy
.
_d
,
copy
.
_e
,
copy
.
_f
);
}
void
setParameters
(
double
a
,
double
b
,
double
c
,
double
d
,
double
e
,
double
f
)
{
_a
=
Utils
::
normalizeValue
(
a
);
_b
=
Utils
::
normalizeValue
(
b
);
_c
=
Utils
::
normalizeValue
(
c
);
_d
=
Utils
::
normalizeValue
(
d
);
_e
=
Utils
::
normalizeValue
(
e
);
_f
=
Utils
::
normalizeValue
(
f
);
}
void
add
(
const
TransformationMatrix
&
tm
)
{
double
newA
=
_a
*
tm
.
_a
+
_b
*
tm
.
_c
;
double
newB
=
_a
*
tm
.
_b
+
_b
*
tm
.
_d
;
double
newC
=
_c
*
tm
.
_a
+
_d
*
tm
.
_c
;
double
newD
=
_c
*
tm
.
_b
+
_d
*
tm
.
_d
;
double
newE
=
_e
*
tm
.
_a
+
_f
*
tm
.
_c
+
tm
.
_e
;
double
newF
=
_e
*
tm
.
_b
+
_f
*
tm
.
_d
+
tm
.
_f
;
// we need to round the values to avoid not-needed transformation
// since 1.e-17 is not 0 from PDF point of view, while such double
// value really means 0.
_a
=
Utils
::
normalizeValue
(
newA
);
_b
=
Utils
::
normalizeValue
(
newB
);
_c
=
Utils
::
normalizeValue
(
newC
);
_d
=
Utils
::
normalizeValue
(
newD
);
_e
=
Utils
::
normalizeValue
(
newE
);
_f
=
Utils
::
normalizeValue
(
newF
);
}
std
::
string
getValue
()
{
std
::
ostringstream
value
;
value
<<
"[ "
<<
_a
<<
" "
<<
_b
<<
" "
<<
_c
<<
" "
<<
_d
<<
" "
<<
_e
<<
" "
<<
_f
<<
" ]
\n
"
;
return
value
.
str
();
}
std
::
string
getCMT
()
{
std
::
ostringstream
buf
;
buf
<<
std
::
fixed
<<
_a
<<
" "
<<
_b
<<
" "
<<
_c
<<
" "
<<
_d
<<
" "
<<
_e
<<
" "
<<
_f
<<
" cm
\n
"
;
return
buf
.
str
();
}
void
recalculateCoordinates
(
double
&
x
,
double
&
y
)
{
double
inputX
=
x
;
double
inputY
=
y
;
x
=
_a
*
inputX
+
_c
*
inputY
+
_e
;
y
=
_b
*
inputX
+
_d
*
inputY
+
_f
;
}
private
:
double
_a
,
_b
,
_c
,
_d
,
_e
,
_f
;
};
// base class of transformation CMT
class
Transformation
{
public
:
Transformation
()
:
_tm
(){};
virtual
Transformation
*
getClone
()
const
=
0
;
std
::
string
getCMT
()
{
return
_tm
.
getCMT
();
}
virtual
~
Transformation
()
{};
const
TransformationMatrix
&
getMatrix
()
{
return
_tm
;
}
void
addMatrix
(
const
TransformationMatrix
&
tm
)
{
_tm
.
add
(
tm
);
}
protected
:
TransformationMatrix
_tm
;
};
// rotation CMT
class
Rotation
:
public
Transformation
{
public
:
Rotation
(
double
angle
)
:
Transformation
(),
_angle
(
angle
)
{
double
cosValue
=
cos
(
_angle
*
(
M_PI
/
180
));
double
sinValue
=
sin
(
_angle
*
(
M_PI
/
180
));
_tm
.
setParameters
(
cosValue
,
sinValue
,
-
sinValue
,
cosValue
,
0
,
0
);
};
virtual
~
Rotation
(){};
virtual
Transformation
*
getClone
()
const
{
return
new
Rotation
(
_angle
);
}
protected
:
double
_angle
;
// number of degrees to rotate
};
// translation CMT
class
Translation
:
public
Transformation
{
public
:
Translation
(
double
x
,
double
y
)
:
Transformation
(),
_x
(
x
),
_y
(
y
)
{
_tm
.
setParameters
(
1
,
0
,
0
,
1
,
_x
,
_y
);
};
virtual
~
Translation
(){};
virtual
Transformation
*
getClone
()
const
{
return
new
Translation
(
_x
,
_y
);
}
protected
:
double
_x
;
double
_y
;
};
// scaling CMT
class
Scaling
:
public
Transformation
{
public
:
Scaling
(
double
x
)
:
Transformation
(),
_x
(
x
)
{
_tm
.
setParameters
(
_x
,
0
,
0
,
_x
,
0
,
0
);
};
virtual
Transformation
*
getClone
()
const
{
return
new
Scaling
(
_x
);
}
protected
:
double
_x
;
// the value to multiply the content
};
// transformation can consist of one or several
// operations like rotation, scaling, translation
typedef
std
::
vector
<
Transformation
*>
PageTransformations
;
// This is interface class for setting transformation parameters
//
class
TransformationDescription
{
public
:
TransformationDescription
(
double
x
=
0
,
// leftBottomX coordinate
double
y
=
0
,
// leftBottomY coordinate
double
scale
=
1
,
// scale (by default = 1 = NONE
int
angel
=
0
)
:
// rotation (0,90,180,270)
_x
(
x
),
_y
(
y
),
_scale
(
scale
),
_angel
(
angel
)
{
if
(
_angel
)
{
_transforms
.
push_back
(
new
Rotation
(
_angel
));
}
if
(
!
Utils
::
doubleEquals
(
_scale
,
1
)
&&
!
Utils
::
doubleEquals
(
_scale
,
0
)
)
{
_transforms
.
push_back
(
new
Scaling
(
_scale
));
}
}
virtual
~
TransformationDescription
()
{
for
(
size_t
i
=
0
;
i
<
_annotsTransforms
.
size
();
i
++
)
{
if
(
_annotsTransforms
[
i
]
)
{
delete
_annotsTransforms
[
i
];
_annotsTransforms
[
i
]
=
0
;
}
_annotsTransforms
.
clear
();
}
for
(
size_t
i
=
0
;
i
<
_transforms
.
size
();
i
++
)
{
if
(
_transforms
[
i
]
)
{
delete
_transforms
[
i
];
_transforms
[
i
]
=
0
;
}
}
_transforms
.
clear
();
}
void
addRotation
(
int
rotation
)
{
if
(
rotation
)
{
_angel
=
(
_angel
-
rotation
)
%
360
;
// /Rotation rotate the object, while _angel rotate the coordinate system
// where object is located, that's why
// we should compensate that
_transforms
.
push_back
(
new
Rotation
(
360
-
rotation
));
}
}
const
PageTransformations
&
getTransformations
()
const
{
return
_transforms
;
}
const
PageTransformations
getAnnotsTransformations
()
const
{
PageTransformations
trans
;
trans
=
_transforms
;
for
(
size_t
i
=
0
;
i
<
_annotsTransforms
.
size
();
++
i
)
{
trans
.
push_back
(
_annotsTransforms
[
i
]);
}
return
trans
;
}
void
addAnnotsTransformation
(
Transformation
&
trans
)
{
_annotsTransforms
.
push_back
(
trans
.
getClone
());
}
// method recalculates the final translation in order to put
// object into needed x,y coordinates.
// Page is located from position 0,0
void
recalculateTranslation
(
double
width
,
double
height
)
{
double
dx1
=
0
;
double
dy1
=
0
;
double
scaling
=
(
Utils
::
doubleEquals
(
_scale
,
0
))
?
1
:
_scale
;
switch
(
_angel
)
{
case
0
:
dx1
=
_x
/
scaling
;
dy1
=
_y
/
scaling
;
break
;
case
-
270
:
case
90
:
dx1
=
_y
/
scaling
;
dy1
=
-
_x
/
scaling
-
height
;
break
;
case
180
:
case
-
180
:
dx1
=
-
_x
/
scaling
-
width
;
dy1
=
-
_y
/
scaling
-
height
;
break
;
case
270
:
case
-
90
:
dx1
=
-
_y
/
scaling
-
width
;
dy1
=
_x
/
scaling
;
break
;
default
:
std
::
cerr
<<
"Unsupported rotation parameter"
<<
_angel
<<
std
::
endl
;
break
;
}
//std::cerr<< "dx1 = "<<dx1<<"dy1 = "<<dy1<<std::endl;
if
(
!
(
Utils
::
doubleEquals
(
dx1
,
0
)
&&
Utils
::
doubleEquals
(
dy1
,
0
))
)
{
// This translation is needed to put transformed content into
// desired coordinates
_transforms
.
push_back
(
new
Translation
(
dx1
,
dy1
));
}
}
TransformationDescription
(
const
TransformationDescription
&
copy
)
{
*
this
=
copy
;
}
TransformationDescription
&
operator
=
(
const
TransformationDescription
&
copy
)
{
if
(
this
!=
&
copy
)
{
for
(
size_t
i
=
0
;
i
<
copy
.
_annotsTransforms
.
size
();
i
++
)
{
_annotsTransforms
.
push_back
(
copy
.
_annotsTransforms
[
i
]
->
getClone
());
}
for
(
size_t
i
=
0
;
i
<
copy
.
_transforms
.
size
();
++
i
)
{
_transforms
.
push_back
(
copy
.
_transforms
[
i
]
->
getClone
());
}
_x
=
copy
.
_x
;
_y
=
copy
.
_y
;
_scale
=
copy
.
_scale
;
_angel
=
copy
.
_angel
;
}
return
*
this
;
}
std
::
string
getCMT
()
{
std
::
stringstream
content
;
for
(
size_t
i
=
0
;
i
<
_transforms
.
size
();
i
++
)
{
content
<<
_transforms
[
i
]
->
getCMT
();
}
return
content
.
str
();
}
private
:
double
_x
;
double
_y
;
double
_scale
;
int
_angel
;
PageTransformations
_transforms
;
PageTransformations
_annotsTransforms
;
};
}
#endif
thirdparty/mera
/pdf-merger/TypeElementHandler.h
→
src
/pdf-merger/TypeElementHandler.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Utils.cpp
→
src
/pdf-merger/Utils.cpp
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/Utils.h
→
src
/pdf-merger/Utils.h
View file @
7564a8ba
#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
thirdparty/mera
/pdf-merger/doc/PDF Merge Library Description.doc
→
src
/pdf-merger/doc/PDF Merge Library Description.doc
View file @
7564a8ba
File moved
thirdparty/mera
/pdf-merger/pdfMerger.pri
→
src
/pdf-merger/pdfMerger.pri
View file @
7564a8ba
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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment