merged changes from tdewolff-master
This commit is contained in:
parent
7946394216
commit
7349a45553
12 changed files with 63 additions and 28 deletions
2
README
2
README
|
@ -1,7 +1,7 @@
|
|||
The Freetype font rasterizer in the Go programming language.
|
||||
|
||||
To download and install from source:
|
||||
$ go get github.com/golang/freetype
|
||||
$ go get github.com/tdewolff/freetype
|
||||
|
||||
It is an incomplete port:
|
||||
* It only supports TrueType fonts, and not Type 1 fonts nor bitmap fonts.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/golang/freetype/raster"
|
||||
"github.com/goki/freetype/raster"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -24,7 +24,7 @@ import (
|
|||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/goki/freetype/truetype"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -23,7 +23,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/golang/freetype"
|
||||
"github.com/goki/freetype"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -20,7 +20,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/golang/freetype/raster"
|
||||
"github.com/goki/freetype/raster"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -26,7 +26,7 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/goki/freetype/truetype"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/golang/freetype/raster"
|
||||
"github.com/goki/freetype/raster"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -27,7 +27,7 @@ import (
|
|||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/golang/freetype/raster"
|
||||
"github.com/goki/freetype/raster"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// +build example
|
||||
//
|
||||
// This build tag means that "go install github.com/golang/freetype/..."
|
||||
// This build tag means that "go install ..."
|
||||
// doesn't install this example program. Use "go run main.go" to run it or "go
|
||||
// install -tags=example" to install it.
|
||||
|
||||
|
@ -17,7 +17,7 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/goki/freetype/truetype"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
|
|
@ -438,12 +438,20 @@ func (k *stroker) stroke(q Path) {
|
|||
if len(k.r) == 0 {
|
||||
return
|
||||
}
|
||||
// TODO(nigeltao): if q is a closed curve then we should join the first and
|
||||
// last segments instead of capping them.
|
||||
k.cr.Cap(k.p, k.u, q.lastPoint(), pNeg(k.anorm))
|
||||
|
||||
closed := q.firstPoint() == q.lastPoint()
|
||||
if !closed {
|
||||
k.cr.Cap(k.p, k.u, q.lastPoint(), pNeg(k.anorm))
|
||||
} else {
|
||||
pivot := q.firstPoint()
|
||||
k.jr.Join(k.p, &k.r, k.u, pivot, k.anorm, pivot.Sub(fixed.Point26_6{k.r[1], k.r[2]}))
|
||||
k.p.Start(fixed.Point26_6{k.r[len(k.r)-3], k.r[len(k.r)-2]}) // reverse path is now separate
|
||||
}
|
||||
addPathReversed(k.p, k.r)
|
||||
pivot := q.firstPoint()
|
||||
k.cr.Cap(k.p, k.u, pivot, pivot.Sub(fixed.Point26_6{k.r[1], k.r[2]}))
|
||||
if !closed {
|
||||
pivot := q.firstPoint()
|
||||
k.cr.Cap(k.p, k.u, pivot, pivot.Sub(fixed.Point26_6{k.r[1], k.r[2]}))
|
||||
}
|
||||
}
|
||||
|
||||
// Stroke adds q stroked with the given width to p. The result is typically
|
||||
|
|
|
@ -66,6 +66,11 @@ type Options struct {
|
|||
//
|
||||
// A zero value means to use 1 sub-pixel location.
|
||||
SubPixelsY int
|
||||
|
||||
// Stroke is the number of pixels that the font glyphs are being stroked.
|
||||
//
|
||||
// A zero values means no stroke.
|
||||
Stroke int
|
||||
}
|
||||
|
||||
func (o *Options) size() float64 {
|
||||
|
@ -182,6 +187,7 @@ func NewFace(f *Font, opts *Options) font.Face {
|
|||
hinting: opts.hinting(),
|
||||
scale: fixed.Int26_6(0.5 + (opts.size() * opts.dpi() * 64 / 72)),
|
||||
glyphCache: make([]glyphCacheEntry, opts.glyphCacheEntries()),
|
||||
stroke: fixed.I(opts.Stroke * 2),
|
||||
}
|
||||
a.subPixelX, a.subPixelBiasX, a.subPixelMaskX = opts.subPixelsX()
|
||||
a.subPixelY, a.subPixelBiasY, a.subPixelMaskY = opts.subPixelsY()
|
||||
|
@ -207,6 +213,10 @@ func NewFace(f *Font, opts *Options) font.Face {
|
|||
a.r.SetBounds(a.maxw, a.maxh)
|
||||
a.p = facePainter{a}
|
||||
|
||||
if a.stroke != 0 {
|
||||
a.r.UseNonZeroWinding = true
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
|
@ -220,6 +230,7 @@ type face struct {
|
|||
subPixelY uint32
|
||||
subPixelBiasY fixed.Int26_6
|
||||
subPixelMaskY fixed.Int26_6
|
||||
stroke fixed.Int26_6
|
||||
masks *image.Alpha
|
||||
glyphCache []glyphCacheEntry
|
||||
r raster.Rasterizer
|
||||
|
@ -333,6 +344,10 @@ func (a *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.In
|
|||
if xmin > xmax || ymin > ymax {
|
||||
return fixed.Rectangle26_6{}, 0, false
|
||||
}
|
||||
xmin -= a.stroke
|
||||
ymin -= a.stroke
|
||||
xmax += a.stroke
|
||||
ymax += a.stroke
|
||||
return fixed.Rectangle26_6{
|
||||
Min: fixed.Point26_6{
|
||||
X: xmin,
|
||||
|
@ -376,6 +391,10 @@ func (a *face) rasterize(index Index, fx, fy fixed.Int26_6) (v glyphCacheVal, ok
|
|||
if xmin > xmax || ymin > ymax {
|
||||
return glyphCacheVal{}, false
|
||||
}
|
||||
xmin -= int(a.stroke) >> 6
|
||||
ymin -= int(a.stroke) >> 6
|
||||
xmax += int(a.stroke) >> 6
|
||||
ymax += int(a.stroke) >> 6
|
||||
// A TrueType's glyph's nodes can have negative co-ordinates, but the
|
||||
// rasterizer clips anything left of x=0 or above y=0. xmin and ymin are
|
||||
// the pixel offsets, based on the font's FUnit metrics, that let a
|
||||
|
@ -446,7 +465,8 @@ func (a *face) drawContour(ps []Point, dx, dy fixed.Int26_6) {
|
|||
others = ps
|
||||
}
|
||||
}
|
||||
a.r.Start(start)
|
||||
path := raster.Path{}
|
||||
path.Start(start)
|
||||
q0, on0 := start, true
|
||||
for _, p := range others {
|
||||
q := fixed.Point26_6{
|
||||
|
@ -456,9 +476,9 @@ func (a *face) drawContour(ps []Point, dx, dy fixed.Int26_6) {
|
|||
on := p.Flags&0x01 != 0
|
||||
if on {
|
||||
if on0 {
|
||||
a.r.Add1(q)
|
||||
path.Add1(q)
|
||||
} else {
|
||||
a.r.Add2(q0, q)
|
||||
path.Add2(q0, q)
|
||||
}
|
||||
} else {
|
||||
if on0 {
|
||||
|
@ -468,16 +488,22 @@ func (a *face) drawContour(ps []Point, dx, dy fixed.Int26_6) {
|
|||
X: (q0.X + q.X) / 2,
|
||||
Y: (q0.Y + q.Y) / 2,
|
||||
}
|
||||
a.r.Add2(q0, mid)
|
||||
path.Add2(q0, mid)
|
||||
}
|
||||
}
|
||||
q0, on0 = q, on
|
||||
}
|
||||
// Close the curve.
|
||||
if on0 {
|
||||
a.r.Add1(start)
|
||||
path.Add1(start)
|
||||
} else {
|
||||
a.r.Add2(q0, start)
|
||||
path.Add2(q0, start)
|
||||
}
|
||||
|
||||
if a.stroke == 0 {
|
||||
a.r.AddPath(path)
|
||||
} else {
|
||||
a.r.AddStroke(path, a.stroke, raster.ButtCapper, raster.RoundJoiner)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
//
|
||||
// To measure a TrueType font in ideal FUnit space, use scale equal to
|
||||
// font.FUnitsPerEm().
|
||||
|
||||
package truetype
|
||||
|
||||
import (
|
||||
|
|
Loading…
Reference in a new issue