diff --git a/crates/engine/src/cmd/gradient.rs b/crates/engine/src/cmd/gradient.rs index 2fddbe963..f777628f2 100644 --- a/crates/engine/src/cmd/gradient.rs +++ b/crates/engine/src/cmd/gradient.rs @@ -23,7 +23,7 @@ pub fn specs() -> Vec { "Gradient", ["Window", "Gradient"], None, - "{stroke?: bool (default: the targeted item's kind, else the active proxy), kind?: linear|radial|freeform (freeform places points on each object, coloured along the stops), mode?: points|lines (freeform: how the Gradient tool adds points), method?: classic|perceptual (how the colours between the stops mix: in display RGB, or perceptually (OKLab) so the steps look even; SVG exports draw a Perceptual gradient as an image, and PDF exports do too unless it is linear or radial, has spot color stops, every other stop is paper white or written in CMYK or gray (a CMYK document, or an export that converts colors to a CMYK destination profile, writes RGB and Lab stops in CMYK), it is not a dithered fill and its curve does not have too many stops: then PDF writes tints of one spot ink as a Separation shading in that ink, and spot inks mixed with other spot, CMYK or gray inks as a DeviceN shading; freeform gradients mix their own way), stops?: [{offset 0..1, color? (needed without swatch; #rrggbbaa and #rgba are refused), opacity? 0..1 (or 0..100), midpoint? 0.13..0.87, swatch?: colour swatch name (a global or spot colour or tint swatch links the stop, so swatch edits recolour it and a spot stop prints on its plate; a process colour just gives its colour), tint?: 0..100 (% of the linked swatch; default 100, or a tint swatch's own)}] (at least 2; a freeform gradient's points are recoloured along them), keepModel?: bool (as paint.setFill; a stop color the gradient already has keeps its model), angle?: deg, aspect?: %, reverse?: bool, dither?: bool (fills only: a linear or radial gradient fill is drawn with fine noise that hides banding, and as pixels in SVG and PDF exports), item?: fill/stroke item index|null (omitted: the Appearance panel's active item when it is of the edited kind), ids?|id?, strokeMode?: within|along|across (strokes only: the gradient lies on the page and shows through the stroke, runs from the start of each subpath to its end, or runs from the stroke's left edge to its right all along it; with nothing selected, for the next object drawn; type characters' own strokes always paint within), target?: \"object\"|\"contents\"} edit the gradient in place (keeps its placement); solid/none paints become the default gradient", + "{stroke?: bool (default: the targeted item's kind, else the active proxy), kind?: linear|radial|freeform (freeform places points on each object, coloured along the stops), mode?: points|lines (freeform: how the Gradient tool adds points), method?: classic|perceptual (how the colours between the stops mix: in display RGB, or perceptually (OKLab) so the steps look even; SVG exports draw a Perceptual gradient as an image, and PDF exports do too unless it is linear or radial, has spot color stops, every other stop is paper white or written in CMYK or gray (an export that converts colors to a CMYK destination profile writes RGB and Lab stops in CMYK, and so does a CMYK document unless the export converts colors to an RGB destination profile), it is not a dithered fill and its curve does not have too many stops: then PDF writes tints of one spot ink as a Separation shading in that ink, and spot inks mixed with other spot, CMYK or gray inks as a DeviceN shading; freeform gradients mix their own way), stops?: [{offset 0..1, color? (needed without swatch; #rrggbbaa and #rgba are refused), opacity? 0..1 (or 0..100), midpoint? 0.13..0.87, swatch?: colour swatch name (a global or spot colour or tint swatch links the stop, so swatch edits recolour it and a spot stop prints on its plate; a process colour just gives its colour), tint?: 0..100 (% of the linked swatch; default 100, or a tint swatch's own)}] (at least 2; a freeform gradient's points are recoloured along them), keepModel?: bool (as paint.setFill; a stop color the gradient already has keeps its model), angle?: deg, aspect?: %, reverse?: bool, dither?: bool (fills only: a linear or radial gradient fill is drawn with fine noise that hides banding, and as pixels in SVG and PDF exports), item?: fill/stroke item index|null (omitted: the Appearance panel's active item when it is of the edited kind), ids?|id?, strokeMode?: within|along|across (strokes only: the gradient lies on the page and shows through the stroke, runs from the start of each subpath to its end, or runs from the stroke's left edge to its right all along it; with nothing selected, for the next object drawn; type characters' own strokes always paint within), target?: \"object\"|\"contents\"} edit the gradient in place (keeps its placement); solid/none paints become the default gradient", has_doc, edit_gradient ), diff --git a/crates/engine/src/tests/linked_stops.rs b/crates/engine/src/tests/linked_stops.rs index c355793d9..eb4712cfc 100644 --- a/crates/engine/src/tests/linked_stops.rs +++ b/crates/engine/src/tests/linked_stops.rs @@ -315,6 +315,17 @@ fn perceptual_spot_gradients_with_rgb_stops_in_a_cmyk_document_export_as_device_ assert!(pdf.contains("/ShadingType 2") && pdf.contains("/Ink]/DeviceCMYK"), "{what}: a DeviceN shading with Ink"); assert!(!r.warnings.iter().any(|w| w.contains("spot")), "{what}: {:?}", r.warnings); } + // A conversion to an RGB destination keeps the RGB stop in RGB, in a CMYK document too: an + // image, with the spot warning. + let mut to_rgb = plain.clone(); + to_rgb.settings.output = vectorcraft_pdf::OutputSettings { + conversion: vectorcraft_pdf::ColorConversion::Destination, + destination: vectorcraft_color::cms::SRGB.into(), + ..Default::default() + }; + let r = vectorcraft_pdf::export_with_report(&cmyk, &to_rgb).unwrap(); + assert!(String::from_utf8_lossy(&r.bytes).contains("/Subtype/Image"), "RGB destination: an image"); + assert!(r.warnings.iter().any(|w| w.contains("spot")), "RGB destination: {:?}", r.warnings); } #[test] diff --git a/docs/mcp.md b/docs/mcp.md index 14ef0f74f..79a4a5749 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -926,8 +926,8 @@ Method (the Gradient panel's menu): `classic` (the default) mixes the colours be Perceptual gradient as an image at the Document Raster Effects resolution (a dithered Perceptual fill with its noise). PDF exports write it the same way, except for a linear or radial gradient with spot color stops whose other stops are all paper white or written in CMYK or gray, that is not a dithered fill and whose curve does not have too many -stops. A CMYK document, or an export that converts colors to a CMYK destination profile, writes RGB and Lab stops in -CMYK. PDF writes tints of one spot ink as a Separation shading in that ink, and spot inks mixed with other spot, CMYK +stops. An export that converts colors to a CMYK destination profile writes RGB and Lab stops in CMYK, and so does a +CMYK document unless the export converts colors to an RGB destination profile. PDF writes tints of one spot ink as a Separation shading in that ink, and spot inks mixed with other spot, CMYK or gray inks as a DeviceN shading. `paint.setFill`/`paint.setStroke` take it in `gradient` too: @@ -2788,8 +2788,8 @@ give it `swatch` (and `tint` %, default 100 or a tint swatch's own) instead of ` in gradient swatches. A spot stop separates on its plate. A linear or radial gradient whose stops are all tints of one spot ink (or paper white, 0 %) exports to PDF as a Separation shading, and one that mixes spot inks with other spot, CMYK or gray inks exports as a DeviceN shading. A gradient that mixes a spot ink with colors written in RGB or Lab is written in -process colors, with a warning; a CMYK document, or an export that converts colors to a CMYK destination profile, -writes RGB and Lab stops in CMYK. Freeform gradients and dithered fills export to PDF as images in process colors, and Method +process colors, with a warning; an export that converts colors to a CMYK destination profile writes RGB and Lab stops +in CMYK, and so does a CMYK document unless the export converts colors to an RGB destination profile. Freeform gradients and dithered fills export to PDF as images in process colors, and Method above covers Perceptual gradients. ```json