483 lines
14 KiB
Go
483 lines
14 KiB
Go
|
// Copyright 2010 The postscript-go Authors. All rights reserved.
|
|||
|
// created: 13/12/2010 by Laurent Le Goff
|
|||
|
|
|||
|
// Graphics operators
|
|||
|
package postscript
|
|||
|
|
|||
|
import (
|
|||
|
"image"
|
|||
|
"draw2d.googlecode.com/hg/draw2d"
|
|||
|
"math"
|
|||
|
"log"
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
//Path Construction Operators
|
|||
|
func newpath(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().BeginPath()
|
|||
|
}
|
|||
|
|
|||
|
func closepath(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().Close()
|
|||
|
}
|
|||
|
|
|||
|
func currentpoint(interpreter *Interpreter) {
|
|||
|
x, y := interpreter.GetGraphicContext().LastPoint()
|
|||
|
interpreter.Push(x)
|
|||
|
interpreter.Push(y)
|
|||
|
}
|
|||
|
|
|||
|
func moveto(interpreter *Interpreter) {
|
|||
|
y := interpreter.PopFloat()
|
|||
|
x := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().MoveTo(x, y)
|
|||
|
}
|
|||
|
|
|||
|
func rmoveto(interpreter *Interpreter) {
|
|||
|
y := interpreter.PopFloat()
|
|||
|
x := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().RMoveTo(x, y)
|
|||
|
}
|
|||
|
|
|||
|
func lineto(interpreter *Interpreter) {
|
|||
|
y := interpreter.PopFloat()
|
|||
|
x := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().LineTo(x, y)
|
|||
|
}
|
|||
|
|
|||
|
func rlineto(interpreter *Interpreter) {
|
|||
|
y := interpreter.PopFloat()
|
|||
|
x := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().RLineTo(x, y)
|
|||
|
}
|
|||
|
|
|||
|
func curveto(interpreter *Interpreter) {
|
|||
|
cy3 := interpreter.PopFloat()
|
|||
|
cx3 := interpreter.PopFloat()
|
|||
|
cy2 := interpreter.PopFloat()
|
|||
|
cx2 := interpreter.PopFloat()
|
|||
|
cy1 := interpreter.PopFloat()
|
|||
|
cx1 := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().CubicCurveTo(cx1, cy1, cx2, cy2, cx3, cy3)
|
|||
|
}
|
|||
|
|
|||
|
func rcurveto(interpreter *Interpreter) {
|
|||
|
cy3 := interpreter.PopFloat()
|
|||
|
cx3 := interpreter.PopFloat()
|
|||
|
cy2 := interpreter.PopFloat()
|
|||
|
cx2 := interpreter.PopFloat()
|
|||
|
cy1 := interpreter.PopFloat()
|
|||
|
cx1 := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().RCubicCurveTo(cx1, cy1, cx2, cy2, cx3, cy3)
|
|||
|
}
|
|||
|
|
|||
|
func arc(interpreter *Interpreter) {
|
|||
|
angle2 := interpreter.PopFloat() * (math.Pi / 180.0)
|
|||
|
angle1 := interpreter.PopFloat() * (math.Pi / 180.0)
|
|||
|
r := interpreter.PopFloat()
|
|||
|
y := interpreter.PopFloat()
|
|||
|
x := interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().ArcTo(x, y, r, r, angle1, angle2-angle1)
|
|||
|
}
|
|||
|
|
|||
|
func clippath(interpreter *Interpreter) {
|
|||
|
log.Printf("clippath not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func stroke(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().Stroke()
|
|||
|
}
|
|||
|
|
|||
|
func fill(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().Fill()
|
|||
|
}
|
|||
|
|
|||
|
func gsave(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().Save()
|
|||
|
}
|
|||
|
|
|||
|
func grestore(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().Restore()
|
|||
|
}
|
|||
|
|
|||
|
func setgray(interpreter *Interpreter) {
|
|||
|
gray := interpreter.PopFloat()
|
|||
|
color := image.RGBAColor{uint8(gray * 0xff), uint8(gray * 0xff), uint8(gray * 0xff), 0xff}
|
|||
|
interpreter.GetGraphicContext().SetStrokeColor(color)
|
|||
|
interpreter.GetGraphicContext().SetFillColor(color)
|
|||
|
}
|
|||
|
|
|||
|
func setrgbcolor(interpreter *Interpreter) {
|
|||
|
blue := interpreter.PopFloat()
|
|||
|
green := interpreter.PopFloat()
|
|||
|
red := interpreter.PopFloat()
|
|||
|
color := image.RGBAColor{uint8(red * 0xff), uint8(green * 0xff), uint8(blue * 0xff), 0xff}
|
|||
|
interpreter.GetGraphicContext().SetStrokeColor(color)
|
|||
|
interpreter.GetGraphicContext().SetFillColor(color)
|
|||
|
}
|
|||
|
|
|||
|
func hsbtorgb(hue, saturation, brightness float64) (red, green, blue int) {
|
|||
|
var fr, fg, fb float64
|
|||
|
if saturation == 0 {
|
|||
|
fr, fg, fb = brightness, brightness, brightness
|
|||
|
} else {
|
|||
|
H := (hue - math.Floor(hue)) * 6
|
|||
|
I := int(math.Floor(H))
|
|||
|
F := H - float64(I)
|
|||
|
M := brightness * (1 - saturation)
|
|||
|
N := brightness * (1 - saturation*F)
|
|||
|
K := brightness * (1 - saturation*(1-F))
|
|||
|
|
|||
|
switch I {
|
|||
|
case 0:
|
|||
|
fr = brightness
|
|||
|
fg = K
|
|||
|
fb = M
|
|||
|
case 1:
|
|||
|
fr = N
|
|||
|
fg = brightness
|
|||
|
fb = M
|
|||
|
case 2:
|
|||
|
fr = M
|
|||
|
fg = brightness
|
|||
|
fb = K
|
|||
|
case 3:
|
|||
|
fr = M
|
|||
|
fg = N
|
|||
|
fb = brightness
|
|||
|
case 4:
|
|||
|
fr = K
|
|||
|
fg = M
|
|||
|
fb = brightness
|
|||
|
case 5:
|
|||
|
fr = brightness
|
|||
|
fg = M
|
|||
|
fb = N
|
|||
|
default:
|
|||
|
fr, fb, fg = 0, 0, 0
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
red = int(fr*255. + 0.5)
|
|||
|
green = int(fg*255. + 0.5)
|
|||
|
blue = int(fb*255. + 0.5)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
func sethsbcolor(interpreter *Interpreter) {
|
|||
|
brightness := interpreter.PopFloat()
|
|||
|
saturation := interpreter.PopFloat()
|
|||
|
hue := interpreter.PopFloat()
|
|||
|
red, green, blue := hsbtorgb(hue, saturation, brightness)
|
|||
|
color := image.RGBAColor{uint8(red), uint8(green), uint8(blue), 0xff}
|
|||
|
interpreter.GetGraphicContext().SetStrokeColor(color)
|
|||
|
interpreter.GetGraphicContext().SetFillColor(color)
|
|||
|
}
|
|||
|
|
|||
|
func setcmybcolor(interpreter *Interpreter) {
|
|||
|
black := interpreter.PopFloat()
|
|||
|
yellow := interpreter.PopFloat()
|
|||
|
magenta := interpreter.PopFloat()
|
|||
|
cyan := interpreter.PopFloat()
|
|||
|
|
|||
|
/* cyan = cyan / 255.0;
|
|||
|
magenta = magenta / 255.0;
|
|||
|
yellow = yellow / 255.0;
|
|||
|
black = black / 255.0; */
|
|||
|
|
|||
|
red := cyan*(1.0-black) + black
|
|||
|
green := magenta*(1.0-black) + black
|
|||
|
blue := yellow*(1.0-black) + black
|
|||
|
|
|||
|
red = (1.0-red)*255.0 + 0.5
|
|||
|
green = (1.0-green)*255.0 + 0.5
|
|||
|
blue = (1.0-blue)*255.0 + 0.5
|
|||
|
|
|||
|
color := image.RGBAColor{uint8(red), uint8(green), uint8(blue), 0xff}
|
|||
|
interpreter.GetGraphicContext().SetStrokeColor(color)
|
|||
|
interpreter.GetGraphicContext().SetFillColor(color)
|
|||
|
}
|
|||
|
|
|||
|
func setdash(interpreter *Interpreter) {
|
|||
|
offset := interpreter.PopInt()
|
|||
|
dash := interpreter.PopArray()
|
|||
|
log.Printf("setdash not yet implemented dash: %v, offset: %d \n", dash, offset)
|
|||
|
}
|
|||
|
|
|||
|
func setlinejoin(interpreter *Interpreter) {
|
|||
|
linejoin := interpreter.PopInt()
|
|||
|
switch linejoin {
|
|||
|
case 0:
|
|||
|
interpreter.GetGraphicContext().SetLineJoin(draw2d.MiterJoin)
|
|||
|
case 1:
|
|||
|
interpreter.GetGraphicContext().SetLineJoin(draw2d.RoundJoin)
|
|||
|
case 2:
|
|||
|
interpreter.GetGraphicContext().SetLineJoin(draw2d.BevelJoin)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func setlinecap(interpreter *Interpreter) {
|
|||
|
linecap := interpreter.PopInt()
|
|||
|
switch linecap {
|
|||
|
case 0:
|
|||
|
interpreter.GetGraphicContext().SetLineCap(draw2d.ButtCap)
|
|||
|
case 1:
|
|||
|
interpreter.GetGraphicContext().SetLineCap(draw2d.RoundCap)
|
|||
|
case 2:
|
|||
|
interpreter.GetGraphicContext().SetLineCap(draw2d.SquareCap)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func setmiterlimit(interpreter *Interpreter) {
|
|||
|
interpreter.PopInt()
|
|||
|
log.Printf("setmiterlimit not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func setlinewidth(interpreter *Interpreter) {
|
|||
|
interpreter.GetGraphicContext().SetLineWidth(interpreter.PopFloat())
|
|||
|
}
|
|||
|
|
|||
|
func showpage(interpreter *Interpreter) {
|
|||
|
log.Printf("showpage may be an implementation specific, override show page to generate multi page images")
|
|||
|
}
|
|||
|
|
|||
|
func show(interpreter *Interpreter) {
|
|||
|
s := interpreter.PopString()
|
|||
|
interpreter.GetGraphicContext().FillString(s)
|
|||
|
log.Printf("show not really implemented")
|
|||
|
}
|
|||
|
//ax ay string ashow – -> Add (ax , ay) to width of each glyph while showing string
|
|||
|
func ashow(interpreter *Interpreter) {
|
|||
|
log.Printf("ashow not really implemented")
|
|||
|
s := interpreter.PopString()
|
|||
|
interpreter.PopFloat()
|
|||
|
interpreter.PopFloat()
|
|||
|
interpreter.GetGraphicContext().FillString(s)
|
|||
|
}
|
|||
|
|
|||
|
func findfont(interpreter *Interpreter) {
|
|||
|
log.Printf("findfont not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func scalefont(interpreter *Interpreter) {
|
|||
|
log.Printf("scalefont not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func setfont(interpreter *Interpreter) {
|
|||
|
log.Printf("setfont not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func stringwidth(interpreter *Interpreter) {
|
|||
|
interpreter.Push(10.0)
|
|||
|
interpreter.Push(10.0)
|
|||
|
log.Printf("stringwidth not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func setflat(interpreter *Interpreter) {
|
|||
|
interpreter.Pop()
|
|||
|
log.Printf("setflat not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
func currentflat(interpreter *Interpreter) {
|
|||
|
interpreter.Push(1.0)
|
|||
|
log.Printf("currentflat not yet implemented")
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Coordinate System and Matrix operators
|
|||
|
func matrix(interpreter *Interpreter) {
|
|||
|
interpreter.Push(draw2d.NewIdentityMatrix())
|
|||
|
}
|
|||
|
|
|||
|
func initmatrix(interpreter *Interpreter) {
|
|||
|
interpreter.Push(draw2d.NewIdentityMatrix())
|
|||
|
}
|
|||
|
|
|||
|
func identmatrix(interpreter *Interpreter) {
|
|||
|
tr := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
ident := draw2d.NewIdentityMatrix()
|
|||
|
copy(tr[:], ident[:])
|
|||
|
interpreter.Push(tr)
|
|||
|
}
|
|||
|
|
|||
|
func defaultmatrix(interpreter *Interpreter) {
|
|||
|
tr := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
ident := draw2d.NewIdentityMatrix()
|
|||
|
copy(tr[:], ident[:])
|
|||
|
interpreter.Push(tr)
|
|||
|
}
|
|||
|
|
|||
|
func currentmatrix(interpreter *Interpreter) {
|
|||
|
tr := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
ctm := interpreter.GetGraphicContext().GetMatrixTransform()
|
|||
|
copy(tr[:], ctm[:])
|
|||
|
interpreter.Push(tr)
|
|||
|
}
|
|||
|
|
|||
|
func setmatrix(interpreter *Interpreter) {
|
|||
|
tr := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
interpreter.GetGraphicContext().SetMatrixTransform(tr)
|
|||
|
}
|
|||
|
|
|||
|
func concat(interpreter *Interpreter) {
|
|||
|
tr := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
interpreter.GetGraphicContext().ComposeMatrixTransform(tr)
|
|||
|
}
|
|||
|
func concatmatrix(interpreter *Interpreter) {
|
|||
|
tr3 := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
tr2 := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
tr1 := interpreter.Pop().(draw2d.MatrixTransform)
|
|||
|
result := tr1.Multiply(tr2)
|
|||
|
copy(tr3[:], result[:])
|
|||
|
interpreter.Push(tr3)
|
|||
|
}
|
|||
|
|
|||
|
func transform(interpreter *Interpreter) {
|
|||
|
value := interpreter.Pop()
|
|||
|
matrix, ok := value.(draw2d.MatrixTransform)
|
|||
|
var y float64
|
|||
|
if !ok {
|
|||
|
matrix = interpreter.GetGraphicContext().GetMatrixTransform()
|
|||
|
y = value.(float64)
|
|||
|
} else {
|
|||
|
y = interpreter.PopFloat()
|
|||
|
}
|
|||
|
x := interpreter.PopFloat()
|
|||
|
matrix.Transform(&x, &y)
|
|||
|
interpreter.Push(x)
|
|||
|
interpreter.Push(y)
|
|||
|
}
|
|||
|
|
|||
|
func itransform(interpreter *Interpreter) {
|
|||
|
value := interpreter.Pop()
|
|||
|
matrix, ok := value.(draw2d.MatrixTransform)
|
|||
|
var y float64
|
|||
|
if !ok {
|
|||
|
matrix = interpreter.GetGraphicContext().GetMatrixTransform()
|
|||
|
y = value.(float64)
|
|||
|
} else {
|
|||
|
y = interpreter.PopFloat()
|
|||
|
}
|
|||
|
x := interpreter.PopFloat()
|
|||
|
matrix.InverseTransform(&x, &y)
|
|||
|
interpreter.Push(x)
|
|||
|
interpreter.Push(y)
|
|||
|
}
|
|||
|
|
|||
|
func translate(interpreter *Interpreter) {
|
|||
|
value := interpreter.Pop()
|
|||
|
matrix, ok := value.(draw2d.MatrixTransform)
|
|||
|
var y float64
|
|||
|
if !ok {
|
|||
|
matrix = interpreter.GetGraphicContext().GetMatrixTransform()
|
|||
|
y = value.(float64)
|
|||
|
} else {
|
|||
|
y = interpreter.PopFloat()
|
|||
|
}
|
|||
|
x := interpreter.PopFloat()
|
|||
|
if !ok {
|
|||
|
interpreter.GetGraphicContext().Translate(x, y)
|
|||
|
} else {
|
|||
|
matrix = draw2d.NewTranslationMatrix(x, y).Multiply(matrix)
|
|||
|
interpreter.Push(matrix)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func rotate(interpreter *Interpreter) {
|
|||
|
value := interpreter.Pop()
|
|||
|
matrix, ok := value.(draw2d.MatrixTransform)
|
|||
|
var angle float64
|
|||
|
if !ok {
|
|||
|
matrix = interpreter.GetGraphicContext().GetMatrixTransform()
|
|||
|
angle = value.(float64) * math.Pi / 180
|
|||
|
} else {
|
|||
|
angle = interpreter.PopFloat() * math.Pi / 180
|
|||
|
}
|
|||
|
if !ok {
|
|||
|
interpreter.GetGraphicContext().Rotate(angle)
|
|||
|
} else {
|
|||
|
matrix = draw2d.NewRotationMatrix(angle).Multiply(matrix)
|
|||
|
interpreter.Push(matrix)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func scale(interpreter *Interpreter) {
|
|||
|
value := interpreter.Pop()
|
|||
|
matrix, ok := value.(draw2d.MatrixTransform)
|
|||
|
var y float64
|
|||
|
if !ok {
|
|||
|
matrix = interpreter.GetGraphicContext().GetMatrixTransform()
|
|||
|
y = value.(float64)
|
|||
|
} else {
|
|||
|
y = interpreter.PopFloat()
|
|||
|
}
|
|||
|
x := interpreter.PopFloat()
|
|||
|
if !ok {
|
|||
|
interpreter.GetGraphicContext().Scale(x, y)
|
|||
|
} else {
|
|||
|
matrix = draw2d.NewScaleMatrix(x, y).Multiply(matrix)
|
|||
|
interpreter.Push(matrix)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
func initDrawingOperators(interpreter *Interpreter) {
|
|||
|
|
|||
|
interpreter.SystemDefine("stroke", NewOperator(stroke))
|
|||
|
interpreter.SystemDefine("fill", NewOperator(fill))
|
|||
|
interpreter.SystemDefine("show", NewOperator(show))
|
|||
|
interpreter.SystemDefine("ashow", NewOperator(ashow))
|
|||
|
interpreter.SystemDefine("showpage", NewOperator(showpage))
|
|||
|
|
|||
|
interpreter.SystemDefine("findfont", NewOperator(findfont))
|
|||
|
interpreter.SystemDefine("scalefont", NewOperator(scalefont))
|
|||
|
interpreter.SystemDefine("setfont", NewOperator(setfont))
|
|||
|
interpreter.SystemDefine("stringwidth", NewOperator(stringwidth))
|
|||
|
|
|||
|
// Graphic state operators
|
|||
|
interpreter.SystemDefine("gsave", NewOperator(gsave))
|
|||
|
interpreter.SystemDefine("grestore", NewOperator(grestore))
|
|||
|
interpreter.SystemDefine("setrgbcolor", NewOperator(setrgbcolor))
|
|||
|
interpreter.SystemDefine("sethsbcolor", NewOperator(sethsbcolor))
|
|||
|
interpreter.SystemDefine("setcmybcolor", NewOperator(setcmybcolor))
|
|||
|
interpreter.SystemDefine("setcmykcolor", NewOperator(setcmybcolor))
|
|||
|
interpreter.SystemDefine("setgray", NewOperator(setgray))
|
|||
|
interpreter.SystemDefine("setdash", NewOperator(setdash))
|
|||
|
interpreter.SystemDefine("setlinejoin", NewOperator(setlinejoin))
|
|||
|
interpreter.SystemDefine("setlinecap", NewOperator(setlinecap))
|
|||
|
interpreter.SystemDefine("setmiterlimit", NewOperator(setmiterlimit))
|
|||
|
interpreter.SystemDefine("setlinewidth", NewOperator(setlinewidth))
|
|||
|
// Graphic state operators device dependent
|
|||
|
interpreter.SystemDefine("setflat", NewOperator(setflat))
|
|||
|
interpreter.SystemDefine("currentflat", NewOperator(currentflat))
|
|||
|
|
|||
|
// Coordinate System and Matrix operators
|
|||
|
interpreter.SystemDefine("matrix", NewOperator(matrix))
|
|||
|
interpreter.SystemDefine("initmatrix", NewOperator(initmatrix))
|
|||
|
interpreter.SystemDefine("identmatrix", NewOperator(identmatrix))
|
|||
|
interpreter.SystemDefine("defaultmatrix", NewOperator(defaultmatrix))
|
|||
|
interpreter.SystemDefine("currentmatrix", NewOperator(currentmatrix))
|
|||
|
interpreter.SystemDefine("setmatrix", NewOperator(setmatrix))
|
|||
|
interpreter.SystemDefine("concat", NewOperator(concat))
|
|||
|
interpreter.SystemDefine("concatmatrix", NewOperator(concatmatrix))
|
|||
|
|
|||
|
interpreter.SystemDefine("transform", NewOperator(transform))
|
|||
|
interpreter.SystemDefine("itransform", NewOperator(itransform))
|
|||
|
interpreter.SystemDefine("translate", NewOperator(translate))
|
|||
|
interpreter.SystemDefine("rotate", NewOperator(rotate))
|
|||
|
interpreter.SystemDefine("scale", NewOperator(scale))
|
|||
|
|
|||
|
//Path Construction Operators
|
|||
|
interpreter.SystemDefine("newpath", NewOperator(newpath))
|
|||
|
interpreter.SystemDefine("closepath", NewOperator(closepath))
|
|||
|
interpreter.SystemDefine("currentpoint", NewOperator(currentpoint))
|
|||
|
interpreter.SystemDefine("moveto", NewOperator(moveto))
|
|||
|
interpreter.SystemDefine("rmoveto", NewOperator(rmoveto))
|
|||
|
interpreter.SystemDefine("lineto", NewOperator(lineto))
|
|||
|
interpreter.SystemDefine("rlineto", NewOperator(rlineto))
|
|||
|
interpreter.SystemDefine("curveto", NewOperator(curveto))
|
|||
|
interpreter.SystemDefine("rcurveto", NewOperator(rcurveto))
|
|||
|
interpreter.SystemDefine("arc", NewOperator(arc))
|
|||
|
interpreter.SystemDefine("clippath", NewOperator(clippath))
|
|||
|
}
|