merged changes from tdewolff-master

This commit is contained in:
Randall C. O'Reilly 2018-08-17 00:57:27 -06:00
parent 7946394216
commit 7349a45553
12 changed files with 63 additions and 28 deletions

2
README
View file

@ -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.

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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

View file

@ -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)
}
}

View file

@ -15,6 +15,7 @@
//
// To measure a TrueType font in ideal FUnit space, use scale equal to
// font.FUnitsPerEm().
package truetype
import (