LibPDF: Move Type1FontProgram to use AK::Error instead of PDF::Error

Makes some of the errors a bit less descriptive. But this is pretty
stable by now and the errors fire basically never, so that seems ok.

Needing the explicit `AK::` prefix is a bit awkward, but that'll go
away once this class moves out of LibPDF.

Move error() into the two subclasses. I'll remove it from CFF in
a follow-up.

No real behavior change.
This commit is contained in:
Nico Weber 2024-04-14 09:08:47 -04:00 committed by Andreas Kling
commit 102ac331c6
Notes: sideshowbarker 2024-07-17 04:10:16 +09:00
6 changed files with 62 additions and 39 deletions

View file

@ -1144,4 +1144,20 @@ PDFErrorOr<CFF::DictOperand> CFF::load_dict_operand(u8 b0, Stream& reader)
return Error { Error::Type::MalformedPDF, ByteString::formatted("Unknown CFF dict element prefix: {}", b0) };
}
Error CFF::error(
ByteString const& message
#ifdef PDF_DEBUG
,
SourceLocation loc
#endif
)
{
#ifdef PDF_DEBUG
dbgln("\033[31m{} Type 1 font error: {}\033[0m", loc, message);
#endif
return Error { Error::Type::MalformedPDF, message };
}
}

View file

@ -137,6 +137,14 @@ public:
static PDFErrorOr<Vector<SID>> parse_charset(Stream&&, size_t);
static PDFErrorOr<Vector<u8>> parse_fdselect(Stream&&, size_t);
static PDFErrorOr<Vector<u8>> parse_encoding(Stream&&, HashMap<Card8, SID>& supplemental);
static Error error(
ByteString const& message
#ifdef PDF_DEBUG
,
SourceLocation loc = SourceLocation::current()
#endif
);
};
}

View file

@ -237,4 +237,19 @@ bool PS1FontProgram::seek_name(Reader& reader, ByteString const& name)
return false;
}
Error PS1FontProgram::error(
ByteString const& message
#ifdef PDF_DEBUG
,
SourceLocation loc
#endif
)
{
#ifdef PDF_DEBUG
dbgln("\033[31m{} Type 1 font error: {}\033[0m", loc, message);
#endif
return Error { Error::Type::MalformedPDF, message };
}
}

View file

@ -23,6 +23,14 @@ public:
static PDFErrorOr<NonnullRefPtr<Type1FontProgram>> create(ReadonlyBytes const&, RefPtr<Encoding>, size_t cleartext_length, size_t encrypted_length);
private:
static Error error(
ByteString const& message
#ifdef PDF_DEBUG
,
SourceLocation loc = SourceLocation::current()
#endif
);
PDFErrorOr<void> parse_encrypted_portion(ByteBuffer const&);
PDFErrorOr<Vector<ByteBuffer>> parse_subroutines(Reader&) const;
static PDFErrorOr<Vector<float>> parse_number_array(Reader&, size_t length);

View file

