Skip to content

Fix EPS protocol violations in PostscriptQRCode: remove showpage and setpagedevice from EPS output#694

Merged
Shane32 merged 6 commits intomasterfrom
fix/eps-protocol-compliance
Mar 27, 2026
Merged

Fix EPS protocol violations in PostscriptQRCode: remove showpage and setpagedevice from EPS output#694
Shane32 merged 6 commits intomasterfrom
fix/eps-protocol-compliance

Conversation

@Shane32
Copy link
Copy Markdown
Owner

@Shane32 Shane32 commented Mar 26, 2026

Fix EPS protocol violations in PostscriptQRCode

Problem

When epsFormat = true, the generated output violated the EPS specification (Adobe Technical Note #5002) in multiple ways. Previously only the magic comment on line 1 changed between PS and EPS modes; all other content — including forbidden operators and non-standard structure — was shared.

Changes

Hard violations fixed

Issue Fix
showpage in EPS — forbidden; causes host document to eject a page when the EPS is placed Removed from EPS output; retained in PS output
setpagedevice in EPS — forbidden device-control operator; EPS must be device-independent Removed from EPS output (entire %%BeginFeature/%%EndFeature block)
0 0 moveto outside gsave — leaks current-point state into the surrounding document Moved inside gsave in EPS output
Procedures defined in host dictionary — risks name collisions and dictfull errors when embedded EPS prolog uses 7 dict begin / end to isolate all 7 definitions (csquare, f, b, background, nl, sz, sc) in a private dictionary

Inappropriate DSC comments removed from EPS

Removed Reason
%%DocumentMedia Describes physical paper media; meaningless in an embedded graphic
%%Pages / %%Page Multi-page document markers; EPS describes a single graphic
%%Origin Device-specific physical origin; not applicable to EPS

Non-standard DSC structure replaced in EPS

Before After
%%BeginConstants / %%EndConstants Constants moved into %%BeginSetup / %%EndSetup
%%BeginFunctions / %%EndFunctions %%BeginProlog / %%EndProlog (standard DSC)
%%BeginBody / %%EndBody Removed (non-standard; not needed in EPS)

Minor PS fixes

  • Removed trailing spaces from %%LanguageLevel: 2, %%BeginFunctions, and showpage in the PS templates
  • Removed trailing space from %!PS-Adobe-3.0 magic comment

Implementation

A separate EPS_HEADER, EPS_FUNCTIONS, and EPS_FOOTER constant set was introduced. The PS path (PS_HEADER, PS_FUNCTIONS, PS_FOOTER) is unchanged in behaviour. GetGraphic() selects the correct set based on epsFormat.

The resulting EPS structure is:

%!PS-Adobe-3.0 EPSF-3.0
%%Creator: QRCoder.NET
%%Title: QRCode
%%DocumentData: Clean7Bit
%%BoundingBox: 0 0 <w> <h>
%%LanguageLevel: 2
%%EndComments
%%BeginProlog
7 dict begin
/csquare { ... } def
/f { ... } def
/b { ... } def
/background { ... } def
/nl { ... } def
%%EndProlog
%%BeginSetup
/sz <w> def
/sc <ppm> def
%%EndSetup
gsave
0 0 moveto
sz sz scale
background
grestore
gsave
sc sc scale
0 <n> 1 sub translate
<module data>
grestore
end
%%EOF

Summary by CodeRabbit

  • New Features

    • Enhanced EPS (Encapsulated PostScript) format support with proper DSC compliance and dedicated template handling.
  • Bug Fixes

    • Improved PostScript output formatting and standards compliance; removed extraneous whitespace from generated documents.
    • Fixed PostScript document structure for better compatibility with PostScript interpreters.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Selects PS vs EPS templates at runtime when generating PostScript/EPS output, adds EPS-specific header/functions/footer constants, updates AppendFormat arguments (including viewBox width and points-per-module), and normalizes approved PostScript/EPS test fixtures’ whitespace and DSC blocks.

Changes

Cohort / File(s) Summary
PostScript generator
QRCoder/PostscriptQRCode.cs
Choose between PS/EPS header, functions, and footer templates at runtime; add EPS_HEADER/EPS_FUNCTIONS/EPS_FOOTER; compute estimated capacity from selected templates; update AppendFormat arguments to include cleaned viewBox.Width and pointsPerModule; use selected footer terminator.
Approved test fixtures
QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_simple.approved.txt, ..._size.approved.txt, ..._size_no_quiet_zones.approved.txt, ..._colors.approved.txt, ..._eps.approved.txt
Normalize trailing whitespace and function spacing across PS fixtures; for EPS fixture, move functions/constants into %%BeginProlog/%%BeginSetup, remove some DSC directives, and change termination from showpage to end where appropriate.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • gfoidl
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the main changes—removing EPS protocol violations by eliminating showpage and setpagedevice from EPS output while maintaining PostScript compatibility.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/eps-protocol-compliance

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@QRCoder/PostscriptQRCode.cs`:
- Around line 113-115: The header currently mixes viewBox.Width and
pointsPerModule causing mismatched geometry when input is non-square; in the
sb.AppendFormat call that formats header (the line using
sb.AppendFormat(CultureInfo.InvariantCulture, header, [...]) in
PostscriptQRCode.cs), replace the first argument CleanSvgVal(viewBox.Width) with
CleanSvgVal(pointsPerModule) so both /sz and %%BoundingBox use the square side
length (pointsPerModule) consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 621116e7-c479-4dca-bf0d-d26d995304ed

📥 Commits

Reviewing files that changed from the base of the PR and between 4973174 and 696ad94.

📒 Files selected for processing (6)
  • QRCoder/PostscriptQRCode.cs
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_colors.approved.txt
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_eps.approved.txt
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_simple.approved.txt
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_size.approved.txt
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_size_no_quiet_zones.approved.txt

@Shane32 Shane32 linked an issue Mar 26, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@QRCoder/PostscriptQRCode.cs`:
- Around line 228-256: The EPS prolog currently does "5 dict begin" but defines
seven symbols (csquare, f, b, background, nl, sz, sc), causing dictfull on Level
1 interpreters; change the dictionary capacity to at least 7 (e.g., replace "5
dict begin" with "7 dict begin" or otherwise allocate a dict large enough before
defining csquare, f, b, background, nl and later sz/sc) so all defs (csquare, f,
b, background, nl, sz, sc) can be stored in the same dictionary without raising
dictfull.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 68a9fb5c-646d-4d97-8513-91d5d381f933

📥 Commits

Reviewing files that changed from the base of the PR and between 5b7ca44 and a520e93.

📒 Files selected for processing (2)
  • QRCoder/PostscriptQRCode.cs
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_eps.approved.txt

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
QRCoder/PostscriptQRCode.cs (1)

117-122: Verify format string placeholders align with argument count.

The functions template now receives 9 arguments (indices 0-8), but PS_FUNCTIONS only uses placeholders {0} through {6}. The extra arguments {7} and {8} (viewBox.Width, pointsPerModule) are only consumed by EPS_FUNCTIONS for /sz and /sc. While this works correctly (unused placeholders are simply ignored), it creates a subtle coupling between the two templates.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@QRCoder/PostscriptQRCode.cs` around lines 117 - 122, The AppendFormat call
passes 9 arguments for the variable `functions` even though `PS_FUNCTIONS` only
expects placeholders {0}..{6}, creating a hidden coupling with `EPS_FUNCTIONS`;
fix by ensuring `functions` is formatted with exactly the arguments it
needs—either build separate argument lists for `PS_FUNCTIONS` and
`EPS_FUNCTIONS` or conditionally call sb.AppendFormat with the correct
subset—adjust the call site using `sb.AppendFormat` and the `functions` variable
(and related values CleanSvgVal(...), drawableModulesCount, viewBox.Width,
pointsPerModule) so placeholders and arguments align exactly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_eps.approved.txt`:
- Around line 8-9: The test fixture contains "5 dict begin" but the PostScript
output defines seven names (csquare, f, b, background, nl, sz, sc); update the
fixture to match the corrected dictionary capacity by replacing "5 dict begin"
with "7 dict begin" (or regenerate the fixture from PostscriptQRCode.cs after
you apply the dictionary-size fix) so the dictionary can hold all seven
definitions.

---

Nitpick comments:
In `@QRCoder/PostscriptQRCode.cs`:
- Around line 117-122: The AppendFormat call passes 9 arguments for the variable
`functions` even though `PS_FUNCTIONS` only expects placeholders {0}..{6},
creating a hidden coupling with `EPS_FUNCTIONS`; fix by ensuring `functions` is
formatted with exactly the arguments it needs—either build separate argument
lists for `PS_FUNCTIONS` and `EPS_FUNCTIONS` or conditionally call
sb.AppendFormat with the correct subset—adjust the call site using
`sb.AppendFormat` and the `functions` variable (and related values
CleanSvgVal(...), drawableModulesCount, viewBox.Width, pointsPerModule) so
placeholders and arguments align exactly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b16c5df5-89e5-4959-b7f8-fc93ca9e8e63

📥 Commits

Reviewing files that changed from the base of the PR and between a520e93 and ab32b8c.

📒 Files selected for processing (2)
  • QRCoder/PostscriptQRCode.cs
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_eps.approved.txt

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
QRCoder/PostscriptQRCode.cs (1)

98-136: Consider adding test coverage for epsFormat=true with drawQuietZones=false.

The existing tests cover:

  • epsFormat=true + drawQuietZones=true (default)
  • epsFormat=false + drawQuietZones=false

The combination epsFormat=true + drawQuietZones=false is untested. This would exercise the EPS-specific gsave/0 0 moveto logic with the non-zero offset path, verifying coordinate handling in constrained spaces.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@QRCoder/PostscriptQRCode.cs` around lines 98 - 136, Add a unit test that
calls GetGraphic with epsFormat=true and drawQuietZones=false to exercise the
EPS-specific branch; specifically construct a QrCodeData instance (or use the
existing test helper) and invoke GetGraphic(viewBox, darkColor, lightColor,
drawQuietZones: false, epsFormat: true) and assert the returned string contains
the EPS header/functions patterns (e.g., EPS_HEADER/EPS_FUNCTIONS markers such
as "gsave" and "0 0 moveto") and the expected module output for the reduced
drawableModulesCount (verify presence of "f "/ "b " sequences and that no extra
quiet-zone modules are rendered), ensuring the same helpers/assertions used in
the other tests are reused for consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@QRCoder/PostscriptQRCode.cs`:
- Around line 98-136: Add a unit test that calls GetGraphic with epsFormat=true
and drawQuietZones=false to exercise the EPS-specific branch; specifically
construct a QrCodeData instance (or use the existing test helper) and invoke
GetGraphic(viewBox, darkColor, lightColor, drawQuietZones: false, epsFormat:
true) and assert the returned string contains the EPS header/functions patterns
(e.g., EPS_HEADER/EPS_FUNCTIONS markers such as "gsave" and "0 0 moveto") and
the expected module output for the reduced drawableModulesCount (verify presence
of "f "/ "b " sequences and that no extra quiet-zone modules are rendered),
ensuring the same helpers/assertions used in the other tests are reused for
consistency.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 65c0f5a7-d4f8-41b1-9e9e-7b0c8be5e458

📥 Commits

Reviewing files that changed from the base of the PR and between ab32b8c and 306d3b4.

📒 Files selected for processing (2)
  • QRCoder/PostscriptQRCode.cs
  • QRCoderTests/PostscriptQRCodeRendererTests.can_render_postscript_qrcode_eps.approved.txt

@Shane32
Copy link
Copy Markdown
Owner Author

Shane32 commented Mar 26, 2026

Final review from ChatGPT regarding the created EPS file:

The only real caution is that %%LanguageLevel: 2 may be unnecessary, and the file uses an opaque white background

@Shane32 Shane32 merged commit 443d5a1 into master Mar 27, 2026
13 of 14 checks passed
@Shane32 Shane32 deleted the fix/eps-protocol-compliance branch March 27, 2026 12:32
@Shane32 Shane32 added this to the 1.8.0 milestone Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix EPS file creation

1 participant