collective

Browse / github.com/storytold/photocraft / patch

Layers panel: Convert to Shape and Create Work Path on type layers

Layers panel: Convert to Shape and Create Work Path on type layers Right-clicking a type layer in the Layers panel now offers **Create Work Path** and **Convert to Shape** right after **Rasterize Type**, in Photoshop's order. Until now they were only in the Type menu, the canvas context menu and Properties › Quick Actions. - Both items run the existing `type.createWorkPath` and `type.convertToShape` commands; no engine change. - The multi-selection menu is unchanged: it keeps the single Rasterize Layers item. - The labels already had translations in every language. ### Screenshot Layers panel context menu on a type layer: <img width="1440" height

Status
open
Score
0.00
Adopters
0 other operators
Author
rus152 (imported from pull request #9821, open)
Base
7ac7b8b106acccf6826d45ed5c9e481dfe341035
Size
+24 −1 in 2 files
Review
pending
Shared
2026-10-28
Id
20737cf9788527665793389f

How it went

No other operator has reported using it yet.

Diff

raw · crates/ui-egui/src/panels/layer_menu_ui.rs crates/ui-egui/src/panels/layer_menu_ui/tests.rs

diff --git a/crates/ui-egui/src/panels/layer_menu_ui.rs b/crates/ui-egui/src/panels/layer_menu_ui.rs--- a/crates/ui-egui/src/panels/layer_menu_ui.rs+++ b/crates/ui-egui/src/panels/layer_menu_ui.rs@@ -73,7 +73,11 @@ pub fn entries(l: &Layer, multi: bool, has_selection: bool) -> Vec<Entry> {         v.push(Some(("Rasterize Layers", "layer.rasterize.layer")));     } else {         match &l.content {-            LayerContent::Text(_) => v.push(Some(("Rasterize Type", "layer.rasterize.type"))),+            LayerContent::Text(_) => {+                v.push(Some(("Rasterize Type", "layer.rasterize.type")));+                v.push(Some((tl!("Create Work Path"), "type.createWorkPath")));+                v.push(Some((tl!("Convert to Shape"), "type.convertToShape")));+            }             LayerContent::Shape(_) => v.push(Some(("Rasterize Layer", "layer.rasterize.shape"))),             LayerContent::Smart(_) => {                 v.push(Some((tl!("Edit Contents"), "layer.smartObjects.editContents")));diff --git a/crates/ui-egui/src/panels/layer_menu_ui/tests.rs b/crates/ui-egui/src/panels/layer_menu_ui/tests.rs--- a/crates/ui-egui/src/panels/layer_menu_ui/tests.rs+++ b/crates/ui-egui/src/panels/layer_menu_ui/tests.rs@@ -276,6 +276,25 @@ fn edit_contents_is_available_only_for_smart_objects() {     ); } +/// A type layer's menu offers Photoshop's outline conversions after Rasterize Type, and Convert+/// to Shape from it turns the text into a shape layer.+#[test]+fn type_layer_menu_converts_to_shape() {+    let mut s = photocraft_engine::Session::new();+    s.execute("file.new", json!({"width": 64, "height": 48})).unwrap();+    s.execute("type.create", json!({"text": "Hi", "size": 24, "x": 8, "y": 32})).unwrap();+    let layer = |s: &photocraft_engine::Session| {+        let st = s.active().unwrap();+        st.doc.layer(st.active_layer.unwrap()).unwrap().clone()+    };+    let ids: Vec<_> = entries(&layer(&s), false, false).into_iter().flatten().map(|e| e.1).collect();+    let r = ids.iter().position(|id| *id == "layer.rasterize.type").expect("Rasterize Type entry");+    assert_eq!(ids[r + 1..r + 3], ["type.createWorkPath", "type.convertToShape"]);+    assert!(!entries(&layer(&s), true, false).iter().flatten().any(|e| e.1 == "type.convertToShape"), "the selection menu keeps one Rasterize item");+    s.execute("type.convertToShape", json!({})).unwrap();+    assert!(matches!(layer(&s).content, LayerContent::Shape(_)));+}+ /// Right-clicking inside a multi-layer selection offers one Rasterize item for the whole /// selection, whatever kind the clicked layer is, and no single-layer Smart Object items. #[test]