Prepare other Graphic Context implementation like OpenGL

This commit is contained in:
Laurent Le Goff 2011-03-24 22:56:53 +01:00
commit 59128cdbf6
107 changed files with 346403 additions and 0 deletions

17
.project Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>draw2d</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.googlecode.goclipse.goBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>goclipse.goNature</nature>
</natures>
</projectDescription>

1
AUTHORS Normal file
View file

@ -0,0 +1 @@
Laurent Le Goff

18
LICENSE Normal file
View file

@ -0,0 +1,18 @@
Copyright (c) 2010, Laurent Le Goff
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
Makefile Normal file
View file

@ -0,0 +1,22 @@
include $(GOROOT)/src/Make.inc
all: install
install:
cd draw2d && make install
cd draw2dgl && make install
cd postscript && make install
clean:
cd draw2d && make clean
cd draw2dgl && make clean
cd postscript && make clean
cd cmd && make clean
nuke:
cd draw2d && make nuke
cd draw2dgl && make nuke
cd postscript && make nuke
command:
cd cmd && make

35
README Normal file
View file

@ -0,0 +1,35 @@
This package (written in *[http://golang.org go]*) provide an API to draw 2d geometrical form on [http://golang.org/pkg/image/ images].
This library is largely inspired by [http://www.tailrecursive.org/postscript/ postscript], [http://cairographics.org/ cairo], [http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#the-2d-drawing-context HTML5 canvas].
The package depends on [http://code.google.com/p/freetype-go/ freetype-go] package thanks to its rasterization algorithm.
Some algorithm have been translated from http://www.antigrain.com project ([http://www.antigrain.com/research/adaptive_bezier/index.html adaptive bezier], and arc drawing)
=== Installation ====
Once you have Go installed, to install draw2d:
* First see the installation procedure of [http://code.google.com/p/freetype-go/ freetype-go]
* goinstall draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d
a good starting point is the [http://code.google.com/p/draw2d/wiki/GettingStarted getting started]
=== [http://code.google.com/p/draw2d/wiki/Samples Samples] ===
Sample images generated by draw2d (inspired by [http://cairographics.org/samples/ cairo samples]):
there's already some bugs please refer to [http://code.google.com/p/draw2d/issues/list issue tracking]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestPath.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestDrawArc.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestDrawArcNegative.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestCurveRectangle.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestDrawCubicCurve.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestDash.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestFillStroke.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestFillStyle.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestMultiSegmentCaps.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestRoundRectangle.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestLineCap.png]
[http://draw2d.googlecode.com/svn/wiki/test_results/TestLineJoin.png]

17
cmd/Makefile Normal file
View file

@ -0,0 +1,17 @@
include $(GOROOT)/src/Make.inc
TARG=gettingStarted testdraw2d testX11draw testandroid testgopher testimage testpostscript
OFILES=$(TARG:%=%.$O)
all: $(TARG)
$(TARG): %: %.$O
$(LD) -o $@ $<
$(OFILES): %.$O: %.go Makefile
$(GC) -o $@ $<
clean:
rm -f *.[$(OS)] $(TARG) $(CLEANFILES)

46
cmd/gettingStarted.go Normal file
View file

@ -0,0 +1,46 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package main
import (
"fmt"
"log"
"os"
"bufio"
"image"
"image/png"
"draw2d.googlecode.com/hg/draw2d"
)
func saveToPngFile(filePath string, m image.Image) {
f, err := os.Open(filePath, os.O_CREAT|os.O_WRONLY, 0600)
if err != nil {
log.Println(err)
os.Exit(1)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, m)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Wrote %s OK.\n", filePath)
}
func main() {
i := image.NewRGBA(200, 200)
gc := draw2d.NewGraphicContext(i)
gc.MoveTo(10.0, 10.0)
gc.LineTo(100.0, 10.0)
gc.Stroke()
saveToPngFile("TestPath.png", i)
}

57
cmd/testX11draw.go Normal file
View file

@ -0,0 +1,57 @@
package main
import (
"fmt"
"exp/draw"
"exp/draw/x11"
"image"
"math"
"draw2d.googlecode.com/hg/draw2d"
)
func main() {
window, err := x11.NewWindow()
if err != nil {
fmt.Printf("Cannot open an x11 window\n")
return
}
screen := window.Screen()
gc := draw2d.NewGraphicContext(screen)
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
gc.Clear()
for i := 0.0; i < 360; i = i + 10 { // Go from 0 to 360 degrees in 10 degree steps
gc.BeginPath() // Start a new path
gc.Save() // Keep rotations temporary
gc.MoveTo(144, 144)
gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
gc.RLineTo(72, 0)
gc.Stroke()
gc.Restore() // Get back the unrotated state
}
window.FlushImage()
gc.SetLineWidth(3)
nbclick := 0
for {
switch evt := (<-window.EventChan()).(type) {
case draw.KeyEvent:
if evt.Key == 'q' {
window.Close()
}
case draw.MouseEvent:
if evt.Buttons&1 != 0 {
if nbclick%2 == 0 {
gc.MoveTo(float64(evt.Loc.X), float64(evt.Loc.Y))
} else {
gc.LineTo(float64(evt.Loc.X), float64(evt.Loc.Y))
gc.Stroke()
window.FlushImage()
}
nbclick = nbclick + 1
}
}
}
}

98
cmd/testandroid.go Normal file
View file

@ -0,0 +1,98 @@
package main
import (
"fmt"
"log"
"os"
"bufio"
"time"
"math"
"image"
"image/png"
"draw2d.googlecode.com/hg/draw2d"
)
const (
width, height = 178, 224
)
var (
lastTime int64
folder = "../resource/result/"
)
func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
i := image.NewRGBA(w, h)
gc := draw2d.NewGraphicContext(i)
lastTime = time.Nanoseconds()
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
// fill the background
//gc.Clear()
return i, gc
}
func saveToPngFile(TestName string, m image.Image) {
dt := time.Nanoseconds() - lastTime
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*10e-6)
filePath := folder + TestName + ".png"
f, err := os.Open(filePath, os.O_CREAT|os.O_WRONLY, 0600)
if err != nil {
log.Println(err)
os.Exit(1)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, m)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Wrote %s OK.\n", filePath)
}
func android(gc draw2d.GraphicContext, x, y float64) {
gc.SetLineCap(draw2d.RoundCap)
gc.SetLineWidth(5)
gc.ArcTo(x+80, y+70, 50, 50, 180*(math.Pi/180), 360*(math.Pi/180)) // head
gc.FillStroke()
gc.MoveTo(x+60, y+25)
gc.LineTo(x+50, y+10)
gc.MoveTo(x+100, y+25)
gc.LineTo(x+110, y+10)
gc.Stroke()
draw2d.Circle(gc, x+60, y+45, 5) // left eye
gc.FillStroke()
draw2d.Circle(gc, x+100, y+45, 5) // right eye
gc.FillStroke()
draw2d.RoundRect(gc, x+30, y+75, x+30+100, y+75+90, 10, 10) // body
gc.FillStroke()
draw2d.Rect(gc, x+30, y+75, x+30+100, y+75+80)
gc.FillStroke()
draw2d.RoundRect(gc, x+5, y+80, x+5+20, y+80+70, 10, 10) // left arm
gc.FillStroke()
draw2d.RoundRect(gc, x+135, y+80, x+135+20, y+80+70, 10, 10) // right arm
gc.FillStroke()
draw2d.RoundRect(gc, x+50, y+150, x+50+20, y+150+50, 10, 10) // left leg
gc.FillStroke()
draw2d.RoundRect(gc, x+90, y+150, x+90+20, y+150+50, 10, 10) // right leg
gc.FillStroke()
}
func main() {
i, gc := initGc(width, height)
gc.SetFillColor(image.RGBAColor{0xff, 0x44, 0x44, 0xff})
gc.SetStrokeColor(image.RGBAColor{0x44, 0x44, 0x44, 0xff})
android(gc, 10, 10)
saveToPngFile("TestAndroid", i)
}

523
cmd/testdraw2d.go Normal file
View file

@ -0,0 +1,523 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package main
import (
"fmt"
"log"
"os"
"bufio"
"time"
"math"
"image"
"image/png"
"draw2d.googlecode.com/hg/draw2d"
)
const (
w, h = 256, 256
)
var (
lastTime int64
folder = "../resource/result/"
)
func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
i := image.NewRGBA(w, h)
gc := draw2d.NewGraphicContext(i)
lastTime = time.Nanoseconds()
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
// fill the background
//gc.Clear()
return i, gc
}
func saveToPngFile(TestName string, m image.Image) {
dt := time.Nanoseconds() - lastTime
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*10e-6)
filePath := folder + TestName + ".png"
f, err := os.Open(filePath, os.O_CREAT|os.O_WRONLY, 0600)
if err != nil {
log.Println(err)
os.Exit(1)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, m)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Wrote %s OK.\n", filePath)
}
/*
<img src="../test_results/TestPath.png"/>
*/
func TestPath() {
i, gc := initGc(w, h)
gc.Translate(10, 10)
gc.MoveTo(0.0, 0.0)
gc.LineTo(100.0, 00.0)
gc.LineTo(100.0, 100.0)
gc.LineTo(0.0, 100.0)
gc.LineTo(0.0, 0.0)
gc.FillStroke()
saveToPngFile("TestPath", i)
}
/*
<img src="../test_results/TestDrawArc.png"/>
*/
func TestDrawArc() {
i, gc := initGc(w, h)
// draw an arc
xc, yc := 128.0, 128.0
radiusX, radiusY := 100.0, 100.0
startAngle := 45.0 * (math.Pi / 180.0) /* angles are specified */
angle := 135 * (math.Pi / 180.0) /* in radians */
gc.SetLineWidth(10)
gc.SetLineCap(draw2d.ButtCap)
gc.SetStrokeColor(image.Black)
gc.ArcTo(xc, yc, radiusX, radiusY, startAngle, angle)
gc.Stroke()
// fill a circle
gc.SetStrokeColor(image.NRGBAColor{255, 0x33, 0x33, 0x80})
gc.SetFillColor(image.NRGBAColor{255, 0x33, 0x33, 0x80})
gc.SetLineWidth(6)
gc.MoveTo(xc, yc)
gc.LineTo(xc+math.Cos(startAngle)*radiusX, yc+math.Sin(startAngle)*radiusY)
gc.MoveTo(xc, yc)
gc.LineTo(xc-radiusX, yc)
gc.Stroke()
gc.ArcTo(xc, yc, 10.0, 10.0, 0, 2*math.Pi)
gc.Fill()
saveToPngFile("TestDrawArc", i)
}
/*
<img src="../test_results/TestDrawArc.png"/>
*/
func TestDrawArcNegative() {
i, gc := initGc(w, h)
// draw an arc
xc, yc := 128.0, 128.0
radiusX, radiusY := 100.0, 100.0
startAngle := 45.0 * (math.Pi / 180.0) /* angles are specified */
angle := -225 * (math.Pi / 180.0) /* in radians */
gc.SetLineWidth(10)
gc.SetLineCap(draw2d.ButtCap)
gc.SetStrokeColor(image.Black)
gc.ArcTo(xc, yc, radiusX, radiusY, startAngle, angle)
gc.Stroke()
// fill a circle
gc.SetStrokeColor(image.NRGBAColor{255, 0x33, 0x33, 0x80})
gc.SetFillColor(image.NRGBAColor{255, 0x33, 0x33, 0x80})
gc.SetLineWidth(6)
gc.MoveTo(xc, yc)
gc.LineTo(xc+math.Cos(startAngle)*radiusX, yc+math.Sin(startAngle)*radiusY)
gc.MoveTo(xc, yc)
gc.LineTo(xc-radiusX, yc)
gc.Stroke()
gc.ArcTo(xc, yc, 10.0, 10.0, 0, 2*math.Pi)
gc.Fill()
saveToPngFile("TestDrawArcNegative", i)
}
func TestCurveRectangle() {
i, gc := initGc(w, h)
/* a custom shape that could be wrapped in a function */
x0, y0 := 25.6, 25.6 /* parameters like cairo_rectangle */
rect_width, rect_height := 204.8, 204.8
radius := 102.4 /* and an approximate curvature radius */
x1 := x0 + rect_width
y1 := y0 + rect_height
if rect_width/2 < radius {
if rect_height/2 < radius {
gc.MoveTo(x0, (y0+y1)/2)
gc.CubicCurveTo(x0, y0, x0, y0, (x0+x1)/2, y0)
gc.CubicCurveTo(x1, y0, x1, y0, x1, (y0+y1)/2)
gc.CubicCurveTo(x1, y1, x1, y1, (x1+x0)/2, y1)
gc.CubicCurveTo(x0, y1, x0, y1, x0, (y0+y1)/2)
} else {
gc.MoveTo(x0, y0+radius)
gc.CubicCurveTo(x0, y0, x0, y0, (x0+x1)/2, y0)
gc.CubicCurveTo(x1, y0, x1, y0, x1, y0+radius)
gc.LineTo(x1, y1-radius)
gc.CubicCurveTo(x1, y1, x1, y1, (x1+x0)/2, y1)
gc.CubicCurveTo(x0, y1, x0, y1, x0, y1-radius)
}
} else {
if rect_height/2 < radius {
gc.MoveTo(x0, (y0+y1)/2)
gc.CubicCurveTo(x0, y0, x0, y0, x0+radius, y0)
gc.LineTo(x1-radius, y0)
gc.CubicCurveTo(x1, y0, x1, y0, x1, (y0+y1)/2)
gc.CubicCurveTo(x1, y1, x1, y1, x1-radius, y1)
gc.LineTo(x0+radius, y1)
gc.CubicCurveTo(x0, y1, x0, y1, x0, (y0+y1)/2)
} else {
gc.MoveTo(x0, y0+radius)
gc.CubicCurveTo(x0, y0, x0, y0, x0+radius, y0)
gc.LineTo(x1-radius, y0)
gc.CubicCurveTo(x1, y0, x1, y0, x1, y0+radius)
gc.LineTo(x1, y1-radius)
gc.CubicCurveTo(x1, y1, x1, y1, x1-radius, y1)
gc.LineTo(x0+radius, y1)
gc.CubicCurveTo(x0, y1, x0, y1, x0, y1-radius)
}
}
gc.Close()
gc.SetFillColor(image.NRGBAColor{0x80, 0x80, 0xFF, 0xFF})
gc.SetStrokeColor(image.NRGBAColor{0x80, 0, 0, 0x80})
gc.SetLineWidth(10.0)
gc.FillStroke()
saveToPngFile("TestCurveRectangle", i)
}
/*
<img src="../test_results/TestDrawCubicCurve.png"/>
*/
func TestDrawCubicCurve() {
i, gc := initGc(w, h)
// draw a cubic curve
x, y := 25.6, 128.0
x1, y1 := 102.4, 230.4
x2, y2 := 153.6, 25.6
x3, y3 := 230.4, 128.0
gc.SetFillColor(image.NRGBAColor{0xAA, 0xAA, 0xAA, 0xFF})
gc.SetLineWidth(10)
gc.MoveTo(x, y)
gc.CubicCurveTo(x1, y1, x2, y2, x3, y3)
gc.Stroke()
gc.SetStrokeColor(image.NRGBAColor{0xFF, 0x33, 0x33, 0x88})
gc.SetLineWidth(6)
// draw segment of curve
gc.MoveTo(x, y)
gc.LineTo(x1, y1)
gc.LineTo(x2, y2)
gc.LineTo(x3, y3)
gc.Stroke()
saveToPngFile("TestDrawCubicCurve", i)
}
/*
<img src="../test_results/TestDash.png"/>
*/
func TestDash() {
i, gc := initGc(w, h)
gc.SetLineDash([]float64{50, 10, 10, 10}, -50.0)
gc.SetLineCap(draw2d.ButtCap)
gc.SetLineJoin(draw2d.BevelJoin)
gc.SetLineWidth(10)
gc.MoveTo(128.0, 25.6)
gc.LineTo(128.0, 25.6)
gc.LineTo(230.4, 230.4)
gc.RLineTo(-102.4, 0.0)
gc.CubicCurveTo(51.2, 230.4, 51.2, 128.0, 128.0, 128.0)
gc.Stroke()
gc.SetLineDash(nil, 0.0)
saveToPngFile("TestDash", i)
}
/*
<img src="../test_results/TestFillStroke.png"/>
*/
func TestFillStroke() {
i, gc := initGc(w, h)
gc.MoveTo(128.0, 25.6)
gc.LineTo(230.4, 230.4)
gc.RLineTo(-102.4, 0.0)
gc.CubicCurveTo(51.2, 230.4, 51.2, 128.0, 128.0, 128.0)
gc.Close()
gc.MoveTo(64.0, 25.6)
gc.RLineTo(51.2, 51.2)
gc.RLineTo(-51.2, 51.2)
gc.RLineTo(-51.2, -51.2)
gc.Close()
gc.SetLineWidth(10.0)
gc.SetFillColor(image.NRGBAColor{0, 0, 0xFF, 0xFF})
gc.SetStrokeColor(image.Black)
gc.FillStroke()
saveToPngFile("TestFillStroke", i)
}
/*
<img src="../test_results/TestFillStyle.png"/>
*/
func TestFillStyle() {
i, gc := initGc(w, h)
gc.SetLineWidth(6)
draw2d.Rect(gc, 12, 12, 244, 70)
wheel1 := new(draw2d.PathStorage)
wheel1.ArcTo(64, 64, 40, 40, 0, 2*math.Pi)
wheel2 := new(draw2d.PathStorage)
wheel2.ArcTo(192, 64, 40, 40, 0, 2*math.Pi)
gc.SetFillRule(draw2d.FillRuleEvenOdd)
gc.SetFillColor(image.NRGBAColor{0, 0xB2, 0, 0xFF})
gc.SetStrokeColor(image.Black)
gc.FillStroke(wheel1, wheel2)
draw2d.Rect(gc, 12, 140, 244, 198)
wheel1 = new(draw2d.PathStorage)
wheel1.ArcTo(64, 192, 40, 40, 0, 2*math.Pi)
wheel2 = new(draw2d.PathStorage)
wheel2.ArcTo(192, 192, 40, 40, 0, -2*math.Pi)
gc.SetFillRule(draw2d.FillRuleWinding)
gc.SetFillColor(image.NRGBAColor{0, 0, 0xE5, 0xFF})
gc.FillStroke(wheel1, wheel2)
saveToPngFile("TestFillStyle", i)
}
func TestMultiSegmentCaps() {
i, gc := initGc(w, h)
gc.MoveTo(50.0, 75.0)
gc.LineTo(200.0, 75.0)
gc.MoveTo(50.0, 125.0)
gc.LineTo(200.0, 125.0)
gc.MoveTo(50.0, 175.0)
gc.LineTo(200.0, 175.0)
gc.SetLineWidth(30.0)
gc.SetLineCap(draw2d.RoundCap)
gc.Stroke()
saveToPngFile("TestMultiSegmentCaps", i)
}
func TestRoundRectangle() {
i, gc := initGc(w, h)
/* a custom shape that could be wrapped in a function */
x, y := 25.6, 25.6
width, height := 204.8, 204.8
aspect := 1.0 /* aspect ratio */
corner_radius := height / 10.0 /* and corner curvature radius */
radius := corner_radius / aspect
degrees := math.Pi / 180.0
gc.ArcTo(x+width-radius, y+radius, radius, radius, -90*degrees, 90*degrees)
gc.ArcTo(x+width-radius, y+height-radius, radius, radius, 0*degrees, 90*degrees)
gc.ArcTo(x+radius, y+height-radius, radius, radius, 90*degrees, 90*degrees)
gc.ArcTo(x+radius, y+radius, radius, radius, 180*degrees, 90*degrees)
gc.Close()
gc.SetFillColor(image.NRGBAColor{0x80, 0x80, 0xFF, 0xFF})
gc.SetStrokeColor(image.NRGBAColor{0x80, 0, 0, 0x80})
gc.SetLineWidth(10.0)
gc.FillStroke()
saveToPngFile("TestRoundRectangle", i)
}
func TestLineCap() {
i, gc := initGc(w, h)
gc.SetLineWidth(30.0)
gc.SetLineCap(draw2d.ButtCap)
gc.MoveTo(64.0, 50.0)
gc.LineTo(64.0, 200.0)
gc.Stroke()
gc.SetLineCap(draw2d.RoundCap)
gc.MoveTo(128.0, 50.0)
gc.LineTo(128.0, 200.0)
gc.Stroke()
gc.SetLineCap(draw2d.SquareCap)
gc.MoveTo(192.0, 50.0)
gc.LineTo(192.0, 200.0)
gc.Stroke()
/* draw helping lines */
gc.SetStrokeColor(image.NRGBAColor{0xFF, 0x33, 0x33, 0xFF})
gc.SetLineWidth(2.56)
gc.MoveTo(64.0, 50.0)
gc.LineTo(64.0, 200.0)
gc.MoveTo(128.0, 50.0)
gc.LineTo(128.0, 200.0)
gc.MoveTo(192.0, 50.0)
gc.LineTo(192.0, 200.0)
gc.Stroke()
saveToPngFile("TestLineCap", i)
}
func TestLineJoin() {
i, gc := initGc(w, h)
gc.SetLineWidth(40.96)
gc.MoveTo(76.8, 84.48)
gc.RLineTo(51.2, -51.2)
gc.RLineTo(51.2, 51.2)
gc.SetLineJoin(draw2d.MiterJoin) /* default */
gc.Stroke()
gc.MoveTo(76.8, 161.28)
gc.RLineTo(51.2, -51.2)
gc.RLineTo(51.2, 51.2)
gc.SetLineJoin(draw2d.BevelJoin)
gc.Stroke()
gc.MoveTo(76.8, 238.08)
gc.RLineTo(51.2, -51.2)
gc.RLineTo(51.2, 51.2)
gc.SetLineJoin(draw2d.RoundJoin)
gc.Stroke()
saveToPngFile("TestLineJoin", i)
}
func TestBubble() {
i, gc := initGc(w, h)
gc.BeginPath()
gc.MoveTo(75, 25)
gc.QuadCurveTo(25, 25, 25, 62.5)
gc.QuadCurveTo(25, 100, 50, 100)
gc.QuadCurveTo(50, 120, 30, 125)
gc.QuadCurveTo(60, 120, 65, 100)
gc.QuadCurveTo(125, 100, 125, 62.5)
gc.QuadCurveTo(125, 25, 75, 25)
gc.Stroke()
saveToPngFile("TestBubble", i)
}
func TestStar() {
i, gc := initGc(w, h)
for i := 0.0; i < 360; i = i + 10 { // Go from 0 to 360 degrees in 10 degree steps
gc.Save()
gc.SetLineWidth(5) // Keep rotations temporary
gc.Translate(144, 144)
gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
gc.MoveTo(0, 0)
gc.LineTo(72, 0)
gc.Stroke()
gc.Restore()
}
saveToPngFile("TestStar", i)
}
func TestTransform() {
i, gc := initGc(800, 600)
gc.Save()
gc.Translate(40, 40) // Set origin to (40, 40)
gc.BeginPath()
gc.MoveTo(0, 0)
gc.RLineTo(72, 0)
gc.RLineTo(0, 72)
gc.RLineTo(-72, 0)
gc.Close()
gc.Stroke()
gc.Restore()
gc.Save()
gc.Translate(100, 150) // Translate origin to (100, 150)
gc.Rotate(30 * (math.Pi / 180.0)) // Rotate counter-clockwise by 30 degrees
gc.BeginPath()
gc.MoveTo(0, 0)
gc.RLineTo(72, 0)
gc.RLineTo(0, 72)
gc.RLineTo(-72, 0)
gc.Close() // Draw box...
gc.Stroke()
gc.Restore()
gc.Save()
gc.Translate(40, 300) // Translate to (40, 300)
gc.Scale(0.5, 1) // Reduce x coord by 1/2, y coord left alone
gc.BeginPath()
gc.MoveTo(0, 0)
gc.RLineTo(72, 0)
gc.RLineTo(0, 72)
gc.RLineTo(-72, 0)
gc.Close() // Draw box...
gc.Stroke()
gc.Restore()
gc.Save()
gc.Translate(300, 300) // Set origin to (300, 300)
gc.Rotate(45 * (math.Pi / 180.0)) // Rotate coordinates by 45 degrees
gc.Scale(0.5, 1) // Scale coordinates
gc.BeginPath()
gc.MoveTo(0, 0)
gc.RLineTo(72, 0)
gc.RLineTo(0, 72)
gc.RLineTo(-72, 0)
gc.Close() // Draw box
gc.Stroke()
gc.Restore()
saveToPngFile("TestTransform", i)
}
func TestPathTransform() {
i, gc := initGc(800, 600)
gc.SetLineWidth(20)
gc.Scale(1, 4)
gc.ArcTo(200, 80, 50, 50, 0, math.Pi*2)
gc.Close()
gc.Stroke()
saveToPngFile("TestPathTransform", i)
}
func TestFillString() {
draw2d.SetFontFolder("../resource/font/")
i, gc := initGc(100, 100)
draw2d.RoundRect(gc, 5, 5, 95, 95, 10, 10)
gc.FillStroke()
gc.SetFontSize(18)
gc.MoveTo(10, 52)
gc.SetFontData(draw2d.FontData{"luxi", draw2d.FontFamilyMono, draw2d.FontStyleBold | draw2d.FontStyleItalic})
width := gc.FillString("cou")
fmt.Printf("width: %f\n", width)
gc.RMoveTo(width+1, 0)
gc.FillString("cou")
saveToPngFile("TestFillString", i)
}
func main() {
TestPath()
TestDrawArc()
TestDrawArcNegative()
TestCurveRectangle()
TestDrawCubicCurve()
TestDash()
TestFillStroke()
TestFillStyle()
TestMultiSegmentCaps()
TestRoundRectangle()
TestLineCap()
TestLineJoin()
TestBubble()
TestStar()
TestTransform()
TestPathTransform()
TestFillString()
}

134
cmd/testgopher.go Normal file
View file

@ -0,0 +1,134 @@
package main
import (
"fmt"
"log"
"os"
"bufio"
"time"
"math"
"image"
"image/png"
"draw2d.googlecode.com/hg/draw2d"
)
const (
width, height = 300, 200
)
var (
lastTime int64
folder = "../resource/result/"
)
func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
i := image.NewRGBA(w, h)
gc := draw2d.NewGraphicContext(i)
lastTime = time.Nanoseconds()
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
// fill the background
//gc.Clear()
return i, gc
}
func saveToPngFile(TestName string, m image.Image) {
dt := time.Nanoseconds() - lastTime
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*10e-6)
filePath := folder + TestName + ".png"
f, err := os.Open(filePath, os.O_CREAT|os.O_WRONLY, 0600)
if err != nil {
log.Println(err)
os.Exit(1)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, m)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Wrote %s OK.\n", filePath)
}
func gordon(gc draw2d.GraphicContext, x, y, w, h float64) {
h23 := (h * 2) / 3
blf := image.RGBAColor{0, 0, 0, 0xff}
wf := image.RGBAColor{0xff, 0xff, 0xff, 0xff}
nf := image.RGBAColor{0x8B, 0x45, 0x13, 0xff}
brf := image.RGBAColor{0x8B, 0x45, 0x13, 0x99}
brb := image.RGBAColor{0x8B, 0x45, 0x13, 0xBB}
gc.MoveTo(x, y+h)
gc.CubicCurveTo(x, y+h, x+w/2, y-h, x+w, y+h)
gc.Close()
gc.SetFillColor(brb)
gc.Fill()
draw2d.RoundRect(gc, x, y+h, x+w, y+h+h, 10, 10)
gc.Fill()
draw2d.Circle(gc, x, y+h, w/12) // left ear
gc.SetFillColor(brf)
gc.Fill()
draw2d.Circle(gc, x, y+h, w/12-10)
gc.SetFillColor(nf)
gc.Fill()
draw2d.Circle(gc, x+w, y+h, w/12) // right ear
gc.SetFillColor(brf)
gc.Fill()
draw2d.Circle(gc, x+w, y+h, w/12-10)
gc.SetFillColor(nf)
gc.Fill()
draw2d.Circle(gc, x+w/3, y+h23, w/9) // left eye
gc.SetFillColor(wf)
gc.Fill()
draw2d.Circle(gc, x+w/3+10, y+h23, w/10-10)
gc.SetFillColor(blf)
gc.Fill()
draw2d.Circle(gc, x+w/3+15, y+h23, 5)
gc.SetFillColor(wf)
gc.Fill()
draw2d.Circle(gc, x+w-w/3, y+h23, w/9) // right eye
gc.Fill()
draw2d.Circle(gc, x+w-w/3+10, y+h23, w/10-10)
gc.SetFillColor(blf)
gc.Fill()
draw2d.Circle(gc, x+w-(w/3)+15, y+h23, 5)
gc.SetFillColor(wf)
gc.Fill()
gc.SetFillColor(wf)
draw2d.RoundRect(gc, x+w/2-w/8, y+h+30, x+w/2-w/8+w/8, y+h+30+w/6, 5, 5) // left tooth
gc.Fill()
draw2d.RoundRect(gc, x+w/2, y+h+30, x+w/2+w/8, y+h+30+w/6, 5, 5) // right tooth
gc.Fill()
draw2d.Ellipse(gc, x+(w/2), y+h+30, w/6, w/12) // snout
gc.SetFillColor(nf)
gc.Fill()
draw2d.Ellipse(gc, x+(w/2), y+h+10, w/10, w/12) // nose
gc.SetFillColor(blf)
gc.Fill()
}
func main() {
i, gc := initGc(width, height)
gc.Clear()
gc.Translate(-75, 58)
gc.Rotate(-30 * (math.Pi / 180.0))
gordon(gc, 48, 48, 240, 72)
saveToPngFile("TestGopher", i)
}

80
cmd/testimage.go Normal file
View file

@ -0,0 +1,80 @@
package main
import (
"fmt"
"log"
"os"
"bufio"
"math"
"image"
"time"
"image/png"
"draw2d.googlecode.com/hg/draw2d"
)
func saveToPngFile(filePath string, m image.Image) {
f, err := os.Open(filePath, os.O_CREAT|os.O_WRONLY, 0600)
if err != nil {
log.Println(err)
os.Exit(1)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, m)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Wrote %s OK.\n", filePath)
}
func loadFromPngFile(filePath string) image.Image {
f, err := os.Open(filePath, 0, 0)
if f == nil {
log.Printf("can't open file; err=%s\n", err.String())
return nil
}
defer f.Close()
b := bufio.NewReader(f)
i, err := png.Decode(b)
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Read %s OK.\n", filePath)
return i
}
func testBubble(gc draw2d.GraphicContext) {
gc.BeginPath()
gc.MoveTo(75, 25)
gc.QuadCurveTo(25, 25, 25, 62.5)
gc.QuadCurveTo(25, 100, 50, 100)
gc.QuadCurveTo(50, 120, 30, 125)
gc.QuadCurveTo(60, 120, 65, 100)
gc.QuadCurveTo(125, 100, 125, 62.5)
gc.QuadCurveTo(125, 25, 75, 25)
gc.Stroke()
}
func main() {
source := loadFromPngFile("../resource/image/Varna_Railway_Station_HDR.png")
i := image.NewRGBA(1024, 768)
gc := draw2d.NewGraphicContext(i)
gc.Scale(2, 0.5)
//gc.Translate(75, 25)
gc.Rotate(30 * math.Pi / 180)
lastTime := time.Nanoseconds()
gc.DrawImage(source)
dt := time.Nanoseconds() - lastTime
fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6)
saveToPngFile("../resource/result/TestDrawImage.png", i)
}

59
cmd/testpostscript.go Normal file
View file

@ -0,0 +1,59 @@
package main
import (
"fmt"
"time"
"log"
"os"
"io/ioutil"
"bufio"
"strings"
"image"
"image/png"
"draw2d.googlecode.com/hg/draw2d"
"draw2d.googlecode.com/hg/postscript"
)
func saveToPngFile(filePath string, m image.Image) {
f, err := os.Open(filePath, os.O_CREAT|os.O_WRONLY, 0600)
if err != nil {
log.Println(err)
os.Exit(1)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, m)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Printf("Wrote %s OK.\n", filePath)
}
func main() {
i := image.NewRGBA(600, 800)
gc := draw2d.NewGraphicContext(i)
gc.Translate(0, 380)
gc.Scale(1, -1)
gc.Translate(0, -380)
lastTime := time.Nanoseconds()
src, err := os.Open("../resource/postscript/tiger.ps", 0, 0)
if err != nil {
return
}
defer src.Close()
bytes, err := ioutil.ReadAll(src)
reader := strings.NewReader(string(bytes))
interpreter := postscript.NewInterpreter(gc)
interpreter.Execute(reader)
dt := time.Nanoseconds() - lastTime
fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6)
saveToPngFile("../resource/result/TestPostscript.png", i)
}

306339
doc/PLRM.pdf Normal file

File diff suppressed because one or more lines are too long

24
draw2d/Makefile Normal file
View file

@ -0,0 +1,24 @@
include $(GOROOT)/src/Make.inc
TARG=draw2d.googlecode.com/hg/draw2d
GOFILES=\
arc.go\
curves.go\
image.go\
math.go\
path.go\
transform.go\
dasher.go\
demux_converter.go\
font.go\
path_adder.go\
path_converter.go\
path_storage.go\
stroker.go\
advanced_path.go\
vertex2d.go\
gc.go\
paint.go\
stack_gc.go\
include $(GOROOT)/src/Make.pkg

43
draw2d/advanced_path.go Normal file
View file

@ -0,0 +1,43 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package draw2d
import (
"math"
)
//high level path creation
func Rect(path Path, x1, y1, x2, y2 float64) {
path.MoveTo(x1, y1)
path.LineTo(x2, y1)
path.LineTo(x2, y2)
path.LineTo(x1, y2)
path.Close()
}
func RoundRect(path Path, x1, y1, x2, y2, arcWidth, arcHeight float64) {
arcWidth = arcWidth / 2
arcHeight = arcHeight / 2
path.MoveTo(x1, y1+arcHeight)
path.QuadCurveTo(x1, y1, x1+arcWidth, y1)
path.LineTo(x2-arcWidth, y1)
path.QuadCurveTo(x2, y1, x2, y1+arcHeight)
path.LineTo(x2, y2-arcHeight)
path.QuadCurveTo(x2, y2, x2-arcWidth, y2)
path.LineTo(x1+arcWidth, y2)
path.QuadCurveTo(x1, y2, x1, y2-arcHeight)
path.Close()
}
func Ellipse(path Path, cx, cy, rx, ry float64) {
path.ArcTo(cx, cy, rx, ry, 0, -math.Pi*2)
path.Close()
}
func Circle(path Path, cx, cy, radius float64) {
path.ArcTo(cx, cy, radius, radius, 0, -math.Pi*2)
path.Close()
}

67
draw2d/arc.go Normal file
View file

@ -0,0 +1,67 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"freetype-go.googlecode.com/hg/freetype/raster"
"math"
)
func arc(t VertexConverter, x, y, rx, ry, start, angle, scale float64) (lastX, lastY float64) {
end := start + angle
clockWise := true
if angle < 0 {
clockWise = false
}
ra := (math.Fabs(rx) + math.Fabs(ry)) / 2
da := math.Acos(ra/(ra+0.125/scale)) * 2
//normalize
if !clockWise {
da = -da
}
angle = start + da
var curX, curY float64
for {
if (angle < end-da/4) != clockWise {
curX = x + math.Cos(end)*rx
curY = y + math.Sin(end)*ry
return curX, curY
}
curX = x + math.Cos(angle)*rx
curY = y + math.Sin(angle)*ry
angle += da
t.Vertex(curX, curY)
}
return curX, curY
}
func arcAdder(adder raster.Adder, x, y, rx, ry, start, angle, scale float64) raster.Point {
end := start + angle
clockWise := true
if angle < 0 {
clockWise = false
}
ra := (math.Fabs(rx) + math.Fabs(ry)) / 2
da := math.Acos(ra/(ra+0.125/scale)) * 2
//normalize
if !clockWise {
da = -da
}
angle = start + da
var curX, curY float64
for {
if (angle < end-da/4) != clockWise {
curX = x + math.Cos(end)*rx
curY = y + math.Sin(end)*ry
return floatToPoint(curX, curY)
}
curX = x + math.Cos(angle)*rx
curY = y + math.Sin(angle)*ry
angle += da
adder.Add1(floatToPoint(curX, curY))
}
return floatToPoint(curX, curY)
}

338
draw2d/curves.go Normal file
View file

@ -0,0 +1,338 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"math"
)
var (
CurveRecursionLimit = 32
CurveCollinearityEpsilon = 1e-30
CurveAngleToleranceEpsilon = 0.01
)
/*
The function has the following parameters:
approximationScale :
Eventually determines the approximation accuracy. In practice we need to transform points from the World coordinate system to the Screen one.
It always has some scaling coefficient.
The curves are usually processed in the World coordinates, while the approximation accuracy should be eventually in pixels.
Usually it looks as follows:
curved.approximationScale(transform.scale());
where transform is the affine matrix that includes all the transformations, including viewport and zoom.
angleTolerance :
You set it in radians.
The less this value is the more accurate will be the approximation at sharp turns.
But 0 means that we don't consider angle conditions at all.
cuspLimit :
An angle in radians.
If 0, only the real cusps will have bevel cuts.
If more than 0, it will restrict the sharpness.
The more this value is the less sharp turns will be cut.
Typically it should not exceed 10-15 degrees.
*/
func cubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4, approximationScale, angleTolerance, cuspLimit float64) {
cuspLimit = computeCuspLimit(cuspLimit)
distanceToleranceSquare := 0.5 / approximationScale
distanceToleranceSquare = distanceToleranceSquare * distanceToleranceSquare
recursiveCubicBezier(v, x1, y1, x2, y2, x3, y3, x4, y4, 0, distanceToleranceSquare, angleTolerance, cuspLimit)
}
/*
* see cubicBezier comments for approximationScale and angleTolerance definition
*/
func quadraticBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, approximationScale, angleTolerance float64) {
distanceToleranceSquare := 0.5 / approximationScale
distanceToleranceSquare = distanceToleranceSquare * distanceToleranceSquare
recursiveQuadraticBezierBezier(v, x1, y1, x2, y2, x3, y3, 0, distanceToleranceSquare, angleTolerance)
}
func computeCuspLimit(v float64) (r float64) {
if v == 0.0 {
r = 0.0
} else {
r = math.Pi - v
}
return
}
/**
* http://www.antigrain.com/research/adaptive_bezier/index.html
*/
func recursiveQuadraticBezierBezier(v VertexConverter, x1, y1, x2, y2, x3, y3 float64, level int, distanceToleranceSquare, angleTolerance float64) {
if level > CurveRecursionLimit {
return
}
// Calculate all the mid-points of the line segments
//----------------------
x12 := (x1 + x2) / 2
y12 := (y1 + y2) / 2
x23 := (x2 + x3) / 2
y23 := (y2 + y3) / 2
x123 := (x12 + x23) / 2
y123 := (y12 + y23) / 2
dx := x3 - x1
dy := y3 - y1
d := math.Fabs(((x2-x3)*dy - (y2-y3)*dx))
if d > CurveCollinearityEpsilon {
// Regular case
//-----------------
if d*d <= distanceToleranceSquare*(dx*dx+dy*dy) {
// If the curvature doesn't exceed the distanceTolerance value
// we tend to finish subdivisions.
//----------------------
if angleTolerance < CurveAngleToleranceEpsilon {
v.Vertex(x123, y123)
return
}
// Angle & Cusp Condition
//----------------------
da := math.Fabs(math.Atan2(y3-y2, x3-x2) - math.Atan2(y2-y1, x2-x1))
if da >= math.Pi {
da = 2*math.Pi - da
}
if da < angleTolerance {
// Finally we can stop the recursion
//----------------------
v.Vertex(x123, y123)
return
}
}
} else {
// Collinear case
//------------------
da := dx*dx + dy*dy
if da == 0 {
d = squareDistance(x1, y1, x2, y2)
} else {
d = ((x2-x1)*dx + (y2-y1)*dy) / da
if d > 0 && d < 1 {
// Simple collinear case, 1---2---3
// We can leave just two endpoints
return
}
if d <= 0 {
d = squareDistance(x2, y2, x1, y1)
} else if d >= 1 {
d = squareDistance(x2, y2, x3, y3)
} else {
d = squareDistance(x2, y2, x1+d*dx, y1+d*dy)
}
}
if d < distanceToleranceSquare {
v.Vertex(x2, y2)
return
}
}
// Continue subdivision
//----------------------
recursiveQuadraticBezierBezier(v, x1, y1, x12, y12, x123, y123, level+1, distanceToleranceSquare, angleTolerance)
recursiveQuadraticBezierBezier(v, x123, y123, x23, y23, x3, y3, level+1, distanceToleranceSquare, angleTolerance)
}
/**
* http://www.antigrain.com/research/adaptive_bezier/index.html
*/
func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 float64, level int, distanceToleranceSquare, angleTolerance, cuspLimit float64) {
if level > CurveRecursionLimit {
return
}
// Calculate all the mid-points of the line segments
//----------------------
x12 := (x1 + x2) / 2
y12 := (y1 + y2) / 2
x23 := (x2 + x3) / 2
y23 := (y2 + y3) / 2
x34 := (x3 + x4) / 2
y34 := (y3 + y4) / 2
x123 := (x12 + x23) / 2
y123 := (y12 + y23) / 2
x234 := (x23 + x34) / 2
y234 := (y23 + y34) / 2
x1234 := (x123 + x234) / 2
y1234 := (y123 + y234) / 2
// Try to approximate the full cubic curve by a single straight line
//------------------
dx := x4 - x1
dy := y4 - y1
d2 := math.Fabs(((x2-x4)*dy - (y2-y4)*dx))
d3 := math.Fabs(((x3-x4)*dy - (y3-y4)*dx))
switch {
case d2 <= CurveCollinearityEpsilon && d3 <= CurveCollinearityEpsilon:
// All collinear OR p1==p4
//----------------------
k := dx*dx + dy*dy
if k == 0 {
d2 = squareDistance(x1, y1, x2, y2)
d3 = squareDistance(x4, y4, x3, y3)
} else {
k = 1 / k
da1 := x2 - x1
da2 := y2 - y1
d2 = k * (da1*dx + da2*dy)
da1 = x3 - x1
da2 = y3 - y1
d3 = k * (da1*dx + da2*dy)
if d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1 {
// Simple collinear case, 1---2---3---4
// We can leave just two endpoints
return
}
if d2 <= 0 {
d2 = squareDistance(x2, y2, x1, y1)
} else if d2 >= 1 {
d2 = squareDistance(x2, y2, x4, y4)
} else {
d2 = squareDistance(x2, y2, x1+d2*dx, y1+d2*dy)
}
if d3 <= 0 {
d3 = squareDistance(x3, y3, x1, y1)
} else if d3 >= 1 {
d3 = squareDistance(x3, y3, x4, y4)
} else {
d3 = squareDistance(x3, y3, x1+d3*dx, y1+d3*dy)
}
}
if d2 > d3 {
if d2 < distanceToleranceSquare {
v.Vertex(x2, y2)
return
}
} else {
if d3 < distanceToleranceSquare {
v.Vertex(x3, y3)
return
}
}
break
case d2 <= CurveCollinearityEpsilon && d3 > CurveCollinearityEpsilon:
// p1,p2,p4 are collinear, p3 is significant
//----------------------
if d3*d3 <= distanceToleranceSquare*(dx*dx+dy*dy) {
if angleTolerance < CurveAngleToleranceEpsilon {
v.Vertex(x23, y23)
return
}
// Angle Condition
//----------------------
da1 := math.Fabs(math.Atan2(y4-y3, x4-x3) - math.Atan2(y3-y2, x3-x2))
if da1 >= math.Pi {
da1 = 2*math.Pi - da1
}
if da1 < angleTolerance {
v.Vertex(x2, y2)
v.Vertex(x3, y3)
return
}
if cuspLimit != 0.0 {
if da1 > cuspLimit {
v.Vertex(x3, y3)
return
}
}
}
break
case d2 > CurveCollinearityEpsilon && d3 <= CurveCollinearityEpsilon:
// p1,p3,p4 are collinear, p2 is significant
//----------------------
if d2*d2 <= distanceToleranceSquare*(dx*dx+dy*dy) {
if angleTolerance < CurveAngleToleranceEpsilon {
v.Vertex(x23, y23)
return
}
// Angle Condition
//----------------------
da1 := math.Fabs(math.Atan2(y3-y2, x3-x2) - math.Atan2(y2-y1, x2-x1))
if da1 >= math.Pi {
da1 = 2*math.Pi - da1
}
if da1 < angleTolerance {
v.Vertex(x2, y2)
v.Vertex(x3, y3)
return
}
if cuspLimit != 0.0 {
if da1 > cuspLimit {
v.Vertex(x2, y2)
return
}
}
}
break
case d2 > CurveCollinearityEpsilon && d3 > CurveCollinearityEpsilon:
// Regular case
//-----------------
if (d2+d3)*(d2+d3) <= distanceToleranceSquare*(dx*dx+dy*dy) {
// If the curvature doesn't exceed the distanceTolerance value
// we tend to finish subdivisions.
//----------------------
if angleTolerance < CurveAngleToleranceEpsilon {
v.Vertex(x23, y23)
return
}
// Angle & Cusp Condition
//----------------------
k := math.Atan2(y3-y2, x3-x2)
da1 := math.Fabs(k - math.Atan2(y2-y1, x2-x1))
da2 := math.Fabs(math.Atan2(y4-y3, x4-x3) - k)
if da1 >= math.Pi {
da1 = 2*math.Pi - da1
}
if da2 >= math.Pi {
da2 = 2*math.Pi - da2
}
if da1+da2 < angleTolerance {
// Finally we can stop the recursion
//----------------------
v.Vertex(x23, y23)
return
}
if cuspLimit != 0.0 {
if da1 > cuspLimit {
v.Vertex(x2, y2)
return
}
if da2 > cuspLimit {
v.Vertex(x3, y3)
return
}
}
}
break
}
// Continue subdivision
//----------------------
recursiveCubicBezier(v, x1, y1, x12, y12, x123, y123, x1234, y1234, level+1, distanceToleranceSquare, angleTolerance, cuspLimit)
recursiveCubicBezier(v, x1234, y1234, x234, y234, x34, y34, x4, y4, level+1, distanceToleranceSquare, angleTolerance, cuspLimit)
}

