A type render spends most of its time after the glyphs are drawn: composing each
colour's coverage over the premultiplied accumulator, dividing it back to straight
colour, and converting the tile bytes. All three are per pixel - no pixel reads a
slot another wrote - so they ran one after another on one core for no reason.
Measured on a 3.75 MP paragraph (4000 characters, 14 pt at 300 dpi, 1851 glyphs),
release, Windows 11, i5-10300H: rasterize 98.3-103.9 ms before, 60.3-61.8 ms after
(1.6-1.7x). Whole-render stage profile before: ink rect 4.1, draw 18.6-22.9, prefix
sum 7.0-8.1, composite 22.6-33.4, unpremultiply 11.2-14.0, write_region 23.8, prune
3.1 ms.
The glyph drawing, the winding prefix sum and the ink-rect pass stay on one thread:
the first two carry a running accumulator across pixels, and the band split that
would keep them bit-identical costs a second glyph traversal per band.
Native only (rayon, as the other crates): the web build keeps the serial loops.
`blocks` and `fnv` exist only for `harris_and_describe_hashes_recorded_from_the
_serial_code`, which is `#[cfg(all(target_os = "linux", target_arch =
"x86_64"))]` because the hashes it compares against go through the platform's
hypot / ln / cos / atan2 / sin_cos. Everywhere else the test is compiled out and
the two helpers are left unused, so `-D warnings` fails on `dead_code`:
error: function `blocks` is never used crates/algo/src/features.rs:704
error: function `fnv` is never used crates/algo/src/features.rs:708
They now carry the same cfg as the only thing that calls them.
CI's matrix is ubuntu-latest and windows-latest and runs clippy on both, so this
fails the Windows leg as much as a local run on macOS: `target_os = "linux"` is
false for both.
#5344 added the export_presets field to Persisted; #5616 rewrote load_presets_json to read each set with take() and its Persisted initializer lacked the new field, so main stopped compiling (E0063 at presets/mod.rs:180). Read export_presets the same way as the other sets; the existing load step and round-trip test cover it.
Co-authored-by: 00xJ0 <56056764+00xJ0@users.noreply.github.com>
The crop tool's W x H x Resolution mode converted points and picas at a
fixed 72 pt/in, while Image Size, Canvas Size (#5757), the rulers, Info
and the shape dialog use Preferences > Units & Rulers > Point/Pica Size.
With Traditional (72.27), W "72 pt" x H "1 in" at 300 ppi cropped to
300 x 300 instead of 299 x 300.
target() and ratio() now take the points per inch, and the callers
(commit_params, preset_ratio, fit_frame) pass the preference.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stamp Down rebuilt the layer below from scratch and copied only its id,
name, blend mode, visibility and locks, so a clipped layer came back
unclipped (its pixels showing outside the clip base) and lost its colour
label and link. Photoshop writes the stamp into the existing layer; keep
the three properties as Merge Down already does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A finite f64 like 1e39 became inf on `as f32`: zoom jumped to 100%,
rotation reset to 0, dockWidth fell to its minimum and center was stored
as [inf, 0], all with ok:true. A new f32_field (same filter as
rotate_view's finite_number) rejects these in the validate phase, so a
rejected call changes nothing. num_field stays as is: pointer events
must keep accepting huge coordinates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>