1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 04:55:00 +00:00
serenity/Userland/Libraries/LibPDF/Object.cpp
Matthew Olsson a8f5b6aaa3 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.
2021-05-10 10:32:39 +02:00

116 lines
2.8 KiB
C++

/*
* 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());
}
}