89
draw2d/dasher.go Normal file
View file

@ -0,0 +1,89 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package draw2d
type DashVertexConverter struct {
command VertexCommand
next VertexConverter
x, y, distance float64
dash []float64
currentDash int
dashOffset float64
}
func NewDashConverter(dash []float64, dashOffset float64, converter VertexConverter) *DashVertexConverter {
var dasher DashVertexConverter
dasher.dash = dash
dasher.currentDash = 0
dasher.dashOffset = dashOffset
dasher.next = converter
return &dasher
}
func (dasher *DashVertexConverter) NextCommand(cmd VertexCommand) {
dasher.command = cmd
if dasher.command == VertexStopCommand {
dasher.next.NextCommand(VertexStopCommand)
}
}
func (dasher *DashVertexConverter) Vertex(x, y float64) {
switch dasher.command {
case VertexStartCommand:
dasher.start(x, y)
default:
dasher.lineTo(x, y)
}
dasher.command = VertexNoCommand
}
func (dasher *DashVertexConverter) start(x, y float64) {
dasher.next.NextCommand(VertexStartCommand)
dasher.next.Vertex(x, y)
dasher.x, dasher.y = x, y
dasher.distance = dasher.dashOffset
dasher.currentDash = 0
}
func (dasher *DashVertexConverter) lineTo(x, y float64) {
rest := dasher.dash[dasher.currentDash] - dasher.distance
for rest < 0 {
dasher.distance = dasher.distance - dasher.dash[dasher.currentDash]
dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash)
rest = dasher.dash[dasher.currentDash] - dasher.distance
}
d := distance(dasher.x, dasher.y, x, y)
for d >= rest {
k := rest / d
lx := dasher.x + k*(x-dasher.x)
ly := dasher.y + k*(y-dasher.y)
if dasher.currentDash%2 == 0 {
// line
dasher.next.Vertex(lx, ly)
} else {
// gap
dasher.next.NextCommand(VertexStopCommand)
dasher.next.NextCommand(VertexStartCommand)
dasher.next.Vertex(lx, ly)
}
d = d - rest
dasher.x, dasher.y = lx, ly
dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash)
rest = dasher.dash[dasher.currentDash]
}
dasher.distance = d
if dasher.currentDash%2 == 0 {
// line
dasher.next.Vertex(x, y)
} else {
// gap
dasher.next.NextCommand(VertexStopCommand)
dasher.next.NextCommand(VertexStartCommand)
dasher.next.Vertex(x, y)
}
if dasher.distance >= dasher.dash[dasher.currentDash] {
dasher.distance = dasher.distance - dasher.dash[dasher.currentDash]
dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash)
}
dasher.x, dasher.y = x, y
}

22
draw2d/demux_converter.go Normal file
View file

@ -0,0 +1,22 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package draw2d
type DemuxConverter struct {
converters []VertexConverter
}
func NewDemuxConverter(converters ...VertexConverter) *DemuxConverter {
return &DemuxConverter{converters}
}
func (dc *DemuxConverter) NextCommand(cmd VertexCommand) {
for _, converter := range dc.converters {
converter.NextCommand(cmd)
}
}
func (dc *DemuxConverter) Vertex(x, y float64) {
for _, converter := range dc.converters {
converter.Vertex(x, y)
}
}

93
draw2d/font.go Normal file
View file

@ -0,0 +1,93 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package draw2d
import (
"freetype-go.googlecode.com/hg/freetype"
"freetype-go.googlecode.com/hg/freetype/truetype"
"path"
"log"
"io/ioutil"
)
var (
fontFolder = "../resource/font/"
fonts = make(map[string]*truetype.Font)
)
type FontStyle byte
const (
FontStyleNormal FontStyle = iota
FontStyleBold
FontStyleItalic
)
type FontFamily byte
const (
FontFamilySans FontFamily = iota
FontFamilySerif
FontFamilyMono
)
type FontData struct {
Name string
Family FontFamily
Style FontStyle
}
func GetFont(fontData FontData) *truetype.Font {
fontFileName := fontData.Name
switch fontData.Family {
case FontFamilySans:
fontFileName += "s"
case FontFamilySerif:
fontFileName += "r"
case FontFamilyMono:
fontFileName += "m"
}
if fontData.Style&FontStyleBold != 0 {
fontFileName += "b"
} else {
fontFileName += "r"
}
if fontData.Style&FontStyleItalic != 0 {
fontFileName += "i"
}
fontFileName += ".ttf"
font := fonts[fontFileName]
if font != nil {
return font
}
fonts[fontFileName] = loadFont(fontFileName)
return fonts[fontFileName]
}
func GetFontFolder() string {
return fontFolder
}
func SetFontFolder(folder string) {
fontFolder = folder
}
func loadFont(fontFileName string) *truetype.Font {
fontBytes, err := ioutil.ReadFile(path.Join(fontFolder, fontFileName))
if err != nil {
log.Println(err)
return nil
}
font, err := freetype.ParseFont(fontBytes)
if err != nil {
log.Println(err)
return nil
}
return font
}

47
draw2d/gc.go Normal file
View file

@ -0,0 +1,47 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"image"
)
type FillRule int
const (
FillRuleEvenOdd FillRule = iota
FillRuleWinding
)
type GraphicContext interface {
BeginPath()
Path
GetMatrixTransform() MatrixTransform
SetMatrixTransform(tr MatrixTransform)
ComposeMatrixTransform(tr MatrixTransform)
Rotate(angle float64)
Translate(tx, ty float64)
Scale(sx, sy float64)
SetStrokeColor(c image.Color)
SetFillColor(c image.Color)
SetFillRule(f FillRule)
SetLineWidth(lineWidth float64)
SetLineCap(cap Cap)
SetLineJoin(join Join)
SetLineDash(dash []float64, dashOffset float64)
SetFontSize(fontSize float64)
GetFontSize() float64
SetFontData(fontData FontData)
GetFontData() FontData
DrawImage(image image.Image)
Save()
Restore()
Clear()
ClearRect(x1, y1, x2, y2 int)
SetDPI(dpi int)
GetDPI() int
FillString(text string) (cursor float64)
Stroke(paths ...*PathStorage)
Fill(paths ...*PathStorage)
FillStroke(paths ...*PathStorage)
}

292
draw2d/image.go Normal file
View file

@ -0,0 +1,292 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"exp/draw"
"image"
"log"
"freetype-go.googlecode.com/hg/freetype"
"freetype-go.googlecode.com/hg/freetype/raster"
)
type Painter interface{
raster.Painter
SetColor(color image.Color)
}
var (
defaultFontData = FontData{"luxi", FontFamilySans, FontStyleNormal}
)
type ImageGraphicContext struct {
*StackGraphicContext
img draw.Image
painter Painter
fillRasterizer *raster.Rasterizer
strokeRasterizer *raster.Rasterizer
freetype *freetype.Context
DPI int
}
/**
* Create a new Graphic context from an image
*/
func NewGraphicContext(img draw.Image) *ImageGraphicContext {
var painter Painter
switch selectImage := img.(type) {
case *image.RGBA:
painter = raster.NewRGBAPainter(selectImage)
case *image.NRGBA:
painter = NewNRGBAPainter(selectImage)
default:
panic("Image type not supported")
}
width, height := img.Bounds().Dx(), img.Bounds().Dy()
dpi := 92
ftContext := freetype.NewContext()
ftContext.SetDPI(dpi)
ftContext.SetClip(img.Bounds())
ftContext.SetDst(img)
gc := &ImageGraphicContext{
NewStackGraphicContext(),
img,
painter,
raster.NewRasterizer(width, height),
raster.NewRasterizer(width, height),
ftContext,
dpi,
}
return gc
}
func (gc *ImageGraphicContext) SetDPI(dpi int) {
gc.DPI = dpi
gc.freetype.SetDPI(dpi)
}
func (gc *ImageGraphicContext) GetDPI() int {
return gc.DPI
}
func (gc *ImageGraphicContext) Clear() {
width, height := gc.img.Bounds().Dx(), gc.img.Bounds().Dy()
gc.ClearRect(0, 0, width, height)
}
func (gc *ImageGraphicContext) ClearRect(x1, y1, x2, y2 int) {
imageColor := image.NewColorImage(gc.current.FillColor)
draw.Draw(gc.img, image.Rect(x1, y1, x2, y2), imageColor, image.ZP)
}
func (gc *ImageGraphicContext) DrawImage(image image.Image) {
width := raster.Fix32(gc.img.Bounds().Dx() * 256)
height := raster.Fix32(gc.img.Bounds().Dy() * 256)
p0 := raster.Point{0, 0}
p1 := raster.Point{0, 0}
p2 := raster.Point{0, 0}
p3 := raster.Point{0, 0}
var i raster.Fix32 = 0
for ; i < width; i += 256 {
var j raster.Fix32 = 0
for ; j < height; j += 256 {
p0.X, p0.Y = i, j
p1.X, p1.Y = p0.X+256, p0.Y
p2.X, p2.Y = p1.X, p0.Y+256
p3.X, p3.Y = p0.X, p2.Y
gc.current.Tr.TransformRasterPoint(&p0, &p1, &p2, &p3)
gc.fillRasterizer.Start(p0)
gc.fillRasterizer.Add1(p1)
gc.fillRasterizer.Add1(p2)
gc.fillRasterizer.Add1(p3)
gc.fillRasterizer.Add1(p0)
gc.painter.SetColor(image.At(int(i>>8), int(j>>8)))
gc.fillRasterizer.Rasterize(gc.painter)
gc.fillRasterizer.Clear()
}
}
}
func (gc *ImageGraphicContext) FillString(text string) (cursor float64) {
gc.freetype.SetSrc(image.NewColorImage(gc.current.StrokeColor))
// Draw the text.
x, y := gc.current.Path.LastPoint()
gc.current.Tr.Transform(&x, &y)
x0, fontSize := 0.0, gc.current.FontSize
gc.current.Tr.VectorTransform(&x0, &fontSize)
font := GetFont(gc.current.FontData)
if font == nil {
font = GetFont(defaultFontData)
}
if font == nil {
return 0
}
gc.freetype.SetFont(font)
gc.freetype.SetFontSize(fontSize)
pt := freetype.Pt(int(x), int(y))
p, err := gc.freetype.DrawString(text, pt)
if err != nil {
log.Println(err)
}
x1, _ := gc.current.Path.LastPoint()
x2, y2 := float64(p.X)/256, float64(p.Y)/256
gc.current.Tr.InverseTransform(&x2, &y2)
width := x2 - x1
return width
}
func (gc *ImageGraphicContext) paint(rasterizer *raster.Rasterizer, color image.Color) {
gc.painter.SetColor(color)
rasterizer.Rasterize(gc.painter)
rasterizer.Clear()
gc.current.Path = new(PathStorage)
}
/**** First method ****/
func (gc *ImageGraphicContext) Stroke2(paths ...*PathStorage) {
paths = append(paths, gc.current.Path)
gc.strokeRasterizer.UseNonZeroWinding = true
rasterPath := new(raster.Path)
var pathConverter *PathConverter
if gc.current.Dash != nil && len(gc.current.Dash) > 0 {
dasher := NewDashConverter(gc.current.Dash, gc.current.DashOffset, NewVertexAdder(rasterPath))
pathConverter = NewPathConverter(dasher)
} else {
pathConverter = NewPathConverter(NewVertexAdder(rasterPath))
}
pathConverter.ApproximationScale = gc.current.Tr.GetMaxAbsScaling()
pathConverter.Convert(paths...)
mta := NewMatrixTransformAdder(gc.current.Tr, gc.strokeRasterizer)
raster.Stroke(mta, *rasterPath, raster.Fix32(gc.current.LineWidth*256), gc.current.Cap.capper(), gc.current.Join.joiner())
gc.paint(gc.strokeRasterizer, gc.current.StrokeColor)
}
/**** second method ****/
func (gc *ImageGraphicContext) Stroke(paths ...*PathStorage) {
paths = append(paths, gc.current.Path)
gc.strokeRasterizer.UseNonZeroWinding = true
stroker := NewLineStroker(gc.current.Cap, gc.current.Join, NewVertexMatrixTransform(gc.current.Tr, NewVertexAdder(gc.strokeRasterizer)))
stroker.HalfLineWidth = gc.current.LineWidth / 2
var pathConverter *PathConverter
if gc.current.Dash != nil && len(gc.current.Dash) > 0 {
dasher := NewDashConverter(gc.current.Dash, gc.current.DashOffset, stroker)
pathConverter = NewPathConverter(dasher)
} else {
pathConverter = NewPathConverter(stroker)
}
pathConverter.ApproximationScale = gc.current.Tr.GetMaxAbsScaling()
pathConverter.Convert(paths...)
gc.paint(gc.strokeRasterizer, gc.current.StrokeColor)
}
/**** first method ****/
func (gc *ImageGraphicContext) Fill2(paths ...*PathStorage) {
paths = append(paths, gc.current.Path)
gc.fillRasterizer.UseNonZeroWinding = gc.current.FillRule.fillRule()
pathConverter := NewPathConverter(NewVertexAdder(NewMatrixTransformAdder(gc.current.Tr, gc.fillRasterizer)))
pathConverter.ApproximationScale = gc.current.Tr.GetMaxAbsScaling()
pathConverter.Convert(paths...)
gc.paint(gc.fillRasterizer, gc.current.FillColor)
}
/**** second method ****/
func (gc *ImageGraphicContext) Fill(paths ...*PathStorage) {
paths = append(paths, gc.current.Path)
gc.fillRasterizer.UseNonZeroWinding = gc.current.FillRule.fillRule()
/**** first method ****/
pathConverter := NewPathConverter(NewVertexMatrixTransform(gc.current.Tr, NewVertexAdder(gc.fillRasterizer)))
pathConverter.ApproximationScale = gc.current.Tr.GetMaxAbsScaling()
pathConverter.Convert(paths...)
gc.paint(gc.fillRasterizer, gc.current.FillColor)
}
func (gc *ImageGraphicContext) FillStroke2(paths ...*PathStorage) {
paths = append(paths, gc.current.Path)
gc.fillRasterizer.UseNonZeroWinding = gc.current.FillRule.fillRule()
gc.strokeRasterizer.UseNonZeroWinding = true
filler := NewVertexMatrixTransform(gc.current.Tr, NewVertexAdder(gc.fillRasterizer))
rasterPath := new(raster.Path)
stroker := NewVertexAdder(rasterPath)
demux := NewDemuxConverter(filler, stroker)
pathConverter := NewPathConverter(demux)
pathConverter.ApproximationScale = gc.current.Tr.GetMaxAbsScaling()
pathConverter.Convert(paths...)
mta := NewMatrixTransformAdder(gc.current.Tr, gc.strokeRasterizer)
raster.Stroke(mta, *rasterPath, raster.Fix32(gc.current.LineWidth*256), gc.current.Cap.capper(), gc.current.Join.joiner())
gc.paint(gc.fillRasterizer, gc.current.FillColor)
gc.paint(gc.strokeRasterizer, gc.current.StrokeColor)
}
/* second method */
func (gc *ImageGraphicContext) FillStroke(paths ...*PathStorage) {
gc.fillRasterizer.UseNonZeroWinding = gc.current.FillRule.fillRule()
gc.strokeRasterizer.UseNonZeroWinding = true
filler := NewVertexMatrixTransform(gc.current.Tr, NewVertexAdder(gc.fillRasterizer))
stroker := NewLineStroker(gc.current.Cap, gc.current.Join, NewVertexMatrixTransform(gc.current.Tr, NewVertexAdder(gc.strokeRasterizer)))
stroker.HalfLineWidth = gc.current.LineWidth / 2
demux := NewDemuxConverter(filler, stroker)
paths = append(paths, gc.current.Path)
pathConverter := NewPathConverter(demux)
pathConverter.ApproximationScale = gc.current.Tr.GetMaxAbsScaling()
pathConverter.Convert(paths...)
gc.paint(gc.fillRasterizer, gc.current.FillColor)
gc.paint(gc.strokeRasterizer, gc.current.StrokeColor)
}
func (f FillRule) fillRule() bool {
switch f {
case FillRuleEvenOdd:
return false
case FillRuleWinding:
return true
}
return false
}
func (c Cap) capper() raster.Capper {
switch c {
case RoundCap:
return raster.RoundCapper
case ButtCap:
return raster.ButtCapper
case SquareCap:
return raster.SquareCapper
}
return raster.RoundCapper
}
func (j Join) joiner() raster.Joiner {
switch j {
case RoundJoin:
return raster.RoundJoiner
case BevelJoin:
return raster.BevelJoiner
}
return raster.RoundJoiner
}

23
draw2d/math.go Normal file
View file

@ -0,0 +1,23 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"math"
)
func distance(x1, y1, x2, y2 float64) float64 {
dx := x2 - x1
dy := y2 - y1
return float64(math.Sqrt(dx*dx + dy*dy))
}
func vectorDistance(dx, dy float64) float64 {
return float64(math.Sqrt(dx*dx + dy*dy))
}
func squareDistance(x1, y1, x2, y2 float64) float64 {
dx := x2 - x1
dy := y2 - y1
return dx*dx + dy*dy
}

94
draw2d/paint.go Normal file
View file

