mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 03:17:35 +00:00
LibPDF: Allow reading documents with incremental updates
The PDF spec allows incremental changes of a document by appending a new XRef table and file trailer to it. These will only contain the changed objects and will point back to the previous change, forming an arbitrarily long chain of XRef sections and file trailers. Every one of those XRef sections may be encoded as an XRef stream as well, in which case the trailer is part of the stream dictionary as usual. To make this easier, I made it so every XRef table may "own" a trailer. This means that the main file trailer is now part of the main XRef table.
This commit is contained in:
parent
0c230f5ff0
commit
34350ee9e7
3 changed files with 41 additions and 25 deletions
|
@ -35,7 +35,7 @@ public:
|
|||
{
|
||||
auto this_size = m_entries.size();
|
||||
auto other_size = other.m_entries.size();
|
||||
m_entries.ensure_capacity(other_size);
|
||||
TRY(m_entries.try_ensure_capacity(other_size));
|
||||
|
||||
for (size_t i = 0; i < other_size; i++) {
|
||||
auto other_entry = other.m_entries[i];
|
||||
|
@ -46,12 +46,9 @@ public:
|
|||
|
||||
auto this_entry = m_entries[i];
|
||||
|
||||
if (this_entry.byte_offset == invalid_byte_offset) {
|
||||
// Only add values that we don't already have.
|
||||
if (this_entry.byte_offset == invalid_byte_offset)
|
||||
m_entries[i] = other_entry;
|
||||
} else if (other_entry.byte_offset != invalid_byte_offset) {
|
||||
// Both xref tables have an entry for the same object index
|
||||
return Error { Error::Type::Parse, "Conflicting xref entry during merge" };
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -68,8 +65,12 @@ public:
|
|||
m_entries.append(entry);
|
||||
}
|
||||
|
||||
void set_trailer(RefPtr<DictObject> trailer) { m_trailer = trailer; }
|
||||
|
||||
ALWAYS_INLINE Vector<XRefEntry>& entries() { return m_entries; }
|
||||
|
||||
ALWAYS_INLINE RefPtr<DictObject> const& trailer() const { return m_trailer; }
|
||||
|
||||
[[nodiscard]] ALWAYS_INLINE bool has_object(size_t index) const
|
||||
{
|
||||
return index < m_entries.size() && m_entries[index].byte_offset != -1;
|
||||
|
@ -113,6 +114,7 @@ private:
|
|||
friend struct AK::Formatter<PDF::XRefTable>;
|
||||
|
||||
Vector<XRefEntry> m_entries;
|
||||
RefPtr<DictObject> m_trailer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue