fix(pdf): place text by its own font, decode jpeg 2000, and clip to the crop box - #689
Merged
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f885b47b15
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Base automatically changed from
fix/pdf-content-stream-comments-and-utf16
to
main
August 14, 2026 18:39
…rut does A line block inherits the default font size, and its strut then outranks the run it holds and takes the line box's baseline. Every run sat below the `ascent` its `top` was derived from, the more so the smaller the text - body text by ~4pt at 6pt, which is why a heading looked low in its banner. The block's strut collapses (`font-size:0`), and an embedded face states the ascent and descent the placement assumes, as a substituted one already did. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8PCMZUVxuGstmmgQzEdif
…crop box Three things a manual in the corpus showed against a native viewer. Its photographs were missing: they are `JPXDecode`, which nothing here decoded. `openjpeg` decodes the codestream and the raster takes the same path as any other - subsampled components resampled, a `cdef` alpha kept, sYCC converted. Its cyan read as `#00ffff`. DeviceCMYK went through the naive `(1-c)(1-k)` in three separate places; one `cmyk_to_rgb` now carries pdf.js's fit of Adobe's transform, so a process cyan is one and cmyk black is the dark neutral a viewer paints. Its cover carried text a page-width to the left of the crop box, which a viewer clips and we drew on the backdrop. A page box hides what overflows it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8PCMZUVxuGstmmgQzEdif
… asked Two from review. A page was sized and translated from its media box, so clipping to it left a bleed showing and the page kept a size no viewer shows; the crop box, which falls back to the media box, decides both, and either corner order reads. A JPX codestream's own opacity channel was always applied. `/SMaskInData` says whether it counts at all - it does not by default - and `2` says the colour is premultiplied by it (Table 89). Not taken: routing openjpeg's diagnostics through `Logger`. Its default handlers are `opj_default_callback`, which does nothing, so a malformed codestream writes nothing to stderr. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8PCMZUVxuGstmmgQzEdif
andiwand
force-pushed
the
fix/pdf-text-baseline-cmyk-jpx
branch
from
August 14, 2026 18:43
2aac9d2 to
fab329c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Stacked on #688 — the four new pdfs it adds are what showed all of this, compared page by page against a native viewer.
Text sat too low. A line block inherits the browser's default font size, so its strut — not the run it holds — set the line box's baseline. Every run landed
13px − ascent × font-sizebelow where itstopwas derived for: ~1.7pt for a 9.5pt heading, ~4pt for 6pt body text, which is why a heading looked off-centre in its banner. The block's strut is collapsed (font-size:0) and an embedded@font-facenow states the ascent and descent the placement assumes, as a substituted face already did. Measured against the same page rendered by CoreGraphics: heading centre 70.3% → 58.7% of the banner (viewer: 59.4%); body lines 26% of a banner height off → ~3%.JPEG 2000 images were missing — all 12 image uses in that manual are
JPXDecode, which nothing here decoded. New dependencyopenjpeg/2.5.4(no transitive requirements; one line inconan.lock, no other pin moved) andpdf_jpx.{hpp,cpp}: a memory-stream decode to 8-bit samples, subsampled components resampled, acdefalpha kept as the coverage plane, sYCC converted. The raster then takes the same PNG path as every other codec. CCITT and JBIG2 stay undecodable.CMYK was the naive
(1-c)(1-k), in three separate copies. Onepdf::cmyk_to_rgbnow carries pdf.js's polynomial fit of Adobe's transform: pure cyan#00ffff→#00b9f2(viewer:#00a3da), and cmyk black is the dark neutral Acrobat and Preview paint rather than#000.Content outside the crop box was drawn.
Laserentfernungsmesser_PLEM50_D5places its cover title at-170.08pt, a page-width to the left of a 170.08pt-wide crop box; a viewer clips it, we drew it onto the backdrop next to the page. The page box now hides what overflows it.Test data: the reference output is regenerated on
mainof both output repos andtest/data.cmakemoves to those pins. Only pdf output changed — 4 public and 28 private documents, nothing else drifted. Suite is 876 passing, with new tests for the colour transform and the jpx reject paths.