Merge pull request #53 from stanim/master

Add samples to draw2d
This commit is contained in:
Stani 2015-07-10 02:22:08 +02:00
commit cec365b96a
28 changed files with 6336 additions and 39 deletions

1
.gitignore vendored
View file

@ -20,3 +20,4 @@ _test*
**/*.dll
**/core*[0-9]
.private
output

View file

@ -10,6 +10,8 @@ Features
Operations in draw2d include stroking and filling polygons, arcs, Bézier curves, drawing images and text rendering with truetype fonts. All drawing operations can be transformed by affine transformations (scale, rotation, translation).
Package draw2d follows the conventions of the [HTML Canvas 2D Context](http://www.w3.org/TR/2dcontext/) for coordinate system, angles, etc...
Installation
------------
@ -72,6 +74,19 @@ There are more examples here: https://github.com/llgcode/draw2d.samples
Drawing on opengl is provided by the draw2dgl package.
Testing
-------
The samples are run as tests from the root package folder `draw2d` by:
```
go test ./...
```
Or if you want to run with test coverage:
```
go test -cover ./... | grep -v "no test"
```
This will generate output by the different backends in the output folder.
Acknowledgments
---------------

View file

@ -13,6 +13,8 @@
// All drawing operations can be transformed by affine transformations
// (scale, rotation, translation).
//
// Package draw2d follows the conventions of http://www.w3.org/TR/2dcontext for coordinate system, angles, etc...
//
// Installation
//
// To install or update the package draw2d on your system, run:
@ -49,6 +51,16 @@
// Drawing on opengl is provided by the draw2dgl package.
// See subdirectories at the bottom of this page.
//
// Testing
//
// The samples are run as tests from the root package folder `draw2d` by:
// go test ./...
//
// Or if you want to run with test coverage:
// go test -cover ./... | grep -v "no test"
//
// This will generate output by the different backends in the output folder.
//
// Acknowledgments
//
// Laurent Le Goff wrote this library, inspired by Postscript and

View file

@ -12,7 +12,6 @@ import (
"log"
"math"
"os"
"path/filepath"
"strconv"
"code.google.com/p/freetype-go/freetype/truetype"
@ -240,8 +239,7 @@ func (gc *GraphicContext) SetFontData(fontData draw2d.FontData) {
}
fn := draw2d.FontFileName(fontData)
fn = fn[:len(fn)-4]
jfn := filepath.Join(draw2d.GetFontFolder(), fn+".json")
gc.pdf.AddFont(fn, style, jfn)
gc.pdf.AddFont(fn, style, fn+".json")
}
// SetFontSize sets the font size in points (as in ``a 12 point font'').

View file

@ -6,14 +6,13 @@ import (
"testing"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d.samples"
"github.com/llgcode/draw2d.samples/android"
"github.com/llgcode/draw2d.samples/frameimage"
"github.com/llgcode/draw2d.samples/gopher"
"github.com/llgcode/draw2d.samples/helloworld"
"github.com/llgcode/draw2d.samples/line"
"github.com/llgcode/draw2d.samples/linecapjoin"
"github.com/llgcode/draw2d.samples/postscript"
"github.com/llgcode/draw2d/samples/android"
"github.com/llgcode/draw2d/samples/frameimage"
"github.com/llgcode/draw2d/samples/gopher"
"github.com/llgcode/draw2d/samples/helloworld"
"github.com/llgcode/draw2d/samples/line"
"github.com/llgcode/draw2d/samples/linecapjoin"
"github.com/llgcode/draw2d/samples/postscript"
)
func TestSampleAndroid(t *testing.T) {
@ -26,9 +25,9 @@ func TestSampleGopher(t *testing.T) {
func TestSampleHelloWorld(t *testing.T) {
// Set the global folder for searching fonts
// The pdf backend needs for every ttf file its corresponding json
// file which is generated by gofpdf/makefont.
draw2d.SetFontFolder(samples.Dir("helloworld", "../"))
// The pdf backend needs for every ttf file its corresponding
// json/.z file which is generated by gofpdf/makefont.
draw2d.SetFontFolder("../resource/font")
test(t, helloworld.Main)
}

View file

@ -4,7 +4,6 @@
package draw2dpdf_test
import (
"os"
"testing"
"github.com/llgcode/draw2d"
@ -18,18 +17,20 @@ func test(t *testing.T, draw sample) {
dest := draw2dpdf.NewPdf("L", "mm", "A4")
gc := draw2dpdf.NewGraphicContext(dest)
// Draw sample
fn, err := draw(gc, "pdf")
output, err := draw(gc, "pdf")
if err != nil {
t.Errorf("Drawing %q failed: %v", fn, err)
t.Errorf("Drawing %q failed: %v", output, err)
return
}
// Save to pdf only if it doesn't exist because of git
if _, err = os.Stat(fn); err == nil {
t.Skipf("Saving %q skipped, as it exists already. (Git would consider it modified.)", fn)
return
}
err = draw2dpdf.SaveToPdfFile(fn, dest)
/*
// Save to pdf only if it doesn't exist because of git
if _, err = os.Stat(output); err == nil {
t.Skipf("Saving %q skipped, as it exists already. (Git would consider it modified.)", output)
return
}
*/
err = draw2dpdf.SaveToPdfFile(output, dest)
if err != nil {
t.Errorf("Saving %q failed: %v", fn, err)
t.Errorf("Saving %q failed: %v", output, err)
}
}

View file

@ -7,6 +7,7 @@ import (
"io/ioutil"
"log"
"path"
"path/filepath"
"code.google.com/p/freetype-go/freetype/truetype"
)
@ -80,7 +81,7 @@ func GetFontFolder() string {
}
func SetFontFolder(folder string) {
fontFolder = folder
fontFolder = filepath.Clean(folder)
}
func loadFont(fontFileName string) *truetype.Font {

0
output/.empty Normal file
View file

View file

@ -0,0 +1 @@
{"Tp":"TrueType","Name":"LuxiMono-BoldOblique","Desc":{"Ascent":783,"Descent":-205,"CapHeight":783,"Flags":97,"FontBBox":{"Xmin":-29,"Ymin":-211,"Xmax":764,"Ymax":1012},"ItalicAngle":-8,"StemV":120,"MissingWidth":600},"Up":0,"Ut":0,"Cw":[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,653,600,653,600,600,653,600,653,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600],"Enc":"cp1252","Diff":"","File":"luximbi.z","Size1":0,"Size2":0,"OriginalSize":69872,"I":0,"N":0,"DiffN":0}

BIN
resource/font/luximbi.z Normal file

Binary file not shown.

BIN
resource/image/gopher.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

2733
resource/image/tiger.ps Normal file

File diff suppressed because it is too large Load diff

88
samples/README.md Normal file
View file

@ -0,0 +1,88 @@
draw2d samples
==============
Various Samples to using draw2d
Using the image backend
-----------------------
The following Go code draws the android sample on a png image:
```
import (
"image"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples/android"
)
function main(){}
// Initialize the graphic context on an RGBA image
dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
gc := draw2d.NewGraphicContext(dest)
// Draw Android logo
fn, err := android.Main(gc, "png")
if err != nil {
t.Errorf("Drawing %q failed: %v", fn, err)
return
}
// Save to png
err = draw2d.SaveToPngFile(fn, dest)
if err != nil {
t.Errorf("Saving %q failed: %v", fn, err)
}
}
```
Using the pdf backend
---------------------
The following Go code draws the android sample on a pdf document:
```
import (
"image"
"github.com/llgcode/draw2d/draw2dpdf"
"github.com/llgcode/draw2d/samples/android"
)
function main(){}
// Initialize the graphic context on a pdf document
dest := draw2dpdf.NewPdf("L", "mm", "A4")
gc := draw2dpdf.NewGraphicContext(dest)
// Draw Android logo
fn, err := android.Main(gc, "png")
if err != nil {
t.Errorf("Drawing %q failed: %v", fn, err)
return
}
// Save to pdf
err = draw2dpdf.SaveToPdfFile(fn, dest)
if err != nil {
t.Errorf("Saving %q failed: %v", fn, err)
}
}
```
Testing
-------
These samples are run as tests from the root package folder `draw2d` by:
```
go test ./...
```
Or if you want to run with test coverage:
```
go test -cover ./... | grep -v "no test"
```
The following files are responsible to run the image tests:
```
draw2d/test_test.go
draw2d/samples_test.go
```
The following files are responsible to run the pdf tests:
```
draw2d/pdf/test_test.go
draw2dpdf/samples_test.go
```

View file

@ -0,0 +1,75 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
// Package android draws an android avatar.
package android
import (
"image/color"
"math"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws a droid and returns the filename. This should only be
// used during testing.
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
// Draw the droid
Draw(gc, 65, 0)
// Return the output filename
return samples.Output("android", ext), nil
}
// Draw the droid on a certain position.
func Draw(gc draw2d.GraphicContext, x, y float64) {
// set the fill and stroke color of the droid
gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff})
gc.SetStrokeColor(color.RGBA{0x44, 0x44, 0x44, 0xff})
// set line properties
gc.SetLineCap(draw2d.RoundCap)
gc.SetLineWidth(5)
// head
gc.MoveTo(x+30, y+70)
gc.ArcTo(x+80, y+70, 50, 50, 180*(math.Pi/180), 180*(math.Pi/180))
gc.Close()
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()
// left eye
draw2d.Circle(gc, x+60, y+45, 5)
gc.FillStroke()
// right eye
draw2d.Circle(gc, x+100, y+45, 5)
gc.FillStroke()
// body
draw2d.RoundRect(gc, x+30, y+75, x+30+100, y+75+90, 10, 10)
gc.FillStroke()
draw2d.Rect(gc, x+30, y+75, x+30+100, y+75+80)
gc.FillStroke()
// left arm
draw2d.RoundRect(gc, x+5, y+80, x+5+20, y+80+70, 10, 10)
gc.FillStroke()
// right arm
draw2d.RoundRect(gc, x+135, y+80, x+135+20, y+80+70, 10, 10)
gc.FillStroke()
// left leg
draw2d.RoundRect(gc, x+50, y+150, x+50+20, y+150+50, 10, 10)
gc.FillStroke()
// right leg
draw2d.RoundRect(gc, x+90, y+150, x+90+20, y+150+50, 10, 10)
gc.FillStroke()
}

View file

@ -0,0 +1,8 @@
application: draw2d-test
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app

View file

@ -0,0 +1,73 @@
// +build appengine
// Package gae demonstrates draw2d on a Google appengine server.
package gae
import (
"fmt"
"image"
"image/png"
"net/http"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/draw2dpdf"
"github.com/llgcode/draw2d/samples/android"
"appengine"
)
type appError struct {
Error error
Message string
Code int
}
type appHandler func(http.ResponseWriter, *http.Request) *appError
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if e := fn(w, r); e != nil { // e is *appError, not os.Error.
c := appengine.NewContext(r)
c.Errorf("%v", e.Error)
http.Error(w, e.Message, e.Code)
}
}
func init() {
http.Handle("/pdf", appHandler(pdf))
http.Handle("/png", appHandler(imgPng))
}
func pdf(w http.ResponseWriter, r *http.Request) *appError {
w.Header().Set("Content-type", "application/pdf")
// Initialize the graphic context on an pdf document
dest := draw2dpdf.NewPdf("L", "mm", "A4")
gc := draw2dpdf.NewGraphicContext(dest)
// Draw sample
android.Draw(gc, 65, 0)
err := dest.Output(w)
if err != nil {
return &appError{err, fmt.Sprintf("Can't write: %s", err), 500}
}
return nil
}
func imgPng(w http.ResponseWriter, r *http.Request) *appError {
w.Header().Set("Content-type", "image/png")
// Initialize the graphic context on an RGBA image
dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
gc := draw2d.NewGraphicContext(dest)
// Draw sample
android.Draw(gc, 65, 0)
err := png.Encode(w, dest)
if err != nil {
return &appError{err, fmt.Sprintf("Can't encode: %s", err), 500}
}
return nil
}

View file

@ -0,0 +1,59 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff, Stani Michiels
// Package frameimage centers a png image and rotates it.
package frameimage
import (
"math"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws the image frame and returns the filename.
// This should only be used during testing.
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
// Margin between the image and the frame
const margin = 30
// Line width od the frame
const lineWidth = 3
// Gopher image
gopher := samples.Resource("image", "gopher.png", ext)
// Draw gopher
err := Draw(gc, gopher, 297, 210, margin, lineWidth)
// Return the output filename
return samples.Output("frameimage", ext), err
}
// Draw the image frame with certain parameters.
func Draw(gc draw2d.GraphicContext, png string,
dw, dh, margin, lineWidth float64) error {
// Draw frame
draw2d.RoundRect(gc, lineWidth, lineWidth,
dw-lineWidth, dh-lineWidth, 100, 100)
gc.SetLineWidth(lineWidth)
gc.FillStroke()
// load the source image
source, err := draw2d.LoadFromPngFile(png)
if err != nil {
return err
}
// Size of source image
sw, sh := float64(source.Bounds().Dx()), float64(source.Bounds().Dy())
// Draw image to fit in the frame
// TODO Seems to have a transform bug here on draw image
scale := math.Min((dw-margin*2)/sw, (dh-margin*2)/sh)
gc.Save()
gc.Translate((dw-sw*scale)/2, (dh-sh*scale)/2)
gc.Scale(scale, scale)
gc.Rotate(0.2)
gc.DrawImage(source)
gc.Restore()
return nil
}

63
samples/gopher/gopher.go Normal file
View file

@ -0,0 +1,63 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
// Package gopher draws a gopher avatar based on a svg of:
// https://github.com/golang-samples/gopher-vector/
package gopher
import (
"image/color"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws a left hand and ear of a gopher. Afterwards it returns
// the filename. This should only be during testing.
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
gc.Save()
gc.Scale(0.5, 0.5)
// Draw a (partial) gopher
Draw(gc)
gc.Restore()
// Return the output filename
return samples.Output("gopher", ext), nil
}
// Draw a left hand and ear of a gopher using a gc thanks to
// https://github.com/golang-samples/gopher-vector/
func Draw(gc draw2d.GraphicContext) {
// Initialize Stroke Attribute
gc.SetLineWidth(3)
gc.SetLineCap(draw2d.RoundCap)
gc.SetStrokeColor(color.Black)
// Left hand
// <path fill-rule="evenodd" clip-rule="evenodd" fill="#F6D2A2" stroke="#000000" stroke-width="3" stroke-linecap="round" d="
// M10.634,300.493c0.764,15.751,16.499,8.463,23.626,3.539c6.765-4.675,8.743-0.789,9.337-10.015
// c0.389-6.064,1.088-12.128,0.744-18.216c-10.23-0.927-21.357,1.509-29.744,7.602C10.277,286.542,2.177,296.561,10.634,300.493"/>
gc.SetFillColor(color.RGBA{0xF6, 0xD2, 0xA2, 0xff})
gc.MoveTo(10.634, 300.493)
gc.RCubicCurveTo(0.764, 15.751, 16.499, 8.463, 23.626, 3.539)
gc.RCubicCurveTo(6.765, -4.675, 8.743, -0.789, 9.337, -10.015)
gc.RCubicCurveTo(0.389, -6.064, 1.088, -12.128, 0.744, -18.216)
gc.RCubicCurveTo(-10.23, -0.927, -21.357, 1.509, -29.744, 7.602)
gc.CubicCurveTo(10.277, 286.542, 2.177, 296.561, 10.634, 300.493)
gc.FillStroke()
// <path fill-rule="evenodd" clip-rule="evenodd" fill="#C6B198" stroke="#000000" stroke-width="3" stroke-linecap="round" d="
// M10.634,300.493c2.29-0.852,4.717-1.457,6.271-3.528"/>
gc.MoveTo(10.634, 300.493)
gc.RCubicCurveTo(2.29, -0.852, 4.717, -1.457, 6.271, -3.528)
gc.Stroke()
// Left Ear
// <path fill-rule="evenodd" clip-rule="evenodd" fill="#6AD7E5" stroke="#000000" stroke-width="3" stroke-linecap="round" d="
// M46.997,112.853C-13.3,95.897,31.536,19.189,79.956,50.74L46.997,112.853z"/>
gc.MoveTo(46.997, 112.853)
gc.CubicCurveTo(-13.3, 95.897, 31.536, 19.189, 79.956, 50.74)
gc.LineTo(46.997, 112.853)
gc.Close()
gc.Stroke()
}

View file

@ -0,0 +1,51 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff, Stani Michiels
// Package helloworld displays "Hello World" twice (one rotated) in a
// rounded rectangle.
package helloworld
import (
"image"
"image/color"
"math"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws "Hello World" and returns the filename. This should only be
// used during testing.
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
// Draw hello world
Draw(gc)
// Return the output filename
return samples.Output("helloworld", ext), nil
}
// Draw "Hello World"
func Draw(gc draw2d.GraphicContext) {
// Draw a rounded rectangle using default colors
draw2d.RoundRect(gc, 5, 5, 292, 205, 10, 10)
gc.FillStroke()
// Set the font luximbi.ttf
gc.SetFontData(draw2d.FontData{
Name: "luxi",
Family: draw2d.FontFamilyMono,
Style: draw2d.FontStyleBold | draw2d.FontStyleItalic})
// Set the fill text color to black
gc.SetFillColor(image.Black)
gc.SetDPI(72)
gc.SetFontSize(14)
// Display Hello World
gc.FillStringAt("Hello World", 8, 52)
gc.Save()
gc.SetFillColor(color.NRGBA{0xFF, 0x33, 0x33, 0xFF})
gc.Translate(145, 105)
gc.Rotate(math.Pi / 4)
gc.FillStringAt("Hello World", 0, 0)
gc.Restore()
}

View file

@ -0,0 +1,116 @@
// Open an OpenGl window and display a rectangle using a OpenGl GraphicContext
package main
import (
"image/color"
"log"
"runtime"
"github.com/go-gl/gl/v2.1/gl"
"github.com/go-gl/glfw/v3.1/glfw"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/draw2dgl"
)
var (
// global rotation
rotate int
width, height int
redraw = true
font draw2d.FontData
)
func reshape(window *glfw.Window, w, h int) {
gl.ClearColor(1, 1, 1, 1)
/* Establish viewing area to cover entire window. */
gl.Viewport(0, 0, int32(w), int32(h))
/* PROJECTION Matrix mode. */
gl.MatrixMode(gl.PROJECTION)
/* Reset project matrix. */
gl.LoadIdentity()
/* Map abstract coords directly to window coords. */
gl.Ortho(0, float64(w), 0, float64(h), -1, 1)
/* Invert Y axis so increasing Y goes down. */
gl.Scalef(1, -1, 1)
/* Shift origin up to upper-left corner. */
gl.Translatef(0, float32(-h), 0)
gl.Enable(gl.BLEND)
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
gl.Disable(gl.DEPTH_TEST)
width, height = w, h
redraw = true
}
// Ask to refresh
func invalidate() {
redraw = true
}
func display() {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.LineWidth(1)
gc := draw2dgl.NewGraphicContext(width, height)
gc.SetFontData(draw2d.FontData{
Name: "luxi",
Family: draw2d.FontFamilyMono,
Style: draw2d.FontStyleBold | draw2d.FontStyleItalic})
gc.BeginPath()
draw2d.RoundRect(gc, 200, 200, 600, 600, 100, 100)
gc.SetFillColor(color.RGBA{0, 0, 0, 0xff})
gc.Fill()
gl.Flush() /* Single buffered, so needs a flush. */
}
func init() {
runtime.LockOSThread()
}
func main() {
err := glfw.Init()
if err != nil {
panic(err)
}
defer glfw.Terminate()
width, height = 800, 800
window, err := glfw.CreateWindow(width, height, "Show RoundedRect", nil, nil)
if err != nil {
panic(err)
}
window.MakeContextCurrent()
window.SetSizeCallback(reshape)
window.SetKeyCallback(onKey)
window.SetCharCallback(onChar)
glfw.SwapInterval(1)
err = gl.Init()
if err != nil {
panic(err)
}
reshape(window, width, height)
for !window.ShouldClose() {
if redraw {
display()
window.SwapBuffers()
redraw = false
}
glfw.PollEvents()
// time.Sleep(2 * time.Second)
}
}
func onChar(w *glfw.Window, char rune) {
log.Println(char)
}
func onKey(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
switch {
case key == glfw.KeyEscape && action == glfw.Press,
key == glfw.KeyQ && action == glfw.Press:
w.SetShouldClose(true)
}
}

30
samples/line/line.go Normal file
View file

@ -0,0 +1,30 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff, Stani Michiels
// Package line draws vertically spaced lines.
package line
import (
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws vertically spaced lines and returns the filename.
// This should only be used during testing.
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
// Draw the line
for x := 5.0; x < 297; x += 10 {
Draw(gc, x, 0, x, 210)
}
// Return the output filename
return samples.Output("line", ext), nil
}
// Draw vertically spaced lines
func Draw(gc draw2d.GraphicContext, x0, y0, x1, y1 float64) {
// Draw a line
gc.MoveTo(x0, y0)
gc.LineTo(x1, y1)
gc.Stroke()
}

View file

@ -0,0 +1,54 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
// Package linecapjoin demonstrates the different line caps and joins.
package linecapjoin
import (
"image/color"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws the different line caps and joins.
// This should only be used during testing.
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
// Draw the line
const offset = 75.0
x := 35.0
caps := []draw2d.Cap{draw2d.ButtCap, draw2d.SquareCap, draw2d.RoundCap}
joins := []draw2d.Join{draw2d.BevelJoin, draw2d.MiterJoin, draw2d.RoundJoin}
for i := range caps {
Draw(gc, caps[i], joins[i], x, 50, x, 160, offset)
x += offset
}
// Return the output filename
return samples.Output("linecapjoin", ext), nil
}
// Draw a line with an angle with specified line cap and join
func Draw(gc draw2d.GraphicContext, cap draw2d.Cap, join draw2d.Join,
x0, y0, x1, y1, offset float64) {
gc.Save() // pdf: save & restore needed to isolate caps and joins
gc.SetLineCap(cap)
gc.SetLineJoin(join)
// Draw thick line
gc.SetStrokeColor(color.NRGBA{0x33, 0x33, 0x33, 0xFF})
gc.SetLineWidth(30.0)
gc.MoveTo(x0, y0)
gc.LineTo((x0+x1)/2+offset, (y0+y1)/2)
gc.LineTo(x1, y1)
gc.Stroke()
// Draw thin helping line
gc.SetStrokeColor(color.NRGBA{0xFF, 0x33, 0x33, 0xFF})
gc.SetLineWidth(2.56)
gc.MoveTo(x0, y0)
gc.LineTo((x0+x1)/2+offset, (y0+y1)/2)
gc.LineTo(x1, y1)
gc.Stroke()
gc.Restore()
}

View file

@ -0,0 +1,49 @@
// Package postscript reads the tiger.ps file and draws it to a backend.
package postscript
import (
"io/ioutil"
"os"
"strings"
"github.com/llgcode/ps"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/samples"
)
// Main draws the tiger
func Main(gc draw2d.GraphicContext, ext string) (string, error) {
gc.Save()
// flip the image
gc.Translate(0, 200)
gc.Scale(0.35, -0.35)
gc.Translate(70, -200)
// Tiger postscript drawing
tiger := samples.Resource("image", "tiger.ps", ext)
// Draw tiger
Draw(gc, tiger)
gc.Restore()
// Return the output filename
return samples.Output("postscript", ext), nil
}
// Draw a tiger
func Draw(gc draw2d.GraphicContext, filename string) {
// Open the postscript
src, err := os.OpenFile(filename, 0, 0)
if err != nil {
panic(err)
}
defer src.Close()
bytes, err := ioutil.ReadAll(src)
reader := strings.NewReader(string(bytes))
// Initialize and interpret the postscript
interpreter := ps.NewInterpreter(gc)
interpreter.Execute(reader)
}

View file

@ -0,0 +1,114 @@
// Open a OpenGL window and display a tiger interpreting a postscript file
package main
import (
"io/ioutil"
"log"
"math"
"os"
"runtime"
"strings"
"time"
"github.com/go-gl/gl/v2.1/gl"
"github.com/go-gl/glfw/v3.1/glfw"
"github.com/llgcode/draw2d/draw2dgl"
"github.com/llgcode/ps"
)
var postscriptContent string
var (
width, height int
rotate int
window *glfw.Window
)
func reshape(window *glfw.Window, w, h int) {
gl.ClearColor(1, 1, 1, 1)
//fmt.Println(gl.GetString(gl.EXTENSIONS))
gl.Viewport(0, 0, int32(w), int32(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)
gl.Disable(gl.DEPTH_TEST)
width, height = w, h
}
func display() {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
lastTime := time.Now()
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 := ps.NewInterpreter(gc)
reader := strings.NewReader(postscriptContent)
interpreter.Execute(reader)
dt := time.Now().Sub(lastTime)
log.Printf("Redraw in : %f ms\n", float64(dt)*1e-6)
gl.Flush() /* Single buffered, so needs a flush. */
}
func main() {
src, err := os.OpenFile("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)
err = glfw.Init()
if err != nil {
panic(err)
}
defer glfw.Terminate()
window, err = glfw.CreateWindow(800, 800, "Show Tiger in OpenGL", nil, nil)
if err != nil {
panic(err)
}
window.MakeContextCurrent()
window.SetSizeCallback(reshape)
window.SetKeyCallback(onKey)
glfw.SwapInterval(1)
err = gl.Init()
if err != nil {
panic(err)
}
reshape(window, 800, 800)
for !window.ShouldClose() {
display()
window.SwapBuffers()
glfw.PollEvents()
// time.Sleep(2 * time.Second)
}
}
func onKey(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
switch {
case key == glfw.KeyEscape && action == glfw.Press,
key == glfw.KeyQ && action == glfw.Press:
w.SetShouldClose(true)
}
}
func init() {
runtime.LockOSThread()
}

File diff suppressed because it is too large Load diff

24
samples/samples.go Normal file
View file

@ -0,0 +1,24 @@
// Package samples provides examples which can be used with different
// backends. They are also used for testing and coverage of the
// draw2d package.
package samples
import "fmt"
// Resource returns a resource filename for testing.
func Resource(folder, filename, ext string) string {
var root string
if ext == "pdf" {
root = "../"
}
return fmt.Sprintf("%sresource/%s/%s", root, folder, filename)
}
// Output returns the output filename for testing.
func Output(name, ext string) string {
var root string
if ext == "pdf" {
root = "../"
}
return fmt.Sprintf("%soutput/%s.%s", root, name, ext)
}

View file

@ -6,14 +6,13 @@ import (
"testing"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d.samples"
"github.com/llgcode/draw2d.samples/android"
"github.com/llgcode/draw2d.samples/frameimage"
"github.com/llgcode/draw2d.samples/gopher"
"github.com/llgcode/draw2d.samples/helloworld"
"github.com/llgcode/draw2d.samples/line"
"github.com/llgcode/draw2d.samples/linecapjoin"
"github.com/llgcode/draw2d.samples/postscript"
"github.com/llgcode/draw2d/samples/android"
"github.com/llgcode/draw2d/samples/frameimage"
"github.com/llgcode/draw2d/samples/gopher"
"github.com/llgcode/draw2d/samples/helloworld"
"github.com/llgcode/draw2d/samples/line"
"github.com/llgcode/draw2d/samples/linecapjoin"
"github.com/llgcode/draw2d/samples/postscript"
)
func TestSampleAndroid(t *testing.T) {
@ -26,7 +25,7 @@ func TestSampleGopher(t *testing.T) {
func TestSampleHelloWorld(t *testing.T) {
// Set the global folder for searching fonts
draw2d.SetFontFolder(samples.Dir("helloworld", ""))
draw2d.SetFontFolder("resource/font")
test(t, helloworld.Main)
}
@ -38,7 +37,7 @@ func TestSampleLine(t *testing.T) {
test(t, line.Main)
}
func TestSampleLineCap(t *testing.T) {
func TestSampleLineCapJoin(t *testing.T) {
test(t, linecapjoin.Main)
}

View file

@ -16,14 +16,14 @@ func test(t *testing.T, draw sample) {
dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
gc := draw2d.NewGraphicContext(dest)
// Draw Android logo
fn, err := draw(gc, "png")
output, err := draw(gc, "png")
if err != nil {
t.Errorf("Drawing %q failed: %v", fn, err)
t.Errorf("Drawing %q failed: %v", output, err)
return
}
// Save to png
err = draw2d.SaveToPngFile(fn, dest)
err = draw2d.SaveToPngFile(output, dest)
if err != nil {
t.Errorf("Saving %q failed: %v", fn, err)
t.Errorf("Saving %q failed: %v", output, err)
}
}