Skip to content

Commit 0614e3d

Browse files
authored
First PDF parsing (#345)
1 parent efad56a commit 0614e3d

32 files changed

Lines changed: 2360 additions & 14 deletions

CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ add_library(odr
146146
"src/odr/internal/ooxml/ooxml_meta.cpp"
147147
"src/odr/internal/ooxml/ooxml_util.cpp"
148148

149+
"src/odr/internal/pdf/pdf_document.cpp"
150+
"src/odr/internal/pdf/pdf_document_element.cpp"
151+
"src/odr/internal/pdf/pdf_document_parser.cpp"
152+
"src/odr/internal/pdf/pdf_object.cpp"
153+
"src/odr/internal/pdf/pdf_file_parser.cpp"
154+
"src/odr/internal/pdf/pdf_graphics_operator.cpp"
155+
"src/odr/internal/pdf/pdf_graphics_operator_parser.cpp"
156+
"src/odr/internal/pdf/pdf_graphics_state.cpp"
157+
"src/odr/internal/pdf/pdf_object.cpp"
158+
"src/odr/internal/pdf/pdf_object_parser.cpp"
159+
149160
"src/odr/internal/svm/svm_file.cpp"
150161
"src/odr/internal/svm/svm_format.cpp"
151162
"src/odr/internal/svm/svm_to_svg.cpp"

src/odr/internal/crypto/crypto_util.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <cryptopp/pwdbased.h>
1212
#include <cryptopp/sha.h>
1313
#include <cryptopp/zinflate.h>
14+
#include <cryptopp/zlib.h>
1415

1516
namespace odr::internal::crypto {
1617

@@ -146,4 +147,12 @@ std::size_t util::padding(const std::string &input) {
146147
return inflator.GetPadding();
147148
}
148149

150+
std::string util::zlib_inflate(const std::string &input) {
151+
std::string result;
152+
CryptoPP::ZlibDecompressor inflator(new CryptoPP::StringSink(result));
153+
inflator.Put(reinterpret_cast<const byte *>(input.data()), input.size());
154+
inflator.MessageEnd();
155+
return result;
156+
}
157+
149158
} // namespace odr::internal::crypto

src/odr/internal/crypto/crypto_util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ std::string decrypt_Blowfish(const std::string &key, const std::string &iv,
2929
std::string inflate(const std::string &input);
3030
std::size_t padding(const std::string &input);
3131

32+
std::string zlib_inflate(const std::string &input);
33+
3234
} // namespace util
3335

3436
} // namespace odr::internal::crypto

src/odr/internal/html/text_file.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Html html::translate_text_file(const TextFile &text_file,
5656
out.write_element_begin("td");
5757

5858
std::ostringstream ss_out;
59-
util::stream::getline(*in, ss_out);
59+
util::stream::pipe_line(*in, ss_out);
6060
out.out() << escape_text(ss_out.str());
6161

6262
out.write_element_end("td");

src/odr/internal/pdf/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# PDF
2+
3+
This is in a very early state and not tested thoroughly.
4+
5+
It includes:
6+
- Reading PDF data types from stream.
7+
- Opening a PDF file and extracting file objects.
8+
- Everything is done via streams but some parts require seeking in the file.
9+
- **What is missing:**
10+
- Support for linearized files
11+
- Support for cross-reference stream
12+
- Updated files?
13+
- Extracting information from the PDF file objects.
14+
- We can construct a page tree and link to annotations and resources.
15+
- **What is missing:**
16+
- Properly parse annotation information
17+
- Properly parse font information
18+
19+
## Discussion: HTML translation
20+
21+
The primer problem of translating PDF to HTML will be to map glyph IDs to Unicode characters.
22+
There can be mapping information in the PDF and in the font but both is not guaranteed.
23+
HTML and SVG do not support drawing characters based on glyph IDs, so we are forced to use Unicode mappings.
24+
If there is no Unicode mapping in the font we would have to transform the font and make up mappings.
25+
This would require the ability of reading and writing font files which may not be trivial and there are a couple of different formats with different versions.
26+
27+
Ultimately it also depends on how often this really happens that we do not have any Unicode mappings at all.
28+
29+
Another problem might be the font support from the browser. Googling suggests that not all formats are supported by popular browsers.
30+
31+
After all this is solved the questions is if we can place text the same way in HTML as it is done in PDF.
32+
PDF has the ability to continue text where it left of or move down a line which could be tricky in HTML.
33+
Apart from that PDF can also modify the spacing between the characters for example which we might be able to translate to CSS positioning.
34+
35+
## References
36+
- https://en.wikipedia.org/wiki/PDF
37+
- File Format
38+
- Objects https://www.oreilly.com/library/view/developing-with-pdf/9781449327903/ch01.html
39+
- https://resources.infosecinstitute.com/topics/hacking/pdf-file-format-basic-structure/
40+
- Structure
41+
- Document Structure https://www.oreilly.com/library/view/pdf-explained/9781449321581/ch04.html
42+
- Cross-reference stream https://www.verypdf.com/document/pdf-format-reference/pg_0106.htm
43+
- Graphics Operators
44+
- https://gendignoux.com/blog/images/pdf-graphics/cheat-sheet-by-nc-sa.png
45+
- https://pdfa.org/wp-content/uploads/2023/08/PDF-Operators-CheatSheet.pdf
46+
- General https://gendignoux.com/blog/2017/01/05/pdf-graphics.html
47+
- Text https://www.syncfusion.com/succinctly-free-ebooks/pdf/text-operators
48+
- Drawing https://www.syncfusion.com/succinctly-free-ebooks/pdf/graphics-operators
49+
- CMap https://blog.idrsolutions.com/how-are-embedded-cmap-tables-in-pdf-file/
50+
- Related projects
51+
- https://github.com/qpdf/qpdf
52+
- https://github.com/caradoc-org/caradoc
53+
- Nasty test files https://github.com/angea/PDF101
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <odr/internal/pdf/pdf_document.hpp>
2+
3+
namespace odr::internal::pdf {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef ODR_INTERNAL_PDF_DOCUMENT_HPP
2+
#define ODR_INTERNAL_PDF_DOCUMENT_HPP
3+
4+
#include <memory>
5+
#include <vector>
6+
7+
namespace odr::internal::pdf {
8+
9+
struct Catalog;
10+
struct Element;
11+
12+
struct Document {
13+
Catalog *catalog;
14+
std::vector<std::unique_ptr<Element>> elements;
15+
16+
template <typename T, typename... Args> T *create_element(Args &&...args) {
17+
auto unique = std::make_unique<T>(std::forward<Args>(args)...);
18+
auto pointer = unique.get();
19+
elements.push_back(std::move(unique));
20+
return pointer;
21+
}
22+
};
23+
24+
} // namespace odr::internal::pdf
25+
26+
#endif // ODR_INTERNAL_PDF_DOCUMENT_HPP
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <odr/internal/pdf/pdf_document_element.hpp>
2+
3+
namespace odr::internal::pdf {}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef ODR_INTERNAL_PDF_DOCUMENT_ELEMENT_HPP
2+
#define ODR_INTERNAL_PDF_DOCUMENT_ELEMENT_HPP
3+
4+
#include <odr/internal/pdf/pdf_object.hpp>
5+
6+
#include <unordered_map>
7+
#include <vector>
8+
9+
namespace odr::internal::pdf {
10+
11+
struct Pages;
12+
struct Page;
13+
struct Annotation;
14+
struct Resources;
15+
struct Font;
16+
17+
enum class Type {
18+
unknown,
19+
catalog,
20+
pages,
21+
page,
22+
annotation,
23+
resources,
24+
font,
25+
};
26+
27+
struct Element {
28+
virtual ~Element() = default;
29+
30+
Type type{Type::unknown};
31+
ObjectReference object_reference;
32+
Object object;
33+
};
34+
35+
struct Catalog : Element {
36+
Pages *pages{nullptr};
37+
};
38+
39+
struct Pages : Element {
40+
std::vector<Element *> kids;
41+
std::uint32_t count{0};
42+
};
43+
44+
struct Page : Element {
45+
Pages *parent{nullptr};
46+
47+
Resources *resources;
48+
std::vector<Annotation *> annotations;
49+
50+
// TODO remove
51+
ObjectReference contents_reference;
52+
};
53+
54+
struct Annotation : Element {};
55+
56+
struct Resources : Element {
57+
std::unordered_map<std::string, Font *> font;
58+
};
59+
60+
struct Font : Element {};
61+
62+
} // namespace odr::internal::pdf
63+
64+
#endif // ODR_INTERNAL_PDF_DOCUMENT_ELEMENT_HPP

0 commit comments

Comments
 (0)