Serenity Operating System
at master 159 lines 6.6 kB view raw
1/* 2 * Copyright (c) 2021-2022, Matthew Olsson <mattco@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Hex.h> 8#include <LibPDF/Document.h> 9#include <LibPDF/ObjectDerivatives.h> 10 11namespace PDF { 12 13PDFErrorOr<NonnullRefPtr<Object>> ArrayObject::get_object_at(Document* document, size_t index) const 14{ 15 return document->resolve_to<Object>(at(index)); 16} 17 18PDFErrorOr<NonnullRefPtr<Object>> DictObject::get_object(Document* document, DeprecatedFlyString const& key) const 19{ 20 return document->resolve_to<Object>(get_value(key)); 21} 22 23#define DEFINE_ACCESSORS(class_name, snake_name) \ 24 PDFErrorOr<NonnullRefPtr<class_name>> ArrayObject::get_##snake_name##_at(Document* document, size_t index) const \ 25 { \ 26 if (index >= m_elements.size()) \ 27 return Error { Error::Type::Internal, "Out of bounds array access" }; \ 28 return document->resolve_to<class_name>(m_elements[index]); \ 29 } \ 30 \ 31 NonnullRefPtr<class_name> ArrayObject::get_##snake_name##_at(size_t index) const \ 32 { \ 33 VERIFY(index < m_elements.size()); \ 34 return cast_to<class_name>(m_elements[index]); \ 35 } \ 36 \ 37 PDFErrorOr<NonnullRefPtr<class_name>> DictObject::get_##snake_name(Document* document, DeprecatedFlyString const& key) const \ 38 { \ 39 return document->resolve_to<class_name>(get_value(key)); \ 40 } \ 41 \ 42 NonnullRefPtr<class_name> DictObject::get_##snake_name(DeprecatedFlyString const& key) const \ 43 { \ 44 return cast_to<class_name>(get_value(key)); \ 45 } 46 47ENUMERATE_OBJECT_TYPES(DEFINE_ACCESSORS) 48#undef DEFINE_INDEXER 49 50static void append_indent(StringBuilder& builder, int indent) 51{ 52 for (int i = 0; i < indent; i++) 53 builder.append(" "sv); 54} 55 56DeprecatedString StringObject::to_deprecated_string(int) const 57{ 58 if (is_binary()) 59 return DeprecatedString::formatted("<{}>", encode_hex(string().bytes()).to_uppercase()); 60 return DeprecatedString::formatted("({})", string()); 61} 62 63DeprecatedString NameObject::to_deprecated_string(int) const 64{ 65 StringBuilder builder; 66 builder.appendff("/{}", this->name()); 67 return builder.to_deprecated_string(); 68} 69 70Vector<float> ArrayObject::float_elements() const 71{ 72 Vector<float> values; 73 values.ensure_capacity(m_elements.size()); 74 for (auto const& value : m_elements) { 75 values.append(value.to_float()); 76 } 77 return values; 78} 79 80DeprecatedString ArrayObject::to_deprecated_string(int indent) const 81{ 82 StringBuilder builder; 83 builder.append("[\n"sv); 84 bool first = true; 85 86 for (auto& element : elements()) { 87 if (!first) 88 builder.append(",\n"sv); 89 first = false; 90 append_indent(builder, indent + 1); 91 builder.appendff("{}", element.to_deprecated_string(indent)); 92 } 93 94 builder.append('\n'); 95 append_indent(builder, indent); 96 builder.append(']'); 97 return builder.to_deprecated_string(); 98} 99 100DeprecatedString DictObject::to_deprecated_string(int indent) const 101{ 102 StringBuilder builder; 103 builder.append("<<\n"sv); 104 bool first = true; 105 106 for (auto& [key, value] : map()) { 107 if (!first) 108 builder.append(",\n"sv); 109 first = false; 110 append_indent(builder, indent + 1); 111 builder.appendff("/{} ", key); 112 builder.appendff("{}", value.to_deprecated_string(indent + 1)); 113 } 114 115 builder.append('\n'); 116 append_indent(builder, indent); 117 builder.append(">>"sv); 118 return builder.to_deprecated_string(); 119} 120 121DeprecatedString StreamObject::to_deprecated_string(int indent) const 122{ 123 StringBuilder builder; 124 builder.append("stream\n"sv); 125 append_indent(builder, indent); 126 builder.appendff("{}\n", dict()->to_deprecated_string(indent + 1)); 127 append_indent(builder, indent + 1); 128 129 auto string = encode_hex(bytes()); 130 while (true) { 131 if (string.length() > 60) { 132 builder.appendff("{}\n", string.substring(0, 60)); 133 append_indent(builder, indent); 134 string = string.substring(60); 135 continue; 136 } 137 138 builder.appendff("{}\n", string); 139 break; 140 } 141 142 append_indent(builder, indent); 143 builder.append("endstream"sv); 144 return builder.to_deprecated_string(); 145} 146 147DeprecatedString IndirectValue::to_deprecated_string(int indent) const 148{ 149 StringBuilder builder; 150 builder.appendff("{} {} obj\n", index(), generation_index()); 151 append_indent(builder, indent + 1); 152 builder.append(value().to_deprecated_string(indent + 1)); 153 builder.append('\n'); 154 append_indent(builder, indent); 155 builder.append("endobj"sv); 156 return builder.to_deprecated_string(); 157} 158 159}