Layers: a layer or gap color with an alpha part is refused instead of losing its alpha

layer.setProps, layer.new, layer.newSublayer and livePaint.gapOptions read
an 8-digit hex color such as #ff000080 as #ff0000 and set it without its
alpha. They now refuse it with the error a bad color already gets, and
change nothing. #rgba was already refused. #rrggbb, #rgb, a preset index
and a preset name are read as before.
This commit is contained in:
dotCooCoo
2026-11-04 18:29:17 +07:00
committed by bflatastic
parent 12508e6c60
commit d79f5ccb75
6 changed files with 62 additions and 6 deletions
+1 -1
View File
@@ -108,7 +108,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Gap Options",
[],
None,
"{id?, ids?: [id…] (instead of id; default: the selected Live Paint groups), detect?: bool (Gap Detection: paint stops at gaps up to size wide), size?: \"small\" (3 pt) | \"medium\" (6 pt) | \"large\" (12 pt) | pt (custom, over 0 up to 72) (Paint Stops At), color?: #rrggbb or a layer color's name such as \"Red\" (Gap Preview Color), closeGaps?: bool (add an unpainted path across each gap up to size wide to the group's paths)} set the Gap Options of Live Paint groups (what is not given stays as it was; a group starts with detect false, small and Red) and make their faces again, keeping their paint → {ids, faces, gaps: [[x0,y0,x1,y1]…] (the gaps up to size wide that no path closes, from a loose end of a path to where it closes to; detect closes them for paint), closed (paths added)}",
"{id?, ids?: [id…] (instead of id; default: the selected Live Paint groups), detect?: bool (Gap Detection: paint stops at gaps up to size wide), size?: \"small\" (3 pt) | \"medium\" (6 pt) | \"large\" (12 pt) | pt (custom, over 0 up to 72) (Paint Stops At), color?: #rrggbb or a layer color's name such as \"Red\" (Gap Preview Color; a hex color with an alpha part, #rrggbbaa or #rgba, is an error), closeGaps?: bool (add an unpainted path across each gap up to size wide to the group's paths)} set the Gap Options of Live Paint groups (what is not given stays as it was; a group starts with detect false, small and Red) and make their faces again, keeping their paint → {ids, faces, gaps: [[x0,y0,x1,y1]…] (the gaps up to size wide that no path closes, from a loose end of a path to where it closes to; detect closes them for paint), closed (paths added)}",
has_selection_or_ids,
lp_gap_options
),
+10 -3
View File
@@ -83,7 +83,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Layer Options…",
["Window", "Layers"],
None,
"{ids?|id? (default: the highlighted rows, else the current layer), name? (with prefs.identifyObjectsBy xmlId: a valid XML ID, stored as the object name), visible?, locked?, template?, printable?, preview?, dimImages?: 0..100|false, color?: index 0..26|\"#rrggbb\"|preset name} Layer Options; rows that are not layers take name, visible and locked. Template on also locks the layer and dims its images to 50% (unless given); off unlocks it and stops dimming. One undo step",
"{ids?|id? (default: the highlighted rows, else the current layer), name? (with prefs.identifyObjectsBy xmlId: a valid XML ID, stored as the object name), visible?, locked?, template?, printable?, preview?, dimImages?: 0..100|false, color?: index 0..26|\"#rrggbb\"|preset name (a hex color with an alpha part, #rrggbbaa or #rgba, is an error)} Layer Options; rows that are not layers take name, visible and locked. Template on also locks the layer and dims its images to 50% (unless given); off unlocks it and stops dimming. One undo step",
has_doc,
set_props
),
@@ -297,7 +297,8 @@ pub(crate) fn make_layer(d: &mut Document, name: Option<&str>) -> Node {
NewLayers::of(d).make(d, name)
}
/// A layer colour: a preset index (0–26), `#rrggbb` or a preset's name (any case).
/// A layer colour: a preset index (0–26), `#rrggbb` or a preset's name (any case). A hex color
/// with an alpha part (`#rrggbbaa` or `#rgba`) is an error.
pub(super) fn layer_color_param(v: &Value) -> std::result::Result<LayerColor, String> {
match v {
Value::Number(n) => match n.as_u64() {
@@ -308,7 +309,13 @@ pub(super) fn layer_color_param(v: &Value) -> std::result::Result<LayerColor, St
if let Some(i) = LAYER_COLORS.iter().position(|(name, _)| name.eq_ignore_ascii_case(s.trim())) {
return Ok(LayerColor::Preset(i as u8));
}
let c = vectorcraft_color::Color::from_hex(s).ok_or_else(|| format!("`{s}` is not a colour (#rrggbb or a preset name)"))?;
let refused = || format!("`{s}` is not a colour (#rrggbb or a preset name)");
// `Color::from_hex` reads `#rrggbbaa` as `#rrggbb`, dropping the alpha.
let digits = s.trim();
if digits.strip_prefix('#').unwrap_or(digits).len() == 8 {
return Err(refused());
}
let c = vectorcraft_color::Color::from_hex(s).ok_or_else(refused)?;
let [r, g, b, _] = c.to_rgba8(1.0);
Ok(LayerColor::Custom([r, g, b]))
}