unipdf/ps/object.go
2019-05-16 20:44:51 +00:00

275 lines
4.8 KiB
Go

/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package ps
import (
"fmt"
)
// PSObject represents a postscript object.
type PSObject interface {
// Duplicate makes a fresh copy of the PSObject.
Duplicate() PSObject
// DebugString returns a descriptive representation of the PSObject with more information than String()
// for debugging purposes.
DebugString() string
// String returns a string representation of the PSObject.
String() string
}
// PSInteger represents an integer.
type PSInteger struct {
Val int
}
func (int *PSInteger) Duplicate() PSObject {
obj := PSInteger{}
obj.Val = int.Val
return &obj
}
func (int *PSInteger) DebugString() string {
return fmt.Sprintf("int:%d", int.Val)
}
func (int *PSInteger) String() string {
return fmt.Sprintf("%d", int.Val)
}
// PSReal represents a real number.
type PSReal struct {
Val float64
}
func (real *PSReal) DebugString() string {
return fmt.Sprintf("real:%.5f", real.Val)
}
func (real *PSReal) String() string {
return fmt.Sprintf("%.5f", real.Val)
}
func (real *PSReal) Duplicate() PSObject {
obj := PSReal{}
obj.Val = real.Val
return &obj
}
// PSBoolean represents a boolean value.
type PSBoolean struct {
Val bool
}
func (bool *PSBoolean) DebugString() string {
return fmt.Sprintf("bool:%v", bool.Val)
}
func (bool *PSBoolean) String() string {
return fmt.Sprintf("%v", bool.Val)
}
func (bool *PSBoolean) Duplicate() PSObject {
obj := PSBoolean{}
obj.Val = bool.Val
return &obj
}
// PSProgram defines a Postscript program which is a series of PS objects (arguments, commands, programs etc).
type PSProgram []PSObject
// NewPSProgram returns an empty, initialized PSProgram.
func NewPSProgram() *PSProgram {
return &PSProgram{}
}
// Append appends an object to the PSProgram.
func (prog *PSProgram) Append(obj PSObject) {
*prog = append(*prog, obj)
}
func (prog *PSProgram) DebugString() string {
s := "{ "
for _, obj := range *prog {
s += obj.DebugString()
s += " "
}
s += "}"
return s
}
func (prog *PSProgram) String() string {
s := "{ "
for _, obj := range *prog {
s += obj.String()
s += " "
}
s += "}"
return s
}
func (prog *PSProgram) Duplicate() PSObject {
prog2 := &PSProgram{}
for _, obj := range *prog {
prog2.Append(obj.Duplicate())
}
return prog2
}
// Exec executes the program, typically leaving output values on the stack.
func (prog *PSProgram) Exec(stack *PSStack) error {
for _, obj := range *prog {
var err error
switch t := obj.(type) {
case *PSInteger:
number := t
err = stack.Push(number)
case *PSReal:
number := t
err = stack.Push(number)
case *PSBoolean:
val := t
err = stack.Push(val)
case *PSProgram:
function := t
err = stack.Push(function)
case *PSOperand:
op := t
err = op.Exec(stack)
default:
return ErrTypeCheck
}
if err != nil {
return err
}
}
return nil
}
// PSOperand represents a Postscript operand (text string).
type PSOperand string
func (op *PSOperand) DebugString() string {
return fmt.Sprintf("op:'%s'", *op)
}
func (op *PSOperand) String() string {
return fmt.Sprintf("%s", *op)
}
func (op *PSOperand) Duplicate() PSObject {
s := *op
return &s
}
// Exec executes the operand `op` in the state specified by `stack`.
func (op *PSOperand) Exec(stack *PSStack) error {
err := ErrUnsupportedOperand
switch *op {
case "abs":
err = op.abs(stack)
case "add":
err = op.add(stack)
case "and":
err = op.and(stack)
case "atan":
err = op.atan(stack)
case "bitshift":
err = op.bitshift(stack)
case "ceiling":
err = op.ceiling(stack)
case "copy":
err = op.copy(stack)
case "cos":
err = op.cos(stack)
case "cvi":
err = op.cvi(stack)
case "cvr":
err = op.cvr(stack)
case "div":
err = op.div(stack)
case "dup":
err = op.dup(stack)
case "eq":
err = op.eq(stack)
case "exch":
err = op.exch(stack)
case "exp":
err = op.exp(stack)
case "floor":
err = op.floor(stack)
case "ge":
err = op.ge(stack)
case "gt":
err = op.gt(stack)
case "idiv":
err = op.idiv(stack)
case "if":
err = op.ifCondition(stack)
case "ifelse":
err = op.ifelse(stack)
case "index":
err = op.index(stack)
case "le":
err = op.le(stack)
case "log":
err = op.log(stack)
case "ln":
err = op.ln(stack)
case "lt":
err = op.lt(stack)
case "mod":
err = op.mod(stack)
case "mul":
err = op.mul(stack)
case "ne":
err = op.ne(stack)
case "neg":
err = op.neg(stack)
case "not":
err = op.not(stack)
case "or":
err = op.or(stack)
case "pop":
err = op.pop(stack)
case "round":
err = op.round(stack)
case "roll":
err = op.roll(stack)
case "sin":
err = op.sin(stack)
case "sqrt":
err = op.sqrt(stack)
case "sub":
err = op.sub(stack)
case "truncate":
err = op.truncate(stack)
case "xor":
err = op.xor(stack)
}
return err
}