@ -0,0 +1,94 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"exp/draw"
"image"
"freetype-go.googlecode.com/hg/freetype/raster"
)
const M = 1<<16 - 1
type NRGBAPainter struct {
// The image to compose onto.
Image *image.NRGBA
// The Porter-Duff composition operator.
Op draw.Op
// The 16-bit color to paint the spans.
cr, cg, cb, ca uint32
}
func min(a, b uint32) uint32 {
if a < b {
return a
}
return b
}
// Paint satisfies the Painter interface by painting ss onto an image.RGBA.
func (r *NRGBAPainter) Paint(ss []raster.Span, done bool) {
b := r.Image.Bounds()
for _, s := range ss {
if s.Y < b.Min.Y {
continue
}
if s.Y >= b.Max.Y {
return
}
if s.X0 < b.Min.X {
s.X0 = b.Min.X
}
if s.X1 > b.Max.X {
s.X1 = b.Max.X
}
if s.X0 >= s.X1 {
continue
}
base := s.Y * r.Image.Stride
p := r.Image.Pix[base+s.X0 : base+s.X1]
// This code is duplicated from drawGlyphOver in $GOROOT/src/pkg/exp/draw/draw.go.
// TODO(nigeltao): Factor out common code into a utility function, once the compiler
// can inline such function calls.
ma := s.A >> 16
if r.Op == draw.Over {
for i, nrgba := range p {
dr, dg, db, da := nrgba.RGBA()
a := M - (r.ca*ma)/M
da = (da*a + r.ca*ma) / M
if da != 0 {
dr = min(M, (dr*a+r.cr*ma)/da)
dg = min(M, (dg*a+r.cg*ma)/da)
db = min(M, (db*a+r.cb*ma)/da)
} else {
dr, dg, db = 0, 0, 0
}
p[i] = image.NRGBAColor{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)}
}
} else {
for i, nrgba := range p {
dr, dg, db, da := nrgba.RGBA()
a := M - ma
da = (da*a + r.ca*ma) / M
if da != 0 {
dr = min(M, (dr*a+r.cr*ma)/da)
dg = min(M, (dg*a+r.cg*ma)/da)
db = min(M, (db*a+r.cb*ma)/da)
} else {
dr, dg, db = 0, 0, 0
}
p[i] = image.NRGBAColor{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)}
}
}
}
}
// SetColor sets the color to paint the spans.
func (r *NRGBAPainter) SetColor(c image.Color) {
r.cr, r.cg, r.cb, r.ca = c.RGBA()
}
// NewRGBAPainter creates a new RGBAPainter for the given image.
func NewNRGBAPainter(m *image.NRGBA) *NRGBAPainter {
return &NRGBAPainter{Image: m}
}

18
draw2d/path.go Normal file
View file

@ -0,0 +1,18 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
type Path interface {
LastPoint() (x, y float64)
MoveTo(x, y float64)
RMoveTo(dx, dy float64)
LineTo(x, y float64)
RLineTo(dx, dy float64)
QuadCurveTo(cx, cy, x, y float64)
RQuadCurveTo(dcx, dcy, dx, dy float64)
CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64)
RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float64)
ArcTo(cx, cy, rx, ry, startAngle, angle float64)
RArcTo(dcx, dcy, rx, ry, startAngle, angle float64)
Close()
}

89
draw2d/path_adder.go Normal file
View file

@ -0,0 +1,89 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package draw2d
import (
"freetype-go.googlecode.com/hg/freetype/raster"
)
type VertexAdder struct {
command VertexCommand
adder raster.Adder
}
func floatToPoint(x, y float64) raster.Point {
return raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)}
}
func NewVertexAdder(adder raster.Adder) *VertexAdder {
return &VertexAdder{VertexNoCommand, adder}
}
func (vertexAdder *VertexAdder) NextCommand(cmd VertexCommand) {
vertexAdder.command = cmd
}
func (vertexAdder *VertexAdder) Vertex(x, y float64) {
switch vertexAdder.command {
case VertexStartCommand:
vertexAdder.adder.Start(floatToPoint(x, y))
default:
vertexAdder.adder.Add1(floatToPoint(x, y))
}
vertexAdder.command = VertexNoCommand
}
type PathAdder struct {
adder raster.Adder
lastPoint raster.Point
ApproximationScale float64
}
func NewPathAdder(adder raster.Adder) *PathAdder {
return &PathAdder{adder, raster.Point{0, 0}, 1}
}
func (pathAdder *PathAdder) Convert(paths ...*PathStorage) {
for _, path := range paths {
j := 0
for _, cmd := range path.commands {
j = j + pathAdder.ConvertCommand(cmd, path.vertices[j:]...)
}
}
}
func (pathAdder *PathAdder) ConvertCommand(cmd PathCmd, vertices ...float64) int {
switch cmd {
case MoveTo:
pathAdder.lastPoint = floatToPoint(vertices[0], vertices[1])
pathAdder.adder.Start(pathAdder.lastPoint)
return 2
case LineTo:
pathAdder.lastPoint = floatToPoint(vertices[0], vertices[1])
pathAdder.adder.Add1(pathAdder.lastPoint)
return 2
case QuadCurveTo:
pathAdder.lastPoint = floatToPoint(vertices[2], vertices[3])
pathAdder.adder.Add2(floatToPoint(vertices[0], vertices[1]), pathAdder.lastPoint)
return 4
case CubicCurveTo:
pathAdder.lastPoint = floatToPoint(vertices[4], vertices[5])
pathAdder.adder.Add3(floatToPoint(vertices[0], vertices[1]), floatToPoint(vertices[2], vertices[3]), pathAdder.lastPoint)
return 6
case ArcTo:
pathAdder.lastPoint = arcAdder(pathAdder.adder, vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5], pathAdder.ApproximationScale)
pathAdder.adder.Add1(pathAdder.lastPoint)
return 6
case Close:
pathAdder.adder.Add1(pathAdder.lastPoint)
return 0
}
return 0
}

153
draw2d/path_converter.go Normal file
View file

@ -0,0 +1,153 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 06/12/2010 by Laurent Le Goff
package draw2d
import (
"math"
)
type PathConverter struct {
converter VertexConverter
ApproximationScale, AngleTolerance, CuspLimit float64
startX, startY, x, y float64
}
func NewPathConverter(converter VertexConverter) *PathConverter {
return &PathConverter{converter, 1, 0, 0, 0, 0, 0, 0}
}
func (c *PathConverter) Convert(paths ...*PathStorage) {
for _, path := range paths {
j := 0
for _, cmd := range path.commands {
j = j + c.ConvertCommand(cmd, path.vertices[j:]...)
}
c.converter.NextCommand(VertexStopCommand)
}
}
func (c *PathConverter) ConvertCommand(cmd PathCmd, vertices ...float64) int {
switch cmd {
case MoveTo:
c.MoveTo(vertices[0], vertices[1])
return 2
case LineTo:
c.LineTo(vertices[0], vertices[1])
return 2
case QuadCurveTo:
c.QuadCurveTo(vertices[0], vertices[1], vertices[2], vertices[3])
return 4
case CubicCurveTo:
c.CubicCurveTo(vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5])
return 6
case ArcTo:
c.x, c.y = arc(c.converter, vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5], c.ApproximationScale)
if c.startX == c.x && c.startY == c.y {
c.converter.NextCommand(VertexCloseCommand)
}
c.converter.Vertex(c.x, c.y)
return 6
case Close:
c.Close()
return 0
}
return 0
}
func (c *PathConverter) MoveTo(x, y float64) *PathConverter {
c.x, c.y = x, y
c.startX, c.startY = c.x, c.y
c.converter.NextCommand(VertexStopCommand)
c.converter.NextCommand(VertexStartCommand)
c.converter.Vertex(c.x, c.y)
return c
}
func (c *PathConverter) RMoveTo(dx, dy float64) *PathConverter {
c.MoveTo(c.x+dx, c.y+dy)
return c
}
func (c *PathConverter) LineTo(x, y float64) *PathConverter {
c.x, c.y = x, y
if c.startX == c.x && c.startY == c.y {
c.converter.NextCommand(VertexCloseCommand)
}
c.converter.Vertex(c.x, c.y)
c.converter.NextCommand(VertexJoinCommand)
return c
}
func (c *PathConverter) RLineTo(dx, dy float64) *PathConverter {
c.LineTo(c.x+dx, c.y+dy)
return c
}
func (c *PathConverter) QuadCurveTo(cx, cy, x, y float64) *PathConverter {
quadraticBezier(c.converter, c.x, c.y, cx, cy, x, y, c.ApproximationScale, c.AngleTolerance)
c.x, c.y = x, y
if c.startX == c.x && c.startY == c.y {
c.converter.NextCommand(VertexCloseCommand)
}
c.converter.Vertex(c.x, c.y)
return c
}
func (c *PathConverter) RQuadCurveTo(dcx, dcy, dx, dy float64) *PathConverter {
c.QuadCurveTo(c.x+dcx, c.y+dcy, c.x+dx, c.y+dy)
return c
}
func (c *PathConverter) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) *PathConverter {
cubicBezier(c.converter, c.x, c.y, cx1, cy1, cx2, cy2, x, y, c.ApproximationScale, c.AngleTolerance, c.CuspLimit)
c.x, c.y = x, y
if c.startX == c.x && c.startY == c.y {
c.converter.NextCommand(VertexCloseCommand)
}
c.converter.Vertex(c.x, c.y)
return c
}
func (c *PathConverter) RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float64) *PathConverter {
c.CubicCurveTo(c.x+dcx1, c.y+dcy1, c.x+dcx2, c.y+dcy2, c.x+dx, c.y+dy)
return c
}
func (c *PathConverter) ArcTo(cx, cy, rx, ry, startAngle, angle float64) *PathConverter {
endAngle := startAngle + angle
clockWise := true
if angle < 0 {
clockWise = false
}
// normalize
if clockWise {
for endAngle < startAngle {
endAngle += math.Pi * 2.0
}
} else {
for startAngle < endAngle {
startAngle += math.Pi * 2.0
}
}
startX := cx + math.Cos(startAngle)*rx
startY := cy + math.Sin(startAngle)*ry
c.MoveTo(startX, startY)
c.x, c.y = arc(c.converter, cx, cy, rx, ry, startAngle, angle, c.ApproximationScale)
if c.startX == c.x && c.startY == c.y {
c.converter.NextCommand(VertexCloseCommand)
}
c.converter.Vertex(c.x, c.y)
return c
}
func (c *PathConverter) RArcTo(dcx, dcy, rx, ry, startAngle, angle float64) *PathConverter {
c.ArcTo(c.x+dcx, c.y+dcy, rx, ry, startAngle, angle)
return c
}
func (c *PathConverter) Close() *PathConverter {
c.converter.NextCommand(VertexCloseCommand)
c.converter.Vertex(c.startX, c.startY)
return c
}

165
draw2d/path_storage.go Normal file
View file

@ -0,0 +1,165 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"fmt"
"math"
)
type PathCmd int
const (
MoveTo PathCmd = iota
LineTo
QuadCurveTo
CubicCurveTo
ArcTo
Close
)
type PathStorage struct {
commands []PathCmd
vertices []float64
x, y float64
}
func (p *PathStorage) appendToPath(cmd PathCmd, vertices ...float64) {
p.commands = append(p.commands, cmd)
p.vertices = append(p.vertices, vertices...)
}
func (src *PathStorage) Copy() (dest *PathStorage) {
dest = new(PathStorage)
dest.commands = make([]PathCmd, len(src.commands))
copy(dest.commands, src.commands)
dest.vertices = make([]float64, len(src.vertices))
copy(dest.vertices, src.vertices)
return dest
}
func (p *PathStorage) LastPoint() (x, y float64) {
return p.x, p.y
}
func (p *PathStorage) IsEmpty() bool {
return len(p.commands) == 0
}
func (p *PathStorage) Close() *PathStorage {
p.appendToPath(Close)
return p
}
func (p *PathStorage) MoveTo(x, y float64) *PathStorage {
p.appendToPath(MoveTo, x, y)
p.x = x
p.y = y
return p
}
func (p *PathStorage) RMoveTo(dx, dy float64) *PathStorage {
x, y := p.LastPoint()
p.MoveTo(x+dx, y+dy)
return p
}
func (p *PathStorage) LineTo(x, y float64) *PathStorage {
p.appendToPath(LineTo, x, y)
p.x = x
p.y = y
return p
}
func (p *PathStorage) RLineTo(dx, dy float64) *PathStorage {
x, y := p.LastPoint()
p.LineTo(x+dx, y+dy)
return p
}
func (p *PathStorage) QuadCurveTo(cx, cy, x, y float64) *PathStorage {
p.appendToPath(QuadCurveTo, cx, cy, x, y)
p.x = x
p.y = y
return p
}
func (p *PathStorage) RQuadCurveTo(dcx, dcy, dx, dy float64) *PathStorage {
x, y := p.LastPoint()
p.QuadCurveTo(x+dcx, y+dcy, x+dx, y+dy)
return p
}
func (p *PathStorage) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) *PathStorage {
p.appendToPath(CubicCurveTo, cx1, cy1, cx2, cy2, x, y)
p.x = x
p.y = y
return p
}
func (p *PathStorage) RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float64) *PathStorage {
x, y := p.LastPoint()
p.CubicCurveTo(x+dcx1, y+dcy1, x+dcx2, y+dcy2, x+dx, y+dy)
return p
}
func (p *PathStorage) ArcTo(cx, cy, rx, ry, startAngle, angle float64) *PathStorage {
endAngle := startAngle + angle
clockWise := true
if angle < 0 {
clockWise = false
}
// normalize
if clockWise {
for endAngle < startAngle {
endAngle += math.Pi * 2.0
}
} else {
for startAngle < endAngle {
startAngle += math.Pi * 2.0
}
}
startX := cx + math.Cos(startAngle)*rx
startY := cy + math.Sin(startAngle)*ry
if len(p.commands) > 0 {
p.LineTo(startX, startY)
} else {
p.MoveTo(startX, startY)
}
p.appendToPath(ArcTo, cx, cy, rx, ry, startAngle, angle)
p.x = cx + math.Cos(endAngle)*rx
p.y = cy + math.Sin(endAngle)*ry
return p
}
func (p *PathStorage) RArcTo(dcx, dcy, rx, ry, startAngle, angle float64) *PathStorage {
x, y := p.LastPoint()
p.ArcTo(x+dcx, y+dcy, rx, ry, startAngle, angle)
return p
}
func (p *PathStorage) String() string {
s := ""
j := 0
for _, cmd := range p.commands {
switch cmd {
case MoveTo:
s += fmt.Sprintf("MoveTo: %f, %f\n", p.vertices[j], p.vertices[j+1])
j = j + 2
case LineTo:
s += fmt.Sprintf("LineTo: %f, %f\n", p.vertices[j], p.vertices[j+1])
j = j + 2
case QuadCurveTo:
s += fmt.Sprintf("QuadCurveTo: %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3])
j = j + 4
case CubicCurveTo:
s += fmt.Sprintf("CubicCurveTo: %f, %f, %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5])
j = j + 6
case ArcTo:
s += fmt.Sprintf("ArcTo: %f, %f, %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5])
j = j + 6
case Close:
s += "Close\n"
}
}
return s
}

199
draw2d/stack_gc.go Normal file
View file

@ -0,0 +1,199 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"image"
)
type StackGraphicContext struct {
current *ContextStack
}
type ContextStack struct {
Tr MatrixTransform
Path *PathStorage
LineWidth float64
Dash []float64
DashOffset float64
StrokeColor image.Color
FillColor image.Color
FillRule FillRule
Cap Cap
Join Join
FontSize float64
FontData FontData
previous *ContextStack
}
/**
* Create a new Graphic context from an image
*/
func NewStackGraphicContext() (*StackGraphicContext){
gc := &StackGraphicContext{}
gc.current = new(ContextStack)
gc.current.Tr = NewIdentityMatrix()
gc.current.Path = new(PathStorage)
gc.current.LineWidth = 1.0
gc.current.StrokeColor = image.Black
gc.current.FillColor = image.White
gc.current.Cap = RoundCap
gc.current.FillRule = FillRuleEvenOdd
gc.current.Join = RoundJoin
gc.current.FontSize = 10
gc.current.FontData = defaultFontData
return gc
}
func (gc *StackGraphicContext) GetMatrixTransform() MatrixTransform {
return gc.current.Tr
}
func (gc *StackGraphicContext) SetMatrixTransform(Tr MatrixTransform) {
gc.current.Tr = Tr
}
func (gc *StackGraphicContext) ComposeMatrixTransform(Tr MatrixTransform) {
gc.current.Tr = Tr.Multiply(gc.current.Tr)
}
func (gc *StackGraphicContext) Rotate(angle float64) {
gc.current.Tr = NewRotationMatrix(angle).Multiply(gc.current.Tr)
}
func (gc *StackGraphicContext) Translate(tx, ty float64) {
gc.current.Tr = NewTranslationMatrix(tx, ty).Multiply(gc.current.Tr)
}
func (gc *StackGraphicContext) Scale(sx, sy float64) {
gc.current.Tr = NewScaleMatrix(sx, sy).Multiply(gc.current.Tr)
}
func (gc *StackGraphicContext) SetStrokeColor(c image.Color) {
gc.current.StrokeColor = c
}
func (gc *StackGraphicContext) SetFillColor(c image.Color) {
gc.current.FillColor = c
}
func (gc *StackGraphicContext) SetFillRule(f FillRule) {
gc.current.FillRule = f
}
func (gc *StackGraphicContext) SetLineWidth(LineWidth float64) {
gc.current.LineWidth = LineWidth
}
func (gc *StackGraphicContext) SetLineCap(Cap Cap) {
gc.current.Cap = Cap
}
func (gc *StackGraphicContext) SetLineJoin(Join Join) {
gc.current.Join = Join
}
func (gc *StackGraphicContext) SetLineDash(Dash []float64, DashOffset float64) {
gc.current.Dash = Dash
gc.current.DashOffset = DashOffset
}
func (gc *StackGraphicContext) SetFontSize(FontSize float64) {
gc.current.FontSize = FontSize
}
func (gc *StackGraphicContext) GetFontSize() float64 {
return gc.current.FontSize
}
func (gc *StackGraphicContext) SetFontData(FontData FontData) {
gc.current.FontData = FontData
}
func (gc *StackGraphicContext) GetFontData() FontData {
return gc.current.FontData
}
func (gc *StackGraphicContext) BeginPath() {
gc.current.Path = new(PathStorage)
}
func (gc *StackGraphicContext) IsEmpty() bool {
return gc.current.Path.IsEmpty()
}
func (gc *StackGraphicContext) LastPoint() (float64, float64) {
return gc.current.Path.LastPoint()
}
func (gc *StackGraphicContext) MoveTo(x, y float64) {
gc.current.Path.MoveTo(x, y)
}
func (gc *StackGraphicContext) RMoveTo(dx, dy float64) {
gc.current.Path.RMoveTo(dx, dy)
}
func (gc *StackGraphicContext) LineTo(x, y float64) {
gc.current.Path.LineTo(x, y)
}
func (gc *StackGraphicContext) RLineTo(dx, dy float64) {
gc.current.Path.RLineTo(dx, dy)
}
func (gc *StackGraphicContext) QuadCurveTo(cx, cy, x, y float64) {
gc.current.Path.QuadCurveTo(cx, cy, x, y)
}
func (gc *StackGraphicContext) RQuadCurveTo(dcx, dcy, dx, dy float64) {
gc.current.Path.RQuadCurveTo(dcx, dcy, dx, dy)
}
func (gc *StackGraphicContext) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
gc.current.Path.CubicCurveTo(cx1, cy1, cx2, cy2, x, y)
}
func (gc *StackGraphicContext) RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float64) {
gc.current.Path.RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy)
}
func (gc *StackGraphicContext) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
gc.current.Path.ArcTo(cx, cy, rx, ry, startAngle, angle)
}
func (gc *StackGraphicContext) RArcTo(dcx, dcy, rx, ry, startAngle, angle float64) {
gc.current.Path.RArcTo(dcx, dcy, rx, ry, startAngle, angle)
}
func (gc *StackGraphicContext) Close() {
gc.current.Path.Close()
}
func (gc *StackGraphicContext) Save() {
context := new(ContextStack)
context.FontSize = gc.current.FontSize
context.FontData = gc.current.FontData
context.LineWidth = gc.current.LineWidth
context.StrokeColor = gc.current.StrokeColor
context.FillColor = gc.current.FillColor
context.FillRule = gc.current.FillRule
context.Dash = gc.current.Dash
context.DashOffset = gc.current.DashOffset
context.Cap = gc.current.Cap
context.Join = gc.current.Join
context.Path = gc.current.Path.Copy()
copy(context.Tr[:], gc.current.Tr[:])
context.previous = gc.current
gc.current = context
}
func (gc *StackGraphicContext) Restore() {
if gc.current.previous != nil {
oldContext := gc.current
gc.current = gc.current.previous
oldContext.previous = nil
}
}

122
draw2d/stroker.go Normal file
View file

@ -0,0 +1,122 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package draw2d
type Cap int
const (
RoundCap Cap = iota
ButtCap
SquareCap
)
type Join int
const (
BevelJoin Join = iota
RoundJoin
MiterJoin
)
type LineStroker struct {
Next VertexConverter
HalfLineWidth float64
Cap Cap
Join Join
vertices []float64
rewind []float64
x, y, nx, ny float64
command VertexCommand
}
func NewLineStroker(c Cap, j Join, converter VertexConverter) *LineStroker {
l := new(LineStroker)
l.Next = converter
l.HalfLineWidth = 0.5
l.vertices = make([]float64, 0)
l.rewind = make([]float64, 0)
l.Cap = c
l.Join = j
l.command = VertexNoCommand
return l
}
func (l *LineStroker) NextCommand(command VertexCommand) {
l.command = command
if command == VertexStopCommand {
l.Next.NextCommand(VertexStartCommand)
for i, j := 0, 1; j < len(l.vertices); i, j = i+2, j+2 {
l.Next.Vertex(l.vertices[i], l.vertices[j])
l.Next.NextCommand(VertexNoCommand)
}
for i, j := len(l.rewind)-2, len(l.rewind)-1; j > 0; i, j = i-2, j-2 {
l.Next.NextCommand(VertexNoCommand)
l.Next.Vertex(l.rewind[i], l.rewind[j])
}
if len(l.vertices) > 1 {
l.Next.NextCommand(VertexNoCommand)
l.Next.Vertex(l.vertices[0], l.vertices[1])
}
l.Next.NextCommand(VertexStopCommand)
// reinit vertices
l.vertices = make([]float64, 0)
l.rewind = make([]float64, 0)
l.x, l.y, l.nx, l.ny = 0, 0, 0, 0
}
}
func (l *LineStroker) Vertex(x, y float64) {
switch l.command {
case VertexNoCommand:
l.line(l.x, l.y, x, y)
case VertexStartCommand:
l.x, l.y = x, y
case VertexJoinCommand:
l.joinLine(l.x, l.y, l.nx, l.ny, x, y)
case VertexCloseCommand:
l.line(l.x, l.y, x, y)
l.joinLine(l.x, l.y, l.nx, l.ny, x, y)
l.closePolygon()
}
l.command = VertexNoCommand
}
func (l *LineStroker) closePolygon() {
if len(l.vertices) > 1 {
l.vertices = append(l.vertices, l.vertices[0], l.vertices[1])
l.rewind = append(l.rewind, l.rewind[0], l.rewind[1])
}
}
func (l *LineStroker) line(x1, y1, x2, y2 float64) {
dx := (x2 - x1)
dy := (y2 - y1)
d := vectorDistance(dx, dy)
if d != 0 {
nx := dy * l.HalfLineWidth / d
ny := -(dx * l.HalfLineWidth / d)
l.vertices = append(l.vertices, x1+nx, y1+ny, x2+nx, y2+ny)
l.rewind = append(l.rewind, x1-nx, y1-ny, x2-nx, y2-ny)
l.x, l.y, l.nx, l.ny = x2, y2, nx, ny
}
}
func (l *LineStroker) joinLine(x1, y1, nx1, ny1, x2, y2 float64) {
dx := (x2 - x1)
dy := (y2 - y1)
d := vectorDistance(dx, dy)
if d != 0 {
nx := dy * l.HalfLineWidth / d
ny := -(dx * l.HalfLineWidth / d)
/* l.join(x1, y1, x1 + nx, y1 - ny, nx, ny, x1 + ny2, y1 + nx2, nx2, ny2)
l.join(x1, y1, x1 - ny1, y1 - nx1, nx1, ny1, x1 - ny2, y1 - nx2, nx2, ny2)*/
l.vertices = append(l.vertices, x1+nx, y1+ny, x2+nx, y2+ny)
l.rewind = append(l.rewind, x1-nx, y1-ny, x2-nx, y2-ny)
l.x, l.y, l.nx, l.ny = x2, y2, nx, ny
}
}

279
draw2d/transform.go Normal file
View file

@ -0,0 +1,279 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"freetype-go.googlecode.com/hg/freetype/raster"
"math"
)
type MatrixTransform [6]float64
const (
epsilon = 1e-6
)
func (tr MatrixTransform) Determinant() float64 {
return tr[0]*tr[3] - tr[1]*tr[2]
}
func (tr MatrixTransform) Transform(points ...*float64) {
for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
x := *points[i]
y := *points[j]
*points[i] = x*tr[0] + y*tr[2] + tr[4]
*points[j] = x*tr[1] + y*tr[3] + tr[5]
}
}
func (tr MatrixTransform) TransformRasterPoint(points ...*raster.Point) {
for _, point := range points {
x := float64(point.X) / 256
y := float64(point.Y) / 256
point.X = raster.Fix32((x*tr[0] + y*tr[2] + tr[4]) * 256)
point.Y = raster.Fix32((x*tr[1] + y*tr[3] + tr[5]) * 256)
}
}
func (tr MatrixTransform) InverseTransform(points ...*float64) {
d := tr.Determinant() // matrix determinant
for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
x := *points[i]
y := *points[j]
*points[i] = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
*points[j] = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
}
}
// ******************** Vector transformations ********************
func (tr MatrixTransform) VectorTransform(points ...*float64) {
for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
x := *points[i]
y := *points[j]
*points[i] = x*tr[0] + y*tr[2]
*points[j] = x*tr[1] + y*tr[3]
}
}
// ******************** Transformations creation ********************
/** Creates an identity transformation. */
func NewIdentityMatrix() MatrixTransform {
return [6]float64{1, 0, 0, 1, 0, 0}
}
/**
* Creates a transformation with a translation, that,
* transform point1 into point2.
*/
func NewTranslationMatrix(tx, ty float64) MatrixTransform {
return [6]float64{1, 0, 0, 1, tx, ty}
}
/**
* Creates a transformation with a sx, sy scale factor
*/
func NewScaleMatrix(sx, sy float64) MatrixTransform {
return [6]float64{sx, 0, 0, sy, 0, 0}
}
/**
* Creates a rotation transformation.
*/
func NewRotationMatrix(angle float64) MatrixTransform {
c := math.Cos(angle)
s := math.Sin(angle)
return [6]float64{c, s, -s, c, 0, 0}
}
/**
* Creates a transformation, combining a scale and a translation, that transform rectangle1 into rectangle2.
*/
func NewMatrixTransform(rectangle1, rectangle2 [4]float64) MatrixTransform {
xScale := (rectangle2[2] - rectangle2[0]) / (rectangle1[2] - rectangle1[0])
yScale := (rectangle2[3] - rectangle2[1]) / (rectangle1[3] - rectangle1[1])
xOffset := rectangle2[0] - (rectangle1[0] * xScale)
yOffset := rectangle2[1] - (rectangle1[1] * yScale)
return [6]float64{xScale, 0, 0, yScale, xOffset, yOffset}
}
// ******************** Transformations operations ********************
/**
* Returns a transformation that is the inverse of the given transformation.
*/
func (tr MatrixTransform) GetInverseTransformation() MatrixTransform {
d := tr.Determinant() // matrix determinant
return [6]float64{
tr[3] / d,
-tr[1] / d,
-tr[2] / d,
tr[0] / d,
(tr[2]*tr[5] - tr[3]*tr[4]) / d,
(tr[1]*tr[4] - tr[0]*tr[5]) / d}
}
func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform {
return [6]float64{
tr1[0]*tr2[0] + tr1[1]*tr2[2],
tr1[1]*tr2[3] + tr1[0]*tr2[1],
tr1[2]*tr2[0] + tr1[3]*tr2[2],
tr1[3]*tr2[3] + tr1[2]*tr2[1],
tr1[4]*tr2[0] + tr1[5]*tr2[2] + tr2[4],
tr1[5]*tr2[3] + tr1[4]*tr2[1] + tr2[5]}
}
func (tr *MatrixTransform) Scale(sx, sy float64) *MatrixTransform {
tr[0] = tr[0] * sx
tr[1] = tr[1] * sx
tr[4] = tr[4] * sx
tr[2] = tr[2] * sy
tr[3] = tr[3] * sy
tr[5] = tr[5] * sy
return tr
}
func (tr *MatrixTransform) Translate(tx, ty float64) *MatrixTransform {
tr[4] = tr[4] + tx
tr[5] = tr[5] + ty
return tr
}
func (tr *MatrixTransform) Rotate(angle float64) *MatrixTransform {
ca := math.Cos(angle)
sa := math.Sin(angle)
t0 := tr[0]*ca - tr[1]*sa
t2 := tr[1]*ca - tr[3]*sa
t4 := tr[4]*ca - tr[5]*sa
tr[1] = tr[0]*sa + tr[1]*ca
tr[3] = tr[2]*sa + tr[3]*ca
tr[5] = tr[4]*sa + tr[5]*ca
tr[0] = t0
tr[2] = t2
tr[4] = t4
return tr
}
func (tr MatrixTransform) GetTranslation() (x, y float64) {
return tr[4], tr[5]
}
func (tr MatrixTransform) GetScaling() (x, y float64) {
return tr[0], tr[3]
}
func (tr MatrixTransform) GetMaxAbsScaling() (s float64) {
sx := math.Fabs(tr[0])
sy := math.Fabs(tr[3])
if sx > sy {
return sx
}
return sy
}
func (tr MatrixTransform) GetMinAbsScaling() (s float64) {
sx := math.Fabs(tr[0])
sy := math.Fabs(tr[3])
if sx > sy {
return sy
}
return sx
}
// ******************** Testing ********************
/**
* Tests if a two transformation are equal. A tolerance is applied when
* comparing matrix elements.
*/
func (tr1 MatrixTransform) Equals(tr2 MatrixTransform) bool {
for i := 0; i < 6; i = i + 1 {
if !fequals(tr1[i], tr2[i]) {
return false
}
}
return true
}
/**
* Tests if a transformation is the identity transformation. A tolerance
* is applied when comparing matrix elements.
*/
func (tr MatrixTransform) IsIdentity() bool {
return fequals(tr[4], 0) && fequals(tr[5], 0) && tr.IsTranslation()
}
/**
* Tests if a transformation is is a pure translation. A tolerance
* is applied when comparing matrix elements.
*/
func (tr MatrixTransform) IsTranslation() bool {
return fequals(tr[0], 1) && fequals(tr[1], 0) && fequals(tr[2], 0) && fequals(tr[3], 1)
}
/**
* Compares two floats.
* return true if the distance between the two floats is less than epsilon, false otherwise
*/
func fequals(float1, float2 float64) bool {
return math.Fabs(float1-float2) <= epsilon
}
// this VertexConverter apply the Matrix transformation tr
type VertexMatrixTransform struct {
tr MatrixTransform
Next VertexConverter
}
func NewVertexMatrixTransform(tr MatrixTransform, converter VertexConverter) *VertexMatrixTransform {
return &VertexMatrixTransform{tr, converter}
}
// Vertex Matrix Transform
func (vmt *VertexMatrixTransform) NextCommand(command VertexCommand) {
vmt.Next.NextCommand(command)
}
func (vmt *VertexMatrixTransform) Vertex(x, y float64) {
vmt.tr.Transform(&x, &y)
vmt.Next.Vertex(x, y)
}
// this adder apply a Matrix transformation to points
type MatrixTransformAdder struct {
tr MatrixTransform
next raster.Adder
}
func NewMatrixTransformAdder(tr MatrixTransform, adder raster.Adder) *MatrixTransformAdder {
return &MatrixTransformAdder{tr, adder}
}
// Start starts a new curve at the given point.
func (mta MatrixTransformAdder) Start(a raster.Point) {
mta.tr.TransformRasterPoint(&a)
mta.next.Start(a)
}
// Add1 adds a linear segment to the current curve.
func (mta MatrixTransformAdder) Add1(b raster.Point) {
mta.tr.TransformRasterPoint(&b)
mta.next.Add1(b)
}
// Add2 adds a quadratic segment to the current curve.
func (mta MatrixTransformAdder) Add2(b, c raster.Point) {
mta.tr.TransformRasterPoint(&b, &c)
mta.next.Add2(b, c)
}
// Add3 adds a cubic segment to the current curve.
func (mta MatrixTransformAdder) Add3(b, c, d raster.Point) {
mta.tr.TransformRasterPoint(&b, &c, &d)
mta.next.Add3(b, c, d)
}

