From 40cde546bcfb46c3efa860a267e9bd04efd7641d Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 26 Apr 2018 13:09:36 -0400 Subject: [PATCH] Added a TextItem Struct to Artlayers. * Converted scripts to use the same getLayers() function from lib.js --- ps_test.go | 42 +++++++++--- scripts/fmtText.jsx | 12 ++-- scripts/getActiveDoc.jsx | 21 +----- scripts/getLayer.jsx | 6 +- scripts/getLayerSet.jsx | 12 ++-- scripts/lib.js | 22 ++++++ scripts/test.jsx | 6 +- structs.go | 143 ++++++++++++++++++++++++++++----------- 8 files changed, 179 insertions(+), 85 deletions(-) diff --git a/ps_test.go b/ps_test.go index 04ba17d..720ff16 100644 --- a/ps_test.go +++ b/ps_test.go @@ -122,14 +122,14 @@ func TestLayerSet(t *testing.T) { } func TestLayer(t *testing.T) { - _, err := Layer("Border/Inner Border") + _, err := layer("Border/Inner Border") if err != nil { t.Fatal(err) } } func TestMove(t *testing.T) { - lyr, err := Layer("Group 1/Layer 1") + lyr, err := layer("Group 1/Layer 1") if err != nil { t.Fatal(err) } @@ -182,15 +182,10 @@ func TestColor(t *testing.T) { } func TestApplyDataset(t *testing.T) { - out := []byte("done!\r\n") - ret, err := ApplyDataset(" Anger") + err := ApplyDataset("Anger") if err != nil { t.Fatal(err) } - if string(ret) != string(out) { - fail := fmt.Sprintf("TestJS failed.\ngot:\t\"%s\"\nwant:\t\"%s\"", ret, out) - t.Fatal(fail) - } } func TestDocumentLayerSet(t *testing.T) { @@ -248,6 +243,37 @@ func TestDoJs_HideLayer(t *testing.T) { } } +func TestTextItem(t *testing.T) { + // err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd") + // if err != nil { + // t.Fatal(err) + // } + + d, err := ActiveDocument() + if err != nil { + t.Fatal(err) + } + for _, lyr := range d.ArtLayers() { + if lyr.Name() == "Text" { + lyr.SetText("Butts") + lyr.FmtText(0, 5, "Arial", "Regular") + lyr.FmtText(0, 3, "Arial", "Bold") + } + } + + /* byt := []byte(`{"Name": "lyr", "TextItem": {"Contents": "lyr", "Size": 12.000, "Font": "ArialItalic"}}`) + lyr := &ArtLayer{} + // byt := []byte(`{"Name": "lyr"}`) + // lyr := &TextItem{} + err := lyr.UnmarshalJSON(byt) + fmt.Printf("%+v\n", lyr) + fmt.Println(lyr.TextItem) + if err != nil { + t.Fatal(err) + } + */ +} + func BenchmarkDoc_Go(b *testing.B) { for i := 0; i < b.N; i++ { _, err := ActiveDocument() diff --git a/scripts/fmtText.jsx b/scripts/fmtText.jsx index 9b88947..1a1f408 100644 --- a/scripts/fmtText.jsx +++ b/scripts/fmtText.jsx @@ -1,12 +1,12 @@ -var start = parseInt(arguments[1]); -var end = parseInt(arguments[2]); -var fontName = arguments[3]; -var fontStyle = arguments[4]; -var colorArray = [0, 0, 0]; if(app.activeDocument.activeLayer.kind == LayerKind.TEXT){ var activeLayer = app.activeDocument.activeLayer; - var fontSize = activeLayer.textItem.size; if(activeLayer.kind == LayerKind.TEXT){ + var start = parseInt(arguments[1]); + var end = parseInt(arguments[2]); + var fontName = arguments[3]; + var fontStyle = arguments[4]; + var fontSize = activeLayer.textItem.size; + var colorArray = [0, 0, 0]; if((activeLayer.textItem.contents != "")&&(start >= 0)&&(end <= activeLayer.textItem.contents.length)){ var idsetd = app.charIDToTypeID( "setd" ); var action = new ActionDescriptor(); diff --git a/scripts/getActiveDoc.jsx b/scripts/getActiveDoc.jsx index c8d2c06..bd46c9d 100644 --- a/scripts/getActiveDoc.jsx +++ b/scripts/getActiveDoc.jsx @@ -3,25 +3,8 @@ var stdout = newFile(arguments[0]); var doc = app.activeDocument; stdout.writeln(('{"Name": "'+doc.name+'", "Height":'+doc.height+ ', "Width":'+doc.width+', "ArtLayers": [').replace(/ px/g, "")); -function layers(lyrs) { - if (typeof lyrs === 'undefined') - return; - for (var i = 0; i < lyrs.length; i++) { - var lyr = lyrs[i]; - stdout.write(('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' + - lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' + - lyr.bounds[3] + ']], "Visible": ' + lyr.visible+', "Text":').replace(/ px/g, "")); - if (lyr.kind == LayerKind.TEXT) - stdout.write('"'+lyr.textItem.contents+'"'); - else - stdout.write("null"); - stdout.write("}") - if (i+1 != lyrs.length) - stdout.write(','); - stdout.writeln(); - } -} -layers(doc.artLayers) + +stdout.writeln(layers(doc.artLayers)) stdout.writeln('], "LayerSets": ['); function lyrSets(sets, nm) { if (typeof sets === 'undefined') diff --git a/scripts/getLayer.jsx b/scripts/getLayer.jsx index 0375de8..2e503a2 100644 --- a/scripts/getLayer.jsx +++ b/scripts/getLayer.jsx @@ -2,6 +2,9 @@ app.displayDialogs=DialogModes.NO var stdout = newFile(arguments[0]); var lyr = eval(arguments[1]); +var lyrs = [lyr]; +stdout.writeln(layers(lyrs)) +/* stdout.write(('{"Name":"' + lyr.name + '","Bounds":[[' + lyr.bounds[0] + ',' + lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' + lyr.bounds[3] + ']],"Visible":' + lyr.visible+',"Text":').replace(/ px/g, "")); @@ -11,4 +14,5 @@ if (lyr.kind == LayerKind.TEXT) { else stdout.write(null) stdout.writeln('}') -stdout.close(); \ No newline at end of file +stdout.close(); +*/ \ No newline at end of file diff --git a/scripts/getLayerSet.jsx b/scripts/getLayerSet.jsx index 24117de..546a142 100644 --- a/scripts/getLayerSet.jsx +++ b/scripts/getLayerSet.jsx @@ -3,6 +3,10 @@ var stdout = newFile(arguments[0]); var set = eval(arguments[1]); stdout.writeln('{"Name": "'+set.name+'", "Visible": '+ set.visible +', "ArtLayers":['); stdout.flush(); +var str = layers(set.artLayers); +str = str.replace(/\r/g, "\\r"); +stdout.writeln(str); +/* for (var i = 0; i < set.artLayers.length; i++) { var lyr = set.artLayers[i]; stdout.write(('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' + @@ -17,6 +21,7 @@ for (var i = 0; i < set.artLayers.length; i++) { stdout.writeln(","); stdout.flush(); } +*/ stdout.writeln("]"); stdout.write(', "LayerSets": [') for (var i = 0; i < set.layerSets.length; i++) { @@ -27,13 +32,6 @@ for (var i = 0; i < set.layerSets.length; i++) { stdout.flush() } stdout.writeln(']') -// app.activeDocument.activeLayer=set; -// set.merge(); -// set=eval(arguments[2]); stdout.write(', "Bounds": [[],[]]'); -// stdout.write((', "Bounds": [[' + set.bounds[0] + ',' + - // set.bounds[1] + '],[' + set.bounds[2] + ',' + - // set.bounds[3] + ']]').replace(/ px/g, "")); stdout.write("}"); -// Undo(); stdout.close(); \ No newline at end of file diff --git a/scripts/lib.js b/scripts/lib.js index a409c0b..25401b7 100644 --- a/scripts/lib.js +++ b/scripts/lib.js @@ -97,4 +97,26 @@ function setFormatting(start, end, fontName, fontStyle, fontSize, colorArray) { } } } +} + +function layers(lyrs) { + if (typeof lyrs === 'undefined') + return; + var str = ""; + for (var i = 0; i < lyrs.length; i++) { + var lyr = lyrs[i]; + str += ('{"Name":"' + lyr.name + '", "Bounds": [[' + lyr.bounds[0] + ',' + + lyr.bounds[1] + '],[' + lyr.bounds[2] + ',' + + lyr.bounds[3] + ']], "Visible": ' + lyr.visible+', "TextItem": ').replace(/ px/g, ""); + if (lyr.kind == LayerKind.TEXT) { + str += ('{"Contents": "'+lyr.textItem.contents+'",').replace(/\r/g, '\\r'); + str += (' "Size": '+lyr.textItem.size+',').replace(/ pt/g, ''); + str += ' "Font": "'+lyr.textItem.font+'"}\n' + } else + str += "null"; + str += "}"; + if (i+1 != lyrs.length) + str += ','; + } + return str } \ No newline at end of file diff --git a/scripts/test.jsx b/scripts/test.jsx index 7f6b4e1..05828f3 100644 --- a/scripts/test.jsx +++ b/scripts/test.jsx @@ -1,10 +1,10 @@ #include lib.js // var saveFile = File(arguments[0]); -var arg = 'app.activeDocument.layerSets.getByName("ResolveGem");'; +var arg = 'app.activeDocument.layerSets.getByName("Text").artLayers.getByName("short");'; var set = eval(arg); -set.visible=false; -alert(set.visible) +// set.textItem.size=10; +alert(set.textItem.font) // var doc=app.activeDocument // doc.layerSets.getByName("ResolveGem").merge(); // alert(doc.artLayers.getByName("ResolveGem").bounds); diff --git a/structs.go b/structs.go index 1768b8d..a9a328c 100644 --- a/structs.go +++ b/structs.go @@ -180,16 +180,16 @@ func (d *Document) Dump() { // ArtLayer reflects certain values from an Art Layer in a Photoshop document. // -// TODO: Make TextLayer a subclass of ArtLayer. +// TODO: (2) Make TextLayer a subclass of ArtLayer. type ArtLayer struct { - name string // The layer's name. - Text *string // The contents of a text layer. - bounds [2][2]int // The layers' corners. - parent Group // The LayerSet/Document this layer is in. - visible bool // Whether or not the layer is visible. - current bool // Whether we've checked this layer since we loaded from disk. - Color // The layer's color overlay. - *Stroke // The layer's stroke. + name string // The layer's name. + bounds [2][2]int // The layers' corners. + parent Group // The LayerSet/Document this layer is in. + visible bool // Whether or not the layer is visible. + current bool // Whether we've checked this layer since we loaded from disk. + Color // The layer's color overlay. + *Stroke // The layer's stroke. + *TextItem //The layer's text, if it's a text layer. } // Bounds returns the furthest corners of the ArtLayer. @@ -207,23 +207,12 @@ type ArtLayerJSON struct { Color [3]int Stroke [3]int StrokeAmt float32 - Text *string -} - -func (a *ArtLayer) SetText(txt string) { - lyr := strings.TrimRight(JSLayer(a.Path()), ";") - js := fmt.Sprintf("%s.textItem.contents='%s';", lyr, txt) - _, err := DoJs("compilejs.jsx", js) - if err != nil { - a.Text = &txt - } - a.Refresh() + TextItem *TextItem } // MarshalJSON implements the json.Marshaler interface, allowing the ArtLayer to be // saved to disk in JSON format. func (a *ArtLayer) MarshalJSON() ([]byte, error) { - // txt := strings.Replace(*a.Text, "\r", "\\r", -1) return json.Marshal(&ArtLayerJSON{ Name: a.name, Bounds: a.bounds, @@ -231,7 +220,7 @@ func (a *ArtLayer) MarshalJSON() ([]byte, error) { Color: a.Color.RGB(), Stroke: a.Stroke.RGB(), StrokeAmt: a.Stroke.Size, - Text: a.Text, + TextItem: a.TextItem, }) } @@ -245,11 +234,11 @@ func (a *ArtLayer) UnmarshalJSON(b []byte) error { a.Color = RGB{tmp.Color[0], tmp.Color[1], tmp.Color[2]} a.Stroke = &Stroke{tmp.StrokeAmt, RGB{tmp.Stroke[0], tmp.Stroke[1], tmp.Stroke[2]}} a.visible = tmp.Visible - if tmp.Text != nil { - // s := strings.Replace(*tmp.Text, "\\r", "\r", -1) - a.Text = tmp.Text - } a.current = false + a.TextItem = tmp.TextItem + if a.TextItem != nil { + a.TextItem.parent = a + } return nil } @@ -371,18 +360,6 @@ func (a *ArtLayer) Path() string { return fmt.Sprintf("%s%s", a.parent.Path(), a.name) } -// TODO: Documentation for Format() -func (a *ArtLayer) Format(start, end int, font, style string) { - if !a.Visible() { - return - } - _, err := DoJs("fmtText.jsx", fmt.Sprint(start), fmt.Sprint(end), - font, style) - if err != nil { - log.Panic(err) - } -} - // Layer returns an ArtLayer from the active document given a specified // path string. func layer(path string) (ArtLayer, error) { @@ -419,8 +396,6 @@ func (a *ArtLayer) Visible() bool { // SetPos snaps the given layer boundry to the given point. // Valid options for bound are: "TL", "TR", "BL", "BR" -// -// TODO: Test TR and BR func (a *ArtLayer) SetPos(x, y int, bound string) { if !a.visible || (x == 0 && y == 0) { return @@ -462,7 +437,10 @@ func (a *ArtLayer) Refresh() error { tmp.SetParent(a.Parent()) a.name = tmp.name a.bounds = tmp.bounds - a.Text = tmp.Text + a.TextItem = tmp.TextItem + if a.TextItem != nil { + a.TextItem.parent = a + } a.parent = tmp.Parent() a.visible = tmp.visible a.current = true @@ -721,3 +699,86 @@ func (l *LayerSet) Refresh() { l.visible = tmp.visible l.current = true } + +type TextItem struct { + contents string + size float64 + // color Color + font string + parent *ArtLayer +} + +type TextItemJSON struct { + Contents string + Size float64 + // Color [3]int + Font string +} + +func (t *TextItem) Contents() string { + return t.contents +} + +func (t *TextItem) Size() float64 { + return t.size +} + +// MarshalJSON implements the json.Marshaler interface, allowing the TextItem to be +// saved to disk in JSON format. +func (t *TextItem) MarshalJSON() ([]byte, error) { + return json.Marshal(&TextItemJSON{ + Contents: t.contents, + Size: t.size, + // Color: t.color.RGB(), + Font: t.font, + }) +} + +func (t *TextItem) UnmarshalJSON(b []byte) error { + tmp := &TextItemJSON{} + if err := json.Unmarshal(b, &tmp); err != nil { + return err + } + t.contents = tmp.Contents + t.size = tmp.Size + // t.color = RGB{tmp.Color[0], tmp.Color[1], tmp.Color[2]} + t.font = tmp.Font + return nil +} + +func (t *TextItem) SetText(txt string) { + if txt == t.contents { + return + } + lyr := strings.TrimRight(JSLayer(t.parent.Path()), ";") + js := fmt.Sprintf("%s.textItem.contents='%s';", lyr, txt) + _, err := DoJs("compilejs.jsx", js) + if err != nil { + t.contents = txt + } +} + +func (t *TextItem) SetSize(s float64) { + if t.size == s { + return + } + lyr := strings.TrimRight(JSLayer(t.parent.Path()), ";") + js := fmt.Sprintf("%s.textItem.size=%f;", lyr, s) + _, err := DoJs("compilejs.jsx", js) + if err != nil { + t.size = s + } +} + +// TODO: Documentation for Format(), make to textItem +func (t *TextItem) Fmt(start, end int, font, style string) { + var err error + if !t.parent.Visible() { + return + } + _, err = DoJs("fmtText.jsx", fmt.Sprint(start), fmt.Sprint(end), + font, style) + if err != nil { + log.Panic(err) + } +}