10ms on win32 tiger
17
.project
Normal 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
|
@ -0,0 +1 @@
|
||||||
|
Laurent Le Goff
|
18
LICENSE
Normal 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.
|
30
Makefile
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
#include $(GOROOT)/src/Make.inc
|
||||||
|
|
||||||
|
all: install
|
||||||
|
|
||||||
|
install:
|
||||||
|
cd draw2d && make install
|
||||||
|
cd draw2dgl && make install
|
||||||
|
cd postscript && make install
|
||||||
|
# cd wingui && make install
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cd draw2d && make clean
|
||||||
|
cd draw2dgl && make clean
|
||||||
|
cd postscript && make clean
|
||||||
|
cd cmd && make clean
|
||||||
|
# cd wingui && make clean
|
||||||
|
|
||||||
|
nuke:
|
||||||
|
cd draw2d && make nuke
|
||||||
|
cd draw2dgl && make nuke
|
||||||
|
cd postscript && make nuke
|
||||||
|
# cd wingui && make nuke
|
||||||
|
|
||||||
|
command:
|
||||||
|
cd cmd && make
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
gofmt -w .
|
||||||
|
|
35
README
Normal 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
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.inc
|
||||||
|
|
||||||
|
TARG=gettingStarted testdraw2d testX11draw testandroid testgopher testimage testpostscript draw2dgl
|
||||||
|
|
||||||
|
OFILES=$(TARG:%=%.$O)
|
||||||
|
|
||||||
|
all: $(TARG)
|
||||||
|
|
||||||
|
$(TARG): %: %.$O
|
||||||
|
$(LD) -o $@ $<
|
||||||
|
|
||||||
|
$(OFILES): %.$O: %.go Makefile
|
||||||
|
$(GC) -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.[$(OS)] $(TARG) $(CLEANFILES)
|
123
cmd/draw2dgl.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// Ported from GLUT's samples. Original copyright below applies.
|
||||||
|
|
||||||
|
/* Copyright (c) Mark J. Kilgard, 1996. */
|
||||||
|
|
||||||
|
/* This program is freely distributable without licensing fees
|
||||||
|
and is provided without guarantee or warrantee expressed or
|
||||||
|
implied. This program is -not- in the public domain. */
|
||||||
|
|
||||||
|
/* This program is a response to a question posed by Gil Colgate
|
||||||
|
<gcolgate@sirius.com> about how lengthy a program is required using
|
||||||
|
OpenGL compared to using Direct3D immediate mode to "draw a
|
||||||
|
triangle at screen coordinates 0,0, to 200,200 to 20,200, and I
|
||||||
|
want it to be blue at the top vertex, red at the left vertex, and
|
||||||
|
green at the right vertex". I'm not sure how long the Direct3D
|
||||||
|
program is; Gil has used Direct3D and his guess is "about 3000
|
||||||
|
lines of code". */
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"math"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"gl"
|
||||||
|
"glut"
|
||||||
|
"image"
|
||||||
|
"draw2d.googlecode.com/hg/draw2d"
|
||||||
|
"draw2d.googlecode.com/hg/draw2dgl"
|
||||||
|
"draw2d.googlecode.com/hg/postscript"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var postscriptContent string
|
||||||
|
|
||||||
|
func TestDrawCubicCurve(gc draw2d.GraphicContext) {
|
||||||
|
// 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.SetStrokeColor(image.NRGBAColor{0, 0, 0, 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, 0x99})
|
||||||
|
|
||||||
|
gc.SetLineWidth(6)
|
||||||
|
// draw segment of curve
|
||||||
|
gc.MoveTo(x, y)
|
||||||
|
gc.LineTo(x1, y1)
|
||||||
|
gc.MoveTo(x2, y2)
|
||||||
|
gc.LineTo(x3, y3)
|
||||||
|
gc.Stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
width, height int
|
||||||
|
rotate int
|
||||||
|
)
|
||||||
|
|
||||||
|
func reshape(w, h int) {
|
||||||
|
/* Because Gil specified "screen coordinates" (presumably with an
|
||||||
|
upper-left origin), this short bit of code sets up the coordinate
|
||||||
|
system to correspond to actual window coodrinates. This code
|
||||||
|
wouldn't be required if you chose a (more typical in 3D) abstract
|
||||||
|
coordinate system. */
|
||||||
|
gl.ClearColor(1, 1, 1, 1)
|
||||||
|
//fmt.Println(gl.GetString(gl.EXTENSIONS))
|
||||||
|
gl.Viewport(0, 0, w, h) /* Establish viewing area to cover entire window. */
|
||||||
|
gl.MatrixMode(gl.PROJECTION) /* Start modifying the projection matrix. */
|
||||||
|
gl.LoadIdentity() /* Reset project matrix. */
|
||||||
|
gl.Ortho(0, float64(w), 0, float64(h), -1, 1) /* Map abstract coords directly to window coords. */
|
||||||
|
gl.Scalef(1, -1, 1) /* Invert Y axis so increasing Y goes down. */
|
||||||
|
gl.Translatef(0, float32(-h), 0) /* Shift origin up to upper-left corner. */
|
||||||
|
gl.Enable(gl.BLEND)
|
||||||
|
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||||
|
|
||||||
|
width, height = w, h
|
||||||
|
}
|
||||||
|
|
||||||
|
func display() {
|
||||||
|
|
||||||
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||||
|
gl.LineWidth(1)
|
||||||
|
gc := draw2dgl.NewGraphicContext(width, height)
|
||||||
|
|
||||||
|
gc.Translate(380, 400)
|
||||||
|
gc.Scale(1, -1)
|
||||||
|
rotate = (rotate + 1) % 360
|
||||||
|
gc.Rotate(float64(rotate) * math.Pi / 180)
|
||||||
|
gc.Translate(-380, -400)
|
||||||
|
interpreter := postscript.NewInterpreter(gc)
|
||||||
|
reader := strings.NewReader(postscriptContent)
|
||||||
|
lastTime := time.Nanoseconds()
|
||||||
|
interpreter.Execute(reader)
|
||||||
|
dt := time.Nanoseconds() - lastTime
|
||||||
|
log.Printf("Redraw in : %f ms\n", float64(dt)*1e-6)
|
||||||
|
gl.Flush() /* Single buffered, so needs a flush. */
|
||||||
|
glut.PostRedisplay()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
src, err := os.OpenFile("../resource/postscript/tiger.ps", 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("can't find postscript file.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
bytes, err := ioutil.ReadAll(src)
|
||||||
|
postscriptContent = string(bytes)
|
||||||
|
glut.Init()
|
||||||
|
glut.InitWindowSize(800, 800)
|
||||||
|
glut.CreateWindow("single triangle")
|
||||||
|
|
||||||
|
glut.DisplayFunc(display)
|
||||||
|
glut.ReshapeFunc(reshape)
|
||||||
|
glut.MainLoop()
|
||||||
|
}
|
46
cmd/gettingStarted.go
Normal 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.Create(filePath)
|
||||||
|
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)
|
||||||
|
}
|
235
cmd/testWalkDraw.go
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
// Copyright 2011 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
"image"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"draw2d.googlecode.com/hg/draw2d"
|
||||||
|
"draw2d.googlecode.com/hg/postscript"
|
||||||
|
"draw2d.googlecode.com/hg/wingui"
|
||||||
|
)
|
||||||
|
|
||||||
|
// some help functions
|
||||||
|
|
||||||
|
func abortf(format string, a ...interface{}) {
|
||||||
|
fmt.Fprintf(os.Stdout, format, a...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func abortErrNo(funcname string, err int) {
|
||||||
|
abortf("%s failed: %d %s\n", funcname, err, syscall.Errstr(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// global vars
|
||||||
|
|
||||||
|
|
||||||
|
func TestDrawCubicCurve(gc draw2d.GraphicContext) {
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
mh uint32
|
||||||
|
wndBufferHeader uint32
|
||||||
|
wndBuffer wingui.BITMAP
|
||||||
|
hdcWndBuffer uint32
|
||||||
|
ppvBits *image.RGBAColor
|
||||||
|
backBuffer *image.RGBA
|
||||||
|
postscriptContent string
|
||||||
|
)
|
||||||
|
|
||||||
|
// WinProc called by windows to notify us of all windows events we might be interested in.
|
||||||
|
func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
|
||||||
|
var rc int32
|
||||||
|
|
||||||
|
switch msg {
|
||||||
|
case wingui.WM_CREATE:
|
||||||
|
hdc := wingui.GetDC(hwnd)
|
||||||
|
hdcWndBuffer = wingui.CreateCompatibleDC(hdc)
|
||||||
|
wndBufferHeader = wingui.CreateCompatibleBitmap(hdc, 600, 800)
|
||||||
|
wingui.GetObject(wndBufferHeader, unsafe.Sizeof(wndBuffer), uintptr(unsafe.Pointer(&wndBuffer)))
|
||||||
|
wingui.SelectObject(hdcWndBuffer, wndBufferHeader)
|
||||||
|
|
||||||
|
var bmp_header wingui.BITMAPINFOHEADER
|
||||||
|
bmp_header.Size = uint32(unsafe.Sizeof(bmp_header))
|
||||||
|
bmp_header.Width = 600
|
||||||
|
bmp_header.Height = 800
|
||||||
|
bmp_header.SizeImage = 0 // the api says this must be 0 for BI_RGB images
|
||||||
|
bmp_header.Compression = wingui.BI_RGB
|
||||||
|
bmp_header.BitCount = 32
|
||||||
|
bmp_header.Planes = 1
|
||||||
|
bmp_header.XPelsPerMeter = 0
|
||||||
|
bmp_header.YPelsPerMeter = 0
|
||||||
|
bmp_header.ClrUsed = 0
|
||||||
|
bmp_header.ClrImportant = 0
|
||||||
|
//bitmap info
|
||||||
|
var bmpinfo wingui.BITMAPINFO
|
||||||
|
bmpinfo.Colors[0].Blue = 0
|
||||||
|
bmpinfo.Colors[0].Green = 0
|
||||||
|
bmpinfo.Colors[0].Red = 0
|
||||||
|
bmpinfo.Colors[0].Reserved = 0
|
||||||
|
bmpinfo.Header = bmp_header
|
||||||
|
wndBufferHeader = wingui.CreateDIBSection(hdc, &bmpinfo, wingui.DIB_RGB_COLORS, uintptr(unsafe.Pointer(&ppvBits)), 0, 0)
|
||||||
|
wingui.GetObject(wndBufferHeader, unsafe.Sizeof(wndBufferHeader), uintptr(unsafe.Pointer(&wndBuffer)))
|
||||||
|
hdcWndBuffer = wingui.CreateCompatibleDC(hdc)
|
||||||
|
wingui.SelectObject(hdcWndBuffer, wndBufferHeader)
|
||||||
|
|
||||||
|
pixel := (*[600 * 800]image.RGBAColor)(unsafe.Pointer(ppvBits))
|
||||||
|
pixelSlice := pixel[:]
|
||||||
|
backBuffer = &image.RGBA{pixelSlice, 600, image.Rect(0, 0, 600, 800)}
|
||||||
|
fmt.Println("Create windows")
|
||||||
|
rc = wingui.DefWindowProc(hwnd, msg, wparam, lparam)
|
||||||
|
case wingui.WM_COMMAND:
|
||||||
|
switch uint32(lparam) {
|
||||||
|
default:
|
||||||
|
rc = wingui.DefWindowProc(hwnd, msg, wparam, lparam)
|
||||||
|
}
|
||||||
|
case wingui.WM_PAINT:
|
||||||
|
var ps wingui.PAINTSTRUCT
|
||||||
|
lastTime := time.Nanoseconds()
|
||||||
|
hdc := wingui.BeginPaint(hwnd, &ps)
|
||||||
|
gc := draw2d.NewGraphicContext(backBuffer)
|
||||||
|
gc.SetFillColor(image.RGBAColor{0xFF, 0xFF, 0xFF, 0xFF})
|
||||||
|
// gc.Clear()
|
||||||
|
gc.Save()
|
||||||
|
//gc.Translate(0, -380)
|
||||||
|
interpreter := postscript.NewInterpreter(gc)
|
||||||
|
reader := strings.NewReader(postscriptContent)
|
||||||
|
interpreter.Execute(reader)
|
||||||
|
dt := time.Nanoseconds() - lastTime
|
||||||
|
gc.Restore()
|
||||||
|
// back buf in
|
||||||
|
|
||||||
|
wingui.BitBlt(hdc, 0, 0, int(wndBuffer.Width), int(wndBuffer.Height), hdcWndBuffer, 0, 0, wingui.SRCCOPY)
|
||||||
|
wingui.EndPaint(hwnd, &ps)
|
||||||
|
rc = wingui.DefWindowProc(hwnd, msg, wparam, lparam)
|
||||||
|
fmt.Printf("Redraw in : %f ms\n", float64(dt)*1e-6)
|
||||||
|
case wingui.WM_CLOSE:
|
||||||
|
wingui.DestroyWindow(hwnd)
|
||||||
|
case wingui.WM_DESTROY:
|
||||||
|
wingui.PostQuitMessage(0)
|
||||||
|
default:
|
||||||
|
rc = wingui.DefWindowProc(hwnd, msg, wparam, lparam)
|
||||||
|
}
|
||||||
|
return uintptr(rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rungui() int {
|
||||||
|
var e int
|
||||||
|
|
||||||
|
// GetModuleHandle
|
||||||
|
mh, e = wingui.GetModuleHandle(nil)
|
||||||
|
if e != 0 {
|
||||||
|
abortErrNo("GetModuleHandle", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get icon we're going to use.
|
||||||
|
myicon, e := wingui.LoadIcon(0, wingui.IDI_APPLICATION)
|
||||||
|
if e != 0 {
|
||||||
|
abortErrNo("LoadIcon", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get cursor we're going to use.
|
||||||
|
mycursor, e := wingui.LoadCursor(0, wingui.IDC_ARROW)
|
||||||
|
if e != 0 {
|
||||||
|
abortErrNo("LoadCursor", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create callback
|
||||||
|
wproc := syscall.NewCallback(WndProc)
|
||||||
|
|
||||||
|
// RegisterClassEx
|
||||||
|
wcname := syscall.StringToUTF16Ptr("Test Draw2d")
|
||||||
|
var wc wingui.Wndclassex
|
||||||
|
wc.Size = uint32(unsafe.Sizeof(wc))
|
||||||
|
wc.WndProc = wproc
|
||||||
|
//wc.Style = wingui.CS_HREDRAW | wingui.CS_VREDRAW
|
||||||
|
wc.Instance = mh
|
||||||
|
wc.Icon = myicon
|
||||||
|
wc.Cursor = mycursor
|
||||||
|
wc.Background = 0
|
||||||
|
wc.MenuName = nil
|
||||||
|
wc.ClassName = wcname
|
||||||
|
wc.IconSm = myicon
|
||||||
|
if _, e := wingui.RegisterClassEx(&wc); e != 0 {
|
||||||
|
abortErrNo("RegisterClassEx", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWindowEx
|
||||||
|
wh, e := wingui.CreateWindowEx(
|
||||||
|
wingui.WS_EX_CLIENTEDGE,
|
||||||
|
wcname,
|
||||||
|
syscall.StringToUTF16Ptr("My window"),
|
||||||
|
wingui.WS_OVERLAPPEDWINDOW,
|
||||||
|
wingui.CW_USEDEFAULT, wingui.CW_USEDEFAULT, 600, 800,
|
||||||
|
0, 0, mh, 0)
|
||||||
|
if e != 0 {
|
||||||
|
abortErrNo("CreateWindowEx", e)
|
||||||
|
}
|
||||||
|
fmt.Printf("main window handle is %x\n", wh)
|
||||||
|
|
||||||
|
// ShowWindow
|
||||||
|
wingui.ShowWindow(wh, wingui.SW_SHOWDEFAULT)
|
||||||
|
|
||||||
|
// UpdateWindow
|
||||||
|
if e := wingui.UpdateWindow(wh); e != 0 {
|
||||||
|
abortErrNo("UpdateWindow", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all windows messages until WM_QUIT.
|
||||||
|
var m wingui.Msg
|
||||||
|
for {
|
||||||
|
r, e := wingui.GetMessage(&m, 0, 0, 0)
|
||||||
|
if e != 0 {
|
||||||
|
abortErrNo("GetMessage", e)
|
||||||
|
}
|
||||||
|
if r == 0 {
|
||||||
|
// WM_QUIT received -> get out
|
||||||
|
break
|
||||||
|
}
|
||||||
|
wingui.TranslateMessage(&m)
|
||||||
|
wingui.DispatchMessage(&m)
|
||||||
|
}
|
||||||
|
return int(m.Wparam)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
src, err := os.OpenFile("../resource/postscript/tiger.ps", 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("can't find postscript file.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
bytes, err := ioutil.ReadAll(src)
|
||||||
|
postscriptContent = string(bytes)
|
||||||
|
rc := rungui()
|
||||||
|
os.Exit(rc)
|
||||||
|
}
|
57
cmd/testX11draw.go
Normal 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
|
@ -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)*1e-6)
|
||||||
|
filePath := folder + TestName + ".png"
|
||||||
|
f, err := os.Create(filePath)
|
||||||
|
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)
|
||||||
|
}
|
537
cmd/testdraw2d.go
Normal file
|
@ -0,0 +1,537 @@
|
||||||
|
// 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 = 512, 512
|
||||||
|
)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
t := time.Nanoseconds()
|
||||||
|
dt := t - lastTime
|
||||||
|
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6)
|
||||||
|
filePath := folder + TestName + ".png"
|
||||||
|
f, err := os.Create(filePath)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
dt = time.Nanoseconds() - t
|
||||||
|
fmt.Printf("Wrote %s OK in %f ms.\n", filePath, float64(dt)*1e-6)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<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")
|
||||||
|
gc.RMoveTo(width+1, 0)
|
||||||
|
gc.FillString("cou")
|
||||||
|
saveToPngFile("TestFillString", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBigPicture() {
|
||||||
|
i, gc := initGc(w, h)
|
||||||
|
gc.SetLineWidth(10)
|
||||||
|
|
||||||
|
draw2d.Rect(gc, 0, 0, w, h)
|
||||||
|
gc.Fill()
|
||||||
|
saveToPngFile("TestBigPicture", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := time.Nanoseconds()
|
||||||
|
TestPath()
|
||||||
|
TestDrawArc()
|
||||||
|
TestDrawArcNegative()
|
||||||
|
TestCurveRectangle()
|
||||||
|
TestDrawCubicCurve()
|
||||||
|
TestDash()
|
||||||
|
TestFillStroke()
|
||||||
|
TestFillStyle()
|
||||||
|
TestMultiSegmentCaps()
|
||||||
|
TestRoundRectangle()
|
||||||
|
TestLineCap()
|
||||||
|
TestLineJoin()
|
||||||
|
TestBubble()
|
||||||
|
TestStar()
|
||||||
|
TestTransform()
|
||||||
|
TestPathTransform()
|
||||||
|
TestFillString()
|
||||||
|
TestBigPicture()
|
||||||
|
dt := time.Nanoseconds() - t
|
||||||
|
fmt.Printf("All tests during: %f ms\n", float64(dt)*1e-6)
|
||||||
|
}
|
134
cmd/testgopher.go
Normal 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)*1e-6)
|
||||||
|
filePath := folder + TestName + ".png"
|
||||||
|
f, err := os.Create(filePath)
|
||||||
|
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)
|
||||||
|
}
|
71
cmd/testimage.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"bufio"
|
||||||
|
"math"
|
||||||
|
"image"
|
||||||
|
"time"
|
||||||
|
"image/png"
|
||||||
|
"exp/draw"
|
||||||
|
"draw2d.googlecode.com/hg/draw2d"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func saveToPngFile(filePath string, m image.Image) {
|
||||||
|
f, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
b := bufio.NewWriter(f)
|
||||||
|
err = png.Encode(b, m)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = b.Flush()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Wrote %s OK.\n", filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFromPngFile(filePath string) image.Image {
|
||||||
|
f, err := os.OpenFile(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 main() {
|
||||||
|
source := loadFromPngFile("../resource/image/TestAndroid.png")
|
||||||
|
dest := image.NewRGBA(1024, 768)
|
||||||
|
width, height := float64(source.Bounds().Dx()), float64(source.Bounds().Dy())
|
||||||
|
tr := draw2d.NewIdentityMatrix()
|
||||||
|
tr.Translate(width/2, height/2)
|
||||||
|
tr.Rotate(30 * math.Pi / 180)
|
||||||
|
//tr.Scale(3, 3)
|
||||||
|
tr.Translate(-width/2, -height/2)
|
||||||
|
tr.Translate(200, 5)
|
||||||
|
lastTime := time.Nanoseconds()
|
||||||
|
draw2d.DrawImage(source, dest, tr, draw.Over, draw2d.BilinearFilter)
|
||||||
|
dt := time.Nanoseconds() - lastTime
|
||||||
|
fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6)
|
||||||
|
saveToPngFile("../resource/result/TestDrawImage.png", dest)
|
||||||
|
}
|
59
cmd/testpostscript.go
Normal 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.Create(filePath)
|
||||||
|
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)
|
||||||
|
src, err := os.OpenFile("../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)
|
||||||
|
lastTime := time.Nanoseconds()
|
||||||
|
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
25
draw2d/Makefile
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
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\
|
||||||
|
rgba_interpolation.go\
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.pkg
|
43
draw2d/advanced_path.go
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
||||||
|
}
|
264
draw2d/image.go
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
// 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(img image.Image) {
|
||||||
|
DrawImage(img, gc.img, gc.Current.Tr, draw.Over, BilinearFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.UseNonZeroWinding()
|
||||||
|
|
||||||
|
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.UseNonZeroWinding()
|
||||||
|
|
||||||
|
/**** 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.UseNonZeroWinding()
|
||||||
|
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.UseNonZeroWinding()
|
||||||
|
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) UseNonZeroWinding() 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
|
||||||
|
}
|
51
draw2d/math.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
func min(x, y float64) float64 {
|
||||||
|
if x < y {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
func max(x, y float64) float64 {
|
||||||
|
if x > y {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
func minMax(x, y float64) (min, max float64) {
|
||||||
|
if x > y {
|
||||||
|
return y, x
|
||||||
|
}
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
func minUint32(a, b uint32) uint32 {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
87
draw2d/paint.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 = minUint32(M, (dr*a+r.cr*ma)/da)
|
||||||
|
dg = minUint32(M, (dg*a+r.cg*ma)/da)
|
||||||
|
db = minUint32(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 = minUint32(M, (dr*a+r.cr*ma)/da)
|
||||||
|
dg = minUint32(M, (dg*a+r.cg*ma)/da)
|
||||||
|
db = minUint32(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
|
@ -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
|
@ -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(raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)})
|
||||||
|
default:
|
||||||
|
vertexAdder.adder.Add1(raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)})
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
173
draw2d/path_converter.go
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
// 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.x, c.y = vertices[0], vertices[1]
|
||||||
|
c.startX, c.startY = c.x, c.y
|
||||||
|
c.converter.NextCommand(VertexStopCommand)
|
||||||
|
c.converter.NextCommand(VertexStartCommand)
|
||||||
|
c.converter.Vertex(c.x, c.y)
|
||||||
|
return 2
|
||||||
|
case LineTo:
|
||||||
|
c.x, c.y = vertices[0], vertices[1]
|
||||||
|
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 2
|
||||||
|
case QuadCurveTo:
|
||||||
|
quadraticBezier(c.converter, c.x, c.y, vertices[0], vertices[1], vertices[2], vertices[3], c.ApproximationScale, c.AngleTolerance)
|
||||||
|
c.x, c.y = vertices[2], vertices[3]
|
||||||
|
if c.startX == c.x && c.startY == c.y {
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
}
|
||||||
|
c.converter.Vertex(c.x, c.y)
|
||||||
|
return 4
|
||||||
|
case CubicCurveTo:
|
||||||
|
cubicBezier(c.converter, c.x, c.y, vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5], c.ApproximationScale, c.AngleTolerance, c.CuspLimit)
|
||||||
|
c.x, c.y = vertices[4], vertices[5]
|
||||||
|
if c.startX == c.x && c.startY == c.y {
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
}
|
||||||
|
c.converter.Vertex(c.x, c.y)
|
||||||
|
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.converter.NextCommand(VertexCloseCommand)
|
||||||
|
c.converter.Vertex(c.startX, c.startY)
|
||||||
|
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
|
||||||
|
}
|
189
draw2d/path_storage.go
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
// 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 NewPathStorage() (p *PathStorage) {
|
||||||
|
p = new(PathStorage)
|
||||||
|
p.commands = make([]PathCmd, 0, 256)
|
||||||
|
p.vertices = make([]float64, 0, 256)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) Clear() {
|
||||||
|
p.commands = p.commands[0:0]
|
||||||
|
p.vertices = p.vertices[0:0]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) appendToPath(cmd PathCmd, vertices ...float64) {
|
||||||
|
if cap(p.vertices) <= len(p.vertices)+6 {
|
||||||
|
a := make([]PathCmd, len(p.commands), cap(p.commands)+256)
|
||||||
|
b := make([]float64, len(p.vertices), cap(p.vertices)+256)
|
||||||
|
copy(a, p.commands)
|
||||||
|
p.commands = a
|
||||||
|
copy(b, p.vertices)
|
||||||
|
p.vertices = b
|
||||||
|
}
|
||||||
|
p.commands = p.commands[0 : len(p.commands)+1]
|
||||||
|
p.commands[len(p.commands)-1] = cmd
|
||||||
|
copy(p.vertices[len(p.vertices):len(p.vertices)+len(vertices)], vertices)
|
||||||
|
p.vertices = p.vertices[0 : len(p.vertices)+len(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
|
||||||
|
}
|
144
draw2d/rgba_interpolation.go
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// see http://pippin.gimp.org/image_processing/chap_resampling.html
|
||||||
|
package draw2d
|
||||||
|
|
||||||
|
import (
|
||||||
|
"exp/draw"
|
||||||
|
"image"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ImageFilter int
|
||||||
|
|
||||||
|
const (
|
||||||
|
LinearFilter ImageFilter = iota
|
||||||
|
BilinearFilter
|
||||||
|
BicubicFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
//see http://pippin.gimp.org/image_processing/chap_resampling.html
|
||||||
|
func getColorLinear(img image.Image, x, y float64) image.Color {
|
||||||
|
return img.At(int(x), int(y))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getColorBilinear(img image.Image, x, y float64) image.Color {
|
||||||
|
x0 := math.Floor(x)
|
||||||
|
y0 := math.Floor(y)
|
||||||
|
dx := x - x0
|
||||||
|
dy := y - y0
|
||||||
|
|
||||||
|
rt, gt, bt, at := img.At(int(x0), int(y0)).RGBA()
|
||||||
|
r0, g0, b0, a0 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = img.At(int(x0+1), int(y0)).RGBA()
|
||||||
|
r1, g1, b1, a1 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = img.At(int(x0+1), int(y0+1)).RGBA()
|
||||||
|
r2, g2, b2, a2 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = img.At(int(x0), int(y0+1)).RGBA()
|
||||||
|
r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
|
||||||
|
r := int(lerp(lerp(r0, r1, dx), lerp(r3, r2, dx), dy))
|
||||||
|
g := int(lerp(lerp(g0, g1, dx), lerp(g3, g2, dx), dy))
|
||||||
|
b := int(lerp(lerp(b0, b1, dx), lerp(b3, b2, dx), dy))
|
||||||
|
a := int(lerp(lerp(a0, a1, dx), lerp(a3, a2, dx), dy))
|
||||||
|
return image.RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
-- LERP
|
||||||
|
-- /lerp/, vi.,n.
|
||||||
|
--
|
||||||
|
-- Quasi-acronym for Linear Interpolation, used as a verb or noun for
|
||||||
|
-- the operation. "Bresenham's algorithm lerps incrementally between the
|
||||||
|
-- two endpoints of the line." (From Jargon File (4.4.4, 14 Aug 2003)
|
||||||
|
*/
|
||||||
|
func lerp(v1, v2, ratio float64) float64 {
|
||||||
|
return v1*(1-ratio) + v2*ratio
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func getColorCubicRow(img image.Image, x, y, offset float64) image.Color {
|
||||||
|
c0 := img.At(int(x), int(y))
|
||||||
|
c1 := img.At(int(x+1), int(y))
|
||||||
|
c2 := img.At(int(x+2), int(y))
|
||||||
|
c3 := img.At(int(x+3), int(y))
|
||||||
|
rt, gt, bt, at := c0.RGBA()
|
||||||
|
r0, g0, b0, a0 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = c1.RGBA()
|
||||||
|
r1, g1, b1, a1 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = c2.RGBA()
|
||||||
|
r2, g2, b2, a2 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = c3.RGBA()
|
||||||
|
r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
r, g, b, a := cubic(offset, r0, r1, r2, r3), cubic(offset, g0, g1, g2, g3), cubic(offset, b0, b1, b2, b3), cubic(offset, a0, a1, a2, a3)
|
||||||
|
return image.RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getColorBicubic(img image.Image, x, y float64) image.Color {
|
||||||
|
x0 := math.Floor(x)
|
||||||
|
y0 := math.Floor(y)
|
||||||
|
dx := x - x0
|
||||||
|
dy := y - y0
|
||||||
|
c0 := getColorCubicRow(img, x0-1, y0-1, dx)
|
||||||
|
c1 := getColorCubicRow(img, x0-1, y0, dx)
|
||||||
|
c2 := getColorCubicRow(img, x0-1, y0+1, dx)
|
||||||
|
c3 := getColorCubicRow(img, x0-1, y0+2, dx)
|
||||||
|
rt, gt, bt, at := c0.RGBA()
|
||||||
|
r0, g0, b0, a0 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = c1.RGBA()
|
||||||
|
r1, g1, b1, a1 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = c2.RGBA()
|
||||||
|
r2, g2, b2, a2 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
rt, gt, bt, at = c3.RGBA()
|
||||||
|
r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at)
|
||||||
|
r, g, b, a := cubic(dy, r0, r1, r2, r3), cubic(dy, g0, g1, g2, g3), cubic(dy, b0, b1, b2, b3), cubic(dy, a0, a1, a2, a3)
|
||||||
|
return image.RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cubic(offset, v0, v1, v2, v3 float64) uint32 {
|
||||||
|
// offset is the offset of the sampled value between v1 and v2
|
||||||
|
return uint32(((((-7*v0+21*v1-21*v2+7*v3)*offset+
|
||||||
|
(15*v0-36*v1+27*v2-6*v3))*offset+
|
||||||
|
(-9*v0+9*v2))*offset + (v0 + 16*v1 + v2)) / 18.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawImage(src image.Image, dest draw.Image, tr MatrixTransform, op draw.Op, filter ImageFilter) {
|
||||||
|
bounds := src.Bounds()
|
||||||
|
x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y)
|
||||||
|
tr.TransformRectangle(&x0, &y0, &x1, &y1)
|
||||||
|
var x, y, u, v float64
|
||||||
|
var c1, c2, cr image.Color
|
||||||
|
var r, g, b, a, ia, r1, g1, b1, a1, r2, g2, b2, a2 uint32
|
||||||
|
var color image.RGBAColor
|
||||||
|
for x = x0; x < x1; x++ {
|
||||||
|
for y = y0; y < y1; y++ {
|
||||||
|
u = x
|
||||||
|
v = y
|
||||||
|
tr.InverseTransform(&u, &v)
|
||||||
|
c1 = dest.At(int(x), int(y))
|
||||||
|
switch filter {
|
||||||
|
case LinearFilter:
|
||||||
|
c2 = src.At(int(u), int(v))
|
||||||
|
case BilinearFilter:
|
||||||
|
c2 = getColorBilinear(src, u, v)
|
||||||
|
case BicubicFilter:
|
||||||
|
c2 = getColorBicubic(src, u, v)
|
||||||
|
}
|
||||||
|
switch op {
|
||||||
|
case draw.Over:
|
||||||
|
r1, g1, b1, a1 = c1.RGBA()
|
||||||
|
r2, g2, b2, a2 = c2.RGBA()
|
||||||
|
ia = M - a2
|
||||||
|
r = ((r1 * ia) / M) + r2
|
||||||
|
g = ((g1 * ia) / M) + g2
|
||||||
|
b = ((b1 * ia) / M) + b2
|
||||||
|
a = ((a1 * ia) / M) + a2
|
||||||
|
color.R = uint8(r >> 8)
|
||||||
|
color.G = uint8(g >> 8)
|
||||||
|
color.B = uint8(b >> 8)
|
||||||
|
color.A = uint8(a >> 8)
|
||||||
|
cr = color
|
||||||
|
default:
|
||||||
|
cr = c2
|
||||||
|
}
|
||||||
|
dest.Set(int(x), int(y), cr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
199
draw2d/stack_gc.go
Normal 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 = NewPathStorage()
|
||||||
|
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.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
137
draw2d/stroker.go
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
// 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, 256)
|
||||||
|
l.rewind = make([]float64, 0, 256)
|
||||||
|
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 = l.vertices[0:0]
|
||||||
|
l.rewind = l.rewind[0: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 VertexJoinCommand:
|
||||||
|
l.joinLine(l.x, l.y, l.nx, l.ny, x, y)
|
||||||
|
case VertexStartCommand:
|
||||||
|
l.x, l.y = 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) appendVertex(vertices ...float64) {
|
||||||
|
s := len(vertices) / 2
|
||||||
|
if len(l.vertices)+s >= cap(l.vertices) {
|
||||||
|
v := make([]float64, len(l.vertices), cap(l.vertices)+128)
|
||||||
|
copy(v, l.vertices)
|
||||||
|
l.vertices = v
|
||||||
|
v = make([]float64, len(l.rewind), cap(l.rewind)+128)
|
||||||
|
copy(v, l.rewind)
|
||||||
|
l.rewind = v
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(l.vertices[len(l.vertices):len(l.vertices)+s], vertices[:s])
|
||||||
|
l.vertices = l.vertices[0 : len(l.vertices)+s]
|
||||||
|
copy(l.rewind[len(l.rewind):len(l.rewind)+s], vertices[s:])
|
||||||
|
l.rewind = l.rewind[0 : len(l.rewind)+s]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LineStroker) closePolygon() {
|
||||||
|
if len(l.vertices) > 1 {
|
||||||
|
l.appendVertex(l.vertices[0], l.vertices[1], 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.appendVertex(x1+nx, y1+ny, x2+nx, y2+ny, 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.appendVertex(x1+nx, y1+ny, x2+nx, y2+ny, x1-nx, y1-ny, x2-nx, y2-ny)
|
||||||
|
l.x, l.y, l.nx, l.ny = x2, y2, nx, ny
|
||||||
|
}
|
||||||
|
}
|
300
draw2d/transform.go
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
// 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) TransformRectangle(x0, y0, x2, y2 *float64) {
|
||||||
|
x1 := *x2
|
||||||
|
y1 := *y0
|
||||||
|
x3 := *x0
|
||||||
|
y3 := *y2
|
||||||
|
tr.Transform(x0, y0, &x1, &y1, x2, y2, &x3, &y3)
|
||||||
|
*x0, x1 = minMax(*x0, x1)
|
||||||
|
*x2, x3 = minMax(*x2, x3)
|
||||||
|
*y0, y1 = minMax(*y0, y1)
|
||||||
|
*y2, y3 = minMax(*y2, y3)
|
||||||
|
|
||||||
|
*x0 = min(*x0, *x2)
|
||||||
|
*y0 = min(*y0, *y2)
|
||||||
|
*x2 = max(x1, x3)
|
||||||
|
*y2 = max(y1, y3)
|
||||||
|
}
|
||||||
|
|
||||||
|
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] = sx * tr[0]
|
||||||
|
tr[1] = sx * tr[1]
|
||||||
|
tr[2] = sy * tr[2]
|
||||||
|
tr[3] = sy * tr[3]
|
||||||
|
return tr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tr *MatrixTransform) Translate(tx, ty float64) *MatrixTransform {
|
||||||
|
tr[4] = tx*tr[0] + ty*tr[2] + tr[4]
|
||||||
|
tr[5] = ty*tr[3] + tx*tr[1] + tr[5]
|
||||||
|
return tr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tr *MatrixTransform) Rotate(angle float64) *MatrixTransform {
|
||||||
|
c := math.Cos(angle)
|
||||||
|
s := math.Sin(angle)
|
||||||
|
t0 := c*tr[0] + s*tr[2]
|
||||||
|
t1 := s*tr[3] + c*tr[1]
|
||||||
|
t2 := c*tr[2] - s*tr[0]
|
||||||
|
t3 := c*tr[3] - s*tr[1]
|
||||||
|
tr[0] = t0
|
||||||
|
tr[1] = t1
|
||||||
|
tr[2] = t2
|
||||||
|
tr[3] = t3
|
||||||
|
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) GetScale() float64 {
|
||||||
|
x := 0.707106781*tr[0] + 0.707106781*tr[1]
|
||||||
|
y := 0.707106781*tr[2] + 0.707106781*tr[3]
|
||||||
|
return math.Sqrt(x*x + y*y)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
u := x*vmt.tr[0] + y*vmt.tr[2] + vmt.tr[4]
|
||||||
|
v := x*vmt.tr[1] + y*vmt.tr[3] + vmt.tr[5]
|
||||||
|
vmt.Next.Vertex(u, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
@ -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
|
@ -0,0 +1,7 @@
|
||||||
|
include $(GOROOT)/src/Make.inc
|
||||||
|
|
||||||
|
TARG=draw2d.googlecode.com/hg/draw2dgl
|
||||||
|
GOFILES=\
|
||||||
|
gc.go\
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.pkg
|
216
draw2dgl/gc.go
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
package draw2dgl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"exp/draw"
|
||||||
|
"gl"
|
||||||
|
"freetype-go.googlecode.com/hg/freetype/raster"
|
||||||
|
"draw2d.googlecode.com/hg/draw2d"
|
||||||
|
//"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GLPainter struct {
|
||||||
|
// The Porter-Duff composition operator.
|
||||||
|
Op draw.Op
|
||||||
|
// The 16-bit color to paint the spans.
|
||||||
|
cr, cg, cb uint8
|
||||||
|
ca uint32
|
||||||
|
colors []uint8
|
||||||
|
vertices []int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const M16 uint32 = 1<<16 - 1
|
||||||
|
|
||||||
|
// Paint satisfies the Painter interface by painting ss onto an image.RGBA.
|
||||||
|
func (p *GLPainter) Paint(ss []raster.Span, done bool) {
|
||||||
|
//gl.Begin(gl.LINES)
|
||||||
|
sslen := len(ss)
|
||||||
|
clenrequired := sslen * 8
|
||||||
|
vlenrequired := sslen * 4
|
||||||
|
if clenrequired >= (cap(p.colors) - len(p.colors)) {
|
||||||
|
p.Flush()
|
||||||
|
|
||||||
|
if clenrequired >= cap(p.colors) {
|
||||||
|
p.vertices = make([]int32, 0, vlenrequired+(vlenrequired/2))
|
||||||
|
p.colors = make([]uint8, 0, clenrequired+(clenrequired/2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vi := len(p.vertices)
|
||||||
|
ci := len(p.colors)
|
||||||
|
p.vertices = p.vertices[0 : vi+vlenrequired]
|
||||||
|
p.colors = p.colors[0 : ci+clenrequired]
|
||||||
|
for _, s := range ss {
|
||||||
|
ma := s.A >> 16
|
||||||
|
a := ma * p.ca / M16
|
||||||
|
p.colors[ci] = p.cr
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = p.cg
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = p.cb
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = uint8(a >> 8)
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = p.cr
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = p.cg
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = p.cb
|
||||||
|
ci++
|
||||||
|
p.colors[ci] = uint8(a >> 8)
|
||||||
|
ci++
|
||||||
|
p.vertices[vi] = int32(s.X0)
|
||||||
|
vi++
|
||||||
|
p.vertices[vi] = int32(s.Y)
|
||||||
|
vi++
|
||||||
|
p.vertices[vi] = int32(s.X1)
|
||||||
|
vi++
|
||||||
|
p.vertices[vi] = int32(s.Y)
|
||||||
|
vi++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GLPainter) Flush() {
|
||||||
|
if len(p.vertices) != 0 {
|
||||||
|
gl.EnableClientState(gl.COLOR_ARRAY)
|
||||||
|
gl.EnableClientState(gl.VERTEX_ARRAY)
|
||||||
|
gl.ColorPointer(4, 0, p.colors)
|
||||||
|
gl.VertexPointer(2, 0, p.vertices)
|
||||||
|
|
||||||
|
// draw lines
|
||||||
|
gl.DrawArrays(gl.LINES, 0, len(p.vertices)/2)
|
||||||
|
gl.DisableClientState(gl.VERTEX_ARRAY)
|
||||||
|
gl.DisableClientState(gl.COLOR_ARRAY)
|
||||||
|
p.vertices = p.vertices[0:0]
|
||||||
|
p.colors = p.colors[0:0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// SetColor sets the color to paint the spans.
|
||||||
|
func (p *GLPainter) SetColor(c image.Color) {
|
||||||
|
r, g, b, a := c.RGBA()
|
||||||
|
if a == 0 {
|
||||||
|
p.cr = 0
|
||||||
|
p.cg = 0
|
||||||
|
p.cb = 0
|
||||||
|
p.ca = a
|
||||||
|
} else {
|
||||||
|
p.cr = uint8((r * M16 / a) >> 8)
|
||||||
|
p.cg = uint8((g * M16 / a) >> 8)
|
||||||
|
p.cb = uint8((b * M16 / a) >> 8)
|
||||||
|
p.ca = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRGBAPainter creates a new RGBAPainter for the given image.
|
||||||
|
func NewGLPainter() *GLPainter {
|
||||||
|
p := new(GLPainter)
|
||||||
|
p.vertices = make([]int32, 0, 1024)
|
||||||
|
p.colors = make([]uint8, 0, 1024)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
type GraphicContext struct {
|
||||||
|
*draw2d.StackGraphicContext
|
||||||
|
painter *GLPainter
|
||||||
|
fillRasterizer *raster.Rasterizer
|
||||||
|
strokeRasterizer *raster.Rasterizer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Graphic context from an image
|
||||||
|
*/
|
||||||
|
func NewGraphicContext(width, height int) *GraphicContext {
|
||||||
|
gc := &GraphicContext{
|
||||||
|
draw2d.NewStackGraphicContext(),
|
||||||
|
NewGLPainter(),
|
||||||
|
raster.NewRasterizer(width, height),
|
||||||
|
raster.NewRasterizer(width, height),
|
||||||
|
}
|
||||||
|
return gc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) SetDPI(dpi int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) GetDPI() int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) Clear() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) ClearRect(x1, y1, x2, y2 int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) DrawImage(img image.Image) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (gc *GraphicContext) FillString(text string) (cursor float64) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (gc *GraphicContext) paint(rasterizer *raster.Rasterizer, color image.Color) {
|
||||||
|
gc.painter.SetColor(color)
|
||||||
|
rasterizer.Rasterize(gc.painter)
|
||||||
|
rasterizer.Clear()
|
||||||
|
gc.painter.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) Stroke(paths ...*draw2d.PathStorage) {
|
||||||
|
paths = append(paths, gc.Current.Path)
|
||||||
|
gc.strokeRasterizer.UseNonZeroWinding = true
|
||||||
|
|
||||||
|
stroker := draw2d.NewLineStroker(gc.Current.Cap, gc.Current.Join, draw2d.NewVertexMatrixTransform(gc.Current.Tr, draw2d.NewVertexAdder(gc.strokeRasterizer)))
|
||||||
|
stroker.HalfLineWidth = gc.Current.LineWidth / 2
|
||||||
|
var pathConverter *draw2d.PathConverter
|
||||||
|
if gc.Current.Dash != nil && len(gc.Current.Dash) > 0 {
|
||||||
|
dasher := draw2d.NewDashConverter(gc.Current.Dash, gc.Current.DashOffset, stroker)
|
||||||
|
pathConverter = draw2d.NewPathConverter(dasher)
|
||||||
|
} else {
|
||||||
|
pathConverter = draw2d.NewPathConverter(stroker)
|
||||||
|
}
|
||||||
|
pathConverter.ApproximationScale = gc.Current.Tr.GetScale() // From agg code
|
||||||
|
pathConverter.Convert(paths...)
|
||||||
|
|
||||||
|
gc.paint(gc.strokeRasterizer, gc.Current.StrokeColor)
|
||||||
|
gc.Current.Path.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) Fill(paths ...*draw2d.PathStorage) {
|
||||||
|
paths = append(paths, gc.Current.Path)
|
||||||
|
gc.fillRasterizer.UseNonZeroWinding = gc.Current.FillRule.UseNonZeroWinding()
|
||||||
|
|
||||||
|
pathConverter := draw2d.NewPathConverter(draw2d.NewVertexMatrixTransform(gc.Current.Tr, draw2d.NewVertexAdder(gc.fillRasterizer)))
|
||||||
|
pathConverter.ApproximationScale = gc.Current.Tr.GetScale() // From agg code
|
||||||
|
pathConverter.Convert(paths...)
|
||||||
|
|
||||||
|
gc.paint(gc.fillRasterizer, gc.Current.FillColor)
|
||||||
|
gc.Current.Path.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GraphicContext) FillStroke(paths ...*draw2d.PathStorage) {
|
||||||
|
gc.fillRasterizer.UseNonZeroWinding = gc.Current.FillRule.UseNonZeroWinding()
|
||||||
|
gc.strokeRasterizer.UseNonZeroWinding = true
|
||||||
|
|
||||||
|
filler := draw2d.NewVertexMatrixTransform(gc.Current.Tr, draw2d.NewVertexAdder(gc.fillRasterizer))
|
||||||
|
|
||||||
|
stroker := draw2d.NewLineStroker(gc.Current.Cap, gc.Current.Join, draw2d.NewVertexMatrixTransform(gc.Current.Tr, draw2d.NewVertexAdder(gc.strokeRasterizer)))
|
||||||
|
stroker.HalfLineWidth = gc.Current.LineWidth / 2
|
||||||
|
|
||||||
|
demux := draw2d.NewDemuxConverter(filler, stroker)
|
||||||
|
paths = append(paths, gc.Current.Path)
|
||||||
|
pathConverter := draw2d.NewPathConverter(demux)
|
||||||
|
pathConverter.ApproximationScale = gc.Current.Tr.GetScale() // From agg code
|
||||||
|
pathConverter.Convert(paths...)
|
||||||
|
|
||||||
|
gc.paint(gc.fillRasterizer, gc.Current.FillColor)
|
||||||
|
gc.paint(gc.strokeRasterizer, gc.Current.StrokeColor)
|
||||||
|
gc.Current.Path = draw2d.NewPathStorage()
|
||||||
|
}
|
18
postscript/Makefile
Normal 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
|
@ -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)
|
||||||
|
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
|
@ -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)
|
||||||
|
}
|
93
postscript/operators_array.go
Normal 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 … anyn−1 array astore array
|
||||||
|
// stores the objects any0 to anyn−1 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))
|
||||||
|
|
||||||
|
}
|
96
postscript/operators_conflict.go
Normal 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))
|
||||||
|
}
|
80
postscript/operators_control.go
Normal 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))
|
||||||
|
}
|
171
postscript/operators_dictionary.go
Normal 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))
|
||||||
|
}
|
482
postscript/operators_graphics.go
Normal 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))
|
||||||
|
}
|
157
postscript/operators_math.go
Normal 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))
|
||||||
|
|
||||||
|
}
|
42
postscript/operators_misc.go
Normal 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))
|
||||||
|
}
|
41
postscript/operators_relational.go
Normal 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))
|
||||||
|
}
|
88
postscript/operators_stack.go
Normal 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)))
|
||||||
|
}
|
||||||
|
//anyn−1 … any0 n j roll any(j−1) mod n … any0 anyn−1 … 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
BIN
resource/font/luximbi.ttf
Normal file
BIN
resource/font/luximr.ttf
Normal file
BIN
resource/font/luximri.ttf
Normal file
BIN
resource/font/luxirb.ttf
Normal file
BIN
resource/font/luxirbi.ttf
Normal file
BIN
resource/font/luxirr.ttf
Normal file
BIN
resource/font/luxirri.ttf
Normal file
BIN
resource/font/luxisb.ttf
Normal file
BIN
resource/font/luxisbi.ttf
Normal file
BIN
resource/font/luxisr.ttf
Normal file
BIN
resource/font/luxisri.ttf
Normal file
BIN
resource/image/TestAndroid.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
18
resource/image/Tests.html
Normal 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
|
@ -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
|
||||||
|
|
||||||
|
|
BIN
resource/image/Varna_Railway_Station_HDR.png
Normal file
After Width: | Height: | Size: 592 KiB |
103
resource/image/test.js
Normal 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()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
57
resource/postscript/3dcolor.ps
Normal 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
|
12684
resource/postscript/JavaPlatform.ps
Normal file
76
resource/postscript/Koch.ps
Normal 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
|
68
resource/postscript/Mand.ps
Normal 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
|
||||||
|
|
||||||
|
|
3537
resource/postscript/bell_206.ps
Normal file
125
resource/postscript/colorcir.ps
Normal 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
|
2485
resource/postscript/doretree.ps
Normal file
380
resource/postscript/escher.ps
Normal 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
|
||||||
|
|
1398
resource/postscript/golfer.ps
Normal file
917
resource/postscript/grade.ps
Normal 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
|
@ -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
|
939
resource/postscript/manylines.ps
Normal 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
|
@ -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
|
91
resource/postscript/snowflak.ps
Normal 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
|
50
resource/postscript/test1.ps
Normal 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
588
resource/postscript/vasarely.ps
Executable 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
5043
resource/postscript/whitepaper.ps
Executable file
BIN
resource/result/TestAndroid.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
resource/result/TestBubble.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
resource/result/TestCurveRectangle.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
resource/result/TestDash.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
resource/result/TestDrawArc.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resource/result/TestDrawArcNegative.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
resource/result/TestDrawCubicCurve.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
resource/result/TestDrawImage.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
resource/result/TestFillString.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
resource/result/TestFillStroke.png
Normal file
After Width: | Height: | Size: 4.1 KiB |