18
draw2d/vertex2d.go Normal file
View file

@ -0,0 +1,18 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
type VertexCommand byte
const (
VertexNoCommand VertexCommand = iota
VertexStartCommand
VertexJoinCommand
VertexCloseCommand
VertexStopCommand
)
type VertexConverter interface {
NextCommand(cmd VertexCommand)
Vertex(x, y float64)
}

7
draw2dgl/Makefile Normal file
View file

@ -0,0 +1,7 @@
include $(GOROOT)/src/Make.inc
TARG=draw2d.googlecode.com/hg/draw2dgl
GOFILES=\
gc.go\
include $(GOROOT)/src/Make.pkg

2
draw2dgl/gc.go Normal file
View file

@ -0,0 +1,2 @@
package draw2dgl

18
postscript/Makefile Normal file
View file

@ -0,0 +1,18 @@
include $(GOROOT)/src/Make.inc
TARG=draw2d.googlecode.com/hg/postscript
GOFILES=operators_array.go\
operators_dictionary.go\
operators_misc.go\
procedure.go\
interpreter.go\
operators_conflict.go\
operators_graphics.go\
operators_relational.go\
scanner.go\
operators.go\
operators_control.go\
operators_math.go\
operators_stack.go\
include $(GOROOT)/src/Make.pkg

309
postscript/interpreter.go Normal file
View file

@ -0,0 +1,309 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
import (
"os"
"log"
"strconv"
"io"
"draw2d.googlecode.com/hg/draw2d"
)
type Interpreter struct {
valueStack ValueStack
dictionaryStack DictionaryStack
gc draw2d.GraphicContext
}
type Value interface{}
type ValueStack []Value
type Dictionary map[string]Value
type DictionaryStack []Dictionary
type Operator interface {
Execute(interpreter *Interpreter)
}
func NewInterpreter(gc draw2d.GraphicContext) *Interpreter {
interpreter := new(Interpreter)
interpreter.valueStack = make([]Value, 0, 100)
interpreter.dictionaryStack = make([]Dictionary, 2, 10)
interpreter.dictionaryStack[0] = NewDictionary(100) // System dictionary
interpreter.dictionaryStack[1] = NewDictionary(100) // user dictionary
initSystemOperators(interpreter)
interpreter.gc = gc
return interpreter
}
func NewDictionary(prealloc int) Dictionary {
return make(Dictionary, prealloc)
}
func (interpreter *Interpreter) GetGraphicContext() draw2d.GraphicContext {
return interpreter.gc
}
func (interpreter *Interpreter) Execute(reader io.Reader) {
var scanner Scanner
scanner.Init(reader)
token := scanner.Scan()
for token != EOF {
interpreter.scan(&scanner, token)
token = scanner.Scan()
}
}
func (interpreter *Interpreter) ExecuteFile(filePath string) os.Error {
src, err := os.Open(filePath, 0, 0)
if src == nil {
log.Printf("can't open file; err=%s\n", err.String())
return err
}
defer src.Close()
interpreter.Execute(src)
return nil
}
func (interpreter *Interpreter) computeReference(ref string) {
value, _ := interpreter.FindValueInDictionaries(ref)
if value == nil {
log.Printf("Unknown def: %s\n", ref)
} else {
operator, isOperator := value.(Operator)
if isOperator {
operator.Execute(interpreter)
} else {
interpreter.Push(value)
}
}
}
func (interpreter *Interpreter) scan(scanner *Scanner, token int) {
if token == Ident {
switch scanner.TokenText() {
case "true":
interpreter.Push(true)
case "false":
interpreter.Push(false)
case "null":
interpreter.Push(nil)
default:
interpreter.computeReference(scanner.TokenText())
}
} else if token == '/' {
scanner.Scan()
interpreter.Push("/" + scanner.TokenText())
} else if token == '[' {
interpreter.Push(interpreter.scanArray(scanner))
} else if token == '{' {
// procedure
interpreter.Push(interpreter.scanProcedure(scanner))
} else if token == Float || token == Int {
f, err := strconv.Atof64(scanner.TokenText())
if err != nil {
log.Printf("Float expected: %s\n", scanner.TokenText())
interpreter.Push(scanner.TokenText())
} else {
interpreter.Push(f)
}
} else {
interpreter.Push(scanner.TokenText())
}
}
func (interpreter *Interpreter) scanArray(scanner *Scanner) []Value {
array := make([]Value, 0, 10)
token := scanner.Scan()
for token != EOF && token != ']' {
if token == Ident {
var v Value = scanner.TokenText()
switch scanner.TokenText() {
case "true":
v = true
case "false":
v = false
case "null":
v = nil
}
array = append(array, v)
} else {
interpreter.scan(scanner, token)
array = append(array, interpreter.Pop())
}
token = scanner.Scan()
}
return array
}
func (interpreter *Interpreter) scanProcedure(scanner *Scanner) *ProcedureDefinition {
proceduredef := NewProcedureDefinition()
token := scanner.Scan()
for token != EOF && token != '}' {
if token == Ident {
var v Value = scanner.TokenText()
switch scanner.TokenText() {
case "true":
v = true
case "false":
v = false
case "null":
v = nil
}
proceduredef.Add(v)
} else {
interpreter.scan(scanner, token)
proceduredef.Add(interpreter.Pop())
}
token = scanner.Scan()
}
return proceduredef
}
//Dictionary Operation
func (interpreter *Interpreter) PushDictionary(dictionary Dictionary) {
interpreter.dictionaryStack = append(interpreter.dictionaryStack, dictionary)
}
func (interpreter *Interpreter) PopDictionary() Dictionary {
stackPointer := len(interpreter.dictionaryStack) - 1
dictionary := interpreter.dictionaryStack[stackPointer]
interpreter.dictionaryStack = interpreter.dictionaryStack[0:stackPointer]
return dictionary
}
func (interpreter *Interpreter) PeekDictionary() Dictionary {
stackPointer := len(interpreter.dictionaryStack) - 1
return interpreter.dictionaryStack[stackPointer]
}
func (interpreter *Interpreter) ClearDictionaries() {
interpreter.dictionaryStack = interpreter.dictionaryStack[:2]
}
func (interpreter *Interpreter) DictionaryStackSize() int {
return len(interpreter.dictionaryStack)
}
func (interpreter *Interpreter) FindValue(name string) Value {
return interpreter.PeekDictionary()[name]
}
func (interpreter *Interpreter) FindValueInDictionaries(name string) (Value, Dictionary) {
for i := len(interpreter.dictionaryStack) - 1; i >= 0; i-- {
value := interpreter.dictionaryStack[i][name]
if value != nil {
return value, interpreter.dictionaryStack[i]
}
}
return nil, nil
}
func (interpreter *Interpreter) UserDictionary() Dictionary {
return interpreter.dictionaryStack[0]
}
func (interpreter *Interpreter) SystemDictionary() Dictionary {
return interpreter.dictionaryStack[0]
}
func (interpreter *Interpreter) Define(name string, value Value) {
interpreter.PeekDictionary()[name] = value
}
func (interpreter *Interpreter) SystemDefine(name string, value Value) {
interpreter.dictionaryStack[0][name] = value
}
//Operand Operation
func (interpreter *Interpreter) Push(operand Value) {
//log.Printf("Push operand: %v\n", operand)
interpreter.valueStack = append(interpreter.valueStack, operand)
}
func (interpreter *Interpreter) Pop() Value {
valueStackPointer := len(interpreter.valueStack) - 1
operand := interpreter.valueStack[valueStackPointer]
interpreter.valueStack = interpreter.valueStack[0:valueStackPointer]
//log.Printf("Pop operand: %v\n", operand)
return operand
}
func (interpreter *Interpreter) PopValues(n int) []Value {
valueStackPointer := len(interpreter.valueStack) - 1
operands := make([]Value, n)
copy(operands, interpreter.valueStack[valueStackPointer-n+1:valueStackPointer+1])
interpreter.valueStack = interpreter.valueStack[0 : valueStackPointer-n+1]
return operands
}
func (interpreter *Interpreter) GetValues(n int) []Value {
valueStackPointer := len(interpreter.valueStack) - 1
operands := make([]Value, n)
copy(operands, interpreter.valueStack[valueStackPointer-n+1:valueStackPointer+1])
return operands
}
func (interpreter *Interpreter) Get(index int) Value {
valueStackPointer := len(interpreter.valueStack) - 1
return interpreter.valueStack[valueStackPointer-index]
}
func (interpreter *Interpreter) Peek() Value {
valueStackPointer := len(interpreter.valueStack) - 1
return interpreter.valueStack[valueStackPointer]
}
func (interpreter *Interpreter) OperandSize() int {
return len(interpreter.valueStack)
}
func (interpreter *Interpreter) ClearOperands() {
interpreter.valueStack = interpreter.valueStack[0:0]
}
// misc pop
func (interpreter *Interpreter) PopFloat() float64 {
operand := interpreter.Pop()
return operand.(float64)
}
func (interpreter *Interpreter) PopInt() int {
f := interpreter.PopFloat()
return int(f)
}
func (interpreter *Interpreter) PopOperator() Operator {
operator := interpreter.Pop()
return operator.(Operator)
}
func (interpreter *Interpreter) PopProcedureDefinition() *ProcedureDefinition {
def := interpreter.Pop()
return def.(*ProcedureDefinition)
}
func (interpreter *Interpreter) PopName() string {
name := interpreter.Pop().(string)
return name[1:]
}
func (interpreter *Interpreter) PopString() string {
s := interpreter.Pop().(string)
return s[1 : len(s)-1]
}
func (interpreter *Interpreter) PopBoolean() bool {
s := interpreter.Pop()
return s.(bool)
}
func (interpreter *Interpreter) PopArray() []Value {
s := interpreter.Pop()
return s.([]Value)
}

43
postscript/operators.go Normal file
View file

@ -0,0 +1,43 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
type OperatorFunc func(interpreter *Interpreter)
type PrimitiveOperator struct {
f OperatorFunc
}
func NewOperator(f OperatorFunc) *PrimitiveOperator {
return &PrimitiveOperator{f}
}
func (o *PrimitiveOperator) Execute(interpreter *Interpreter) {
o.f(interpreter)
}
func save(interpreter *Interpreter) {
interpreter.Push("VM Snapshot")
}
func restore(interpreter *Interpreter) {
interpreter.Pop()
}
func initSystemOperators(interpreter *Interpreter) {
interpreter.SystemDefine("save", NewOperator(save))
interpreter.SystemDefine("restore", NewOperator(restore))
initStackOperator(interpreter)
initMathOperators(interpreter)
initArrayOperators(interpreter)
initDictionaryOperators(interpreter)
initRelationalOperators(interpreter)
initControlOperators(interpreter)
initMiscellaneousOperators(interpreter)
initDrawingOperators(interpreter)
initConflictingOperators(interpreter)
}

View file

@ -0,0 +1,93 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
import ()
//int array array -> Create array of length int
func array(interpreter *Interpreter) {
interpreter.Push(make([]Value, interpreter.PopInt()))
}
//array length int -> Return number of elements in array
func lengtharray(interpreter *Interpreter) {
interpreter.Push(float64(len(interpreter.Pop().([]Value))))
}
//array index get any -> Return array element indexed by index
func getarray(interpreter *Interpreter) {
index := interpreter.PopInt()
array := interpreter.Pop().([]Value)
interpreter.Push(array[index])
}
//array index any put -> Put any into array at index
func putarray(interpreter *Interpreter) {
value := interpreter.Pop()
index := interpreter.PopInt()
array := interpreter.Pop().([]Value)
array[index] = value
}
//array index count getinterval subarray -> Return subarray of array starting at index for count elements
func getinterval(interpreter *Interpreter) {
count := interpreter.PopInt()
index := interpreter.PopInt()
array := interpreter.Pop().([]Value)
subarray := make([]Value, count)
copy(subarray, array[index:index+count])
interpreter.Push(subarray)
}
//array1 index array2 putinterval Replace subarray of array1 starting at index by array2|packedarray2
func putinterval(interpreter *Interpreter) {
array2 := interpreter.Pop().([]Value)
index := interpreter.PopInt()
array1 := interpreter.Pop().([]Value)
for i, v := range array2 {
array1[i+index] = v
}
}
// any0 … anyn1 array astore array
// stores the objects any0 to anyn1 from the operand stack into array, where n is the length of array
func astore(interpreter *Interpreter) {
array := interpreter.Pop().([]Value)
n := len(array)
for i := 0; i < n; i++ {
array[i] = interpreter.Pop()
}
}
//array aload any0 … any-1 array
//Push all elements of array on stack
func aload(interpreter *Interpreter) {
array := interpreter.Pop().([]Value)
for _, v := range array {
interpreter.Push(v)
}
interpreter.Push(array)
}
//array proc forall Execute proc for each element of array
func forallarray(interpreter *Interpreter) {
proc := NewProcedure(interpreter.PopProcedureDefinition())
array := interpreter.Pop().([]Value)
for _, v := range array {
interpreter.Push(v)
proc.Execute(interpreter)
}
}
var packing bool = false
func currentpacking(interpreter *Interpreter) {
interpreter.Push(packing)
}
func setpacking(interpreter *Interpreter) {
packing = interpreter.PopBoolean()
}
func initArrayOperators(interpreter *Interpreter) {
interpreter.SystemDefine("array", NewOperator(array))
interpreter.SystemDefine("getinterval", NewOperator(getinterval))
interpreter.SystemDefine("putinterval", NewOperator(putinterval))
interpreter.SystemDefine("astore", NewOperator(astore))
interpreter.SystemDefine("aload", NewOperator(aload))
interpreter.SystemDefine("currentpacking", NewOperator(currentpacking))
interpreter.SystemDefine("setpacking", NewOperator(setpacking))
}

View file

@ -0,0 +1,96 @@
package postscript
import (
"fmt"
"log"
)
// dictionary copy conflict with stack copy
// type dicriminant
func commonCopy(interpreter *Interpreter) {
switch v := interpreter.Peek().(type) {
case float64:
copystack(interpreter)
case Dictionary:
copydict(interpreter)
default:
panic(fmt.Sprintf("Not yet implemented: %v copy", v))
}
}
func commonforall(interpreter *Interpreter) {
switch v := interpreter.Get(1).(type) {
case Dictionary:
foralldict(interpreter)
case []Value:
forallarray(interpreter)
case string:
panic("Not yet implemented: string proc forall")
default:
panic(fmt.Sprintf("Not yet implemented: %v proc forall", v))
}
}
func length(interpreter *Interpreter) {
switch v := interpreter.Peek().(type) {
case Dictionary:
lengthdict(interpreter)
case []Value:
lengtharray(interpreter)
case string:
panic("Not yet implemented: string proc forall")
default:
panic(fmt.Sprintf("Not yet implemented: %v length", v))
}
}
func get(interpreter *Interpreter) {
switch v := interpreter.Get(1).(type) {
case Dictionary:
getdict(interpreter)
case []Value:
getarray(interpreter)
case string:
panic("Not yet implemented: string proc forall")
default:
panic(fmt.Sprintf("Not yet implemented: %v index get", v))
}
}
func put(interpreter *Interpreter) {
switch v := interpreter.Get(2).(type) {
case Dictionary:
putdict(interpreter)
case []Value:
putarray(interpreter)
case string:
panic("Not yet implemented: string proc forall")
default:
panic(fmt.Sprintf("Not yet implemented: %v index any put", v))
}
}
func readonly(interpreter *Interpreter) {
log.Println("readonly, not yet implemented")
}
func cvlit(interpreter *Interpreter) {
log.Println("cvlit, not yet implemented")
}
func xcheck(interpreter *Interpreter) {
value := interpreter.Pop()
if _, ok := value.(*ProcedureDefinition); ok {
interpreter.Push(true)
} else {
interpreter.Push(false)
}
}
func initConflictingOperators(interpreter *Interpreter) {
interpreter.SystemDefine("copy", NewOperator(commonCopy))
interpreter.SystemDefine("forall", NewOperator(commonforall))
interpreter.SystemDefine("length", NewOperator(length))
interpreter.SystemDefine("get", NewOperator(get))
interpreter.SystemDefine("put", NewOperator(put))
interpreter.SystemDefine("readonly", NewOperator(readonly))
interpreter.SystemDefine("cvlit", NewOperator(cvlit))
interpreter.SystemDefine("xcheck", NewOperator(xcheck))
}

View file

@ -0,0 +1,80 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
import (
"log"
)
// any exec Execute arbitrary object
func exec(interpreter *Interpreter) {
value := interpreter.Pop()
if pdef, ok := value.(*ProcedureDefinition); ok {
NewProcedure(pdef).Execute(interpreter)
} else if procedure, ok := value.(*Procedure); ok {
procedure.Execute(interpreter)
} else {
log.Printf("Push value: %v\n", value)
interpreter.Push(value)
}
}
func ifoperator(interpreter *Interpreter) {
operator := NewProcedure(interpreter.PopProcedureDefinition())
condition := interpreter.PopBoolean()
if condition {
operator.Execute(interpreter)
}
}
func ifelse(interpreter *Interpreter) {
operator2 := NewProcedure(interpreter.PopProcedureDefinition())
operator1 := NewProcedure(interpreter.PopProcedureDefinition())
condition := interpreter.PopBoolean()
if condition {
operator1.Execute(interpreter)
} else {
operator2.Execute(interpreter)
}
}
func foroperator(interpreter *Interpreter) {
proc := NewProcedure(interpreter.PopProcedureDefinition())
limit := interpreter.PopFloat()
inc := interpreter.PopFloat()
initial := interpreter.PopFloat()
for i := initial; i <= limit; i += inc {
interpreter.Push(i)
proc.Execute(interpreter)
}
}
func repeat(interpreter *Interpreter) {
proc := NewProcedure(interpreter.PopProcedureDefinition())
times := interpreter.PopInt()
for i := 0; i <= times; i++ {
proc.Execute(interpreter)
}
}
// any stopped bool -> Establish context for catching stop
func stopped(interpreter *Interpreter) {
value := interpreter.Pop()
if pdef, ok := value.(*ProcedureDefinition); ok {
NewProcedure(pdef).Execute(interpreter)
} else {
interpreter.Push(value)
}
interpreter.Push(false)
}
func initControlOperators(interpreter *Interpreter) {
interpreter.SystemDefine("exec", NewOperator(exec))
interpreter.SystemDefine("if", NewOperator(ifoperator))
interpreter.SystemDefine("ifelse", NewOperator(ifelse))
interpreter.SystemDefine("for", NewOperator(foroperator))
interpreter.SystemDefine("repeat", NewOperator(repeat))
interpreter.SystemDefine("stopped", NewOperator(stopped))
}

View file

@ -0,0 +1,171 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
import (
"log"
)
//int dict dict -> Create dictionary with capacity for int elements
func dict(interpreter *Interpreter) {
interpreter.Push(NewDictionary(interpreter.PopInt()))
}
//dict length int -> Return number of entries in dict
func lengthdict(interpreter *Interpreter) {
dictionary := interpreter.Pop().(Dictionary)
interpreter.Push(float64(len(dictionary)))
}
//dict maxlength int -> Return current capacity of dict
func maxlength(interpreter *Interpreter) {
interpreter.Pop()
interpreter.Push(float64(999999999)) // push arbitrary value
}
//dict begin -> Push dict on dictionary stack
func begin(interpreter *Interpreter) {
interpreter.PushDictionary(interpreter.Pop().(Dictionary))
}
// end -> Pop current dictionary off dictionary stack
func end(interpreter *Interpreter) {
interpreter.PopDictionary()
}
//key value def -> Associate key and value in current dictionary
func def(interpreter *Interpreter) {
value := interpreter.Pop()
name := interpreter.PopName()
if p, ok := value.(*ProcedureDefinition); ok {
value = NewProcedure(p)
}
interpreter.Define(name, value)
}
//key load value -> Search dictionary stack for key and return associated value
func load(interpreter *Interpreter) {
name := interpreter.PopName()
value, _ := interpreter.FindValueInDictionaries(name)
if value == nil {
log.Printf("Can't find value %s\n", name)
}
interpreter.Push(value)
}
//key value store -> Replace topmost definition of key
func store(interpreter *Interpreter) {
value := interpreter.Pop()
key := interpreter.PopName()
_, dictionary := interpreter.FindValueInDictionaries(key)
if dictionary != nil {
dictionary[key] = value
}
}
//dict key get any -> Return value associated with key in dict
func getdict(interpreter *Interpreter) {
key := interpreter.PopName()
dictionary := interpreter.Pop().(Dictionary)
interpreter.Push(dictionary[key])
}
//dict key value put -> Associate key with value in dict
func putdict(interpreter *Interpreter) {
value := interpreter.Pop()
key := interpreter.PopName()
dictionary := interpreter.Pop().(Dictionary)
dictionary[key] = value
}
//dict key undef Remove key and its value from dict
func undef(interpreter *Interpreter) {
key := interpreter.PopName()
dictionary := interpreter.Pop().(Dictionary)
dictionary[key] = nil
}
//dict key known bool -> Test whether key is in dict
func known(interpreter *Interpreter) {
key := interpreter.PopName()
dictionary := interpreter.Pop().(Dictionary)
interpreter.Push(dictionary[key] != nil)
}
//key where (dict true) or false -> Find dictionary in which key is defined
func where(interpreter *Interpreter) {
key := interpreter.PopName()
_, dictionary := interpreter.FindValueInDictionaries(key)
if dictionary == nil {
interpreter.Push(false)
} else {
interpreter.Push(dictionary)
interpreter.Push(true)
}
}
// dict1 dict2 copy dict2 -> Copy contents of dict1 to dict2
func copydict(interpreter *Interpreter) {
dict2 := interpreter.Pop().(Dictionary)
dict1 := interpreter.Pop().(Dictionary)
for key, value := range dict1 {
dict2[key] = value
}
interpreter.Push(dict2)
}
//dict proc forall -> Execute proc for each entry in dict
func foralldict(interpreter *Interpreter) {
proc := NewProcedure(interpreter.PopProcedureDefinition())
dict := interpreter.Pop().(Dictionary)
for key, value := range dict {
interpreter.Push(key)
interpreter.Push(value)
proc.Execute(interpreter)
}
}
// currentdict dict -> Return current dictionary
func currentdict(interpreter *Interpreter) {
interpreter.Push(interpreter.PeekDictionary())
}
// systemdict dict -> Return system dictionary
func systemdict(interpreter *Interpreter) {
interpreter.Push(interpreter.SystemDictionary())
}
// userdict dict -> Return writeable dictionary in local VM
func userdict(interpreter *Interpreter) {
interpreter.Push(interpreter.UserDictionary())
}
// globaldict dict -> Return writeable dictionary in global VM
func globaldict(interpreter *Interpreter) {
interpreter.Push(interpreter.UserDictionary())
}
// statusdict dict -> Return product-dependent dictionary
func statusdict(interpreter *Interpreter) {
interpreter.Push(interpreter.UserDictionary())
}
// countdictstack int -> Count elements on dictionary stack
func countdictstack(interpreter *Interpreter) {
interpreter.Push(float64(interpreter.DictionaryStackSize()))
}
//array dictstack subarray -> Copy dictionary stack into array
func dictstack(interpreter *Interpreter) {
panic("No yet implemenented")
}
// cleardictstack -> Pop all nonpermanent dictionaries off dictionary stack
func cleardictstack(interpreter *Interpreter) {
interpreter.ClearDictionaries()
}
func initDictionaryOperators(interpreter *Interpreter) {
interpreter.SystemDefine("dict", NewOperator(dict))
//interpreter.SystemDefine("length", NewOperator(length)) // already define in operators_conflict.go
interpreter.SystemDefine("maxlength", NewOperator(maxlength))
interpreter.SystemDefine("begin", NewOperator(begin))
interpreter.SystemDefine("end", NewOperator(end))
interpreter.SystemDefine("def", NewOperator(def))
interpreter.SystemDefine("load", NewOperator(load))
interpreter.SystemDefine("store", NewOperator(store))
//interpreter.SystemDefine("get", NewOperator(get)) // already define in operators_conflict.go
//interpreter.SystemDefine("put", NewOperator(put)) // already define in operators_conflict.go
interpreter.SystemDefine("undef", NewOperator(undef))
interpreter.SystemDefine("known", NewOperator(known))
interpreter.SystemDefine("where", NewOperator(where))
//interpreter.SystemDefine("copydict", NewOperator(copydict)) // already define in operators_conflict.go
//interpreter.SystemDefine("foralldict", NewOperator(foralldict)) // already define in operators_conflict.go
interpreter.SystemDefine("currentdict", NewOperator(currentdict))
interpreter.SystemDefine("systemdict", NewOperator(systemdict))
interpreter.SystemDefine("userdict", NewOperator(userdict))
interpreter.SystemDefine("globaldict", NewOperator(globaldict))
interpreter.SystemDefine("statusdict", NewOperator(statusdict))
interpreter.SystemDefine("countdictstack", NewOperator(countdictstack))
interpreter.SystemDefine("dictstack", NewOperator(dictstack))
interpreter.SystemDefine("cleardictstack", NewOperator(cleardictstack))
}

View file

@ -0,0 +1,482 @@
// 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))
}

View file

@ -0,0 +1,157 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
//Arithmetic and Math Operators
package postscript
import (
"math"
"rand"
)
// begin Primitive Operator implementation
//num1 num2 add sum -> Return num1 plus num2
func add(interpreter *Interpreter) {
num2 := interpreter.PopFloat()
num1 := interpreter.PopFloat()
interpreter.Push(num1 + num2)
}
//num1 num2 div quotient -> Return num1 divided by num2
func div(interpreter *Interpreter) {
num2 := interpreter.PopFloat()
num1 := interpreter.PopFloat()
interpreter.Push(num1 / num2)
}
//int1 int2 idiv quotient -> Return int1 divided by int2
func idiv(interpreter *Interpreter) {
int2 := interpreter.PopInt()
int1 := interpreter.PopInt()
interpreter.Push(float64(int1 / int2))
}
//int int mod remainder -> Return remainder after dividing int by int
func mod(interpreter *Interpreter) {
int2 := interpreter.PopInt()
int1 := interpreter.PopInt()
interpreter.Push(float64(int1 % int2))
}
//num1 num2 mul product -> Return num1 times num2
func mul(interpreter *Interpreter) {
num2 := interpreter.PopFloat()
num1 := interpreter.PopFloat()
interpreter.Push(num1 * num2)
}
//num1 num2 sub difference -> Return num1 minus num2
func sub(interpreter *Interpreter) {
num2 := interpreter.PopFloat()
num1 := interpreter.PopFloat()
interpreter.Push(num1 - num2)
}
//num1 abs num2 -> Return absolute value of num1
func abs(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(math.Fabs(f))
}
//num1 neg num2 -> Return negative of num1
func neg(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(-f)
}
//num1 ceiling num2 -> Return ceiling of num1
func ceiling(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(float64(int(f + 1)))
}
//num1 floor num2 -> Return floor of num1
func floor(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(math.Floor(f))
}
//num1 round num2 -> Round num1 to nearest integer
func round(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(float64(int(f + 0.5)))
}
//num1 truncate num2 -> Remove fractional part of num1
func truncate(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(float64(int(f)))
}
//num sqrt real -> Return square root of num
func sqrt(interpreter *Interpreter) {
f := interpreter.PopFloat()
interpreter.Push(float64(math.Sqrt(f)))
}
//num den atan angle -> Return arctangent of num/den in degrees
func atan(interpreter *Interpreter) {
den := interpreter.PopFloat()
num := interpreter.PopFloat()
interpreter.Push(math.Atan2(num, den) * (180.0 / math.Pi))
}
//angle cos real -> Return cosine of angle degrees
func cos(interpreter *Interpreter) {
a := interpreter.PopFloat() * math.Pi / 180
interpreter.Push(math.Cos(a))
}
//angle sin real -> Return sine of angle degrees
func sin(interpreter *Interpreter) {
a := interpreter.PopFloat() * math.Pi / 180
interpreter.Push(math.Sin(a))
}
//base exponent exp real -> Raise base to exponent power
func exp(interpreter *Interpreter) {
exponent := interpreter.PopFloat()
base := interpreter.PopFloat()
interpreter.Push(math.Pow(base, exponent))
}
//num ln real -> Return natural logarithm (base e)
func ln(interpreter *Interpreter) {
num := interpreter.PopFloat()
interpreter.Push(math.Log(num))
}
//num log real -> Return common logarithm (base 10)
func log10(interpreter *Interpreter) {
num := interpreter.PopFloat()
interpreter.Push(math.Log10(num))
}
// rand int Generate pseudo-random integer
func randInt(interpreter *Interpreter) {
interpreter.Push(float64(rand.Int()))
}
var randGenerator *rand.Rand
//int srand -> Set random number seed
func srand(interpreter *Interpreter) {
randGenerator = rand.New(rand.NewSource(int64(interpreter.PopInt())))
}
// rrand int -> Return random number seed
func rrand(interpreter *Interpreter) {
interpreter.Push(float64(randGenerator.Int()))
}
func initMathOperators(interpreter *Interpreter) {
interpreter.SystemDefine("add", NewOperator(add))
interpreter.SystemDefine("div", NewOperator(div))
interpreter.SystemDefine("idiv", NewOperator(idiv))
interpreter.SystemDefine("mod", NewOperator(mod))
interpreter.SystemDefine("mul", NewOperator(mul))
interpreter.SystemDefine("sub", NewOperator(sub))
interpreter.SystemDefine("abs", NewOperator(abs))
interpreter.SystemDefine("neg", NewOperator(neg))
interpreter.SystemDefine("ceiling", NewOperator(ceiling))
interpreter.SystemDefine("floor", NewOperator(floor))
interpreter.SystemDefine("round", NewOperator(round))
interpreter.SystemDefine("truncate", NewOperator(truncate))
interpreter.SystemDefine("sqrt", NewOperator(sqrt))
interpreter.SystemDefine("atan", NewOperator(atan))
interpreter.SystemDefine("cos", NewOperator(cos))
interpreter.SystemDefine("sin", NewOperator(sin))
interpreter.SystemDefine("exp", NewOperator(exp))
interpreter.SystemDefine("ln", NewOperator(ln))
interpreter.SystemDefine("log", NewOperator(log10))
interpreter.SystemDefine("rand", NewOperator(randInt))
interpreter.SystemDefine("srand", NewOperator(srand))
interpreter.SystemDefine("rrand", NewOperator(rrand))
}

View file

@ -0,0 +1,42 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
// Miscellaneous Operators
package postscript
import (
"log"
)
//proc bind proc Replace operator names in proc with operators; perform idiom recognition
func bind(interpreter *Interpreter) {
pdef := interpreter.PopProcedureDefinition()
values := make([]Value, len(pdef.Values))
for i, value := range pdef.Values {
if s, ok := value.(string); ok {
firstChar := s[0]
if firstChar != '(' && firstChar != '/' {
v, _ := interpreter.FindValueInDictionaries(s)
operator, isOperator := v.(Operator)
if v == nil {
log.Printf("Can't find def: %s\n", s)
}
if isOperator {
values[i] = operator
} else {
values[i] = value
}
} else {
values[i] = value
}
} else {
values[i] = value
}
}
pdef.Values = values
interpreter.Push(pdef)
}
func initMiscellaneousOperators(interpreter *Interpreter) {
interpreter.SystemDefine("bind", NewOperator(bind))
}

View file

