mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:17:35 +00:00
LibPDF: Create basic object structure
This commit is the start of LibPDF, and introduces some basic structure objects. This emulates LibJS's Value structure, where Value is a simple class that can contain a pointer to a more complex Object class with more data. All of the basic PDF objects have a representation.
This commit is contained in:
parent
af9a7b1374
commit
a8f5b6aaa3
10 changed files with 637 additions and 0 deletions
116
Userland/Libraries/LibPDF/Object.cpp
Normal file
116
Userland/Libraries/LibPDF/Object.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Hex.h>
|
||||
#include <LibPDF/Object.h>
|
||||
|
||||
namespace PDF {
|
||||
|
||||
static void append_indent(StringBuilder& builder, int indent)
|
||||
{
|
||||
for (int i = 0; i < indent; i++)
|
||||
builder.append(" ");
|
||||
}
|
||||
|
||||
String StringObject::to_string(int) const
|
||||
{
|
||||
if (is_binary())
|
||||
return String::formatted("<{}>", encode_hex(string().bytes()).to_uppercase());
|
||||
return String::formatted("({})", string());
|
||||
}
|
||||
|
||||
String NameObject::to_string(int) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.appendff("/{}", this->name());
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
String ArrayObject::to_string(int indent) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.append("[\n");
|
||||
bool first = true;
|
||||
|
||||
for (auto& element : elements()) {
|
||||
if (!first)
|
||||
builder.append(",\n");
|
||||
first = false;
|
||||
append_indent(builder, indent + 1);
|
||||
builder.appendff("{}", element.to_string(indent));
|
||||
}
|
||||
|
||||
builder.append('\n');
|
||||
append_indent(builder, indent);
|
||||
builder.append(']');
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
String DictObject::to_string(int indent) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.append("<<\n");
|
||||
bool first = true;
|
||||
|
||||
for (auto& [key, value] : map()) {
|
||||
if (!first)
|
||||
builder.append(",\n");
|
||||
first = false;
|
||||
append_indent(builder, indent + 1);
|
||||
builder.appendff("/{} ", key);
|
||||
builder.appendff("{}", value.to_string(indent + 1));
|
||||
}
|
||||
|
||||
builder.append('\n');
|
||||
append_indent(builder, indent);
|
||||
builder.append(">>");
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
String StreamObject::to_string(int indent) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.append("stream\n");
|
||||
append_indent(builder, indent);
|
||||
builder.appendff("{}\n", dict()->to_string(indent + 1));
|
||||
append_indent(builder, indent + 1);
|
||||
|
||||
auto string = encode_hex(bytes());
|
||||
while (true) {
|
||||
if (string.length() > 60) {
|
||||
builder.appendff("{}\n", string.substring(0, 60));
|
||||
append_indent(builder, indent);
|
||||
string = string.substring(60);
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.appendff("{}\n", string);
|
||||
break;
|
||||
}
|
||||
|
||||
append_indent(builder, indent);
|
||||
builder.append("endstream");
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
String IndirectValue::to_string(int indent) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.appendff("{} {} obj\n", index(), generation_index());
|
||||
append_indent(builder, indent + 1);
|
||||
builder.append(value().to_string(indent + 1));
|
||||
builder.append('\n');
|
||||
append_indent(builder, indent);
|
||||
builder.append("endobj");
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
String IndirectValueRef::to_string(int) const
|
||||
{
|
||||
return String::formatted("{} {} R", index(), generation_index());
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue