PDF stage 4.4: PDF function evaluator + colour spaces#562
Conversation
Shared prerequisite for proper colour (and, later, shadings): evaluate PDF functions and resolve non-device colour spaces to RGB at emit time. 4.4a — function evaluator (`pdf_function`, ISO 32000-1 7.10): - type 2 (exponential interpolation), type 3 (stitching), type 0 (sampled, multilinear interpolation over an m-dimensional grid), and type 4 (a PostScript calculator stack machine: arithmetic, comparison, boolean, stack and `if`/`ifelse` control). Inputs clip to `/Domain`, outputs to `/Range`. Pure and unit-tested in isolation via a small resolve/load-stream context. 4.4b — colour spaces (`pdf_color`, 8.6): - resolve `/ColorSpace` resources and the `cs`/`CS`/`sc`/`scn`/`SC`/`SCN` operators (previously only the device operators were modelled). Convert to sRGB at emit time: ICCBased (by `/Alternate` or component count), Cal*/Lab (Lab → XYZ → sRGB), Indexed (palette lookup), Separation/DeviceN (tint transform via 4.4a). Overprint ignored. - The colour operators that need the resources are handled in `pdf_page_extractor` (which has them); the device operators stay in `GraphicsState::execute` and now clear any active non-device space. The active space rides on `GraphicsState::Color`, so `q`/`Q` scope it. Tests: each function type against worked vectors (incl. domain clipping, ifelse); each colour space → expected RGB (incl. Lab extremes, an Indexed palette, a Separation tint); and end-to-end `cs`/`scn` resolution through the extractor. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7Lp7cZPX84gvGmaGA6bHq
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19ef43757f
ℹ️ 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".
| default: | ||
| return std::vector<double>( | ||
| static_cast<std::size_t>(std::max(components, 1)), 0.0); |
There was a problem hiding this comment.
Preserve black when aliasing DeviceCMYK resources
When a /ColorSpace resource aliases /DeviceCMYK (for example /CS1 /DeviceCMYK) and content selects it with /CS1 cs, this path initializes the color via ColorSpaceDef::initial_components(), which returns four zero components. to_rgb({0,0,0,0}) is white, while the direct /DeviceCMYK cs branch in set_color_space explicitly initializes {0,0,0,1} as black, so the same color space renders differently whenever a path is painted after selecting the resource alias before an scn value is supplied.
Useful? React with 👍 / 👎.
Stage 4.4: the PDF function evaluator and colour-space resolution — a shared prerequisite for faithful colour (and, later, shadings). Stacked on #561 (4.3).
4.4a — function evaluator (
pdf_function, ISO 32000-1 7.10)if/ifelse)./Domain, outputs to/Range. Pure and unit-testable via a small resolve/load-stream context.4.4b — colour spaces (
pdf_color, 8.6)/ColorSpaceresources and thecs/CS/sc/scn/SC/SCNoperators (previously only the device operators were modelled). Convert to sRGB at emit time: ICCBased (by/Alternateor component count), Cal*/Lab (Lab → XYZ → sRGB), Indexed (palette lookup), Separation/DeviceN (tint transform via 4.4a). Overprint ignored.pdf_page_extractor(which has theResources); the device operators stay inGraphicsState::executeand now clear any active non-device space. The active space rides onGraphicsState::Color, soq/Qscope it.Tests
Each function type against worked vectors (incl. domain clipping,
ifelse); each colour space → expected RGB (Lab extremes, an Indexed palette, a Separation tint); end-to-endcs/scnresolution through the extractor. Full suite green.🤖 Generated with Claude Code