@ -0,0 +1,41 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
func eq(interpreter *Interpreter) {
value1 := interpreter.Pop()
value2 := interpreter.Pop()
interpreter.Push(value1 == value2)
}
func ne(interpreter *Interpreter) {
value1 := interpreter.Pop()
value2 := interpreter.Pop()
interpreter.Push(value1 != value2)
}
func not(interpreter *Interpreter) {
b := interpreter.PopBoolean()
interpreter.Push(!b)
}
func lt(interpreter *Interpreter) {
f2 := interpreter.PopFloat()
f1 := interpreter.PopFloat()
interpreter.Push(f1 < f2)
}
func gt(interpreter *Interpreter) {
f2 := interpreter.PopFloat()
f1 := interpreter.PopFloat()
interpreter.Push(f1 > f2)
}
func initRelationalOperators(interpreter *Interpreter) {
interpreter.SystemDefine("eq", NewOperator(eq))
interpreter.SystemDefine("ne", NewOperator(ne))
interpreter.SystemDefine("not", NewOperator(not))
interpreter.SystemDefine("lt", NewOperator(lt))
interpreter.SystemDefine("gt", NewOperator(gt))
}

View file

@ -0,0 +1,88 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
//Operand Stack Manipulation Operators
package postscript
//any pop -> Discard top element
func pop(interpreter *Interpreter) {
interpreter.Pop()
}
//any1 any2 exch any2 any1 -> Exchange top two elements
func exch(interpreter *Interpreter) {
value1 := interpreter.Pop()
value2 := interpreter.Pop()
interpreter.Push(value1)
interpreter.Push(value2)
}
//any dup any any -> Duplicate top element
func dup(interpreter *Interpreter) {
interpreter.Push(interpreter.Peek())
}
//any1 … anyn n copy any1 … anyn any1 … anyn -> Duplicate top n elements
func copystack(interpreter *Interpreter) {
n := interpreter.PopInt()
values := interpreter.GetValues(n)
for _, value := range values {
interpreter.Push(value)
}
}
//anyn … any0 n index anyn … any0 anyn -> Duplicate arbitrary element
func index(interpreter *Interpreter) {
f := interpreter.PopInt()
interpreter.Push(interpreter.Get(int(f)))
}
//anyn1 … any0 n j roll any(j1) mod n … any0 anyn1 … anyj mod n -> Roll n elements up j times
func roll(interpreter *Interpreter) {
j := interpreter.PopInt()
n := interpreter.PopInt()
values := interpreter.PopValues(n)
j %= n
for i := 0; i < n; i++ {
interpreter.Push(values[(n+i-j)%n])
}
}
//any1 … anyn clear -> Discard all elements
func clear(interpreter *Interpreter) {
interpreter.ClearOperands()
}
//any1 … anyn count any1 … anyn n -> Count elements on stack
func count(interpreter *Interpreter) {
interpreter.Push(interpreter.OperandSize())
}
//Mark
type Mark struct{}
// mark mark -> Push mark on stack
func mark(interpreter *Interpreter) {
interpreter.Push(Mark{})
}
//mark obj 1 … obj n cleartomark -> Discard elements down through mark
func cleartomark(interpreter *Interpreter) {
value := interpreter.Pop()
for _, ok := value.(Mark); !ok; {
value = interpreter.Pop()
}
}
//mark obj 1 … obj n counttomark mark obj 1 … obj n n -> Count elements down to mark
func counttomark(interpreter *Interpreter) {
i := 0
value := interpreter.Get(i)
for _, ok := value.(Mark); !ok; i++ {
value = interpreter.Get(i)
}
interpreter.Push(float64(i))
}
func initStackOperator(interpreter *Interpreter) {
interpreter.SystemDefine("pop", NewOperator(pop))
interpreter.SystemDefine("exch", NewOperator(exch))
interpreter.SystemDefine("dup", NewOperator(dup))
interpreter.SystemDefine("index", NewOperator(index))
interpreter.SystemDefine("roll", NewOperator(roll))
interpreter.SystemDefine("clear", NewOperator(clear))
interpreter.SystemDefine("count", NewOperator(count))
interpreter.SystemDefine("mark", NewOperator(mark))
interpreter.SystemDefine("cleartomark", NewOperator(mark))
interpreter.SystemDefine("counttomark", NewOperator(mark))
}

46
postscript/procedure.go Normal file
View file

@ -0,0 +1,46 @@
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff
package postscript
type ProcedureDefinition struct {
Values []Value
}
func NewProcedureDefinition() *ProcedureDefinition {
proceduredef := new(ProcedureDefinition)
proceduredef.Values = make([]Value, 0, 100)
return proceduredef
}
func (p *ProcedureDefinition) Add(value Value) {
p.Values = append(p.Values, value)
}
type Procedure struct {
def *ProcedureDefinition
}
func NewProcedure(def *ProcedureDefinition) *Procedure {
return &Procedure{def}
}
func (p *Procedure) Execute(interpreter *Interpreter) {
for _, value := range p.def.Values {
if s, ok := value.(string); ok {
firstChar := s[0]
if firstChar != '(' && firstChar != '/' {
interpreter.computeReference(s)
} else {
interpreter.Push(value)
}
} else {
operator, isOperator := value.(Operator)
if isOperator {
operator.Execute(interpreter)
} else {
interpreter.Push(value)
}
}
}
}

602
postscript/scanner.go Normal file
View file

@ -0,0 +1,602 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// postscript scanner derived form the scanner package of go sources
package postscript
import (
"bytes"
"fmt"
"io"
"os"
"unicode"
"utf8"
)
// A source position is represented by a Position value.
// A position is valid if Line > 0.
type Position struct {
Filename string // filename, if any
Offset int // byte offset, starting at 0
Line int // line number, starting at 1
Column int // column number, starting at 0 (character count per line)
}
// IsValid returns true if the position is valid.
func (pos *Position) IsValid() bool { return pos.Line > 0 }
func (pos Position) String() string {
s := pos.Filename
if pos.IsValid() {
if s != "" {
s += ":"
}
s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
}
if s == "" {
s = "???"
}
return s
}
// Predefined mode bits to control recognition of tokens. For instance,
// to configure a Scanner such that it only recognizes (Go) identifiers,
// integers, and skips comments, set the Scanner's Mode field to:
//
// ScanIdents | ScanInts | SkipComments
//
const (
ScanIdents = 1 << -Ident
ScanInts = 1 << -Int
ScanFloats = 1 << -Float // includes Ints
ScanChars = 1 << -Char
ScanStrings = 1 << -String
ScanRawStrings = 1 << -RawString
ScanComments = 1 << -Comment
SkipComments = 1 << -skipComment // if set with ScanComments, comments become white space
GoTokens = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
)
// The result of Scan is one of the following tokens or a Unicode character.
const (
EOF = -(iota + 1)
Ident
Int
Float
Char
String
RawString
Comment
skipComment
)
var tokenString = map[int]string{
EOF: "EOF",
Ident: "Ident",
Int: "Int",
Float: "Float",
Char: "Char",
String: "String",
RawString: "RawString",
Comment: "Comment",
}
// TokenString returns a (visible) string for a token or Unicode character.
func TokenString(tok int) string {
if s, found := tokenString[tok]; found {
return s
}
return fmt.Sprintf("U+%04X", tok)
}
// GoWhitespace is the default value for the Scanner's Whitespace field.
// Its value selects Go's white space characters.
const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
const bufLen = 1024 // at least utf8.UTFMax
// A Scanner implements reading of Unicode characters and tokens from an io.Reader.
type Scanner struct {
// Input
src io.Reader
// Source buffer
srcBuf [bufLen + 1]byte // +1 for sentinel for common case of s.next()
srcPos int // reading position (srcBuf index)
srcEnd int // source end (srcBuf index)
// Source position
srcBufOffset int // byte offset of srcBuf[0] in source
line int // newline count + 1
column int // character count on line
// Token text buffer
// Typically, token text is stored completely in srcBuf, but in general
// the token text's head may be buffered in tokBuf while the token text's
// tail is stored in srcBuf.
tokBuf bytes.Buffer // token text head that is not in srcBuf anymore
tokPos int // token text tail position (srcBuf index)
tokEnd int // token text tail end (srcBuf index)
// One character look-ahead
ch int // character before current srcPos
// Error is called for each error encountered. If no Error
// function is set, the error is reported to os.Stderr.
Error func(s *Scanner, msg string)
// ErrorCount is incremented by one for each error encountered.
ErrorCount int
// The Mode field controls which tokens are recognized. For instance,
// to recognize Ints, set the ScanInts bit in Mode. The field may be
// changed at any time.
Mode uint
// The Whitespace field controls which characters are recognized
// as white space. To recognize a character ch <= ' ' as white space,
// set the ch'th bit in Whitespace (the Scanner's behavior is undefined
// for values ch > ' '). The field may be changed at any time.
Whitespace uint64
// Current token position. The Offset, Line, and Column fields
// are set by Scan(); the Filename field is left untouched by the
// Scanner.
Position
}
// Init initializes a Scanner with a new source and returns itself.
// Error is set to nil, ErrorCount is set to 0, Mode is set to GoTokens,
// and Whitespace is set to GoWhitespace.
func (s *Scanner) Init(src io.Reader) *Scanner {
s.src = src
// initialize source buffer
s.srcBuf[0] = utf8.RuneSelf // sentinel
s.srcPos = 0
s.srcEnd = 0
// initialize source position
s.srcBufOffset = 0
s.line = 1
s.column = 0
// initialize token text buffer
s.tokPos = -1
// initialize one character look-ahead
s.ch = s.next()
// initialize public fields
s.Error = nil
s.ErrorCount = 0
s.Mode = GoTokens
s.Whitespace = GoWhitespace
return s
}
// next reads and returns the next Unicode character. It is designed such
// that only a minimal amount of work needs to be done in the common ASCII
// case (one test to check for both ASCII and end-of-buffer, and one test
// to check for newlines).
func (s *Scanner) next() int {
ch := int(s.srcBuf[s.srcPos])
if ch >= utf8.RuneSelf {
// uncommon case: not ASCII or not enough bytes
for s.srcPos+utf8.UTFMax > s.srcEnd && !utf8.FullRune(s.srcBuf[s.srcPos:s.srcEnd]) {
// not enough bytes: read some more, but first
// save away token text if any
if s.tokPos >= 0 {
s.tokBuf.Write(s.srcBuf[s.tokPos:s.srcPos])
s.tokPos = 0
}
// move unread bytes to beginning of buffer
copy(s.srcBuf[0:], s.srcBuf[s.srcPos:s.srcEnd])
s.srcBufOffset += s.srcPos
// read more bytes
i := s.srcEnd - s.srcPos
n, err := s.src.Read(s.srcBuf[i:bufLen])
s.srcEnd = i + n
s.srcPos = 0
s.srcBuf[s.srcEnd] = utf8.RuneSelf // sentinel
if err != nil {
if s.srcEnd == 0 {
return EOF
}
if err != os.EOF {
s.error(err.String())
break
}
}
}
// at least one byte
ch = int(s.srcBuf[s.srcPos])
if ch >= utf8.RuneSelf {
// uncommon case: not ASCII
var width int
ch, width = utf8.DecodeRune(s.srcBuf[s.srcPos:s.srcEnd])
if ch == utf8.RuneError && width == 1 {
s.error("illegal UTF-8 encoding")
}
s.srcPos += width - 1
}
}
s.srcPos++
s.column++
switch ch {
case 0:
// implementation restriction for compatibility with other tools
s.error("illegal character NUL")
case '\n':
s.line++
s.column = 0
}
return ch
}
// Next reads and returns the next Unicode character.
// It returns EOF at the end of the source. It reports
// a read error by calling s.Error, if set, or else
// prints an error message to os.Stderr. Next does not
// update the Scanner's Position field; use Pos() to
// get the current position.
func (s *Scanner) Next() int {
s.tokPos = -1 // don't collect token text
ch := s.ch
s.ch = s.next()
return ch
}
// Peek returns the next Unicode character in the source without advancing
// the scanner. It returns EOF if the scanner's position is at the last
// character of the source.
func (s *Scanner) Peek() int {
return s.ch
}
func (s *Scanner) error(msg string) {
s.ErrorCount++
if s.Error != nil {
s.Error(s, msg)
return
}
fmt.Fprintf(os.Stderr, "%s: %s", s.Position, msg)
}
func (s *Scanner) scanIdentifier() int {
ch := s.next() // read character after first '_' or letter
for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '.' || ch == '-' || ch == '`' {
ch = s.next()
}
return ch
}
func digitVal(ch int) int {
switch {
case '0' <= ch && ch <= '9':
return ch - '0'
case 'a' <= ch && ch <= 'f':
return ch - 'a' + 10
case 'A' <= ch && ch <= 'F':
return ch - 'A' + 10
}
return 16 // larger than any legal digit val
}
func isDecimal(ch int) bool { return '0' <= ch && ch <= '9' }
func (s *Scanner) scanMantissa(ch int) int {
for isDecimal(ch) {
ch = s.next()
}
return ch
}
func (s *Scanner) scanFraction(ch int) int {
if ch == '.' {
ch = s.scanMantissa(s.next())
}
return ch
}
func (s *Scanner) scanExponent(ch int) int {
if ch == 'e' || ch == 'E' {
ch = s.next()
if ch == '-' || ch == '+' {
ch = s.next()
}
ch = s.scanMantissa(ch)
}
return ch
}
func (s *Scanner) scanNumber(ch int) (int, int) {
// isDecimal(ch)
if ch == '0' {
// int or float
ch = s.next()
if ch == 'x' || ch == 'X' {
// hexadecimal int
ch = s.next()
for digitVal(ch) < 16 {
ch = s.next()
}
} else {
// octal int or float
seenDecimalDigit := false
for isDecimal(ch) {
if ch > '7' {
seenDecimalDigit = true
}
ch = s.next()
}
if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
// float
ch = s.scanFraction(ch)
ch = s.scanExponent(ch)
return Float, ch
}
// octal int
if seenDecimalDigit {
s.error("illegal octal number")
}
}
return Int, ch
}
// decimal int or float
ch = s.scanMantissa(ch)
if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
// float
ch = s.scanFraction(ch)
ch = s.scanExponent(ch)
return Float, ch
}
return Int, ch
}
func (s *Scanner) scanDigits(ch, base, n int) int {
for n > 0 && digitVal(ch) < base {
ch = s.next()
n--
}
if n > 0 {
s.error("illegal char escape")
}
return ch
}
func (s *Scanner) scanEscape(quote int) int {
ch := s.next() // read character after '/'
switch ch {
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
// nothing to do
ch = s.next()
case '0', '1', '2', '3', '4', '5', '6', '7':
ch = s.scanDigits(ch, 8, 3)
case 'x':
ch = s.scanDigits(s.next(), 16, 2)
case 'u':
ch = s.scanDigits(s.next(), 16, 4)
case 'U':
ch = s.scanDigits(s.next(), 16, 8)
default:
s.error("illegal char escape")
}
return ch
}
func (s *Scanner) scanString(quote int) (n int) {
ch := s.next() // read character after quote
for ch != quote {
if ch == '\n' || ch < 0 {
s.error("literal not terminated")
return
}
if ch == '\\' {
ch = s.scanEscape(quote)
} else {
ch = s.next()
}
n++
}
return
}
func (s *Scanner) scanRawString() {
ch := s.next() // read character after '`'
for ch != '`' {
if ch < 0 {
s.error("literal not terminated")
return
}
ch = s.next()
}
}
func (s *Scanner) scanLineComment() {
ch := s.next() // read character after "//"
for ch != '\n' {
if ch < 0 {
s.error("comment not terminated")
return
}
ch = s.next()
}
}
func (s *Scanner) scanComment(ch int) {
s.scanLineComment()
}
// Scan reads the next token or Unicode character from source and returns it.
// It only recognizes tokens t for which the respective Mode bit (1<<-t) is set.
// It returns EOF at the end of the source. It reports scanner errors (read and
// token errors) by calling s.Error, if set; otherwise it prints an error message
// to os.Stderr.
func (s *Scanner) Scan() int {
ch := s.ch
// reset token text position
s.tokPos = -1
redo:
// skip white space
for s.Whitespace&(1<<uint(ch)) != 0 {
ch = s.next()
}
// start collecting token text
s.tokBuf.Reset()
s.tokPos = s.srcPos - 1
// set token position
s.Offset = s.srcBufOffset + s.tokPos
s.Line = s.line
s.Column = s.column
// determine token value
tok := ch
switch {
case unicode.IsLetter(ch) || ch == '_' || ch == '`':
if s.Mode&ScanIdents != 0 {
tok = Ident
ch = s.scanIdentifier()
} else {
ch = s.next()
}
case ch == '-': // minus
ch = s.next()
if !isDecimal(ch) {
s.error(fmt.Sprintf("Error may be a digi: %c\n", ch))
} else {
if s.Mode&(ScanInts|ScanFloats) != 0 {
tok, ch = s.scanNumber(ch)
} else {
ch = s.next()
}
}
case isDecimal(ch):
if s.Mode&(ScanInts|ScanFloats) != 0 {
tok, ch = s.scanNumber(ch)
} else {
ch = s.next()
}
default:
switch ch {
case '(':
if s.Mode&ScanStrings != 0 {
s.scanString(')')
tok = String
}
ch = s.next()
case '.':
ch = s.next()
if isDecimal(ch) && s.Mode&ScanFloats != 0 {
tok = Float
ch = s.scanMantissa(ch)
ch = s.scanExponent(ch)
}
case '%':
ch = s.next()
if s.Mode&ScanComments != 0 {
if s.Mode&SkipComments != 0 {
s.tokPos = -1 // don't collect token text
s.scanComment(ch)
ch = s.next()
goto redo
}
s.scanComment(ch)
tok = Comment
ch = s.next()
}
case '`':
if s.Mode&ScanRawStrings != 0 {
s.scanRawString()
tok = String
}
ch = s.next()
default:
ch = s.next()
}
}
// end of token text
s.tokEnd = s.srcPos - 1
s.ch = ch
return tok
}
// Position returns the current source position. If called before Next()
// or Scan(), it returns the position of the next Unicode character or token
// returned by these functions. If called afterwards, it returns the position
// immediately after the last character of the most recent token or character
// scanned.
func (s *Scanner) Pos() Position {
return Position{
s.Filename,
s.srcBufOffset + s.srcPos - 1,
s.line,
s.column,
}
}
// TokenText returns the string corresponding to the most recently scanned token.
// Valid after calling Scan().
func (s *Scanner) TokenText() string {
if s.tokPos < 0 {
// no token text
return ""
}
if s.tokEnd < 0 {
// if EOF was reached, s.tokEnd is set to -1 (s.srcPos == 0)
s.tokEnd = s.tokPos
}
if s.tokBuf.Len() == 0 {
// common case: the entire token text is still in srcBuf
return string(s.srcBuf[s.tokPos:s.tokEnd])
}
// part of the token text was saved in tokBuf: save the rest in
// tokBuf as well and return its content
s.tokBuf.Write(s.srcBuf[s.tokPos:s.tokEnd])
s.tokPos = s.tokEnd // ensure idempotency of TokenText() call
return s.tokBuf.String()
}

42
resource/font/COPYING Normal file
View file

