Merge branch 'hotfix/v1.0' into develop

This commit is contained in:
Unknown
2018-04-28 15:55:54 -04:00
5 changed files with 99 additions and 82 deletions

View File

@@ -14,7 +14,7 @@ type Color interface {
Hex() []uint8 // The color in hexadecimal format. 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 { func Compare(a, b Color) Color {
A := a.RGB() A := a.RGB()
B := b.RGB() B := b.RGB()
@@ -26,7 +26,7 @@ func Compare(a, b Color) Color {
return b 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 { type RGB struct {
Red int Red int
Green int Green int
@@ -38,9 +38,10 @@ func (r RGB) RGB() [3]int {
return [3]int{r.Red, r.Green, r.Blue} return [3]int{r.Red, r.Green, r.Blue}
} }
// TODO: Implement RGB.Hex()
func (r RGB) Hex() []uint8 { 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. // Hex is a color in hexadecimal format. It implements the Color interface.

10
examples_test.go Normal file
View File

@@ -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');
}

129
ps.go
View File

@@ -2,6 +2,8 @@
// The interaction between the two is implemented using Javascript/VBScript. // The interaction between the two is implemented using Javascript/VBScript.
// //
// Currently only supports Photoshop CS5 Windows x86_64. // Currently only supports Photoshop CS5 Windows x86_64.
//
// TODO: Creatue a Photoshop struct to hold program values and functions.
package ps package ps
import ( import (
@@ -9,12 +11,12 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
// "log"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
// "update"
) )
// The name of the program that runs scripts on this OS. // The name of the program that runs scripts on this OS.
@@ -34,11 +36,16 @@ func init() {
case "darwin": case "darwin":
scmd = "osacript" scmd = "osacript"
} }
// update.Update()
} }
// Start opens Photoshop. // ApplyDataset fills out a template file with information
func Start() error { // from a given dataset (csv) file. It is important to note that running this
_, err := run("start") // 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 return err
} }
@@ -48,28 +55,14 @@ func Close(save PSSaveOptions) error {
return err return err
} }
// Open opens a Photoshop document with the specified path. // DoAction runs the Photoshop Action "name" from the Action Set "set".
// If Photoshop is not currently running, it is started before func DoAction(set, name string) error {
// opening the document. _, err := run("action", set, name)
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)
return err return err
} }
// DoJs runs a Photoshop Javascript script file (.jsx) from the specified location. // 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. // a temporary file ($TEMP/js_out.txt), whose contents is then read and returned.
func DoJs(path string, args ...string) (out []byte, err error) { func DoJs(path string, args ...string) (out []byte, err error) {
// Temp file for js to output to. // Temp file for js to output to.
@@ -97,16 +90,43 @@ func DoJs(path string, args ...string) (out []byte, err error) {
return cmd, err return cmd, err
} }
// Wait prints a message to the console and halts operation until the user // JSLayer "compiles" Javascript code to get an ArtLayer with the given path.
// signals that they are ready (by pushing enter). // 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 // TODO: get rid of the semicolon.
// otherwise automated process. (i.e. loading a dataset). func JSLayer(path string, art ...bool) string {
func Wait(msg string) { path = strings.TrimLeft(path, "/")
fmt.Print(msg) pth := strings.Split(path, "/")
var input string js := "app.activeDocument"
fmt.Scanln(&input) last := len(pth) - 1
fmt.Println() 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. // 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 return out.Bytes(), nil
} }
// DoAction runs the Photoshop Action "name" from the Action Set "set". // SaveAs saves the Photoshop document to the given location.
func DoAction(set, name string) error { func SaveAs(path string) error {
_, err := run("action", set, name) _, err := run("save", path)
return err return err
} }
// ApplyDataset fills out a template file with information // Start opens Photoshop.
// from a given dataset (csv) file. It is important to note that running this func Start() error {
// function will change data in the Photoshop document, but will not update _, err := run("start")
// 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 return err
} }
// JSLayer "compiles" Javascript code to get an ArtLayer with the given path. // Wait prints a message to the console and halts operation until the user
// The output always ends with a semicolon, so if you want to access a specific // signals that they are ready to continue (by pushing enter).
// property of the layer, you'll have to trim the output before concatenating.
// //
// TODO: get rid of the semicolon. // Useful for when you need to do something by hand in the middle of an
func JSLayer(path string, art ...bool) string { // otherwise automated process. (i.e. importing a dataset).
path = strings.TrimLeft(path, "/") func Wait(msg string) {
pth := strings.Split(path, "/") fmt.Print(msg)
js := "app.activeDocument" var input string
last := len(pth) - 1 fmt.Scanln(&input)
if len(art) > 0 { fmt.Println()
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 + ";"
} }

View File

@@ -1,3 +1,4 @@
// TODO: Update package tests.
package ps package ps
import ( import (
@@ -256,8 +257,8 @@ func TestTextItem(t *testing.T) {
for _, lyr := range d.ArtLayers() { for _, lyr := range d.ArtLayers() {
if lyr.Name() == "Text" { if lyr.Name() == "Text" {
lyr.SetText("Butts") lyr.SetText("Butts")
lyr.FmtText(0, 5, "Arial", "Regular") // lyr.FmtText(0, 5, "Arial", "Regular")
lyr.FmtText(0, 3, "Arial", "Bold") // lyr.FmtText(0, 3, "Arial", "Bold")
} }
} }

View File

@@ -72,6 +72,10 @@ func (d *Document) Name() string {
return d.name return d.name
} }
func (d *Document) Parent() Group {
return nil
}
// The height of the document, in pixels. // The height of the document, in pixels.
func (d *Document) Height() int { func (d *Document) Height() int {
return d.height return d.height
@@ -100,9 +104,6 @@ func (d *Document) LayerSet(name string) *LayerSet {
return nil return nil
} }
func (d *Document) Parent() Group {
return nil
}
func (d *Document) SetParent(g Group) {} func (d *Document) SetParent(g Group) {}
func (d *Document) Path() string { func (d *Document) Path() string {
@@ -178,21 +179,21 @@ func (d *Document) Dump() {
f.Write(byt) 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: (2) Make TextLayer a subclass of ArtLayer. // TODO: (2) Make TextLayer a subclass of ArtLayer.
type ArtLayer struct { type ArtLayer struct {
name string // The layer's name. name string // The layer's name.
bounds [2][2]int // The layers' corners. bounds [2][2]int // The corners of the layer's bounding box.
parent Group // The LayerSet/Document this layer is in. parent Group // The LayerSet/Document this layer is in.
visible bool // Whether or not the layer is visible. visible bool // Whether or not the layer is visible.
current bool // Whether we've checked this layer since we loaded from disk. current bool // Whether we've checked this layer since we loaded from disk.
Color // The layer's color overlay. Color // The layer's color overlay effect (if any).
*Stroke // The layer's stroke. *Stroke // The layer's stroke effect (if any).
*TextItem //The layer's text, if it's a text layer. *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 { func (a *ArtLayer) Bounds() [2][2]int {
return a.bounds return a.bounds
} }
@@ -246,6 +247,11 @@ func (a *ArtLayer) Name() string {
return a.name 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. // X1 returns the layer's leftmost x value.
func (a *ArtLayer) X1() int { func (a *ArtLayer) X1() int {
return a.bounds[0][0] return a.bounds[0][0]
@@ -352,10 +358,6 @@ func (a *ArtLayer) SetStroke(stk Stroke, fill Color) {
} }
} }
func (a *ArtLayer) Parent() Group {
return a.parent
}
func (a *ArtLayer) Path() string { func (a *ArtLayer) Path() string {
return fmt.Sprintf("%s%s", a.parent.Path(), a.name) return fmt.Sprintf("%s%s", a.parent.Path(), a.name)
} }