소스 검색

LibPDF: Make PDF version accessible on Document

Nico Weber 2 년 전
부모
커밋
ea89053c12

+ 1 - 2
Userland/Libraries/LibPDF/Document.cpp

@@ -79,8 +79,7 @@ PDFErrorOr<NonnullRefPtr<Document>> Document::create(ReadonlyBytes bytes)
     auto parser = adopt_ref(*new DocumentParser({}, bytes));
     auto document = adopt_ref(*new Document(parser));
 
-    TRY(parser->initialize());
-
+    document->m_version = TRY(parser->initialize());
     document->m_trailer = parser->trailer();
     document->m_catalog = TRY(parser->trailer()->get_dict(document, CommonNames::Root));
 

+ 3 - 0
Userland/Libraries/LibPDF/Document.h

@@ -122,6 +122,8 @@ public:
     // need to handle the case where the user password is the empty string.
     PDFErrorOr<void> initialize();
 
+    Version version() const { return m_version; }
+
     ALWAYS_INLINE RefPtr<SecurityHandler> const& security_handler() const { return m_security_handler; }
 
     ALWAYS_INLINE RefPtr<OutlineDict> const& outline() const { return m_outline; }
@@ -188,6 +190,7 @@ private:
     PDFErrorOr<NonnullRefPtr<Object>> find_in_key_value_array(NonnullRefPtr<ArrayObject> key_value_array, DeprecatedFlyString name);
 
     NonnullRefPtr<DocumentParser> m_parser;
+    Version m_version;
     RefPtr<DictObject> m_catalog;
     RefPtr<DictObject> m_trailer;
     Vector<u32> m_page_object_indices;

+ 15 - 11
Userland/Libraries/LibPDF/DocumentParser.cpp

@@ -21,22 +21,25 @@ DocumentParser::DocumentParser(Document* document, ReadonlyBytes bytes)
 {
 }
 
-PDFErrorOr<void> DocumentParser::initialize()
+PDFErrorOr<Version> DocumentParser::initialize()
 {
     m_reader.set_reading_forwards();
     if (m_reader.remaining() == 0)
         return error("Empty PDF document");
 
-    auto maybe_error = parse_header();
-    if (maybe_error.is_error()) {
-        warnln("{}", maybe_error.error().message());
+    auto maybe_version = parse_header();
+    if (maybe_version.is_error()) {
+        warnln("{}", maybe_version.error().message());
         warnln("No valid PDF header detected, continuing anyway.");
+        maybe_version = Version { 1, 6 }; // ¯\_(ツ)_/¯
     }
 
     auto const linearization_result = TRY(initialize_linearization_dict());
 
-    if (linearization_result == LinearizationResult::NotLinearized)
-        return initialize_non_linearized_xref_table();
+    if (linearization_result == LinearizationResult::NotLinearized) {
+        TRY(initialize_non_linearized_xref_table());
+        return maybe_version.value();
+    }
 
     bool is_linearized = m_linearization_dictionary.has_value();
     if (is_linearized) {
@@ -53,9 +56,11 @@ PDFErrorOr<void> DocumentParser::initialize()
     }
 
     if (is_linearized)
-        return initialize_linearized_xref_table();
+        TRY(initialize_linearized_xref_table());
+    else
+        TRY(initialize_non_linearized_xref_table());
 
-    return initialize_non_linearized_xref_table();
+    return maybe_version.value();
 }
 
 PDFErrorOr<Value> DocumentParser::parse_object_with_index(u32 index)
@@ -73,9 +78,8 @@ PDFErrorOr<Value> DocumentParser::parse_object_with_index(u32 index)
     return indirect_value->value();
 }
 
-PDFErrorOr<void> DocumentParser::parse_header()
+PDFErrorOr<Version> DocumentParser::parse_header()
 {
-    // FIXME: Do something with the version?
     m_reader.move_to(0);
     if (m_reader.remaining() < 8 || !m_reader.matches("%PDF-"))
         return error("Not a PDF document");
@@ -106,7 +110,7 @@ PDFErrorOr<void> DocumentParser::parse_header()
         }
     }
 
-    return {};
+    return Version { major_ver - '0', minor_ver - '0' };
 }
 
 PDFErrorOr<DocumentParser::LinearizationResult> DocumentParser::initialize_linearization_dict()

+ 7 - 2
Userland/Libraries/LibPDF/DocumentParser.h

@@ -10,6 +10,11 @@
 
 namespace PDF {
 
+struct Version {
+    int major { 0 };
+    int minor { 0 };
+};
+
 class DocumentParser final : public RefCounted<DocumentParser>
     , public Parser {
 public:
@@ -23,7 +28,7 @@ public:
     [[nodiscard]] ALWAYS_INLINE RefPtr<DictObject> const& trailer() const { return m_xref_table->trailer(); }
 
     // Parses the header and initializes the xref table and trailer
-    PDFErrorOr<void> initialize();
+    PDFErrorOr<Version> initialize();
 
     bool can_resolve_references() { return m_xref_table; }
 
@@ -77,7 +82,7 @@ private:
     friend struct AK::Formatter<PageOffsetHintTable>;
     friend struct AK::Formatter<PageOffsetHintTableEntry>;
 
-    PDFErrorOr<void> parse_header();
+    PDFErrorOr<Version> parse_header();
     PDFErrorOr<LinearizationResult> initialize_linearization_dict();
     PDFErrorOr<void> initialize_linearized_xref_table();
     PDFErrorOr<void> initialize_non_linearized_xref_table();