@ -0,0 +1,42 @@
Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font
instruction code copyright (c) 2001 by URW++ GmbH. All Rights
Reserved. Luxi is a registered trademark of Bigelow & Holmes Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of these Fonts and associated documentation files (the "Font
Software"), to deal in the Font Software, including without
limitation the rights to use, copy, merge, publish, distribute,
sublicense, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to
the following conditions:
The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software.
The Font Software may not be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may not
be modified nor may additional glyphs or characters be added to the
Fonts. This License becomes null and void when the Fonts or Font
Software have been modified.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
BIGELOW & HOLMES INC. OR URW++ GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT,
INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT
SOFTWARE.
Except as contained in this notice, the names of Bigelow & Holmes
Inc. and URW++ GmbH. shall not be used in advertising or otherwise to
promote the sale, use or other dealings in this Font Software without
prior written authorization from Bigelow & Holmes Inc. and URW++ GmbH.
For further information, contact:
info@urwpp.de
or
design@bigelowandholmes.com

24
resource/font/README Normal file
View file

@ -0,0 +1,24 @@
All questions regarding this software should be directed at the
Xorg mailing list:
http://lists.freedesktop.org/mailman/listinfo/xorg
Please submit bug reports to the Xorg bugzilla:
https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
The master development code repository can be found at:
git://anongit.freedesktop.org/git/xorg/font/bh-ttf
http://cgit.freedesktop.org/xorg/font/bh-ttf
For patch submission instructions, see:
http://www.x.org/wiki/Development/Documentation/SubmittingPatches
For more information on the git code manager, see:
http://wiki.x.org/wiki/GitPage

BIN
resource/font/luximb.ttf Normal file

Binary file not shown.

BIN
resource/font/luximbi.ttf Normal file

Binary file not shown.

BIN
resource/font/luximr.ttf Normal file

Binary file not shown.

BIN
resource/font/luximri.ttf Normal file

Binary file not shown.

BIN
resource/font/luxirb.ttf Normal file

Binary file not shown.

BIN
resource/font/luxirbi.ttf Normal file

Binary file not shown.

BIN
resource/font/luxirr.ttf Normal file

Binary file not shown.

BIN
resource/font/luxirri.ttf Normal file

Binary file not shown.

BIN
resource/font/luxisb.ttf Normal file

Binary file not shown.

BIN
resource/font/luxisbi.ttf Normal file

Binary file not shown.

BIN
resource/font/luxisr.ttf Normal file

Binary file not shown.

BIN
resource/font/luxisri.ttf Normal file

Binary file not shown.

18
resource/image/Tests.html Normal file
View file

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
canvas { border: 1px solid black; }
</style>
<title>Canvas tutorial</title>
<script type="text/javascript" src="test.js">
</script>
</head>
<body onload="executeTests()">
<p>TestStar</p>
<canvas id="TestStar" width="400" height="400"></canvas>
<p>TestTransform</p>
<canvas id="TestTransform" width="400" height="400"></canvas>
<canvas id="TestFillRect" width="300" height="300"></canvas>
</body>
</html>

64
resource/image/Tests.ps Normal file
View file

@ -0,0 +1,64 @@
%!
% Example of rotation... draws 36 lines in a circular pattern
0 10 360 { % Go from 0 to 360 degrees in 10 degree steps
newpath % Start a new path
gsave % Keep rotations temporary
144 144 moveto
rotate % Rotate by degrees on stack from 'for'
72 0 rlineto
stroke
grestore % Get back the unrotated state
} for % Iterate over angles
showpage
/box {
newpath
moveto
72 0 rlineto
0 72 rlineto
-72 0 rlineto
closepath
} def
% Specify font for text labels
/Helvetica findfont 40 scalefont setfont
gsave
40 40 translate % Set origin to (40, 40)
0 0 box stroke % Draw box at new origin...
77 0 moveto
(Translated) show % and label
grestore
gsave
100 150 translate % Translate origin to (100, 150)
30 rotate % Rotate counter-clockwise by 30 degrees
0 0 box stroke % Draw box...
75 0 moveto
(Translated & Rotated) show % and label
grestore
gsave
40 300 translate % Translate to (40, 300)
0.5 1 scale % Reduce x coord by 1/2, y coord left alone
0 0 box stroke % Draw box...
75 0 moveto
(Translated & Squished) show % and label
grestore
gsave
100 450 translate % Set origin to (300, 300)
45 rotate % Rotate coordinates by 45 degrees
0.5 1 scale % Scale coordinates
0 0 box stroke % Draw box
75 0 moveto
(Everything) show
grestore
showpage

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

103
resource/image/test.js Normal file
View file

@ -0,0 +1,103 @@
function toDegree(radians) {
return radians * 180 / Math.PI;
}
function toRadians(degree) {
return degree * Math.PI / 180;
}
function draw(test){
var canvas = document.getElementById(test.name);
if (canvas.getContext){
var gc = canvas.getContext('2d');
test(gc)
}
}
function executeTests() {
draw(TestStar)
draw(TestTransform)
draw(TestFillRect)
}
function TestStar(gc) {
for(i = 0.0 ; i < 360; i = i + 10) {// Go from 0 to 360 degrees in 10 degree steps
gc.beginPath() // Start a new path
gc.save() // Keep rotations temporary
gc.translate(144, 144)
gc.rotate(i * (Math.PI / 180.0)) // Rotate by degrees on stack from 'for'
gc.moveTo(0, 0)
gc.lineTo(72, 0)
gc.stroke()
gc.restore() // Get back the unrotated state
}
}
function TestTransform(gc) {
gc.save()
gc.translate(40, 40) // Set origin to (40, 40)
gc.beginPath()
gc.moveTo(0,0)
gc.lineTo(72,0)
gc.lineTo(72, 72)
gc.lineTo(0, 72)
gc.closePath()
gc.stroke()
gc.restore()
gc.save()
gc.translate(100, 150) // Translate origin to (100, 150)
gc.rotate(30* (Math.PI / 180.0)) // Rotate counter-clockwise by 30 degrees
gc.beginPath()
gc.moveTo(0,0)
gc.lineTo(72,0)
gc.lineTo(72, 72)
gc.lineTo(0, 72)
gc.closePath() // Draw box...
gc.stroke()
gc.restore()
gc.save()
gc.translate(40, 300) // Translate to (40, 300)
gc.scale(0.5, 1) // Reduce x coord by 1/2, y coord left alone
gc.beginPath()
gc.moveTo(0,0)
gc.lineTo(72,0)
gc.lineTo(72, 72)
gc.lineTo(0, 72)
gc.closePath() // Draw box...
gc.stroke()
gc.restore()
gc.save()
gc.translate(300, 300) // Set origin to (300, 300)
gc.rotate(45* (Math.PI / 180.0)) // Rotate coordinates by 45 degrees
gc.scale(0.5, 1) // Scale coordinates
gc.beginPath()
gc.moveTo(0,0)
gc.lineTo(72,0)
gc.lineTo(72, 72)
gc.lineTo(0, 72)
gc.closePath() // Draw box
gc.stroke()
gc.restore()
}
function TestFillRect(gc) {
gc.moveTo(95,95)
gc.lineTo(195,95)
gc.lineTo(195, 195)
gc.lineTo(95, 195)
gc.lineTo(95, 95)
gc.moveTo(105,105)
gc.lineTo(105, 205)
gc.lineTo(205, 205)
gc.lineTo(205,105)
gc.lineTo(105, 105)
gc.fill()
}

View file

@ -0,0 +1,57 @@
%!PS
/B {bind} bind def
/D {def} def
/Q {bind def} B D
/E {exch def} Q
/S {gsave} Q
/R {grestore} Q
/P 20 D
/N P 1 sub D
/I 1 P div D
initclip clippath pathbbox newpath
72 sub /URy E 72 sub /URx E 72 add /LLy E 72 add /LLx E
/Sq5 5 sqrt D
/F 2 Sq5 add D
/Wx URx LLx sub D /Wy URy LLy sub D
/Xx Wx 4 div D /Xy Wy F div D /X Xx Xy le {Xx}{Xy}ifelse D
Wx X 4 mul sub 2 div LLx add X 2 mul add Wy X F mul sub 2 div LLy add translate
/X X Sq5 mul D
X dup scale
0.1 X div setlinewidth
S
[ 1 .5 0 1 0 0 ] concat
0 1 N {I mul /A E
0 1 N {I mul /B E
S A B translate
newpath 0 0 moveto I 0 rlineto 0 I rlineto I neg 0 rlineto
closepath
S I B add 1 1 A sub setrgbcolor fill R stroke % Green
R
} for
} for
R
S
[ -1 .5 0 1 0 0 ] concat
0 1 N {I mul /A E
0 1 N {I mul /B E
S A B translate
newpath 0 0 moveto I 0 rlineto 0 I rlineto I neg 0 rlineto
closepath
S I B add 1 A sub 1 setrgbcolor fill R stroke % Blue
R
} for
} for
R
S
[ 1 .5 -1 0.5 0 1 ] concat
0 1 N {I mul /A E
0 1 N {I mul /B E
S A B translate
newpath 0 0 moveto I 0 rlineto 0 I rlineto I neg 0 rlineto
closepath
S 1 1 B sub 1 A sub setrgbcolor fill R stroke % Red
R
} for
} for
R
showpage

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
%%% Start of L-system definition
/STARTK { FK plusK plusK FK plusK plusK FK} def
/FK {
dup 0 eq
{ DK } % if the recursion order ends, draw forward
{
1 sub % recurse
4 {dup} repeat % dup the number of parameters (order) needed.
FK minusK FK plusK plusK FK minusK FK }
ifelse
pop % pop the dup'd order
} bind def
/angleK 60 def
/minusK { % rotation to the right
angleK neg rotate
} bind def
/plusK { % rotation to the left
angleK rotate
} bind def
%%% End of L-System definition
/DK { sizeK 3 orderK exp div 0 rlineto } bind def
/thicknessK {1 orderK dup mul div} bind def
%%% Scaling factors
/orderK 3 def
/sizeK 300 def
%%% Draws a Koch's snowflake of radius 180 at 0 0
/Koch180 {
gsave
newpath
thicknessK setlinewidth
200 300 60 cos mul add
neg
200 100 60 sin mul add
neg
translate
200 200 moveto
orderK orderK orderK STARTK
stroke
closepath
grestore
} def % receives nothing
%%% Draws an arbitrary Koch's snowflake
/Koch {
/orderK exch store
gsave
3 1 roll
translate
180 div dup scale
rand 360 mod rotate
Koch180
grestore
} def % Receives x y size order
%%% Sample, bounded by an arc
400 400 100 3 Koch
newpath
400 400
100 0 360 arc
stroke
closepath
showpage

View file

@ -0,0 +1,68 @@
%!PS-Adobe-2.0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Mandelbrot set via PostScript code. Not optimized %
% in any way. Centered in A4 paper. Escape time, B&W %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/fun {
4 3 roll % y c1 c2 x
dup dup % y c1 c2 x x x
mul % y c1 c2 x x^2
5 4 roll % c1 c2 x x^2 y
dup dup mul % c1 c2 x x^2 y y^2
2 index exch sub % c1 c2 x x^2 y (x^2-y^2)
6 1 roll 2 index % (x^2-y^2) c1 c2 x x^2 y x
2 mul mul % (x^2-y^2) c1 c2 x x^2 2xy
6 1 roll % 2xy (x^2-y^2) c1 c2 x x^2
pop pop 4 1 roll % c2 2xy (x^2-y^2) c1
dup 5 1 roll add % c1 c2 2xy (x^2-y^2+c1)
4 1 roll % (x^2-y^2+c1) c1 c2 2xy
1 index % (x^2-y^2+c1) c1 c2 2xy c2
add 4 3 roll % c1 c2 (2xy+c2) (x^2-y^2+c1)
exch 4 2 roll % (x^2-y^2+c1) (2xy+c2) c1 c2
} def
/res 500 def
/iter 50 def
300 300 translate
90 rotate
-150 -260 translate
0 1 res {
/x exch def
0 1 res {
/y exch def
0 0
-2.5 4 x mul res div add
2 4 y mul res div sub
iter -1 0 {
/n exch store
fun
2 index dup mul
4 index dup mul
add sqrt
4 gt
{exit} if
} for
pop pop pop pop
n 0 gt
{1 setgray
x y 0.7 0 360 arc
fill
}
{
0 setgray
x y 0.5 0 360 arc
fill
} ifelse
} for
}for
showpage

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,125 @@
%!
%/colorcirsave save def % prevent left over effects
gsave
/Times-Roman findfont 24 scalefont setfont
72 72 translate 0 0 moveto 1 0 0 setrgbcolor (Red) show
72 0 translate 0 0 moveto 0 1 0 setrgbcolor (Green) show
72 0 translate 0 0 moveto 0 0 1 setrgbcolor (Blue) show
72 0 translate 0 0 moveto 1 1 0 setrgbcolor (Yellow) show
72 0 translate 0 0 moveto 1 0 1 setrgbcolor (Pink) show
72 0 translate 0 0 moveto 0 1 1 setrgbcolor (Cyan) show
72 0 translate 0 0 moveto 0.9 0.9 0.9 setrgbcolor ('White') show
grestore
0.0 setlinewidth
/length 0.1 def
/width 0.02 def
/hsvcircle {
gsave
/h 0.0 def
0 4 360 {
pop
gsave
0.5 0.0 translate
newpath
0.0 0.0 moveto
length 0.0 lineto
length width lineto
0.0 width lineto
closepath
h 1.0 1.0 sethsbcolor
fill
%newpath
%0.0 0.0 moveto
%length 0.0 lineto
%length width lineto
%0.0 width lineto
%closepath
%0.0 setgray
%stroke
grestore
/h h 4 360 div add def
4 rotate
} for
grestore
} def
/graycircle {
gsave
/h -1.0 def
0 4 360 {
pop
gsave
0.5 0.0 translate
newpath
0.0 0.0 moveto
length 0.0 lineto
length width lineto
0.0 width lineto
closepath
h abs setgray
fill
%newpath
%0.0 0.0 moveto
%length 0.0 lineto
%length width lineto
%0.0 width lineto
%closepath
%0.0 setgray
%stroke
grestore
/h h 8 360 div add def
4 rotate
} for
grestore
} def
0.0 setlinewidth
0.0 setgray
300 400 translate
500 500 scale
30 rotate
1.0 0.7 scale
-30 rotate
hsvcircle
0.8 0.8 scale
graycircle
0.8 0.8 scale
hsvcircle
0.8 0.8 scale
graycircle
0.8 0.8 scale
hsvcircle
0.8 0.8 scale
graycircle
0.8 0.8 scale
hsvcircle
0.8 0.8 scale
graycircle
0.8 0.8 scale
hsvcircle
0.8 0.8 scale
graycircle
0.8 0.8 scale
hsvcircle
0.8 0.8 scale
graycircle
0.8 0.8 scale
hsvcircle
0.8 0.8 scale
graycircle
showpage
%clear cleardictstack
%colorcirsave restore

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,380 @@
%!
% If you're concerned that the cpu in your PostScript printer will atrophy
% from disuse, here is another Escher-like contribution to to keep it busy
% for a while. It uses PostScript color commands, but will still work on
% a monochrome printer (but isn't very pretty in black & white).
%
% The butterflies are arranged in a hexagonal grid (wallpaper group p6),
% and the moveto, lineto, curveto commands used to render the tesselation
% are redefined so as to impose a nonlinear transform that shrinks the
% infinite plane to an ellipse. This is a sleazy way to mimic Escher's
% "circle limit" sorts of things.
%
% The butterfly permimeter was made by imposing all the symmetry constraints
% on a path, and then that path was filled in using Adobe Illustrator
%
% The routines Xform and next_color are easy to change if you want to hack
% with them. The code was written to sacrifice efficiency for readability.
%
% Bob Wallis
%
% UUCP {sun,pyramid,cae780,apple}!weitek!wallis
%statusdict begin waittimeout 6000 lt % if you have a slow printer, you
% {0 60 6000 setdefaulttimeouts} % might need to uncomment this
%if end
/nlayers 1 def % 1 takes about 10 minutes on a LW+; 2 takes 4x longer
/warp 1 def % 1 -> ellipsoidal distortion; 0 -> flat Euclidean
/inch {72 mul} def
/x4 152 def /y4 205.6 def % 6 fold rotation center of bfly
/x12 387.20 def /y12 403.84 def % 3 fold center of bfly
/dx x4 x12 sub def % [dx,dy] = distance between the
/dy y4 y12 sub def % two fixed points above
/Dm dx dup mul dy dup mul % magnitude of basis vectors of
add sqrt 3 sqrt mul % parallelogram lattice
def % = |dx,dy| * sqrt(3)
/Da dy dx atan 30 add def
/D1x Dm Da cos mul def % [D1x, D1y] = basis vector vector #1
/D1y Dm Da sin mul def % = [Dm,0] exp(j30)
/Da dy dx atan 30 sub def
/D2x Dm Da cos mul def % [D2x, D2y] = basis vector vector #2
/D2y Dm Da sin mul def % = [Dm,0] exp(-j30)
/m { moveto} def
/L {lineto} def
/S {stroke} def
/c {curveto} def
/f {closepath fill} def
/F {closepath fill} def
/g { setgray} def
/FillStroke { % fill interior & stroke black border
closepath gsave fill grestore 0 setgray stroke
} def
%
% Description of 1 butterfly
%
/body {
314.96 280.19 m
383.4 261.71 445.11 243.23 513.52 224.68 c
463.68 256.59 490.26 328.83 446.99 360.76 c
423.71 347.32 397.08 339.7 367.07 337.9 c
388.93 358.28 414.14 372.84 442.73 381.58 c
426.68 398.18 394.07 389.7 387.2 403.84 c
371.52 404.96 362.56 372.48 340.16 366.88 c
346.88 396.01 346.88 425.12 340.16 454.24 c
326.72 427.35 320 400.48 320 373.6 c
270.71 352.1 221.44 411.23 168.88 384.02 c
189.04 388.03 202.48 380.4 212.57 366.95 c
216.72 350.85 209.23 341.46 190.1 338.79 c
177.34 343.57 167.94 354.17 161.9 370.59 c
176.06 305.52 132.02 274.05 152 205.6 c
201.29 257.12 250.56 234.72 299.84 279.52 c
288.64 266.08 284.16 252.64 286.4 239.2 c
298.27 223.97 310.15 222.18 322.02 233.82 c
328.62 249.28 328.51 264.74 314.96 280.19 c
FillStroke
} def
/eyes {
294.8125 238.3246 m
296.9115 238.3246 298.6132 242.7964 298.6132 248.3125 c
298.6132 253.8286 296.9115 258.3004 294.8125 258.3004 c
292.7135 258.3004 291.0118 253.8286 291.0118 248.3125 c
291.0118 242.7964 292.7135 238.3246 294.8125 238.3246 c
closepath gsave 1 g fill grestore 0 g S
319.5 241.1782 m
321.7455 241.1782 323.5659 245.4917 323.5659 250.8125 c
323.5659 256.1333 321.7455 260.4468 319.5 260.4468 c
317.2545 260.4468 315.4341 256.1333 315.4341 250.8125 c
315.4341 245.4917 317.2545 241.1782 319.5 241.1782 c
closepath gsave 1 g fill grestore 0 g S
0 g
296.875 242.0939 m
297.4608 242.0939 297.9356 243.479 297.9356 245.1875 c
297.9356 246.896 297.4608 248.2811 296.875 248.2811 c
296.2892 248.2811 295.8143 246.896 295.8143 245.1875 c
295.8143 243.479 296.2892 242.0939 296.875 242.0939 c
f
0 g
318.5 243.7707 m
319.281 243.7707 319.9142 245.0766 319.9142 246.6875 c
319.9142 248.2984 319.281 249.6043 318.5 249.6043 c
317.719 249.6043 317.0858 248.2984 317.0858 246.6875 c
317.0858 245.0766 317.719 243.7707 318.5 243.7707 c
f
} def
/stripes {
292 289 m
252 294 241 295 213 279 c
185 263 175 252 159 222 c
S
285 313 m
239 326 226 325 206 315 c
186 305 164 278 161 267 c
S
298 353 m
262 342 251 339 237 355 c
223 371 213 380 201 383 c
S
330 288 m
384 293 385 292 418 280 c
451 268 452 264 473 247 c
S
342 306 m
381 311 386 317 410 311 c
434 305 460 287 474 262 c
S
345 321 m
352 357 359 367 379 377 c
399 387 409 385 426 382 c
S
327.75 367.75 m
336.5 392.25 333.682 403.348 335.25 415.5 c
S
320 364.75 m
322 361.75 323.5 360.5 326.25 360 c
329 359.5 332 360.5 334 362.75 c
S
316.25 356.5 m
318.75 353.25 320 353 323.25 352.25 c
326.5 351.5 329 352 331.5 353.25 c
S
312.5 349 m
316.75 345.5 318.25 344.5 321.25 343.75 c
324.25 343 327 344 329.75 346 c
S
310.75 340.75 m
314.25 336.5 316.25 335.25 320 335.25 c
323.75 335.25 327 336.5 329.25 338 c
S
308.5 332 m
311.75 328.5 312.5 327.25 317 327 c
321.5 326.75 325.75 328.25 327.75 329.75 c
S
305 322 m
309.5 317.75 310.75 317 315 316.5 c
319.25 316 322.25 318 324.75 320 c
S
302.25 311 m
307 307.5 307.75 306.25 312.75 306 c
317.75 305.75 320 307.25 323.75 309.5 c
S
301.25 298.25 m
304.5 292.75 305.25 292 308.25 292 c
311.25 292 313.75 293.75 315.75 295.75 c
S
} def
/nostrils {
0 g
304.062 227.775 m
304.599 227.775 305.034 228.883 305.034 230.25 c
305.034 231.616 304.599 232.724 304.062 232.724 c
303.525 232.724 303.09 231.616 303.09 230.25 c
303.09 228.883 303.525 227.775 304.062 227.775 c
f
304.062 230.25 m
F
309.562 228.275 m
310.099 228.275 310.534 229.383 310.534 230.75 c
310.534 232.116 310.099 233.224 309.562 233.224 c
309.025 233.224 308.59 232.116 308.59 230.75 c
308.59 229.383 309.025 228.275 309.562 228.275 c
f
} def
/thorax
{
327.5 300 m
316.5 283 315.5 275.5 308 277.5 c
294 311.5 299 313.5 304 334 c
309 354.5 315.5 362 322.5 372 c
329.5 382 327.5 376.5 331 376 c
334.5 375.5 339.1367 379.1109 339 369 c
338.5 332 333.4999 324.5 330.5 311.5 c
0 g S
} def
/spots {
next_color
192 242.201 m
202.1535 242.201 210.3848 251.0655 210.3848 262 c
210.3848 272.9345 202.1535 281.799 192 281.799 c
181.8465 281.799 173.6152 272.9345 173.6152 262 c
173.6152 251.0655 181.8465 242.201 192 242.201 c
FillStroke
next_color
447.5 250.2365 m
459.6061 250.2365 469.4203 257.5181 469.4203 266.5 c
469.4203 275.4819 459.6061 282.7635 447.5 282.7635 c
435.3939 282.7635 425.5797 275.4819 425.5797 266.5 c
425.5797 257.5181 435.3939 250.2365 447.5 250.2365 c
FillStroke
next_color
401 369.1005 m
409.5914 369.1005 416.5563 373.5327 416.5563 379 c
416.5563 384.4673 409.5914 388.8995 401 388.8995 c
392.4086 388.8995 385.4436 384.4673 385.4436 379 c
385.4436 373.5327 392.4086 369.1005 401 369.1005 c
FillStroke
next_color
249 348.2721 m
261.4966 348.2721 271.6274 353.9707 271.6274 361 c
271.6274 368.0293 261.4966 373.7279 249 373.7279 c
236.5034 373.7279 226.3726 368.0293 226.3726 361 c
226.3726 353.9707 236.5034 348.2721 249 348.2721 c
FillStroke
} def
/ncolor 6 def
/cidx 0 def
/next_color {
cidx ncolor div % hue
.75 % saturation (change these if you like)
.8 % lightness
sethsbcolor
/cidx cidx 1 add ncolor mod def
} def
/cidx 0 def
/max_r2 % radius^2 for center of outermost ring of butterflies
Dm nlayers mul 1.05 mul dup mul
def
/max_radius max_r2 sqrt def
/max_radius_inv 1 max_radius div def
/Dm_inv 1 Dm div def
%
% Ellipsoidal distortion, maps "nlayers" concentric rings of cells into
% an ellipse centered on page
% D length of 1 basis vector separating hexagonal cells
% z0 center of 6-fold rotation = origin of shrink xform
% z' = (z - z0)/D new coord system
% |z'| = sqrt(x^2 + [(8.5/11)*y]^2) aspect ratio of paper
% z" = z' * a/M(|z'|) shrink by "a/M(|z|)" as fcn of radius
% At the max radius, we want the shrunk ellipse to be "W" units wide so it
% just fits our output format - solve for scale factor "a"
% zmax = n+0.5 for n layers of cells
% zmax * [a/M(zmax)] = W 1/2 width of output on paper
% a = M(zmax)*W/zmax solve for "a"
%/M{dup mul 1 add sqrt}bind def % M(u) = sqrt(1+|u|^2) = one possible shrink
/M { 1.5 add } bind def % M(u) = (1.5+|u|) = another possible one
/W 3.8 inch def % 1/2 width of ellipse
/zmax 0.5 nlayers add def % radius at last layer of hexagons
/a zmax M W mul zmax div def % a = M(zmax)*W/zmax
/Xform { % [x0,y0] = ctr ellipse
Matrix transform
/y exch def
/x exch def
/z x dup mul y .773 mul dup mul add sqrt def % ellipse radius
/Scale a z M div def % z=a/M(|z|)
x Scale mul x0 add % magnify back up
y Scale mul y0 add % [x0+x*s, y0+y*s]
} bind def
/Helvetica findfont 8 scalefont setfont
4.25 inch 0.5 inch moveto
(RHW) stringwidth pop -0.5 mul 0 rmoveto
(RHW) show % autograph
warp 1 eq { % redefine commands to use Xform
/moveto { Xform moveto} bind def
/lineto { Xform lineto} bind def
/curveto {
Xform 6 -2 roll
Xform 6 -2 roll
Xform 6 -2 roll
curveto
} bind def
}if
/bfly { % paint 1 butterfly
next_color body
1 setgray eyes
stripes
0 setgray nostrils
0.5 setgray thorax next_color
spots
} def
/x0 x4 def % center
/y0 y4 def
/T1matrix % xlate to center of image
x0 neg y0 neg matrix translate
def
/Smatrix % scale so that 1 basis vector = 1.0
Dm_inv dup matrix scale
def
/HexCell { % 6 butterflys rotated about center of
/cidx 0 def % 6 fold symmetry
/color 0 def
/T2matrix dx dy matrix translate def
0 60 300 {
/angle exch def
/Rmatrix angle matrix rotate def
/Matrix % translate, rotate, scale - used by Xform
T1matrix Rmatrix matrix concatmatrix
T2matrix matrix concatmatrix
Smatrix matrix concatmatrix
def
gsave
warp 0 eq % then may use usual PostScript machinery
{ % else using Xform
x0 y0 translate angle rotate
.5 dup scale
dx x0 sub dy y0 sub translate
} if
bfly
next_color
grestore
} for
} def
%320 x4 sub 240 y4 sub translate
4.25 inch x4 sub 5.5 inch y4 sub translate
0 setlinewidth
/N 2 def
N neg 1 N {
/i exch def % translate to
N neg 1 N { % i*D1 + j*D2
/j exch def % and draw HexCell
gsave
/dx i D1x mul j D2x mul add def % translate HexCell by
/dy i D1y mul j D2y mul add def % [dx,dy]
/r2 dx dup mul dy dup mul add def % r^2 = |dx,dy|^2
r2 max_r2 lt % inside radius?
{ % yes
1 r2 max_r2 div sub sqrt 2 div
setlinewidth % make skinnier lines
HexCell % 6 butterflies
}
if
grestore
} for
} for
showpage

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,917 @@
%!PS-Adobe-3.0 Resource-Form
%%Title: GRADE
%%DocumentFonts: (atend)
%%Creator: Proform III by Lytrod Software, Inc.
%%CreationDate: Mon Jun 29 14:17:21 1998
%%For: Version 4.00A Serial #012345
%%Pages: (atend)
%%BoundingBox (atend)
%%KDKAccentColor:
%%EndComments
%-----convenience definitions
/pxlk 1. def
/rd{.25 sub round .25 add}bind def
/tf{transform rd exch rd exch itransform}bind def
/m{pxlk .9 lt{moveto}{tf moveto}ifelse}bind def
/l{pxlk .9 lt{lineto}{tf lineto}ifelse}bind def
/gs{gsave}bind def
/gr{grestore}bind def
/sg{setgray}bind def
/sl{setlinewidth}bind def
/sj{setlinejoin}bind def
/sd{setdash}bind def
/np{newpath}bind def
/sk{stroke}bind def
/ep{closepath}bind def
/tr{pxlk .9 lt{translate}{tf translate}ifelse}bind def
/sc{scale}bind def
/sw{stringwidth}bind def
/rot{rotate}bind def
/tl{gs m show gr}bind def
/lrot{gs m exch rot show gr}bind def
/ssf{findfont exch makefont setfont}bind def
%-----end of standard definitions
%%EndProlog
% initialization
[12 0 0 12 0 0] /Courier ssf
%%Page: 1 1
612 0 tr
90 rot
0 612 tr
1 -1 sc
[12 0 0 -12 0 0] /Courier ssf
np
19.92 sl
0 setlinecap
0.078 0 0.125 0 setcmykcolor
58.56 118.08 m
281.28 118.08 l
sk
13.2 sl
294.72 121.44 m
317.28 121.44 l
sk
357.84 121.44 m
382.56 121.44 l
sk
389.28 121.44 m
411.84 121.44 l
sk
452.16 121.44 m
476.88 121.44 l
sk
483.84 121.44 m
506.4 121.44 l
sk
546.72 121.44 m
571.44 121.44 l
sk
598.56 121.44 m
623.28 121.44 l
sk
708.72 121.44 m
733.44 121.44 l
sk
8.88 sl
58.56 141.84 m
281.28 141.84 l
sk
389.28 141.84 m
477.12 141.84 l
sk
483.84 141.84 m
571.68 141.84 l
sk
578.16 141.84 m
733.44 141.84 l
sk
294.72 142.08 m
382.32 142.08 l
sk
294.72 159.36 m
382.32 159.36 l
sk
58.56 159.84 m
281.28 159.84 l
sk
389.28 159.84 m
477.12 159.84 l
sk
483.84 159.84 m
571.68 159.84 l
sk
578.16 159.84 m
733.44 159.84 l
sk
58.56 177.84 m
281.28 177.84 l
sk
294.72 177.84 m
382.32 177.84 l
sk
389.28 177.84 m
477.12 177.84 l
sk
483.84 177.84 m
571.68 177.84 l
sk
578.16 177.84 m
733.44 177.84 l
sk
58.56 195.84 m
281.28 195.84 l
sk
294.72 195.84 m
382.32 195.84 l
sk
389.28 195.84 m
477.12 195.84 l
sk
483.84 195.84 m
571.68 195.84 l
sk
578.16 195.84 m
733.44 195.84 l
sk
58.56 213.84 m
281.28 213.84 l
sk
294.72 213.84 m
382.32 213.84 l
sk
389.28 213.84 m
477.12 213.84 l
sk
483.84 213.84 m
571.68 213.84 l
sk
578.16 213.84 m
733.44 213.84 l
sk
58.56 231.84 m
281.28 231.84 l
sk
294.72 231.84 m
382.32 231.84 l
sk
389.28 231.84 m
477.12 231.84 l
sk
483.84 231.84 m
571.68 231.84 l
sk
578.16 231.84 m
733.44 231.84 l
sk
58.56 249.84 m
281.28 249.84 l
sk
294.72 249.84 m
382.32 249.84 l
sk
389.28 249.84 m
477.12 249.84 l
sk
483.84 249.84 m
571.68 249.84 l
sk
578.16 249.84 m
733.44 249.84 l
sk
58.56 267.84 m
281.28 267.84 l
sk
294.72 267.84 m
382.32 267.84 l
sk
389.28 267.84 m
477.12 267.84 l
sk
483.84 267.84 m
571.68 267.84 l
sk
578.16 267.84 m
733.44 267.84 l
sk
58.56 285.84 m
281.28 285.84 l
sk
294.72 285.84 m
382.32 285.84 l
sk
389.28 285.84 m
477.12 285.84 l
sk
483.84 285.84 m
571.68 285.84 l
sk
578.16 285.84 m
733.44 285.84 l
sk
19.92 sl
58.56 421.92 m
281.28 421.92 l
sk
13.2 sl
294.72 425.28 m
317.28 425.28 l
sk
357.84 425.28 m
382.56 425.28 l
sk
389.28 425.28 m
411.84 425.28 l
sk
452.16 425.28 m
476.88 425.28 l
sk
483.84 425.28 m
506.4 425.28 l
sk
546.72 425.28 m
571.44 425.28 l
sk
598.56 425.28 m
623.28 425.28 l
sk
708.72 425.28 m
733.44 425.28 l
sk
8.88 sl
58.56 445.68 m
281.28 445.68 l
sk
389.28 445.68 m
477.12 445.68 l
sk
483.84 445.68 m
571.68 445.68 l
sk
578.16 445.68 m
733.44 445.68 l
sk
294.72 445.92 m
382.32 445.92 l
sk
294.72 463.2 m
382.32 463.2 l
sk
58.56 463.68 m
281.28 463.68 l
sk
389.28 463.68 m
477.12 463.68 l
sk
483.84 463.68 m
571.68 463.68 l
sk
578.16 463.68 m
733.44 463.68 l
sk
58.56 481.68 m
281.28 481.68 l
sk
294.72 481.68 m
382.32 481.68 l
sk
389.28 481.68 m
477.12 481.68 l
sk
483.84 481.68 m
571.68 481.68 l
sk
578.16 481.68 m
733.44 481.68 l
sk
58.56 499.68 m
281.28 499.68 l
sk
294.72 499.68 m
382.32 499.68 l
sk
389.28 499.68 m
477.12 499.68 l
sk
483.84 499.68 m
571.68 499.68 l
sk
578.16 499.68 m
733.44 499.68 l
sk
58.56 517.68 m
281.28 517.68 l
sk
294.72 517.68 m
382.32 517.68 l
sk
389.28 517.68 m
477.12 517.68 l
sk
483.84 517.68 m
571.68 517.68 l
sk
578.16 517.68 m
733.44 517.68 l
sk
58.56 535.68 m
281.28 535.68 l
sk
294.72 535.68 m
382.32 535.68 l
sk
389.28 535.68 m
477.12 535.68 l
sk
483.84 535.68 m
571.68 535.68 l
sk
578.16 535.68 m
733.44 535.68 l
sk
58.56 553.68 m
281.28 553.68 l
sk
294.72 553.68 m
382.32 553.68 l
sk
389.28 553.68 m
477.12 553.68 l
sk
483.84 553.68 m
571.68 553.68 l
sk
578.16 553.68 m
733.44 553.68 l
sk
58.56 571.68 m
281.28 571.68 l
sk
294.72 571.68 m
382.32 571.68 l
sk
389.28 571.68 m
477.12 571.68 l
sk
483.84 571.68 m
571.68 571.68 l
sk
578.16 571.68 m
733.44 571.68 l
sk
58.56 589.68 m
281.28 589.68 l
sk
294.72 589.68 m
382.32 589.68 l
sk
389.28 589.68 m
477.12 589.68 l
sk
483.84 589.68 m
571.68 589.68 l
sk
578.16 589.68 m
733.44 589.68 l
sk
1 1 0 0 setcmykcolor
278.16 29.28 m
594.72 35.28 6 270 0 arc
600.72 38.16 l
272.16 38.16 l
278.16 35.28 6 180 270 arc
ep
0.078 0 0.125 0 setcmykcolor
fill
1 1 0 0 setcmykcolor
611.04 29.28 m
747.6 35.28 6 270 0 arc
753.6 38.16 l
605.04 38.16 l
611.04 35.28 6 180 270 arc
ep
0.078 0 0.125 0 setcmykcolor
fill
1 1 0 0 setcmykcolor
278.16 333.12 m
594.72 339.12 6 270 0 arc
600.72 342 l
272.16 342 l
278.16 339.12 6 180 270 arc
ep
0.078 0 0.125 0 setcmykcolor
fill
1 1 0 0 setcmykcolor
611.04 333.12 m
747.6 339.12 6 270 0 arc
753.6 342 l
605.04 342 l
611.04 339.12 6 180 270 arc
ep
0.078 0 0.125 0 setcmykcolor
fill
0.72 sl
2 setlinecap
1 1 0 0 setcmykcolor
499.44 29.04 m
499.44 55.92 l
519.6 29.04 m
519.6 55.92 l
272.16 38.16 m
600.48 38.16 l
605.04 38.16 m
753.6 38.16 l
58.32 83.04 m
58.32 289.92 l
733.44 83.04 m
733.44 289.92 l
294.72 98.88 m
382.32 98.88 l
317.04 98.88 m
317.04 289.92 l
357.6 98.88 m
357.6 289.92 l
389.04 98.88 m
476.64 98.88 l
411.6 98.88 m
411.6 289.92 l
452.16 98.88 m
452.16 289.92 l
483.6 98.88 m
571.2 98.88 l
506.16 98.88 m
506.16 289.92 l
546.72 98.88 m
546.72 289.92 l
578.16 98.88 m
733.2 98.88 l
598.32 98.88 m
598.32 289.92 l
623.04 98.88 m
623.04 289.92 l
663.6 98.88 m
663.6 289.92 l
708.72 98.88 m
708.72 289.92 l
294.72 114.72 m
294.72 128.16 l
294.72 114.72 m
317.04 114.72 l
357.6 114.72 m
382.32 114.72 l
389.04 114.72 m
411.36 114.72 l
452.16 114.72 m
476.88 114.72 l
483.6 114.72 m
505.92 114.72 l
546.72 114.72 m
571.44 114.72 l
598.32 114.72 m
623.04 114.72 l
708.72 114.72 m
733.44 114.72 l
40.32 128.16 m
281.04 128.16 l
294.72 128.16 m
382.32 128.16 l
389.04 128.16 m
476.64 128.16 l
483.6 128.16 m
571.2 128.16 l
578.16 128.16 m
751.2 128.16 l
40.32 146.16 m
281.04 146.16 l
294.72 146.16 m
382.32 146.16 l
389.04 146.16 m
476.64 146.16 l
483.6 146.16 m
571.2 146.16 l
578.16 146.16 m
751.2 146.16 l
40.32 164.16 m
281.04 164.16 l
294.72 164.16 m
382.32 164.16 l
389.04 164.16 m
476.64 164.16 l
483.6 164.16 m
571.2 164.16 l
578.16 164.16 m
751.2 164.16 l
40.32 182.16 m
281.04 182.16 l
294.72 182.16 m
382.32 182.16 l
389.04 182.16 m
476.64 182.16 l
483.6 182.16 m
571.2 182.16 l
578.16 182.16 m
751.2 182.16 l
40.32 200.16 m
281.04 200.16 l
294.72 200.16 m
382.32 200.16 l
389.04 200.16 m
476.64 200.16 l
483.6 200.16 m
571.2 200.16 l
578.16 200.16 m
751.2 200.16 l
40.32 218.16 m
281.04 218.16 l
294.72 218.16 m
382.32 218.16 l
389.04 218.16 m
476.64 218.16 l
483.6 218.16 m
571.2 218.16 l
578.16 218.16 m
751.2 218.16 l
40.32 236.16 m
281.04 236.16 l
294.72 236.16 m
382.32 236.16 l
389.04 236.16 m
476.64 236.16 l
483.6 236.16 m
571.2 236.16 l
578.16 236.16 m
751.2 236.16 l
40.32 254.16 m
281.04 254.16 l
294.72 254.16 m
382.32 254.16 l
389.04 254.16 m
476.64 254.16 l
483.6 254.16 m
571.2 254.16 l
578.16 254.16 m
751.2 254.16 l
40.32 272.16 m
281.04 272.16 l
294.72 272.16 m
382.32 272.16 l
389.04 272.16 m
476.64 272.16 l
483.6 272.16 m
571.2 272.16 l
578.16 272.16 m
751.2 272.16 l
40.32 290.16 m
281.04 290.16 l
294.72 290.16 m
382.32 290.16 l
389.04 290.16 m
476.64 290.16 l
483.6 290.16 m
571.2 290.16 l
578.16 290.16 m
751.2 290.16 l
499.44 332.88 m
499.44 359.76 l
519.6 332.88 m
519.6 359.76 l
272.16 342 m
600.48 342 l
605.04 342 m
753.6 342 l
58.32 386.88 m
58.32 593.76 l
733.44 386.88 m
733.44 593.76 l
294.72 402.72 m
382.32 402.72 l
317.04 402.72 m
317.04 593.76 l
357.6 402.72 m
357.6 593.76 l
389.04 402.72 m
476.64 402.72 l
411.6 402.72 m
411.6 593.76 l
452.16 402.72 m
452.16 593.76 l
483.6 402.72 m
571.2 402.72 l
506.16 402.72 m
506.16 593.76 l
546.72 402.72 m
546.72 593.76 l
578.16 402.72 m
733.2 402.72 l
598.32 402.72 m
598.32 593.76 l
623.04 402.72 m
623.04 593.76 l
663.6 402.72 m
663.6 593.76 l
708.72 402.72 m
708.72 593.76 l
294.72 418.32 m
317.04 418.32 l
294.72 418.32 m
294.72 431.76 l
sk
357.6 418.32 m
382.32 418.32 l
389.04 418.32 m
411.36 418.32 l
452.16 418.32 m
476.88 418.32 l
483.6 418.32 m
505.92 418.32 l
546.72 418.32 m
571.44 418.32 l
598.32 418.32 m
623.04 418.32 l
708.72 418.32 m
733.44 418.32 l
40.32 432 m
281.04 432 l
294.72 432 m
382.32 432 l
389.04 432 m
476.64 432 l
483.6 432 m
571.2 432 l
578.16 432 m
751.2 432 l
40.32 450 m
281.04 450 l
294.72 450 m
382.32 450 l
389.04 450 m
476.64 450 l
483.6 450 m
571.2 450 l
578.16 450 m
751.2 450 l
40.32 468 m
281.04 468 l
294.72 468 m
382.32 468 l
389.04 468 m
476.64 468 l
483.6 468 m
571.2 468 l
578.16 468 m
751.2 468 l
40.32 486 m
281.04 486 l
294.72 486 m
382.32 486 l
389.04 486 m
476.64 486 l
483.6 486 m
571.2 486 l
578.16 486 m
751.2 486 l
40.32 504 m
281.04 504 l
294.72 504 m
382.32 504 l
389.04 504 m
476.64 504 l
483.6 504 m
571.2 504 l
578.16 504 m
751.2 504 l
40.32 522 m
281.04 522 l
294.72 522 m
382.32 522 l
389.04 522 m
476.64 522 l
483.6 522 m
571.2 522 l
578.16 522 m
751.2 522 l
40.32 540 m
281.04 540 l
294.72 540 m
382.32 540 l
389.04 540 m
476.64 540 l
483.6 540 m
571.2 540 l
578.16 540 m
751.2 540 l
40.32 558 m
281.04 558 l
294.72 558 m
382.32 558 l
389.04 558 m
476.64 558 l
483.6 558 m
571.2 558 l
578.16 558 m
751.2 558 l
40.32 576 m
281.04 576 l
294.72 576 m
382.32 576 l
389.04 576 m
476.64 576 l
483.6 576 m
571.2 576 l
578.16 576 m
751.2 576 l
40.32 594 m
281.04 594 l
294.72 594 m
382.32 594 l
389.04 594 m
476.64 594 l
483.6 594 m
571.2 594 l
578.16 594 m
751.2 594 l
sk
0 setlinecap
47.04 29.28 m
260.16 35.28 6 270 0 arc
260.16 68.4 6 0 90 arc
47.04 68.4 6 90 180 arc
47.04 35.28 6 180 270 arc
sk
278.16 29.28 m
594.72 35.28 6 270 0 arc
600.72 56.4 l
272.16 56.4 l
278.16 35.28 6 180 270 arc
sk
611.28 29.28 m
747.84 35.28 6 270 0 arc
753.84 56.4 l
605.28 56.4 l
611.28 35.28 6 180 270 arc
sk
46.56 83.28 m
275.28 89.28 6 270 0 arc
281.28 290.4 l
40.56 290.4 l
46.56 89.28 6 180 270 arc
sk
300.72 83.28 m
376.56 89.28 6 270 0 arc
382.56 290.4 l
294.72 290.4 l
300.72 89.28 6 180 270 arc
sk
395.28 83.28 m
471.12 89.28 6 270 0 arc
477.12 290.4 l
389.28 290.4 l
395.28 89.28 6 180 270 arc
sk
489.84 83.28 m
565.68 89.28 6 270 0 arc
571.68 290.4 l
483.84 290.4 l
489.84 89.28 6 180 270 arc
sk
584.16 83.28 m
745.44 89.28 6 270 0 arc
751.44 290.4 l
578.16 290.4 l
584.16 89.28 6 180 270 arc
sk
47.04 333.12 m
260.16 339.12 6 270 0 arc
260.16 372.24 6 0 90 arc
47.04 372.24 6 90 180 arc
47.04 339.12 6 180 270 arc
sk
278.16 333.12 m
594.72 339.12 6 270 0 arc
600.72 360.24 l
272.16 360.24 l
278.16 339.12 6 180 270 arc
sk
611.28 333.12 m
747.84 339.12 6 270 0 arc
753.84 360.24 l
605.28 360.24 l
611.28 339.12 6 180 270 arc
sk
46.56 387.12 m
275.28 393.12 6 270 0 arc
281.28 594.24 l
40.56 594.24 l
46.56 393.12 6 180 270 arc
sk
300.72 387.12 m
376.56 393.12 6 270 0 arc
382.56 594.24 l
294.72 594.24 l
300.72 393.12 6 180 270 arc
sk
395.28 387.12 m
471.12 393.12 6 270 0 arc
477.12 594.24 l
389.28 594.24 l
395.28 393.12 6 180 270 arc
sk
489.84 387.12 m
565.68 393.12 6 270 0 arc
571.68 594.24 l
483.84 594.24 l
489.84 393.12 6 180 270 arc
sk
584.16 387.12 m
745.44 393.12 6 270 0 arc
751.44 594.24 l
578.16 594.24 l
584.16 393.12 6 180 270 arc
sk
[8 0 0 -8 0 0] /Helvetica-Narrow ssf
(STUDENT NAME) 274.8 36.72 tl
(NUMBER) 522.48 36.72 tl
(COUNSELOR) 607.68 36.96 tl
(COURSE TITLE) 61.68 96.24 tl
(TEACHER) 179.76 123.12 tl
(STUDENT NAME) 274.8 340.56 tl
(NUMBER) 522.48 340.56 tl
(COUNSELOR) 607.92 340.56 tl
(COURSE TITLE) 61.68 399.84 tl
(TEACHER) 179.76 426.72 tl
(Designed using Lytrod Software products. 800 /4 LYTROD.) 562.56 599.04 tl
[4 0 0 -4 0 0] /Helvetica-Narrow-Bold ssf
(GRADE) 503.76 33.6 tl
(LEVEL) 504.96 37.2 tl
(GRADE) 503.76 337.44 tl
(LEVEL) 504.96 341.04 tl
[18 0 0 -18 0 0] /Helvetica-Bold ssf
(STUDENT GRADE REPORT) 515.04 75.84 tl
(STUDENT GRADE REPORT) 515.04 379.44 tl
[7 0 0 -7 0 0] /Helvetica-Narrow ssf
(GRADE) 296.16 109.44 tl
(ABS.) 363.84 109.44 tl
(GRADE) 390.48 109.44 tl
(ABS.) 458.16 109.44 tl
(GRADE) 485.04 109.44 tl
(ABS.) 552.72 109.44 tl
(GRADE) 600.96 109.44 tl
(ABS.) 714.72 109.44 tl
(COMMENTS) 669.36 111.6 tl
(FINAL) 580.56 112.08 tl
(CREDITS) 631.2 112.08 tl
(COMMENTS) 320.64 115.68 tl
(COMMENTS) 415.2 115.68 tl
(COMMENTS) 509.76 115.68 tl
(EXAM) 580.56 120.24 tl
(EARNED) 631.92 120.24 tl
(\(SEE BACK\)) 321.12 123.84 tl
(\(SEE BACK\)) 415.68 123.84 tl
(\(SEE BACK\)) 510.24 123.84 tl
(CIT.) 300.72 124.08 tl
(TARDY) 360.72 124.08 tl
(CIT.) 394.8 124.08 tl
(TARDY) 455.04 124.08 tl
(CIT.) 489.36 124.08 tl
(TARDY) 549.6 124.08 tl
(CIT.) 605.52 124.08 tl
(TARDY) 711.6 124.08 tl
(GRADE) 296.16 413.28 tl
(ABS.) 363.84 413.28 tl
(GRADE) 390.48 413.28 tl
(ABS.) 458.16 413.28 tl
(GRADE) 485.04 413.28 tl
(ABS.) 552.72 413.28 tl
(GRADE) 600.96 413.28 tl
(ABS.) 714.72 413.28 tl
(COMMENTS) 669.36 415.2 tl
(FINAL) 580.56 415.92 tl
(CREDITS) 631.2 415.92 tl
(COMMENTS) 320.64 419.52 tl
(COMMENTS) 415.2 419.52 tl
(COMMENTS) 509.76 419.52 tl
(EXAM) 580.56 424.08 tl
(EARNED) 631.92 424.08 tl
(\(SEE BACK\)) 321.12 427.68 tl
(\(SEE BACK\)) 415.68 427.68 tl
(\(SEE BACK\)) 510.24 427.68 tl
(CIT.) 300.72 427.92 tl
(TARDY) 360.72 427.92 tl
(CIT.) 395.28 427.92 tl
(TARDY) 455.04 427.92 tl
(CIT.) 489.84 427.92 tl
(TARDY) 549.6 427.92 tl
(CIT.) 605.52 427.92 tl
(TARDY) 711.6 427.92 tl
[8 0 0 -8 0 0] /Helvetica-Narrow ssf
270 (PERIOD) 52.56 118.56 lrot
270 (PERIOD) 745.44 118.56 lrot
270 (PERIOD) 52.56 422.4 lrot
270 (PERIOD) 745.44 422.4 lrot
/#copies 1 def
%%PageFonts: Courier Helvetica-Narrow Helvetica-Narrow-Bold Helvetica-Bold
showpage
%%Trailer
%%Pages: 1
%%DocumentFonts: Courier Helvetica-Narrow Helvetica-Narrow-Bold Helvetica-Bold
%%BoundingBox: 0 0 792 612


65
resource/postscript/grayalph.ps Executable file
View file

@ -0,0 +1,65 @@
%!
% grayscaled text test, including a trivial user bitmap font
/grayalphsave save def % prevent left over effects
/inch {72 mul} def
/BuildCharDict 10 dict def
/$ExampleFont 7 dict def
$ExampleFont begin
/FontType 3 def % user defined font.
/FontMatrix [1 0 0 1 0 0] def
/FontBBox [0 0 1 1] def
/Encoding 256 array def
0 1 255 {Encoding exch /.notdef put} for
Encoding (a) 0 get /plus put
/CharStrings 2 dict def
CharStrings /.notdef {} put
CharStrings /plus
{ gsave
0 0 moveto
32 32 true [32 0 0 -32 0 32]
{<0007E000 0007E000 0007E000 0007E000 0007E000 0007E000 0007E000 0007E000
0007E000 0007E000 0007E000 0007E000 0007E000 FFFFFFFF FFFFFFFF FFFFFFFF
FFFFFFFF FFFFFFFF FFFFFFFF 0007E000 0007E000 0007E000 0007E000 0007E000
0007E000 0007E000 0007E000 0007E000 0007E000 0007E000 0007E000 0007E000>
} imagemask
grestore
} put
/BuildChar
{ BuildCharDict begin
/char exch def
/fontdict exch def
/charproc
fontdict /Encoding get char get
fontdict /CharStrings get
exch get def
1 0 0 0 1 1 setcachedevice
charproc
end
} def
end
/MyFont $ExampleFont definefont pop
newpath
.5 inch 7.5 inch moveto
7.5 inch 0 rlineto
0 1.5 inch rlineto
-7.5 inch 0 rlineto
closepath
0 setgray
fill
/MyFont findfont 72 scalefont setfont
.75 inch 7.75 inch moveto
0 1 6
{ /n exch def
1 n 6 div sub setgray
(a) show
} for
showpage
clear cleardictstack
grayalphsave restore

View file

@ -0,0 +1,939 @@
%!PS-Adobe-2.0
%%Title: Just A Little PostScript
%%Creator: Randolph J. Herber
%%CreationDate: Mon Aug 19 18:39:39 CDT 1996
%%DocumentData: Clean7Bit
%%LanguageLevel: 1
%%Pages: (atend)
%%BoundingBox: 0 0 792 612
%%Orientation: Portrait
%%PageOrder: Ascend
%%EndComments
%%BeginProlog
/DoColor true def
/Handout true def
%!
% behandler.ps, v1.3, Mar 23 1990, a modified version of Adobe's ehandler.ps
% Original program copyright (c) 1986 Adobe Systems Incorporated
% Modified by Fredric Ihren, for support contact fred@nada.kth.se or write to
% Fredric Ihren; Moerbydalen 17; S-182 32 D-RYD; Sweden
% Adobe will not keep maintenance of this program.
% Distributed with permission from Adobe Systems Incorporated
% 0000 % serverloop password
% /$brkpage where not {
% dup serverdict begin statusdict begin checkpassword
% { (NEW Error Handler downloaded.\n) print flush exitserver }
% { pop (Bad Password on loading error handler.\n) print flush stop }
% ifelse
% } {
% pop pop (NEW Error Handler in place - not loaded again\n) print flush stop
% } ifelse
/$brkpage 64 dict def
$brkpage begin
/== { /cp 0 def typeprint nl } def
/printpage {
/prnt {
dup type /stringtype ne { =string cvs } if dup length 6 mul /tx exch def
/ty 10 def currentpoint /toy exch def /tox exch def 1 setgray newpath
tox toy 2 sub moveto 0 ty rlineto tx 0 rlineto 0 ty neg rlineto
closepath fill tox toy moveto 0 setgray show
} bind def
/nl { currentpoint exch pop lmargin exch moveto 0 -10 rmoveto } def
/doshowpage systemdict /showpage get def
} def
/printonly {
/nl { (\n) print } def
/prnt { dup type /stringtype ne { =string cvs } if print } def
/doshowpage null cvx def
} def
printpage
/typeprint { dup type dup currentdict exch known
{ exec } { unknowntype } ifelse
} def
/lmargin 72 def /rmargin 72 def
/tprint { dup length cp add rmargin gt { nl /cp 0 def } if
dup length cp add /cp exch def prnt
} def
/cvsprint { =string cvs tprint( ) tprint } def
/unknowntype { exch pop cvlit (??) tprint cvsprint } def
/integertype { cvsprint } def
/realtype { cvsprint } def
/booleantype { cvsprint } def
/operatortype { (//) tprint cvsprint } def
/marktype { pop (-mark- ) tprint } def
/dicttype { pop (-dictionary- ) tprint } def
/nulltype { pop (-null- ) tprint } def
/filetype { pop (-filestream- ) tprint } def
/savetype { pop (-savelevel- ) tprint } def
/fonttype { pop (-fontid- ) tprint } def
/nametype { dup xcheck not { (/) tprint } if cvsprint } def
/stringtype {
dup rcheck
{ (\() tprint tprint (\)) tprint }
{ pop (-string- ) tprint }
ifelse
} def
/arraytype {
dup rcheck { dup xcheck
{ ({) tprint { typeprint } forall (}) tprint }
{ ([) tprint { typeprint } forall (]) tprint }
ifelse } { pop (-array- ) tprint } ifelse
} def
/packedarraytype {
dup rcheck { dup xcheck
{ ({) tprint { typeprint } forall (}) tprint }
{ ([) tprint { typeprint } forall (]) tprint }
ifelse } { pop (-packedarray- ) tprint } ifelse
} def
/stackmax 50 def
/execmax 25 def
/filemax 10 def
/courier /Courier findfont 10 scalefont def
/OLDhandleerror errordict /handleerror get def
end %$brkpage
errordict /handleerror {
systemdict begin $error begin $brkpage begin newerror {
{
/newerror false store
vmstatus pop pop 0 ne { grestoreall } if initgraphics courier setfont
lmargin 750 moveto
statusdict /jobname get dup null ne
{ (Jobname: ) prnt prnt nl } { pop } ifelse
(Error: ) prnt errorname prnt nl
(Command: ) prnt /command load ==
$error /ostack known {
$error /ostack get dup length 0 ne {
(Stack \() prnt
aload length dup prnt (\):) prnt nl
/i 0 def
{ /i i 1 add def i stackmax le { == } { pop } ifelse }
repeat
} { pop } ifelse
} if
$error /estack known {
$error /estack get dup dup length 1 sub get type /filetype ne {
(Execstack \() prnt
aload length dup prnt (\):) prnt nl
/i 0 def
{ /i i 1 add def dup type /filetype eq { /i 99 def } if
i execmax le { == } { pop } ifelse
} repeat
} { pop } ifelse
} if
(%stdin) (r) file
dup =string readline {
(File:) prnt nl prnt nl
filemax 1 sub { dup =string readline { prnt nl } { exit } ifelse }
repeat
} if pop
userdict /debug known {
(Debug:) prnt nl
userdict /debug get stopped pop nl
} if
} stopped pop
doshowpage
/newerror true store
/OLDhandleerror load end end end exec
} { end end end }
ifelse
} dup 0 systemdict put dup 4 $brkpage put bind put
/PageFrame 600 dict dup begin
%%Copyright: Copyright 1991 University Research Associates.
%%+ ***************************************************************************
%%+ ** Copyright (c) 1991 Randolph J. Herber **
%%+ ** All Rights Reserved. **
%%+ ** Applies only to the included type 3 font **
%%+ ** describing the Fermilab logo. **
%%+ ** The type 3 font was developed using personal **
%%+ ** equipment and own time and materials. **
%%+ ** The following license granted to the **
%%+ ** Government. **
%%+ ** Copyright (c) 1991 Universities Research Association, Inc. **
%%+ ** All Rights Reserved. **
%%+ ** **
%%+ ** This material resulted from work developed under a Government **
%%+ ** Contract and is subject to the following license: **
%%+ ** **
%%+ ** LICENSE **
%%+ ** The Government retains a paid-up, nonexclusive, irrevocable worldwide **
%%+ ** license to reproduce, prepare derivative works, perform publicly and **
%%+ ** display publicly by or for the Government, including the right to **
%%+ ** distribute to other Government contractors. Neither the **
%%+ ** United States nor the United States Department of Energy nor any of **
%%+ ** their employees, nor the author of the type 3 font included makes **
%%+ ** any warranty, express or implied, or assumes any legal liability or **
%%+ ** responsibility for the accuracy, completeness, or usefulness of any **
%%+ ** information, apparatus, product, or process disclosed, or represents **
%%+ ** that its use would not infringe privately owned rights. **
%%+ ** **
%%+ ** **
%%+ ** Fermilab Computing Division/Distributed Computing Department **
%%+ ** **
%%+ ***************************************************************************
%%
%% Begining of Logo font definition
%%
9 dict dup begin
/FontType 3 def
/FontName (Logo) cvn def
/FontMatrix [0.001 0 0 0.001 0 0] def
/FontBBox [0 0 0 0] def % Some interperters need this
/Encoding 256 array def
0 1 255 { Encoding exch /.notdef put } bind for
Encoding
dup 70 /Fermi put
pop
/CharProcs 7 dict dup begin
/Fermi {
0 setlinecap
0 setlinejoin
1 setlinewidth
1000 0 0 0 1000 1000 setcachedevice
475 887.5 moveto
0 80.88 rlineto
-150 0 rlineto
0 -93.38 rlineto
-155.72 0 rlineto
0 -150 rlineto
154.46 0 rlineto
262.5 737.5 62.5 348.46 270 arcn
-230.88 0 rlineto
0 -150 rlineto
230.88 0 rlineto
262.5 737.5 212.5 270 360 arc
50 0 rlineto
737.5 737.5 212.5 180 270 arc
230.88 0 rlineto
0 150 rlineto
-230.88 0 rlineto
737.5 737.5 62.5 270 191.54 arcn
154.46 0 rlineto
0 150 rlineto
-155.72 0 rlineto
0 93.38 rlineto
-150 0 rlineto
0 -80.88 rlineto fill
525 112.5 moveto
0 -80.88 rlineto
150 0 rlineto
0 93.38 rlineto
155.72 0 rlineto
0 150 rlineto
-154.46 0 rlineto
737.5 262.5 62.5 168.46 90 arcn
230.88 0 rlineto
0 150 rlineto
-230.88 0 rlineto
737.5 262.5 212.5 90 180 arc
-50 0 rlineto
262.5 262.5 212.5 0 90 arc
-230.88 0 rlineto
0 -150 rlineto
230.88 0 rlineto
262.5 262.5 62.5 90 11.54 arcn
-154.46 0 rlineto
0 -150 rlineto
155.72 0 rlineto
0 -93.38 rlineto
150 0 rlineto
0 80.88 rlineto fill
} bind def
end def
/BuildChar {
0
begin
exch begin
Encoding exch get
CharProcs exch get
end
exec
end
} bind def
/BuildChar load 0
6 dict dup begin
end put
end
/Logo exch definefont pop
%
% Copyright 1990 by Adobe Systems Incorporated. All rights reserved.
%
% This file may be freely copied and redistributed as long as:
% 1) This entire notice continues to be included in the file,
% 2) If the file has been modified in any way, a notice of such
% modification is conspicuously indicated.
%
% PostScript, Display PostScript, and Adobe are registered trademarks of
% Adobe Systems Incorporated.
%
% ************************************************************************
% THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
% NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
% INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
% LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
% KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
% AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
% ************************************************************************
%
% This file defines a PostScript procedure called "R" which will
% reencode a font. It expects to find three things on the operand stack:
%
% [ array ] /NewName /OldName
%
% The array should contain pairs of <number> <name>, like "32 /space",
% each of which will define a slot in the encoding and the name to put
% in that slot. Only those names which are needed to over-ride the
% existing ones need be specified. An encoding value (number) may
% be specified followed by more than one name, like "128 /name1 /name2".
% In this case, the names will be sequentially stored in the encoding
% starting at the initial number given (128).
/R {
findfont begin currentdict dup length dict begin
{ %forall
1 index /FID ne {def} {pop pop} ifelse
} forall
/FontName exch def dup length 0 ne { %if
/Encoding Encoding 256 array copy def
0 exch { %forall
dup type /nametype eq { %ifelse
Encoding 2 index 2 index put
pop 1 add
}{ %else
exch pop
} ifelse
} forall
} if pop
currentdict dup end end
/FontName get exch definefont pop
} bind def
% sample use:
% [ 8#360 /apple ] /_Symbol /Symbol R
% declare page sizes
/D {def} bind def
/B {bind D} bind D
/E {exch D} B
/M {moveto} B
/S {marking {show}
{stringwidth rmoveto
currentpoint pop dup MaxX gt{/MaxX E}{pop}ifelse}
ifelse} B
/H {marking {currentlinewidth exch true charpath 0.5 setlinewidth
gsave 1 setgray fill grestore stroke setlinewidth}
{stringwidth rmoveto
currentpoint pop dup MaxX gt{/MaxX E}{pop}ifelse}
ifelse} B
/Stroke {currentpoint pop dup MaxX gt{/MaxX E}{pop}ifelse marking {stroke}if} B
/W {stringwidth pop} B
/Short 612 D
/Long 792 D
% at this point in the program, the default coordinate system is still in place
/Shrink where {pop
Short 1.0 Shrink sub 0.5 mul mul Long 1.0 Shrink sub 0.5 mul mul translate
Shrink Shrink scale} if
/margin 36 D
/logosize 48 D % memo head size is 56.25
/radius 18 D
/gap 12 D
/offset 8 D
/High 480 D
/Wide 720 D
/CenterX 396 D
/CenterY 336 D
/Top CenterY High 0.5 mul add D
/Tsize 36 D
/Tlead 9 D
/Tspace Tsize Tlead add D
/esize 18 D
/elead 6 D
/espace esize elead add D
/tsize 18 D
/tlead 6 D
/tspace tsize tlead add D
/Ssize 6 D
/Slead 2 D
/Sspace Ssize Slead add D
/setline {1 sub /lineno E} B
/LT {/lineno exch def lineno Lmax gt {/Lmax lineno def}if} B
/eT {/lineno exch def lineno emax gt {/emax lineno def}if} B
/lT {/lineno exch def lineno lmax gt {/lmax lineno def}if} B
/Line {LT lineno 1 sub Tspace mul Base exch sub /Y E} B
/L+ {lineno 1 add LT lineno 1 sub Tspace mul Base exch sub /Y E} B
/L+2 {lineno 2 add LT lineno 1 sub Tspace mul Base exch sub /Y E} B
/eline {eT lineno 1 sub espace mul ebase exch sub /Y E} B
/e+ {lineno 1 add eT lineno 1 sub espace mul ebase exch sub /Y E} B
/e+2 {lineno 2 add eT lineno 1 sub espace mul ebase exch sub /Y E} B
/line {lT lineno 1 sub tspace mul base exch sub /Y E} B
/l+ {lineno 1 add lT lineno 1 sub tspace mul base exch sub /Y E} B
/l+2 {lineno 2 add lT lineno 1 sub tspace mul base exch sub /Y E} B
/C1 {col1 Y moveto} B
/C2 {col2 Y moveto} B
/C3 {col3 Y moveto} B
/C4 {col4 Y moveto} B
/C5 {col5 Y moveto} B
/C6 {col6 Y moveto} B
/C7 {col7 Y moveto} B
/C8 {col8 Y moveto} B
/C9 {col9 Y moveto} B
/RC [ 8#375 /copyright /registered /trademark ] def
RC /_Times-Roman /Times-Roman R
/foliofont /_Times-Roman findfont logosize offset 3 mul sub scalefont D
/FO {foliofont setfont} B
/textsize /_Times-Roman findfont tsize scalefont D
/TX {textsize setfont} B
/TXS {currentfont exch TX S setfont} B
RC /_Times-Italic /Times-Italic R
/italics /_Times-Italic findfont tsize scalefont D
/TI {italics setfont} B
/TIS {currentfont exch TI S setfont} B
RC /_Times-BoldItalic /Times-BoldItalic R
/bold_italics /_Times-BoldItalic findfont tsize scalefont D
/TJ {bold_italics setfont} B
/TJS {currentfont exch TJ S setfont} B
RC /_Times-Bold /Times-Bold R
/boldfont /_Times-Bold findfont tsize scalefont D
/TB {boldfont setfont} B
/TBS {currentfont exch TB S setfont} B
/monospace /Courier-Bold findfont tsize scalefont D
/CM {monospace setfont} B
/CMS {currentfont exch CM S setfont} B
/monolite /Courier findfont tsize scalefont D
/CR {monolite setfont} B
/CRS {currentfont exch CR S setfont} B
/monoitalic /Courier-Oblique findfont tsize scalefont D
/CI {monoitalic setfont} B
/CIS {currentfont exch CI S setfont} B
/monoBI /Courier-BoldOblique findfont tsize scalefont D
/CJ {monoBI setfont} B
/CJS {currentfont exch CJ S setfont} B
/narrowmono /Courier-Bold findfont [.8 tsize mul 0 0 tsize 0 0] makefont D
/SC {narrowmono setfont} B
/SCS {currentfont exch SC S setfont} B
/largesize /_Times-Roman findfont Tsize scalefont D
/LG {largesize setfont} B
/LGS {currentfont exch LG S setfont} B
/smallfont /_Times-Roman findfont Ssize scalefont D
/SM {smallfont setfont} B
/SMS {currentfont exch SM S setfont} B
/symbolfont /Symbol findfont tsize scalefont D
/SY {symbolfont setfont} B
/microsymbol /Symbol findfont tsize 0.4 mul scalefont D
/MY {microsymbol setfont} B
/pointerfont /ZapfDingbats findfont tsize scalefont D
/PT {pointerfont setfont} B
/FNALfont /Logo findfont tsize scalefont D
/FN {FNALfont setfont} B
/Item {currentfont SY(\267)S setfont} B
/Note {currentfont PT(-)S setfont} B
/Here {currentfont PT(+)S setfont} B
/Gives {currentfont SY(\336)S setfont} B
/Moon {currentfont PT(m)S setfont} B
/FNAL {currentfont FN(F)S setfont} B
/Block1 {currentfont PT(y)S setfont} B
/Block2 {currentfont PT(z)S setfont} B
/Start {currentpoint gsave currentpoint translate MY (\355) stringwidth
pop -.5 mul tsize -.5 mul moveto (\255) S grestore moveto } B
/Mark {currentpoint gsave currentpoint translate MY (\355) stringwidth
pop -.5 mul tsize -.5 mul moveto (\335) S grestore moveto } B
/More {660 108 M currentfont TX ((more)) show setfont} B
/center {/Text E Long Text stringwidth pop sub 0.5 mul exch moveto
Text marking{show}{pop}ifelse} B
/Center {Long exch sub 0.5 mul exch moveto} B
/Fickle {Index lineno eq {Here} {Item} ifelse} B
/RVS {marking {dup save exch currentpoint newpath moveto
1 0 rmoveto true charpath pathbbox
1 add /Uy E 1 add /Ux E 1 sub /Ly E 1 sub /Lx E newpath
Lx Ux add 0.5 mul Ly moveto
Lx Ly Lx Uy 1 arcto pop pop pop pop
Lx Uy Ux Uy 1 arcto pop pop pop pop
Ux Uy Ux Ly 1 arcto pop pop pop pop
Ux Ly Lx Ly 1 arcto pop pop pop pop
closepath
0 setgray fill restore
currentgray exch 1 setgray 1 0 rmoveto show 1 0 rmoveto setgray}
{stringwidth rmoveto 2 0 rmoveto
currentpoint pop dup MaxX gt{/MaxX E}{pop}ifelse}
ifelse} B
/Frame {
/ll E /el E /Ll E
/Lmax 0 D /emax 0 D /lmax 0 D
/Gaps 1 Ll 1 lt{0 /THght 0 D}{1 /THght Ll Tspace mul Tlead sub D}ifelse add
el 1 lt{0 /eHght 0 D}{1 /eHght el espace mul elead sub D}ifelse add
ll 1 lt{0 /tHght 0 D}{1 /tHght ll tspace mul tlead sub D}ifelse add D
/GapSize High THght sub eHght sub tHght sub Gaps div D
/Base Top Ll 1 ge{GapSize sub Tsize sub}if D
/ebase Top Ll 1 ge{GapSize sub THght sub}if
el 1 ge{GapSize sub esize sub}if D
/base Top Ll 1 ge{GapSize sub THght sub}if
el 1 ge{GapSize sub eHght sub}if
ll 1 ge{GapSize sub tsize sub}if D
/Rnd {rand 2147483647.0 div mul add} bind def
% size of rounded box allowing for logo at top
/boxx Long margin dup add sub D
/boxy Short margin dup add sub logosize sub gap sub D
% left edge of logo area
/logox Long margin sub logosize 1.2 mul sub
/Helvetica-Bold findfont logosize 0.5 mul scalefont setfont (Fermilab)
stringwidth pop sub D
% left edge of titling area
/titlesize logosize 6 div D
/titlefont /Helvetica-Bold findfont titlesize 1.6 mul scalefont D
/giverfont /Times-Roman findfont titlesize 0.8 mul scalefont D
/titlex logox gap sub
titlefont setfont talktitle stringwidth pop
giverfont setfont talkgiver stringwidth pop 2 copy lt {exch} if pop
talkdept stringwidth pop 2 copy lt {exch} if pop
talkaddr stringwidth pop 2 copy lt {exch} if pop
talkcopyr stringwidth pop 2 copy lt {exch} if pop
sub D
% determine folio box size
/folioboxx foliofont setfont folio stringwidth pop offset dup add add D
/folioboxy logosize offset sub D
% determine folio box x origin
/folioorgx titlex margin add gap sub offset sub folioboxx sub 2 div D
% rotate to landscape orientation
90 rotate
% move origin to lower left hand corner of sheet
0 Short neg translate
% draw logo in lower right hand corner
save
/DoColor where {pop DoColor {.4 .6 Rnd .2 .8 Rnd .2 .8 Rnd setrgbcolor}if}if
logox margin translate
/Logo findfont logosize scalefont setfont 0 0 moveto (F) show
/DoColor where {pop DoColor {0 setgray}if}if
/Helvetica-Bold findfont
logosize 0.5 mul scalefont setfont
logosize 1.2 mul logosize 0.375 mul moveto
(Fermilab) show
restore
% add talk data
save
titlex margin translate
0 titlesize 4 mul moveto titlefont setfont talktitle show
0 titlesize 3 mul moveto giverfont setfont talkgiver show
0 titlesize 2 mul moveto talkdept show
0 titlesize moveto talkaddr show
0 0 moveto talkcopyr show
restore
% add folio
save
0 setlinecap % square butt ends
1 setlinejoin % rounded corners
0.5 setlinewidth % width of line to draw
/box {1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath} B
folioorgx margin translate
gsave
offset 0 translate 0 0 moveto 0 setgray folioboxx folioboxy box fill
grestore
gsave
0 offset translate
0 0 moveto 0.95 setgray folioboxx folioboxy box fill
0 0 moveto 0 setgray folioboxx folioboxy box stroke
grestore
gsave
offset dup dup add translate 0 0 moveto foliofont setfont
folio true charpath
gsave 1 setgray fill grestore stroke
grestore
restore
%
% draw rounded box
%
save
/DoColor where {pop DoColor {0 0 1 setrgbcolor}if}if
% start a new path
% line characters
0 setlinecap % square butt ends
1 setlinejoin % rounded corners
3 setlinewidth % width of line to draw
newpath
% make lower left corner of the rounded box the origin
margin margin logosize add gap add translate
% center of bottom edge
boxx 0.5 mul 0 moveto
% draw lower left corner to center of left edge
0 0 0 boxy mul 0.5 radius arcto pop pop pop pop
% draw upper left corner to center of top edge
0 boxy boxx 0.5 mul boxy radius arcto pop pop pop pop
% draw upper right corner to center of right edge
boxx boxy boxx boxy 0.5 mul radius arcto pop pop pop pop
% draw lower left corner to near center of bottom edge
boxx 0 boxx mul 0.5 6 add 0 radius arcto pop pop pop pop
% close the path
closepath
% draw the box
stroke
restore
save
filenames {756 SM filename stringwidth pop sub 588 moveto filename show}if
restore} B
/Check {
filenames {
Lmax dup add emax add lmax add 18 lt
{Lmax Ll ne emax el ne or lmax ll ne or}
{Lmax Ll ne emax el ne or lmax 1 add ll ne or} ifelse
{ 36 588 moveto SM
Lmax =string cvs show (/)show Ll =string cvs show ( )show
emax =string cvs show (/)show el =string cvs show ( )show
lmax =string cvs show (/)show ll =string cvs show
} if
} if } B
%
% draw rounded box
%
/drbradius tsize 3 div D
/drb { /drbtext E /drbxy E /drbxx E
marking
{ save
currentpoint translate
0 setlinecap % square butt ends
1 setlinejoin % rounded corners
0.5 setlinewidth % width of line to draw
newpath
% the origin is the lower left corner of the rounded box
% start drawing the box at the center of the bottom edge
drbxx 0.5 mul 0 moveto
% draw lower left corner to center of left edge
0 0 0 drbxy mul 0.5 drbradius arcto pop pop pop pop
% draw upper left corner to center of top edge
0 drbxy drbxx 0.5 mul drbxy drbradius arcto pop pop pop pop
% draw upper right corner to center of right edge
drbxx drbxy drbxx drbxy 0.5 mul drbradius arcto pop pop pop pop
% draw lower left corner to near center of bottom edge
drbxx 0 drbxx mul 0.5 6 add 0 drbradius arcto pop pop pop pop
% close the path
closepath
% draw the box
stroke
% place the text
drbxx drbtext stringwidth pop sub 0.5 mul
drbxy tspace sub 0.5 mul tlead add
moveto drbtext show
restore
}{
/drbright currentpoint pop drbxx add 0.25 add D
drbright MaxX gt {/MaxX drbright D} if
} ifelse
} B
/PlaceText {
/Markings E
save /marking false D /MaxX 0 D Markings
CenterX MaxX 0.5 mul sub 0 translate
/marking true D Markings lmax exch restore /lmax exch def} B
/MeasureText {/Markings E /marking false D /MaxX 0 D /Base Top D /base Top D
Markings /OffsetX CenterX MaxX 0.5 mul sub D} B
/MarkText {save OffsetX 0 translate /marking true D Markings restore} B
/marking true D
/filenames false D
/OffsetX 90 D
/col1 0 D
/col2 30 D
/col3 60 D
/col4 90 D
/col5 120 D
/col6 150 D
/col7 180 D
/col8 210 D
/col9 240 D
%%
%% Used to divide the page into two sections divided horizonally
%%
/Scale 0.625 D
/SubPageX Short Scale mul D
/SubPageY Long Scale mul D
/AdjustX -6 D
/AdjustUX Long -0.5 mul AdjustX sub SubPageX sub D
/AdjustLX Long -0.5 mul AdjustX add D
/AdjustY Short SubPageY sub 0.5 mul D
/Upper{Handout
{-90 rotate AdjustUX AdjustY translate Scale Scale scale }if}B
/Lower{Handout
{-90 rotate AdjustLX AdjustY translate Scale Scale scale }if}B
%%
%% Used to print handout format text
%%
/LineBuffer 128 string D
/in{72 mul}B /mm{2.8346 mul}B /pt{}B /by{}B
/PageSize{/long E /short E}B
/land{90 rotate 0 short neg translate /High short D /Wide long D}B
/port{/High long D /Wide short D}B
/Offset{/Yoff E /Xoff E Xoff Yoff translate
/High High Yoff sub Yoff sub D /Wide Wide Xoff sub Xoff sub D}B
/LineSize{/Lhigh E /Lwide E
/Lvert High Lhigh div cvi D /Lhori Wide Lwide div cvi D}B
/SetFont{findfont exch /FS E [ .8 FS mul 0 0 FS 0 0 ] makefont setfont}B
/R3{3 1 roll}B
/DC{2 index Lhori 1 sub ge
{NewPage pop pop 0 Lvert false}
{R3 pop Lvert R3 1 add R3}ifelse}B
/DR{1 index 0 le{DC}if exch 1 sub exch}B
/T{exch pop true exch 3 index Lwide mul 3 index Lhigh mul M show}B
/ReadLine {currentfile LineBuffer readline exch /Text E not Text EOF eq or}B
%
% Sheet description
%
/NoteText{/EOF E Handout
{8.5 in by 11 in PageSize land 36 36 Offset
360 pt by 12 pt LineSize 11 /Courier-Bold SetFont
save 0 Lvert false
{ReadLine {exit}{DR Text length 0 ne {Text T}if}ifelse}loop
pop pop pop restore}
{{ReadLine {exit}if}loop}
ifelse restore}B
/Viewgraph {save Upper} B
/EndViewgraph {Check restore} B
/Notes {save Lower (EndNotes) NoteText} B
end def
/PageTop {PageFrame begin save 100 dict begin} bind def
/PageBottom {end restore end} bind def
/DoColor where {pop}{/DoColor false def}ifelse
/Handout where {pop}{/Handout false def}ifelse
% titling data
/talktitle (Just a little PostScript) def
/talkgiver (Randolph J. Herber, herber@fnal.fnal.gov, 1 630 840 2966 CDF PK149O)
def
/talkdept (Computing Division/Operating System Support/CDF Task Force) def
/talkaddr (P.O. Box 500, Mail Stop 234 (WH6W), Batavia, IL 60510) def
/talkcopyr () def
/filenames true def
%%EndProlog
%%Page: Examples12 1
PageTop
Viewgraph
/folio (Examples) def
/filename (examples.12) def
/@ {transform .5 add floor exch .5 add floor exch itransform} bind def
/! {dtransform .5 add floor exch .5 add floor exch idtransform} bind def
1 0 19 Frame
LG 1 Line Y (Many different ways to draw two parallel lines) center
8 line save /showpage {} def 146 Y @ translate .2 dup scale
gsave newpath 0 0 moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
2 setlinewidth
0 0 @ moveto 500 0 ! rlineto stroke
0 500 @ moveto 500 0 ! rlineto stroke
showpage
restore
8 line save /showpage {} def 271 Y @ @ translate .2 dup scale
gsave newpath 0 0 moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
2 setlinewidth
0 0 @ moveto
gsave
0 500 @ moveto 500 0 ! rlineto stroke
grestore
500 0 ! rlineto stroke
showpage
restore
8 line save /showpage {} def 396 Y @ translate .2 dup scale
gsave newpath 0 0 moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
2 setlinewidth
[500] 0 setdash
0 0 @ moveto 500 0 ! rlineto 0 500 ! rlineto -500 0 ! rlineto closepath stroke
showpage
restore
8 line save /showpage {} def 521 Y @ translate .2 dup scale
gsave newpath 0 0 moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
2 setlinewidth
[50] 0 setdash
0 0 @ moveto 500 0 ! rlineto stroke
500 500 @ moveto -500 0 ! rlineto stroke
500 0 @ moveto -500 0 ! rlineto stroke
0 500 @ moveto 500 0 ! rlineto stroke
showpage
restore
16 line save /showpage {} def 146 Y @ translate .2 dup scale
gsave newpath 0 0 moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
2 setlinewidth
[50] 0 setdash
.2 setgray 0 0 @ moveto 500 0 ! rlineto stroke
.4 setgray 500 500 @ moveto -500 0 ! rlineto stroke
.6 setgray 500 0 @ moveto -500 0 ! rlineto stroke
.8 setgray 0 500 @ moveto 500 0 ! rlineto stroke
showpage
restore
16 line save /showpage {} def 271 Y @ translate .2 dup scale
gsave newpath 0 0 @ moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
/B {bind def} dup exec
/E {exch def} B
/Box {/W E /H E
@ moveto W 0 ! rlineto 0 H ! rlineto W neg 0 ! rlineto closepath} B
0 -1 2 500 Box 0 499 2 500 Box fill
showpage
restore
16 line save /showpage {} def 390 Y @ translate .2 dup scale
gsave newpath 0 0 @ moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
/B {bind def} dup exec
/E {exch def} B
/Box {/W E /H E
@ moveto W 0 ! rlineto 0 H ! rlineto W neg 0 ! rlineto closepath} B
0 -2 504 500 Box fill 1 setgray 0 1 498 500 Box fill
showpage
restore
16 line save /showpage {} def 521 Y @ translate .2 dup scale
gsave newpath 0 0 @ moveto 612 0 rlineto 0 792 rlineto -612 0 rlineto closepath
DoColor{0 0 1 setrgbcolor}if stroke grestore
66 146 @ translate
2 setlinewidth
[5] 0 setdash
newpath
500 0 0 0 -500 0 500 500 -500 0 500 0 500 0 0 500
4 {@ moveto ! rlineto} bind repeat
stroke
showpage
restore
{
18 setline TX
l+ C1(These look alike and have vastly different PostScript language codes.)S
} PlaceText
EndViewgraph
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Notes lines should not be longer than 65 characters. %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Notes
==> Q1.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate 2 setlinewidth
0 0 moveto 500 0 rlineto stroke
0 500 moveto 500 0 rlineto stroke
showpage
==> Q2.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate 2 setlinewidth
0 0 moveto gsave 0 500 moveto 500 0 rlineto stroke
grestore 500 0 rlineto stroke
showpage
==> Q3.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate 2 setlinewidth [500] 0 setdash
0 0 moveto 500 0 rlineto 0 500 rlineto -500 0 rlineto
closepath stroke
showpage
==> Q4.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate 2 setlinewidth [50] 0 setdash
0 0 moveto 500 0 rlineto stroke
500 500 moveto -500 0 rlineto stroke
500 0 moveto -500 0 rlineto stroke
0 500 moveto 500 0 rlineto stroke
showpage
==> Q5.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate 2 setlinewidth [50] 0 setdash
.2 setgray 0 0 moveto 500 0 rlineto stroke
.4 setgray 500 500 moveto -500 0 rlineto stroke
.6 setgray 500 0 moveto -500 0 rlineto stroke
.8 setgray 0 500 moveto 500 0 rlineto stroke
showpage
==> Q6.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate /B {bind def} dup exec /E {exch def} B
/Box {/W E /H E moveto
W 0 rlineto 0 H rlineto W neg 0 rlineto closepath} B
0 -1 2 500 Box 0 499 2 500 Box fill
showpage
==> Q7.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate /B {bind def} dup exec /E {exch def} B
/Box {/W E /H E moveto
W 0 rlineto 0 H rlineto W neg 0 rlineto closepath} B
0 -1 502 500 Box fill 1 setgray 0 1 498 500 Box fill
showpage
==> Q8.ps <==
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 55 145 557 647
%%Pages: 1
%%EndComments
66 146 translate 2 setlinewidth [5] 0 setdash newpath
500 0 0 0 -500 0 500 500 -500 0 500 0 500 0 0 500
4 {moveto rlineto} bind repeat stroke
showpage
EndNotes
showpage
PageBottom
%%EOF

275
resource/postscript/maze.ps Executable file
View file

@ -0,0 +1,275 @@
%!PS
%%Pages: 1
%%EndComments
% Yet Another Maze Maker
% Version 2
% Written by Peter Sorotokin, 1996-1998
% This program is in the public domain.
% Note: do not send this job to the printer until you know
% how to cancel it (it may take a LOT of time on slow printer;
% it takes couple minutes on my LaserJet 4).
%%BeginSetup
% put your sizes here:
/width 25 def
/height 25 def
% seed number here:
0 srand % put your seed number instead of 0 (normally not required)
systemdict /realtime known { realtime srand } if
% initialization
/size width height mul def
/zone size array def
/zsize size array def
/vert width 1 add array def
/hor height 1 add array def
/w1 width 1 sub def
/h1 height 1 sub def
0 1 size 1 sub { dup zsize exch 1 put zone exch dup put } bind for
0 1 width { vert exch height string 0 1 h1
{ 1 index exch 255 put } for put } bind for
0 1 height { hor exch width string 0 1 w1
{ 1 index exch 255 put } for put } bind for
% define subroutines
/db { dup 20 string cvs = } bind def
/find_set { { zone 1 index get dup 3 1 roll eq {exit} if } loop} bind def
/merge_sets {
2 copy zsize exch get
exch zsize exch get 2 copy gt
3 1 roll add exch
{ zsize 2 index 3 -1 roll put
zone 3 1 roll put }
{ zsize 3 index 3 -1 roll put
zone 3 1 roll exch put }
ifelse } bind def
%%EndSetup
%%Page: maze 1
% building
size 1 sub
{
{
rand 2 mod 0 eq
{
rand height mod
rand w1 mod 2 copy
height mul add
dup height add
find_set exch find_set
2 copy eq
{
pop pop pop pop
}
{
merge_sets vert exch 1 add get exch 0 put exit
}
ifelse
}
{
rand h1 mod
rand width mod 2 copy
height mul add
dup 1 add
find_set exch find_set
2 copy eq
{
pop pop pop pop
}
{
merge_sets exch hor exch 1 add get exch 0 put exit
}
ifelse
}
ifelse
}
loop
} bind repeat
% make entrance and exit
vert 0 get rand height mod 0 put
vert width get rand height mod 0 put
% setup output
clippath pathbbox
2 index sub exch
3 index sub exch
4 2 roll translate
2 copy height 4 add div exch width 4 add div
2 copy gt {exch} if pop /myscale exch def
myscale height mul sub 2 div exch
myscale width mul sub 2 div exch
translate
myscale myscale scale
0.05 setlinewidth
newpath
% render the maze
0 1 width { dup 0 moveto vert exch get 0 1 height 1 sub
{ 1 index exch get 0 eq 0 1 3 -1 roll { rmoveto } { rlineto } ifelse }
for pop } bind for
0 1 height { dup 0 exch moveto hor exch get 0 1 width 1 sub
{ 1 index exch get 0 eq 1 0 3 -1 roll { rmoveto } { rlineto } ifelse }
for pop } bind for
stroke
stroke
% Quick hack to solve the maze.
% This part written by Christian Lehner.
clear
/NORTH 1 def
/WEST 2 def
/SOUTH 4 def
/EAST 8 def
/CRUMB 16 def
/find_door {% column => index
dup 0 1 3 -1 roll length 1 sub {
2 copy get 0 eq {
exch pop
exit
} {
pop
} ifelse
} for
} bind def
/mentrance vert 0 get find_door def
/mexit vert width get find_door def
/maze [height {[width {0} repeat]} repeat] def
/mget {% row col => int
maze 3 -1 roll get exch get
} bind def
/mset {% row col int => -
maze 4 -1 roll get 3 -2 roll put
} bind def
/initmaze {
0 1 height 1 sub {/row exch def
/mrow maze row get def
0 1 width 1 sub {/col exch def
% north
hor row 1 add get col get 0 eq {
mrow col 2 copy get //NORTH or put
} if
% west
vert col get row get 0 eq {
mrow col 2 copy get //WEST or put
} if
% south
hor row get col get 0 eq {
mrow col 2 copy get //SOUTH or put
} if
% east
vert col 1 add get row get 0 eq {
mrow col 2 copy get //EAST or put
} if
} for
} for
} bind def
/step {% row col side => row' col'
/side exch def
/col exch def
/row exch def
side //NORTH eq {
row 1 add col
} {
side //WEST eq {
row col 1 sub
} {
side //SOUTH eq {
row 1 sub col
} {
side //EAST eq {
row col 1 add
} {
(step: bad side ) print side ==
} ifelse
} ifelse
} ifelse
} ifelse
} bind def
/done false def
/escape {% row col => -
/col exch def
/row exch def
row mexit eq col width 1 sub eq and {
(done)==
row col
/done true store
} {
row col 2 copy mget //CRUMB or mset
row col
[//NORTH //WEST //SOUTH //EAST] {/side exch def
done {exit} if
2 copy mget /val exch def
val side and 0 ne {
2 copy side step 2 copy
mget /val exch def
val //CRUMB and 0 eq {
escape
} {
pop pop
} ifelse
} if
} forall
done not {
pop pop
} if
} ifelse
} bind def
/solve {
% close the entrance
vert 0 get mentrance 1 put
initmaze
% start the escape
/path [mentrance -1 mentrance 0 escape 2 copy 1 add] def
% draw the path
.5 setgray
.5 .5 translate
path 1 get path 0 get moveto
2 2 path length 1 sub {/i exch def
path i 1 add get path i get lineto
} for
stroke
showpage
} bind def
% eject the page
copypage solve
%%EOF

