switched from float32 to float64 for better compatibility with the default go math package; moved vector and matrix code into package
This commit is contained in:
parent
d0dc6c1f5c
commit
26d11865b5
9 changed files with 424 additions and 294 deletions
165
canvas.go
165
canvas.go
|
@ -5,7 +5,6 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/tfriedel6/lm"
|
||||
)
|
||||
|
||||
//go:generate go run make_shaders.go
|
||||
|
@ -15,7 +14,7 @@ import (
|
|||
// using a set of functions very similar to the HTML5 canvas
|
||||
type Canvas struct {
|
||||
x, y, w, h int
|
||||
fx, fy, fw, fh float32
|
||||
fx, fy, fw, fh float64
|
||||
|
||||
polyPath []pathPoint
|
||||
linePath []pathPoint
|
||||
|
@ -25,26 +24,26 @@ type Canvas struct {
|
|||
}
|
||||
|
||||
type pathPoint struct {
|
||||
pos lm.Vec2
|
||||
tf lm.Vec2
|
||||
pos vec
|
||||
tf vec
|
||||
move bool
|
||||
next lm.Vec2
|
||||
next vec
|
||||
attach bool
|
||||
}
|
||||
|
||||
type drawState struct {
|
||||
transform lm.Mat3x3
|
||||
transform mat
|
||||
fill drawStyle
|
||||
stroke drawStyle
|
||||
font *Font
|
||||
fontSize float32
|
||||
lineWidth float32
|
||||
fontSize float64
|
||||
lineWidth float64
|
||||
lineJoin lineJoin
|
||||
lineEnd lineEnd
|
||||
|
||||
lineDash []float32
|
||||
lineDash []float64
|
||||
lineDashPoint int
|
||||
lineDashOffset float32
|
||||
lineDashOffset float64
|
||||
|
||||
clip []pathPoint
|
||||
/*
|
||||
|
@ -83,18 +82,18 @@ const (
|
|||
func New(x, y, w, h int) *Canvas {
|
||||
cv := &Canvas{
|
||||
x: x, y: y, w: w, h: h,
|
||||
fx: float32(x), fy: float32(y),
|
||||
fw: float32(w), fh: float32(h),
|
||||
fx: float64(x), fy: float64(y),
|
||||
fw: float64(w), fh: float64(h),
|
||||
stateStack: make([]drawState, 0, 20),
|
||||
}
|
||||
cv.state.lineWidth = 1
|
||||
cv.state.transform = lm.Mat3x3Identity()
|
||||
cv.state.transform = matIdentity()
|
||||
return cv
|
||||
}
|
||||
|
||||
func (cv *Canvas) SetSize(w, h int) {
|
||||
cv.w, cv.h = w, h
|
||||
cv.fw, cv.fh = float32(w), float32(h)
|
||||
cv.fw, cv.fh = float64(w), float64(h)
|
||||
activeCanvas = nil
|
||||
}
|
||||
|
||||
|
@ -102,8 +101,8 @@ func (cv *Canvas) W() int { return cv.w }
|
|||
func (cv *Canvas) H() int { return cv.h }
|
||||
func (cv *Canvas) Size() (int, int) { return cv.w, cv.h }
|
||||
|
||||
func (cv *Canvas) tf(v lm.Vec2) lm.Vec2 {
|
||||
v, _ = v.MulMat3x3(cv.state.transform)
|
||||
func (cv *Canvas) tf(v vec) vec {
|
||||
v, _ = v.mulMat(cv.state.transform)
|
||||
return v
|
||||
}
|
||||
|
||||
|
@ -310,15 +309,15 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
|
|||
gli.UseProgram(lgr.id)
|
||||
from := cv.tf(lg.from)
|
||||
to := cv.tf(lg.to)
|
||||
dir := to.Sub(from)
|
||||
length := dir.Len()
|
||||
dir = dir.DivF(length)
|
||||
gli.Uniform2f(lgr.canvasSize, cv.fw, cv.fh)
|
||||
inv := cv.state.transform.Invert()
|
||||
dir := to.sub(from)
|
||||
length := dir.len()
|
||||
dir = dir.divf(length)
|
||||
gli.Uniform2f(lgr.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
inv := cv.state.transform.invert().f32()
|
||||
gli.UniformMatrix3fv(lgr.invmat, 1, false, &inv[0])
|
||||
gli.Uniform2f(lgr.from, from[0], from[1])
|
||||
gli.Uniform2f(lgr.dir, dir[0], dir[1])
|
||||
gli.Uniform1f(lgr.len, length)
|
||||
gli.Uniform2f(lgr.from, float32(from[0]), float32(from[1]))
|
||||
gli.Uniform2f(lgr.dir, float32(dir[0]), float32(dir[1]))
|
||||
gli.Uniform1f(lgr.len, float32(length))
|
||||
gli.Uniform1i(lgr.gradient, 0)
|
||||
return lgr.vertex
|
||||
}
|
||||
|
@ -329,18 +328,18 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
|
|||
gli.UseProgram(rgr.id)
|
||||
from := cv.tf(rg.from)
|
||||
to := cv.tf(rg.to)
|
||||
dir := to.Sub(from)
|
||||
length := dir.Len()
|
||||
dir = dir.DivF(length)
|
||||
gli.Uniform2f(rgr.canvasSize, cv.fw, cv.fh)
|
||||
inv := cv.state.transform.Invert()
|
||||
dir := to.sub(from)
|
||||
length := dir.len()
|
||||
dir = dir.divf(length)
|
||||
gli.Uniform2f(rgr.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
inv := cv.state.transform.invert().f32()
|
||||
gli.UniformMatrix3fv(rgr.invmat, 1, false, &inv[0])
|
||||
gli.Uniform2f(rgr.from, from[0], from[1])
|
||||
gli.Uniform2f(rgr.to, to[0], to[1])
|
||||
gli.Uniform2f(rgr.dir, dir[0], dir[1])
|
||||
gli.Uniform1f(rgr.radFrom, rg.radFrom)
|
||||
gli.Uniform1f(rgr.radTo, rg.radTo)
|
||||
gli.Uniform1f(rgr.len, length)
|
||||
gli.Uniform2f(rgr.from, float32(from[0]), float32(from[1]))
|
||||
gli.Uniform2f(rgr.to, float32(to[0]), float32(to[1]))
|
||||
gli.Uniform2f(rgr.dir, float32(dir[0]), float32(dir[1]))
|
||||
gli.Uniform1f(rgr.radFrom, float32(rg.radFrom))
|
||||
gli.Uniform1f(rgr.radTo, float32(rg.radTo))
|
||||
gli.Uniform1f(rgr.len, float32(length))
|
||||
gli.Uniform1i(rgr.gradient, 0)
|
||||
return rgr.vertex
|
||||
}
|
||||
|
@ -348,8 +347,8 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
|
|||
gli.UseProgram(ipr.id)
|
||||
gli.ActiveTexture(gl_TEXTURE0)
|
||||
gli.BindTexture(gl_TEXTURE_2D, img.tex)
|
||||
gli.Uniform2f(ipr.canvasSize, cv.fw, cv.fh)
|
||||
inv := cv.state.transform.Invert()
|
||||
gli.Uniform2f(ipr.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
inv := cv.state.transform.invert().f32()
|
||||
gli.UniformMatrix3fv(ipr.invmat, 1, false, &inv[0])
|
||||
gli.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h))
|
||||
gli.Uniform1i(ipr.image, 0)
|
||||
|
@ -357,9 +356,9 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
|
|||
}
|
||||
|
||||
gli.UseProgram(sr.id)
|
||||
gli.Uniform2f(sr.canvasSize, cv.fw, cv.fh)
|
||||
gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
c := style.color
|
||||
gli.Uniform4f(sr.color, c.r, c.g, c.b, c.a)
|
||||
gli.Uniform4f(sr.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a))
|
||||
return sr.vertex
|
||||
}
|
||||
|
||||
|
@ -371,15 +370,15 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
|
|||
gli.UseProgram(lgar.id)
|
||||
from := cv.tf(lg.from)
|
||||
to := cv.tf(lg.to)
|
||||
dir := to.Sub(from)
|
||||
length := dir.Len()
|
||||
dir = dir.DivF(length)
|
||||
gli.Uniform2f(lgar.canvasSize, cv.fw, cv.fh)
|
||||
inv := cv.state.transform.Invert()
|
||||
dir := to.sub(from)
|
||||
length := dir.len()
|
||||
dir = dir.divf(length)
|
||||
gli.Uniform2f(lgar.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
inv := cv.state.transform.invert().f32()
|
||||
gli.UniformMatrix3fv(lgar.invmat, 1, false, &inv[0])
|
||||
gli.Uniform2f(lgar.from, from[0], from[1])
|
||||
gli.Uniform2f(lgar.dir, dir[0], dir[1])
|
||||
gli.Uniform1f(lgar.len, length)
|
||||
gli.Uniform2f(lgar.from, float32(from[0]), float32(from[1]))
|
||||
gli.Uniform2f(lgar.dir, float32(dir[0]), float32(dir[1]))
|
||||
gli.Uniform1f(lgar.len, float32(length))
|
||||
gli.Uniform1i(lgar.gradient, 0)
|
||||
gli.Uniform1i(lgar.alphaTex, alphaTexSlot)
|
||||
return lgar.vertex, lgar.alphaTexCoord
|
||||
|
@ -391,18 +390,18 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
|
|||
gli.UseProgram(rgar.id)
|
||||
from := cv.tf(rg.from)
|
||||
to := cv.tf(rg.to)
|
||||
dir := to.Sub(from)
|
||||
length := dir.Len()
|
||||
dir = dir.DivF(length)
|
||||
gli.Uniform2f(rgar.canvasSize, cv.fw, cv.fh)
|
||||
inv := cv.state.transform.Invert()
|
||||
dir := to.sub(from)
|
||||
length := dir.len()
|
||||
dir = dir.divf(length)
|
||||
gli.Uniform2f(rgar.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
inv := cv.state.transform.invert().f32()
|
||||
gli.UniformMatrix3fv(rgar.invmat, 1, false, &inv[0])
|
||||
gli.Uniform2f(rgar.from, from[0], from[1])
|
||||
gli.Uniform2f(rgar.to, to[0], to[1])
|
||||
gli.Uniform2f(rgar.dir, dir[0], dir[1])
|
||||
gli.Uniform1f(rgar.radFrom, rg.radFrom)
|
||||
gli.Uniform1f(rgar.radTo, rg.radTo)
|
||||
gli.Uniform1f(rgar.len, length)
|
||||
gli.Uniform2f(rgar.from, float32(from[0]), float32(from[1]))
|
||||
gli.Uniform2f(rgar.to, float32(to[0]), float32(to[1]))
|
||||
gli.Uniform2f(rgar.dir, float32(dir[0]), float32(dir[1]))
|
||||
gli.Uniform1f(rgar.radFrom, float32(rg.radFrom))
|
||||
gli.Uniform1f(rgar.radTo, float32(rg.radTo))
|
||||
gli.Uniform1f(rgar.len, float32(length))
|
||||
gli.Uniform1i(rgar.gradient, 0)
|
||||
gli.Uniform1i(rgar.alphaTex, alphaTexSlot)
|
||||
return rgar.vertex, rgar.alphaTexCoord
|
||||
|
@ -411,8 +410,8 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
|
|||
gli.UseProgram(ipar.id)
|
||||
gli.ActiveTexture(gl_TEXTURE0)
|
||||
gli.BindTexture(gl_TEXTURE_2D, img.tex)
|
||||
gli.Uniform2f(ipar.canvasSize, cv.fw, cv.fh)
|
||||
inv := cv.state.transform.Invert()
|
||||
gli.Uniform2f(ipar.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
inv := cv.state.transform.invert().f32()
|
||||
gli.UniformMatrix3fv(ipar.invmat, 1, false, &inv[0])
|
||||
gli.Uniform2f(ipar.imageSize, float32(img.w), float32(img.h))
|
||||
gli.Uniform1i(ipar.image, 0)
|
||||
|
@ -421,20 +420,20 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
|
|||
}
|
||||
|
||||
gli.UseProgram(sar.id)
|
||||
gli.Uniform2f(sar.canvasSize, cv.fw, cv.fh)
|
||||
gli.Uniform2f(sar.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
c := style.color
|
||||
gli.Uniform4f(sar.color, c.r, c.g, c.b, c.a)
|
||||
gli.Uniform4f(sar.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a))
|
||||
gli.Uniform1i(sar.alphaTex, alphaTexSlot)
|
||||
return sar.vertex, sar.alphaTexCoord
|
||||
}
|
||||
|
||||
// SetLineWidth sets the line width for any line drawing calls
|
||||
func (cv *Canvas) SetLineWidth(width float32) {
|
||||
func (cv *Canvas) SetLineWidth(width float64) {
|
||||
cv.state.lineWidth = width
|
||||
}
|
||||
|
||||
// SetFont sets the font and font size
|
||||
func (cv *Canvas) SetFont(font interface{}, size float32) {
|
||||
func (cv *Canvas) SetFont(font interface{}, size float64) {
|
||||
switch v := font.(type) {
|
||||
case *Font:
|
||||
cv.state.font = v
|
||||
|
@ -464,14 +463,14 @@ func (cv *Canvas) SetLineEnd(end lineEnd) {
|
|||
}
|
||||
|
||||
// SetLineDash sets the line dash style
|
||||
func (cv *Canvas) SetLineDash(dash []float32) {
|
||||
func (cv *Canvas) SetLineDash(dash []float64) {
|
||||
l := len(dash)
|
||||
if l%2 == 0 {
|
||||
d2 := make([]float32, l)
|
||||
d2 := make([]float64, l)
|
||||
copy(d2, dash)
|
||||
cv.state.lineDash = d2
|
||||
} else {
|
||||
d2 := make([]float32, l*2)
|
||||
d2 := make([]float64, l*2)
|
||||
copy(d2[:l], dash)
|
||||
copy(d2[l:], dash)
|
||||
cv.state.lineDash = d2
|
||||
|
@ -503,37 +502,37 @@ func (cv *Canvas) Restore() {
|
|||
}
|
||||
}
|
||||
|
||||
func (cv *Canvas) Scale(x, y float32) {
|
||||
cv.state.transform = lm.Mat3x3Scale(lm.Vec2{x, y}).Mul(cv.state.transform)
|
||||
func (cv *Canvas) Scale(x, y float64) {
|
||||
cv.state.transform = matScale(vec{x, y}).mul(cv.state.transform)
|
||||
}
|
||||
|
||||
func (cv *Canvas) Translate(x, y float32) {
|
||||
cv.state.transform = lm.Mat3x3Translate(lm.Vec2{x, y}).Mul(cv.state.transform)
|
||||
func (cv *Canvas) Translate(x, y float64) {
|
||||
cv.state.transform = matTranslate(vec{x, y}).mul(cv.state.transform)
|
||||
}
|
||||
|
||||
func (cv *Canvas) Rotate(angle float32) {
|
||||
cv.state.transform = lm.Mat3x3Rotate(angle).Mul(cv.state.transform)
|
||||
func (cv *Canvas) Rotate(angle float64) {
|
||||
cv.state.transform = matRotate(angle).mul(cv.state.transform)
|
||||
}
|
||||
|
||||
func (cv *Canvas) Transform(a, b, c, d, e, f float32) {
|
||||
cv.state.transform = lm.Mat3x3{a, b, 0, c, d, 0, e, f, 1}.Mul(cv.state.transform)
|
||||
func (cv *Canvas) Transform(a, b, c, d, e, f float64) {
|
||||
cv.state.transform = mat{a, b, 0, c, d, 0, e, f, 1}.mul(cv.state.transform)
|
||||
}
|
||||
|
||||
func (cv *Canvas) SetTransform(a, b, c, d, e, f float32) {
|
||||
cv.state.transform = lm.Mat3x3{a, b, 0, c, d, 0, e, f, 1}
|
||||
func (cv *Canvas) SetTransform(a, b, c, d, e, f float64) {
|
||||
cv.state.transform = mat{a, b, 0, c, d, 0, e, f, 1}
|
||||
}
|
||||
|
||||
// FillRect fills a rectangle with the active fill style
|
||||
func (cv *Canvas) FillRect(x, y, w, h float32) {
|
||||
func (cv *Canvas) FillRect(x, y, w, h float64) {
|
||||
cv.activate()
|
||||
|
||||
p0 := cv.tf(lm.Vec2{x, y})
|
||||
p1 := cv.tf(lm.Vec2{x, y + h})
|
||||
p2 := cv.tf(lm.Vec2{x + w, y + h})
|
||||
p3 := cv.tf(lm.Vec2{x + w, y})
|
||||
p0 := cv.tf(vec{x, y})
|
||||
p1 := cv.tf(vec{x, y + h})
|
||||
p2 := cv.tf(vec{x + w, y + h})
|
||||
p3 := cv.tf(vec{x + w, y})
|
||||
|
||||
gli.BindBuffer(gl_ARRAY_BUFFER, buf)
|
||||
data := [8]float32{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]}
|
||||
data := [8]float64{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]}
|
||||
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
|
||||
|
||||
vertex := cv.useShader(&cv.state.fill)
|
||||
|
|
58
color.go
58
color.go
|
@ -8,16 +8,16 @@ import (
|
|||
)
|
||||
|
||||
type glColor struct {
|
||||
r, g, b, a float32
|
||||
r, g, b, a float64
|
||||
}
|
||||
|
||||
func colorGoToGL(color color.Color) glColor {
|
||||
ir, ig, ib, ia := color.RGBA()
|
||||
var c glColor
|
||||
c.r = float32(ir) / 65535
|
||||
c.g = float32(ig) / 65535
|
||||
c.b = float32(ib) / 65535
|
||||
c.a = float32(ia) / 65535
|
||||
c.r = float64(ir) / 65535
|
||||
c.g = float64(ig) / 65535
|
||||
c.b = float64(ib) / 65535
|
||||
c.a = float64(ia) / 65535
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -74,18 +74,18 @@ func parseHexRunePair(rn1, rn2 rune) (int, bool) {
|
|||
return i1*16 + i2, true
|
||||
}
|
||||
|
||||
func parseColorComponent(value interface{}) (float32, bool) {
|
||||
func parseColorComponent(value interface{}) (float64, bool) {
|
||||
switch v := value.(type) {
|
||||
case float32:
|
||||
return v, true
|
||||
return float64(v), true
|
||||
case float64:
|
||||
return float32(v), true
|
||||
return v, true
|
||||
case int:
|
||||
return float32(v) / 255, true
|
||||
return float64(v) / 255, true
|
||||
case uint:
|
||||
return float32(v) / 255, true
|
||||
return float64(v) / 255, true
|
||||
case uint8:
|
||||
return float32(v) / 255, true
|
||||
return float64(v) / 255, true
|
||||
case string:
|
||||
if len(v) == 0 {
|
||||
return 0, false
|
||||
|
@ -99,7 +99,7 @@ func parseColorComponent(value interface{}) (float32, bool) {
|
|||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return float32(conv) / 255, true
|
||||
return float64(conv) / 255, true
|
||||
} else if strings.ContainsRune(v, '.') {
|
||||
conv, err := strconv.ParseFloat(v, 32)
|
||||
if err != nil {
|
||||
|
@ -110,13 +110,13 @@ func parseColorComponent(value interface{}) (float32, bool) {
|
|||
} else if conv > 1 {
|
||||
conv = 1
|
||||
}
|
||||
return float32(conv), true
|
||||
return float64(conv), true
|
||||
} else {
|
||||
conv, err := strconv.ParseUint(v, 10, 8)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return float32(conv) / 255, true
|
||||
return float64(conv) / 255, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
|
@ -130,25 +130,25 @@ func parseColor(value ...interface{}) (c glColor, ok bool) {
|
|||
ok = true
|
||||
return
|
||||
case [3]float32:
|
||||
return glColor{r: v[0], g: v[1], b: v[2], a: 1}, true
|
||||
return glColor{r: float64(v[0]), g: float64(v[1]), b: float64(v[2]), a: 1}, true
|
||||
case [4]float32:
|
||||
return glColor{r: v[0], g: v[1], b: v[2], a: v[3]}, true
|
||||
return glColor{r: float64(v[0]), g: float64(v[1]), b: float64(v[2]), a: float64(v[3])}, true
|
||||
case [3]float64:
|
||||
return glColor{r: float32(v[0]), g: float32(v[1]), b: float32(v[2]), a: 1}, true
|
||||
return glColor{r: v[0], g: v[1], b: v[2], a: 1}, true
|
||||
case [4]float64:
|
||||
return glColor{r: float32(v[0]), g: float32(v[1]), b: float32(v[2]), a: float32(v[3])}, true
|
||||
return glColor{r: v[0], g: v[1], b: v[2], a: v[3]}, true
|
||||
case [3]int:
|
||||
return glColor{r: float32(v[0]) / 255, g: float32(v[1]) / 255, b: float32(v[2]) / 255, a: 1}, true
|
||||
return glColor{r: float64(v[0]) / 255, g: float64(v[1]) / 255, b: float64(v[2]) / 255, a: 1}, true
|
||||
case [4]int:
|
||||
return glColor{r: float32(v[0]) / 255, g: float32(v[1]) / 255, b: float32(v[2]) / 255, a: float32(v[3]) / 255}, true
|
||||
return glColor{r: float64(v[0]) / 255, g: float64(v[1]) / 255, b: float64(v[2]) / 255, a: float64(v[3]) / 255}, true
|
||||
case [3]uint:
|
||||
return glColor{r: float32(v[0]) / 255, g: float32(v[1]) / 255, b: float32(v[2]) / 255, a: 1}, true
|
||||
return glColor{r: float64(v[0]) / 255, g: float64(v[1]) / 255, b: float64(v[2]) / 255, a: 1}, true
|
||||
case [4]uint:
|
||||
return glColor{r: float32(v[0]) / 255, g: float32(v[1]) / 255, b: float32(v[2]) / 255, a: float32(v[3]) / 255}, true
|
||||
return glColor{r: float64(v[0]) / 255, g: float64(v[1]) / 255, b: float64(v[2]) / 255, a: float64(v[3]) / 255}, true
|
||||
case [3]uint8:
|
||||
return glColor{r: float32(v[0]) / 255, g: float32(v[1]) / 255, b: float32(v[2]) / 255, a: 1}, true
|
||||
return glColor{r: float64(v[0]) / 255, g: float64(v[1]) / 255, b: float64(v[2]) / 255, a: 1}, true
|
||||
case [4]uint8:
|
||||
return glColor{r: float32(v[0]) / 255, g: float32(v[1]) / 255, b: float32(v[2]) / 255, a: float32(v[3]) / 255}, true
|
||||
return glColor{r: float64(v[0]) / 255, g: float64(v[1]) / 255, b: float64(v[2]) / 255, a: float64(v[3]) / 255}, true
|
||||
case string:
|
||||
if len(v) == 0 {
|
||||
return
|
||||
|
@ -180,7 +180,7 @@ func parseColor(value ...interface{}) (c glColor, ok bool) {
|
|||
}
|
||||
ia = ia*16 + ia
|
||||
}
|
||||
return glColor{r: float32(ir) / 255, g: float32(ig) / 255, b: float32(ib) / 255, a: float32(ia) / 255}, true
|
||||
return glColor{r: float64(ir) / 255, g: float64(ig) / 255, b: float64(ib) / 255, a: float64(ia) / 255}, true
|
||||
} else if len(str) == 6 || len(str) == 8 {
|
||||
var ir, ig, ib int
|
||||
ia := 255
|
||||
|
@ -202,7 +202,7 @@ func parseColor(value ...interface{}) (c glColor, ok bool) {
|
|||
return
|
||||
}
|
||||
}
|
||||
return glColor{r: float32(ir) / 255, g: float32(ig) / 255, b: float32(ib) / 255, a: float32(ia) / 255}, true
|
||||
return glColor{r: float64(ir) / 255, g: float64(ig) / 255, b: float64(ib) / 255, a: float64(ia) / 255}, true
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
@ -211,16 +211,16 @@ func parseColor(value ...interface{}) (c glColor, ok bool) {
|
|||
var ir, ig, ib, ia int
|
||||
n, err := fmt.Sscanf(v, "rgb(%d,%d,%d)", &ir, &ig, &ib)
|
||||
if err == nil && n == 3 {
|
||||
return glColor{r: float32(ir) / 255, g: float32(ig) / 255, b: float32(ib) / 255, a: 1}, true
|
||||
return glColor{r: float64(ir) / 255, g: float64(ig) / 255, b: float64(ib) / 255, a: 1}, true
|
||||
}
|
||||
n, err = fmt.Sscanf(v, "rgba(%d,%d,%d,%d)", &ir, &ig, &ib, &ia)
|
||||
if err == nil && n == 4 {
|
||||
return glColor{r: float32(ir) / 255, g: float32(ig) / 255, b: float32(ib) / 255, a: float32(ia) / 255}, true
|
||||
return glColor{r: float64(ir) / 255, g: float64(ig) / 255, b: float64(ib) / 255, a: float64(ia) / 255}, true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if len(value) == 3 || len(value) == 4 {
|
||||
var pr, pg, pb, pa float32
|
||||
var pr, pg, pb, pa float64
|
||||
pr, ok = parseColorComponent(value[0])
|
||||
if !ok {
|
||||
return
|
||||
|
|
32
gradients.go
32
gradients.go
|
@ -1,10 +1,8 @@
|
|||
package canvas
|
||||
|
||||
import (
|
||||
"math"
|
||||
"runtime"
|
||||
|
||||
"github.com/barnex/fmath"
|
||||
"github.com/tfriedel6/lm"
|
||||
)
|
||||
|
||||
type LinearGradient struct {
|
||||
|
@ -13,11 +11,11 @@ type LinearGradient struct {
|
|||
|
||||
type RadialGradient struct {
|
||||
gradient
|
||||
radFrom, radTo float32
|
||||
radFrom, radTo float64
|
||||
}
|
||||
|
||||
type gradient struct {
|
||||
from, to lm.Vec2
|
||||
from, to vec
|
||||
stops []gradientStop
|
||||
tex uint32
|
||||
loaded bool
|
||||
|
@ -25,12 +23,12 @@ type gradient struct {
|
|||
}
|
||||
|
||||
type gradientStop struct {
|
||||
pos float32
|
||||
pos float64
|
||||
color glColor
|
||||
}
|
||||
|
||||
func NewLinearGradient(x0, y0, x1, y1 float32) *LinearGradient {
|
||||
lg := &LinearGradient{gradient: gradient{from: lm.Vec2{x0, y0}, to: lm.Vec2{x1, y1}}}
|
||||
func NewLinearGradient(x0, y0, x1, y1 float64) *LinearGradient {
|
||||
lg := &LinearGradient{gradient: gradient{from: vec{x0, y0}, to: vec{x1, y1}}}
|
||||
gli.GenTextures(1, &lg.tex)
|
||||
gli.ActiveTexture(gl_TEXTURE0)
|
||||
gli.BindTexture(gl_TEXTURE_1D, lg.tex)
|
||||
|
@ -45,8 +43,8 @@ func NewLinearGradient(x0, y0, x1, y1 float32) *LinearGradient {
|
|||
return lg
|
||||
}
|
||||
|
||||
func NewRadialGradient(x0, y0, r0, x1, y1, r1 float32) *RadialGradient {
|
||||
rg := &RadialGradient{gradient: gradient{from: lm.Vec2{x0, y0}, to: lm.Vec2{x1, y1}}, radFrom: r0, radTo: r1}
|
||||
func NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGradient {
|
||||
rg := &RadialGradient{gradient: gradient{from: vec{x0, y0}, to: vec{x1, y1}}, radFrom: r0, radTo: r1}
|
||||
gli.GenTextures(1, &rg.tex)
|
||||
gli.ActiveTexture(gl_TEXTURE0)
|
||||
gli.BindTexture(gl_TEXTURE_1D, rg.tex)
|
||||
|
@ -75,18 +73,18 @@ func (g *gradient) load() {
|
|||
var pixels [2048 * 4]byte
|
||||
pp := 0
|
||||
for i := 0; i < 2048; i++ {
|
||||
c := g.colorAt(float32(i) / 2047)
|
||||
pixels[pp] = byte(fmath.Floor(c.r*255 + 0.5))
|
||||
pixels[pp+1] = byte(fmath.Floor(c.g*255 + 0.5))
|
||||
pixels[pp+2] = byte(fmath.Floor(c.b*255 + 0.5))
|
||||
pixels[pp+3] = byte(fmath.Floor(c.a*255 + 0.5))
|
||||
c := g.colorAt(float64(i) / 2047)
|
||||
pixels[pp] = byte(math.Floor(c.r*255 + 0.5))
|
||||
pixels[pp+1] = byte(math.Floor(c.g*255 + 0.5))
|
||||
pixels[pp+2] = byte(math.Floor(c.b*255 + 0.5))
|
||||
pixels[pp+3] = byte(math.Floor(c.a*255 + 0.5))
|
||||
pp += 4
|
||||
}
|
||||
gli.TexImage1D(gl_TEXTURE_1D, 0, gl_RGBA, 2048, 0, gl_RGBA, gl_UNSIGNED_BYTE, gli.Ptr(&pixels[0]))
|
||||
g.loaded = true
|
||||
}
|
||||
|
||||
func (g *gradient) colorAt(pos float32) glColor {
|
||||
func (g *gradient) colorAt(pos float64) glColor {
|
||||
if len(g.stops) == 0 {
|
||||
return glColor{}
|
||||
} else if len(g.stops) == 1 {
|
||||
|
@ -115,7 +113,7 @@ func (g *gradient) colorAt(pos float32) glColor {
|
|||
return c
|
||||
}
|
||||
|
||||
func (g *gradient) AddColorStop(pos float32, color ...interface{}) {
|
||||
func (g *gradient) AddColorStop(pos float64, color ...interface{}) {
|
||||
c, _ := parseColor(color...)
|
||||
insert := len(g.stops)
|
||||
for i, stop := range g.stops {
|
||||
|
|
|
@ -81,7 +81,7 @@ func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) {
|
|||
|
||||
gli.UseProgram(ir.id)
|
||||
gli.Uniform1i(ir.image, 0)
|
||||
gli.Uniform2f(ir.canvasSize, cv.fw, cv.fh)
|
||||
gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, nil)
|
||||
gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4))
|
||||
gli.EnableVertexAttribArray(ir.vertex)
|
||||
|
|
30
images.go
30
images.go
|
@ -7,8 +7,6 @@ import (
|
|||
"io/ioutil"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tfriedel6/lm"
|
||||
)
|
||||
|
||||
type Image struct {
|
||||
|
@ -174,7 +172,7 @@ func (img *Image) Delete() {
|
|||
img.deleted = true
|
||||
}
|
||||
|
||||
func (cv *Canvas) DrawImage(image interface{}, coords ...float32) {
|
||||
func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
|
||||
var img *Image
|
||||
switch v := image.(type) {
|
||||
case *Image:
|
||||
|
@ -200,9 +198,9 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float32) {
|
|||
|
||||
cv.activate()
|
||||
|
||||
var sx, sy, sw, sh, dx, dy, dw, dh float32
|
||||
sw, sh = float32(img.w), float32(img.h)
|
||||
dw, dh = float32(img.w), float32(img.h)
|
||||
var sx, sy, sw, sh, dx, dy, dw, dh float64
|
||||
sw, sh = float64(img.w), float64(img.h)
|
||||
dw, dh = float64(img.w), float64(img.h)
|
||||
if len(coords) == 2 {
|
||||
dx, dy = coords[0], coords[1]
|
||||
} else if len(coords) == 4 {
|
||||
|
@ -215,18 +213,18 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float32) {
|
|||
dw, dh = coords[6], coords[7]
|
||||
}
|
||||
|
||||
sx /= float32(img.w)
|
||||
sy /= float32(img.h)
|
||||
sw /= float32(img.w)
|
||||
sh /= float32(img.h)
|
||||
sx /= float64(img.w)
|
||||
sy /= float64(img.h)
|
||||
sw /= float64(img.w)
|
||||
sh /= float64(img.h)
|
||||
|
||||
p0 := cv.tf(lm.Vec2{dx, dy})
|
||||
p1 := cv.tf(lm.Vec2{dx, dy + dh})
|
||||
p2 := cv.tf(lm.Vec2{dx + dw, dy + dh})
|
||||
p3 := cv.tf(lm.Vec2{dx + dw, dy})
|
||||
p0 := cv.tf(vec{dx, dy})
|
||||
p1 := cv.tf(vec{dx, dy + dh})
|
||||
p2 := cv.tf(vec{dx + dw, dy + dh})
|
||||
p3 := cv.tf(vec{dx + dw, dy})
|
||||
|
||||
gli.BindBuffer(gl_ARRAY_BUFFER, buf)
|
||||
data := [16]float32{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1],
|
||||
data := [16]float64{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1],
|
||||
sx, sy, sx, sy + sh, sx + sw, sy + sh, sx + sw, sy}
|
||||
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
|
||||
|
||||
|
@ -235,7 +233,7 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float32) {
|
|||
|
||||
gli.UseProgram(ir.id)
|
||||
gli.Uniform1i(ir.image, 0)
|
||||
gli.Uniform2f(ir.canvasSize, cv.fw, cv.fh)
|
||||
gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, nil)
|
||||
gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4))
|
||||
gli.EnableVertexAttribArray(ir.vertex)
|
||||
|
|
141
math.go
Normal file
141
math.go
Normal file
|
@ -0,0 +1,141 @@
|
|||
package canvas
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type vec [2]float64
|
||||
|
||||
func (v vec) String() string {
|
||||
return fmt.Sprintf("[%f,%f]", v[0], v[1])
|
||||
}
|
||||
|
||||
func (v1 vec) add(v2 vec) vec {
|
||||
return vec{v1[0] + v2[0], v1[1] + v2[1]}
|
||||
}
|
||||
|
||||
func (v1 vec) sub(v2 vec) vec {
|
||||
return vec{v1[0] - v2[0], v1[1] - v2[1]}
|
||||
}
|
||||
|
||||
func (v1 vec) mul(v2 vec) vec {
|
||||
return vec{v1[0] * v2[0], v1[1] * v2[1]}
|
||||
}
|
||||
|
||||
func (v vec) mulf(f float64) vec {
|
||||
return vec{v[0] * f, v[1] * f}
|
||||
}
|
||||
|
||||
func (v vec) mulMat(m mat) (vec, float64) {
|
||||
return vec{
|
||||
m[0]*v[0] + m[3]*v[1] + m[6],
|
||||
m[1]*v[0] + m[4]*v[1] + m[7]},
|
||||
m[2]*v[0] + m[5]*v[1] + m[8]
|
||||
}
|
||||
|
||||
func (v1 vec) div(v2 vec) vec {
|
||||
return vec{v1[0] / v2[0], v1[1] / v2[1]}
|
||||
}
|
||||
|
||||
func (v vec) divf(f float64) vec {
|
||||
return vec{v[0] / f, v[1] / f}
|
||||
}
|
||||
|
||||
func (v1 vec) dot(v2 vec) float64 {
|
||||
return v1[0]*v2[0] + v1[1]*v2[1]
|
||||
}
|
||||
|
||||
func (v vec) len() float64 {
|
||||
return math.Sqrt(v[0]*v[0] + v[1]*v[1])
|
||||
}
|
||||
|
||||
func (v vec) lenSqr() float64 {
|
||||
return v[0]*v[0] + v[1]*v[1]
|
||||
}
|
||||
|
||||
func (v vec) norm() vec {
|
||||
return v.mulf(1.0 / v.len())
|
||||
}
|
||||
|
||||
func (v vec) atan2() float64 {
|
||||
return math.Atan2(v[1], v[0])
|
||||
}
|
||||
|
||||
func (v vec) angle() float64 {
|
||||
return math.Pi*0.5 - math.Atan2(v[1], v[0])
|
||||
}
|
||||
|
||||
func (v vec) angleTo(v2 vec) float64 {
|
||||
return math.Acos(v.norm().dot(v2.norm()))
|
||||
}
|
||||
|
||||
type mat [9]float64
|
||||
|
||||
func (m *mat) String() string {
|
||||
return fmt.Sprintf("[%f,%f,%f,\n %f,%f,%f,\n %f,%f,%f,]", m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8])
|
||||
}
|
||||
|
||||
func matIdentity() mat {
|
||||
return mat{
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1}
|
||||
}
|
||||
|
||||
func matTranslate(v vec) mat {
|
||||
return mat{
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
v[0], v[1], 1}
|
||||
}
|
||||
|
||||
func matScale(v vec) mat {
|
||||
return mat{
|
||||
v[0], 0, 0,
|
||||
0, v[1], 0,
|
||||
0, 0, 1}
|
||||
}
|
||||
|
||||
func matRotate(radians float64) mat {
|
||||
s, c := math.Sincos(radians)
|
||||
return mat{
|
||||
c, s, 0,
|
||||
-s, c, 0,
|
||||
0, 0, 1}
|
||||
}
|
||||
|
||||
func (m1 mat) mul(m2 mat) mat {
|
||||
return mat{
|
||||
m1[0]*m2[0] + m1[1]*m2[3] + m1[2]*m2[6],
|
||||
m1[0]*m2[1] + m1[1]*m2[4] + m1[2]*m2[7],
|
||||
m1[0]*m2[2] + m1[1]*m2[5] + m1[2]*m2[8],
|
||||
m1[3]*m2[0] + m1[4]*m2[3] + m1[5]*m2[6],
|
||||
m1[3]*m2[1] + m1[4]*m2[4] + m1[5]*m2[7],
|
||||
m1[3]*m2[2] + m1[4]*m2[5] + m1[5]*m2[8],
|
||||
m1[6]*m2[0] + m1[7]*m2[3] + m1[8]*m2[6],
|
||||
m1[6]*m2[1] + m1[7]*m2[4] + m1[8]*m2[7],
|
||||
m1[6]*m2[2] + m1[7]*m2[5] + m1[8]*m2[8]}
|
||||
}
|
||||
|
||||
func (m mat) invert() mat {
|
||||
var identity float64 = 1.0 / (m[0]*m[4]*m[8] + m[3]*m[7]*m[2] + m[6]*m[1]*m[5] - m[6]*m[4]*m[2] - m[3]*m[1]*m[8] - m[0]*m[7]*m[5])
|
||||
|
||||
return mat{
|
||||
(m[4]*m[8] - m[5]*m[7]) * identity,
|
||||
(m[2]*m[7] - m[1]*m[8]) * identity,
|
||||
(m[1]*m[5] - m[2]*m[4]) * identity,
|
||||
(m[5]*m[6] - m[3]*m[8]) * identity,
|
||||
(m[0]*m[8] - m[2]*m[6]) * identity,
|
||||
(m[2]*m[3] - m[0]*m[5]) * identity,
|
||||
(m[3]*m[7] - m[4]*m[6]) * identity,
|
||||
(m[1]*m[6] - m[0]*m[7]) * identity,
|
||||
(m[0]*m[4] - m[1]*m[3]) * identity}
|
||||
}
|
||||
|
||||
func (m mat) f32() [9]float32 {
|
||||
return [9]float32{
|
||||
float32(m[0]), float32(m[1]), float32(m[2]),
|
||||
float32(m[3]), float32(m[4]), float32(m[5]),
|
||||
float32(m[6]), float32(m[7]), float32(m[8])}
|
||||
}
|
247
paths.go
247
paths.go
|
@ -3,9 +3,6 @@ package canvas
|
|||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/barnex/fmath"
|
||||
"github.com/tfriedel6/lm"
|
||||
)
|
||||
|
||||
func (cv *Canvas) BeginPath() {
|
||||
|
@ -19,37 +16,37 @@ func (cv *Canvas) BeginPath() {
|
|||
cv.polyPath = cv.polyPath[:0]
|
||||
}
|
||||
|
||||
func isSamePoint(a, b lm.Vec2, maxDist float32) bool {
|
||||
return fmath.Abs(b[0]-a[0]) <= maxDist && fmath.Abs(b[1]-a[1]) <= maxDist
|
||||
func isSamePoint(a, b vec, maxDist float64) bool {
|
||||
return math.Abs(b[0]-a[0]) <= maxDist && math.Abs(b[1]-a[1]) <= maxDist
|
||||
}
|
||||
|
||||
func (cv *Canvas) MoveTo(x, y float32) {
|
||||
tf := cv.tf(lm.Vec2{x, y})
|
||||
func (cv *Canvas) MoveTo(x, y float64) {
|
||||
tf := cv.tf(vec{x, y})
|
||||
if len(cv.linePath) > 0 && isSamePoint(cv.linePath[len(cv.linePath)-1].tf, tf, 0.1) {
|
||||
return
|
||||
}
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: lm.Vec2{x, y}, tf: tf, move: true})
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: lm.Vec2{x, y}, tf: tf, move: true})
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf, move: true})
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf, move: true})
|
||||
}
|
||||
|
||||
func (cv *Canvas) LineTo(x, y float32) {
|
||||
func (cv *Canvas) LineTo(x, y float64) {
|
||||
cv.strokeLineTo(x, y)
|
||||
cv.fillLineTo(x, y)
|
||||
}
|
||||
|
||||
func (cv *Canvas) strokeLineTo(x, y float32) {
|
||||
if len(cv.linePath) > 0 && isSamePoint(cv.linePath[len(cv.linePath)-1].tf, cv.tf(lm.Vec2{x, y}), 0.1) {
|
||||
func (cv *Canvas) strokeLineTo(x, y float64) {
|
||||
if len(cv.linePath) > 0 && isSamePoint(cv.linePath[len(cv.linePath)-1].tf, cv.tf(vec{x, y}), 0.1) {
|
||||
return
|
||||
}
|
||||
if len(cv.linePath) == 0 {
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: lm.Vec2{x, y}, tf: cv.tf(lm.Vec2{x, y}), move: true})
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: cv.tf(vec{x, y}), move: true})
|
||||
return
|
||||
}
|
||||
if len(cv.state.lineDash) > 0 {
|
||||
lp := cv.linePath[len(cv.linePath)-1].pos
|
||||
tp := lm.Vec2{x, y}
|
||||
v := tp.Sub(lp)
|
||||
vl := v.Len()
|
||||
tp := vec{x, y}
|
||||
v := tp.sub(lp)
|
||||
vl := v.len()
|
||||
prev := cv.state.lineDashOffset
|
||||
for vl > 0 {
|
||||
draw := cv.state.lineDashPoint%2 == 0
|
||||
|
@ -58,7 +55,7 @@ func (cv *Canvas) strokeLineTo(x, y float32) {
|
|||
if cv.state.lineDashOffset > cv.state.lineDash[cv.state.lineDashPoint] {
|
||||
cv.state.lineDashOffset = 0
|
||||
dl := cv.state.lineDash[cv.state.lineDashPoint] - prev
|
||||
p = lp.Add(v.MulF(dl / vl))
|
||||
p = lp.add(v.mulf(dl / vl))
|
||||
vl -= dl
|
||||
cv.state.lineDashPoint++
|
||||
cv.state.lineDashPoint %= len(cv.state.lineDash)
|
||||
|
@ -76,36 +73,36 @@ func (cv *Canvas) strokeLineTo(x, y float32) {
|
|||
}
|
||||
|
||||
lp = p
|
||||
v = tp.Sub(lp)
|
||||
v = tp.sub(lp)
|
||||
}
|
||||
} else {
|
||||
tf := cv.tf(lm.Vec2{x, y})
|
||||
tf := cv.tf(vec{x, y})
|
||||
cv.linePath[len(cv.linePath)-1].next = tf
|
||||
cv.linePath[len(cv.linePath)-1].attach = true
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: lm.Vec2{x, y}, tf: tf, move: false})
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf, move: false})
|
||||
}
|
||||
}
|
||||
|
||||
func (cv *Canvas) fillLineTo(x, y float32) {
|
||||
if len(cv.polyPath) > 0 && isSamePoint(cv.polyPath[len(cv.polyPath)-1].tf, cv.tf(lm.Vec2{x, y}), 0.1) {
|
||||
func (cv *Canvas) fillLineTo(x, y float64) {
|
||||
if len(cv.polyPath) > 0 && isSamePoint(cv.polyPath[len(cv.polyPath)-1].tf, cv.tf(vec{x, y}), 0.1) {
|
||||
return
|
||||
}
|
||||
if len(cv.polyPath) == 0 {
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: lm.Vec2{x, y}, tf: cv.tf(lm.Vec2{x, y}), move: true})
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: cv.tf(vec{x, y}), move: true})
|
||||
return
|
||||
}
|
||||
tf := cv.tf(lm.Vec2{x, y})
|
||||
tf := cv.tf(vec{x, y})
|
||||
cv.polyPath[len(cv.polyPath)-1].next = tf
|
||||
cv.polyPath[len(cv.polyPath)-1].attach = true
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: lm.Vec2{x, y}, tf: tf, move: false})
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf, move: false})
|
||||
}
|
||||
|
||||
func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float32, anticlockwise bool) {
|
||||
startAngle = fmath.Mod(startAngle, math.Pi*2)
|
||||
func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise bool) {
|
||||
startAngle = math.Mod(startAngle, math.Pi*2)
|
||||
if startAngle < 0 {
|
||||
startAngle += math.Pi * 2
|
||||
}
|
||||
endAngle = fmath.Mod(endAngle, math.Pi*2)
|
||||
endAngle = math.Mod(endAngle, math.Pi*2)
|
||||
if endAngle < 0 {
|
||||
endAngle += math.Pi * 2
|
||||
}
|
||||
|
@ -114,8 +111,8 @@ func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float32, anticlockwise
|
|||
} else if anticlockwise && endAngle >= startAngle {
|
||||
endAngle -= math.Pi * 2
|
||||
}
|
||||
tr := cv.tf(lm.Vec2{radius, radius})
|
||||
step := 6 / fmath.Max(tr[0], tr[1])
|
||||
tr := cv.tf(vec{radius, radius})
|
||||
step := 6 / math.Max(tr[0], tr[1])
|
||||
if step > 0.8 {
|
||||
step = 0.8
|
||||
} else if step < 0.05 {
|
||||
|
@ -123,106 +120,106 @@ func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float32, anticlockwise
|
|||
}
|
||||
if anticlockwise {
|
||||
for a := startAngle; a > endAngle; a -= step {
|
||||
s, c := fmath.Sincos(a)
|
||||
s, c := math.Sincos(a)
|
||||
cv.LineTo(x+radius*c, y+radius*s)
|
||||
}
|
||||
} else {
|
||||
for a := startAngle; a < endAngle; a += step {
|
||||
s, c := fmath.Sincos(a)
|
||||
s, c := math.Sincos(a)
|
||||
cv.LineTo(x+radius*c, y+radius*s)
|
||||
}
|
||||
}
|
||||
s, c := fmath.Sincos(endAngle)
|
||||
s, c := math.Sincos(endAngle)
|
||||
cv.LineTo(x+radius*c, y+radius*s)
|
||||
}
|
||||
|
||||
func (cv *Canvas) ArcTo(x1, y1, x2, y2, radius float32) {
|
||||
func (cv *Canvas) ArcTo(x1, y1, x2, y2, radius float64) {
|
||||
if len(cv.linePath) == 0 {
|
||||
return
|
||||
}
|
||||
p0, p1, p2 := cv.linePath[len(cv.linePath)-1].pos, lm.Vec2{x1, y1}, lm.Vec2{x2, y2}
|
||||
v0, v1 := p0.Sub(p1).Norm(), p2.Sub(p1).Norm()
|
||||
angle := fmath.Acos(v0.Dot(v1))
|
||||
p0, p1, p2 := cv.linePath[len(cv.linePath)-1].pos, vec{x1, y1}, vec{x2, y2}
|
||||
v0, v1 := p0.sub(p1).norm(), p2.sub(p1).norm()
|
||||
angle := math.Acos(v0.dot(v1))
|
||||
// should be in the range [0-pi]. if parallel, use a straight line
|
||||
if angle <= 0 || angle >= math.Pi {
|
||||
cv.LineTo(x2, y2)
|
||||
return
|
||||
}
|
||||
// cv are the vectors orthogonal to the lines that point to the center of the circle
|
||||
cv0 := lm.Vec2{-v0[1], v0[0]}
|
||||
cv1 := lm.Vec2{v1[1], -v1[0]}
|
||||
x := cv1.Sub(cv0).Div(v0.Sub(v1))[0] * radius
|
||||
cv0 := vec{-v0[1], v0[0]}
|
||||
cv1 := vec{v1[1], -v1[0]}
|
||||
x := cv1.sub(cv0).div(v0.sub(v1))[0] * radius
|
||||
if x < 0 {
|
||||
cv0 = cv0.MulF(-1)
|
||||
cv1 = cv1.MulF(-1)
|
||||
cv0 = cv0.mulf(-1)
|
||||
cv1 = cv1.mulf(-1)
|
||||
}
|
||||
center := p1.Add(v0.MulF(fmath.Abs(x))).Add(cv0.MulF(radius))
|
||||
a0, a1 := cv0.MulF(-1).Atan2(), cv1.MulF(-1).Atan2()
|
||||
center := p1.add(v0.mulf(math.Abs(x))).add(cv0.mulf(radius))
|
||||
a0, a1 := cv0.mulf(-1).atan2(), cv1.mulf(-1).atan2()
|
||||
cv.Arc(center[0], center[1], radius, a0, a1, x > 0)
|
||||
}
|
||||
|
||||
func (cv *Canvas) QuadraticCurveTo(x1, y1, x2, y2 float32) {
|
||||
func (cv *Canvas) QuadraticCurveTo(x1, y1, x2, y2 float64) {
|
||||
if len(cv.linePath) == 0 {
|
||||
return
|
||||
}
|
||||
p0 := cv.linePath[len(cv.linePath)-1].pos
|
||||
p1 := lm.Vec2{x1, y1}
|
||||
p2 := lm.Vec2{x2, y2}
|
||||
v0 := p1.Sub(p0)
|
||||
v1 := p2.Sub(p1)
|
||||
p1 := vec{x1, y1}
|
||||
p2 := vec{x2, y2}
|
||||
v0 := p1.sub(p0)
|
||||
v1 := p2.sub(p1)
|
||||
|
||||
tp0, tp1, tp2 := cv.tf(p0), cv.tf(p1), cv.tf(p2)
|
||||
tv0 := tp1.Sub(tp0)
|
||||
tv1 := tp2.Sub(tp1)
|
||||
tv0 := tp1.sub(tp0)
|
||||
tv1 := tp2.sub(tp1)
|
||||
|
||||
step := 1 / fmath.Max(fmath.Max(tv0[0], tv0[1]), fmath.Max(tv1[0], tv1[1]))
|
||||
step := 1 / math.Max(math.Max(tv0[0], tv0[1]), math.Max(tv1[0], tv1[1]))
|
||||
if step > 0.1 {
|
||||
step = 0.1
|
||||
} else if step < 0.005 {
|
||||
step = 0.005
|
||||
}
|
||||
|
||||
for r := float32(0); r < 1; r += step {
|
||||
i0 := v0.MulF(r).Add(p0)
|
||||
i1 := v1.MulF(r).Add(p1)
|
||||
p := i1.Sub(i0).MulF(r).Add(i0)
|
||||
for r := 0.0; r < 1; r += step {
|
||||
i0 := v0.mulf(r).add(p0)
|
||||
i1 := v1.mulf(r).add(p1)
|
||||
p := i1.sub(i0).mulf(r).add(i0)
|
||||
cv.LineTo(p[0], p[1])
|
||||
}
|
||||
}
|
||||
|
||||
func (cv *Canvas) BezierCurveTo(x1, y1, x2, y2, x3, y3 float32) {
|
||||
func (cv *Canvas) BezierCurveTo(x1, y1, x2, y2, x3, y3 float64) {
|
||||
if len(cv.linePath) == 0 {
|
||||
return
|
||||
}
|
||||
p0 := cv.linePath[len(cv.linePath)-1].pos
|
||||
p1 := lm.Vec2{x1, y1}
|
||||
p2 := lm.Vec2{x2, y2}
|
||||
p3 := lm.Vec2{x3, y3}
|
||||
v0 := p1.Sub(p0)
|
||||
v1 := p2.Sub(p1)
|
||||
v2 := p3.Sub(p2)
|
||||
p1 := vec{x1, y1}
|
||||
p2 := vec{x2, y2}
|
||||
p3 := vec{x3, y3}
|
||||
v0 := p1.sub(p0)
|
||||
v1 := p2.sub(p1)
|
||||
v2 := p3.sub(p2)
|
||||
|
||||
tp0, tp1, tp2, tp3 := cv.tf(p0), cv.tf(p1), cv.tf(p2), cv.tf(p3)
|
||||
tv0 := tp1.Sub(tp0)
|
||||
tv1 := tp2.Sub(tp1)
|
||||
tv2 := tp3.Sub(tp2)
|
||||
tv0 := tp1.sub(tp0)
|
||||
tv1 := tp2.sub(tp1)
|
||||
tv2 := tp3.sub(tp2)
|
||||
|
||||
step := 1 / fmath.Max(fmath.Max(fmath.Max(tv0[0], tv0[1]), fmath.Max(tv1[0], tv1[1])), fmath.Max(tv2[0], tv2[1]))
|
||||
step := 1 / math.Max(math.Max(math.Max(tv0[0], tv0[1]), math.Max(tv1[0], tv1[1])), math.Max(tv2[0], tv2[1]))
|
||||
if step > 0.1 {
|
||||
step = 0.1
|
||||
} else if step < 0.005 {
|
||||
step = 0.005
|
||||
}
|
||||
|
||||
for r := float32(0); r < 1; r += step {
|
||||
i0 := v0.MulF(r).Add(p0)
|
||||
i1 := v1.MulF(r).Add(p1)
|
||||
i2 := v2.MulF(r).Add(p2)
|
||||
iv0 := i1.Sub(i0)
|
||||
iv1 := i2.Sub(i1)
|
||||
j0 := iv0.MulF(r).Add(i0)
|
||||
j1 := iv1.MulF(r).Add(i1)
|
||||
p := j1.Sub(j0).MulF(r).Add(j0)
|
||||
for r := 0.0; r < 1; r += step {
|
||||
i0 := v0.mulf(r).add(p0)
|
||||
i1 := v1.mulf(r).add(p1)
|
||||
i2 := v2.mulf(r).add(p2)
|
||||
iv0 := i1.sub(i0)
|
||||
iv1 := i2.sub(i1)
|
||||
j0 := iv0.mulf(r).add(i0)
|
||||
j1 := iv1.mulf(r).add(i1)
|
||||
p := j1.sub(j0).mulf(r).add(j0)
|
||||
cv.LineTo(p[0], p[1])
|
||||
}
|
||||
}
|
||||
|
@ -255,10 +252,10 @@ func (cv *Canvas) Stroke() {
|
|||
|
||||
var buf [1000]float32
|
||||
tris := buf[:0]
|
||||
tris = append(tris, 0, 0, cv.fw, 0, cv.fw, cv.fh, 0, 0, cv.fw, cv.fh, 0, cv.fh)
|
||||
tris = append(tris, 0, 0, float32(cv.fw), 0, float32(cv.fw), float32(cv.fh), 0, 0, float32(cv.fw), float32(cv.fh), 0, float32(cv.fh))
|
||||
|
||||
start := true
|
||||
var p0 lm.Vec2
|
||||
var p0 vec
|
||||
for _, p := range cv.linePath {
|
||||
if p.move {
|
||||
p0 = p.tf
|
||||
|
@ -267,22 +264,22 @@ func (cv *Canvas) Stroke() {
|
|||
}
|
||||
p1 := p.tf
|
||||
|
||||
v0 := p1.Sub(p0).Norm()
|
||||
v1 := lm.Vec2{v0[1], -v0[0]}.MulF(cv.state.lineWidth * 0.5)
|
||||
v0 = v0.MulF(cv.state.lineWidth * 0.5)
|
||||
v0 := p1.sub(p0).norm()
|
||||
v1 := vec{v0[1], -v0[0]}.mulf(cv.state.lineWidth * 0.5)
|
||||
v0 = v0.mulf(cv.state.lineWidth * 0.5)
|
||||
|
||||
lp0 := p0.Add(v1)
|
||||
lp1 := p1.Add(v1)
|
||||
lp2 := p0.Sub(v1)
|
||||
lp3 := p1.Sub(v1)
|
||||
lp0 := p0.add(v1)
|
||||
lp1 := p1.add(v1)
|
||||
lp2 := p0.sub(v1)
|
||||
lp3 := p1.sub(v1)
|
||||
|
||||
if start {
|
||||
switch cv.state.lineEnd {
|
||||
case Butt:
|
||||
// no need to do anything
|
||||
case Square:
|
||||
lp0 = lp0.Sub(v0)
|
||||
lp2 = lp2.Sub(v0)
|
||||
lp0 = lp0.sub(v0)
|
||||
lp2 = lp2.sub(v0)
|
||||
case Round:
|
||||
tris = cv.addCircleTris(p0, cv.state.lineWidth*0.5, tris)
|
||||
}
|
||||
|
@ -293,16 +290,16 @@ func (cv *Canvas) Stroke() {
|
|||
case Butt:
|
||||
// no need to do anything
|
||||
case Square:
|
||||
lp1 = lp1.Add(v0)
|
||||
lp3 = lp3.Add(v0)
|
||||
lp1 = lp1.add(v0)
|
||||
lp3 = lp3.add(v0)
|
||||
case Round:
|
||||
tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris)
|
||||
}
|
||||
}
|
||||
|
||||
tris = append(tris,
|
||||
lp0[0], lp0[1], lp1[0], lp1[1], lp3[0], lp3[1],
|
||||
lp0[0], lp0[1], lp3[0], lp3[1], lp2[0], lp2[1])
|
||||
float32(lp0[0]), float32(lp0[1]), float32(lp1[0]), float32(lp1[1]), float32(lp3[0]), float32(lp3[1]),
|
||||
float32(lp0[0]), float32(lp0[1]), float32(lp3[0]), float32(lp3[1]), float32(lp2[0]), float32(lp2[1]))
|
||||
|
||||
if p.attach {
|
||||
tris = cv.lineJoint(p, p0, p1, p.next, lp0, lp1, lp2, lp3, tris)
|
||||
|
@ -316,7 +313,7 @@ func (cv *Canvas) Stroke() {
|
|||
|
||||
gli.UseProgram(sr.id)
|
||||
gli.Uniform4f(sr.color, 0, 0, 0, 0)
|
||||
gli.Uniform2f(sr.canvasSize, cv.fw, cv.fh)
|
||||
gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
|
||||
gli.ColorMask(false, false, false, false)
|
||||
|
||||
|
@ -344,41 +341,41 @@ func (cv *Canvas) Stroke() {
|
|||
gli.StencilMask(0xFF)
|
||||
}
|
||||
|
||||
func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 lm.Vec2, tris []float32) []float32 {
|
||||
v2 := p1.Sub(p2).Norm()
|
||||
v3 := lm.Vec2{v2[1], -v2[0]}.MulF(cv.state.lineWidth * 0.5)
|
||||
func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 vec, tris []float32) []float32 {
|
||||
v2 := p1.sub(p2).norm()
|
||||
v3 := vec{v2[1], -v2[0]}.mulf(cv.state.lineWidth * 0.5)
|
||||
|
||||
switch cv.state.lineJoin {
|
||||
case Miter:
|
||||
l1p0 := p2.Sub(v3)
|
||||
l1p1 := p1.Sub(v3)
|
||||
l1p2 := p2.Add(v3)
|
||||
l1p3 := p1.Add(v3)
|
||||
l1p0 := p2.sub(v3)
|
||||
l1p1 := p1.sub(v3)
|
||||
l1p2 := p2.add(v3)
|
||||
l1p3 := p1.add(v3)
|
||||
|
||||
var ip0, ip1 lm.Vec2
|
||||
if l0p1.Sub(l1p1).LenSqr() < 0.000000001 {
|
||||
ip0 = l0p1.Sub(l1p1).MulF(0.5).Add(l1p1)
|
||||
var ip0, ip1 vec
|
||||
if l0p1.sub(l1p1).lenSqr() < 0.000000001 {
|
||||
ip0 = l0p1.sub(l1p1).mulf(0.5).add(l1p1)
|
||||
} else {
|
||||
ip0, _, _ = lineIntersection(l0p0, l0p1, l1p1, l1p0)
|
||||
}
|
||||
if l0p3.Sub(l1p3).LenSqr() < 0.000000001 {
|
||||
ip1 = l0p3.Sub(l1p3).MulF(0.5).Add(l1p3)
|
||||
if l0p3.sub(l1p3).lenSqr() < 0.000000001 {
|
||||
ip1 = l0p3.sub(l1p3).mulf(0.5).add(l1p3)
|
||||
} else {
|
||||
ip1, _, _ = lineIntersection(l0p2, l0p3, l1p3, l1p2)
|
||||
}
|
||||
|
||||
tris = append(tris,
|
||||
p1[0], p1[1], l0p1[0], l0p1[1], ip0[0], ip0[1],
|
||||
p1[0], p1[1], ip0[0], ip0[1], l1p1[0], l1p1[1],
|
||||
p1[0], p1[1], l1p3[0], l1p3[1], ip1[0], ip1[1],
|
||||
p1[0], p1[1], ip1[0], ip1[1], l0p3[0], l0p3[1])
|
||||
float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(ip0[0]), float32(ip0[1]),
|
||||
float32(p1[0]), float32(p1[1]), float32(ip0[0]), float32(ip0[1]), float32(l1p1[0]), float32(l1p1[1]),
|
||||
float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(ip1[0]), float32(ip1[1]),
|
||||
float32(p1[0]), float32(p1[1]), float32(ip1[0]), float32(ip1[1]), float32(l0p3[0]), float32(l0p3[1]))
|
||||
case Bevel:
|
||||
l1p1 := p1.Sub(v3)
|
||||
l1p3 := p1.Add(v3)
|
||||
l1p1 := p1.sub(v3)
|
||||
l1p3 := p1.add(v3)
|
||||
|
||||
tris = append(tris,
|
||||
p1[0], p1[1], l0p1[0], l0p1[1], l1p1[0], l1p1[1],
|
||||
p1[0], p1[1], l1p3[0], l1p3[1], l0p3[0], l0p3[1])
|
||||
float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(l1p1[0]), float32(l1p1[1]),
|
||||
float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(l0p3[0]), float32(l0p3[1]))
|
||||
case Round:
|
||||
tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris)
|
||||
}
|
||||
|
@ -386,8 +383,8 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 lm.V
|
|||
return tris
|
||||
}
|
||||
|
||||
func (cv *Canvas) addCircleTris(center lm.Vec2, radius float32, tris []float32) []float32 {
|
||||
p0 := lm.Vec2{center[0], center[1] + radius}
|
||||
func (cv *Canvas) addCircleTris(center vec, radius float64, tris []float32) []float32 {
|
||||
p0 := vec{center[0], center[1] + radius}
|
||||
step := 6 / radius
|
||||
if step > 0.8 {
|
||||
step = 0.8
|
||||
|
@ -395,30 +392,30 @@ func (cv *Canvas) addCircleTris(center lm.Vec2, radius float32, tris []float32)
|
|||
step = 0.05
|
||||
}
|
||||
for angle := step; angle <= math.Pi*2+step; angle += step {
|
||||
s, c := fmath.Sincos(angle)
|
||||
p1 := lm.Vec2{center[0] + s*radius, center[1] + c*radius}
|
||||
tris = append(tris, center[0], center[1], p0[0], p0[1], p1[0], p1[1])
|
||||
s, c := math.Sincos(angle)
|
||||
p1 := vec{center[0] + s*radius, center[1] + c*radius}
|
||||
tris = append(tris, float32(center[0]), float32(center[1]), float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]))
|
||||
p0 = p1
|
||||
}
|
||||
return tris
|
||||
}
|
||||
|
||||
func lineIntersection(a0, a1, b0, b1 lm.Vec2) (lm.Vec2, float32, float32) {
|
||||
va := a1.Sub(a0)
|
||||
vb := b1.Sub(b0)
|
||||
func lineIntersection(a0, a1, b0, b1 vec) (vec, float64, float64) {
|
||||
va := a1.sub(a0)
|
||||
vb := b1.sub(b0)
|
||||
|
||||
if (va[0] == 0 && vb[0] == 0) || (va[1] == 0 && vb[1] == 0) || (va[0] == 0 && va[1] == 0) || (vb[0] == 0 && vb[1] == 0) {
|
||||
return lm.Vec2{}, float32(math.Inf(1)), float32(math.Inf(1))
|
||||
return vec{}, float64(math.Inf(1)), float64(math.Inf(1))
|
||||
}
|
||||
p := (vb[1]*(a0[0]-b0[0]) - a0[1]*vb[0] + b0[1]*vb[0]) / (va[1]*vb[0] - va[0]*vb[1])
|
||||
var q float32
|
||||
var q float64
|
||||
if vb[0] == 0 {
|
||||
q = (a0[1] + p*va[1] - b0[1]) / vb[1]
|
||||
} else {
|
||||
q = (a0[0] + p*va[0] - b0[0]) / vb[0]
|
||||
}
|
||||
|
||||
return a0.Add(va.MulF(p)), p, q
|
||||
return a0.add(va.mulf(p)), p, q
|
||||
}
|
||||
|
||||
func (cv *Canvas) Fill() {
|
||||
|
@ -471,7 +468,7 @@ func (cv *Canvas) clip(path []pathPoint) {
|
|||
|
||||
var triBuf [1000]float32
|
||||
tris := triBuf[:0]
|
||||
tris = append(tris, 0, 0, cv.fw, 0, cv.fw, cv.fh, 0, 0, cv.fw, cv.fh, 0, cv.fh)
|
||||
tris = append(tris, 0, 0, float32(cv.fw), 0, float32(cv.fw), float32(cv.fh), 0, 0, float32(cv.fw), float32(cv.fh), 0, float32(cv.fh))
|
||||
tris = triangulatePath(path, tris)
|
||||
if len(tris) > 0 {
|
||||
return
|
||||
|
@ -483,7 +480,7 @@ func (cv *Canvas) clip(path []pathPoint) {
|
|||
|
||||
gli.UseProgram(sr.id)
|
||||
gli.Uniform4f(sr.color, 1, 1, 1, 1)
|
||||
gli.Uniform2f(sr.canvasSize, cv.fw, cv.fh)
|
||||
gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
gli.EnableVertexAttribArray(sr.vertex)
|
||||
|
||||
gli.DrawArrays(gl_TRIANGLES, 0, 6)
|
||||
|
|
21
text.go
21
text.go
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/golang/freetype"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/tfriedel6/lm"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
@ -51,7 +50,7 @@ func LoadFont(src interface{}, name string) (*Font, error) {
|
|||
return f, nil
|
||||
}
|
||||
|
||||
func (cv *Canvas) FillText(str string, x, y float32) {
|
||||
func (cv *Canvas) FillText(str string, x, y float64) {
|
||||
cv.activate()
|
||||
|
||||
frc := fontRenderingContext
|
||||
|
@ -83,7 +82,7 @@ func (cv *Canvas) FillText(str string, x, y float32) {
|
|||
if frc.hinting != font.HintingNone {
|
||||
kern = (kern + 32) &^ 63
|
||||
}
|
||||
x += float32(kern) / 64
|
||||
x += float64(kern) / 64
|
||||
}
|
||||
advance, mask, offset, err := frc.glyph(idx, fixed.Point26_6{})
|
||||
if err != nil {
|
||||
|
@ -98,13 +97,13 @@ func (cv *Canvas) FillText(str string, x, y float32) {
|
|||
gli.TexSubImage2D(gl_TEXTURE_2D, 0, 0, int32(alphaTexSize-1-y), int32(w), 1, gl_ALPHA, gl_UNSIGNED_BYTE, gli.Ptr(&mask.Pix[off]))
|
||||
}
|
||||
|
||||
p0 := cv.tf(lm.Vec2{float32(bounds.Min.X) + x, float32(bounds.Min.Y) + y})
|
||||
p1 := cv.tf(lm.Vec2{float32(bounds.Min.X) + x, float32(bounds.Max.Y) + y})
|
||||
p2 := cv.tf(lm.Vec2{float32(bounds.Max.X) + x, float32(bounds.Max.Y) + y})
|
||||
p3 := cv.tf(lm.Vec2{float32(bounds.Max.X) + x, float32(bounds.Min.Y) + y})
|
||||
tw := float32(bounds.Dx()) / alphaTexSize
|
||||
th := float32(bounds.Dy()) / alphaTexSize
|
||||
data := [16]float32{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1],
|
||||
p0 := cv.tf(vec{float64(bounds.Min.X) + x, float64(bounds.Min.Y) + y})
|
||||
p1 := cv.tf(vec{float64(bounds.Min.X) + x, float64(bounds.Max.Y) + y})
|
||||
p2 := cv.tf(vec{float64(bounds.Max.X) + x, float64(bounds.Max.Y) + y})
|
||||
p3 := cv.tf(vec{float64(bounds.Max.X) + x, float64(bounds.Min.Y) + y})
|
||||
tw := float64(bounds.Dx()) / alphaTexSize
|
||||
th := float64(bounds.Dy()) / alphaTexSize
|
||||
data := [16]float64{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1],
|
||||
0, 1, 0, 1 - th, tw, 1 - th, tw, 1}
|
||||
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
|
||||
|
||||
|
@ -116,7 +115,7 @@ func (cv *Canvas) FillText(str string, x, y float32) {
|
|||
gli.TexSubImage2D(gl_TEXTURE_2D, 0, 0, int32(alphaTexSize-1-y), int32(w), 1, gl_ALPHA, gl_UNSIGNED_BYTE, gli.Ptr(&zeroes[0]))
|
||||
}
|
||||
|
||||
x += float32(advance) / 64
|
||||
x += float64(advance) / 64
|
||||
}
|
||||
|
||||
gli.DisableVertexAttribArray(vertex)
|
||||
|
|
|
@ -3,11 +3,9 @@ package canvas
|
|||
import (
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
"github.com/tfriedel6/lm"
|
||||
)
|
||||
|
||||
func pointIsRightOfLine(a, b, p lm.Vec2) bool {
|
||||
func pointIsRightOfLine(a, b, p vec) bool {
|
||||
if a[1] == b[1] {
|
||||
return false
|
||||
}
|
||||
|
@ -17,13 +15,13 @@ func pointIsRightOfLine(a, b, p lm.Vec2) bool {
|
|||
if p[1] < a[1] || p[1] > b[1] {
|
||||
return false
|
||||
}
|
||||
v := b.Sub(a)
|
||||
v := b.sub(a)
|
||||
r := (p[1] - a[1]) / v[1]
|
||||
x := a[0] + r*v[0]
|
||||
return p[0] > x
|
||||
}
|
||||
|
||||
func triangleContainsPoint(a, b, c, p lm.Vec2) bool {
|
||||
func triangleContainsPoint(a, b, c, p vec) bool {
|
||||
// if point is outside triangle bounds, return false
|
||||
if p[0] < a[0] && p[0] < b[0] && p[0] < c[0] {
|
||||
return false
|
||||
|
@ -52,7 +50,7 @@ func triangleContainsPoint(a, b, c, p lm.Vec2) bool {
|
|||
return count == 1
|
||||
}
|
||||
|
||||
func polygonContainsPoint(polygon []lm.Vec2, p lm.Vec2) bool {
|
||||
func polygonContainsPoint(polygon []vec, p vec) bool {
|
||||
a := polygon[len(polygon)-1]
|
||||
count := 0
|
||||
for _, b := range polygon {
|
||||
|
@ -65,7 +63,7 @@ func polygonContainsPoint(polygon []lm.Vec2, p lm.Vec2) bool {
|
|||
}
|
||||
|
||||
func triangulatePath(path []pathPoint, target []float32) []float32 {
|
||||
var buf [500]lm.Vec2
|
||||
var buf [500]vec
|
||||
polygon := buf[:0]
|
||||
for _, p := range path {
|
||||
polygon = append(polygon, p.tf)
|
||||
|
@ -78,7 +76,7 @@ func triangulatePath(path []pathPoint, target []float32) []float32 {
|
|||
a := polygon[i]
|
||||
b := polygon[(i+1)%len(polygon)]
|
||||
c := polygon[(i+2)%len(polygon)]
|
||||
if isSamePoint(a, c, math.SmallestNonzeroFloat32) {
|
||||
if isSamePoint(a, c, math.SmallestNonzeroFloat64) {
|
||||
break
|
||||
}
|
||||
for i2, p := range polygon {
|
||||
|
@ -88,13 +86,13 @@ func triangulatePath(path []pathPoint, target []float32) []float32 {
|
|||
if triangleContainsPoint(a, b, c, p) {
|
||||
continue triangles
|
||||
}
|
||||
center := a.Add(b).Add(c).DivF(3)
|
||||
center := a.add(b).add(c).divf(3)
|
||||
if !polygonContainsPoint(polygon, center) {
|
||||
continue triangles
|
||||
}
|
||||
break
|
||||
}
|
||||
target = append(target, a[0], a[1], b[0], b[1], c[0], c[1])
|
||||
target = append(target, float32(a[0]), float32(a[1]), float32(b[0]), float32(b[1]), float32(c[0]), float32(c[1]))
|
||||
break
|
||||
}
|
||||
remove := (i + 1) % len(polygon)
|
||||
|
@ -108,8 +106,8 @@ func (cv *Canvas) cutIntersections(path []pathPoint) []pathPoint {
|
|||
from, to int
|
||||
j int
|
||||
b bool
|
||||
ratio float32
|
||||
point lm.Vec2
|
||||
ratio float64
|
||||
point vec
|
||||
}
|
||||
|
||||
var cutBuf [50]cut
|
||||
|
|
Loading…
Reference in a new issue