@ -136,14 +136,14 @@ void Type1FontProgram::consolidate_glyphs()
}
}
PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes const& data, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines, GlyphParserState& state, bool is_type2)
ErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes const& data, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines, GlyphParserState& state, bool is_type2)
{
// Type 1 Font Format: https://adobe-type-tools.github.io/font-tech-notes/pdfs/T1_SPEC.pdf (Chapter 6: CharStrings dictionary)
// Type 2 Charstring Format: https://adobe-type-tools.github.io/font-tech-notes/pdfs/5177.Type2.pdf
auto push = [&](float value) -> PDFErrorOr<void> {
auto push = [&](float value) -> ErrorOr<void> {
if (state.sp >= state.stack.size())
return error("Operand stack overflow");
return AK::Error::from_string_literal("Operand stack overflow");
state.stack[state.sp++] = value;
return {};
};
@ -260,9 +260,9 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
// Parse the stream of parameters and commands that make up a glyph outline.
for (size_t i = 0; i < data.size(); ++i) {
auto require = [&](unsigned num) -> PDFErrorOr<void> {
auto require = [&](unsigned num) -> ErrorOr<void> {
if (i + num >= data.size())
return error("Malformed glyph outline definition");
return AK::Error::from_string_literal("Malformed glyph outline definition");
return {};
};
@ -299,7 +299,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
i += 2;
TRY(push(a));
} else {
return error("CFF Subr command 28 only valid in type2 data");
return AK::Error::from_string_literal("CFF Subr command 28 only valid in type2 data");
}
} else {
// Not a parameter but a command byte.
@ -389,7 +389,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
case CallGsubr:
if (!is_type2)
return error(ByteString::formatted("CFF Gsubr only valid in type2 data"));
return AK::Error::from_string_literal("CFF Gsubr only valid in type2 data");
[[fallthrough]];
case CallSubr: {
Vector<ByteBuffer> const& subroutines = v == CallSubr ? local_subroutines : global_subroutines;
@ -410,11 +410,11 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
}
if (static_cast<size_t>(subr_number) >= subroutines.size())
return error("Subroutine index out of range");
return AK::Error::from_string_literal("Subroutine index out of range");
auto const& subr = subroutines[subr_number];
if (subr.is_empty())
return error("Empty subroutine");
return AK::Error::from_string_literal("Empty subroutine");
TRY(parse_glyph(subr, local_subroutines, global_subroutines, state, is_type2));
break;
@ -483,7 +483,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
switch ((OtherSubrCommand)othersubr_number) {
case EndFlex: {
if (n != 3)
return error("Unexpected argument code for othersubr 0");
return AK::Error::from_string_literal("Unexpected argument code for othersubr 0");
auto y = pop();
auto x = pop();
@ -512,14 +512,14 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
}
case StartFlex:
if (n != 0)
return error("Unexpected argument code for othersubr 1");
return AK::Error::from_string_literal("Unexpected argument code for othersubr 1");
state.flex_feature = true;
state.flex_index = 0;
state.sp = 0;
break;
case AddFlexPoint:
if (n != 0)
return error("Unexpected argument code for othersubr 2");
return AK::Error::from_string_literal("Unexpected argument code for othersubr 2");
// We do this directly in move_to().
state.sp = 0;
break;
@ -633,7 +633,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
default:
dbgln("Unhandled command: 12 {}", data[i]);
return error("Unhandled command");
return AK::Error::from_string_literal("Unhandled command");
}
break;
}
@ -747,19 +747,4 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
return state.glyph;
}
Error Type1FontProgram::error(
ByteString const& message
#ifdef PDF_DEBUG
,
SourceLocation loc
#endif
)
{
#ifdef PDF_DEBUG
dbgln("\033[31m{} Type 1 font error: {}\033[0m", loc, message);
#endif
return Error { Error::Type::MalformedPDF, message };
}
}

View file

@ -11,7 +11,6 @@
#include <LibGfx/Font/Font.h>
#include <LibGfx/Path.h>
#include <LibPDF/Encoding.h>
#include <LibPDF/Error.h>
namespace PDF {
@ -90,15 +89,7 @@ protected:
bool is_first_command { true };
};
static PDFErrorOr<Glyph> parse_glyph(ReadonlyBytes const&, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines, GlyphParserState&, bool is_type2);
static Error error(
ByteString const& message
#ifdef PDF_DEBUG
,
SourceLocation loc = SourceLocation::current()
#endif
);
static ErrorOr<Glyph> parse_glyph(ReadonlyBytes const&, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines, GlyphParserState&, bool is_type2);
void set_encoding(RefPtr<Encoding>&& encoding)
{
@ -110,7 +101,7 @@ protected:
m_font_matrix = move(font_matrix);
}
PDFErrorOr<void> add_glyph(DeprecatedFlyString name, Glyph&& glyph)
ErrorOr<void> add_glyph(DeprecatedFlyString name, Glyph&& glyph)
{
TRY(m_glyph_map.try_set(move(name), move(glyph)));
return {};