Name the frame's category for the decision, not the maths

`Attribute::Geometry` becomes `Attribute::Compose`, and `film_sim` moves
from `[tone, colour]` to `[effect]`.

Two categories were doing the wrong job. "Geometry" describes what crop,
straighten and the quarter turns do to coordinates — but it describes lens
distortion correction exactly as well, and that is not a compositional
choice at all. Naming the attribute for the photographer's decision is what
separates it from `Optics`: one is what the lens did, the other is what
they chose. The maths the two have in common is not the thing worth
filing them under.

A film stock declared both `tone` and `colour`, so "Kodachrome" appeared in
the Light group beside exposure and again in Colour beside white balance —
two places, neither of which is where anyone looks for it. It is neither:
`Effect` is defined in this same file as "applied rather than corrected — a
look, not a fix", which is what a stock is. That it moves tone and colour
is true of every look, and is not what the attribute is for.

`from_name` still accepts "geometry" on the way in. That string is
persisted in `develop.copy_attributes`, and an entry it fails to parse is
not an error — `presets::scope_for` logs it and drops it — so without the
alias an existing settings file would have quietly narrowed what a paste
carries. `name` writes the current spelling, so the file migrates itself
the first time it is saved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-05 14:34:03 +02:00
co-authored by Claude Opus 5
parent 95e854b5a2
commit 8e7b1350bf
14 changed files with 55 additions and 34 deletions
+21 -6
View File
@@ -580,8 +580,15 @@ pub enum Attribute {
/// Corrections for the lens that took the photograph: distortion,
/// chromatic aberration, vignetting.
Optics,
/// The shape of the frame: crop, straighten, rotation, flips.
Geometry,
/// How the frame is composed: crop, straighten, rotation, flips.
///
/// Named for the decision rather than for the maths. The lens corrections
/// are geometry too — distortion moves pixels exactly as a straighten
/// does — and lumping the two together would file a correction the
/// photographer never asked for beside a choice that is the whole reason
/// they opened the photograph. [`Self::Optics`] is what the lens did;
/// this is what they decided.
Compose,
/// Applied rather than corrected — a look, not a fix.
Effect,
}
@@ -598,7 +605,7 @@ impl Attribute {
Attribute::Colour,
Attribute::Detail,
Attribute::Optics,
Attribute::Geometry,
Attribute::Compose,
Attribute::Effect,
];
@@ -613,7 +620,7 @@ impl Attribute {
Self::Colour => "attr.colour",
Self::Detail => "attr.detail",
Self::Optics => "attr.optics",
Self::Geometry => "attr.geometry",
Self::Compose => "attr.compose",
Self::Effect => "attr.effect",
})
}
@@ -630,7 +637,7 @@ impl Attribute {
Self::Colour => "colour",
Self::Detail => "detail",
Self::Optics => "optics",
Self::Geometry => "geometry",
Self::Compose => "compose",
Self::Effect => "effect",
}
}
@@ -642,7 +649,15 @@ impl Attribute {
"colour" => Self::Colour,
"detail" => Self::Detail,
"optics" => Self::Optics,
"geometry" => Self::Geometry,
"compose" => Self::Compose,
// The name this attribute was persisted under before it was
// called Compose. Settings written by an older build carry it in
// `develop.copy_attributes`, and `from_name` returning `None`
// there does not fail loudly — `presets::scope_for` logs and drops
// the entry, silently narrowing what a paste carries. Accepted on
// the way in only; `name` writes the current spelling, so a
// settings file rewrites itself the first time it is saved.
"geometry" => Self::Compose,
"effect" => Self::Effect,
_ => return None,
})