Swatch libraries: Gradients › Holographic adds iridescent foil and glow gradients

Window › Swatch Libraries › Gradients gains Holographic, after Organic
Fades: seven foils (opaque linear gradients of six narrow pastel and
pearl bands with off-center midpoints) and seven glows (radial
gradients from a bright center out to a clear edge), all mixed with the
Perceptual method. They also list in the Swatches panel's library menu,
swatch.library.list/get/add and the Gradient panel's Presets.

The names, colors and stops are VectorCraft's own. A saved preset that
already uses one of the new names is renamed with the first free number
when the preferences load.

Docs: docs/target-app-parity.md Swatches line, ROADMAP.
This commit is contained in:
dotCooCoo
2026-11-11 23:19:16 -08:00
parent 5eefe7d1c5
commit fc8a7e46c6
33 changed files with 242 additions and 3 deletions
+1
View File
@@ -138,6 +138,7 @@ Ranked; detail in [docs/roadmap.md](docs/roadmap.md) and [docs/gaps.md](docs/gap
- 2026-10-31: Export for Screens works as the reference app's dialog: Artboards and Assets tabs with a grid or list of thumbnails, Clear Selection and Prefix, Create Sub-folders by Scale or Format (on by default), Export PDFs As Single File (the chosen artboards as one PDF's pages, `pdfs: "single"`) or Multiple Files, iOS and Android rows, format presets in a ☰ menu, and a count of the files the export writes (#4895). About 55 community PRs and fixes landed the same day: Find Font, Replace Font, Outline Stroke and Expand leave hidden and locked art alone (with a warning); DXF export writes LINE and ELLIPSE entities and outlines only the strokes a CAD line can't draw; Blob Brush Angle and Roundness; Shift-constrained Perspective Selection; Grid Repeat Options Preview; a gradient mesh from a file budgeted at about a million quads; width-profile strokes keep their shape zoomed out; `.ai`/EPS import fidelity (area type, envelopes, transparency in dictionaries, character styles); PDF import finds hyphenated and CMap-suffixed font names; Windows renders follow the process's core affinity; Enter or Escape in a floating panel's field no longer reaches the canvas (#4803); Properties shows Blend Options for any selected blend (#4817); Artwork Cleanup finds doubled type (#4835) and joins stacked lines into one object (Join Point Text, #4826). Headline numbers unchanged.
- 2026-10-31: Arrange Tools, a built-in add-on (Object › Plug-ins › Arrange Tools): Arrange in Grid lays the selected objects out in rows and columns, a row or a column with gaps, from the selection's top-left or centred on the artboard; Swap Objects swaps two objects' places (and, with Swap Objects and Sizes, their sizes); Replace with Top Object puts a copy of the topmost selected object in place of each of the others, kept, stretched or fitted in proportion; Set Size of Each gives every selected object an exact width and/or height about a reference point; Zoom to Selection fits the view to the selection. Each is one undo step with a previewed dialog where it has options. A VectorCraft addition: headline numbers unchanged.
- 2026-11-11: Window › Swatch Libraries › Gradients › Organic Fades: fifteen soft fades (ten linear, five radial) through three to five unevenly spaced stops with off-center midpoints, mixed with the Perceptual method, that thin out to transparent at the end of a linear one and at the edge of a radial one; they also list in the Swatches panel's library menu, `swatch.library.list` and the Gradient panel's Presets.
- 2026-11-11: Window › Swatch Libraries › Gradients › Holographic: seven foils (opaque linear gradients of six narrow pastel and pearl bands with off-center midpoints) and seven glows (radial gradients from a bright center out to a clear edge), mixed with the Perceptual method; they also list in the Swatches panel's library menu, `swatch.library.list` and the Gradient panel's Presets.
- 2026-10-30: Gradient panel presets: a Presets menu applies one of the built-in gradient libraries' presets (grouped by theme) or a saved one to the gradient behind the active proxy, keeping its placement, as one undo step; the panel menu saves the current gradient as a preset, kept with the preferences, and deletes saved ones (`gradient.presets.list/apply/save/delete`).
- 2026-10-23: Pathfinder › Trap: the Pathfinder panel's Trap… and Effect › Pathfinder › Trap… add a thin overprinting strip of the lighter colour inside the darker one where two solid colours meet, so misregistered plates leave no gap ([trapping](https://helpx.adobe.com/illustrator/using/trapping.html)), with Thickness, Height/Width, Tint Reduction, Traps with Process Color and Reverse Traps. Illustrator effects 49/50 (SVG Filters remains); Live vector effects hours 6–10 → 4–8; headline numbers unchanged.
- 2026-10-23: OpenType SVG colour fonts draw as vector art: each glyph's SVG document is read by the SVG importer, in the text's colours where it asks for them, and draws, exports and outlines as COLR glyphs do; all colour font formats are now drawn.
+112 -1
View File
@@ -73,6 +73,7 @@ pub const GRADIENT_LIBRARIES: &[BuiltinLibrary] = &[
lib!("sky-gradients", "Sky Gradients", sky_gradients),
lib!("neutral-gradients", "Neutral Gradients", neutral_gradients),
lib!("organic-fades", "Organic Fades", organic_fades),
lib!("holographic", "Holographic", holographic),
lib!("duotone-gradients", "Duotone Gradients", duotone_gradients),
lib!("radial-glows", "Radial Glows", radial_glows),
];
@@ -531,6 +532,62 @@ fn organic_fades() -> (Vec<Swatch>, Vec<SwatchGroup>) {
(s, vec![])
}
/// The stops of a [`holographic`] look: offset, opacity and midpoint toward the next stop.
type Bands = [(f32, f32, f32)];
/// Foil: six opaque linear bands, a narrow bright one among them, with off-center midpoints.
const FOIL: &Bands = &[(0.0, 1.0, 0.37), (0.13, 1.0, 0.64), (0.34, 1.0, 0.28), (0.48, 1.0, 0.68), (0.71, 1.0, 0.42), (1.0, 1.0, 0.5)];
/// Glow: five radial rings from a bright center out to a clear edge.
const GLOW: &Bands = &[(0.0, 0.95, 0.4), (0.12, 1.0, 0.58), (0.31, 0.72, 0.34), (0.58, 0.3, 0.62), (1.0, 0.0, 0.5)];
/// A [`holographic`] look: name, kind, stops and the OKLCH color of each stop in order.
type Look = (&'static str, GradientKind, &'static Bands, Anchors);
/// Iridescent looks mixed perceptually: linear foils of narrow pastel and pearl bands, and radial
/// glows that fade out to a clear edge. Each color is one stop of [`FOIL`] or [`GLOW`] in order.
fn holographic() -> (Vec<Swatch>, Vec<SwatchGroup>) {
use GradientKind::{Linear, Radial};
// Pale pearl, pastel and deep-violet OKLCH `(l, c, h°)` anchors.
const PEARL: (f64, f64, f64) = (0.97, 0.01, 90.0);
const SILVER: (f64, f64, f64) = (0.86, 0.015, 255.0);
const BLUSH: (f64, f64, f64) = (0.82, 0.055, 340.0);
const VIOLET: (f64, f64, f64) = (0.72, 0.1, 310.0);
const BLUE: (f64, f64, f64) = (0.73, 0.09, 255.0);
const CYAN: (f64, f64, f64) = (0.79, 0.09, 210.0);
const MINT: (f64, f64, f64) = (0.82, 0.08, 165.0);
const LIME: (f64, f64, f64) = (0.86, 0.085, 125.0);
const GOLD: (f64, f64, f64) = (0.89, 0.08, 85.0);
const AMBER: (f64, f64, f64) = (0.82, 0.1, 55.0);
const CORAL: (f64, f64, f64) = (0.78, 0.09, 25.0);
const DEEP_VIOLET: (f64, f64, f64) = (0.42, 0.04, 275.0);
let looks: [Look; 14] = [
("Prism Veil", Linear, FOIL, &[SILVER, BLUSH, PEARL, CYAN, VIOLET, SILVER]),
("Opal Ribbon", Linear, FOIL, &[PEARL, MINT, BLUSH, PEARL, BLUE, SILVER]),
("Pearl Flash", Linear, FOIL, &[SILVER, VIOLET, PEARL, GOLD, CYAN, PEARL]),
("Aurora Foil", Linear, FOIL, &[BLUE, MINT, PEARL, BLUSH, CYAN, SILVER]),
("Iris Sheen", Linear, FOIL, &[BLUSH, VIOLET, PEARL, CYAN, MINT, SILVER]),
("Frost Spectrum", Linear, FOIL, &[CYAN, BLUE, PEARL, MINT, BLUSH, SILVER]),
("Silver Tide", Linear, FOIL, &[SILVER, CYAN, PEARL, VIOLET, BLUE, SILVER]),
("Rose Quartz Gleam", Radial, GLOW, &[PEARL, BLUSH, CORAL, VIOLET, BLUSH]),
("Moonstone Shift", Radial, GLOW, &[PEARL, CYAN, MINT, BLUE, SILVER]),
("Violet Edge", Radial, GLOW, &[PEARL, VIOLET, BLUSH, BLUE, DEEP_VIOLET]),
("Mint Halo", Radial, GLOW, &[PEARL, MINT, CYAN, LIME, MINT]),
("Amber Corona", Radial, GLOW, &[PEARL, GOLD, AMBER, CORAL, AMBER]),
("Polar Glint", Radial, GLOW, &[PEARL, CYAN, BLUE, VIOLET, BLUE]),
("Pastel Orbit", Radial, GLOW, &[PEARL, BLUSH, MINT, CYAN, VIOLET]),
];
let s = looks
.iter()
.map(|&(name, kind, bands, colors)| {
let stops: Vec<(f32, Color, f32, f32)> =
bands.iter().zip(colors).map(|(&(at, opacity, mid), &(l, c, h))| (at, oklch(l, c, h), opacity, mid)).collect();
gradient_with(name, kind, GradientMethod::Perceptual, &stops)
})
.collect();
(s, vec![])
}
/// The sequential scales of [`perceptual`]: name and anchors of rising lightness.
const SEQUENTIAL: [(&str, Anchors); 5] = [
("Ember", &[(0.22, 0.10, 300.0), (0.55, 0.18, 30.0), (0.93, 0.15, 100.0)]),
@@ -708,9 +765,63 @@ mod tests {
}
}
#[test]
fn holographic_holds_seven_opaque_foils_and_seven_glows_to_a_clear_edge() {
let lib = builtin_library("holographic").unwrap();
let order: Vec<&str> = GRADIENT_LIBRARIES.iter().map(|b| b.name).collect();
assert_eq!(order.iter().position(|n| *n == "Holographic"), Some(4), "after Organic Fades: {order:?}");
assert!(lib.groups.is_empty());
assert_eq!(lib.len(), 14);
// No name another built-in gradient has, in any case.
let mut others = std::collections::HashSet::new();
for other in builtins().filter(|b| b.id != "holographic").map(|b| builtin_library(b.id).unwrap()) {
others.extend(other.iter().filter(|s| matches!(s.paint, Paint::Gradient(_))).map(|s| s.name.to_lowercase()));
}
assert!(lib.iter().all(|s| !others.contains(&s.name.to_lowercase())), "a name another library has");
let (mut foils, mut glows) = (0, 0);
for s in lib.iter() {
let Paint::Gradient(g) = &s.paint else { panic!("{} is a gradient", s.name) };
let (g, n) = (&g.gradient, &s.name);
assert_eq!(g.method, GradientMethod::Perceptual, "{n}");
let bands = match &g.kind {
GradientKind::Linear => {
foils += 1;
FOIL
}
GradientKind::Radial => {
glows += 1;
GLOW
}
kind => panic!("{n}: {kind:?}"),
};
// Every stop takes its band's offset, opacity and midpoint, and none is dropped.
let shape: Vec<(f32, f32, f32)> = g.stops.iter().map(|st| (st.offset, st.opacity, st.midpoint)).collect();
assert_eq!(shape, bands, "{n}");
assert!(g.stops.iter().all(|st| matches!(st.color, Color::Rgb { .. })), "{n}");
}
assert_eq!((foils, glows), (7, 7));
// Foils are opaque; a glow is clear at the edge.
assert!(FOIL.iter().all(|&(_, opacity, _)| opacity == 1.0));
assert_eq!(GLOW.last().map(|b| b.1), Some(0.0));
// Every segment's midpoint is off center and within the Gradient panel's 13 to 87%.
for bands in [FOIL, GLOW] {
assert!(bands[..bands.len() - 1].iter().all(|&(_, _, m)| (m - 0.5).abs() > 0.02 && (0.13..=0.87).contains(&m)));
assert!(bands.windows(2).all(|w| w[0].0 < w[1].0) && bands[0].0 == 0.0 && bands[bands.len() - 1].0 == 1.0);
}
// Sampled colors: Prism Veil's bright band is the pearl anchor, and Violet Edge ends in deep violet.
let stop = |name: &str, i: usize| match &lib.swatch(name).unwrap().paint {
Paint::Gradient(g) => g.gradient.stops[i].color,
_ => panic!("{name} is a gradient"),
};
assert_eq!(stop("Prism Veil", 2), oklch(0.97, 0.01, 90.0));
assert_eq!(stop("Violet Edge", 4), oklch(0.42, 0.04, 275.0));
let [l, ..] = to_oklab(&stop("Violet Edge", 4));
assert!(l < 0.5 && to_oklab(&stop("Prism Veil", 2))[0] > 0.95, "{l}");
}
#[test]
fn the_other_libraries_keep_classic_mixing_and_centered_midpoints() {
for b in builtins().filter(|b| b.id != "organic-fades") {
for b in builtins().filter(|b| !["organic-fades", "holographic"].contains(&b.id)) {
for s in builtin_library(b.id).unwrap().iter() {
if let Paint::Gradient(g) = &s.paint {
assert_eq!(g.gradient.method, GradientMethod::Classic, "{}", s.name);
+46 -1
View File
@@ -40,7 +40,16 @@ fn built_in_presets_are_the_gradient_libraries_by_theme_with_unique_names() {
libraries.dedup();
assert_eq!(
libraries,
["Spectrum Gradients", "Sky Gradients", "Neutral Gradients", "Organic Fades", "Duotone Gradients", "Radial Glows", "Metallic Gradients"]
[
"Spectrum Gradients",
"Sky Gradients",
"Neutral Gradients",
"Organic Fades",
"Holographic",
"Duotone Gradients",
"Radial Glows",
"Metallic Gradients"
]
);
let mut seen = std::collections::HashSet::new();
assert!(names(&list).iter().all(|n| seen.insert(n.to_lowercase())), "a name names one preset");
@@ -82,6 +91,42 @@ fn an_organic_fade_applies_with_its_method_midpoints_and_opacities() {
assert_eq!(row["gradient"]["method"], "perceptual");
}
#[test]
fn a_holographic_foil_applies_in_place_as_one_undo_step() {
let (mut s, id) = session_with(json!({"gradient": {"angle": 30}}));
let before = paint(&s, id, false);
let undo = s.doc().unwrap().history.undo.len();
let veil = s.gradient_preset("prism veil").unwrap();
assert_eq!((veil.library, veil.gradient.method), (Some("Holographic"), GradientMethod::Perceptual));
let r = s.execute("gradient.presets.apply", &json!({"name": "prism veil"})).unwrap();
assert_eq!(r["name"].as_str(), Some("Prism Veil"));
let g = paint(&s, id, false);
assert_eq!((g.gradient.kind, g.gradient.method, &g.gradient.stops), (GradientKind::Linear, GradientMethod::Perceptual, &veil.gradient.stops));
assert_eq!(g.gradient.stops.len(), 6);
assert_eq!(g.angle, before.angle, "the placement stays");
assert_eq!(s.doc().unwrap().history.undo.len(), undo + 1, "one undo step");
assert_eq!(s.gradient_preset_name(&g.gradient).as_deref(), Some("Prism Veil"));
s.execute("edit.undo", &json!({})).unwrap();
assert_eq!(paint(&s, id, false), before);
}
/// A preset saved as "Mint Halo" before Holographic existed stays listed under a free name.
#[test]
fn a_saved_preset_named_like_a_holographic_glow_gets_a_free_name() {
let (mut s, id) = session_with(json!({"gradient": {"kind": "radial"}}));
let halo = s.gradient_preset("Mint Halo").unwrap().gradient;
let mut own = paint(&s, id, false).gradient;
own.dither = true;
let mut prefs = s.prefs.clone();
prefs.gradient_presets = vec![crate::cmd::GradientPreset { name: "MINT HALO".into(), gradient: own.clone() }];
s.apply_prefs(prefs);
assert_eq!(s.prefs.gradient_presets.iter().map(|p| p.name.as_str()).collect::<Vec<_>>(), ["MINT HALO 2"]);
s.execute("gradient.presets.apply", &json!({"name": "mint halo 2"})).unwrap();
assert_eq!(paint(&s, id, false).gradient, own);
s.execute("gradient.presets.apply", &json!({"name": "Mint Halo"})).unwrap();
assert_eq!(paint(&s, id, false).gradient.stops, halo.stops);
}
#[test]
fn a_preset_applies_to_the_stroke_and_to_a_solid_paint() {
let (mut s, id) = session_with(json!({"color": "#336699"}));
+38
View File
@@ -671,6 +671,44 @@ fn organic_fades_add_with_their_method_midpoints_and_opacities_in_rgb_and_cmyk()
}
}
#[test]
fn holographic_glows_add_whole_in_rgb_and_cmyk_as_one_undo_step() {
let lib = vectorcraft_color::libraries::builtin_library("holographic").unwrap();
let Paint::Gradient(want) = &lib.swatch("Mint Halo").unwrap().paint else { panic!("Mint Halo is a gradient") };
for mode in ["rgb", "cmyk"] {
let mut s = Session::new();
run(&mut s, "file.new", json!({"width": 100, "height": 100, "colorMode": mode}));
let list = run(&mut s, "swatch.library.list", json!({}));
let row = list["libraries"].as_array().unwrap().iter().find(|l| l["id"] == "holographic").unwrap().clone();
assert_eq!((row["name"].as_str(), row["category"].as_str(), row["count"].as_u64()), (Some("Holographic"), Some("gradients"), Some(14)));
let got = run(&mut s, "swatch.library.get", json!({"library": "holographic"}));
assert!(got.to_string().contains("Mint Halo"), "{mode}: get lists Mint Halo");
let id = run(&mut s, "shape.rectangle", json!({"x": 0, "y": 0, "width": 50, "height": 50}))["id"].clone();
let node = vectorcraft_doc::NodeId(id.as_u64().unwrap());
let before = undo_len(&s);
let r = run(&mut s, "swatch.library.add", json!({"library": "holographic", "names": ["Mint Halo"], "apply": "fill"}));
assert_eq!((r["added"].clone(), r["applied"].clone()), (json!(["Mint Halo"]), json!("Mint Halo")), "{mode}");
assert_eq!(undo_len(&s), before + 1, "{mode}: added and applied as one step");
// The swatch comes as the library has it: kind, stops (RGB colors, opacities, midpoints) and method.
let Paint::Gradient(added) = &doc(&s).swatch("Mint Halo").unwrap().paint else { panic!("{mode}: a gradient swatch") };
assert_eq!(added.gradient, want.gradient, "{mode}");
assert!(added.gradient.stops.iter().all(|st| matches!(st.color, Color::Rgb { .. })), "{mode}: the stops stay RGB");
assert_eq!(added.gradient.stops.last().map(|st| st.opacity), Some(0.0), "{mode}: clear at the edge");
let Paint::Gradient(fill) = doc(&s).node(node).unwrap().appearance.fill_paint() else { panic!("{mode}: a gradient fill") };
assert_eq!((fill.gradient.kind, fill.gradient.method), (want.gradient.kind, want.gradient.method), "{mode}");
assert_eq!(fill.gradient.stops, want.gradient.stops, "{mode}");
run(&mut s, "edit.undo", json!({}));
assert!(doc(&s).swatch("Mint Halo").is_none(), "{mode}: undo removes the add");
assert!(!matches!(doc(&s).node(node).unwrap().appearance.fill_paint(), Paint::Gradient(_)), "{mode}: and the fill");
// A document swatch already named Mint Halo stays; the glow comes in under a number.
run(&mut s, "swatch.new", json!({"name": "Mint Halo", "color": "#123456"}));
let r = run(&mut s, "swatch.library.add", json!({"library": "holographic", "names": ["Mint Halo"]}));
assert_eq!(r["added"], json!(["Mint Halo 2"]), "{mode}");
assert!(doc(&s).swatch("Mint Halo").unwrap().paint.color().is_some(), "{mode}: the document's swatch is kept");
assert!(matches!(&doc(&s).swatch("Mint Halo 2").unwrap().paint, Paint::Gradient(g) if g.gradient == want.gradient));
}
}
#[test]
fn pattern_libraries_bring_their_patterns_and_add_each_once() {
let mut s = session();
+1
View File
@@ -2283,6 +2283,7 @@ font-technology Variable Променливи
Options: Опции:
Options… Опции…
Organic Fades Органични преливания
Holographic Холографски
or more spaces with a tab или повече интервала с табулация
Order: Ред:
Ordinals Поредни номера
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -828,6 +828,7 @@
Sky Gradients Gradijenti neba
Neutral Gradients Neutralni gradijenti
Organic Fades Organski prelazi
Holographic Holografski
Duotone Gradients Duoton gradijenti
Radial Glows Radijalni sjajevi
Save Swatch Library… Sačuvaj biblioteku uzoraka boja…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2918,6 +2918,7 @@ digits Malayalam Malaiàlam
Options: Opcions:
Options… Opcions…
Organic Fades Esvaïments orgànics
Holographic Hologràfics
or more spaces with a tab o més espais amb un tabulador
Orange Taronja
Order: Ordre:
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -837,6 +837,7 @@
Sky Gradients Přechody oblohy
Neutral Gradients Neutrální přechody
Organic Fades Organické přechody
Holographic Holografické
Duotone Gradients Dvoutónové přechody
Radial Glows Kruhové záře
Save Swatch Library… Uložit knihovnu vzorníku…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -774,6 +774,7 @@
Sky Gradients Himmelgradienter
Neutral Gradients Neutrale gradienter
Organic Fades Organiske toninger
Holographic Holografiske
Duotone Gradients Duotonegradienter
Radial Glows Radiale gløder
Save Swatch Library… Gem bibliotek med farveprøver…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2319,6 +2319,7 @@ file-filter Templates Vorlagen
Options: Optionen:
Options… Optionen…
Organic Fades Organische Verläufe
Holographic Holografisch
or more spaces with a tab oder mehr Leerzeichen durch einen Tabulator
Order: Reihenfolge:
Ordinals Ordinalzahlen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1842,6 +1842,7 @@ font-technology Variable Μεταβλητές
Options… Επιλογές…
Ordinals Τακτικοί αριθμοί
Organic Fades Οργανικές διαβαθμίσεις
Holographic Ολογραφικά
Orientation Προσανατολισμός
Orientation: Προσανατολισμός:
Original Πρωτότυπο
Can't render this file because it is too large.
+1
View File
@@ -2357,6 +2357,7 @@ font-technology Variable Variables
Options: Opciones:
Options… Opciones…
Organic Fades Desvanecidos orgánicos
Holographic Holográficos
or more spaces with a tab o más espacios por una tabulación
Order: Orden:
Ordinals Ordinales
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -828,6 +828,7 @@
Sky Gradients Taivasliukuvärit
Neutral Gradients Neutraalit liukuvärit
Organic Fades Orgaaniset häivytykset
Holographic Holografiset
Duotone Gradients Kaksisävyliukuvärit
Radial Glows Säteittäiset hehkut
Save Swatch Library… Tallenna värimallikirjasto…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2349,6 +2349,7 @@ font-technology Variable Variables
Options: Options :
Options… Options…
Organic Fades Fondus organiques
Holographic Holographiques
or more spaces with a tab espaces ou plus par une tabulation
Order: Ordre :
Ordinals Ordinaux
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3174,6 +3174,7 @@ antiAlias Sharp शार्प
Options: ऑप्शन्स:
Options… ऑप्शन्स…
Organic Fades ऑर्गेनिक फ़ेड
Holographic होलोग्राफ़िक
or more spaces with a tab या एक टैब के साथ अधिक रिक्त स्थान
Orange नारंगी
Order: आदेश:
Can't render this file because it is too large.
+1
View File
@@ -3175,6 +3175,7 @@ mark-style Japanese Japán
Radial Blur… Körkörös elmosás…
Radial Glows Körkörös ragyogások
Organic Fades Organikus áttűnések
Holographic Holografikus
Radial Gradient Körkörös színátmenet
Conic Gradient Kúpos színátmenet
Diamond Gradient Rombusz színátmenet
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -774,6 +774,7 @@
Sky Gradients Gradien langit
Neutral Gradients Gradien netral
Organic Fades Pudar organik
Holographic Holografik
Duotone Gradients Gradien duotone
Radial Glows Pendar radial
Save Swatch Library… Simpan pustaka sampel warna…
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
774
775
776
777
778
779
780
+1
View File
@@ -2395,6 +2395,7 @@ file-filter Templates Modelli
Options: Opzioni:
Options… Opzioni…
Organic Fades Dissolvenze organiche
Holographic Olografici
or more spaces with a tab o più spazi con una tabulazione
Order: Ordine:
Ordinals Ordinali
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -860,6 +860,7 @@ digits Malayalam マラヤーラム数字
Sky Gradients 空のグラデーション
Neutral Gradients ニュートラルグラデーション
Organic Fades オーガニックフェード
Holographic ホログラフィック
Duotone Gradients ダブルトーングラデーション
Radial Glows 円形グロー
Save Swatch Library… スウォッチライブラリを保存…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -734,6 +734,7 @@
Sky Gradients ცის გრადიენტები
Neutral Gradients ნეიტრალური გრადიენტები
Organic Fades ორგანული გაქრობები
Holographic ჰოლოგრაფიული
Duotone Gradients ორტონიანი გრადიენტები
Radial Glows რადიალური ნათებები
Save Swatch Library… ფერის ნიმუშების ბიბლიოთეკის შენახვა…
Can't render this file because it is too large.
+1
View File
@@ -853,6 +853,7 @@ digits Malayalam 말라얄람어
Sky Gradients 하늘 그레이디언트
Neutral Gradients 중간색 그레이디언트
Organic Fades 유기적 페이드
Holographic 홀로그래픽
Duotone Gradients 듀오톤 그레이디언트
Radial Glows 방사형 광선
Save Swatch Library… 견본 라이브러리 저장…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -788,6 +788,7 @@
Sky Gradients Luchtverlopen
Neutral Gradients Neutrale verlopen
Organic Fades Organische vervagingen
Holographic Holografisch
Duotone Gradients Duotoonverlopen
Radial Glows Radiale gloed
Save Swatch Library… Staalenbibliotheek opslaan…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -784,6 +784,7 @@
Sky Gradients Gradienty nieba
Neutral Gradients Gradienty neutralne
Organic Fades Organiczne zanikania
Holographic Holograficzne
Duotone Gradients Gradienty dwutonowe
Radial Glows Blaski promieniste
Save Swatch Library… Zapisz bibliotekę próbek…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1954,6 +1954,7 @@ antiAlias Sharp Nítido
Order: Ordem:
Ordinals Ordinais
Organic Fades Esmaecimentos Orgânicos
Holographic Holográficos
Orientation Orientação
Orientation: Orientação:
Original Original
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -2382,6 +2382,7 @@ file-filter Templates Шаблоны
Options: Параметры:
Options… Параметры…
Organic Fades Органические затухания
Holographic Голографические
or more spaces with a tab или больше пробелов на табуляцию
Order: Порядок:
Ordinals Порядковые числительные
Can't render this file because it is too large.
+1
View File
@@ -2296,6 +2296,7 @@ font-technology Variable Variabla
Options: Alternativ:
Options… Alternativ…
Organic Fades Organiska toningar
Holographic Holografiska
or more spaces with a tab eller fler blanksteg med en tabb
Order: Ordning:
Ordinals Ordningstal
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -2168,6 +2168,7 @@ shape Open Açık
Options: Seçenekler:
Options… Seçenekler…
Organic Fades Organik Solmalar
Holographic Holografik
or more spaces with a tab veya sekmeli daha fazla alan
Order: Sipariş:
Ordinals Sıra Sayıları
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -2387,6 +2387,7 @@ file-filter Templates Шаблони
Options: Параметри:
Options… Параметри…
Organic Fades Органічні згасання
Holographic Голографічні
or more spaces with a tab або більше прогалин на табуляцію
Order: Порядок:
Ordinals Порядкові числівники
Can't render this file because it contains an unexpected character in line 182 and column 5.
+1
View File
@@ -2964,6 +2964,7 @@ mark-style Japanese Kiểu Nhật
Radial Dividers: Đường chia hướng tâm:
Radial Glows Ánh sáng hướng tâm
Organic Fades Mờ dần tự nhiên
Holographic Ảnh ba chiều
Radial Gradient Chuyển sắc hướng tâm
Conic Gradient Chuyển sắc hình nón
Diamond Gradient Chuyển sắc hình thoi
Can't render this file because it contains an unexpected character in line 204 and column 5.
+1
View File
@@ -2254,6 +2254,7 @@ file-filter Templates 模板
Options: 选项:
Options… 选项…
Organic Fades 自然渐隐
Holographic 全息
or more spaces with a tab 或多个空格加一个制表符
Order: 顺序:
Ordinals 序数字
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3354,6 +3354,7 @@ file-filter Templates 範本
Options: 選項:
Options… 選項…
Organic Fades 自然漸隱
Holographic 全像
or more spaces with a tab 個以上的空格取代為定位字元
Order: 順序:
Ordinals 序數字
Can't render this file because it contains an unexpected character in line 6 and column 47.
+17
View File
@@ -828,6 +828,23 @@ mod gradient_chip_tests {
assert!(chip.iter().all(|c| c.a() == 0), "{chip:?}");
}
/// A Holographic glow's chip is clear at the corners and nearly opaque at the center; a foil's
/// chip is opaque everywhere.
#[test]
fn holographic_chips_show_a_glow_clear_at_its_edge_and_a_foil_opaque() {
use vectorcraft_color::Paint;
let lib = vectorcraft_color::libraries::builtin_library("holographic").unwrap();
let chip = |name: &str| match &lib.swatch(name).unwrap().paint {
Paint::Gradient(g) => gradient_chip_colors(g, 20.0, 20.0, 4, 4),
p => panic!("{name}: {p:?}"),
};
let glow = chip("Mint Halo");
assert!([0, 4, 20, 24].iter().all(|&i| glow[i].a() == 0), "{glow:?}");
assert!(glow[2 * 5 + 2].a() >= 240, "{glow:?}");
let foil = chip("Prism Veil");
assert!(foil.iter().all(|c| c.a() == 255), "{foil:?}");
}
#[test]
fn freeform_chip_mixes_points_in_the_model_they_share() {
use vectorcraft_color::{Color, Freeform, FreeformPoint};
+1 -1
View File
@@ -1288,7 +1288,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
Double-clicking the Objects on Path tool opens Objects on Path Tool Options ([Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)): the nine-point Pivot grid and the Rotate field set the attachment point and angle of the objects attached next, and groups already attached keep theirs; Reset puts the center and 0° back. Save keeps the options across tool switches and saves them with the preferences (`tool.setOption {tool: "objectsOnPath"}`).
- **Paint and appearance (M3):**
- **CSS swatch libraries:** fractional linear and radial gradient stop positions are preserved, so nearby stops such as 12.5% and 12.890625% remain distinct instead of collapsing to 13%. Reference: [CSS Images 3 color stops](https://www.w3.org/TR/css-images-3/#color-stop-syntax). The original synthetic regression is `palette_io::tests::css_preserves_fractional_gradient_stop_positions` in `crates/color/src/palette_io.rs`. Scores and hours are unchanged.
- **Swatches:** names follow the colour model and are unique; Swatch Options (process/spot, Global, Gray/RGB/HSB/CMYK/Web, live preview); editing a global or spot swatch recolours every linked fill, stroke and text run in one undo step; multi-select and delete with confirmation; New Swatch and New Color Group dialogs (a group from the selected artwork's colours); swatches in colour groups convert, separate and count like any other. The Swatches panel selects ranges and whole groups, has a find field, and drags swatches to reorder, regroup or paint art; Add Used Colors, Select All Unused, Merge, Ungroup and Sort by Kind; a CMYK document keeps applied colours in CMYK. Swatch libraries: nine generated colour libraries, six gradient libraries (Organic Fades among them: soft, perceptually mixed multi-stop fades that thin out to transparent) and a pattern library (Geometric Patterns, whose swatches bring their patterns) in a library panel, saved as `.vcswatches`, `.gpl`, swatch exchange (`.ase`) or CSS, and loaded from `.vcswatches`, `.gpl` and `.ase` files (`.ase` both ways: RGB, CMYK, Lab and Gray; global, spot and process; groups) and from color books (`.acb`, read only: the RGB, CMYK or Lab colors of a book such as a Pantone book a user owns, named with its prefix and suffix, spot unless it says process, #831); `swatch.library.copyToUser` copies a loaded library into the User Defined folder without replacing a file, and a file with the same extension and bytes as a User Defined library opens as that library. Tints of global and spot colours ("Name 40%") stay linked and separate as a percentage of their plate. Spot colours can be defined in Lab (Spot Colors options). A built-in [Registration] swatch prints on every plate.
- **Swatches:** names follow the colour model and are unique; Swatch Options (process/spot, Global, Gray/RGB/HSB/CMYK/Web, live preview); editing a global or spot swatch recolours every linked fill, stroke and text run in one undo step; multi-select and delete with confirmation; New Swatch and New Color Group dialogs (a group from the selected artwork's colours); swatches in colour groups convert, separate and count like any other. The Swatches panel selects ranges and whole groups, has a find field, and drags swatches to reorder, regroup or paint art; Add Used Colors, Select All Unused, Merge, Ungroup and Sort by Kind; a CMYK document keeps applied colours in CMYK. Swatch libraries: nine generated colour libraries, seven gradient libraries (among them Organic Fades, soft perceptually mixed multi-stop fades that thin out to transparent, and Holographic, seven opaque linear foils of narrow pastel and pearl bands and seven radial glows that fade out to a clear edge) and a pattern library (Geometric Patterns, whose swatches bring their patterns) in a library panel, saved as `.vcswatches`, `.gpl`, swatch exchange (`.ase`) or CSS, and loaded from `.vcswatches`, `.gpl` and `.ase` files (`.ase` both ways: RGB, CMYK, Lab and Gray; global, spot and process; groups) and from color books (`.acb`, read only: the RGB, CMYK or Lab colors of a book such as a Pantone book a user owns, named with its prefix and suffix, spot unless it says process, #831); `swatch.library.copyToUser` copies a loaded library into the User Defined folder without replacing a file, and a file with the same extension and bytes as a User Defined library opens as that library. Tints of global and spot colours ("Name 40%") stay linked and separate as a percentage of their plate. Spot colours can be defined in Lab (Spot Colors options). A built-in [Registration] swatch prints on every plate.
Editing, renaming, deleting or merging a global swatch also changes the colors linked to it in graph designs, the art of brushes and the tile that pattern editing's Cancel puts back, in the same undo step as the rest of the art; Default Swatches with replace unlinks them there too.
Add Used Colors (`swatch.addUsedColors`) and Select All Unused (`swatch.unused`) look colors, swatch names, links, tints and gradients up in hash sets instead of searching every swatch and color for each color or linked paint (New Color Group from artwork too), and New Swatch with several colors (`swatch.new`), New Color Group (`swatch.newGroup`) and Edit Color Group (`swatch.editGroup`) name their new swatches from one set of the names already taken. The new swatches keep their names, order and links, and Select All Unused lists the same swatches. Evidence: `add_used_colors_adds_each_new_color_once_with_free_names`, `add_used_colors_global_links_every_paint_of_a_new_color`, `unused_matches_links_tints_colors_gradients_and_patterns_exactly`, `new_swatches_from_colors_are_numbered_after_names_already_taken`, `new_color_group_numbers_its_colors_after_the_group_and_its_moved_swatches`, `new_color_group_from_artwork_lists_each_color_once_with_free_names` and `edit_color_group_numbers_extra_colors_after_the_names_it_keeps` in `crates/engine/src/tests/swatchcmds.rs`; `free_swatch_names_match_naming_each_swatch_as_it_is_added` and `free_swatch_names_match_new_swatch_names_as_swatches_are_added` in `crates/doc/src/swatches.rs`.
- **Colorized images (#1466):** a fill color applied to a selected grayscale or 1-bit image (`paint.setFill`) colorizes it with black, white, a process color or a spot color, and refuses a process color when the image has an alpha channel ([Convert color modes](https://web.archive.org/web/20251220223850/https://helpx.adobe.com/illustrator/desktop/manage-colors/select-and-adjust-colors/convert-color-modes.html), "Colorize Grayscale or 1-bit images"); black and white are accepted there too. The canvas draws each pixel in the color as far as the pixel is dark, with white pixels transparent; PDF export writes the image in the color (a spot color as its ink, Registration in every ink) with the image as its soft mask; Separations Preview and printed separations show it on its color's plates; native files keep the color. SVG writes the fill color through a coverage mask (or a colorized PNG in Tiny 1.2); EPS writes binary coverage as an image mask in the color's ink, and a grayscale image as ink samples scaled by coverage, with white pixels left out at Level 3 and gray midtones written over white.