mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-20 08:18:55 +00:00
LibPDF: Move rest of CFF from Reader to Stream
parse_index_data() wants to take ReadonlyByte views of the stream data, so we need FixedMemoryStream::read_in_place(size_t). All other remaining code indirectly calls parse_index_data(), so that all operates on FixedMemoryStreams too. No behavior change.
This commit is contained in:
parent
cc3d4b6adb
commit
2b905cc482
Notes:
sideshowbarker
2024-07-17 07:43:05 +09:00
Author: https://github.com/nico
Commit: 2b905cc482
Pull-request: https://github.com/SerenityOS/serenity/pull/23957
Reviewed-by: https://github.com/LucasChollet ✅
2 changed files with 27 additions and 30 deletions
|
@ -13,7 +13,6 @@
|
||||||
#include <LibPDF/Encoding.h>
|
#include <LibPDF/Encoding.h>
|
||||||
#include <LibPDF/Error.h>
|
#include <LibPDF/Error.h>
|
||||||
#include <LibPDF/Fonts/CFF.h>
|
#include <LibPDF/Fonts/CFF.h>
|
||||||
#include <LibPDF/Reader.h>
|
|
||||||
|
|
||||||
namespace PDF {
|
namespace PDF {
|
||||||
|
|
||||||
|
@ -97,15 +96,15 @@ static constexpr auto s_predefined_charset_expert_subset = to_array<CFF::SID>({
|
||||||
|
|
||||||
PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPtr<Encoding> encoding)
|
PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPtr<Encoding> encoding)
|
||||||
{
|
{
|
||||||
Reader reader(cff_bytes);
|
FixedMemoryStream reader(cff_bytes);
|
||||||
|
|
||||||
// CFF spec, "6 Header"
|
// CFF spec, "6 Header"
|
||||||
// skip major, minor version
|
// skip major, minor version
|
||||||
reader.consume(2);
|
TRY(reader.discard(2));
|
||||||
auto header_size = TRY(reader.try_read<Card8>());
|
auto header_size = TRY(reader.read_value<Card8>());
|
||||||
// skip offset size
|
// skip offset size
|
||||||
reader.consume(1);
|
TRY(reader.discard(1));
|
||||||
reader.move_to(header_size);
|
TRY(reader.seek(header_size));
|
||||||
|
|
||||||
// CFF spec, "7 Name INDEX"
|
// CFF spec, "7 Name INDEX"
|
||||||
Vector<String> font_names;
|
Vector<String> font_names;
|
||||||
|
@ -157,7 +156,7 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
|
||||||
dbgln_if(CFF_DEBUG, "CFF has {} gsubr entries", global_subroutines.size());
|
dbgln_if(CFF_DEBUG, "CFF has {} gsubr entries", global_subroutines.size());
|
||||||
|
|
||||||
// Create glyphs (now that we have the subroutines) and associate missing information to store them and their encoding
|
// Create glyphs (now that we have the subroutines) and associate missing information to store them and their encoding
|
||||||
auto glyphs = TRY(parse_charstrings(Reader(cff_bytes.slice(top_dict.charstrings_offset)), top_dict.local_subroutines, global_subroutines));
|
auto glyphs = TRY(parse_charstrings(FixedMemoryStream(cff_bytes.slice(top_dict.charstrings_offset)), top_dict.local_subroutines, global_subroutines));
|
||||||
|
|
||||||
// CFF spec, "Table 16 Encoding ID"
|
// CFF spec, "Table 16 Encoding ID"
|
||||||
// FIXME: Only read this if the built-in encoding is actually needed? (ie. `if (!encoding)`)
|
// FIXME: Only read this if the built-in encoding is actually needed? (ie. `if (!encoding)`)
|
||||||
|
@ -216,7 +215,7 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
|
||||||
// CFF spec, "18 CID-keyed Fonts"
|
// CFF spec, "18 CID-keyed Fonts"
|
||||||
Vector<TopDict> font_dicts;
|
Vector<TopDict> font_dicts;
|
||||||
if (top_dict.fdarray_offset != 0) {
|
if (top_dict.fdarray_offset != 0) {
|
||||||
Reader fdarray_reader { cff_bytes.slice(top_dict.fdarray_offset) };
|
FixedMemoryStream fdarray_reader { cff_bytes.slice(top_dict.fdarray_offset) };
|
||||||
font_dicts = TRY(parse_top_dicts(fdarray_reader, cff_bytes));
|
font_dicts = TRY(parse_top_dicts(fdarray_reader, cff_bytes));
|
||||||
dbgln_if(CFF_DEBUG, "CFF has {} FDArray entries", font_dicts.size());
|
dbgln_if(CFF_DEBUG, "CFF has {} FDArray entries", font_dicts.size());
|
||||||
}
|
}
|
||||||
|
@ -294,7 +293,7 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
|
||||||
return cff;
|
return cff;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<Vector<CFF::TopDict>> CFF::parse_top_dicts(Reader& reader, ReadonlyBytes const& cff_bytes)
|
PDFErrorOr<Vector<CFF::TopDict>> CFF::parse_top_dicts(FixedMemoryStream& reader, ReadonlyBytes const& cff_bytes)
|
||||||
{
|
{
|
||||||
Vector<TopDict> top_dicts;
|
Vector<TopDict> top_dicts;
|
||||||
|
|
||||||
|
@ -379,7 +378,7 @@ PDFErrorOr<Vector<CFF::TopDict>> CFF::parse_top_dicts(Reader& reader, ReadonlyBy
|
||||||
// CFF spec, "16 Local/Global Subrs INDEXes"
|
// CFF spec, "16 Local/Global Subrs INDEXes"
|
||||||
// "Local subrs are stored in an INDEX structure which is located via the offset operand of the Subrs operator in the Private DICT."
|
// "Local subrs are stored in an INDEX structure which is located via the offset operand of the Subrs operator in the Private DICT."
|
||||||
auto subrs_offset = operands[0].get<int>();
|
auto subrs_offset = operands[0].get<int>();
|
||||||
Reader subrs_reader { cff_bytes.slice(private_dict_offset + subrs_offset) };
|
FixedMemoryStream subrs_reader { cff_bytes.slice(private_dict_offset + subrs_offset) };
|
||||||
TRY(parse_index(subrs_reader, [&](ReadonlyBytes const& subroutine_bytes) -> PDFErrorOr<void> {
|
TRY(parse_index(subrs_reader, [&](ReadonlyBytes const& subroutine_bytes) -> PDFErrorOr<void> {
|
||||||
return TRY(top_dict.local_subroutines.try_append(TRY(ByteBuffer::copy(subroutine_bytes))));
|
return TRY(top_dict.local_subroutines.try_append(TRY(ByteBuffer::copy(subroutine_bytes))));
|
||||||
}));
|
}));
|
||||||
|
@ -831,7 +830,7 @@ static constexpr Array s_cff_builtin_names {
|
||||||
"Semibold"sv,
|
"Semibold"sv,
|
||||||
};
|
};
|
||||||
|
|
||||||
PDFErrorOr<Vector<StringView>> CFF::parse_strings(Reader& reader)
|
PDFErrorOr<Vector<StringView>> CFF::parse_strings(FixedMemoryStream& reader)
|
||||||
{
|
{
|
||||||
// CFF spec "10 String Index"
|
// CFF spec "10 String Index"
|
||||||
Vector<StringView> strings;
|
Vector<StringView> strings;
|
||||||
|
@ -940,7 +939,7 @@ PDFErrorOr<Vector<u8>> CFF::parse_fdselect(Stream&& reader, size_t glyph_count)
|
||||||
return fd_selector_array;
|
return fd_selector_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<Vector<CFF::Glyph>> CFF::parse_charstrings(Reader&& reader, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines)
|
PDFErrorOr<Vector<CFF::Glyph>> CFF::parse_charstrings(FixedMemoryStream&& reader, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines)
|
||||||
{
|
{
|
||||||
// CFF spec, "14 CharStrings INDEX"
|
// CFF spec, "14 CharStrings INDEX"
|
||||||
Vector<Glyph> glyphs;
|
Vector<Glyph> glyphs;
|
||||||
|
@ -1034,19 +1033,19 @@ PDFErrorOr<OperatorT> CFF::parse_dict_operator(u8 b0, Stream& reader)
|
||||||
|
|
||||||
template PDFErrorOr<CFF::TopDictOperator> CFF::parse_dict_operator(u8, Stream&);
|
template PDFErrorOr<CFF::TopDictOperator> CFF::parse_dict_operator(u8, Stream&);
|
||||||
|
|
||||||
PDFErrorOr<void> CFF::parse_index(Reader& reader, IndexDataHandler&& data_handler)
|
PDFErrorOr<void> CFF::parse_index(FixedMemoryStream& reader, IndexDataHandler&& data_handler)
|
||||||
{
|
{
|
||||||
// CFF spec, "5 INDEX Data"
|
// CFF spec, "5 INDEX Data"
|
||||||
Card16 count = TRY(reader.try_read<BigEndian<Card16>>());
|
Card16 count = TRY(reader.read_value<BigEndian<Card16>>());
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return {};
|
return {};
|
||||||
auto offset_size = TRY(reader.try_read<OffSize>());
|
auto offset_size = TRY(reader.read_value<OffSize>());
|
||||||
if (offset_size > 4)
|
if (offset_size > 4)
|
||||||
return error("CFF INDEX Data offset_size > 4 not supported");
|
return error("CFF INDEX Data offset_size > 4 not supported");
|
||||||
return parse_index_data(offset_size, count, reader, data_handler);
|
return parse_index_data(offset_size, count, reader, data_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<void> CFF::parse_index_data(OffSize offset_size, Card16 count, Reader& reader, IndexDataHandler& handler)
|
PDFErrorOr<void> CFF::parse_index_data(OffSize offset_size, Card16 count, FixedMemoryStream& reader, IndexDataHandler& handler)
|
||||||
{
|
{
|
||||||
// CFF spec, "5 INDEX Data"
|
// CFF spec, "5 INDEX Data"
|
||||||
u32 last_data_end = 1;
|
u32 last_data_end = 1;
|
||||||
|
@ -1054,24 +1053,24 @@ PDFErrorOr<void> CFF::parse_index_data(OffSize offset_size, Card16 count, Reader
|
||||||
auto read_offset = [&]() -> PDFErrorOr<u32> {
|
auto read_offset = [&]() -> PDFErrorOr<u32> {
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
for (OffSize i = 0; i < offset_size; ++i)
|
for (OffSize i = 0; i < offset_size; ++i)
|
||||||
offset = (offset << 8) | TRY(reader.try_read<u8>());
|
offset = (offset << 8) | TRY(reader.read_value<u8>());
|
||||||
return offset;
|
return offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto offset_refpoint = reader.offset() + offset_size * (count + 1) - 1;
|
auto offset_refpoint = reader.offset() + offset_size * (count + 1) - 1;
|
||||||
for (u16 i = 0; i < count; i++) {
|
for (u16 i = 0; i < count; i++) {
|
||||||
reader.save();
|
auto saved_offset = TRY(reader.tell());
|
||||||
|
|
||||||
reader.move_by(offset_size * i);
|
TRY(reader.seek(offset_size * i, SeekMode::FromCurrentPosition));
|
||||||
u32 data_start = TRY(read_offset());
|
u32 data_start = TRY(read_offset());
|
||||||
last_data_end = TRY(read_offset());
|
last_data_end = TRY(read_offset());
|
||||||
|
|
||||||
auto data_size = last_data_end - data_start;
|
auto data_size = last_data_end - data_start;
|
||||||
reader.move_to(offset_refpoint + data_start);
|
TRY(reader.seek(offset_refpoint + data_start));
|
||||||
TRY(handler(reader.bytes().slice(reader.offset(), data_size)));
|
TRY(handler(TRY(reader.read_in_place<u8 const>(data_size))));
|
||||||
reader.load();
|
TRY(reader.seek(saved_offset));
|
||||||
}
|
}
|
||||||
reader.move_to(offset_refpoint + last_data_end);
|
TRY(reader.seek(offset_refpoint + last_data_end));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
namespace PDF {
|
namespace PDF {
|
||||||
|
|
||||||
class Reader;
|
|
||||||
|
|
||||||
// CFF spec: https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf
|
// CFF spec: https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf
|
||||||
|
|
||||||
class CFF : public Type1FontProgram {
|
class CFF : public Type1FontProgram {
|
||||||
|
@ -104,9 +102,9 @@ public:
|
||||||
static PDFErrorOr<DictOperand> load_dict_operand(u8, Stream&);
|
static PDFErrorOr<DictOperand> load_dict_operand(u8, Stream&);
|
||||||
|
|
||||||
using IndexDataHandler = Function<PDFErrorOr<void>(ReadonlyBytes const&)>;
|
using IndexDataHandler = Function<PDFErrorOr<void>(ReadonlyBytes const&)>;
|
||||||
static PDFErrorOr<void> parse_index(Reader& reader, IndexDataHandler&&);
|
static PDFErrorOr<void> parse_index(FixedMemoryStream&, IndexDataHandler&&);
|
||||||
|
|
||||||
static PDFErrorOr<void> parse_index_data(OffSize offset_size, Card16 count, Reader& reader, IndexDataHandler&);
|
static PDFErrorOr<void> parse_index_data(OffSize offset_size, Card16 count, FixedMemoryStream&, IndexDataHandler&);
|
||||||
|
|
||||||
template<typename OperatorT>
|
template<typename OperatorT>
|
||||||
using DictEntryHandler = Function<PDFErrorOr<void>(OperatorT, Vector<DictOperand> const&)>;
|
using DictEntryHandler = Function<PDFErrorOr<void>(OperatorT, Vector<DictOperand> const&)>;
|
||||||
|
@ -129,11 +127,11 @@ public:
|
||||||
int fdselect_offset = 0;
|
int fdselect_offset = 0;
|
||||||
int fdarray_offset = 0;
|
int fdarray_offset = 0;
|
||||||
};
|
};
|
||||||
static PDFErrorOr<Vector<TopDict>> parse_top_dicts(Reader&, ReadonlyBytes const& cff_bytes);
|
static PDFErrorOr<Vector<TopDict>> parse_top_dicts(FixedMemoryStream&, ReadonlyBytes const& cff_bytes);
|
||||||
|
|
||||||
static PDFErrorOr<Vector<StringView>> parse_strings(Reader&);
|
static PDFErrorOr<Vector<StringView>> parse_strings(FixedMemoryStream&);
|
||||||
|
|
||||||
static PDFErrorOr<Vector<CFF::Glyph>> parse_charstrings(Reader&&, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines);
|
static PDFErrorOr<Vector<CFF::Glyph>> parse_charstrings(FixedMemoryStream&&, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines);
|
||||||
|
|
||||||
static DeprecatedFlyString resolve_sid(SID, Vector<StringView> const&);
|
static DeprecatedFlyString resolve_sid(SID, Vector<StringView> const&);
|
||||||
static PDFErrorOr<Vector<SID>> parse_charset(Stream&&, size_t);
|
static PDFErrorOr<Vector<SID>> parse_charset(Stream&&, size_t);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue