fixed dependencies
This commit is contained in:
41
vendor/github.com/go-latex/latex/.travis.yml
generated
vendored
Normal file
41
vendor/github.com/go-latex/latex/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
sudo: false
|
||||
go_import_path: github.com/go-latex/latex
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.14.x
|
||||
- 1.13.x
|
||||
- master
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
arch:
|
||||
- amd64
|
||||
|
||||
env:
|
||||
global:
|
||||
- GO111MODULE=on
|
||||
- GOFLAGS="-mod=readonly"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/go-build
|
||||
- $HOME/gopath/pkg/mod
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
autocrlf: input
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- go: master
|
||||
|
||||
script:
|
||||
- go install -v ./...
|
||||
- go run ./ci/run-tests.go -coverpkg=github.com/go-latex/latex/... -race
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
12
vendor/github.com/go-latex/latex/AUTHORS
generated
vendored
Normal file
12
vendor/github.com/go-latex/latex/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is the official list of go-latex authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Google Inc
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
19
vendor/github.com/go-latex/latex/CONTRIBUTORS
generated
vendored
Normal file
19
vendor/github.com/go-latex/latex/CONTRIBUTORS
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the go-latex
|
||||
# project.
|
||||
#
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees would be listed here
|
||||
# but not in AUTHORS, because Google would hold the copyright.
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file.
|
||||
#
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
|
||||
Dan Lorenc <lorenc.d@gmail.com>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
23
vendor/github.com/go-latex/latex/LICENSE
generated
vendored
Normal file
23
vendor/github.com/go-latex/latex/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Copyright ©2020 The go-latex Authors. 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.
|
||||
* Neither the name of the go-latex project nor the names of its authors and
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
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.
|
||||
74
vendor/github.com/go-latex/latex/README.md
generated
vendored
Normal file
74
vendor/github.com/go-latex/latex/README.md
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# latex
|
||||
|
||||
[](https://pkg.go.dev/github.com/go-latex/latex)
|
||||
[](https://github.com/go-latex/latex/releases)
|
||||
[](https://github.com/go-latex/latex/actions)
|
||||
[](https://codecov.io/gh/go-latex/latex)
|
||||
[](https://godoc.org/github.com/go-latex/latex)
|
||||
[](https://github.com/go-latex/latex/raw/master/LICENSE)
|
||||
|
||||
`latex` is a package holding Go tools for [LaTeX](https://www.latex-project.org/).
|
||||
|
||||
`latex` is supposed to provide features akin to `MathJax` or `matplotlib`'s `TeX` capabilities.
|
||||
_ie:_ it is supposed to be able to draw mathematical equations, in pure-Go.
|
||||
|
||||
`latex` is *NOT SUPPOSED* to be a complete typesetting system like `LaTeX` or `TeX`.
|
||||
|
||||
For this, please take look at:
|
||||
|
||||
- [Star-TeX](https://star-tex.org)
|
||||
- [Star-TeX (git repo)](https://git.sr.ht/~sbinet/star-tex)
|
||||
|
||||
Eventually, `go-latex/latex` might just use `star-tex.org/...` to provide the `MathJax`-like capabilities.
|
||||
(once `star-tex.org/...` is ready and exports a nice Go API.)
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$> go get github.com/go-latex/latex/...
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation is served by [godoc](https://godoc.org), here:
|
||||
|
||||
- [godoc.org/github.com/go-latex/latex](https://godoc.org/github.com/go-latex/latex)
|
||||
|
||||
The main use case for `go-latex/latex` is to draw a mathematical equation.
|
||||
This is typically achieved via the `latex/mtex.Render` function that knows how to render mathematical `TeX` equations to a renderer interface.
|
||||
|
||||
### Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/go-latex/latex/drawtex/drawimg"
|
||||
"github.com/go-latex/latex/mtex"
|
||||
)
|
||||
|
||||
func main() {
|
||||
f, err := os.Create("output.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
dst := drawimg.NewRenderer(f)
|
||||
err = mtex.Render(dst, `$f(x) = \frac{\sqrt{x +20}}{2\pi} +\hbar \sum y\partial y$`, 12, 72, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## LICENSE
|
||||
|
||||
BSD-3.
|
||||
266
vendor/github.com/go-latex/latex/ast/ast.go
generated
vendored
Normal file
266
vendor/github.com/go-latex/latex/ast/ast.go
generated
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
// Copyright ©2020 The go-latex 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 ast declares the types used to represent syntax trees for
|
||||
// LaTeX documents.
|
||||
package ast // import "github.com/go-latex/latex/ast"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-latex/latex/token"
|
||||
)
|
||||
|
||||
// Node is a node in a LaTeX document.
|
||||
type Node interface {
|
||||
Pos() token.Pos // position of first character belonging to the node.
|
||||
End() token.Pos // position of first character immediately after the node.
|
||||
|
||||
isNode()
|
||||
}
|
||||
|
||||
// List is a collection of nodes.
|
||||
type List []Node
|
||||
|
||||
func (x List) isNode() {}
|
||||
func (x List) Pos() token.Pos {
|
||||
if len(x) == 0 {
|
||||
return -1
|
||||
}
|
||||
return x[0].Pos()
|
||||
}
|
||||
|
||||
func (x List) End() token.Pos {
|
||||
if len(x) == 0 {
|
||||
return -1
|
||||
}
|
||||
return x[len(x)-1].End()
|
||||
}
|
||||
|
||||
// Macro is a LaTeX macro.
|
||||
// ex:
|
||||
// \sqrt{a}
|
||||
// \frac{num}{den}
|
||||
type Macro struct {
|
||||
Name *Ident
|
||||
Args List
|
||||
}
|
||||
|
||||
func (x *Macro) isNode() {}
|
||||
func (x *Macro) Pos() token.Pos { return x.Name.Pos() }
|
||||
func (x *Macro) End() token.Pos {
|
||||
if len(x.Args) > 0 {
|
||||
return x.Args[len(x.Args)-1].End()
|
||||
}
|
||||
return x.Name.End()
|
||||
}
|
||||
|
||||
// Arg is an argument of a macro.
|
||||
// ex:
|
||||
// {a} in \sqrt{a}
|
||||
type Arg struct {
|
||||
Lbrace token.Pos // position of '{'
|
||||
List List // or stmt?
|
||||
Rbrace token.Pos // position of '}'
|
||||
}
|
||||
|
||||
func (x *Arg) Pos() token.Pos { return x.Lbrace }
|
||||
func (x *Arg) End() token.Pos { return x.Rbrace }
|
||||
func (x *Arg) isNode() {}
|
||||
|
||||
// OptArg is an optional argument of a macro
|
||||
// ex:
|
||||
// [n] in \sqrt[n]{a}
|
||||
type OptArg struct {
|
||||
Lbrack token.Pos // position of '['
|
||||
List List
|
||||
Rbrack token.Pos // position of ']'
|
||||
}
|
||||
|
||||
func (x *OptArg) Pos() token.Pos { return x.Lbrack }
|
||||
func (x *OptArg) End() token.Pos { return x.Rbrack }
|
||||
func (x *OptArg) isNode() {}
|
||||
|
||||
type Ident struct {
|
||||
NamePos token.Pos // identifier position
|
||||
Name string // identifier name
|
||||
}
|
||||
|
||||
func (x *Ident) Pos() token.Pos { return x.NamePos }
|
||||
func (x *Ident) End() token.Pos { return token.Pos(int(x.NamePos) + len(x.Name)) }
|
||||
func (x *Ident) isNode() {}
|
||||
|
||||
// MathExpr is a math expression.
|
||||
// ex:
|
||||
// $f(x) \doteq \sqrt[n]{x}$
|
||||
// \[ x^n + y^n = z^n \]
|
||||
type MathExpr struct {
|
||||
Delim string // delimiter used for this math expression.
|
||||
Left token.Pos // position of opening '$', '\(', '\[' or '\begin{math}'
|
||||
List List
|
||||
Right token.Pos // position of closing '$', '\)', '\]' or '\end{math}'
|
||||
}
|
||||
|
||||
func (x *MathExpr) isNode() {}
|
||||
func (x *MathExpr) Pos() token.Pos { return x.Left }
|
||||
func (x *MathExpr) End() token.Pos { return x.Right }
|
||||
|
||||
type Word struct {
|
||||
WordPos token.Pos
|
||||
Text string
|
||||
}
|
||||
|
||||
func (x *Word) isNode() {}
|
||||
func (x *Word) Pos() token.Pos { return x.WordPos }
|
||||
func (x *Word) End() token.Pos { return token.Pos(int(x.WordPos) + len(x.Text)) }
|
||||
|
||||
type Literal struct {
|
||||
LitPos token.Pos
|
||||
Text string
|
||||
}
|
||||
|
||||
func (x *Literal) isNode() {}
|
||||
func (x *Literal) Pos() token.Pos { return x.LitPos }
|
||||
func (x *Literal) End() token.Pos { return token.Pos(int(x.LitPos) + len(x.Text)) }
|
||||
|
||||
type Symbol struct {
|
||||
SymPos token.Pos
|
||||
Text string
|
||||
}
|
||||
|
||||
func (x *Symbol) isNode() {}
|
||||
func (x *Symbol) Pos() token.Pos { return x.SymPos }
|
||||
func (x *Symbol) End() token.Pos { return token.Pos(int(x.SymPos) + len(x.Text)) }
|
||||
|
||||
// Sub is a subscript node.
|
||||
//
|
||||
// e.g.: \sum_{i=0}
|
||||
type Sub struct {
|
||||
UnderPos token.Pos
|
||||
Node Node
|
||||
}
|
||||
|
||||
func (x *Sub) isNode() {}
|
||||
func (x *Sub) Pos() token.Pos { return x.UnderPos }
|
||||
func (x *Sub) End() token.Pos { return x.Node.End() }
|
||||
|
||||
// Sup is a superscript node.
|
||||
//
|
||||
// e.g.: \sum^{n}
|
||||
type Sup struct {
|
||||
HatPos token.Pos
|
||||
Node Node
|
||||
}
|
||||
|
||||
func (x *Sup) isNode() {}
|
||||
func (x *Sup) Pos() token.Pos { return x.HatPos }
|
||||
func (x *Sup) End() token.Pos { return x.Node.End() }
|
||||
|
||||
// Print prints node to w.
|
||||
func Print(o io.Writer, node Node) {
|
||||
switch node := node.(type) {
|
||||
case *Arg:
|
||||
fmt.Fprintf(o, "{")
|
||||
for i, n := range node.List {
|
||||
if i > 0 {
|
||||
fmt.Fprintf(o, ", ")
|
||||
}
|
||||
Print(o, n)
|
||||
}
|
||||
fmt.Fprintf(o, "}")
|
||||
|
||||
case *Ident:
|
||||
fmt.Fprintf(o, "ast.Ident{%q}", node.Name)
|
||||
|
||||
case *Macro:
|
||||
fmt.Fprintf(o, "ast.Macro{%q", node.Name.Name)
|
||||
switch len(node.Args) {
|
||||
case 0:
|
||||
// no-op
|
||||
default:
|
||||
fmt.Fprintf(o, ", Args:")
|
||||
for i, n := range node.Args {
|
||||
if i > 0 {
|
||||
fmt.Fprintf(o, ", ")
|
||||
}
|
||||
Print(o, n)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(o, "}")
|
||||
case *MathExpr:
|
||||
fmt.Fprintf(o, "ast.MathExpr{")
|
||||
switch len(node.List) {
|
||||
case 0:
|
||||
// no-op
|
||||
default:
|
||||
fmt.Fprintf(o, "List:")
|
||||
for i, n := range node.List {
|
||||
if i > 0 {
|
||||
fmt.Fprintf(o, ", ")
|
||||
}
|
||||
Print(o, n)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(o, "}")
|
||||
case *OptArg:
|
||||
fmt.Fprintf(o, "[")
|
||||
for i, n := range node.List {
|
||||
if i > 0 {
|
||||
fmt.Fprintf(o, ", ")
|
||||
}
|
||||
Print(o, n)
|
||||
}
|
||||
fmt.Fprintf(o, "]")
|
||||
case *Word:
|
||||
fmt.Fprintf(o, "ast.Word{%q}", node.Text)
|
||||
case *Literal:
|
||||
fmt.Fprintf(o, "ast.Lit{%q}", node.Text)
|
||||
case List:
|
||||
fmt.Fprintf(o, "ast.List{")
|
||||
for i, n := range node {
|
||||
if i > 0 {
|
||||
fmt.Fprintf(o, ", ")
|
||||
}
|
||||
Print(o, n)
|
||||
}
|
||||
fmt.Fprintf(o, "}")
|
||||
|
||||
case *Sub:
|
||||
fmt.Fprintf(o, "ast.Sub{")
|
||||
Print(o, node.Node)
|
||||
fmt.Fprintf(o, "}")
|
||||
|
||||
case *Sup:
|
||||
fmt.Fprintf(o, "ast.Sup{")
|
||||
Print(o, node.Node)
|
||||
fmt.Fprintf(o, "}")
|
||||
|
||||
case *Symbol:
|
||||
fmt.Fprintf(o, "ast.Symbol{%q}", node.Text)
|
||||
|
||||
// case *Op:
|
||||
// fmt.Fprintf(o, "ast.Op{%q}", node.Text)
|
||||
|
||||
case nil:
|
||||
fmt.Fprintf(o, "<nil>")
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("unknown node %T", node))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_ Node = (*List)(nil)
|
||||
_ Node = (*Arg)(nil)
|
||||
_ Node = (*Ident)(nil)
|
||||
_ Node = (*Macro)(nil)
|
||||
_ Node = (*MathExpr)(nil)
|
||||
_ Node = (*OptArg)(nil)
|
||||
_ Node = (*Word)(nil)
|
||||
_ Node = (*Literal)(nil)
|
||||
_ Node = (*Sup)(nil)
|
||||
_ Node = (*Sub)(nil)
|
||||
_ Node = (*Symbol)(nil)
|
||||
)
|
||||
88
vendor/github.com/go-latex/latex/ast/walk.go
generated
vendored
Normal file
88
vendor/github.com/go-latex/latex/ast/walk.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright ©2020 The go-latex 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 ast
|
||||
|
||||
import "fmt"
|
||||
|
||||
// A Visitor's Visit method is invoked for each node encountered by Walk.
|
||||
// If the result visitor w is not nil, Walk visits each of the children
|
||||
// of node with the visitor w, followed by a call of w.Visit(nil).
|
||||
type Visitor interface {
|
||||
Visit(node Node) (w Visitor)
|
||||
}
|
||||
|
||||
// Walk traverses an AST in depth-first order: It starts by calling
|
||||
// v.Visit(node); node must not be nil. If the visitor w returned by
|
||||
// v.Visit(node) is not nil, Walk is invoked recursively with visitor
|
||||
// w for each of the non-nil children of node, followed by a call of
|
||||
// w.Visit(nil).
|
||||
func Walk(v Visitor, node Node) {
|
||||
if v = v.Visit(node); v == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch n := node.(type) {
|
||||
case List:
|
||||
for _, x := range n {
|
||||
Walk(v, x)
|
||||
}
|
||||
|
||||
case *Macro:
|
||||
if n.Name != nil {
|
||||
Walk(v, n.Name)
|
||||
}
|
||||
walkNodes(v, n.Args)
|
||||
|
||||
case *Arg:
|
||||
walkNodes(v, n.List)
|
||||
|
||||
case *OptArg:
|
||||
walkNodes(v, n.List)
|
||||
|
||||
case *Ident:
|
||||
// nothing to do.
|
||||
|
||||
case *MathExpr:
|
||||
walkNodes(v, n.List)
|
||||
|
||||
case *Word, *Literal, *Symbol:
|
||||
// nothing to do.
|
||||
|
||||
case *Sub:
|
||||
Walk(v, n.Node)
|
||||
|
||||
case *Sup:
|
||||
Walk(v, n.Node)
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("unknown ast node %#v (type=%T)", n, n))
|
||||
}
|
||||
|
||||
v.Visit(nil)
|
||||
}
|
||||
|
||||
func walkNodes(v Visitor, nodes []Node) {
|
||||
for _, x := range nodes {
|
||||
Walk(v, x)
|
||||
}
|
||||
}
|
||||
|
||||
type inspector func(Node) bool
|
||||
|
||||
func (f inspector) Visit(node Node) Visitor {
|
||||
if f(node) {
|
||||
return f
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inspect traverses an AST in depth-first order: It starts by calling
|
||||
// f(node); node must not be nil. If f returns true, Inspect invokes f
|
||||
// recursively for each of the non-nil children of node, followed by a
|
||||
// call of f(nil).
|
||||
//
|
||||
func Inspect(node Node, f func(Node) bool) {
|
||||
Walk(inspector(f), node)
|
||||
}
|
||||
62
vendor/github.com/go-latex/latex/drawtex/canvas.go
generated
vendored
Normal file
62
vendor/github.com/go-latex/latex/drawtex/canvas.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright ©2020 The go-latex 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 drawtex describes the graphics interface for drawing LaTeX.
|
||||
package drawtex // import "github.com/go-latex/latex/drawtex"
|
||||
|
||||
import (
|
||||
"github.com/go-latex/latex/font"
|
||||
"golang.org/x/image/font/sfnt"
|
||||
)
|
||||
|
||||
type Canvas struct {
|
||||
ops []Op
|
||||
}
|
||||
|
||||
func New() *Canvas {
|
||||
return &Canvas{}
|
||||
}
|
||||
|
||||
func (c *Canvas) RenderGlyph(x, y float64, infos Glyph) {
|
||||
c.ops = append(c.ops, GlyphOp{x, y, infos})
|
||||
}
|
||||
|
||||
func (c *Canvas) RenderRectFilled(x1, y1, x2, y2 float64) {
|
||||
c.ops = append(c.ops, RectOp{x1, y1, x2, y2})
|
||||
}
|
||||
|
||||
func (c *Canvas) Ops() []Op { return c.ops }
|
||||
|
||||
type Op interface {
|
||||
isOp()
|
||||
}
|
||||
|
||||
type GlyphOp struct {
|
||||
X, Y float64
|
||||
Glyph Glyph
|
||||
}
|
||||
|
||||
func (GlyphOp) isOp() {}
|
||||
|
||||
type RectOp struct {
|
||||
X1, Y1 float64
|
||||
X2, Y2 float64
|
||||
}
|
||||
|
||||
func (RectOp) isOp() {}
|
||||
|
||||
type Glyph struct {
|
||||
Font *sfnt.Font
|
||||
Size float64
|
||||
Postscript string
|
||||
Metrics font.Metrics
|
||||
Symbol string
|
||||
Num sfnt.GlyphIndex
|
||||
Offset float64
|
||||
}
|
||||
|
||||
var (
|
||||
_ Op = (*GlyphOp)(nil)
|
||||
_ Op = (*RectOp)(nil)
|
||||
)
|
||||
52
vendor/github.com/go-latex/latex/font/font.go
generated
vendored
Normal file
52
vendor/github.com/go-latex/latex/font/font.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright ©2020 The go-latex 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 font holds types to handle and abstract away font management.
|
||||
package font
|
||||
|
||||
// Font represents a font.
|
||||
type Font struct {
|
||||
Name string // Name is the LaTeX name of the font (regular, default, it, ...)
|
||||
Type string // Type is the LaTeX class of the font (it, rm, ...)
|
||||
Size float64 // Size is the font size in points.
|
||||
}
|
||||
|
||||
// Backend is the interface that allows to render math expressions.
|
||||
type Backend interface {
|
||||
// RenderGlyphs renders the glyph g at the reference point (x,y).
|
||||
RenderGlyph(x, y float64, font Font, symbol string, dpi float64)
|
||||
|
||||
// RenderRectFilled draws a filled black rectangle from (x1,y1) to (x2,y2).
|
||||
RenderRectFilled(x1, y1, x2, y2 float64)
|
||||
|
||||
// Kern returns the kerning distance between two symbols.
|
||||
Kern(ft1 Font, sym1 string, ft2 Font, sym2 string, dpi float64) float64
|
||||
|
||||
// Metrics returns the metrics.
|
||||
Metrics(symbol string, font Font, dpi float64, math bool) Metrics
|
||||
|
||||
// XHeight returns the xheight for the given font and dpi.
|
||||
XHeight(font Font, dpi float64) float64
|
||||
|
||||
// UnderlineThickness returns the line thickness that matches the given font.
|
||||
// It is used as a base unit for drawing lines such as in a fraction or radical.
|
||||
UnderlineThickness(font Font, dpi float64) float64
|
||||
}
|
||||
|
||||
// Metrics represents the metrics of a glyph in a given font.
|
||||
type Metrics struct {
|
||||
Advance float64 // Advance distance of the glyph, in points.
|
||||
Height float64 // Height of the glyph in points.
|
||||
Width float64 // Width of the glyph in points.
|
||||
|
||||
// Ink rectangle of the glyph.
|
||||
XMin, XMax, YMin, YMax float64
|
||||
|
||||
// Iceberg is the distance from the baseline to the top of the glyph.
|
||||
// Iceberg corresponds to TeX's definition of "height".
|
||||
Iceberg float64
|
||||
|
||||
// Slanted indicates whether the glyph is slanted.
|
||||
Slanted bool
|
||||
}
|
||||
308
vendor/github.com/go-latex/latex/font/ttf/ttf.go
generated
vendored
Normal file
308
vendor/github.com/go-latex/latex/font/ttf/ttf.go
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
// Copyright ©2020 The go-latex 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 ttf provides a truetype font Backend
|
||||
package ttf // import "github.com/go-latex/latex/font/ttf"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unicode"
|
||||
|
||||
"github.com/go-latex/latex/drawtex"
|
||||
"github.com/go-latex/latex/font"
|
||||
"github.com/go-latex/latex/internal/tex2unicode"
|
||||
stdfont "golang.org/x/image/font"
|
||||
"golang.org/x/image/font/gofont/gobold"
|
||||
"golang.org/x/image/font/gofont/gobolditalic"
|
||||
"golang.org/x/image/font/gofont/goitalic"
|
||||
"golang.org/x/image/font/gofont/goregular"
|
||||
"golang.org/x/image/font/opentype"
|
||||
"golang.org/x/image/font/sfnt"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
type Fonts struct {
|
||||
Default *sfnt.Font
|
||||
|
||||
Rm *sfnt.Font
|
||||
It *sfnt.Font
|
||||
Bf *sfnt.Font
|
||||
BfIt *sfnt.Font
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
canvas *drawtex.Canvas
|
||||
glyphs map[ttfKey]ttfVal
|
||||
fonts map[string]*sfnt.Font
|
||||
}
|
||||
|
||||
func New(cnv *drawtex.Canvas) *Backend {
|
||||
return NewFrom(cnv, &defaultFonts)
|
||||
}
|
||||
|
||||
func NewFrom(cnv *drawtex.Canvas, fnts *Fonts) *Backend {
|
||||
be := &Backend{
|
||||
canvas: cnv,
|
||||
glyphs: make(map[ttfKey]ttfVal),
|
||||
fonts: make(map[string]*sfnt.Font),
|
||||
}
|
||||
|
||||
be.fonts["default"] = fnts.Default
|
||||
be.fonts["regular"] = fnts.Rm
|
||||
be.fonts["rm"] = fnts.Rm
|
||||
be.fonts["it"] = fnts.It
|
||||
be.fonts["bf"] = fnts.Bf
|
||||
|
||||
return be
|
||||
}
|
||||
|
||||
// RenderGlyphs renders the glyph g at the reference point (x,y).
|
||||
func (be *Backend) RenderGlyph(x, y float64, font font.Font, symbol string, dpi float64) {
|
||||
glyph := be.getInfo(symbol, font, dpi, true)
|
||||
be.canvas.RenderGlyph(x, y, drawtex.Glyph{
|
||||
Font: glyph.font,
|
||||
Size: glyph.size,
|
||||
Postscript: glyph.postscript,
|
||||
Metrics: glyph.metrics,
|
||||
Symbol: string(glyph.rune),
|
||||
Num: glyph.glyph,
|
||||
Offset: glyph.offset,
|
||||
})
|
||||
}
|
||||
|
||||
// RenderRectFilled draws a filled black rectangle from (x1,y1) to (x2,y2).
|
||||
func (be *Backend) RenderRectFilled(x1, y1, x2, y2 float64) {
|
||||
be.canvas.RenderRectFilled(x1, y1, x2, y2)
|
||||
}
|
||||
|
||||
// Metrics returns the metrics.
|
||||
func (be *Backend) Metrics(symbol string, fnt font.Font, dpi float64, math bool) font.Metrics {
|
||||
return be.getInfo(symbol, fnt, dpi, math).metrics
|
||||
}
|
||||
|
||||
func (be *Backend) getInfo(symbol string, fnt font.Font, dpi float64, math bool) ttfVal {
|
||||
key := ttfKey{symbol, fnt, dpi}
|
||||
val, ok := be.glyphs[key]
|
||||
if ok {
|
||||
return val
|
||||
}
|
||||
|
||||
var (
|
||||
buf sfnt.Buffer
|
||||
hinting = hintingNone
|
||||
)
|
||||
|
||||
ft, rn, _ /*symbol*/, fontSize, slanted := be.getGlyph(symbol, fnt, math)
|
||||
|
||||
postscript, err := ft.Name(&buf, sfnt.NameIDPostScript)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not retrieve postscript name of font: %+v", err))
|
||||
}
|
||||
|
||||
idx, err := ft.GlyphIndex(&buf, rn)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not retrieve glyph index for %q: %+v", rn, err))
|
||||
}
|
||||
|
||||
symName, err := ft.GlyphName(&buf, idx)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not retrieve glyph name of %q: %+v", rn, err))
|
||||
}
|
||||
|
||||
var ppem = int(ft.UnitsPerEm() * 6)
|
||||
_, err = ft.LoadGlyph(&buf, idx, fixed.I(ppem), nil)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not load glyph %q: %+v", rn, err))
|
||||
}
|
||||
|
||||
adv, err := ft.GlyphAdvance(&buf, idx, fixed.I(ppem), hinting)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not retrieve glyph advance for %q: %+v", rn, err))
|
||||
}
|
||||
|
||||
fupe := fixed.Int26_6(ft.UnitsPerEm())
|
||||
_, err = ft.LoadGlyph(&buf, idx, fupe, nil)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not load glyph %q: %+v", rn, err))
|
||||
}
|
||||
|
||||
bnds, _, err := ft.GlyphBounds(&buf, idx, fixed.I(12), hinting)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var (
|
||||
scale = fontSize / 12
|
||||
xmin = scale * float64(bnds.Min.X) / 64
|
||||
xmax = scale * float64(bnds.Max.X) / 64
|
||||
ymin = scale * float64(-bnds.Max.Y) / 64 // FIXME
|
||||
ymax = scale * float64(-bnds.Min.Y) / 64 // FIXME
|
||||
width = xmax - xmin
|
||||
height = ymax - ymin
|
||||
)
|
||||
|
||||
offset := 0.0
|
||||
if postscript == "Cmex10" {
|
||||
offset = height/2 + (fnt.Size / 3 * dpi / 72)
|
||||
}
|
||||
|
||||
me := font.Metrics{
|
||||
Advance: float64(adv) / 65536 * fnt.Size / 12,
|
||||
Height: height,
|
||||
Width: width,
|
||||
XMin: xmin,
|
||||
XMax: xmax,
|
||||
YMin: ymin + offset,
|
||||
YMax: ymax + offset,
|
||||
Iceberg: ymax + offset,
|
||||
Slanted: slanted,
|
||||
}
|
||||
|
||||
be.glyphs[key] = ttfVal{
|
||||
font: ft,
|
||||
size: fnt.Size,
|
||||
postscript: postscript,
|
||||
metrics: me,
|
||||
symbolName: symName,
|
||||
rune: rn,
|
||||
glyph: idx,
|
||||
offset: offset,
|
||||
}
|
||||
return be.glyphs[key]
|
||||
}
|
||||
|
||||
// XHeight returns the xheight for the given font and dpi.
|
||||
func (be *Backend) XHeight(fnt font.Font, dpi float64) float64 {
|
||||
ft := be.getFont(fnt.Type)
|
||||
face, err := opentype.NewFace(ft, &opentype.FaceOptions{
|
||||
DPI: dpi,
|
||||
Size: fnt.Size,
|
||||
Hinting: stdfont.HintingNone,
|
||||
})
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not open font face for font=%s,%g,%s: %+v",
|
||||
fnt.Name, fnt.Size, fnt.Type, err,
|
||||
))
|
||||
}
|
||||
defer face.Close()
|
||||
|
||||
return float64(-face.Metrics().XHeight) / 64
|
||||
}
|
||||
|
||||
const (
|
||||
hintingNone = stdfont.HintingNone
|
||||
//hintingFull = stdfont.HintingFull
|
||||
)
|
||||
|
||||
func (be *Backend) getGlyph(symbol string, font font.Font, math bool) (*sfnt.Font, rune, string, float64, bool) {
|
||||
var (
|
||||
fontType = font.Type
|
||||
idx = tex2unicode.Index(symbol, math)
|
||||
)
|
||||
|
||||
// only characters in the "Letter" class should be italicized in "it" mode.
|
||||
// Greek capital letters should be roman.
|
||||
if font.Type == "it" && idx < 0x10000 {
|
||||
if !unicode.Is(unicode.L, idx) {
|
||||
fontType = "rm"
|
||||
}
|
||||
}
|
||||
slanted := (fontType == "it") || be.isSlanted(symbol)
|
||||
ft := be.getFont(fontType)
|
||||
if ft == nil {
|
||||
panic("could not find TTF font for [" + fontType + "]")
|
||||
}
|
||||
|
||||
// FIXME(sbinet):
|
||||
// \sigma -> sigma, A->A, \infty->infinity, \nabla->gradient
|
||||
// etc...
|
||||
symbolName := symbol
|
||||
return ft, idx, symbolName, font.Size, slanted
|
||||
}
|
||||
|
||||
func (*Backend) isSlanted(symbol string) bool {
|
||||
switch symbol {
|
||||
case `\int`, `\oint`:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (be *Backend) getFont(fontType string) *sfnt.Font {
|
||||
return be.fonts[fontType]
|
||||
}
|
||||
|
||||
// UnderlineThickness returns the line thickness that matches the given font.
|
||||
// It is used as a base unit for drawing lines such as in a fraction or radical.
|
||||
func (*Backend) UnderlineThickness(font font.Font, dpi float64) float64 {
|
||||
// theoretically, we could grab the underline thickness from the font
|
||||
// metrics.
|
||||
// but that information is just too un-reliable.
|
||||
// so, it is hardcoded.
|
||||
return (0.75 / 12 * font.Size * dpi) / 72
|
||||
}
|
||||
|
||||
// Kern returns the kerning distance between two symbols.
|
||||
func (be *Backend) Kern(ft1 font.Font, sym1 string, ft2 font.Font, sym2 string, dpi float64) float64 {
|
||||
if ft1.Name == ft2.Name && ft1.Size == ft2.Size {
|
||||
const math = true
|
||||
info1 := be.getInfo(sym1, ft1, dpi, math)
|
||||
info2 := be.getInfo(sym2, ft2, dpi, math)
|
||||
scale := fixed.Int26_6(info1.font.UnitsPerEm())
|
||||
var buf sfnt.Buffer
|
||||
k, err := info1.font.Kern(&buf, info1.glyph, info2.glyph, scale, hintingNone)
|
||||
if err != nil {
|
||||
if errors.Is(err, sfnt.ErrNotFound) {
|
||||
return 0
|
||||
}
|
||||
panic(fmt.Errorf("could not compute kerning for %q/%q: %+v",
|
||||
sym1, sym2, err,
|
||||
))
|
||||
}
|
||||
return float64(k) / 64
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ttfKey struct {
|
||||
symbol string
|
||||
font font.Font
|
||||
dpi float64
|
||||
}
|
||||
|
||||
type ttfVal struct {
|
||||
font *sfnt.Font
|
||||
size float64
|
||||
postscript string
|
||||
metrics font.Metrics
|
||||
symbolName string
|
||||
rune rune
|
||||
glyph sfnt.GlyphIndex
|
||||
offset float64
|
||||
}
|
||||
|
||||
var defaultFonts = Fonts{
|
||||
Rm: mustParseTTF(goregular.TTF),
|
||||
It: mustParseTTF(goitalic.TTF),
|
||||
Bf: mustParseTTF(gobold.TTF),
|
||||
BfIt: mustParseTTF(gobolditalic.TTF),
|
||||
}
|
||||
|
||||
func mustParseTTF(raw []byte) *sfnt.Font {
|
||||
ft, err := sfnt.Parse(raw)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not parse raw TTF data: %+v", err))
|
||||
}
|
||||
return ft
|
||||
}
|
||||
|
||||
func init() {
|
||||
defaultFonts.Default = defaultFonts.Rm
|
||||
}
|
||||
|
||||
var (
|
||||
_ font.Backend = (*Backend)(nil)
|
||||
)
|
||||
634
vendor/github.com/go-latex/latex/internal/tex2unicode/utf8.go
generated
vendored
Normal file
634
vendor/github.com/go-latex/latex/internal/tex2unicode/utf8.go
generated
vendored
Normal file
@@ -0,0 +1,634 @@
|
||||
// Copyright ©2020 The go-latex 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 tex2unicode provides tools for associating TeX symbols to UTF-8.
|
||||
package tex2unicode // import "github.com/go-latex/latex/internal/tex2unicode"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Index associates a LaTeX symbol or unicode letter to a unicode rune.
|
||||
func Index(v string, math bool) rune {
|
||||
if !math {
|
||||
r, _ := utf8.DecodeRune([]byte(v))
|
||||
if r == utf8.RuneError {
|
||||
panic(fmt.Errorf("tex: invalid rune %q", v))
|
||||
}
|
||||
return r
|
||||
}
|
||||
// From UTF #25: U+2212 minus sign is the preferred
|
||||
// representation of the unary and binary minus sign rather than
|
||||
// the ASCII-derived U+002D hyphen-minus, because minus sign is
|
||||
// unambiguous and because it is rendered with a more desirable
|
||||
// length, usually longer than a hyphen.
|
||||
if v == "-" {
|
||||
return 0x2212
|
||||
}
|
||||
|
||||
if len(v) == 1 {
|
||||
r, _ := utf8.DecodeRune([]byte(v))
|
||||
if r != utf8.RuneError {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
r, ok := tex2uni[strings.Replace(v, `\`, "", 1)]
|
||||
if ok {
|
||||
return r
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("%q is not a valid unicode character nor a known TeX symbol", v))
|
||||
}
|
||||
|
||||
func HasSymbol(v string) bool {
|
||||
_, ok := tex2uni[v]
|
||||
return ok
|
||||
}
|
||||
|
||||
func Symbols() []string {
|
||||
names := make([]string, 0, len(tex2uni))
|
||||
for k := range tex2uni {
|
||||
names = append(names, k)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
var (
|
||||
tex2uni = map[string]rune{
|
||||
`widehat`: 0x0302,
|
||||
`widetilde`: 0x0303,
|
||||
`widebar`: 0x0305,
|
||||
`langle`: 0x27e8,
|
||||
`rangle`: 0x27e9,
|
||||
`perp`: 0x27c2,
|
||||
`neq`: 0x2260,
|
||||
`Join`: 0x2a1d,
|
||||
`leqslant`: 0x2a7d,
|
||||
`geqslant`: 0x2a7e,
|
||||
`lessapprox`: 0x2a85,
|
||||
`gtrapprox`: 0x2a86,
|
||||
`lesseqqgtr`: 0x2a8b,
|
||||
`gtreqqless`: 0x2a8c,
|
||||
`triangleeq`: 0x225c,
|
||||
`eqslantless`: 0x2a95,
|
||||
`eqslantgtr`: 0x2a96,
|
||||
`backepsilon`: 0x03f6,
|
||||
`precapprox`: 0x2ab7,
|
||||
`succapprox`: 0x2ab8,
|
||||
`fallingdotseq`: 0x2252,
|
||||
`subseteqq`: 0x2ac5,
|
||||
`supseteqq`: 0x2ac6,
|
||||
`varpropto`: 0x221d,
|
||||
`precnapprox`: 0x2ab9,
|
||||
`succnapprox`: 0x2aba,
|
||||
`subsetneqq`: 0x2acb,
|
||||
`supsetneqq`: 0x2acc,
|
||||
`lnapprox`: 0x2ab9,
|
||||
`gnapprox`: 0x2aba,
|
||||
`longleftarrow`: 0x27f5,
|
||||
`longrightarrow`: 0x27f6,
|
||||
`longleftrightarrow`: 0x27f7,
|
||||
`Longleftarrow`: 0x27f8,
|
||||
`Longrightarrow`: 0x27f9,
|
||||
`Longleftrightarrow`: 0x27fa,
|
||||
`longmapsto`: 0x27fc,
|
||||
`leadsto`: 0x21dd,
|
||||
`dashleftarrow`: 0x290e,
|
||||
`dashrightarrow`: 0x290f,
|
||||
`circlearrowleft`: 0x21ba,
|
||||
`circlearrowright`: 0x21bb,
|
||||
`leftrightsquigarrow`: 0x21ad,
|
||||
`leftsquigarrow`: 0x219c,
|
||||
`rightsquigarrow`: 0x219d,
|
||||
`Game`: 0x2141,
|
||||
`hbar`: 0x0127,
|
||||
`hslash`: 0x210f,
|
||||
`ldots`: 0x2026,
|
||||
`vdots`: 0x22ee,
|
||||
`doteqdot`: 0x2251,
|
||||
`doteq`: 8784,
|
||||
`partial`: 8706,
|
||||
`gg`: 8811,
|
||||
`asymp`: 8781,
|
||||
`blacktriangledown`: 9662,
|
||||
`otimes`: 8855,
|
||||
`nearrow`: 8599,
|
||||
`varpi`: 982,
|
||||
`vee`: 8744,
|
||||
`vec`: 8407,
|
||||
`smile`: 8995,
|
||||
`succnsim`: 8937,
|
||||
`gimel`: 8503,
|
||||
`vert`: 124,
|
||||
`|`: 124,
|
||||
`varrho`: 1009,
|
||||
`P`: 182,
|
||||
`approxident`: 8779,
|
||||
`Swarrow`: 8665,
|
||||
`textasciicircum`: 94,
|
||||
`imageof`: 8887,
|
||||
`ntriangleleft`: 8938,
|
||||
`nleq`: 8816,
|
||||
`div`: 247,
|
||||
`nparallel`: 8742,
|
||||
`Leftarrow`: 8656,
|
||||
`lll`: 8920,
|
||||
`oiint`: 8751,
|
||||
`ngeq`: 8817,
|
||||
`Theta`: 920,
|
||||
`origof`: 8886,
|
||||
`blacksquare`: 9632,
|
||||
`solbar`: 9023,
|
||||
`neg`: 172,
|
||||
`sum`: 8721,
|
||||
`Vdash`: 8873,
|
||||
`coloneq`: 8788,
|
||||
`degree`: 176,
|
||||
`bowtie`: 8904,
|
||||
`blacktriangleright`: 9654,
|
||||
`varsigma`: 962,
|
||||
`leq`: 8804,
|
||||
`ggg`: 8921,
|
||||
`lneqq`: 8808,
|
||||
`scurel`: 8881,
|
||||
`stareq`: 8795,
|
||||
`BbbN`: 8469,
|
||||
`nLeftarrow`: 8653,
|
||||
`nLeftrightarrow`: 8654,
|
||||
`k`: 808,
|
||||
`bot`: 8869,
|
||||
`BbbC`: 8450,
|
||||
`Lsh`: 8624,
|
||||
`leftleftarrows`: 8647,
|
||||
`BbbZ`: 8484,
|
||||
`digamma`: 989,
|
||||
`BbbR`: 8477,
|
||||
`BbbP`: 8473,
|
||||
`BbbQ`: 8474,
|
||||
`vartriangleright`: 8883,
|
||||
`succsim`: 8831,
|
||||
`wedge`: 8743,
|
||||
`lessgtr`: 8822,
|
||||
`veebar`: 8891,
|
||||
`mapsdown`: 8615,
|
||||
`Rsh`: 8625,
|
||||
`chi`: 967,
|
||||
`prec`: 8826,
|
||||
`nsubseteq`: 8840,
|
||||
`therefore`: 8756,
|
||||
`eqcirc`: 8790,
|
||||
`textexclamdown`: 161,
|
||||
`nRightarrow`: 8655,
|
||||
`flat`: 9837,
|
||||
`notin`: 8713,
|
||||
`llcorner`: 8990,
|
||||
`varepsilon`: 949,
|
||||
`bigtriangleup`: 9651,
|
||||
`aleph`: 8501,
|
||||
`dotminus`: 8760,
|
||||
`upsilon`: 965,
|
||||
`Lambda`: 923,
|
||||
`cap`: 8745,
|
||||
`barleftarrow`: 8676,
|
||||
`mu`: 956,
|
||||
`boxplus`: 8862,
|
||||
`mp`: 8723,
|
||||
`circledast`: 8859,
|
||||
`tau`: 964,
|
||||
`in`: 8712,
|
||||
`backslash`: 92,
|
||||
`varnothing`: 8709,
|
||||
`sharp`: 9839,
|
||||
`eqsim`: 8770,
|
||||
`gnsim`: 8935,
|
||||
`Searrow`: 8664,
|
||||
`updownarrows`: 8645,
|
||||
`heartsuit`: 9825,
|
||||
`trianglelefteq`: 8884,
|
||||
`ddag`: 8225,
|
||||
`sqsubseteq`: 8849,
|
||||
`mapsfrom`: 8612,
|
||||
`boxbar`: 9707,
|
||||
`sim`: 8764,
|
||||
`Nwarrow`: 8662,
|
||||
`nequiv`: 8802,
|
||||
`succ`: 8827,
|
||||
`vdash`: 8866,
|
||||
`Leftrightarrow`: 8660,
|
||||
`parallel`: 8741,
|
||||
`invnot`: 8976,
|
||||
`natural`: 9838,
|
||||
`ss`: 223,
|
||||
`uparrow`: 8593,
|
||||
`nsim`: 8769,
|
||||
`hookrightarrow`: 8618,
|
||||
`Equiv`: 8803,
|
||||
`approx`: 8776,
|
||||
`Vvdash`: 8874,
|
||||
`nsucc`: 8833,
|
||||
`leftrightharpoons`: 8651,
|
||||
`Re`: 8476,
|
||||
`boxminus`: 8863,
|
||||
`equiv`: 8801,
|
||||
`Lleftarrow`: 8666,
|
||||
`ll`: 8810,
|
||||
`Cup`: 8915,
|
||||
`measeq`: 8798,
|
||||
`upharpoonleft`: 8639,
|
||||
`lq`: 8216,
|
||||
`Upsilon`: 933,
|
||||
`subsetneq`: 8842,
|
||||
`greater`: 62,
|
||||
`supsetneq`: 8843,
|
||||
`Cap`: 8914,
|
||||
`L`: 321,
|
||||
`spadesuit`: 9824,
|
||||
`lrcorner`: 8991,
|
||||
`not`: 824,
|
||||
`bar`: 772,
|
||||
`rightharpoonaccent`: 8401,
|
||||
`boxdot`: 8865,
|
||||
`l`: 322,
|
||||
`leftharpoondown`: 8637,
|
||||
`bigcup`: 8899,
|
||||
`iint`: 8748,
|
||||
`bigwedge`: 8896,
|
||||
`downharpoonleft`: 8643,
|
||||
`textasciitilde`: 126,
|
||||
`subset`: 8834,
|
||||
`leqq`: 8806,
|
||||
`mapsup`: 8613,
|
||||
`nvDash`: 8877,
|
||||
`looparrowleft`: 8619,
|
||||
`nless`: 8814,
|
||||
`rightarrowbar`: 8677,
|
||||
`Vert`: 8214,
|
||||
`downdownarrows`: 8650,
|
||||
`uplus`: 8846,
|
||||
`simeq`: 8771,
|
||||
`napprox`: 8777,
|
||||
`ast`: 8727,
|
||||
`twoheaduparrow`: 8607,
|
||||
`doublebarwedge`: 8966,
|
||||
`Sigma`: 931,
|
||||
`leftharpoonaccent`: 8400,
|
||||
`ntrianglelefteq`: 8940,
|
||||
`nexists`: 8708,
|
||||
`times`: 215,
|
||||
`measuredangle`: 8737,
|
||||
`bumpeq`: 8783,
|
||||
`carriagereturn`: 8629,
|
||||
`adots`: 8944,
|
||||
`checkmark`: 10003,
|
||||
`lambda`: 955,
|
||||
`xi`: 958,
|
||||
`rbrace`: 125,
|
||||
`rbrack`: 93,
|
||||
`Nearrow`: 8663,
|
||||
`maltese`: 10016,
|
||||
`clubsuit`: 9827,
|
||||
`top`: 8868,
|
||||
`overarc`: 785,
|
||||
`varphi`: 966,
|
||||
`Delta`: 916,
|
||||
`iota`: 953,
|
||||
`nleftarrow`: 8602,
|
||||
`candra`: 784,
|
||||
`supset`: 8835,
|
||||
`triangleleft`: 9665,
|
||||
`gtreqless`: 8923,
|
||||
`ntrianglerighteq`: 8941,
|
||||
`quad`: 8195,
|
||||
`Xi`: 926,
|
||||
`gtrdot`: 8919,
|
||||
`leftthreetimes`: 8907,
|
||||
`minus`: 8722,
|
||||
`preccurlyeq`: 8828,
|
||||
`nleftrightarrow`: 8622,
|
||||
`lambdabar`: 411,
|
||||
`blacktriangle`: 9652,
|
||||
`kernelcontraction`: 8763,
|
||||
`Phi`: 934,
|
||||
`angle`: 8736,
|
||||
`spadesuitopen`: 9828,
|
||||
`eqless`: 8924,
|
||||
`mid`: 8739,
|
||||
`varkappa`: 1008,
|
||||
`Ldsh`: 8626,
|
||||
`updownarrow`: 8597,
|
||||
`beta`: 946,
|
||||
`textquotedblleft`: 8220,
|
||||
`rho`: 961,
|
||||
`alpha`: 945,
|
||||
`intercal`: 8890,
|
||||
`beth`: 8502,
|
||||
`grave`: 768,
|
||||
`acwopencirclearrow`: 8634,
|
||||
`nmid`: 8740,
|
||||
`nsupset`: 8837,
|
||||
`sigma`: 963,
|
||||
`dot`: 775,
|
||||
`Rightarrow`: 8658,
|
||||
`turnednot`: 8985,
|
||||
`backsimeq`: 8909,
|
||||
`leftarrowtail`: 8610,
|
||||
`approxeq`: 8778,
|
||||
`curlyeqsucc`: 8927,
|
||||
`rightarrowtail`: 8611,
|
||||
`Psi`: 936,
|
||||
`copyright`: 169,
|
||||
`yen`: 165,
|
||||
`vartriangleleft`: 8882,
|
||||
`rasp`: 700,
|
||||
`triangleright`: 9655,
|
||||
`precsim`: 8830,
|
||||
`infty`: 8734,
|
||||
`geq`: 8805,
|
||||
`updownarrowbar`: 8616,
|
||||
`precnsim`: 8936,
|
||||
`H`: 779,
|
||||
`ulcorner`: 8988,
|
||||
`looparrowright`: 8620,
|
||||
`ncong`: 8775,
|
||||
`downarrow`: 8595,
|
||||
`circeq`: 8791,
|
||||
`subseteq`: 8838,
|
||||
`bigstar`: 9733,
|
||||
`prime`: 8242,
|
||||
`lceil`: 8968,
|
||||
`Rrightarrow`: 8667,
|
||||
`oiiint`: 8752,
|
||||
`curlywedge`: 8911,
|
||||
`vDash`: 8872,
|
||||
`lfloor`: 8970,
|
||||
`ddots`: 8945,
|
||||
`exists`: 8707,
|
||||
`underbar`: 817,
|
||||
`Pi`: 928,
|
||||
`leftrightarrows`: 8646,
|
||||
`sphericalangle`: 8738,
|
||||
`coprod`: 8720,
|
||||
`circledcirc`: 8858,
|
||||
`gtrsim`: 8819,
|
||||
`gneqq`: 8809,
|
||||
`between`: 8812,
|
||||
`theta`: 952,
|
||||
`complement`: 8705,
|
||||
`arceq`: 8792,
|
||||
`nVdash`: 8878,
|
||||
`S`: 167,
|
||||
`wr`: 8768,
|
||||
`wp`: 8472,
|
||||
`backcong`: 8780,
|
||||
`lasp`: 701,
|
||||
`c`: 807,
|
||||
`nabla`: 8711,
|
||||
`dotplus`: 8724,
|
||||
`eta`: 951,
|
||||
`forall`: 8704,
|
||||
`eth`: 240,
|
||||
`colon`: 58,
|
||||
`sqcup`: 8852,
|
||||
`rightrightarrows`: 8649,
|
||||
`sqsupset`: 8848,
|
||||
`mapsto`: 8614,
|
||||
`bigtriangledown`: 9661,
|
||||
`sqsupseteq`: 8850,
|
||||
`propto`: 8733,
|
||||
`pi`: 960,
|
||||
`pm`: 177,
|
||||
`dots`: 0x2026,
|
||||
`nrightarrow`: 8603,
|
||||
`textasciiacute`: 180,
|
||||
`Doteq`: 8785,
|
||||
`breve`: 774,
|
||||
`sqcap`: 8851,
|
||||
`twoheadrightarrow`: 8608,
|
||||
`kappa`: 954,
|
||||
`vartriangle`: 9653,
|
||||
`diamondsuit`: 9826,
|
||||
`pitchfork`: 8916,
|
||||
`blacktriangleleft`: 9664,
|
||||
`nprec`: 8832,
|
||||
`curvearrowright`: 8631,
|
||||
`barwedge`: 8892,
|
||||
`multimap`: 8888,
|
||||
`textquestiondown`: 191,
|
||||
`cong`: 8773,
|
||||
`rtimes`: 8906,
|
||||
`rightzigzagarrow`: 8669,
|
||||
`rightarrow`: 8594,
|
||||
`leftarrow`: 8592,
|
||||
`__sqrt__`: 8730,
|
||||
`twoheaddownarrow`: 8609,
|
||||
`oint`: 8750,
|
||||
`bigvee`: 8897,
|
||||
`eqdef`: 8797,
|
||||
`sterling`: 163,
|
||||
`phi`: 981,
|
||||
`Updownarrow`: 8661,
|
||||
`backprime`: 8245,
|
||||
`emdash`: 8212,
|
||||
`Gamma`: 915,
|
||||
`i`: 305,
|
||||
`rceil`: 8969,
|
||||
`leftharpoonup`: 8636,
|
||||
`Im`: 8465,
|
||||
`curvearrowleft`: 8630,
|
||||
`wedgeq`: 8793,
|
||||
`curlyeqprec`: 8926,
|
||||
`questeq`: 8799,
|
||||
`less`: 60,
|
||||
`upuparrows`: 8648,
|
||||
`tilde`: 771,
|
||||
`textasciigrave`: 96,
|
||||
`smallsetminus`: 8726,
|
||||
`ell`: 8467,
|
||||
`cup`: 8746,
|
||||
`danger`: 9761,
|
||||
`nVDash`: 8879,
|
||||
`cdotp`: 183,
|
||||
`cdots`: 8943,
|
||||
`hat`: 770,
|
||||
`eqgtr`: 8925,
|
||||
`psi`: 968,
|
||||
`frown`: 8994,
|
||||
`acute`: 769,
|
||||
`downzigzagarrow`: 8623,
|
||||
`ntriangleright`: 8939,
|
||||
`cupdot`: 8845,
|
||||
`circleddash`: 8861,
|
||||
`oslash`: 8856,
|
||||
`mho`: 8487,
|
||||
`d`: 803,
|
||||
`sqsubset`: 8847,
|
||||
`cdot`: 8901,
|
||||
`Omega`: 937,
|
||||
`OE`: 338,
|
||||
`veeeq`: 8794,
|
||||
`Finv`: 8498,
|
||||
`t`: 865,
|
||||
`leftrightarrow`: 8596,
|
||||
`swarrow`: 8601,
|
||||
`rightthreetimes`: 8908,
|
||||
`rightleftharpoons`: 8652,
|
||||
`lesssim`: 8818,
|
||||
`searrow`: 8600,
|
||||
`because`: 8757,
|
||||
`gtrless`: 8823,
|
||||
`star`: 8902,
|
||||
`nsubset`: 8836,
|
||||
`zeta`: 950,
|
||||
`dddot`: 8411,
|
||||
`bigcirc`: 9675,
|
||||
`Supset`: 8913,
|
||||
`circ`: 8728,
|
||||
`slash`: 8725,
|
||||
`ocirc`: 778,
|
||||
`prod`: 8719,
|
||||
`twoheadleftarrow`: 8606,
|
||||
`daleth`: 8504,
|
||||
`upharpoonright`: 8638,
|
||||
`odot`: 8857,
|
||||
`Uparrow`: 8657,
|
||||
`O`: 216,
|
||||
`hookleftarrow`: 8617,
|
||||
`trianglerighteq`: 8885,
|
||||
`nsime`: 8772,
|
||||
`oe`: 339,
|
||||
`nwarrow`: 8598,
|
||||
`o`: 248,
|
||||
`ddddot`: 8412,
|
||||
`downharpoonright`: 8642,
|
||||
`succcurlyeq`: 8829,
|
||||
`gamma`: 947,
|
||||
`scrR`: 8475,
|
||||
`dag`: 8224,
|
||||
`thickspace`: 8197,
|
||||
`frakZ`: 8488,
|
||||
`lessdot`: 8918,
|
||||
`triangledown`: 9663,
|
||||
`ltimes`: 8905,
|
||||
`scrB`: 8492,
|
||||
`endash`: 8211,
|
||||
`scrE`: 8496,
|
||||
`scrF`: 8497,
|
||||
`scrH`: 8459,
|
||||
`scrI`: 8464,
|
||||
`rightharpoondown`: 8641,
|
||||
`scrL`: 8466,
|
||||
`scrM`: 8499,
|
||||
`frakC`: 8493,
|
||||
`nsupseteq`: 8841,
|
||||
`circledR`: 174,
|
||||
`circledS`: 9416,
|
||||
`ngtr`: 8815,
|
||||
`bigcap`: 8898,
|
||||
`scre`: 8495,
|
||||
`Downarrow`: 8659,
|
||||
`scrg`: 8458,
|
||||
`overleftrightarrow`: 8417,
|
||||
`scro`: 8500,
|
||||
`lnsim`: 8934,
|
||||
`eqcolon`: 8789,
|
||||
`curlyvee`: 8910,
|
||||
`urcorner`: 8989,
|
||||
`lbrace`: 123,
|
||||
`Bumpeq`: 8782,
|
||||
`delta`: 948,
|
||||
`boxtimes`: 8864,
|
||||
`overleftarrow`: 8406,
|
||||
`prurel`: 8880,
|
||||
`clubsuitopen`: 9831,
|
||||
`cwopencirclearrow`: 8635,
|
||||
`geqq`: 8807,
|
||||
`rightleftarrows`: 8644,
|
||||
`ac`: 8766,
|
||||
`ae`: 230,
|
||||
`int`: 8747,
|
||||
`rfloor`: 8971,
|
||||
`risingdotseq`: 8787,
|
||||
`nvdash`: 8876,
|
||||
`diamond`: 8900,
|
||||
`ddot`: 776,
|
||||
`backsim`: 8765,
|
||||
`oplus`: 8853,
|
||||
`triangleq`: 8796,
|
||||
`check`: 780,
|
||||
`ni`: 8715,
|
||||
`iiint`: 8749,
|
||||
`ne`: 8800,
|
||||
`lesseqgtr`: 8922,
|
||||
`obar`: 9021,
|
||||
`supseteq`: 8839,
|
||||
`nu`: 957,
|
||||
`AA`: 197,
|
||||
`AE`: 198,
|
||||
`models`: 8871,
|
||||
`ominus`: 8854,
|
||||
`dashv`: 8867,
|
||||
`omega`: 969,
|
||||
`rq`: 8217,
|
||||
`Subset`: 8912,
|
||||
`rightharpoonup`: 8640,
|
||||
`Rdsh`: 8627,
|
||||
`bullet`: 8729,
|
||||
`divideontimes`: 8903,
|
||||
`lbrack`: 91,
|
||||
`textquotedblright`: 8221,
|
||||
`Colon`: 8759,
|
||||
`%`: 37,
|
||||
`$`: 36,
|
||||
`{`: 123,
|
||||
`}`: 125,
|
||||
`_`: 95,
|
||||
`#`: 35,
|
||||
`imath`: 0x131,
|
||||
`circumflexaccent`: 770,
|
||||
`combiningbreve`: 774,
|
||||
`combiningoverline`: 772,
|
||||
`combininggraveaccent`: 768,
|
||||
`combiningacuteaccent`: 769,
|
||||
`combiningdiaeresis`: 776,
|
||||
`combiningtilde`: 771,
|
||||
`combiningrightarrowabove`: 8407,
|
||||
`combiningdotabove`: 775,
|
||||
`to`: 8594,
|
||||
`succeq`: 8829,
|
||||
`emptyset`: 8709,
|
||||
`(`: 40,
|
||||
`)`: 41,
|
||||
`leftparen`: 40,
|
||||
`rightparen`: 41,
|
||||
`bigoplus`: 10753,
|
||||
`leftangle`: 10216,
|
||||
`rightangle`: 10217,
|
||||
`leftbrace`: 124,
|
||||
`rightbrace`: 125,
|
||||
`jmath`: 567,
|
||||
`bigodot`: 10752,
|
||||
`preceq`: 8828,
|
||||
`biguplus`: 10756,
|
||||
`epsilon`: 949,
|
||||
`vartheta`: 977,
|
||||
`bigotimes`: 10754,
|
||||
`guillemotleft`: 171,
|
||||
`ring`: 730,
|
||||
`Thorn`: 222,
|
||||
`guilsinglright`: 8250,
|
||||
`perthousand`: 8240,
|
||||
`macron`: 175,
|
||||
`cent`: 162,
|
||||
`guillemotright`: 187,
|
||||
`equal`: 61,
|
||||
`asterisk`: 42,
|
||||
`guilsinglleft`: 8249,
|
||||
`plus`: 43,
|
||||
`thorn`: 254,
|
||||
`dagger`: 8224,
|
||||
}
|
||||
)
|
||||
6
vendor/github.com/go-latex/latex/latex.go
generated
vendored
Normal file
6
vendor/github.com/go-latex/latex/latex.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2020 The go-latex 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 latex provides types and functions to work with LaTeX.
|
||||
package latex // import "github.com/go-latex/latex"
|
||||
361
vendor/github.com/go-latex/latex/macros.go
generated
vendored
Normal file
361
vendor/github.com/go-latex/latex/macros.go
generated
vendored
Normal file
@@ -0,0 +1,361 @@
|
||||
// Copyright ©2020 The go-latex 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 latex
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-latex/latex/ast"
|
||||
"github.com/go-latex/latex/internal/tex2unicode"
|
||||
)
|
||||
|
||||
type macroParser interface {
|
||||
parseMacro(p *parser) ast.Node
|
||||
}
|
||||
|
||||
func (p *parser) addBuiltinMacros() {
|
||||
p.macros = map[string]macroParser{
|
||||
// binary operators
|
||||
`\amalg`: builtinMacro(""),
|
||||
`\ast`: builtinMacro(""),
|
||||
`\bigcirc`: builtinMacro(""),
|
||||
`\bigtriangledown`: builtinMacro(""),
|
||||
`\bigtriangleup`: builtinMacro(""),
|
||||
`\bullet`: builtinMacro(""),
|
||||
`\cdot`: builtinMacro(""),
|
||||
`\circ`: builtinMacro(""),
|
||||
`\cap`: builtinMacro(""),
|
||||
`\cup`: builtinMacro(""),
|
||||
`\dagger`: builtinMacro(""),
|
||||
`\ddagger`: builtinMacro(""),
|
||||
`\diamond`: builtinMacro(""),
|
||||
`\div`: builtinMacro(""),
|
||||
`\lhd`: builtinMacro(""),
|
||||
`\mp`: builtinMacro(""),
|
||||
`\odot`: builtinMacro(""),
|
||||
`\ominus`: builtinMacro(""),
|
||||
`\oplus`: builtinMacro(""),
|
||||
`\oslash`: builtinMacro(""),
|
||||
`\otimes`: builtinMacro(""),
|
||||
`\pm`: builtinMacro(""),
|
||||
`\rhd`: builtinMacro(""),
|
||||
`\setminus`: builtinMacro(""),
|
||||
`\sqcap`: builtinMacro(""),
|
||||
`\sqcup`: builtinMacro(""),
|
||||
`\star`: builtinMacro(""),
|
||||
`\times`: builtinMacro(""),
|
||||
`\triangleleft`: builtinMacro(""),
|
||||
`\triangleright`: builtinMacro(""),
|
||||
`\uplus`: builtinMacro(""),
|
||||
`\unlhd`: builtinMacro(""),
|
||||
`\unrhd`: builtinMacro(""),
|
||||
`\vee`: builtinMacro(""),
|
||||
`\wedge`: builtinMacro(""),
|
||||
`\wr`: builtinMacro(""),
|
||||
|
||||
// arithmetic operators
|
||||
`\binom`: builtinMacro("AA"),
|
||||
`\dfrac`: builtinMacro("AA"),
|
||||
`\frac`: builtinMacro("AA"),
|
||||
`\stackrel`: builtinMacro("AA"),
|
||||
`\tfrac`: builtinMacro("AA"),
|
||||
`\genfrac`: nil, // FIXME(sbinet)
|
||||
|
||||
// relation symbols
|
||||
`\approx`: builtinMacro(""),
|
||||
`\asymp`: builtinMacro(""),
|
||||
`\bowtie`: builtinMacro(""),
|
||||
`\cong`: builtinMacro(""),
|
||||
`\dashv`: builtinMacro(""),
|
||||
`\doteq`: builtinMacro(""),
|
||||
`\doteqdot`: builtinMacro(""),
|
||||
`\dotplus`: builtinMacro(""),
|
||||
`\dots`: builtinMacro(""),
|
||||
`\equiv`: builtinMacro(""),
|
||||
`\frown`: builtinMacro(""),
|
||||
`\geq`: builtinMacro(""),
|
||||
`\gg`: builtinMacro(""),
|
||||
`\in`: builtinMacro(""),
|
||||
`\leq`: builtinMacro(""),
|
||||
`\ll`: builtinMacro(""),
|
||||
`\mid`: builtinMacro(""),
|
||||
`\models`: builtinMacro(""),
|
||||
`\neq`: builtinMacro(""),
|
||||
`\ni`: builtinMacro(""),
|
||||
`\parallel`: builtinMacro(""),
|
||||
`\perp`: builtinMacro(""),
|
||||
`\prec`: builtinMacro(""),
|
||||
`\preceq`: builtinMacro(""),
|
||||
`\propto`: builtinMacro(""),
|
||||
`\sim`: builtinMacro(""),
|
||||
`\simeq`: builtinMacro(""),
|
||||
`\smile`: builtinMacro(""),
|
||||
`\sqsubset`: builtinMacro(""),
|
||||
`\sqsubseteq`: builtinMacro(""),
|
||||
`\sqsupset`: builtinMacro(""),
|
||||
`\sqsupseteq`: builtinMacro(""),
|
||||
`\subset`: builtinMacro(""),
|
||||
`\subseteq`: builtinMacro(""),
|
||||
`\succ`: builtinMacro(""),
|
||||
`\succeq`: builtinMacro(""),
|
||||
`\supset`: builtinMacro(""),
|
||||
`\supseteq`: builtinMacro(""),
|
||||
`\vdash`: builtinMacro(""),
|
||||
`\Join`: builtinMacro(""),
|
||||
|
||||
// arrow symbols
|
||||
`\downarrow`: builtinMacro(""),
|
||||
`\hookleftarrow`: builtinMacro(""),
|
||||
`\hookrightarrow`: builtinMacro(""),
|
||||
`\leadsto`: builtinMacro(""),
|
||||
`\leftarrow`: builtinMacro(""),
|
||||
`\leftharpoondown`: builtinMacro(""),
|
||||
`\leftharpoonup`: builtinMacro(""),
|
||||
`\leftrightarrow`: builtinMacro(""),
|
||||
`\longleftarrow`: builtinMacro(""),
|
||||
`\longleftrightarrow`: builtinMacro(""),
|
||||
`\longmapsto`: builtinMacro(""),
|
||||
`\longrightarrow`: builtinMacro(""),
|
||||
`\rightarrow`: builtinMacro(""),
|
||||
`\mapsto`: builtinMacro(""),
|
||||
`\nearrow`: builtinMacro(""),
|
||||
`\nwarrow`: builtinMacro(""),
|
||||
`\rightharpoondown`: builtinMacro(""),
|
||||
`\rightharpoonup`: builtinMacro(""),
|
||||
`\rightleftharpoons`: builtinMacro(""),
|
||||
`\searrow`: builtinMacro(""),
|
||||
`\swarrow`: builtinMacro(""),
|
||||
`\uparrow`: builtinMacro(""),
|
||||
`\updownarrow`: builtinMacro(""),
|
||||
`\Downarrow`: builtinMacro(""),
|
||||
`\Leftarrow`: builtinMacro(""),
|
||||
`\Leftrightarrow`: builtinMacro(""),
|
||||
`\Longleftarrow`: builtinMacro(""),
|
||||
`\Longleftrightarrow`: builtinMacro(""),
|
||||
`\Longrightarrow`: builtinMacro(""),
|
||||
`\Rightarrow`: builtinMacro(""),
|
||||
`\Uparrow`: builtinMacro(""),
|
||||
`\Updownarrow`: builtinMacro(""),
|
||||
|
||||
// punctuation symbols
|
||||
`\ldotp`: builtinMacro(""),
|
||||
`\cdotp`: builtinMacro(""),
|
||||
|
||||
// over-under symbols
|
||||
`\bigcap`: builtinMacro(""),
|
||||
`\bigcup`: builtinMacro(""),
|
||||
`\bigodot`: builtinMacro(""),
|
||||
`\bigoplus`: builtinMacro(""),
|
||||
`\bigotimes`: builtinMacro(""),
|
||||
`\bigsqcup`: builtinMacro(""),
|
||||
`\biguplus`: builtinMacro(""),
|
||||
`\bigvee`: builtinMacro(""),
|
||||
`\bigwedge`: builtinMacro(""),
|
||||
`\coprod`: builtinMacro(""),
|
||||
`\prod`: builtinMacro(""),
|
||||
`\sum`: builtinMacro(""),
|
||||
|
||||
// over-under functions
|
||||
`\lim`: builtinMacro(""),
|
||||
`\liminf`: builtinMacro(""),
|
||||
`\limsup`: builtinMacro(""),
|
||||
`\max`: builtinMacro(""),
|
||||
`\min`: builtinMacro(""),
|
||||
`\sup`: builtinMacro(""),
|
||||
|
||||
// dropsub symbols
|
||||
`\int`: builtinMacro(""),
|
||||
`\oint`: builtinMacro(""),
|
||||
|
||||
// font names
|
||||
`\rm`: builtinMacro(""),
|
||||
`\cal`: builtinMacro(""),
|
||||
`\it`: builtinMacro(""),
|
||||
`\tt`: builtinMacro(""),
|
||||
`\sf`: builtinMacro(""),
|
||||
`\bf`: builtinMacro(""),
|
||||
`\default`: builtinMacro(""),
|
||||
`\bb`: builtinMacro(""),
|
||||
`\frak`: builtinMacro(""),
|
||||
`\scr`: builtinMacro(""),
|
||||
`\regular`: builtinMacro(""),
|
||||
|
||||
// function names
|
||||
`\arccos`: builtinMacro(""),
|
||||
`\arcsin`: builtinMacro(""),
|
||||
`\arctan`: builtinMacro(""),
|
||||
`\arg`: builtinMacro(""),
|
||||
`\cos`: builtinMacro(""),
|
||||
`\cosh`: builtinMacro(""),
|
||||
`\cot`: builtinMacro(""),
|
||||
`\coth`: builtinMacro(""),
|
||||
`\csc`: builtinMacro(""),
|
||||
`\deg`: builtinMacro(""),
|
||||
`\det`: builtinMacro(""),
|
||||
`\dim`: builtinMacro(""),
|
||||
`\exp`: builtinMacro("A"),
|
||||
`\gcd`: builtinMacro(""),
|
||||
`\hom`: builtinMacro(""),
|
||||
`\inf`: builtinMacro(""),
|
||||
`\ker`: builtinMacro(""),
|
||||
`\lg`: builtinMacro(""),
|
||||
`\ln`: builtinMacro(""),
|
||||
`\log`: builtinMacro(""),
|
||||
`\sec`: builtinMacro(""),
|
||||
`\sin`: builtinMacro(""),
|
||||
`\sinh`: builtinMacro(""),
|
||||
`\sqrt`: builtinMacro("OA"),
|
||||
`\tan`: builtinMacro(""),
|
||||
`\tanh`: builtinMacro(""),
|
||||
`\Pr`: builtinMacro(""),
|
||||
|
||||
// ambi delim
|
||||
`\backslash`: builtinMacro(""),
|
||||
`\vert`: builtinMacro(""),
|
||||
`\Vert`: builtinMacro(""),
|
||||
|
||||
// left delim
|
||||
`\{`: builtinMacro(""),
|
||||
`\(`: builtinMacro(""),
|
||||
`\langle`: builtinMacro(""),
|
||||
`\lceil`: builtinMacro(""),
|
||||
`\lfloor`: builtinMacro(""),
|
||||
|
||||
// right delim
|
||||
`\}`: builtinMacro(""),
|
||||
`\)`: builtinMacro(""),
|
||||
`\rangle`: builtinMacro(""),
|
||||
`\rceil`: builtinMacro(""),
|
||||
`\rfloor`: builtinMacro(""),
|
||||
|
||||
// symbols
|
||||
`\alpha`: builtinMacro(""),
|
||||
`\beta`: builtinMacro(""),
|
||||
`\gamma`: builtinMacro(""),
|
||||
`\delta`: builtinMacro(""),
|
||||
`\iota`: builtinMacro(""),
|
||||
`\epsilon`: builtinMacro(""),
|
||||
`\eta`: builtinMacro(""),
|
||||
`\kappa`: builtinMacro(""),
|
||||
`\lambda`: builtinMacro(""),
|
||||
`\mu`: builtinMacro(""),
|
||||
`\nu`: builtinMacro(""),
|
||||
`\omicron`: builtinMacro(""),
|
||||
`\pi`: builtinMacro(""),
|
||||
`\theta`: builtinMacro(""),
|
||||
`\xi`: builtinMacro(""),
|
||||
`\rho`: builtinMacro(""),
|
||||
`\sigma`: builtinMacro(""),
|
||||
`\tau`: builtinMacro(""),
|
||||
`\upsilon`: builtinMacro(""),
|
||||
`\phi`: builtinMacro(""),
|
||||
`\chi`: builtinMacro(""),
|
||||
`\psi`: builtinMacro(""),
|
||||
`\omega`: builtinMacro(""),
|
||||
`\zeta`: builtinMacro(""),
|
||||
`\Alpha`: builtinMacro(""),
|
||||
`\Beta`: builtinMacro(""),
|
||||
`\Gamma`: builtinMacro(""),
|
||||
`\Delta`: builtinMacro(""),
|
||||
`\Epsilon`: builtinMacro(""),
|
||||
`\Zeta`: builtinMacro(""),
|
||||
`\Eta`: builtinMacro(""),
|
||||
`\Theta`: builtinMacro(""),
|
||||
`\Iota`: builtinMacro(""),
|
||||
`\Kappa`: builtinMacro(""),
|
||||
`\Lambda`: builtinMacro(""),
|
||||
`\Mu`: builtinMacro(""),
|
||||
`\Nu`: builtinMacro(""),
|
||||
`\Xi`: builtinMacro(""),
|
||||
`\Omicron`: builtinMacro(""),
|
||||
`\Pi`: builtinMacro(""),
|
||||
`\Rho`: builtinMacro(""),
|
||||
`\Sigma`: builtinMacro(""),
|
||||
`\Tau`: builtinMacro(""),
|
||||
`\Upsilon`: builtinMacro(""),
|
||||
`\Phi`: builtinMacro(""),
|
||||
`\Chi`: builtinMacro(""),
|
||||
`\Psi`: builtinMacro(""),
|
||||
`\Omega`: builtinMacro(""),
|
||||
`\hbar`: builtinMacro(""),
|
||||
`\nabla`: builtinMacro(""),
|
||||
|
||||
// math font
|
||||
`\mathbf`: builtinMacro("A"),
|
||||
`\mathit`: builtinMacro("A"),
|
||||
`\mathsf`: builtinMacro("A"),
|
||||
`\mathtt`: builtinMacro("A"),
|
||||
`\mathcal`: builtinMacro("A"),
|
||||
`\mathdefault`: builtinMacro("A"),
|
||||
`\mathbb`: builtinMacro("A"),
|
||||
`\mathfrak`: builtinMacro("A"),
|
||||
`\mathscr`: builtinMacro("A"),
|
||||
`\mathregular`: builtinMacro("A"),
|
||||
|
||||
// text
|
||||
`\textbf`: builtinMacro("A"),
|
||||
`\textit`: builtinMacro("A"),
|
||||
`\textsf`: builtinMacro("A"),
|
||||
`\texttt`: builtinMacro("A"),
|
||||
`\textcal`: builtinMacro("A"),
|
||||
`\textdefault`: builtinMacro("A"),
|
||||
`\textbb`: builtinMacro("A"),
|
||||
`\textfrak`: builtinMacro("A"),
|
||||
`\textscr`: builtinMacro("A"),
|
||||
`\textregular`: builtinMacro("A"),
|
||||
|
||||
// space, symbols
|
||||
`\ `: builtinMacro(""),
|
||||
`\,`: builtinMacro(""),
|
||||
`\;`: builtinMacro(""),
|
||||
`\!`: builtinMacro(""),
|
||||
`\quad`: builtinMacro(""),
|
||||
`\qquad`: builtinMacro(""),
|
||||
`\:`: builtinMacro(""),
|
||||
`\cdots`: builtinMacro(""),
|
||||
`\ddots`: builtinMacro(""),
|
||||
`\ldots`: builtinMacro(""),
|
||||
`\vdots`: builtinMacro(""),
|
||||
`\hspace`: builtinMacro("A"),
|
||||
|
||||
// catch-all
|
||||
//
|
||||
`\overline`: builtinMacro("A"),
|
||||
`\operatorname`: builtinMacro("A"),
|
||||
}
|
||||
|
||||
// add all known UTF-8 symbols
|
||||
for _, k := range tex2unicode.Symbols() {
|
||||
_, ok := p.macros[`\`+k]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
p.macros[`\`+k] = builtinMacro("")
|
||||
}
|
||||
}
|
||||
|
||||
type builtinMacro string
|
||||
|
||||
func (m builtinMacro) parseMacro(p *parser) ast.Node {
|
||||
node := &ast.Macro{
|
||||
Name: &ast.Ident{
|
||||
NamePos: p.s.tok.Pos,
|
||||
Name: p.s.tok.Text,
|
||||
},
|
||||
}
|
||||
|
||||
for _, typ := range strings.ToLower(string(m)) {
|
||||
switch typ {
|
||||
case 'a':
|
||||
p.parseMacroArg(node)
|
||||
case 'o':
|
||||
p.parseOptMacroArg(node)
|
||||
case 'v':
|
||||
p.parseVerbatimMacroArg(node)
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
11
vendor/github.com/go-latex/latex/mtex/README.md
generated
vendored
Normal file
11
vendor/github.com/go-latex/latex/mtex/README.md
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# mtex
|
||||
|
||||
`mtex` provides a Go implementation of a naive LaTeX-like math expression parser and renderer.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
$> mtex-render -font-size=48 -dpi=100 "$\sum\sqrt{\frac{a+b}{2\pi}}\cos\omega\binom{a+b}{\beta}\prod \alpha x\int\frac{\partial x}{x}\hbar$"
|
||||
```
|
||||
|
||||

|
||||
358
vendor/github.com/go-latex/latex/mtex/macros.go
generated
vendored
Normal file
358
vendor/github.com/go-latex/latex/mtex/macros.go
generated
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
// Copyright ©2020 The go-latex 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 mtex
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-latex/latex/ast"
|
||||
"github.com/go-latex/latex/tex"
|
||||
)
|
||||
|
||||
type handlerFunc func(p *parser, node ast.Node, state tex.State, math bool) tex.Node
|
||||
|
||||
func (h handlerFunc) Handle(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
return h(p, node, state, math)
|
||||
}
|
||||
|
||||
type handler interface {
|
||||
Handle(p *parser, node ast.Node, state tex.State, math bool) tex.Node
|
||||
}
|
||||
|
||||
var (
|
||||
builtinMacros = map[string]handler{
|
||||
// binary operators
|
||||
`\amalg`: builtinMacro(""),
|
||||
`\ast`: builtinMacro(""),
|
||||
`\bigcirc`: builtinMacro(""),
|
||||
`\bigtriangledown`: builtinMacro(""),
|
||||
`\bigtriangleup`: builtinMacro(""),
|
||||
`\bullet`: builtinMacro(""),
|
||||
`\cdot`: builtinMacro(""),
|
||||
`\circ`: builtinMacro(""),
|
||||
`\cap`: builtinMacro(""),
|
||||
`\cup`: builtinMacro(""),
|
||||
`\dagger`: builtinMacro(""),
|
||||
`\ddagger`: builtinMacro(""),
|
||||
`\diamond`: builtinMacro(""),
|
||||
`\div`: builtinMacro(""),
|
||||
`\lhd`: builtinMacro(""),
|
||||
`\mp`: builtinMacro(""),
|
||||
`\odot`: builtinMacro(""),
|
||||
`\ominus`: builtinMacro(""),
|
||||
`\oplus`: builtinMacro(""),
|
||||
`\oslash`: builtinMacro(""),
|
||||
`\otimes`: builtinMacro(""),
|
||||
`\pm`: builtinMacro(""),
|
||||
`\rhd`: builtinMacro(""),
|
||||
`\setminus`: builtinMacro(""),
|
||||
`\sqcap`: builtinMacro(""),
|
||||
`\sqcup`: builtinMacro(""),
|
||||
`\star`: builtinMacro(""),
|
||||
`\times`: builtinMacro(""),
|
||||
`\triangleleft`: builtinMacro(""),
|
||||
`\triangleright`: builtinMacro(""),
|
||||
`\uplus`: builtinMacro(""),
|
||||
`\unlhd`: builtinMacro(""),
|
||||
`\unrhd`: builtinMacro(""),
|
||||
`\vee`: builtinMacro(""),
|
||||
`\wedge`: builtinMacro(""),
|
||||
`\wr`: builtinMacro(""),
|
||||
|
||||
// arithmetic operators
|
||||
`\binom`: builtinMacro("AA"),
|
||||
`\dfrac`: builtinMacro("AA"),
|
||||
`\frac`: builtinMacro("AA"),
|
||||
`\stackrel`: builtinMacro("AA"),
|
||||
`\tfrac`: builtinMacro("AA"),
|
||||
`\genfrac`: nil, // FIXME(sbinet)
|
||||
|
||||
// relation symbols
|
||||
`\approx`: builtinMacro(""),
|
||||
`\asymp`: builtinMacro(""),
|
||||
`\bowtie`: builtinMacro(""),
|
||||
`\cong`: builtinMacro(""),
|
||||
`\dashv`: builtinMacro(""),
|
||||
`\doteq`: builtinMacro(""),
|
||||
`\doteqdot`: builtinMacro(""),
|
||||
`\dotplus`: builtinMacro(""),
|
||||
`\dots`: builtinMacro(""),
|
||||
`\equiv`: builtinMacro(""),
|
||||
`\frown`: builtinMacro(""),
|
||||
`\geq`: builtinMacro(""),
|
||||
`\gg`: builtinMacro(""),
|
||||
`\in`: builtinMacro(""),
|
||||
`\leq`: builtinMacro(""),
|
||||
`\ll`: builtinMacro(""),
|
||||
`\mid`: builtinMacro(""),
|
||||
`\models`: builtinMacro(""),
|
||||
`\neq`: builtinMacro(""),
|
||||
`\ni`: builtinMacro(""),
|
||||
`\parallel`: builtinMacro(""),
|
||||
`\perp`: builtinMacro(""),
|
||||
`\prec`: builtinMacro(""),
|
||||
`\preceq`: builtinMacro(""),
|
||||
`\propto`: builtinMacro(""),
|
||||
`\sim`: builtinMacro(""),
|
||||
`\simeq`: builtinMacro(""),
|
||||
`\smile`: builtinMacro(""),
|
||||
`\sqsubset`: builtinMacro(""),
|
||||
`\sqsubseteq`: builtinMacro(""),
|
||||
`\sqsupset`: builtinMacro(""),
|
||||
`\sqsupseteq`: builtinMacro(""),
|
||||
`\subset`: builtinMacro(""),
|
||||
`\subseteq`: builtinMacro(""),
|
||||
`\succ`: builtinMacro(""),
|
||||
`\succeq`: builtinMacro(""),
|
||||
`\supset`: builtinMacro(""),
|
||||
`\supseteq`: builtinMacro(""),
|
||||
`\vdash`: builtinMacro(""),
|
||||
`\Join`: builtinMacro(""),
|
||||
|
||||
// arrow symbols
|
||||
`\downarrow`: builtinMacro(""),
|
||||
`\hookleftarrow`: builtinMacro(""),
|
||||
`\hookrightarrow`: builtinMacro(""),
|
||||
`\leadsto`: builtinMacro(""),
|
||||
`\leftarrow`: builtinMacro(""),
|
||||
`\leftharpoondown`: builtinMacro(""),
|
||||
`\leftharpoonup`: builtinMacro(""),
|
||||
`\leftrightarrow`: builtinMacro(""),
|
||||
`\longleftarrow`: builtinMacro(""),
|
||||
`\longleftrightarrow`: builtinMacro(""),
|
||||
`\longmapsto`: builtinMacro(""),
|
||||
`\longrightarrow`: builtinMacro(""),
|
||||
`\rightarrow`: builtinMacro(""),
|
||||
`\mapsto`: builtinMacro(""),
|
||||
`\nearrow`: builtinMacro(""),
|
||||
`\nwarrow`: builtinMacro(""),
|
||||
`\rightharpoondown`: builtinMacro(""),
|
||||
`\rightharpoonup`: builtinMacro(""),
|
||||
`\rightleftharpoons`: builtinMacro(""),
|
||||
`\searrow`: builtinMacro(""),
|
||||
`\swarrow`: builtinMacro(""),
|
||||
`\uparrow`: builtinMacro(""),
|
||||
`\updownarrow`: builtinMacro(""),
|
||||
`\Downarrow`: builtinMacro(""),
|
||||
`\Leftarrow`: builtinMacro(""),
|
||||
`\Leftrightarrow`: builtinMacro(""),
|
||||
`\Longleftarrow`: builtinMacro(""),
|
||||
`\Longleftrightarrow`: builtinMacro(""),
|
||||
`\Longrightarrow`: builtinMacro(""),
|
||||
`\Rightarrow`: builtinMacro(""),
|
||||
`\Uparrow`: builtinMacro(""),
|
||||
`\Updownarrow`: builtinMacro(""),
|
||||
|
||||
// punctuation symbols
|
||||
`\ldotp`: builtinMacro(""),
|
||||
`\cdotp`: builtinMacro(""),
|
||||
|
||||
// over-under symbols
|
||||
`\bigcap`: builtinMacro(""),
|
||||
`\bigcup`: builtinMacro(""),
|
||||
`\bigodot`: builtinMacro(""),
|
||||
`\bigoplus`: builtinMacro(""),
|
||||
`\bigotimes`: builtinMacro(""),
|
||||
`\bigsqcup`: builtinMacro(""),
|
||||
`\biguplus`: builtinMacro(""),
|
||||
`\bigvee`: builtinMacro(""),
|
||||
`\bigwedge`: builtinMacro(""),
|
||||
`\coprod`: builtinMacro(""),
|
||||
`\prod`: builtinMacro(""),
|
||||
`\sum`: builtinMacro(""),
|
||||
|
||||
// over-under functions
|
||||
`\lim`: builtinMacro(""),
|
||||
`\liminf`: builtinMacro(""),
|
||||
`\limsup`: builtinMacro(""),
|
||||
`\max`: builtinMacro(""),
|
||||
`\min`: builtinMacro(""),
|
||||
`\sup`: builtinMacro(""),
|
||||
|
||||
// dropsub symbols
|
||||
`\int`: builtinMacro(""),
|
||||
`\oint`: builtinMacro(""),
|
||||
|
||||
// font names
|
||||
`\rm`: builtinMacro(""),
|
||||
`\cal`: builtinMacro(""),
|
||||
`\it`: builtinMacro(""),
|
||||
`\tt`: builtinMacro(""),
|
||||
`\sf`: builtinMacro(""),
|
||||
`\bf`: builtinMacro(""),
|
||||
`\default`: builtinMacro(""),
|
||||
`\bb`: builtinMacro(""),
|
||||
`\frak`: builtinMacro(""),
|
||||
`\scr`: builtinMacro(""),
|
||||
`\regular`: builtinMacro(""),
|
||||
|
||||
// function names
|
||||
`\arccos`: builtinMacro(""),
|
||||
`\arcsin`: builtinMacro(""),
|
||||
`\arctan`: builtinMacro(""),
|
||||
`\arg`: builtinMacro(""),
|
||||
`\cos`: builtinMacro(""),
|
||||
`\cosh`: builtinMacro(""),
|
||||
`\cot`: builtinMacro(""),
|
||||
`\coth`: builtinMacro(""),
|
||||
`\csc`: builtinMacro(""),
|
||||
`\deg`: builtinMacro(""),
|
||||
`\det`: builtinMacro(""),
|
||||
`\dim`: builtinMacro(""),
|
||||
`\exp`: builtinMacro("A"),
|
||||
`\gcd`: builtinMacro(""),
|
||||
`\hom`: builtinMacro(""),
|
||||
`\inf`: builtinMacro(""),
|
||||
`\ker`: builtinMacro(""),
|
||||
`\lg`: builtinMacro(""),
|
||||
`\ln`: builtinMacro(""),
|
||||
`\log`: builtinMacro(""),
|
||||
`\sec`: builtinMacro(""),
|
||||
`\sin`: builtinMacro(""),
|
||||
`\sinh`: builtinMacro(""),
|
||||
`\sqrt`: builtinMacro("OA"),
|
||||
`\tan`: builtinMacro(""),
|
||||
`\tanh`: builtinMacro(""),
|
||||
`\Pr`: builtinMacro(""),
|
||||
|
||||
// ambi delim
|
||||
`\backslash`: builtinMacro(""),
|
||||
`\vert`: builtinMacro(""),
|
||||
`\Vert`: builtinMacro(""),
|
||||
|
||||
// left delim
|
||||
`\{`: builtinMacro(""),
|
||||
`\(`: builtinMacro(""),
|
||||
`(`: builtinMacro(""),
|
||||
`\langle`: builtinMacro(""),
|
||||
`\lceil`: builtinMacro(""),
|
||||
`\lfloor`: builtinMacro(""),
|
||||
|
||||
// right delim
|
||||
`\}`: builtinMacro(""),
|
||||
`\)`: builtinMacro(""),
|
||||
`)`: builtinMacro(""),
|
||||
`\rangle`: builtinMacro(""),
|
||||
`\rceil`: builtinMacro(""),
|
||||
`\rfloor`: builtinMacro(""),
|
||||
|
||||
// symbols
|
||||
`\alpha`: builtinMacro(""),
|
||||
`\beta`: builtinMacro(""),
|
||||
`\gamma`: builtinMacro(""),
|
||||
`\delta`: builtinMacro(""),
|
||||
`\iota`: builtinMacro(""),
|
||||
`\epsilon`: builtinMacro(""),
|
||||
`\eta`: builtinMacro(""),
|
||||
`\kappa`: builtinMacro(""),
|
||||
`\lambda`: builtinMacro(""),
|
||||
`\mu`: builtinMacro(""),
|
||||
`\nu`: builtinMacro(""),
|
||||
`\omicron`: builtinMacro(""),
|
||||
`\pi`: builtinMacro(""),
|
||||
`\theta`: builtinMacro(""),
|
||||
`\xi`: builtinMacro(""),
|
||||
`\rho`: builtinMacro(""),
|
||||
`\sigma`: builtinMacro(""),
|
||||
`\tau`: builtinMacro(""),
|
||||
`\upsilon`: builtinMacro(""),
|
||||
`\phi`: builtinMacro(""),
|
||||
`\chi`: builtinMacro(""),
|
||||
`\psi`: builtinMacro(""),
|
||||
`\omega`: builtinMacro(""),
|
||||
`\zeta`: builtinMacro(""),
|
||||
`\Alpha`: builtinMacro(""),
|
||||
`\Beta`: builtinMacro(""),
|
||||
`\Gamma`: builtinMacro(""),
|
||||
`\Delta`: builtinMacro(""),
|
||||
`\Epsilon`: builtinMacro(""),
|
||||
`\Zeta`: builtinMacro(""),
|
||||
`\Eta`: builtinMacro(""),
|
||||
`\Theta`: builtinMacro(""),
|
||||
`\Iota`: builtinMacro(""),
|
||||
`\Kappa`: builtinMacro(""),
|
||||
`\Lambda`: builtinMacro(""),
|
||||
`\Mu`: builtinMacro(""),
|
||||
`\Nu`: builtinMacro(""),
|
||||
`\Xi`: builtinMacro(""),
|
||||
`\Omicron`: builtinMacro(""),
|
||||
`\Pi`: builtinMacro(""),
|
||||
`\Rho`: builtinMacro(""),
|
||||
`\Sigma`: builtinMacro(""),
|
||||
`\Tau`: builtinMacro(""),
|
||||
`\Upsilon`: builtinMacro(""),
|
||||
`\Phi`: builtinMacro(""),
|
||||
`\Chi`: builtinMacro(""),
|
||||
`\Psi`: builtinMacro(""),
|
||||
`\Omega`: builtinMacro(""),
|
||||
`\hbar`: builtinMacro(""),
|
||||
`\nabla`: builtinMacro(""),
|
||||
|
||||
// math font
|
||||
`\mathbf`: builtinMacro("A"),
|
||||
`\mathit`: builtinMacro("A"),
|
||||
`\mathsf`: builtinMacro("A"),
|
||||
`\mathtt`: builtinMacro("A"),
|
||||
`\mathcal`: builtinMacro("A"),
|
||||
`\mathdefault`: builtinMacro("A"),
|
||||
`\mathbb`: builtinMacro("A"),
|
||||
`\mathfrak`: builtinMacro("A"),
|
||||
`\mathscr`: builtinMacro("A"),
|
||||
`\mathregular`: builtinMacro("A"),
|
||||
|
||||
// text
|
||||
`\textbf`: builtinMacro("A"),
|
||||
`\textit`: builtinMacro("A"),
|
||||
`\textsf`: builtinMacro("A"),
|
||||
`\texttt`: builtinMacro("A"),
|
||||
`\textcal`: builtinMacro("A"),
|
||||
`\textdefault`: builtinMacro("A"),
|
||||
`\textbb`: builtinMacro("A"),
|
||||
`\textfrak`: builtinMacro("A"),
|
||||
`\textscr`: builtinMacro("A"),
|
||||
`\textregular`: builtinMacro("A"),
|
||||
|
||||
// space, symbols
|
||||
`\ `: builtinMacro(""),
|
||||
`\,`: builtinMacro(""),
|
||||
`\;`: builtinMacro(""),
|
||||
`\!`: builtinMacro(""),
|
||||
`\quad`: builtinMacro(""),
|
||||
`\qquad`: builtinMacro(""),
|
||||
`\:`: builtinMacro(""),
|
||||
`\cdots`: builtinMacro(""),
|
||||
`\ddots`: builtinMacro(""),
|
||||
`\ldots`: builtinMacro(""),
|
||||
`\vdots`: builtinMacro(""),
|
||||
`\hspace`: builtinMacro("A"),
|
||||
|
||||
// catch-all
|
||||
//
|
||||
`\overline`: builtinMacro("A"),
|
||||
`\operatorname`: builtinMacro("A"),
|
||||
}
|
||||
)
|
||||
|
||||
type builtinMacro string
|
||||
|
||||
func (m builtinMacro) Handle(p *parser, n ast.Node, state tex.State, math bool) tex.Node {
|
||||
node := n.(*ast.Macro)
|
||||
if m == "" {
|
||||
return tex.NewChar(node.Name.Name, state, math)
|
||||
}
|
||||
|
||||
for _, typ := range strings.ToLower(string(m)) {
|
||||
switch typ {
|
||||
case 'a':
|
||||
panic("not implemented")
|
||||
case 'o':
|
||||
panic("not implemented")
|
||||
case 'v':
|
||||
panic("not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
6
vendor/github.com/go-latex/latex/mtex/mtex.go
generated
vendored
Normal file
6
vendor/github.com/go-latex/latex/mtex/mtex.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2020 The go-latex 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 mtex provides tools to render LaTeX math expressions.
|
||||
package mtex
|
||||
573
vendor/github.com/go-latex/latex/mtex/parser.go
generated
vendored
Normal file
573
vendor/github.com/go-latex/latex/mtex/parser.go
generated
vendored
Normal file
@@ -0,0 +1,573 @@
|
||||
// Copyright ©2020 The go-latex 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 mtex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-latex/latex"
|
||||
"github.com/go-latex/latex/ast"
|
||||
"github.com/go-latex/latex/font"
|
||||
"github.com/go-latex/latex/internal/tex2unicode"
|
||||
"github.com/go-latex/latex/mtex/symbols"
|
||||
"github.com/go-latex/latex/tex"
|
||||
)
|
||||
|
||||
// Parse parses a LaTeX math expression and returns the TeX-like box model
|
||||
// and an error if any.
|
||||
func Parse(expr string, fontSize, DPI float64, backend font.Backend) (tex.Node, error) {
|
||||
p := newParser(backend)
|
||||
return p.parse(expr, fontSize, DPI)
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
be font.Backend
|
||||
|
||||
expr string
|
||||
macros map[string]handler
|
||||
}
|
||||
|
||||
func newParser(be font.Backend) *parser {
|
||||
p := &parser{
|
||||
be: be,
|
||||
macros: make(map[string]handler),
|
||||
}
|
||||
p.init()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *parser) parse(x string, size, dpi float64) (tex.Node, error) {
|
||||
p.expr = x
|
||||
node, err := latex.ParseExpr(x)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse latex expression %q: %w", x, err)
|
||||
}
|
||||
|
||||
state := tex.NewState(p.be, font.Font{
|
||||
Name: "default",
|
||||
Size: size,
|
||||
Type: "rm",
|
||||
}, dpi)
|
||||
|
||||
v := visitor{p: p, state: state}
|
||||
ast.Walk(&v, node)
|
||||
nodes := tex.HListOf(v.nodes, true)
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
type visitor struct {
|
||||
p *parser
|
||||
nodes []tex.Node
|
||||
state tex.State
|
||||
math bool
|
||||
}
|
||||
|
||||
func (v *visitor) Visit(n ast.Node) ast.Visitor {
|
||||
switch n := n.(type) {
|
||||
case ast.List:
|
||||
case *ast.Symbol:
|
||||
switch {
|
||||
case v.math:
|
||||
h := v.p.handler(n.Text)
|
||||
if h == nil {
|
||||
panic("no handler for symbol [" + n.Text + "]")
|
||||
}
|
||||
v.nodes = append(v.nodes, h.Handle(v.p, n, v.state, v.math))
|
||||
default:
|
||||
v.nodes = append(v.nodes, tex.NewChar(string(n.Text), v.state, v.math))
|
||||
}
|
||||
case *ast.Word:
|
||||
var nodes []tex.Node
|
||||
for _, x := range n.Text {
|
||||
nodes = append(nodes, tex.NewChar(string(x), v.state, v.math))
|
||||
}
|
||||
v.nodes = append(v.nodes, tex.HListOf(nodes, true))
|
||||
case *ast.Literal:
|
||||
h := handlerFunc(handleSymbol)
|
||||
for _, c := range n.Text {
|
||||
n := &ast.Literal{Text: string(c)}
|
||||
v.nodes = append(v.nodes, h.Handle(v.p, n, v.state, v.math))
|
||||
}
|
||||
|
||||
case *ast.MathExpr:
|
||||
oldm := v.math
|
||||
oldt := v.state.Font.Type
|
||||
v.math = true
|
||||
v.state.Font.Type = rcparams("mathtext.default").(string)
|
||||
|
||||
for _, x := range n.List {
|
||||
v.Visit(x)
|
||||
}
|
||||
v.math = oldm
|
||||
v.state.Font.Type = oldt
|
||||
return nil
|
||||
|
||||
case *ast.Macro:
|
||||
if n.Name == nil {
|
||||
panic("macro with nil identifier")
|
||||
}
|
||||
macro := n.Name.Name
|
||||
h := v.p.handler(macro)
|
||||
if h == nil {
|
||||
panic(fmt.Errorf("unknown macro %q", macro))
|
||||
}
|
||||
v.nodes = append(v.nodes, h.Handle(v.p, n, v.state, v.math))
|
||||
return nil
|
||||
|
||||
case nil:
|
||||
return v
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("unknown ast node %T", n))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (p *parser) handleNode(node ast.Node, state tex.State, math bool) tex.Node {
|
||||
v := visitor{p: p, state: state, math: math}
|
||||
ast.Walk(&v, node)
|
||||
return tex.HListOf(v.nodes, true)
|
||||
}
|
||||
|
||||
func (p *parser) handler(name string) handler {
|
||||
if _, ok := spaceWidth[name]; ok {
|
||||
return handlerFunc(handleSpace)
|
||||
}
|
||||
if symbols.IsSpaced(name) || symbols.PunctuationSymbols.Has(name) {
|
||||
return handlerFunc(handleSymbol)
|
||||
}
|
||||
if name == `\hspace` {
|
||||
return handlerFunc(handleCustomSpace)
|
||||
}
|
||||
if symbols.FunctionNames.Has(name[1:]) { // drop leading `\`
|
||||
return handlerFunc(handleFunction)
|
||||
}
|
||||
switch name {
|
||||
case `\frac`:
|
||||
return handlerFunc(handleFrac)
|
||||
case `\dfrac`:
|
||||
return handlerFunc(handleDFrac)
|
||||
case `\tfrac`:
|
||||
return handlerFunc(handleTFrac)
|
||||
case `\binom`:
|
||||
return handlerFunc(handleBinom)
|
||||
// case `\genfrac`:
|
||||
// return handlerFunc(handleGenFrac)
|
||||
case `\sqrt`:
|
||||
return handlerFunc(handleSqrt)
|
||||
case `\overline`:
|
||||
return handlerFunc(handleOverline)
|
||||
}
|
||||
_, ok := p.macros[name]
|
||||
if ok {
|
||||
return handlerFunc(handleSymbol)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) init() {
|
||||
for _, k := range tex2unicode.Symbols() {
|
||||
p.macros[`\`+k] = builtinMacro("")
|
||||
}
|
||||
for k, v := range builtinMacros {
|
||||
p.macros[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func handleSymbol(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
pos := int(node.Pos())
|
||||
sym := ""
|
||||
switch node := node.(type) {
|
||||
case *ast.Macro:
|
||||
sym = node.Name.Name
|
||||
case *ast.Symbol:
|
||||
sym = node.Text
|
||||
case *ast.Word:
|
||||
sym = node.Text
|
||||
case *ast.Literal:
|
||||
sym = node.Text
|
||||
default:
|
||||
panic("invalid ast Node")
|
||||
}
|
||||
ch := tex.NewChar(sym, state, math)
|
||||
switch {
|
||||
case symbols.IsSpaced(sym):
|
||||
i := strings.LastIndexFunc(p.expr[:pos], func(r rune) bool {
|
||||
return r != ' '
|
||||
})
|
||||
prev := ""
|
||||
if i >= 0 {
|
||||
prev = string(p.expr[i])
|
||||
}
|
||||
switch {
|
||||
case symbols.BinaryOperators.Has(sym) && (len(strings.Split(p.expr[:pos], " ")) == 0 ||
|
||||
prev == "{" ||
|
||||
symbols.LeftDelim.Has(prev)):
|
||||
// binary operators at start of string should not be spaced
|
||||
return ch
|
||||
default:
|
||||
return tex.HListOf([]tex.Node{
|
||||
p.makeSpace(state, 0.2),
|
||||
ch,
|
||||
p.makeSpace(state, 0.2),
|
||||
}, true)
|
||||
}
|
||||
|
||||
case symbols.PunctuationSymbols.Has(sym):
|
||||
switch sym {
|
||||
case ".":
|
||||
pos := strings.Index(p.expr[pos:], sym)
|
||||
if (pos > 0 && isdigit(p.expr[pos-1])) &&
|
||||
(pos < len(p.expr)-1 && isdigit(p.expr[pos+1])) {
|
||||
// do not space dots as decimal separators.
|
||||
return ch
|
||||
}
|
||||
return tex.HListOf([]tex.Node{
|
||||
ch,
|
||||
p.makeSpace(state, 0.2),
|
||||
}, true)
|
||||
}
|
||||
panic("not implemented")
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
var spaceWidth = map[string]float64{
|
||||
`\,`: 0.16667, // 3/18 em = 3 mu
|
||||
`\thinspace`: 0.16667, // 3/18 em = 3 mu
|
||||
`\/`: 0.16667, // 3/18 em = 3 mu
|
||||
`\>`: 0.22222, // 4/18 em = 4 mu
|
||||
`\:`: 0.22222, // 4/18 em = 4 mu
|
||||
`\;`: 0.27778, // 5/18 em = 5 mu
|
||||
`\ `: 0.33333, // 6/18 em = 6 mu
|
||||
`~`: 0.33333, // 6/18 em = 6 mu, nonbreakable
|
||||
`\enspace`: 0.5, // 9/18 em = 9 mu
|
||||
`\quad`: 1, // 1 em = 18 mu
|
||||
`\qquad`: 2, // 2 em = 36 mu
|
||||
`\!`: -0.16667, // -3/18 em = -3 mu
|
||||
|
||||
}
|
||||
|
||||
func handleSpace(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
var (
|
||||
width float64
|
||||
ok bool
|
||||
)
|
||||
switch node := node.(type) {
|
||||
case *ast.Symbol:
|
||||
width, ok = spaceWidth[node.Text]
|
||||
case *ast.Macro:
|
||||
width, ok = spaceWidth[node.Name.Name]
|
||||
default:
|
||||
panic(fmt.Errorf("invalid ast node %#v (%T)", node, node))
|
||||
}
|
||||
if !ok {
|
||||
panic(fmt.Errorf("could not find a width for %#v (%T)", node, node))
|
||||
}
|
||||
|
||||
return p.makeSpace(state, width)
|
||||
}
|
||||
|
||||
func handleCustomSpace(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
macro := node.(*ast.Macro)
|
||||
arg := macro.Args[0].(*ast.Arg).List[0].(*ast.Literal).Text
|
||||
val, err := strconv.ParseFloat(arg, 64)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not parse customspace: %+v", err))
|
||||
}
|
||||
return p.makeSpace(state, val)
|
||||
}
|
||||
|
||||
func handleFunction(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
macro := node.(*ast.Macro)
|
||||
state.Font.Type = "rm"
|
||||
fun := macro.Name.Name[1:] // drop leading `\`
|
||||
nodes := make([]tex.Node, 0, len(fun))
|
||||
for _, c := range fun {
|
||||
nodes = append(nodes, tex.NewChar(string(c), state, math))
|
||||
}
|
||||
return tex.HListOf(nodes, true)
|
||||
}
|
||||
|
||||
func handleFrac(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
var (
|
||||
macro = node.(*ast.Macro)
|
||||
thickness = state.Backend().UnderlineThickness(state.Font, state.DPI)
|
||||
numNode = ast.List(macro.Args[0].(*ast.Arg).List)
|
||||
denNode = ast.List(macro.Args[1].(*ast.Arg).List)
|
||||
)
|
||||
|
||||
num := p.handleNode(numNode, state, math)
|
||||
den := p.handleNode(denNode, state, math)
|
||||
|
||||
// FIXME(sbinet): this should be infered from the context.
|
||||
// ie: textStyle when in $ $ environment.
|
||||
// displayStyle when in \[\] environment.
|
||||
sty := textStyle
|
||||
|
||||
return p.genfrac("", "", thickness, sty, num, den, state)
|
||||
}
|
||||
|
||||
func handleDFrac(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
var (
|
||||
macro = node.(*ast.Macro)
|
||||
thickness = state.Backend().UnderlineThickness(state.Font, state.DPI)
|
||||
numNode = ast.List(macro.Args[0].(*ast.Arg).List)
|
||||
denNode = ast.List(macro.Args[1].(*ast.Arg).List)
|
||||
)
|
||||
|
||||
num := p.handleNode(numNode, state, math)
|
||||
den := p.handleNode(denNode, state, math)
|
||||
|
||||
return p.genfrac("", "", thickness, displayStyle, num, den, state)
|
||||
}
|
||||
|
||||
func handleTFrac(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
var (
|
||||
macro = node.(*ast.Macro)
|
||||
thickness = state.Backend().UnderlineThickness(state.Font, state.DPI)
|
||||
numNode = ast.List(macro.Args[0].(*ast.Arg).List)
|
||||
denNode = ast.List(macro.Args[1].(*ast.Arg).List)
|
||||
)
|
||||
|
||||
num := p.handleNode(numNode, state, math)
|
||||
den := p.handleNode(denNode, state, math)
|
||||
|
||||
return p.genfrac("", "", thickness, textStyle, num, den, state)
|
||||
}
|
||||
|
||||
func handleBinom(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
var (
|
||||
macro = node.(*ast.Macro)
|
||||
numNode = ast.List(macro.Args[0].(*ast.Arg).List)
|
||||
denNode = ast.List(macro.Args[1].(*ast.Arg).List)
|
||||
)
|
||||
|
||||
num := p.handleNode(numNode, state, math)
|
||||
den := p.handleNode(denNode, state, math)
|
||||
|
||||
return p.genfrac("(", ")", 0, textStyle, num, den, state)
|
||||
}
|
||||
|
||||
func (p *parser) genfrac(ldelim, rdelim string, rule float64, style mathStyleKind, num, den tex.Node, state tex.State) tex.Node {
|
||||
thickness := state.Backend().UnderlineThickness(state.Font, state.DPI)
|
||||
|
||||
if style != displayStyle {
|
||||
num.Shrink()
|
||||
den.Shrink()
|
||||
}
|
||||
|
||||
cnum := tex.HCentered([]tex.Node{num})
|
||||
cden := tex.HCentered([]tex.Node{den})
|
||||
width := math.Max(num.Width(), den.Width())
|
||||
|
||||
const additional = false // i.e.: exactly
|
||||
cnum.HPack(width, additional)
|
||||
cden.HPack(width, additional)
|
||||
|
||||
vlist := tex.VListOf([]tex.Node{
|
||||
cnum, // numerator
|
||||
tex.VBox(0, thickness*2), // space
|
||||
tex.HRule(state, rule), // rule
|
||||
tex.VBox(0, thickness*2), // space
|
||||
cden, // denominator
|
||||
})
|
||||
|
||||
// shift so the fraction line sits in the middle of the '=' sign
|
||||
fnt := state.Font
|
||||
fnt.Type = rcparams("mathtext.default").(string)
|
||||
metrics := state.Backend().Metrics("=", fnt, state.DPI, true)
|
||||
shift := cden.Height() - ((metrics.YMax+metrics.YMin)/2 - 3*thickness)
|
||||
vlist.SetShift(shift)
|
||||
|
||||
box := tex.HListOf([]tex.Node{vlist, tex.HBox(2 * thickness)}, true)
|
||||
if ldelim != "" || rdelim != "" {
|
||||
if ldelim == "" {
|
||||
ldelim = "."
|
||||
}
|
||||
if rdelim == "" {
|
||||
rdelim = "."
|
||||
}
|
||||
return p.autoSizedDelimiter(ldelim, []tex.Node{box}, rdelim, state)
|
||||
}
|
||||
|
||||
return box
|
||||
}
|
||||
|
||||
func handleSqrt(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
var (
|
||||
macro = node.(*ast.Macro)
|
||||
root tex.Node
|
||||
body *tex.HList
|
||||
)
|
||||
switch len(macro.Args) {
|
||||
case 2:
|
||||
root = p.handleNode(
|
||||
ast.List(macro.Args[0].(*ast.OptArg).List),
|
||||
state, math,
|
||||
)
|
||||
body = p.handleNode(
|
||||
ast.List(macro.Args[1].(*ast.Arg).List),
|
||||
state, math,
|
||||
).(*tex.HList)
|
||||
case 1:
|
||||
// ok
|
||||
body = p.handleNode(
|
||||
ast.List(macro.Args[0].(*ast.Arg).List),
|
||||
state, math,
|
||||
).(*tex.HList)
|
||||
default:
|
||||
panic("invalid sqrt")
|
||||
}
|
||||
|
||||
thickness := state.Backend().UnderlineThickness(state.Font, state.DPI)
|
||||
|
||||
// determine the height of the body, add a little extra to it so
|
||||
// it doesn't seem too cramped.
|
||||
height := body.Height() - body.Shift() + 5*thickness
|
||||
depth := body.Depth() + body.Shift()
|
||||
check := tex.AutoHeightChar(`\__sqrt__`, height, depth, state, 0)
|
||||
height = check.Height() - check.Shift()
|
||||
depth = check.Depth() + check.Shift()
|
||||
|
||||
// put a little extra space to the left and right of the body
|
||||
padded := tex.HListOf([]tex.Node{
|
||||
tex.HBox(2 * thickness),
|
||||
body,
|
||||
tex.HBox(2 * thickness),
|
||||
}, true)
|
||||
rhs := tex.VListOf([]tex.Node{
|
||||
tex.HRule(state, -1),
|
||||
tex.NewGlue("fill"),
|
||||
padded,
|
||||
})
|
||||
|
||||
// stretch the glue between the HRule and the body
|
||||
const additional = false
|
||||
rhs.VPack(height+(state.Font.Size*state.DPI)/(100*12), additional, depth)
|
||||
|
||||
// add the root and shift it upward so it is above the tick.
|
||||
switch root {
|
||||
case nil:
|
||||
root = tex.HBox(check.Width() * 0.5)
|
||||
default:
|
||||
root.Shrink()
|
||||
root.Shrink()
|
||||
}
|
||||
|
||||
vl := tex.VListOf([]tex.Node{
|
||||
tex.HListOf([]tex.Node{
|
||||
root,
|
||||
}, true),
|
||||
})
|
||||
vl.SetShift(-height * 0.6)
|
||||
|
||||
hl := tex.HListOf([]tex.Node{
|
||||
vl, // root
|
||||
// negative kerning to put root over tick
|
||||
tex.NewKern(-check.Width() * 0.5),
|
||||
check,
|
||||
rhs,
|
||||
}, true)
|
||||
|
||||
return hl
|
||||
}
|
||||
|
||||
func handleOverline(p *parser, node ast.Node, state tex.State, math bool) tex.Node {
|
||||
macro := node.(*ast.Macro)
|
||||
body := p.handleNode(
|
||||
ast.List(macro.Args[0].(*ast.Arg).List),
|
||||
state, math,
|
||||
).(*tex.HList)
|
||||
|
||||
thickness := state.Backend().UnderlineThickness(state.Font, state.DPI)
|
||||
|
||||
height := body.Height() - body.Shift() + 3*thickness
|
||||
depth := body.Depth() + body.Shift()
|
||||
|
||||
// place overline above body
|
||||
rhs := tex.VListOf([]tex.Node{
|
||||
tex.HRule(state, -1),
|
||||
tex.NewGlue("fill"),
|
||||
tex.HListOf([]tex.Node{body}, true),
|
||||
})
|
||||
|
||||
// stretch the glue between the HRule and the body
|
||||
const additional = false
|
||||
rhs.VPack(height+(state.Font.Size*state.DPI)/(100*12), additional, depth)
|
||||
|
||||
hl := tex.HListOf([]tex.Node{rhs}, true)
|
||||
return hl
|
||||
}
|
||||
|
||||
func (p *parser) makeSpace(state tex.State, percentage float64) *tex.Kern {
|
||||
const math = true
|
||||
fnt := state.Font
|
||||
fnt.Name = "it"
|
||||
fnt.Type = rcparams("mathtext.default").(string)
|
||||
width := p.be.Metrics("m", fnt, state.DPI, math).Advance
|
||||
return tex.NewKern(width * percentage)
|
||||
}
|
||||
|
||||
func (p *parser) autoSizedDelimiter(left string, middle []tex.Node, right string, state tex.State) tex.Node {
|
||||
var (
|
||||
height float64
|
||||
depth float64
|
||||
factor float64 = 1
|
||||
)
|
||||
|
||||
if len(middle) > 0 {
|
||||
for _, node := range middle {
|
||||
height = math.Max(height, node.Height())
|
||||
depth = math.Max(depth, node.Depth())
|
||||
}
|
||||
factor = 0
|
||||
}
|
||||
|
||||
var parts []tex.Node
|
||||
if left != "." {
|
||||
// \left. isn't supposed to produce any symbol
|
||||
ahc := tex.AutoHeightChar(left, height, depth, state, factor)
|
||||
parts = append(parts, ahc)
|
||||
}
|
||||
parts = append(parts, middle...)
|
||||
if right != "." {
|
||||
// \right. isn't supposed to produce any symbol
|
||||
ahc := tex.AutoHeightChar(right, height, depth, state, factor)
|
||||
parts = append(parts, ahc)
|
||||
}
|
||||
return tex.HListOf(parts, true)
|
||||
}
|
||||
|
||||
type mathStyleKind int
|
||||
|
||||
const (
|
||||
displayStyle mathStyleKind = iota
|
||||
textStyle
|
||||
//scriptStyle // FIXME
|
||||
//scriptScriptStyle // FIXME
|
||||
)
|
||||
|
||||
func rcparams(k string) interface{} {
|
||||
switch k {
|
||||
case "mathtext.default":
|
||||
return "it"
|
||||
default:
|
||||
panic("unknown rc.params key [" + k + "]")
|
||||
}
|
||||
}
|
||||
|
||||
func isdigit(v byte) bool {
|
||||
switch v {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
50
vendor/github.com/go-latex/latex/mtex/render.go
generated
vendored
Normal file
50
vendor/github.com/go-latex/latex/mtex/render.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright ©2020 The go-latex 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 mtex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/go-latex/latex/drawtex"
|
||||
"github.com/go-latex/latex/font/ttf"
|
||||
"github.com/go-latex/latex/tex"
|
||||
)
|
||||
|
||||
type Renderer interface {
|
||||
Render(w, h, dpi float64, cnv *drawtex.Canvas) error
|
||||
}
|
||||
|
||||
func Render(dst Renderer, expr string, size, dpi float64, fonts *ttf.Fonts) error {
|
||||
var (
|
||||
canvas = drawtex.New()
|
||||
backend *ttf.Backend
|
||||
)
|
||||
switch fonts {
|
||||
case nil:
|
||||
backend = ttf.New(canvas)
|
||||
default:
|
||||
backend = ttf.NewFrom(canvas, fonts)
|
||||
}
|
||||
|
||||
box, err := Parse(expr, size, 72, backend)
|
||||
if err != nil {
|
||||
return 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()
|
||||
|
||||
err = dst.Render(w/72, math.Ceil(h+math.Max(d, 0))/72, dpi, canvas)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not render math expression: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
43
vendor/github.com/go-latex/latex/mtex/symbols/set.go
generated
vendored
Normal file
43
vendor/github.com/go-latex/latex/mtex/symbols/set.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright ©2020 The go-latex 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 symbols
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Set map[string]struct{}
|
||||
|
||||
func NewSet(vs ...string) Set {
|
||||
o := make(Set, len(vs))
|
||||
for _, k := range vs {
|
||||
o[k] = struct{}{}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (set Set) Has(k string) bool {
|
||||
_, ok := set[k]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (set Set) Keys() []string {
|
||||
keys := make([]string, 0, len(set))
|
||||
for k := range set {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func UnionOf(sets ...Set) Set {
|
||||
o := make(Set, len(sets))
|
||||
for _, set := range sets {
|
||||
for k := range set {
|
||||
o[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
16
vendor/github.com/go-latex/latex/mtex/symbols/symbols.go
generated
vendored
Normal file
16
vendor/github.com/go-latex/latex/mtex/symbols/symbols.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright ©2020 The go-latex 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 symbols contains logic about TeX symbols.
|
||||
package symbols // import "github.com/go-latex/latex/mtex/symbols"
|
||||
|
||||
//go:generate go run ./gen-symbols.go
|
||||
|
||||
var (
|
||||
SpacedSymbols = UnionOf(BinaryOperators, RelationSymbols, ArrowSymbols)
|
||||
)
|
||||
|
||||
func IsSpaced(s string) bool {
|
||||
return SpacedSymbols.Has(s)
|
||||
}
|
||||
254
vendor/github.com/go-latex/latex/mtex/symbols/symbols_gen.go
generated
vendored
Normal file
254
vendor/github.com/go-latex/latex/mtex/symbols/symbols_gen.go
generated
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
// Autogenerated. DO NOT EDIT.
|
||||
|
||||
package symbols
|
||||
|
||||
var (
|
||||
AmbiDelim = NewSet(
|
||||
"\\downarrow",
|
||||
"\\Uparrow",
|
||||
"\\|",
|
||||
"\\updownarrow",
|
||||
"\\vert",
|
||||
"\\Vert",
|
||||
"\\backslash",
|
||||
".",
|
||||
"\\Updownarrow",
|
||||
"/",
|
||||
"\\Downarrow",
|
||||
"|",
|
||||
"\\\\|",
|
||||
"\\uparrow",
|
||||
)
|
||||
|
||||
ArrowSymbols = NewSet(
|
||||
"\\Uparrow",
|
||||
"\\searrow",
|
||||
"\\hookleftarrow",
|
||||
"\\longleftrightarrow",
|
||||
"\\longrightarrow",
|
||||
"\\rightarrow",
|
||||
"\\leadsto",
|
||||
"\\nearrow",
|
||||
"\\Updownarrow",
|
||||
"\\rightharpoonup",
|
||||
"\\Longrightarrow",
|
||||
"\\leftrightarrow",
|
||||
"\\downarrow",
|
||||
"\\nwarrow",
|
||||
"\\leftarrow",
|
||||
"\\leftharpoondown",
|
||||
"\\swarrow",
|
||||
"\\Longleftarrow",
|
||||
"\\Leftarrow",
|
||||
"\\Longleftrightarrow",
|
||||
"\\uparrow",
|
||||
"\\hookrightarrow",
|
||||
"\\rightleftharpoons",
|
||||
"\\mapsto",
|
||||
"\\Leftrightarrow",
|
||||
"\\leftharpoonup",
|
||||
"\\rightharpoondown",
|
||||
"\\updownarrow",
|
||||
"\\Rightarrow",
|
||||
"\\longleftarrow",
|
||||
"\\Downarrow",
|
||||
"\\longmapsto",
|
||||
)
|
||||
|
||||
BinaryOperators = NewSet(
|
||||
"\\triangleleft",
|
||||
"\\cup",
|
||||
"+",
|
||||
"\\oplus",
|
||||
"*",
|
||||
"\\bullet",
|
||||
"\\star",
|
||||
"\\diamond",
|
||||
"\\div",
|
||||
"\\bigtriangledown",
|
||||
"\\unrhd",
|
||||
"\\wr",
|
||||
"\\bigtriangleup",
|
||||
"\\sqcup",
|
||||
"\\vee",
|
||||
"\\sqcap",
|
||||
"\\dagger",
|
||||
"\\cdot",
|
||||
"\\unlhd",
|
||||
"\\triangleright",
|
||||
"\\ddagger",
|
||||
"\\amalg",
|
||||
"\\circ",
|
||||
"\\odot",
|
||||
"\\cap",
|
||||
"\\bigcirc",
|
||||
"\\lhd",
|
||||
"\\times",
|
||||
"-",
|
||||
"\\wedge",
|
||||
"\\mp",
|
||||
"\\otimes",
|
||||
"\\ominus",
|
||||
"\\ast",
|
||||
"\\pm",
|
||||
"\\oslash",
|
||||
"\\rhd",
|
||||
"\\setminus",
|
||||
"\\uplus",
|
||||
)
|
||||
|
||||
DropSubSymbols = NewSet(
|
||||
"\\oint",
|
||||
"\\int",
|
||||
)
|
||||
|
||||
FontNames = NewSet(
|
||||
"circled",
|
||||
"default",
|
||||
"cal",
|
||||
"bf",
|
||||
"regular",
|
||||
"tt",
|
||||
"scr",
|
||||
"sf",
|
||||
"frak",
|
||||
"rm",
|
||||
"it",
|
||||
"bb",
|
||||
)
|
||||
|
||||
FunctionNames = NewSet(
|
||||
"lim",
|
||||
"arccos",
|
||||
"min",
|
||||
"arcsin",
|
||||
"gcd",
|
||||
"arctan",
|
||||
"sup",
|
||||
"sec",
|
||||
"max",
|
||||
"cos",
|
||||
"deg",
|
||||
"arg",
|
||||
"sin",
|
||||
"log",
|
||||
"sinh",
|
||||
"ker",
|
||||
"liminf",
|
||||
"coth",
|
||||
"exp",
|
||||
"det",
|
||||
"ln",
|
||||
"lg",
|
||||
"Pr",
|
||||
"tan",
|
||||
"tanh",
|
||||
"csc",
|
||||
"hom",
|
||||
"cosh",
|
||||
"cot",
|
||||
"dim",
|
||||
"limsup",
|
||||
"inf",
|
||||
)
|
||||
|
||||
LeftDelim = NewSet(
|
||||
"\\lfloor",
|
||||
"<",
|
||||
"\\{",
|
||||
"\\langle",
|
||||
"[",
|
||||
"(",
|
||||
"\\lceil",
|
||||
)
|
||||
|
||||
OverUnderFunctions = NewSet(
|
||||
"sup",
|
||||
"max",
|
||||
"lim",
|
||||
"limsup",
|
||||
"min",
|
||||
"liminf",
|
||||
)
|
||||
|
||||
OverUnderSymbols = NewSet(
|
||||
"\\biguplus",
|
||||
"\\bigoplus",
|
||||
"\\prod",
|
||||
"\\bigcap",
|
||||
"\\bigsqcup",
|
||||
"\\bigodot",
|
||||
"\\bigvee",
|
||||
"\\bigwedge",
|
||||
"\\sum",
|
||||
"\\bigcup",
|
||||
"\\coprod",
|
||||
"\\bigotimes",
|
||||
)
|
||||
|
||||
PunctuationSymbols = NewSet(
|
||||
"!",
|
||||
";",
|
||||
"\\cdotp",
|
||||
",",
|
||||
".",
|
||||
"\\ldotp",
|
||||
)
|
||||
|
||||
RelationSymbols = NewSet(
|
||||
"\\ni",
|
||||
"\\leq",
|
||||
"\\ll",
|
||||
"\\supseteq",
|
||||
"\\succ",
|
||||
"=",
|
||||
"\\neq",
|
||||
"\\parallel",
|
||||
"\\geq",
|
||||
"\\prec",
|
||||
"\\frown",
|
||||
"\\in",
|
||||
"\\Join",
|
||||
"\\sqsubset",
|
||||
"\\dashv",
|
||||
"\\vdash",
|
||||
"\\dots",
|
||||
"\\asymp",
|
||||
"\\subset",
|
||||
"\\subseteq",
|
||||
"\\sqsupseteq",
|
||||
"<",
|
||||
"\\models",
|
||||
"\\bowtie",
|
||||
"\\equiv",
|
||||
":",
|
||||
"\\sqsupset",
|
||||
"\\smile",
|
||||
"\\propto",
|
||||
"\\dotplus",
|
||||
"\\preceq",
|
||||
"\\cong",
|
||||
"\\simeq",
|
||||
">",
|
||||
"\\mid",
|
||||
"\\approx",
|
||||
"\\supset",
|
||||
"\\gg",
|
||||
"\\doteq",
|
||||
"\\sqsubseteq",
|
||||
"\\doteqdot",
|
||||
"\\succeq",
|
||||
"\\perp",
|
||||
"\\sim",
|
||||
)
|
||||
|
||||
RightDelim = NewSet(
|
||||
"\\rceil",
|
||||
"]",
|
||||
"\\rangle",
|
||||
">",
|
||||
"\\}",
|
||||
"\\rfloor",
|
||||
")",
|
||||
)
|
||||
)
|
||||
337
vendor/github.com/go-latex/latex/parser.go
generated
vendored
Normal file
337
vendor/github.com/go-latex/latex/parser.go
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
// Copyright ©2020 The go-latex 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 latex // import "github.com/go-latex/latex"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-latex/latex/ast"
|
||||
"github.com/go-latex/latex/token"
|
||||
)
|
||||
|
||||
// ParseExpr parses a simple LaTeX expression.
|
||||
func ParseExpr(x string) (ast.Node, error) {
|
||||
p := newParser(x)
|
||||
return p.parse()
|
||||
}
|
||||
|
||||
type state int
|
||||
|
||||
const (
|
||||
normalState state = iota
|
||||
mathState
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
s *texScanner
|
||||
state state
|
||||
|
||||
macros map[string]macroParser
|
||||
}
|
||||
|
||||
func newParser(x string) *parser {
|
||||
p := &parser{
|
||||
s: newScanner(strings.NewReader(x)),
|
||||
state: normalState,
|
||||
}
|
||||
p.addBuiltinMacros()
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *parser) parse() (ast.Node, error) {
|
||||
var nodes ast.List
|
||||
for p.s.Next() {
|
||||
tok := p.s.Token()
|
||||
node := p.parseNode(tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (p *parser) next() token.Token {
|
||||
if !p.s.Next() {
|
||||
return token.Token{Kind: token.EOF}
|
||||
}
|
||||
return p.s.tok
|
||||
}
|
||||
|
||||
func (p *parser) expect(v rune) {
|
||||
p.next()
|
||||
if p.s.tok.Text != string(v) {
|
||||
panic(fmt.Errorf("expected %q, got %q", v, p.s.tok.Text))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) parseNode(tok token.Token) ast.Node {
|
||||
switch tok.Kind {
|
||||
case token.Comment:
|
||||
return nil
|
||||
case token.Macro:
|
||||
return p.parseMacro(tok)
|
||||
case token.Word:
|
||||
return p.parseWord(tok)
|
||||
case token.Number:
|
||||
return p.parseNumber(tok)
|
||||
case token.Symbol:
|
||||
switch tok.Text {
|
||||
case "$":
|
||||
return p.parseMathExpr(tok)
|
||||
case "^":
|
||||
return p.parseSup(tok)
|
||||
case "_":
|
||||
return p.parseSub(tok)
|
||||
default:
|
||||
return p.parseSymbol(tok)
|
||||
}
|
||||
case token.Lbrace:
|
||||
switch p.state {
|
||||
case mathState:
|
||||
return p.parseMathLbrace(tok)
|
||||
default:
|
||||
panic("not implemented")
|
||||
}
|
||||
case token.Other:
|
||||
switch tok.Text {
|
||||
default:
|
||||
panic("not implemented: " + tok.String())
|
||||
}
|
||||
case token.Space:
|
||||
switch p.state {
|
||||
case mathState:
|
||||
return nil
|
||||
default:
|
||||
return p.parseSymbol(tok)
|
||||
}
|
||||
|
||||
case token.Lparen, token.Rparen,
|
||||
token.Lbrack, token.Rbrack:
|
||||
return p.parseSymbol(tok)
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("impossible: %v (%v)", tok, tok.Kind))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) parseMathExpr(tok token.Token) ast.Node {
|
||||
state := p.state
|
||||
p.state = mathState
|
||||
defer func() {
|
||||
p.state = state
|
||||
}()
|
||||
|
||||
math := &ast.MathExpr{
|
||||
Delim: tok.Text,
|
||||
Left: tok.Pos,
|
||||
}
|
||||
var end string
|
||||
switch tok.Text {
|
||||
case "$":
|
||||
end = "$"
|
||||
case `\(`:
|
||||
end = `\)`
|
||||
case `\[`:
|
||||
end = `\]`
|
||||
case `\begin`:
|
||||
panic("not implemented")
|
||||
default:
|
||||
panic(fmt.Errorf("opening math-expression delimiter %q not supported", tok.Text))
|
||||
}
|
||||
|
||||
loop:
|
||||
for p.s.Next() {
|
||||
switch p.s.tok.Text {
|
||||
case end:
|
||||
math.Right = p.s.tok.Pos
|
||||
break loop
|
||||
default:
|
||||
node := p.parseNode(p.s.tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
math.List = append(math.List, node)
|
||||
}
|
||||
}
|
||||
|
||||
return math
|
||||
}
|
||||
|
||||
func (p *parser) parseMacro(tok token.Token) ast.Node {
|
||||
name := tok.Text
|
||||
macro, ok := p.macros[name]
|
||||
if !ok {
|
||||
panic("unknown macro " + name)
|
||||
//return nil
|
||||
}
|
||||
return macro.parseMacro(p)
|
||||
}
|
||||
|
||||
func (p *parser) parseWord(tok token.Token) ast.Node {
|
||||
return &ast.Word{
|
||||
WordPos: tok.Pos,
|
||||
Text: tok.Text,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) parseNumber(tok token.Token) ast.Node {
|
||||
return &ast.Literal{
|
||||
LitPos: tok.Pos,
|
||||
Text: tok.Text,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) parseMacroArg(macro *ast.Macro) {
|
||||
var arg ast.Arg
|
||||
p.expect('{')
|
||||
arg.Lbrace = p.s.tok.Pos
|
||||
|
||||
loop:
|
||||
for p.s.Next() {
|
||||
switch p.s.tok.Kind {
|
||||
case token.Rbrace:
|
||||
arg.Rbrace = p.s.tok.Pos
|
||||
break loop
|
||||
default:
|
||||
node := p.parseNode(p.s.tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
arg.List = append(arg.List, node)
|
||||
}
|
||||
}
|
||||
macro.Args = append(macro.Args, &arg)
|
||||
}
|
||||
|
||||
func (p *parser) parseOptMacroArg(macro *ast.Macro) {
|
||||
nxt := p.s.sc.Peek()
|
||||
if nxt != '[' {
|
||||
return
|
||||
}
|
||||
|
||||
var opt ast.OptArg
|
||||
|
||||
p.expect('[')
|
||||
opt.Lbrack = p.s.tok.Pos
|
||||
|
||||
loop:
|
||||
for p.s.Next() {
|
||||
switch p.s.tok.Kind {
|
||||
case token.Rbrack:
|
||||
opt.Rbrack = p.s.tok.Pos
|
||||
break loop
|
||||
default:
|
||||
node := p.parseNode(p.s.tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
opt.List = append(opt.List, node)
|
||||
}
|
||||
}
|
||||
macro.Args = append(macro.Args, &opt)
|
||||
}
|
||||
|
||||
func (p *parser) parseVerbatimMacroArg(macro *ast.Macro) {
|
||||
}
|
||||
|
||||
func (p *parser) parseSup(tok token.Token) ast.Node {
|
||||
hat := &ast.Sup{
|
||||
HatPos: tok.Pos,
|
||||
}
|
||||
|
||||
switch next := p.s.sc.Peek(); next {
|
||||
case '{':
|
||||
p.expect('{')
|
||||
var list ast.List
|
||||
loop:
|
||||
for p.s.Next() {
|
||||
switch p.s.tok.Kind {
|
||||
case token.Rbrace:
|
||||
break loop
|
||||
default:
|
||||
node := p.parseNode(p.s.tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, node)
|
||||
}
|
||||
}
|
||||
hat.Node = list
|
||||
default:
|
||||
hat.Node = p.parseNode(p.next())
|
||||
}
|
||||
|
||||
return hat
|
||||
}
|
||||
|
||||
func (p *parser) parseSub(tok token.Token) ast.Node {
|
||||
sub := &ast.Sub{
|
||||
UnderPos: tok.Pos,
|
||||
}
|
||||
|
||||
switch next := p.s.sc.Peek(); next {
|
||||
case '{':
|
||||
p.expect('{')
|
||||
var list ast.List
|
||||
loop:
|
||||
for p.s.Next() {
|
||||
switch p.s.tok.Kind {
|
||||
case token.Rbrace:
|
||||
break loop
|
||||
default:
|
||||
node := p.parseNode(p.s.tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, node)
|
||||
}
|
||||
}
|
||||
sub.Node = list
|
||||
default:
|
||||
sub.Node = p.parseNode(p.next())
|
||||
}
|
||||
|
||||
return sub
|
||||
}
|
||||
|
||||
func (p *parser) parseSymbol(tok token.Token) ast.Node {
|
||||
return &ast.Symbol{
|
||||
SymPos: tok.Pos,
|
||||
Text: tok.Text,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) parseMathLbrace(tok token.Token) ast.Node {
|
||||
var (
|
||||
lst ast.List
|
||||
ldelim = tok.Kind
|
||||
rdelim = map[token.Kind]token.Kind{
|
||||
token.Lbrace: token.Rbrace,
|
||||
token.Lparen: token.Rparen,
|
||||
}[ldelim]
|
||||
)
|
||||
|
||||
if rdelim == token.Invalid {
|
||||
panic("impossible: no matching right-delim for: " + tok.String())
|
||||
}
|
||||
|
||||
loop:
|
||||
for p.s.Next() {
|
||||
switch p.s.tok.Kind {
|
||||
case rdelim:
|
||||
break loop
|
||||
default:
|
||||
node := p.parseNode(p.s.tok)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
lst = append(lst, node)
|
||||
}
|
||||
}
|
||||
return lst
|
||||
}
|
||||
205
vendor/github.com/go-latex/latex/scanner.go
generated
vendored
Normal file
205
vendor/github.com/go-latex/latex/scanner.go
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
// Copyright ©2020 The go-latex 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 latex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/scanner"
|
||||
"unicode"
|
||||
|
||||
"github.com/go-latex/latex/token"
|
||||
)
|
||||
|
||||
type texScanner struct {
|
||||
sc scanner.Scanner
|
||||
|
||||
r rune
|
||||
tok token.Token
|
||||
}
|
||||
|
||||
func newScanner(r io.Reader) *texScanner {
|
||||
sc := &texScanner{}
|
||||
sc.sc.Init(r)
|
||||
sc.sc.Mode = (scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats)
|
||||
sc.sc.Mode |= scanner.ScanStrings
|
||||
//scanner.ScanRawStrings)
|
||||
// sc.sc.Error = func(s *scanner.Scanner, msg string) {}
|
||||
sc.sc.IsIdentRune = func(ch rune, i int) bool {
|
||||
return unicode.IsLetter(ch) //|| unicode.IsDigit(ch) && i > 0
|
||||
}
|
||||
sc.sc.Whitespace = 1<<'\t' | 1<<'\n' | 1<<'\r'
|
||||
return sc
|
||||
}
|
||||
|
||||
// Token returns the most recently parsed token
|
||||
func (s *texScanner) Token() token.Token {
|
||||
return s.tok
|
||||
}
|
||||
|
||||
// Next iterates over all tokens.
|
||||
// Next retrieves the most recent token with Token().
|
||||
// It returns false once it reaches token.EOF.
|
||||
func (s *texScanner) Next() bool {
|
||||
s.tok = s.scan()
|
||||
return s.tok.Kind != token.EOF
|
||||
}
|
||||
|
||||
func (s *texScanner) scan() token.Token {
|
||||
s.next()
|
||||
pos := s.pos()
|
||||
switch s.r {
|
||||
case scanner.Ident:
|
||||
return token.Token{
|
||||
Kind: token.Word,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case '\\':
|
||||
nxt := s.sc.Peek()
|
||||
switch nxt {
|
||||
case ' ':
|
||||
s.next()
|
||||
return token.Token{
|
||||
Kind: token.Space,
|
||||
Pos: pos,
|
||||
Text: `\ `,
|
||||
}
|
||||
default:
|
||||
return s.scanMacro()
|
||||
}
|
||||
case ' ':
|
||||
return token.Token{
|
||||
Kind: token.Space,
|
||||
Pos: pos,
|
||||
Text: ` `,
|
||||
}
|
||||
|
||||
case '%':
|
||||
line := s.scanComment()
|
||||
return token.Token{
|
||||
Kind: token.Comment,
|
||||
Pos: pos,
|
||||
Text: line,
|
||||
}
|
||||
|
||||
case '$', '_', '=', '<', '>', '^', '/', '*', '-', '+',
|
||||
'!', '?', '\'', ':', ',', ';', '.':
|
||||
return token.Token{
|
||||
Kind: token.Symbol,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
|
||||
case '[':
|
||||
return token.Token{
|
||||
Kind: token.Lbrack,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case ']':
|
||||
return token.Token{
|
||||
Kind: token.Rbrack,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case '{':
|
||||
return token.Token{
|
||||
Kind: token.Lbrace,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case '}':
|
||||
return token.Token{
|
||||
Kind: token.Rbrace,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case '(':
|
||||
return token.Token{
|
||||
Kind: token.Lparen,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case ')':
|
||||
return token.Token{
|
||||
Kind: token.Rparen,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case scanner.Int, scanner.Float:
|
||||
return token.Token{
|
||||
Kind: token.Number,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case scanner.String, scanner.Char:
|
||||
return token.Token{
|
||||
Kind: token.Other,
|
||||
Pos: pos,
|
||||
Text: s.sc.TokenText(),
|
||||
}
|
||||
case scanner.EOF:
|
||||
return token.Token{
|
||||
Kind: token.EOF,
|
||||
Pos: pos,
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unhandled token: %v %v", scanner.TokenString(s.r), s.r))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *texScanner) next() {
|
||||
s.r = s.sc.Scan()
|
||||
}
|
||||
|
||||
func (s *texScanner) scanMacro() token.Token {
|
||||
var (
|
||||
macro = new(strings.Builder)
|
||||
pos = s.pos()
|
||||
)
|
||||
s.next()
|
||||
macro.WriteString(`\` + s.sc.TokenText())
|
||||
|
||||
return token.Token{
|
||||
Kind: token.Macro,
|
||||
Pos: pos,
|
||||
Text: macro.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *texScanner) scanComment() string {
|
||||
comment := new(strings.Builder)
|
||||
comment.WriteString("%")
|
||||
wsp := s.sc.Whitespace
|
||||
defer func() {
|
||||
s.sc.Whitespace = wsp
|
||||
}()
|
||||
s.sc.Whitespace = 0
|
||||
|
||||
for {
|
||||
s.next()
|
||||
if s.r == '\r' {
|
||||
continue
|
||||
}
|
||||
if s.r == '\n' || s.r == scanner.EOF {
|
||||
break
|
||||
}
|
||||
comment.WriteString(s.sc.TokenText())
|
||||
}
|
||||
return comment.String()
|
||||
}
|
||||
|
||||
// func (s *texScanner) expect(want rune) {
|
||||
// s.next()
|
||||
// if s.r != want {
|
||||
// panic(fmt.Errorf("invalid rune: got=%q, want=%q", s.r, want))
|
||||
// }
|
||||
// }
|
||||
|
||||
func (s *texScanner) pos() token.Pos {
|
||||
return token.Pos(s.sc.Position.Offset)
|
||||
}
|
||||
1226
vendor/github.com/go-latex/latex/tex/box.go
generated
vendored
Normal file
1226
vendor/github.com/go-latex/latex/tex/box.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
vendor/github.com/go-latex/latex/tex/state.go
generated
vendored
Normal file
25
vendor/github.com/go-latex/latex/tex/state.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright ©2020 The go-latex 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 tex
|
||||
|
||||
import (
|
||||
"github.com/go-latex/latex/font"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
be font.Backend
|
||||
Font font.Font
|
||||
DPI float64
|
||||
}
|
||||
|
||||
func NewState(be font.Backend, font font.Font, dpi float64) State {
|
||||
return State{
|
||||
be: be,
|
||||
Font: font,
|
||||
DPI: dpi,
|
||||
}
|
||||
}
|
||||
|
||||
func (state State) Backend() font.Backend { return state.be }
|
||||
30
vendor/github.com/go-latex/latex/tex/tex.go
generated
vendored
Normal file
30
vendor/github.com/go-latex/latex/tex/tex.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright ©2020 The go-latex 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 tex provides a TeX-like box model.
|
||||
//
|
||||
// The following is based directly on the document 'woven' from the
|
||||
// TeX82 source code. This information is also available in printed
|
||||
// form:
|
||||
//
|
||||
// Knuth, Donald E.. 1986. Computers and Typesetting, Volume B:
|
||||
// TeX: The Program. Addison-Wesley Professional.
|
||||
//
|
||||
// An electronic version is also available from:
|
||||
//
|
||||
// http://brokestream.com/tex.pdf
|
||||
//
|
||||
// The most relevant "chapters" are:
|
||||
// Data structures for boxes and their friends
|
||||
// Shipping pages out (Ship class)
|
||||
// Packaging (hpack and vpack)
|
||||
// Data structures for math mode
|
||||
// Subroutines for math mode
|
||||
// Typesetting math formulas
|
||||
//
|
||||
// Many of the docstrings below refer to a numbered "node" in that
|
||||
// book, e.g., node123
|
||||
//
|
||||
// Note that (as TeX) y increases downward.
|
||||
package tex // import "github.com/go-latex/latex/tex"
|
||||
26
vendor/github.com/go-latex/latex/tex/utils.go
generated
vendored
Normal file
26
vendor/github.com/go-latex/latex/tex/utils.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright ©2020 The go-latex 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 tex
|
||||
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func clamp(v float64) float64 {
|
||||
const (
|
||||
min = -1000000000.
|
||||
max = +1000000000.
|
||||
)
|
||||
switch {
|
||||
case v < min:
|
||||
return min
|
||||
case v > max:
|
||||
return max
|
||||
}
|
||||
return v
|
||||
}
|
||||
43
vendor/github.com/go-latex/latex/token/kind_string.go
generated
vendored
Normal file
43
vendor/github.com/go-latex/latex/token/kind_string.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Code generated by "stringer -type Kind"; DO NOT EDIT.
|
||||
|
||||
// Copyright ©2020 The go-latex 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 token
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Invalid-0]
|
||||
_ = x[Macro-1]
|
||||
_ = x[EmptyLine-2]
|
||||
_ = x[Comment-3]
|
||||
_ = x[Space-4]
|
||||
_ = x[Word-5]
|
||||
_ = x[Number-6]
|
||||
_ = x[Symbol-7]
|
||||
_ = x[Lbrace-8]
|
||||
_ = x[Rbrace-9]
|
||||
_ = x[Lbrack-10]
|
||||
_ = x[Rbrack-11]
|
||||
_ = x[Lparen-12]
|
||||
_ = x[Rparen-13]
|
||||
_ = x[Other-14]
|
||||
_ = x[Verbatim-15]
|
||||
_ = x[EOF-16]
|
||||
}
|
||||
|
||||
const _Kind_name = "InvalidMacroEmptyLineCommentSpaceWordNumberSymbolLbraceRbraceLbrackRbrackLparenRparenOtherVerbatimEOF"
|
||||
|
||||
var _Kind_index = [...]uint8{0, 7, 12, 21, 28, 33, 37, 43, 49, 55, 61, 67, 73, 79, 85, 90, 98, 101}
|
||||
|
||||
func (i Kind) String() string {
|
||||
if i < 0 || i >= Kind(len(_Kind_index)-1) {
|
||||
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
|
||||
}
|
||||
50
vendor/github.com/go-latex/latex/token/token.go
generated
vendored
Normal file
50
vendor/github.com/go-latex/latex/token/token.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright ©2020 The go-latex 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 token defines constants representing the lexical tokens of
|
||||
// LaTeX documents.
|
||||
package token // import "github.com/go-latex/latex/token"
|
||||
|
||||
//go:generate stringer -type Kind
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// Kind is a kind of LaTeX token.
|
||||
type Kind int
|
||||
|
||||
const (
|
||||
Invalid Kind = iota
|
||||
Macro
|
||||
EmptyLine
|
||||
Comment
|
||||
Space
|
||||
Word
|
||||
Number
|
||||
Symbol // +,-,?,>,>=,...
|
||||
Lbrace
|
||||
Rbrace
|
||||
Lbrack
|
||||
Rbrack
|
||||
Lparen
|
||||
Rparen
|
||||
Other
|
||||
Verbatim
|
||||
EOF
|
||||
)
|
||||
|
||||
// Token holds informations about a token.
|
||||
type Token struct {
|
||||
Kind Kind // Kind is the kind of token.
|
||||
Pos Pos // Pos is the position of a token.
|
||||
Text string
|
||||
}
|
||||
|
||||
func (t Token) String() string { return t.Text }
|
||||
|
||||
// Pos is a compact encoding of a source position within a file set.
|
||||
//
|
||||
// Aliased from go/token.Pos
|
||||
type Pos = token.Pos
|
||||
Reference in New Issue
Block a user