View file

@ -0,0 +1,91 @@
%!
%% Elizabeth D. Zwicky
%% zwicky@erg.sri.com
%% multiflake
/newflake
{/seed usertime def
seed srand
/strokecolor [rand 99 mod 100 div
rand 99 mod 100 div
100 rand 22 mod sub 100 div] def
/fillcolor [rand 99 mod 100 div
100 rand 22 mod sub 100 div
rand 99 mod 100 div] def
/eofillcolor [rand 99 mod 100 div
rand 22 mod 100 div
100 rand 22 mod sub 100 div] def
/colorfill {fillcolor aload pop setrgbcolor fill } def
/colorstroke {strokecolor aload pop setrgbcolor stroke } def
/eocolorfill {eofillcolor aload pop setrgbcolor eofill } def
/arm {0 0 moveto
5 {3 {x y x y x y curveto} repeat} repeat
seed srand
0 0 moveto
5 {3 {x neg y x neg y x neg y curveto} repeat} repeat
seed srand
} def
newpath
0 0 moveto boxsize 0 rlineto 0 boxsize rlineto boxsize neg 0 rlineto
0 0 lineto
rand 99 mod 100 div
100 rand 22 mod sub 100 div
100 rand 22 mod sub 100 div
sethsbcolor fill
seed srand
boxsize 2 div boxsize 2 div translate
%% If the device you are using can handle complex fills, replace the
%% next three lines with:
%%
6 {arm 60 rotate} repeat
gsave colorfill grestore gsave eocolorfill grestore colorstroke
%%
%% This will be not only faster, but prettier. On a LaserWriter or a
%% Tektronix Phaser II PS it gives a limitcheck.
%% 6 {arm 60 rotate colorfill} repeat
%% 6 {arm 60 rotate eocolorfill} repeat
%% 6 {arm 60 rotate} repeat colorstroke
} def
1 setlinewidth
clippath [pathbbox]== pathbbox /ury exch def /urx exch def /lly exch def /llx exch def
/minsize 250 def
/pagewidth urx llx sub def
/pageheight ury lly sub def
/inwidth pagewidth minsize div def
/inheight pageheight minsize div def
/boxsize
inwidth inheight gt
{pagewidth inwidth truncate div}
{pageheight inheight truncate div}
ifelse
def
/inwidth pagewidth boxsize div cvi def
/inheight pageheight boxsize div cvi def
/x {rand 70 mod abs} def
/y {rand 120 mod abs} def
llx lly translate
inheight dup == {
inwidth {
gsave
(NEWFLAKE)==
newflake
grestore
boxsize 0 translate
} repeat
boxsize inwidth mul neg boxsize translate
} repeat
showpage

