fixed dependencies
This commit is contained in:
6
vendor/gonum.org/v1/plot/text/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/plot/text/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 text provides types and functions to parse, format and render text.
|
||||
package text // import "gonum.org/v1/plot/text"
|
||||
268
vendor/gonum.org/v1/plot/text/latex.go
generated
vendored
Normal file
268
vendor/gonum.org/v1/plot/text/latex.go
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
// 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 text
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/go-latex/latex/drawtex"
|
||||
"github.com/go-latex/latex/font/ttf"
|
||||
"github.com/go-latex/latex/mtex"
|
||||
"github.com/go-latex/latex/tex"
|
||||
stdfnt "golang.org/x/image/font"
|
||||
|
||||
"gonum.org/v1/plot/font"
|
||||
"gonum.org/v1/plot/vg"
|
||||
)
|
||||
|
||||
// Latex parses, formats and renders LaTeX.
|
||||
type Latex struct {
|
||||
// Fonts is the cache of font faces used by this text handler.
|
||||
Fonts *font.Cache
|
||||
|
||||
// DPI is the dot-per-inch controlling the font resolution used by LaTeX.
|
||||
// If zero, the resolution defaults to 72.
|
||||
DPI float64
|
||||
}
|
||||
|
||||
var _ Handler = (*Latex)(nil)
|
||||
|
||||
// Cache returns the cache of fonts used by the text handler.
|
||||
func (hdlr Latex) Cache() *font.Cache {
|
||||
return hdlr.Fonts
|
||||
}
|
||||
|
||||
// Extents returns the Extents of a font.
|
||||
func (hdlr Latex) Extents(fnt font.Font) font.Extents {
|
||||
face := hdlr.Fonts.Lookup(fnt, fnt.Size)
|
||||
return face.Extents()
|
||||
}
|
||||
|
||||
// Lines splits a given block of text into separate lines.
|
||||
func (hdlr Latex) Lines(txt string) []string {
|
||||
txt = strings.TrimRight(txt, "\n")
|
||||
return strings.Split(txt, "\n")
|
||||
}
|
||||
|
||||
// Box returns the bounding box of the given non-multiline text where:
|
||||
// - width is the horizontal space from the origin.
|
||||
// - height is the vertical space above the baseline.
|
||||
// - depth is the vertical space below the baseline, a positive number.
|
||||
func (hdlr Latex) Box(txt string, fnt font.Font) (width, height, depth vg.Length) {
|
||||
cnv := drawtex.New()
|
||||
face := hdlr.Fonts.Lookup(fnt, fnt.Size)
|
||||
fnts := hdlr.fontsFor(fnt)
|
||||
box, err := mtex.Parse(txt, face.Font.Size.Points(), latexDPI, ttf.NewFrom(cnv, fnts))
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not parse math expression: %w", err))
|
||||
}
|
||||
|
||||
var sh tex.Ship
|
||||
sh.Call(0, 0, box.(tex.Tree))
|
||||
|
||||
width = vg.Length(box.Width())
|
||||
height = vg.Length(box.Height())
|
||||
depth = vg.Length(box.Depth())
|
||||
|
||||
// Add a bit of space, with a linegap as mtex.Box is returning
|
||||
// a very tight bounding box.
|
||||
// See gonum/plot#661.
|
||||
if depth != 0 {
|
||||
var (
|
||||
e = face.Extents()
|
||||
linegap = e.Height - (e.Ascent + e.Descent)
|
||||
)
|
||||
depth += linegap
|
||||
}
|
||||
|
||||
dpi := vg.Length(hdlr.dpi() / latexDPI)
|
||||
return width * dpi, height * dpi, depth * dpi
|
||||
}
|
||||
|
||||
// Draw renders the given text with the provided style and position
|
||||
// on the canvas.
|
||||
func (hdlr Latex) Draw(c vg.Canvas, txt string, sty Style, pt vg.Point) {
|
||||
cnv := drawtex.New()
|
||||
face := hdlr.Fonts.Lookup(sty.Font, sty.Font.Size)
|
||||
fnts := hdlr.fontsFor(sty.Font)
|
||||
box, err := mtex.Parse(txt, face.Font.Size.Points(), latexDPI, ttf.NewFrom(cnv, fnts))
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not parse math expression: %w", err))
|
||||
}
|
||||
|
||||
var sh tex.Ship
|
||||
sh.Call(0, 0, box.(tex.Tree))
|
||||
|
||||
w := box.Width()
|
||||
h := box.Height()
|
||||
d := box.Depth()
|
||||
|
||||
dpi := hdlr.dpi() / latexDPI
|
||||
o := latex{
|
||||
cnv: c,
|
||||
fonts: hdlr.Fonts,
|
||||
sty: sty,
|
||||
pt: pt,
|
||||
w: vg.Length(w * dpi),
|
||||
h: vg.Length((h + d) * dpi),
|
||||
cos: 1,
|
||||
sin: 0,
|
||||
}
|
||||
e := face.Extents()
|
||||
o.xoff = vg.Length(sty.XAlign) * o.w
|
||||
o.yoff = o.h + o.h*vg.Length(sty.YAlign) - (e.Height - e.Ascent)
|
||||
|
||||
if sty.Rotation != 0 {
|
||||
sin64, cos64 := math.Sincos(sty.Rotation)
|
||||
o.cos = vg.Length(cos64)
|
||||
o.sin = vg.Length(sin64)
|
||||
|
||||
o.cnv.Push()
|
||||
defer o.cnv.Pop()
|
||||
o.cnv.Rotate(sty.Rotation)
|
||||
}
|
||||
|
||||
err = o.Render(w/latexDPI, (h+d)/latexDPI, dpi, cnv)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not render math expression: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
func (hdlr *Latex) fontsFor(fnt font.Font) *ttf.Fonts {
|
||||
rm := fnt
|
||||
rm.Variant = "Serif"
|
||||
rm.Weight = stdfnt.WeightNormal
|
||||
rm.Style = stdfnt.StyleNormal
|
||||
|
||||
it := rm
|
||||
it.Style = stdfnt.StyleItalic
|
||||
|
||||
bf := rm
|
||||
bf.Style = stdfnt.StyleNormal
|
||||
bf.Weight = stdfnt.WeightBold
|
||||
|
||||
bfit := bf
|
||||
bfit.Style = stdfnt.StyleItalic
|
||||
|
||||
return &ttf.Fonts{
|
||||
Rm: hdlr.Fonts.Lookup(rm, fnt.Size).Face,
|
||||
Default: hdlr.Fonts.Lookup(rm, fnt.Size).Face,
|
||||
It: hdlr.Fonts.Lookup(it, fnt.Size).Face,
|
||||
Bf: hdlr.Fonts.Lookup(bf, fnt.Size).Face,
|
||||
BfIt: hdlr.Fonts.Lookup(bfit, fnt.Size).Face,
|
||||
}
|
||||
}
|
||||
|
||||
// latexDPI is the default LaTeX resolution used for computing the LaTeX
|
||||
// layout of equations and regular text.
|
||||
// Dimensions are then rescaled to the desired resolution.
|
||||
const latexDPI = 72.0
|
||||
|
||||
func (hdlr Latex) dpi() float64 {
|
||||
if hdlr.DPI == 0 {
|
||||
return latexDPI
|
||||
}
|
||||
return hdlr.DPI
|
||||
}
|
||||
|
||||
type latex struct {
|
||||
cnv vg.Canvas
|
||||
fonts *font.Cache
|
||||
sty Style
|
||||
pt vg.Point
|
||||
|
||||
w vg.Length
|
||||
h vg.Length
|
||||
|
||||
cos vg.Length
|
||||
sin vg.Length
|
||||
|
||||
xoff vg.Length
|
||||
yoff vg.Length
|
||||
}
|
||||
|
||||
var _ mtex.Renderer = (*latex)(nil)
|
||||
|
||||
func (r *latex) Render(width, height, dpi float64, c *drawtex.Canvas) error {
|
||||
r.cnv.SetColor(r.sty.Color)
|
||||
|
||||
for _, op := range c.Ops() {
|
||||
switch op := op.(type) {
|
||||
case drawtex.GlyphOp:
|
||||
r.drawGlyph(dpi, op)
|
||||
case drawtex.RectOp:
|
||||
r.drawRect(dpi, op)
|
||||
default:
|
||||
panic(fmt.Errorf("unknown drawtex op %T", op))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *latex) drawGlyph(dpi float64, op drawtex.GlyphOp) {
|
||||
pt := r.pt
|
||||
if r.sty.Rotation != 0 {
|
||||
pt.X, pt.Y = r.rotate(pt.X, pt.Y)
|
||||
}
|
||||
|
||||
pt = pt.Add(vg.Point{
|
||||
X: r.xoff + vg.Length(op.X*dpi),
|
||||
Y: r.yoff - vg.Length(op.Y*dpi),
|
||||
})
|
||||
|
||||
fnt := font.Face{
|
||||
Font: font.From(r.sty.Font, vg.Length(op.Glyph.Size)),
|
||||
Face: op.Glyph.Font,
|
||||
}
|
||||
r.cnv.FillString(fnt, pt, op.Glyph.Symbol)
|
||||
}
|
||||
|
||||
func (r *latex) drawRect(dpi float64, op drawtex.RectOp) {
|
||||
x1 := r.xoff + vg.Length(op.X1*dpi)
|
||||
x2 := r.xoff + vg.Length(op.X2*dpi)
|
||||
y1 := r.yoff - vg.Length(op.Y1*dpi)
|
||||
y2 := r.yoff - vg.Length(op.Y2*dpi)
|
||||
|
||||
pt := r.pt
|
||||
if r.sty.Rotation != 0 {
|
||||
pt.X, pt.Y = r.rotate(pt.X, pt.Y)
|
||||
}
|
||||
|
||||
pts := []vg.Point{
|
||||
vg.Point{X: x1, Y: y1}.Add(pt),
|
||||
vg.Point{X: x2, Y: y1}.Add(pt),
|
||||
vg.Point{X: x2, Y: y2}.Add(pt),
|
||||
vg.Point{X: x1, Y: y2}.Add(pt),
|
||||
vg.Point{X: x1, Y: y1}.Add(pt),
|
||||
}
|
||||
|
||||
fillPolygon(r.cnv, r.sty.Color, pts)
|
||||
}
|
||||
|
||||
func (r *latex) rotate(x, y vg.Length) (vg.Length, vg.Length) {
|
||||
u := x*r.cos + y*r.sin
|
||||
v := y*r.cos - x*r.sin
|
||||
return u, v
|
||||
}
|
||||
|
||||
// FillPolygon fills a polygon with the given color.
|
||||
func fillPolygon(c vg.Canvas, clr color.Color, pts []vg.Point) {
|
||||
if len(pts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
c.SetColor(clr)
|
||||
p := make(vg.Path, 0, len(pts)+1)
|
||||
p.Move(pts[0])
|
||||
for _, pt := range pts[1:] {
|
||||
p.Line(pt)
|
||||
}
|
||||
p.Close()
|
||||
c.Fill(p)
|
||||
}
|
||||
86
vendor/gonum.org/v1/plot/text/plain.go
generated
vendored
Normal file
86
vendor/gonum.org/v1/plot/text/plain.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// 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 text // import "gonum.org/v1/plot/text"
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"gonum.org/v1/plot/font"
|
||||
"gonum.org/v1/plot/vg"
|
||||
)
|
||||
|
||||
// Plain is a text/plain handler.
|
||||
type Plain struct {
|
||||
Fonts *font.Cache
|
||||
}
|
||||
|
||||
var _ Handler = (*Plain)(nil)
|
||||
|
||||
// Cache returns the cache of fonts used by the text handler.
|
||||
func (hdlr Plain) Cache() *font.Cache {
|
||||
return hdlr.Fonts
|
||||
}
|
||||
|
||||
// Extents returns the Extents of a font.
|
||||
func (hdlr Plain) Extents(fnt font.Font) font.Extents {
|
||||
face := hdlr.Fonts.Lookup(fnt, fnt.Size)
|
||||
return face.Extents()
|
||||
}
|
||||
|
||||
// Lines splits a given block of text into separate lines.
|
||||
func (hdlr Plain) Lines(txt string) []string {
|
||||
txt = strings.TrimRight(txt, "\n")
|
||||
return strings.Split(txt, "\n")
|
||||
}
|
||||
|
||||
// Box returns the bounding box of the given non-multiline text where:
|
||||
// - width is the horizontal space from the origin.
|
||||
// - height is the vertical space above the baseline.
|
||||
// - depth is the vertical space below the baseline, a positive number.
|
||||
func (hdlr Plain) Box(txt string, fnt font.Font) (width, height, depth vg.Length) {
|
||||
face := hdlr.Fonts.Lookup(fnt, fnt.Size)
|
||||
ext := face.Extents()
|
||||
width = face.Width(txt)
|
||||
height = ext.Ascent
|
||||
depth = ext.Descent
|
||||
|
||||
return width, height, depth
|
||||
}
|
||||
|
||||
// Draw renders the given text with the provided style and position
|
||||
// on the canvas.
|
||||
func (hdlr Plain) Draw(c vg.Canvas, txt string, sty Style, pt vg.Point) {
|
||||
txt = strings.TrimRight(txt, "\n")
|
||||
if len(txt) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
fnt := hdlr.Fonts.Lookup(sty.Font, sty.Font.Size)
|
||||
c.SetColor(sty.Color)
|
||||
|
||||
if sty.Rotation != 0 {
|
||||
c.Push()
|
||||
c.Rotate(sty.Rotation)
|
||||
}
|
||||
|
||||
sin64, cos64 := math.Sincos(sty.Rotation)
|
||||
cos := vg.Length(cos64)
|
||||
sin := vg.Length(sin64)
|
||||
pt.X, pt.Y = pt.Y*sin+pt.X*cos, pt.Y*cos-pt.X*sin
|
||||
|
||||
lines := hdlr.Lines(txt)
|
||||
ht := sty.Height(txt)
|
||||
pt.Y += ht*vg.Length(sty.YAlign) - fnt.Extents().Ascent
|
||||
for i, line := range lines {
|
||||
xoffs := vg.Length(sty.XAlign) * fnt.Width(line)
|
||||
n := vg.Length(len(lines) - i)
|
||||
c.FillString(fnt, pt.Add(vg.Point{X: xoffs, Y: n * sty.Font.Size}), line)
|
||||
}
|
||||
|
||||
if sty.Rotation != 0 {
|
||||
c.Pop()
|
||||
}
|
||||
}
|
||||
200
vendor/gonum.org/v1/plot/text/text.go
generated
vendored
Normal file
200
vendor/gonum.org/v1/plot/text/text.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright ©2021 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 text
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
"gonum.org/v1/plot/font"
|
||||
"gonum.org/v1/plot/vg"
|
||||
)
|
||||
|
||||
// Handler parses, formats and renders text.
|
||||
type Handler interface {
|
||||
// Cache returns the cache of fonts used by the text handler.
|
||||
Cache() *font.Cache
|
||||
|
||||
// Extents returns the Extents of a font.
|
||||
Extents(fnt font.Font) font.Extents
|
||||
|
||||
// Lines splits a given block of text into separate lines.
|
||||
Lines(txt string) []string
|
||||
|
||||
// Box returns the bounding box of the given non-multiline text where:
|
||||
// - width is the horizontal space from the origin.
|
||||
// - height is the vertical space above the baseline.
|
||||
// - depth is the vertical space below the baseline, a positive number.
|
||||
Box(txt string, fnt font.Font) (width, height, depth vg.Length)
|
||||
|
||||
// Draw renders the given text with the provided style and position
|
||||
// on the canvas.
|
||||
Draw(c vg.Canvas, txt string, sty Style, pt vg.Point)
|
||||
}
|
||||
|
||||
// XAlignment specifies text alignment in the X direction. Three preset
|
||||
// options are available, but an arbitrary alignment
|
||||
// can also be specified using XAlignment(desired number).
|
||||
type XAlignment float64
|
||||
|
||||
const (
|
||||
// XLeft aligns the left edge of the text with the specified location.
|
||||
XLeft XAlignment = 0
|
||||
// XCenter aligns the horizontal center of the text with the specified location.
|
||||
XCenter XAlignment = -0.5
|
||||
// XRight aligns the right edge of the text with the specified location.
|
||||
XRight XAlignment = -1
|
||||
)
|
||||
|
||||
// YAlignment specifies text alignment in the Y direction. Three preset
|
||||
// options are available, but an arbitrary alignment
|
||||
// can also be specified using YAlignment(desired number).
|
||||
type YAlignment float64
|
||||
|
||||
const (
|
||||
// YTop aligns the top of of the text with the specified location.
|
||||
YTop YAlignment = -1
|
||||
// YCenter aligns the vertical center of the text with the specified location.
|
||||
YCenter YAlignment = -0.5
|
||||
// YBottom aligns the bottom of the text with the specified location.
|
||||
YBottom YAlignment = 0
|
||||
)
|
||||
|
||||
// Position specifies the text position.
|
||||
const (
|
||||
PosLeft = -1
|
||||
PosBottom = -1
|
||||
PosCenter = 0
|
||||
PosTop = +1
|
||||
PosRight = +1
|
||||
)
|
||||
|
||||
// Style describes what text will look like.
|
||||
type Style struct {
|
||||
// Color is the text color.
|
||||
Color color.Color
|
||||
|
||||
// Font is the font description.
|
||||
Font font.Font
|
||||
|
||||
// Rotation is the text rotation in radians, performed around the axis
|
||||
// defined by XAlign and YAlign.
|
||||
Rotation float64
|
||||
|
||||
// XAlign and YAlign specify the alignment of the text.
|
||||
XAlign XAlignment
|
||||
YAlign YAlignment
|
||||
|
||||
// Handler parses and formats text according to a given
|
||||
// dialect (Markdown, LaTeX, plain, ...)
|
||||
// The default is a plain text handler.
|
||||
Handler Handler
|
||||
}
|
||||
|
||||
// FontExtents returns the extents of this Style's font.
|
||||
func (s Style) FontExtents() font.Extents {
|
||||
return s.Handler.Extents(s.Font)
|
||||
}
|
||||
|
||||
// Width returns the width of lines of text
|
||||
// when using the given font before any text rotation is applied.
|
||||
func (s Style) Width(txt string) (max vg.Length) {
|
||||
w, _ := s.box(txt)
|
||||
return w
|
||||
}
|
||||
|
||||
// Height returns the height of the text when using
|
||||
// the given font before any text rotation is applied.
|
||||
func (s Style) Height(txt string) vg.Length {
|
||||
_, h := s.box(txt)
|
||||
return h
|
||||
}
|
||||
|
||||
// box returns the bounding box of a possibly multi-line text.
|
||||
func (s Style) box(txt string) (w, h vg.Length) {
|
||||
var (
|
||||
lines = s.Handler.Lines(txt)
|
||||
e = s.FontExtents()
|
||||
linegap = (e.Height - e.Ascent - e.Descent)
|
||||
)
|
||||
for i, line := range lines {
|
||||
ww, hh, dd := s.Handler.Box(line, s.Font)
|
||||
if ww > w {
|
||||
w = ww
|
||||
}
|
||||
h += hh + dd
|
||||
if i > 0 {
|
||||
h += linegap
|
||||
}
|
||||
}
|
||||
|
||||
return w, h
|
||||
}
|
||||
|
||||
// Rectangle returns a rectangle giving the bounds of
|
||||
// this text assuming that it is drawn at (0, 0).
|
||||
func (s Style) Rectangle(txt string) vg.Rectangle {
|
||||
e := s.Handler.Extents(s.Font)
|
||||
w, h := s.box(txt)
|
||||
desc := vg.Length(e.Height - e.Ascent) // descent + linegap
|
||||
xoff := vg.Length(s.XAlign) * w
|
||||
yoff := vg.Length(s.YAlign)*h - desc
|
||||
|
||||
// lower left corner
|
||||
p1 := rotatePoint(s.Rotation, vg.Point{X: xoff, Y: yoff})
|
||||
// upper left corner
|
||||
p2 := rotatePoint(s.Rotation, vg.Point{X: xoff, Y: h + yoff})
|
||||
// lower right corner
|
||||
p3 := rotatePoint(s.Rotation, vg.Point{X: w + xoff, Y: yoff})
|
||||
// upper right corner
|
||||
p4 := rotatePoint(s.Rotation, vg.Point{X: w + xoff, Y: h + yoff})
|
||||
|
||||
return vg.Rectangle{
|
||||
Max: vg.Point{
|
||||
X: max(p1.X, p2.X, p3.X, p4.X),
|
||||
Y: max(p1.Y, p2.Y, p3.Y, p4.Y),
|
||||
},
|
||||
Min: vg.Point{
|
||||
X: min(p1.X, p2.X, p3.X, p4.X),
|
||||
Y: min(p1.Y, p2.Y, p3.Y, p4.Y),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// rotatePoint applies rotation theta (in radians) about the origin to point p.
|
||||
func rotatePoint(theta float64, p vg.Point) vg.Point {
|
||||
if theta == 0 {
|
||||
return p
|
||||
}
|
||||
x := float64(p.X)
|
||||
y := float64(p.Y)
|
||||
|
||||
sin, cos := math.Sincos(theta)
|
||||
|
||||
return vg.Point{
|
||||
X: vg.Length(x*cos - y*sin),
|
||||
Y: vg.Length(y*cos + x*sin),
|
||||
}
|
||||
}
|
||||
|
||||
func max(d ...vg.Length) vg.Length {
|
||||
o := vg.Length(math.Inf(-1))
|
||||
for _, dd := range d {
|
||||
if dd > o {
|
||||
o = dd
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func min(d ...vg.Length) vg.Length {
|
||||
o := vg.Length(math.Inf(1))
|
||||
for _, dd := range d {
|
||||
if dd < o {
|
||||
o = dd
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
Reference in New Issue
Block a user