mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-18 18:03:24 -05:00
Copy refused fill and adjustment layers ("the active layer has no
pixels"). With no pixel selection they are now taken whole, like smart
objects, type, shape and group layers, and Paste recreates them in this
or another document. An adjustment layer's clip spans the canvas, so
paste placement and the OS-clipboard mirror stay consistent.
Scorecard UI-217-23 note, gaps.md G9 and target-app-parity.md updated;
the row stays partial (a single pixel layer still copies pixels only).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
72a3423a7e
commit
ca69059dd0
5 files changed
+73
-17
No files matched your search
@@ -35,15 +35,14 @@ pub struct Clip {
|
||||
|
||||
/// Photoshop's layer-based copy (CC 2018 on): with no selection, Copy takes the active layer
|
||||
/// whole when it is a smart object (#2428), a type or shape layer, or a group (its whole subtree)
|
||||
/// (#2670), so Paste recreates it instead of its pixels. Pixel layers still copy their pixels;
|
||||
/// several selected layers are [`multi_copy_ids`].
|
||||
/// (#2670), so Paste recreates it instead of its pixels. Fill and adjustment layers have no
|
||||
/// pixels of their own, so they are taken whole too rather than refused (#2344). Pixel layers
|
||||
/// still copy their pixels; several selected layers are [`multi_copy_ids`].
|
||||
fn takes_whole(d: &crate::DocState, id: LayerId) -> bool {
|
||||
d.doc.selection.is_none()
|
||||
&& d.selected_layers().len() <= 1
|
||||
&& crate::layer_copy_cmds::layered(d.doc.mode)
|
||||
&& d.doc
|
||||
.layer(id)
|
||||
.is_some_and(|l| matches!(l.content, LayerContent::Smart(_) | LayerContent::Text(_) | LayerContent::Shape(_) | LayerContent::Group(_)))
|
||||
&& d.doc.layer(id).is_some_and(|l| !matches!(l.content, LayerContent::Raster(_)))
|
||||
}
|
||||
|
||||
/// A scratch document in the source's colour, to hold copied layers.
|
||||
@@ -280,13 +279,18 @@ fn copy(s: &mut Session, merged: bool) -> Result<Value> {
|
||||
}
|
||||
match (d.doc.layer(id).and_then(Layer::surface).filter(|_| several.is_empty()), &layers) {
|
||||
(Some(surf), _) => Clip { layers, ..lift(surf, d.doc.selection.as_ref(), canvas)? },
|
||||
// A group has no pixels of its own: the clipboard pixels are what it shows.
|
||||
// A group or fill layer has no pixels of its own: the clipboard pixels are what it
|
||||
// shows. Adjustment layers show nothing by themselves, so their clip spans the canvas
|
||||
// they apply to: Paste places them as a full-canvas layer, and the UI still mirrors
|
||||
// the clip to the OS clipboard (an empty clip would let a stale OS image replace it).
|
||||
(None, Some(copies)) => {
|
||||
let mut shown = (**copies).clone();
|
||||
for l in &mut shown.layers {
|
||||
l.visible = true;
|
||||
}
|
||||
Clip { layers, ..lift(&merged_surface(&shown), None, canvas)? }
|
||||
let clip = lift(&merged_surface(&shown), None, canvas)?;
|
||||
let bounds = if clip.bounds.is_empty() { canvas } else { clip.bounds };
|
||||
Clip { layers, bounds, ..clip }
|
||||
}
|
||||
(None, None) => return Err(EngineError::Other("the active layer has no pixels".into())),
|
||||
}
|
||||
@@ -1454,12 +1458,12 @@ mod tests {
|
||||
assert!(s.clipboard.is_none(), "a refused copy leaves the clipboard alone");
|
||||
s.execute("layer.layerMask.revealAll", json!({})).unwrap();
|
||||
assert!(s.execute("edit.copy", json!({"target": "mask"})).is_ok());
|
||||
// An adjustment layer has no pixels of its own: Copy is only enabled while its mask is
|
||||
// targeted (#2928).
|
||||
// An adjustment layer has no pixels of its own: Copy takes the layer whole (#2344), and
|
||||
// its mask while that is targeted (#2928).
|
||||
s.execute("file.new", json!({"width": 20, "height": 20})).unwrap();
|
||||
let a = s.execute("layer.newAdjustmentLayer.levels", json!({})).unwrap()["layer"].as_u64().unwrap();
|
||||
s.execute("layer.select", json!({"layer": a})).unwrap();
|
||||
assert!(!s.is_enabled("edit.copy"), "no pixels to copy");
|
||||
assert!(s.is_enabled("edit.copy"), "the layer itself can be copied");
|
||||
s.execute("layer.layerMask.revealAll", json!({})).unwrap();
|
||||
assert!(s.is_enabled_with("edit.copy", &json!({"target": "mask"})), "the mask can be copied");
|
||||
}
|
||||
@@ -1916,6 +1920,56 @@ mod tests {
|
||||
assert_eq!(shape.surface().map(|c| c.format().sample), Some(s.active().unwrap().doc.depth), "converted to 16 bits");
|
||||
}
|
||||
|
||||
/// #2344: fill and adjustment layers have no pixels of their own, so with no selection Copy
|
||||
/// takes them whole and Paste recreates them, in the same or another document, in one step.
|
||||
#[test]
|
||||
fn copy_paste_keeps_fill_and_adjustment_layers() {
|
||||
for (depth, other) in [(8, 16), (16, 32), (32, 8)] {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 60, "height": 40, "depth": depth})).unwrap();
|
||||
s.execute("layer.newFillLayer.gradient", json!({"from": "#000000", "to": "#ffffff", "angle": 0})).unwrap();
|
||||
let LayerContent::Fill(fill) = active_content(&s) else { panic!("a fill layer") };
|
||||
let src = s.active().unwrap().active_layer.unwrap();
|
||||
assert!(s.is_enabled("edit.copy"), "{depth}-bit: a fill layer can be copied");
|
||||
assert_eq!(s.execute("edit.copy", json!({})).unwrap()["bounds"], json!([0, 0, 60, 40]), "{depth}-bit: what it shows");
|
||||
let clip = s.clipboard.clone().unwrap();
|
||||
assert!(clip.surface.rgba(59, 20)[0] > clip.surface.rgba(0, 20)[0], "{depth}-bit: the clip holds the gradient's pixels");
|
||||
let steps = s.active().unwrap().history.past_len();
|
||||
s.execute("edit.pasteSpecial.pasteInPlace", json!({})).unwrap();
|
||||
assert_eq!(s.active().unwrap().history.past_len(), steps + 1, "{depth}-bit: one history step");
|
||||
assert_eq!(active_content(&s), LayerContent::Fill(fill.clone()), "{depth}-bit: the paste is the same fill layer");
|
||||
assert_ne!(s.active().unwrap().active_layer, Some(src), "{depth}-bit: a new layer");
|
||||
s.undo();
|
||||
assert_eq!(s.active().unwrap().active_layer, Some(src), "{depth}-bit: undo removes the paste");
|
||||
s.redo();
|
||||
assert!(matches!(active_content(&s), LayerContent::Fill(_)), "{depth}-bit: redo brings it back");
|
||||
|
||||
s.execute("layer.newAdjustmentLayer.levels", json!({})).unwrap();
|
||||
let LayerContent::Adjustment(levels) = active_content(&s) else { panic!("an adjustment layer") };
|
||||
assert_eq!(s.execute("edit.copy", json!({})).unwrap()["bounds"], json!([0, 0, 60, 40]), "{depth}-bit: it applies to the canvas");
|
||||
s.execute("file.new", json!({"width": 30, "height": 30, "depth": other})).unwrap();
|
||||
s.execute("edit.paste", json!({})).unwrap();
|
||||
assert_eq!(active_content(&s), LayerContent::Adjustment(levels), "{depth}-bit: the same Levels layer in the {other}-bit document");
|
||||
assert_eq!(s.active().unwrap().doc.layers.len(), 2, "{depth}-bit: pasted above the Background");
|
||||
}
|
||||
}
|
||||
|
||||
/// #2344: several adjustment layers, which show nothing alone, still copy and paste together.
|
||||
#[test]
|
||||
fn several_adjustment_layers_copy_together() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 40, "height": 40})).unwrap();
|
||||
let a = s.execute("layer.newAdjustmentLayer.levels", json!({})).unwrap()["layer"].as_u64().unwrap();
|
||||
let b = s.execute("layer.newAdjustmentLayer.levels", json!({})).unwrap()["layer"].as_u64().unwrap();
|
||||
s.execute("layer.select", json!({"layer": a})).unwrap();
|
||||
s.execute("layer.select", json!({"layer": b, "mode": "toggle"})).unwrap();
|
||||
assert_eq!(s.execute("edit.copy", json!({})).unwrap()["bounds"], json!([0, 0, 40, 40]));
|
||||
s.execute("edit.pasteSpecial.pasteInPlace", json!({})).unwrap();
|
||||
let d = &s.active().unwrap().doc;
|
||||
assert_eq!(d.layers.len(), 5, "both are pasted");
|
||||
assert!(d.layers[3..].iter().all(|l| matches!(l.content, LayerContent::Adjustment(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_visible_keeps_hidden_layers() {
|
||||
let mut s = session();
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
# Where PhotoCraft falls short of Photoshop
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bins it, psd-tools oracle floor 241/309; G1: Gradient Map driven by the W3C luminosity, Photoshop-oracle floor 147/258; G7: Field Blur's on-canvas pins, #3373; G4: Hue Jitter amount track, #3825 partial; G4: minimum field interaction, #3825 partial; G1: CMYK Invert, Posterize and Threshold on the inks, 16-bit Lab Invert; Photoshop-oracle floor 145/258; G11: `.atn` import maps 112 events: Select and Mask, Filter Gallery Spatter, Ripple, Crystallize, Pattern Fill layers, mask targeting, Step Backward, nudges in points, Bitmap mode; G5: Free Transform H/V skew fields; G9: toolbar tool shortcut editing; refreshed against main: G2, G5, G7, G9, G10, G13, G14, G17 items that landed; G10: DPX read and write, #1049; G4: checkbox-only Brush Settings rows; G11: Load/Save Actions `.atn` landed, AUTO-219-2 partial; G5: hold-a-key spring-loaded tools landed, #2672; G1: #2465 fixed; stale missing-tool rows corrected: Color Replacement, Red Eye and Add/Delete Anchor Point are live tools, so only Art History Brush is missing; no estimate changed) · **Target:** Adobe Photoshop 2026
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** minor (G9: fill and adjustment layers copy and paste whole, #2344; G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bins it, psd-tools oracle floor 241/309; G1: Gradient Map driven by the W3C luminosity, Photoshop-oracle floor 147/258; G7: Field Blur's on-canvas pins, #3373; G4: Hue Jitter amount track, #3825 partial; G4: minimum field interaction, #3825 partial; G1: CMYK Invert, Posterize and Threshold on the inks, 16-bit Lab Invert; Photoshop-oracle floor 145/258; G11: `.atn` import maps 112 events: Select and Mask, Filter Gallery Spatter, Ripple, Crystallize, Pattern Fill layers, mask targeting, Step Backward, nudges in points, Bitmap mode; G5: Free Transform H/V skew fields; G9: toolbar tool shortcut editing; refreshed against main: G2, G5, G7, G9, G10, G13, G14, G17 items that landed; G10: DPX read and write, #1049; G4: checkbox-only Brush Settings rows; G11: Load/Save Actions `.atn` landed, AUTO-219-2 partial; G5: hold-a-key spring-loaded tools landed, #2672; G1: #2465 fixed; stale missing-tool rows corrected: Color Replacement, Red Eye and Add/Delete Anchor Point are live tools, so only Art History Brush is missing; no estimate changed) · **Target:** Adobe Photoshop 2026
|
||||
|
||||
Every known shortfall against Photoshop 2026 (27.11.0), one entry each, ranked by user impact
|
||||
on the way to beta. This is the work list agents pick from: take the highest-ranked entry that
|
||||
@@ -199,8 +199,8 @@ what an agent can't finish alone.
|
||||
with saved bindings, matching toolbar hints and regression coverage (`ui-egui/src/tool_shortcuts.rs`).
|
||||
- **Missing:** 27 of 156 preferences do nothing (scorecard prefs audit); panel groups can't
|
||||
float or tear off into OS windows (UI-217-5, #1828, #1213, #2305); Color panel lacks wheel and
|
||||
slider modes (UI-217-17, #2569); more themes (UI-217-11, #2661); layer clipboard
|
||||
(UI-217-23, #2670); tool-specific context menus beyond brushes, selections and Pen
|
||||
slider modes (UI-217-17, #2569); more themes (UI-217-11, #2661); a single pixel layer
|
||||
copies without its mask and styles (UI-217-23; fill and adjustment layers copy whole, #2344); tool-specific context menus beyond brushes, selections and Pen
|
||||
([context-menu-parity.md](context-menu-parity.md)); Libraries, Comments, Contextual Task Bar
|
||||
panels.
|
||||
- **Estimate:** 150–250 h.
|
||||
@@ -270,6 +270,7 @@ what an agent can't finish alone.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-18 | minor | G9: with no selection, Copy takes fill and adjustment layers whole and Paste recreates them (#2344); UI-217-23 stays partial (a single pixel layer copies its pixels only); estimate unchanged |
|
||||
| 2026-10-14 | minor | G1: a PSD smart object's filter mask shows when the file opens (Photoshop stores the filtered pixels unmasked); export stores them that way too; Photoshop-oracle floor 185 → 188 of 258 |
|
||||
| 2026-10-13 | minor | G14: D90 image area measured (4288 × 2848 at (10, 10)); gap remains open |
|
||||
| 2026-10-14 | minor | Corpus floors raised to the measured results of the CMYK, Lab, 32-bit, Levels, Threshold, Posterize, feather and pass-through fixes landed together: Photoshop-authored 165 → 185 of 258, io 146 → 148 of 170, psd-tools 242 → 249 of 309 |
|
||||
|
||||
+1
-1
@@ -207,7 +207,7 @@ Unread: `general.color_picker`, `general.animated_zoom`, `general.zoom_resizes_w
|
||||
| UI-217-20 | 'Show rulers in new documents' preference; guides stored as f64 | done | [#217](https://github.com/storytold/photocraft/issues/217) | View › Rulers is remembered in unitsAndRulers.showRulers and applied at launch and on change (#2918; rulers_open_as_last_set_after_a_restart); doc Guides are Vec<f64> through New Guide, .pcraft and PSD 1032 (guides_keep_sub_pixel_positions_through_pcraft_and_psd) |
|
||||
| UI-217-21 | One Preset Manager for every preset kind with folders, search, reorder, load/save sets | partial | [#217](https://github.com/storytold/photocraft/issues/217) | edit_menu_cmds.rs:714 covers brushes, custom shapes, patterns with reorder |
|
||||
| UI-217-22 | Stamp Visible into a new layer keeping originals; Alt+Merge keeps originals | done | [#217](https://github.com/storytold/photocraft/issues/217) | stamp_cmds.rs layer.stampVisible (Cmd+Alt+Shift+E) merges every visible layer into a new layer above the active one and keeps the originals; layer.stampDown (Cmd+Alt+E) too. As in Photoshop they have no menu item of their own: Alt + Layer > Merge Visible / Merge Down / Merge Layers run them (stamp_cmds::alt_variant, menus.rs); stamp_tests.rs alt_click_on_merge_items_stamps and cmd_alt_shift_e_stamps_visible_and_can_be_rebound |
|
||||
| UI-217-23 | Layer clipboard: copy/paste whole layers (masks, styles, type) between documents | partial | [#217](https://github.com/storytold/photocraft/issues/217) | layer.copyToDocument copies layers into another open document keeping names, content, masks, styles and blending, converting to the destination's profile and depth, as one history step (layer_copy_cmds.rs, #589). It is the command a drag between documents dispatches; there is still no copy/paste layer clipboard |
|
||||
| UI-217-23 | Layer clipboard: copy/paste whole layers (masks, styles, type) between documents | partial | [#217](https://github.com/storytold/photocraft/issues/217) | Edit › Copy with no pixel selection takes layers whole and Paste recreates them in this or another open document, converted to its profile and depth, as one history step (edit_cmds.rs takes_whole, paste_layers): smart objects (#2428), type, shape and group layers (#2670), fill and adjustment layers (#2344), and several selected layers with their masks and styles (#2478). layer.copyToDocument is the drag between documents (layer_copy_cmds.rs, #589). Missing: a single pixel layer copies its pixels only, leaving its mask and styles behind |
|
||||
|
||||
## Type
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# PhotoCraft vs Adobe Photoshop: target-app parity
|
||||
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-13 · **Change:** minor (on-canvas corner radius widgets, TOOL-214-12; `.atn` import maps 112 events; Free Transform H/V skew fields; stale rows corrected against `main` and the scorecard, estimates unchanged; Photoshop Actions `.atn` load and save; 2026-10-10: Tilt-Shift measurements added; earlier the same day: major, full re-measure against Photoshop 2026 27.11.0; merged `parity-estimate.md` and the roadmap's honest assessment; stale missing-tool rows corrected: Color Replacement and Red Eye are live toolbar tools, Frame landed; percentages unchanged) · **Target:** Adobe Photoshop 2026
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-18 · **Change:** minor (fill and adjustment layers copy and paste whole, UI-217-23 partial, #2344; on-canvas corner radius widgets, TOOL-214-12; `.atn` import maps 112 events; Free Transform H/V skew fields; stale rows corrected against `main` and the scorecard, estimates unchanged; Photoshop Actions `.atn` load and save; 2026-10-10: Tilt-Shift measurements added; earlier the same day: major, full re-measure against Photoshop 2026 27.11.0; merged `parity-estimate.md` and the roadmap's honest assessment; stale missing-tool rows corrected: Color Replacement and Red Eye are live toolbar tools, Frame landed; percentages unchanged) · **Target:** Adobe Photoshop 2026
|
||||
|
||||
The authoritative answer to "how close is PhotoCraft to Photoshop, and how much work is left". The
|
||||
one-page summary is [`ROADMAP.md`](../ROADMAP.md); the ranked work list is [`gaps.md`](gaps.md);
|
||||
@@ -167,7 +167,7 @@ parity for the area and are already contained in the dimension rows above.
|
||||
|
||||
| Area | % | Hours | Notes |
|
||||
|---|---:|---:|---|
|
||||
| Layers, groups, masks, blend modes, smart objects, layer styles | 65% | 150–250 | Broad and GPU-accelerated. Open: layer clipboard between documents (UI-217-23: `layer.copyToDocument` exists, no copy/paste), smart-object perspective (FILE-215-6), a user contour library (FILE-215-15). Multi-layer Smart Object conversion (#2052, #2651), Stamp Visible (UI-217-22) and mask targeting by command (#2458) are done |
|
||||
| Layers, groups, masks, blend modes, smart objects, layer styles | 65% | 150–250 | Broad and GPU-accelerated. Open: a single pixel layer copies its pixels without its mask and styles (UI-217-23: smart object, type, shape, group, fill and adjustment layers and multi-layer selections copy and paste whole), smart-object perspective (FILE-215-6), a user contour library (FILE-215-15). Multi-layer Smart Object conversion (#2052, #2651), Stamp Visible (UI-217-22) and mask targeting by command (#2458) are done |
|
||||
| Selections, Select and Mask, channels | 55% | 120–200 | All selection tools, single row/column marquee included (#2837). Select and Mask is a dialog with Photoshop's view modes, a Refine Edge Brush and six outputs, not a workspace (TOOL-214-1), no Refine Hair (#2671); Select Subject/Sky classical, 559 ms p50 on 24 MP vs a 100 ms budget |
|
||||
| Painting and brush engine | 55% | 150–250 | Every Brush Settings section exists; feel is the gap: lag on big brushes, pressure jumps, smoothing and edge quality reports ([brush-parity.md](brush-parity.md)) |
|
||||
| Retouching (healing, clone, patch, remove, content-aware) | 50% | 100–180 | Remove tool non-generative; Content-Aware Fill has no workspace (TOOL-214-15); live stroke preview only for Brush/Eraser (TOOL-213-7) |
|
||||
@@ -565,6 +565,7 @@ See [method, raw measurements and reproduction](five-algorithm-performance.md).
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-18 | minor | Layers: with no selection, Copy takes fill and adjustment layers whole and Paste recreates them (#2344); UI-217-23 stays partial; percentages unchanged |
|
||||
| 2026-10-13 | minor | Vector shapes: on-canvas corner radius widgets on live rectangles (TOOL-214-12); estimates unchanged |
|
||||
| 2026-10-13 | minor | Stale "missing tool" rows corrected against main: Color Replacement (`paint.colorReplacement`), Red Eye (`paint.redEye`) and Add/Delete Anchor Point (the Pen flyout) are live toolbar tools and Frame landed, so Art History Brush is the only tool still missing; percentages unchanged |
|
||||
| 2026-10-12 | minor | Free Transform options bar H/V skew fields; percentages unchanged |
|
||||
|
||||
+1
-1
@@ -164,4 +164,4 @@ id = "UI-217-23"
|
||||
target = "Layer clipboard: copy/paste whole layers (masks, styles, type) between documents"
|
||||
status = "partial"
|
||||
issue = 217
|
||||
note = "layer.copyToDocument copies layers into another open document keeping names, content, masks, styles and blending, converting to the destination's profile and depth, as one history step (layer_copy_cmds.rs, #589). It is the command a drag between documents dispatches; there is still no copy/paste layer clipboard"
|
||||
note = "Edit › Copy with no pixel selection takes layers whole and Paste recreates them in this or another open document, converted to its profile and depth, as one history step (edit_cmds.rs takes_whole, paste_layers): smart objects (#2428), type, shape and group layers (#2670), fill and adjustment layers (#2344), and several selected layers with their masks and styles (#2478). layer.copyToDocument is the drag between documents (layer_copy_cmds.rs, #589). Missing: a single pixel layer copies its pixels only, leaving its mask and styles behind"
|
||||
Reference in new issue
Block a user