mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
* fix(render): sampled functions index a flat sample array (vendored hayro-interpret patch 31) A Type 0 sampled function kept its samples in a HashMap keyed by each point of its /Size grid (two SmallVecs per key, SipHash), and the renderer builds a shading's functions again every time it is painted, so every paint hashed one insert per sample. A 2,097,152-sample ramp painted 30 times took 38 s; the pdf.js corpus's bug1721218 (InDesign) spent most of a 1.5 s page on it. The samples now stay in stream order in one Vec, and a grid point is found by strides (first input fastest). The interpolation keeps the same recursion and arithmetic, so results are bit for bit the same, and a point the stream ended before still gives no value. The repeated-paint page draws in well under a second. The maximum sample value no longer computes 2^32 in a u32 (a panic with overflow checks on at 32 bits per sample). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MoEx9Nj8KC4WKDcf5YaokQ * fix(render): one decode of an image serves every size it is drawn at (vendored hayro-interpret patch 32) The decoded-image cache (patch 24) keyed each decode by the size the image is drawn at, but only the JPX filter decodes a reduced resolution for a size: every other filter decodes the whole image. So a JPEG or Flate scan missed the cache at every zoom step, was decoded again, and was kept once per zoom level. The key now carries the target size only when JPX decodes the image, its /SMask or its /Mask (read from /Filter or /F, erring towards keeping the target). `InterpreterCache::decoded_image_decodes` counts the cache's decodes; the new test draws a Flate image at five sizes and sees one decode, and a copy whose soft mask is JPX-encoded still decodes per size. Both assertions fail with the old keying. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MoEx9Nj8KC4WKDcf5YaokQ * fix(render): patch meshes copy their vertices' colours less (vendored hayro-interpret patch 33) A Coons or tensor-product patch is drawn as 722 triangles over a 20 x 20 grid of points, and every vertex's colours (a SmallVec) were produced or copied up to five times: each grid cell interpolated its four corners itself (1,444 interpolations a patch for 400 points), cloned all six vertices of its two triangles, and the mesh sampler cloned each vertex again to move the triangle into device space. Profiling page 8 of the annual report in #1584 put a quarter of its time in those clones. Each grid point's colours are now interpolated once, a cell's second triangle takes the vertices its first copied, and the sampler moves a patch's freshly made triangles instead of copying them (`TriangleSampler::sample_owned`; a free-form triangle mesh, which the shading keeps, is still copied). The same inputs give the same values: rendering the first three pages of every pdf.js corpus file is byte for byte the same. Release build, Linux: report page 8 773 -> 696 ms, personwithdog.pdf 149 -> 129 ms, issue13520.pdf 104 -> 87 ms. The new test pins the colours near each corner, at the centre and between them for a Coons and a tensor-product patch (taken before the change); swapping two vertices' grid points makes it fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MoEx9Nj8KC4WKDcf5YaokQ * docs: roadmap entries for faster sampled functions, image decodes and patch meshes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MoEx9Nj8KC4WKDcf5YaokQ --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>