Skip to content

Commit

Permalink
LibPDF: Allow and skip comments in PostScriptCalculatorFunction
Browse files Browse the repository at this point in the history
The PDF spec doesn't explicitly mention supporting comments here,
but other implementations (I checked Preview.app and PDFium) seem
to allow and skip them, so follow suit.
  • Loading branch information
nico committed Feb 25, 2025
1 parent 4f74c82 commit 137fc03
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
36 changes: 36 additions & 0 deletions Tests/LibPDF/TestPDF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,42 @@ TEST_CASE(postscript)
check_evaluate("{ pop }"sv, { 8.0f, 1.0f, 0.5f }, { 8.0f, 1.0f });
check_evaluate("{ 3 1 roll }"sv, { 0.5f, 1.0f, 2.0f }, { 2.0f, 0.5f, 1.0f });
check_evaluate("{ 3 -1 roll }"sv, { 0.5f, 1.0f, 2.0f }, { 1.0f, 2.0f, 0.5f });

// Comments
check_evaluate(R"(
% comment
{
% comment
1
% comment
{
% comment
1
% comment
}
% comment
if
% comment
{
% comment
1
% comment
}
% comment
{
% comment
0
% comment
}
ifelse
% comment
}
% comment
)"sv,
{}, { 1.0f });
}

TEST_CASE(render)
Expand Down
29 changes: 25 additions & 4 deletions Userland/Libraries/LibPDF/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ class PostScriptCalculatorFunction final : public Function {
Vector<Token> if_false;
};

static bool skip_whitespace_and_comments(Reader&);
static PDFErrorOr<Vector<Token>> parse_postscript_calculator_function(Reader&, Vector<NonnullOwnPtr<IfElse>>&);

struct Stack {
Expand Down Expand Up @@ -639,22 +640,42 @@ Optional<PostScriptCalculatorFunction::OperatorType> PostScriptCalculatorFunctio
return {};
}

bool PostScriptCalculatorFunction::skip_whitespace_and_comments(Reader& reader)
{
bool did_skip = false;
while (!reader.done()) {
if (reader.consume_whitespace()) {
did_skip = true;
continue;
}
if (reader.matches('%')) {
did_skip = true;
reader.consume();
while (!reader.consume_eol())
reader.consume();
continue;
}
break;
}
return did_skip;
}

PDFErrorOr<Vector<PostScriptCalculatorFunction::Token>>
PostScriptCalculatorFunction::parse_postscript_calculator_function(Reader& reader, Vector<NonnullOwnPtr<IfElse>>& if_elses)
{
// Assumes valid syntax.
reader.consume_whitespace();
skip_whitespace_and_comments(reader);
if (!reader.consume('{'))
return Error { Error::Type::MalformedPDF, "PostScript expected '{'" };

Vector<PostScriptCalculatorFunction::Token> tokens;
while (!reader.matches('}')) {
if (reader.consume_whitespace())
if (skip_whitespace_and_comments(reader))
continue;

if (reader.matches('{')) {
auto if_true = TRY(parse_postscript_calculator_function(reader, if_elses));
reader.consume_whitespace();
skip_whitespace_and_comments(reader);
if (reader.matches("if")) {
reader.consume(2);
tokens.append({ OperatorType::If, (int)if_elses.size() });
Expand All @@ -664,7 +685,7 @@ PostScriptCalculatorFunction::parse_postscript_calculator_function(Reader& reade

VERIFY(reader.matches('{'));
auto if_false = TRY(parse_postscript_calculator_function(reader, if_elses));
reader.consume_whitespace();
skip_whitespace_and_comments(reader);

if (reader.matches("ifelse")) {
reader.consume(6);
Expand Down

0 comments on commit 137fc03

Please sign in to comment.