// 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)) }