diff --git a/Userland/Libraries/LibPDF/CMakeLists.txt b/Userland/Libraries/LibPDF/CMakeLists.txt index c3a959e4b2..e0ec0d86d9 100644 --- a/Userland/Libraries/LibPDF/CMakeLists.txt +++ b/Userland/Libraries/LibPDF/CMakeLists.txt @@ -3,7 +3,7 @@ set(SOURCES CommonNames.cpp Document.cpp Filter.cpp - Object.cpp + ObjectDerivatives.cpp Parser.cpp Renderer.cpp Value.cpp diff --git a/Userland/Libraries/LibPDF/ColorSpace.cpp b/Userland/Libraries/LibPDF/ColorSpace.cpp index 1336eb6aa7..ccb487e20f 100644 --- a/Userland/Libraries/LibPDF/ColorSpace.cpp +++ b/Userland/Libraries/LibPDF/ColorSpace.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace PDF { diff --git a/Userland/Libraries/LibPDF/ColorSpace.h b/Userland/Libraries/LibPDF/ColorSpace.h index 2a680ff5ff..c22ee7d36e 100644 --- a/Userland/Libraries/LibPDF/ColorSpace.h +++ b/Userland/Libraries/LibPDF/ColorSpace.h @@ -8,7 +8,6 @@ #include #include -#include #include #define ENUMERATE_COLOR_SPACES(V) \ diff --git a/Userland/Libraries/LibPDF/Document.h b/Userland/Libraries/LibPDF/Document.h index 6c885cfcf2..7a4fc14a6f 100644 --- a/Userland/Libraries/LibPDF/Document.h +++ b/Userland/Libraries/LibPDF/Document.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include namespace PDF { diff --git a/Userland/Libraries/LibPDF/Object.h b/Userland/Libraries/LibPDF/Object.h index d7673e8ca5..f3d0fea884 100644 --- a/Userland/Libraries/LibPDF/Object.h +++ b/Userland/Libraries/LibPDF/Object.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -36,199 +35,6 @@ private: u32 m_generation_index { 0 }; }; -class StringObject final : public Object { -public: - StringObject(String string, bool is_binary) - : m_string(move(string)) - , m_is_binary(is_binary) - { - } - - ~StringObject() override = default; - - [[nodiscard]] ALWAYS_INLINE String const& string() const { return m_string; } - [[nodiscard]] ALWAYS_INLINE bool is_binary() const { return m_is_binary; } - - ALWAYS_INLINE bool is_string() const override { return true; } - ALWAYS_INLINE const char* type_name() const override { return "string"; } - String to_string(int indent) const override; - -private: - String m_string; - bool m_is_binary; -}; - -class NameObject final : public Object { -public: - explicit NameObject(FlyString name) - : m_name(move(name)) - { - } - - ~NameObject() override = default; - - [[nodiscard]] ALWAYS_INLINE FlyString const& name() const { return m_name; } - - ALWAYS_INLINE bool is_name() const override { return true; } - ALWAYS_INLINE const char* type_name() const override { return "name"; } - String to_string(int indent) const override; - -private: - FlyString m_name; -}; - -class ArrayObject final : public Object { -public: - explicit ArrayObject(Vector elements) - : m_elements(move(elements)) - { - } - - ~ArrayObject() override = default; - - [[nodiscard]] ALWAYS_INLINE size_t size() const { return m_elements.size(); } - [[nodiscard]] ALWAYS_INLINE Vector elements() const { return m_elements; } - - ALWAYS_INLINE auto begin() const { return m_elements.begin(); } - ALWAYS_INLINE auto end() const { return m_elements.end(); } - - ALWAYS_INLINE Value const& operator[](size_t index) const { return at(index); } - ALWAYS_INLINE Value const& at(size_t index) const { return m_elements[index]; } - - NonnullRefPtr get_object_at(Document*, size_t index) const; - -#define DEFINE_INDEXER(class_name, snake_name) \ - NonnullRefPtr get_##snake_name##_at(Document*, size_t index) const; - ENUMERATE_OBJECT_TYPES(DEFINE_INDEXER) -#undef DEFINE_INDEXER - - ALWAYS_INLINE bool is_array() const override - { - return true; - } - ALWAYS_INLINE const char* type_name() const override { return "array"; } - String to_string(int indent) const override; - -private: - Vector m_elements; -}; - -class DictObject final : public Object { -public: - explicit DictObject(HashMap map) - : m_map(move(map)) - { - } - - ~DictObject() override = default; - - [[nodiscard]] ALWAYS_INLINE HashMap const& map() const { return m_map; } - - template - bool contains(Args&&... keys) const { return (m_map.contains(keys) && ...); } - - ALWAYS_INLINE Optional get(FlyString const& key) const { return m_map.get(key); } - - Value get_value(FlyString const& key) const - { - auto value = get(key); - VERIFY(value.has_value()); - return value.value(); - } - - NonnullRefPtr get_object(Document*, FlyString const& key) const; - -#define DEFINE_GETTER(class_name, snake_name) \ - NonnullRefPtr get_##snake_name(Document*, FlyString const& key) const; - ENUMERATE_OBJECT_TYPES(DEFINE_GETTER) -#undef DEFINE_GETTER - - ALWAYS_INLINE bool is_dict() const override - { - return true; - } - ALWAYS_INLINE const char* type_name() const override { return "dict"; } - String to_string(int indent) const override; - -private: - HashMap m_map; -}; - -class StreamObject : public Object { -public: - explicit StreamObject(NonnullRefPtr const& dict) - : m_dict(dict) - { - } - - virtual ~StreamObject() override = default; - - [[nodiscard]] ALWAYS_INLINE NonnullRefPtr dict() const { return m_dict; } - [[nodiscard]] virtual ReadonlyBytes bytes() const = 0; - - ALWAYS_INLINE bool is_stream() const override { return true; } - ALWAYS_INLINE const char* type_name() const override { return "stream"; } - String to_string(int indent) const override; - -private: - NonnullRefPtr m_dict; -}; - -class PlainTextStreamObject final : public StreamObject { -public: - PlainTextStreamObject(NonnullRefPtr const& dict, ReadonlyBytes const& bytes) - : StreamObject(dict) - , m_bytes(bytes) - { - } - - virtual ~PlainTextStreamObject() override = default; - - [[nodiscard]] ALWAYS_INLINE virtual ReadonlyBytes bytes() const override { return m_bytes; } - -private: - ReadonlyBytes m_bytes; -}; - -class EncodedStreamObject final : public StreamObject { -public: - EncodedStreamObject(NonnullRefPtr const& dict, ByteBuffer&& buffer) - : StreamObject(dict) - , m_buffer(buffer) - { - } - - virtual ~EncodedStreamObject() override = default; - - [[nodiscard]] ALWAYS_INLINE virtual ReadonlyBytes bytes() const override { return m_buffer.bytes(); } - -private: - ByteBuffer m_buffer; -}; - -class IndirectValue final : public Object { -public: - IndirectValue(u32 index, u32 generation_index, Value const& value) - : m_index(index) - , m_value(value) - { - set_generation_index(generation_index); - } - - ~IndirectValue() override = default; - - [[nodiscard]] ALWAYS_INLINE u32 index() const { return m_index; } - [[nodiscard]] ALWAYS_INLINE Value const& value() const { return m_value; } - - ALWAYS_INLINE bool is_indirect_value() const override { return true; } - ALWAYS_INLINE const char* type_name() const override { return "indirect_object"; } - String to_string(int indent) const override; - -private: - u32 m_index; - Value m_value; -}; - template [[nodiscard]] ALWAYS_INLINE static NonnullRefPtr object_cast(NonnullRefPtr obj #ifdef PDF_DEBUG diff --git a/Userland/Libraries/LibPDF/Object.cpp b/Userland/Libraries/LibPDF/ObjectDerivatives.cpp similarity index 99% rename from Userland/Libraries/LibPDF/Object.cpp rename to Userland/Libraries/LibPDF/ObjectDerivatives.cpp index c94f868a27..28e66fce08 100644 --- a/Userland/Libraries/LibPDF/Object.cpp +++ b/Userland/Libraries/LibPDF/ObjectDerivatives.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include namespace PDF { diff --git a/Userland/Libraries/LibPDF/ObjectDerivatives.h b/Userland/Libraries/LibPDF/ObjectDerivatives.h new file mode 100644 index 0000000000..9c23023361 --- /dev/null +++ b/Userland/Libraries/LibPDF/ObjectDerivatives.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021, Matthew Olsson + * Copyright (c) 2021, Ben Wiederhake + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace PDF { + +class StringObject final : public Object { +public: + StringObject(String string, bool is_binary) + : m_string(move(string)) + , m_is_binary(is_binary) + { + } + + ~StringObject() override = default; + + [[nodiscard]] ALWAYS_INLINE String const& string() const { return m_string; } + [[nodiscard]] ALWAYS_INLINE bool is_binary() const { return m_is_binary; } + + ALWAYS_INLINE bool is_string() const override { return true; } + ALWAYS_INLINE const char* type_name() const override { return "string"; } + String to_string(int indent) const override; + +private: + String m_string; + bool m_is_binary; +}; + +class NameObject final : public Object { +public: + explicit NameObject(FlyString name) + : m_name(move(name)) + { + } + + ~NameObject() override = default; + + [[nodiscard]] ALWAYS_INLINE FlyString const& name() const { return m_name; } + + ALWAYS_INLINE bool is_name() const override { return true; } + ALWAYS_INLINE const char* type_name() const override { return "name"; } + String to_string(int indent) const override; + +private: + FlyString m_name; +}; + +class ArrayObject final : public Object { +public: + explicit ArrayObject(Vector elements) + : m_elements(move(elements)) + { + } + + ~ArrayObject() override = default; + + [[nodiscard]] ALWAYS_INLINE size_t size() const { return m_elements.size(); } + [[nodiscard]] ALWAYS_INLINE Vector elements() const { return m_elements; } + + ALWAYS_INLINE auto begin() const { return m_elements.begin(); } + ALWAYS_INLINE auto end() const { return m_elements.end(); } + + ALWAYS_INLINE Value const& operator[](size_t index) const { return at(index); } + ALWAYS_INLINE Value const& at(size_t index) const { return m_elements[index]; } + + NonnullRefPtr get_object_at(Document*, size_t index) const; + +#define DEFINE_INDEXER(class_name, snake_name) \ + NonnullRefPtr get_##snake_name##_at(Document*, size_t index) const; + ENUMERATE_OBJECT_TYPES(DEFINE_INDEXER) +#undef DEFINE_INDEXER + + ALWAYS_INLINE bool is_array() const override + { + return true; + } + ALWAYS_INLINE const char* type_name() const override { return "array"; } + String to_string(int indent) const override; + +private: + Vector m_elements; +}; + +class DictObject final : public Object { +public: + explicit DictObject(HashMap map) + : m_map(move(map)) + { + } + + ~DictObject() override = default; + + [[nodiscard]] ALWAYS_INLINE HashMap const& map() const { return m_map; } + + template + bool contains(Args&&... keys) const { return (m_map.contains(keys) && ...); } + + ALWAYS_INLINE Optional get(FlyString const& key) const { return m_map.get(key); } + + Value get_value(FlyString const& key) const + { + auto value = get(key); + VERIFY(value.has_value()); + return value.value(); + } + + NonnullRefPtr get_object(Document*, FlyString const& key) const; + +#define DEFINE_GETTER(class_name, snake_name) \ + NonnullRefPtr get_##snake_name(Document*, FlyString const& key) const; + ENUMERATE_OBJECT_TYPES(DEFINE_GETTER) +#undef DEFINE_GETTER + + ALWAYS_INLINE bool is_dict() const override + { + return true; + } + ALWAYS_INLINE const char* type_name() const override { return "dict"; } + String to_string(int indent) const override; + +private: + HashMap m_map; +}; + +class StreamObject : public Object { +public: + explicit StreamObject(NonnullRefPtr const& dict) + : m_dict(dict) + { + } + + virtual ~StreamObject() override = default; + + [[nodiscard]] ALWAYS_INLINE NonnullRefPtr dict() const { return m_dict; } + [[nodiscard]] virtual ReadonlyBytes bytes() const = 0; + + ALWAYS_INLINE bool is_stream() const override { return true; } + ALWAYS_INLINE const char* type_name() const override { return "stream"; } + String to_string(int indent) const override; + +private: + NonnullRefPtr m_dict; +}; + +class PlainTextStreamObject final : public StreamObject { +public: + PlainTextStreamObject(NonnullRefPtr const& dict, ReadonlyBytes const& bytes) + : StreamObject(dict) + , m_bytes(bytes) + { + } + + virtual ~PlainTextStreamObject() override = default; + + [[nodiscard]] ALWAYS_INLINE virtual ReadonlyBytes bytes() const override { return m_bytes; } + +private: + ReadonlyBytes m_bytes; +}; + +class EncodedStreamObject final : public StreamObject { +public: + EncodedStreamObject(NonnullRefPtr const& dict, ByteBuffer&& buffer) + : StreamObject(dict) + , m_buffer(buffer) + { + } + + virtual ~EncodedStreamObject() override = default; + + [[nodiscard]] ALWAYS_INLINE virtual ReadonlyBytes bytes() const override { return m_buffer.bytes(); } + +private: + ByteBuffer m_buffer; +}; + +class IndirectValue final : public Object { +public: + IndirectValue(u32 index, u32 generation_index, Value const& value) + : m_index(index) + , m_value(value) + { + set_generation_index(generation_index); + } + + ~IndirectValue() override = default; + + [[nodiscard]] ALWAYS_INLINE u32 index() const { return m_index; } + [[nodiscard]] ALWAYS_INLINE Value const& value() const { return m_value; } + + ALWAYS_INLINE bool is_indirect_value() const override { return true; } + ALWAYS_INLINE const char* type_name() const override { return "indirect_object"; } + String to_string(int indent) const override; + +private: + u32 m_index; + Value m_value; +}; + +} diff --git a/Userland/Libraries/LibPDF/Value.h b/Userland/Libraries/LibPDF/Value.h index a8e8cd735e..2f6e0b1b63 100644 --- a/Userland/Libraries/LibPDF/Value.h +++ b/Userland/Libraries/LibPDF/Value.h @@ -10,11 +10,10 @@ #include #include #include +#include namespace PDF { -class Object; - class Value { public: // We store refs as u32, with 18 bits for the index and 14 bits for the