View file

@ -0,0 +1,50 @@
%!
% Example of rotation... draws 36 lines in a circular pattern
/box {
newpath
moveto
72 0 rlineto
0 72 rlineto
-72 0 rlineto
closepath
} def
% Specify font for text labels
/Helvetica findfont 40 scalefont setfont
gsave
40 40 translate % Set origin to (40, 40)
0 0 box stroke % Draw box at new origin...
77 0 moveto
(Translated) show % and label
grestore
gsave
100 150 translate % Translate origin to (100, 150)
30 rotate % Rotate counter-clockwise by 30 degrees
0 0 box stroke % Draw box...
75 0 moveto
(Translated & Rotated) show % and label
grestore
gsave
40 300 translate % Translate to (40, 300)
0.5 1 scale % Reduce x coord by 1/2, y coord left alone
0 0 box stroke % Draw box...
75 0 moveto
(Translated & Squished) show % and label
grestore
gsave
300 300 translate % Set origin to (300, 300)
45 rotate % Rotate coordinates by 45 degrees
0.5 1 scale % Scale coordinates
0 0 box stroke % Draw box
75 0 moveto
(Everything) show
grestore
showpage

2733
resource/postscript/tiger.ps Normal file

File diff suppressed because it is too large Load diff

588
resource/postscript/vasarely.ps Executable file
View file

@ -0,0 +1,588 @@
%!
% vasarely
% Elizabeth D. Zwicky
% zwicky@sgi.com
/vasarelysave save def % prevent residual side effects
%
% Inspired by Vasarely's experiments with tilting circles and squares
% (for instance "Tlinko" and "Betelgeuse"
%% circles
/part { circle } def /nnrand false def
%% squares
% /part { ngon } def /nn 4 def /nnrand false def
%% random polygons
% /part { ngon } def /nnrand true def
%% random stars (not my favorite on this program)
% /part { nstar } def /nnrand true def
%% tilt the base shape a random amount?
/twist false def
% /twist true def
/rainbow false def
%% To make rainbows
% /rainbow true def
%% Set this to 1 to go through a full range of colors
/rainrange .25 def
% number of different designs per page
/inheight 2 def
/inwidth 2 def
% number of repeats in a design
/xtimes 10 def
/ytimes 16 def
%% This sets the relationship between the two hues: comptwo is maximum contrast
/colorway {comptwo} def
%% monochrome comptwo harmtwo harmfour freecolor compthree closeharm
%% origcolor
%% This sets the brightness and saturation of the colors; vivid makes
%% them both bright
/colorfam {vivid} def
%% vivid jewel intense medium pastel free orig contrast
%% medjewel medvivid vivpastel medpastel
%% Only experts below this point!
10 srand
/seed rand def
/starcompensate false def
/constroke 1 def
/circle {
/radius radius 1.33 mul def
currentpoint /herey exch def /herex exch def
herex herey radius 0 360 arc
} def
/ngon{ % polygon of n sides, n determined by nn
nside 2 div radius rmoveto
nn cvi {
nside neg 0 rlineto
360 360 nn div sub neg rotate
} repeat
closepath
} def
/nstar{ % star of n points, n determined by nstarslider
/radius radius 1.33 mul def
currentpoint /herey exch def /herex exch def
0 radius rmoveto
90 nstarangle 2 div add neg rotate
nn cvi {nstarside 0 rlineto
180 180 nstarangle 2 mul sub sub neg rotate
nstarside 0 rlineto
180 180 360 nn div sub nstarangle 2 mul sub sub rotate
} repeat
90 nstarangle 2 div add rotate
closepath
} def
/nstarangle {180 360 nn div sub 3 div} def
/nstarside {
2
radius
1
180 nn div
sin
div
div
mul
nstarangle sin
mul
180
nstarangle 2 mul
sub
sin
div
} def
/nside {
2
radius
360 nn div 2 div tan
mul
mul
} def
/tan { /alpha exch def
alpha sin
1 alpha sin dup mul sub sqrt
div
} def
/pastel {
/backbright high def
/backsat medlow def
/fillbright high def
/fillsat medlow def
/eobright high def
/eosat medlow def
constroke 0 eq {
/strokebright high def
/strokesat medlow def
}
{
/strokebright low def
/strokesat high def
} ifelse
} def
/jewel {
/fillbright med def
/fillsat high def
/backbright med def
/backsat high def
/eobright med def
/eosat high def
constroke 0 eq {
/strokebright medlow def
/strokesat high def
}
{
/strokebright high def
/strokesat medlow def
} ifelse
} def
/vivid {
/fillsat 1 def
/fillbright high def
/eosat 1 def
/eobright high def
/backsat 1 def
/backbright high def
constroke 0 eq {
/strokesat 1 def
/strokebright high def
}
{
/strokesat high def
/strokebright medlow def
} ifelse
} def
/free {
/fillsat anyrand def
/fillbright anyrand def
/eosat anyrand def
/eobright anyrand def
/backsat anyrand def
/backbright anyrand def
/strokesat anyrand def
/strokebright anyrand def
} def
/contrast {
/sat medhigh def
/bright rand 2 mod 0 eq {medhigh} {medlow} ifelse def
/backsat sat def
/backbright bright def
/eosat sat def
/eobright 1 bright sub def
/fillsat sat def
/fillbright bright def
/strokebright rand 2 mod def
/strokesat rand 2 mod def
} def
/medium {
/backsat med def
/backbright med def
/eosat med def
/eobright med def
/fillsat med def
/fillbright med def
/strokebright med def
/strokesat med def
} def
/intense {
/backsat high def
/backbright med def
/eosat high def
/eobright high def
/fillsat high def
/fillbright med def
/strokebright high def
/strokesat high def
} def
/orig {
/backsat rand 99 mod 55 add 100 div def
/backbright rand 99 mod 35 add 100 div def
/eosat rand 77 mod 22 add 100 div def
/eobright 90 rand 75 mod sub 15 add 100 div def
/fillsat 100 rand 90 mod sub 100 div def
/fillbright 100 rand 45 mod sub 20 add 100 div def
/strokebright 100 rand 55 mod sub 100 div def
/strokesat 100 rand 85 mod sub 100 div def
} def
/medjewel {
/alt rand 2 mod def
/backsat alt 0 eq {high} { med} ifelse def
/fillsat alt 0 eq {med} {high} ifelse def
/eosat alt 0 eq {high} {med} ifelse def
/backbright med def
/fillbright med def
/eobright med def
constroke 0 eq {
/strokebright medlow def
/strokesat high def
}
{
/strokebright high def
/strokesat medlow def
} ifelse
} def
/medvivid {
/alt rand 2 mod def
/backsat alt 0 eq {1} { med} ifelse def
/fillsat alt 0 eq {med} {1} ifelse def
/eosat alt 0 eq {1} {med} ifelse def
/backbright alt 0 eq {high} {med} ifelse def
/eobright alt 0 eq {high} {med} ifelse def
/fillbright alt 0 eq {med} {high} ifelse def
constroke 0 eq {
/strokesat 1 def
/strokebright high def
}
{
/strokesat high def
/strokebright medlow def
} ifelse
} def
/vivpastel {
/backlight rand 2 mod def
/backsat backlight 0 eq {medlow} {1} ifelse def
/eosat backlight 0 eq {medlow} {1} ifelse def
/fillsat backlight 0 eq {1} {medlow} ifelse def
/fillbright high def
/backbright high def
/eobright high def
constroke 0 eq {
/strokesat 1 def
/strokebright high def
}
{
/strokesat high def
/strokebright medlow def
} ifelse
} def
/medpastel {
/alt rand 2 mod def
/backsat alt 0 eq {medlow} {med} ifelse def
/eosat alt 0 eq {medlow} {med} ifelse def
/fillsat alt 0 eq {med} {medlow} ifelse def
/fillbright alt 0 eq { high } {med} ifelse def
/backbright alt 0 eq {med} { high } ifelse def
/eobright alt 0 eq {med} { high } ifelse def
constroke 0 eq {
/strokebright high def
/strokesat medlow def
}
{
/strokebright low def
/strokesat high def
} ifelse
} def
/maxcon {
rand 2 mod 1 eq {
/backsat 0 def
/backbright 0 def
/eosat 0 def
/eobright 0 def
/fillsat 0 def
/fillbright 1 def
/strokebright 1 def
/strokesat 0 def
}
{
/backsat 0 def
/backbright 1 def
/eosat 0 def
/eobright 1 def
/fillsat 0 def
/fillbright 0 def
/strokebright 0 def
/strokesat 0 def
}
ifelse
} def
/monochrome {
/fillhue hue closevary def
/strokehue hue closevary def
/eohue hue closevary def
/backhue hue def
} def
/blackandwhite {
/fillhue 1 def
/eohue 0 def
/backhue 0 def
/strokehue 1 def
} def
/freecolor {
/fillhue anyrand def
/strokehue anyrand def
/eohue anyrand def
/backhue anyrand def
} def
/purple {
/fillhue rand 15 mod 80 add 100 div def
/backhue rand 15 mod 80 add 100 div def
/strokehue rand 15 mod 80 add 100 div def
/eohue rand 15 mod 80 add 100 div def
/backhue rand 15 mod 80 add 100 div def
} def
/comptwo {
/fillhue hue closevary def
/strokehue hue .5 add dup 1 gt {1 sub} if def
/backhue strokehue def
/eohue strokehue closevary def
} def
/compthree {
/backhue hue def
/strokehue hue 1 3 div add dup 1 gt {1 sub} if closevary def
/fillhue strokehue closevary def
/eohue hue 1 3 div sub dup 1 lt { 1 add} if closevary def
} def
/origcolor {
/backhue hue def
/strokehue
hue 1000 mul cvi 3 mod dup 1 eq
{hue closevary}
{2 eq
{rand 999 mod 1000 div}
{hue .5 add dup 1 gt {1 sub} if }
ifelse
}
ifelse def
/fillhue hue 1000 mul cvi 3 mod dup 1 eq
{hue closevary}
{2 eq
{rand 999 mod 1000 div}
{hue .5 add dup 1 gt {1 sub} if }
ifelse
}
ifelse
def
/eohue hue 1000 mul cvi 2 mod 1 eq
{hue closevary}
{rand 999 mod 1000 div}
ifelse def
} def
/harmtwo {
/fillhue hue closevary def
/backhue hue def
/strokehue hue .2 add dup 1 gt {1 sub} if closevary def
/eohue strokehue closevary def
} def
/harmfour {
/fillhue hue closevary def
/backhue hue .1 add dup 1 gt {1 sub} if def
/strokehue hue .2 add dup 1 gt {1 sub} if closevary def
/eohue hue .1 sub dup 1 lt {1 add} if closevary def
} def
/closeharm {
/fillhue hue def
/backhue hue .05 add dup 1 gt {1 sub} if closevary def
/strokehue hue .1 add dup 1 gt {1 sub} if closevary def
/eohue hue .05 sub dup 0 lt {1 add} if closevary def
} def
/high {100 rand 25 mod sub 100 div } def
/med { rand 33 mod 33 add 100 div } def
/medhigh {100 rand 50 mod sub 100 div } def
/medlow {rand 50 mod 100 div } def
/low { rand 25 mod 100 div} def
/anyrand { rand 100 mod 100 div } def
/closevary {rand 70 mod rand 100 mod sub 1000 div add} def
%rainbow
% {/colorfill {fillhue 1 1 sethsbcolor fill} def}
/colorfill {fillhue fillsat fillbright sethsbcolor fill } def
%ifelse
/colorstroke {strokehue strokesat strokebright sethsbcolor stroke } def
/eocolorfill {eohue eosat eobright sethsbcolor eofill } def
/backfill{ backhue backsat backbright sethsbcolor fill } def
/xstep { xrange xtimes 1 sub div x 1 sub mul } def
/ystep { yrange ytimes 1 sub div y 1 sub mul} def
/functionarray [
{sin abs}
{sin }
{cos }
{cos abs}
{sin dup mul }
{cos dup mul }
{sin abs sqrt }
{cos abs sqrt }
] def
/range { /top exch def /bottom exch def /number exch def
% number is between -1 and 1
/rangesize top bottom sub def
number 1 add 2 div
% number is now between 0 and 1
rangesize mul
bottom add
} def
/drawone {
/radius
width height lt {width 3 div} {height 3 div} ifelse
def
seed srand
0 0 moveto
/origmatrix [ 0 0 0 0 0 0 ] currentmatrix def
[ % xstep function ystep function2 add 0.4 1.3 range
1
ystep function xstep function add -0.25 0.25 range
ystep function3 xstep function2 add -0.5 0.5 range
% xstep function4 ystep function mul 0.4 1.3 range
1
0
0
]
concat
twist {twistdeg rotate} if
part colorfill
origmatrix setmatrix
rainbow
{/fillhue fillhue rainrange xtimes ytimes mul div add dup 1 gt {1 sub} if def}
if
} def
/notdrawone {
seed srand
twist {/twistdeg rand 360 mod def} if
nnrand {/nn rand 6 mod 3 add def} if
/x1 rand width 3 div cvi mod width 8 div add def
/y1 rand height 3 div cvi mod height 8 div add def
rand 3 mod dup 1 eq
{pop /x2 rand width 2 div cvi mod def
/y2 rand height 2 div cvi mod def}
{ 2 eq
{/x2 y1 def /y2 x1 def}
{/x2 y1 width mul height div def /y2 x1 height mul width div def}
ifelse
}
ifelse
/radius width height gt {width} {height} ifelse 2.5 div def
/stripe rand width 10 div cvi mod 2 add def
starcompensate { /stripe stripe 2 mul def /radius radius 10 nn div mul def } if
/i 1 def
/repeats radius stripe div cvi 1 add def
/nnincr 1 def
repeats {
colorvary {colorfam colorway} if
/i i 1 add def
/radius radius stripe sub def
} repeat
} def
/page {
clippath pathbbox /ury exch def /urx exch def /lly exch def /llx exch
def
/pagewidth urx llx sub 36 72 mul min def
/pageheight ury lly sub 36 72 mul min def
0 0 moveto
llx lly translate
/outerwidth
pagewidth inwidth div
def
/outerheight
pageheight inheight div
def
/width
outerwidth xtimes div
def
/height
outerheight ytimes div
def
/size
width height gt {width} {height} ifelse
def
inwidth {
inheight {
/seed rand def
/hue rand 999 mod 1000 div def
colorway colorfam
/x 1 def /y 1 def
nnrand {/nn rand 6 mod 3 add def} if
/twistdeg rand 360 mod def
/function functionarray rand functionarray length mod get def
/function2 functionarray rand functionarray length mod get def
/function3 functionarray rand functionarray length mod get def
/function4 functionarray rand functionarray length mod get def
/xrange [ 90 180 270 360 180 360 ] rand 6 mod get def
/yrange [ 90 180 270 360 180 360 ] rand 6 mod get def
initclip
newpath
0 0 moveto
outerwidth 0 rlineto
0 outerheight rlineto
outerwidth neg 0 rlineto
backfill
xtimes {
ytimes{
/y y 1 add def
width 2 div height 2 div translate
drawone
width 2 div neg height 2 div neg translate
0 height translate
} repeat
/y 1 def
/x x 1 add def
width height ytimes mul neg translate
} repeat
width xtimes mul neg outerheight translate
} repeat
outerwidth outerheight inheight mul neg translate
} repeat
} def
page showpage
clear cleardictstack
vasarelysave restore

2743
resource/postscript/vw.ps Normal file

File diff suppressed because it is too large Load diff

5043
resource/postscript/whitepaper.ps Executable file

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show more