From c8420a46ff5dba3d90fe0dfd5eb09d198aa8b7f6 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 28 Apr 2018 15:55:04 -0400 Subject: [PATCH] gitflow-hotfix-stash: v1.0 --- colors.go | 9 ++-- examples_test.go | 10 ++++ ps.go | 129 ++++++++++++++++++++++++----------------------- ps_test.go | 32 ++++++++++++ structs.go | 36 ++++++------- 5 files changed, 132 insertions(+), 84 deletions(-) create mode 100644 examples_test.go diff --git a/colors.go b/colors.go index 0586a73..5d43d1d 100644 --- a/colors.go +++ b/colors.go @@ -14,7 +14,7 @@ type Color interface { Hex() []uint8 // The color in hexadecimal format. } -// Compare determines which of two colors is "brighter". +// Compare returns the brighter of a and b. func Compare(a, b Color) Color { A := a.RGB() B := b.RGB() @@ -26,7 +26,7 @@ func Compare(a, b Color) Color { return b } -// RGB is a color in RGB format. It implements the Color interface. +// RGB is a color format. It implements the Color interface. type RGB struct { Red int Green int @@ -38,9 +38,10 @@ func (r RGB) RGB() [3]int { return [3]int{r.Red, r.Green, r.Blue} } -// TODO: Implement RGB.Hex() func (r RGB) Hex() []uint8 { - return make([]uint8, 6) + src := []byte([]uint8{uint8(r.Red), uint8(r.Green), uint8(r.Blue)}) + hex := make([]byte, hex.EncodedLen(len(src))) + return []uint8(hex) } // Hex is a color in hexadecimal format. It implements the Color interface. diff --git a/examples_test.go b/examples_test.go new file mode 100644 index 0000000..4b6e479 --- /dev/null +++ b/examples_test.go @@ -0,0 +1,10 @@ +package ps + +import "fmt" + +func ExampleJSLayer() { + // The path of a layer inside a top level group. + path := "/Group 1/Layer 1" + fmt.Println(JSLayer(path)) + // Output: app.activeDocument.layerSets.getByName('Group 1').artLayers.getByName('Layer 1'); +} diff --git a/ps.go b/ps.go index 482d410..37d370f 100644 --- a/ps.go +++ b/ps.go @@ -2,6 +2,8 @@ // The interaction between the two is implemented using Javascript/VBScript. // // Currently only supports Photoshop CS5 Windows x86_64. +// +// TODO: Creatue a Photoshop struct to hold program values and functions. package ps import ( @@ -9,12 +11,12 @@ import ( "errors" "fmt" "io/ioutil" - // "log" "os" "os/exec" "path/filepath" "runtime" "strings" + // "update" ) // The name of the program that runs scripts on this OS. @@ -34,11 +36,16 @@ func init() { case "darwin": scmd = "osacript" } + // update.Update() } -// Start opens Photoshop. -func Start() error { - _, err := run("start") +// ApplyDataset fills out a template file with information +// from a given dataset (csv) file. It is important to note that running this +// function will change data in the Photoshop document, but will not update +// data in the Go Document struct- you will have to implement syncing +// them yourself. +func ApplyDataset(name string) error { + _, err := DoJs("applyDataset.jsx", name) return err } @@ -48,28 +55,14 @@ func Close(save PSSaveOptions) error { return err } -// Open opens a Photoshop document with the specified path. -// If Photoshop is not currently running, it is started before -// opening the document. -func Open(path string) error { - _, err := run("open", path) - return err -} - -// Quit exits Photoshop with the given saving option. -func Quit(save PSSaveOptions) error { - _, err := run("quit", save.String()) - return err -} - -// SaveAs saves the Photoshop document to the given location. -func SaveAs(path string) error { - _, err := run("save", path) +// DoAction runs the Photoshop Action "name" from the Action Set "set". +func DoAction(set, name string) error { + _, err := run("action", set, name) return err } // DoJs runs a Photoshop Javascript script file (.jsx) from the specified location. -// It can't directly return output, so instead the script must write their output to +// The script can't directly return output, so instead it writes output to // a temporary file ($TEMP/js_out.txt), whose contents is then read and returned. func DoJs(path string, args ...string) (out []byte, err error) { // Temp file for js to output to. @@ -97,16 +90,43 @@ func DoJs(path string, args ...string) (out []byte, err error) { return cmd, err } -// Wait prints a message to the console and halts operation until the user -// signals that they are ready (by pushing enter). +// JSLayer "compiles" Javascript code to get an ArtLayer with the given path. +// The output always ends with a semicolon, so if you want to access a specific +// property of the layer, you'll have to trim the output before concatenating. // -// Useful for when you need to do something by hand in the middle of an -// otherwise automated process. (i.e. loading a dataset). -func Wait(msg string) { - fmt.Print(msg) - var input string - fmt.Scanln(&input) - fmt.Println() +// TODO: get rid of the semicolon. +func JSLayer(path string, art ...bool) string { + path = strings.TrimLeft(path, "/") + pth := strings.Split(path, "/") + js := "app.activeDocument" + last := len(pth) - 1 + if len(art) > 0 { + pth = pth[:len(pth)-1] + last-- + } + if last > 0 { + for i := 0; i < last; i++ { + js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i]) + } + } + if pth[last] != "" { + js += fmt.Sprintf(".artLayers.getByName('%s')", pth[last]) + } + return js + ";" +} + +// Open opens a Photoshop document with the specified path. +// If Photoshop is not currently running, it is started before +// opening the document. +func Open(path string) error { + _, err := run("open", path) + return err +} + +// Quit exits Photoshop using the given save option. +func Quit(save PSSaveOptions) error { + _, err := run("quit", save.String()) + return err } // run handles running the script files, returning output, and displaying errors. @@ -143,43 +163,26 @@ func run(name string, args ...string) ([]byte, error) { return out.Bytes(), nil } -// DoAction runs the Photoshop Action "name" from the Action Set "set". -func DoAction(set, name string) error { - _, err := run("action", set, name) +// SaveAs saves the Photoshop document to the given location. +func SaveAs(path string) error { + _, err := run("save", path) return err } -// ApplyDataset fills out a template file with information -// from a given dataset (csv) file. It is important to note that running this -// function will change data in the Photoshop document, but will not update -// data in the Go Document struct- you will have to implement syncing -// them yourself. -func ApplyDataset(name string) error { - _, err := DoJs("applyDataset.jsx", name) +// Start opens Photoshop. +func Start() error { + _, err := run("start") return err } -// JSLayer "compiles" Javascript code to get an ArtLayer with the given path. -// The output always ends with a semicolon, so if you want to access a specific -// property of the layer, you'll have to trim the output before concatenating. +// Wait prints a message to the console and halts operation until the user +// signals that they are ready to continue (by pushing enter). // -// TODO: get rid of the semicolon. -func JSLayer(path string, art ...bool) string { - path = strings.TrimLeft(path, "/") - pth := strings.Split(path, "/") - js := "app.activeDocument" - last := len(pth) - 1 - if len(art) > 0 { - pth = pth[:len(pth)-1] - last-- - } - if last > 0 { - for i := 0; i < last; i++ { - js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i]) - } - } - if pth[last] != "" { - js += fmt.Sprintf(".artLayers.getByName('%s')", pth[last]) - } - return js + ";" +// Useful for when you need to do something by hand in the middle of an +// otherwise automated process. (i.e. importing a dataset). +func Wait(msg string) { + fmt.Print(msg) + var input string + fmt.Scanln(&input) + fmt.Println() } diff --git a/ps_test.go b/ps_test.go index 04ba17d..93d178c 100644 --- a/ps_test.go +++ b/ps_test.go @@ -1,3 +1,4 @@ +// TODO: Update package tests. package ps import ( @@ -248,6 +249,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/structs.go b/structs.go index 1768b8d..82ae262 100644 --- a/structs.go +++ b/structs.go @@ -72,6 +72,10 @@ func (d *Document) Name() string { return d.name } +func (d *Document) Parent() Group { + return nil +} + // The height of the document, in pixels. func (d *Document) Height() int { return d.height @@ -100,9 +104,6 @@ func (d *Document) LayerSet(name string) *LayerSet { return nil } -func (d *Document) Parent() Group { - return nil -} func (d *Document) SetParent(g Group) {} func (d *Document) Path() string { @@ -178,21 +179,21 @@ func (d *Document) Dump() { f.Write(byt) } -// ArtLayer reflects certain values from an Art Layer in a Photoshop document. +// ArtLayer reflects some values from an Art Layer in a Photoshop document. // // TODO: 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 corners of the layer's bounding box. + 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 effect (if any). + *Stroke // The layer's stroke effect (if any). + *TextItem // The layer's text, if it's a text layer. } -// Bounds returns the furthest corners of the ArtLayer. +// Bounds returns the coordinates of the corners of the ArtLayer's bounding box. func (a *ArtLayer) Bounds() [2][2]int { return a.bounds } @@ -257,6 +258,11 @@ func (a *ArtLayer) Name() string { return a.name } +// Parent returns the Document or LayerSet this layer is contained in. +func (a *ArtLayer) Parent() Group { + return a.parent +} + // X1 returns the layer's leftmost x value. func (a *ArtLayer) X1() int { return a.bounds[0][0] @@ -363,10 +369,6 @@ func (a *ArtLayer) SetStroke(stk Stroke, fill Color) { } } -func (a *ArtLayer) Parent() Group { - return a.parent -} - func (a *ArtLayer) Path() string { return fmt.Sprintf("%s%s", a.parent.Path(), a.name) }