* Keep Quick Mask's empty start and Select All apart (#2743)
Quick Mask stored "no selection" as an all-white mask, the same as Select
All. With Color Indicates Selected Areas that white was coloured over the
whole canvas, and leaving Quick Mask turned any all-white mask (a real
Select All too) into no selection.
The document now records that Quick Mask was entered with no selection.
The empty mask is white for Masked Areas and black for Selected Areas, so
neither shows colour; switching the option on an untouched empty mask
keeps it empty. On exit only that untouched white start becomes no
selection, so Select All survives the round trip. The flag is saved with
the document.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Quick Mask tests: pass the active layer to channel_view::render (new main signature)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Fabio Lussi <198260595+itrycodinganditsbad@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
PNG tEXt/zTXt/iTXt entries (and TIFF ASCII tags) were dropped on open with a warning. The
document now keeps them in Metadata.text, the .pcraft manifest saves them (older files still
load), and PNG/TIFF saves write them back; Metadata: None and embed_metadata=false strip them,
and PSD/PSB and palette PNG exports warn that they are dropped. XMP in a tEXt or zTXt chunk is
read as XMP too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Smart objects keep their four-corner (Distort / Perspective) placement
A smart object's placement was an affine transform, so a perspective
placement lost its fourth corner: a mockup PSD's distorted screen looked
right on open (Photoshop's cached pixels) but re-rendered as a
parallelogram after Edit Contents → Save.
- SmartObject gains `perspective`, the full projective map (source px →
document px); `transform` keeps its affine approximation
- Re-renders go through it (place_source_projective), as do moves,
canvas rotations and edit.transform, so Distort / Perspective now work
on smart objects instead of being refused
- PSD import reads the quad (nonAffineTransform / Trnf) and export writes
it back; .pcraft stores the field (absent for affine placements)
- Test: a distorted smart object survives Edit Contents → Save
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Smart objects: warp maps through a distorted placement; perspective round-trip tests
Warp handles and stored warps on a Distort / Perspective smart object go through its full
projective placement (smart_cmds::placement) instead of the affine approximation, so they sit
on the distorted corners. Tests: SoLd perspective round trip and quad_moved (io), a perspective
smart layer in the .pcraft rich_doc, warp on a distorted smart object (engine). Comments no
longer name another product.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Jason Short <3344856+jason4short@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Adjustments: full parameter sets for every kind, Hue/Sat ranges, CMYK/Lab tone channels
- doc: Hue/Saturation gains six colour ranges (HueRange), Gradient Map a dither flag,
Levels/Curves a ToneSpace (RGB, CMYK inks + black, Lab) for mode-native channels.
- engine: new adjust_params module (from_params over a base / to_params) used by
image.adjustments.*, layer.newAdjustmentLayer.* and layer.setAdjustment. Curves,
Color Balance, Channel Mixer, Black & White, Gradient Map and Photo Filter now honour
their params; bad params are BadParams errors; setAdjustment merges (empty = reset).
- compose/gpu: hue-range tables, CMYK/Lab tone channels (CPU; GPU falls back), dithered
Gradient Map, Black & White from grey/secondary/primary parts; GPU parity extended.
- io: hue2 ranges, grdm dither, CMYK/Lab Levels/Curves records round-trip.
- destructive adjustments use the document's tone transfer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Adjustments UI: one editor per kind for Properties and Image › Adjustments dialogs
- adjust_editors: Brightness/Contrast (legacy), Levels and Curves (per channel in RGB, Gray,
CMYK and Lab, histogram behind), Exposure, Vibrance, Hue/Saturation (master + six ranges with
draggable range sliders, colorize, before/after spectrum), Color Balance (tones, preserve
luminosity), Black & White (six weights, tint colour), Photo Filter (presets or colour,
density), Channel Mixer (outputs, constant, monochrome, total), Posterize, Threshold
(histogram), Gradient Map (stops, presets, reverse, dither). Replaces the M7 placeholder.
- Properties previews live (GPU) while a control moves and commits one setAdjustment per gesture.
- adjust_dialog: Image › Adjustments opens the same editor modally; the canvas previews the
real command on the proxy, Preview checkbox, OK = one history step, Cancel leaves the doc.
- Curves (#43): hit-test at the press origin, Delete/Backspace removes the selected point when
the graph has focus, Cmd/Ctrl-click removes, dragging off removes (and back on restores),
arrows nudge; endpoints and the last two points stay; pressing the gradient bars does nothing.
- tone: histograms per channel space, of the image below a layer or of the target layer alone.
- kittests: every adjustment layer kind edited through the Properties panel with real input at
8/16/32-bit RGB, Gray, CMYK and Lab (#12); Curves point interactions; dialog preview/OK/Cancel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* io tests: adjustment round trip covers the new Levels/Curves/Hue-Sat/Gradient Map fields
#60's round-trip tests predate #68's doc-model additions (tone space and black channel,
Hue/Saturation ranges, Gradient Map dither); fill them with their defaults.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
CI's `cargo fmt --all -- --check` has failed on every run because the
repo had no rustfmt config and was never formatted. Use the same settings
as EffectCraft/FilmCraft (max_width 160, use_small_heuristics Max), which
also keeps the churn small. Formatting only; no code changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>