Skip to content

vg/vggio: first import of a Gio-backed canvas #628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: cgo-dependencies
run: sudo apt install pkg-config libgles2-mesa-dev libxkbcommon-dev libxkbcommon-x11-dev
- name: golangci-lint
uses: golangci/golangci-lint-action@v1
with:
Expand Down
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sudo: false
sudo: true

language: go
go_import_path: gonum.org/v1/plot
Expand Down Expand Up @@ -29,6 +29,9 @@ before_install:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls

before_script:
- sudo apt-get install -qq pkg-config libgles2-mesa-dev libxkbcommon-dev libxkbcommon-x11-dev

# Get deps, build, test, and ensure the code is gofmt'ed.
# If we are building as gonum, then we have access to the coveralls api key, so we can run coverage as well.
script:
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ module gonum.org/v1/plot
go 1.13

require (
gioui.org v0.0.0-20200618124658-602d54dc5ef7
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af
github.com/fogleman/gg v1.3.0
github.com/go-latex/latex v0.0.0-20200518072620-0806b477ea35
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/jung-kurt/gofpdf v1.16.2
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3
golang.org/x/image v0.0.0-20200618115811-c13761719519
gonum.org/v1/gonum v0.7.0
rsc.io/pdf v0.1.1
)
26 changes: 21 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20200618124658-602d54dc5ef7 h1:PH02mpvkp5MNZcqi/wWY+YJTG5kvvuyc6kJ/efTGfXE=
gioui.org v0.0.0-20200618124658-602d54dc5ef7/go.mod h1:jiUwifN9cRl/zmco43aAqh0aV+s9GbhG13KcD+gEpkU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af h1:wVe6/Ea46ZMeNkQjjBW6xcqyQA/j5e0D6GytH95g0gQ=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
Expand All @@ -9,6 +12,7 @@ github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-latex/latex v0.0.0-20200518072620-0806b477ea35 h1:uroDDLmuCK5Pz5J/Ef5vCL6F0sJmAtZFTm0/cF027F4=
github.com/go-latex/latex v0.0.0-20200518072620-0806b477ea35/go.mod h1:PNI+CcWytn/2Z/9f1SGOOYn0eILruVyp0v2/iAs8asQ=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
Expand All @@ -24,25 +28,37 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 h1:n9HxLrNxWWtEb1cA950nuEEj3QnKbtsCJ6KjcgisNUs=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067 h1:KYGJGHOQy8oSi1fDlSpcZF0+juKwk/hEMv5SiwHogR0=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw=
gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM=
Expand Down
74 changes: 74 additions & 0 deletions vg/vggio/example_vg_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright ©2020 The Gonum 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 vggio_test

import (
"log"
"os"
"time"

"gioui.org/app"
"gioui.org/io/key"
"gioui.org/io/system"
"gioui.org/unit"

"gonum.org/v1/plot"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
"gonum.org/v1/plot/vg/vggio"
)

func ExampleCanvas() {
const (
w = 20 * vg.Centimeter
h = 15 * vg.Centimeter
dpi = 96
)
go func(w, h vg.Length) {
win := app.NewWindow(
app.Title("Gonum"),
app.Size(
unit.Px(float32(w.Dots(dpi))),
unit.Px(float32(h.Dots(dpi))),
),
)
defer win.Close()

done := time.NewTimer(2 * time.Second)
defer done.Stop()

for {
select {
case e := <-win.Events():
switch e := e.(type) {
case system.FrameEvent:
p, err := plot.New()
if err != nil {
log.Fatalf("could not create plot: %+v", err)
}
p.Title.Text = "My title"
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"

cnv := vggio.New(e, w, h, vggio.UseDPI(dpi))
p.Draw(draw.New(cnv))
cnv.Paint(e)

case key.Event:
switch e.Name {
case "Q", key.NameEscape:
os.Exit(0)
}
}
case <-done.C:
os.Exit(0)
}
}
}(w, h)

app.Main()

// Output:
}
104 changes: 104 additions & 0 deletions vg/vggio/vg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright ©2020 The Gonum 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 vggio provides a vg.Canvas implementation backed by Gioui.
package vggio // import "gonum.org/v1/plot/vg/vggio"

import (
"image/color"

"gioui.org/f32"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint"

"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/vgimg"
)

// Canvas implements the vg.Canvas interface,
// drawing to an image.Image using vgimg and painting that image
// into a Gioui context.
type Canvas struct {
*vgimg.Canvas
gtx layout.Context
}

// DefaultDPI is the default dot resolution for image
// drawing in dots per inch.
const DefaultDPI = 96

// New returns a new image canvas with the provided dimensions and options.
// The currently accepted options are UseDPI and UseBackgroundColor.
// If the resolution or background color are not specified, defaults are used.
func New(e system.FrameEvent, w, h vg.Length, opts ...option) *Canvas {
cfg := &config{
dpi: DefaultDPI,
bkg: color.White,
}
for _, opt := range opts {
opt(cfg)
}
c := &Canvas{
gtx: layout.NewContext(new(op.Ops), e),
Canvas: vgimg.NewWith(
vgimg.UseDPI(cfg.dpi),
vgimg.UseWH(w, h),
vgimg.UseBackgroundColor(cfg.bkg),
),
}
return c
}

type config struct {
dpi int
bkg color.Color
}

type option func(*config)

// UseDPI sets the dots per inch of a canvas. It should only be
// used as an option argument when initializing a new canvas.
func UseDPI(dpi int) option {
if dpi <= 0 {
panic("DPI must be > 0.")
}
return func(c *config) {
c.dpi = dpi
}
}

// UseBackgroundColor specifies the image background color.
// Without UseBackgroundColor, the default color is white.
func UseBackgroundColor(c color.Color) option {
return func(cfg *config) {
cfg.bkg = c
}
}

func (c *Canvas) pt32(p vg.Point) f32.Point {
_, h := c.Size()
dpi := c.DPI()
return f32.Point{
X: float32(p.X.Dots(dpi)),
Y: float32(h.Dots(dpi) - p.Y.Dots(dpi)),
}
}

// Paint paints the canvas' content on the screen.
func (c *Canvas) Paint(e system.FrameEvent) {
w, h := c.Size()
box := vg.Rectangle{Max: vg.Point{X: w, Y: h}}
img := c.Canvas.Image()
ops := c.gtx.Ops
min := c.pt32(box.Min)
max := c.pt32(box.Max)
r32 := f32.Rect(min.X, min.Y, max.X, max.Y)

paint.NewImageOp(img).Add(ops)
paint.PaintOp{Rect: r32}.Add(ops)

e.Frame(ops)
}