Add stroke functionality

This commit is contained in:
Taco de Wolff 2017-05-17 00:07:36 +02:00
parent bcfeb16b74
commit d70502db33
13 changed files with 53 additions and 29 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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/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 github.com/tdewolff/freetype/..."
// 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/tdewolff/freetype/truetype"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)

View file

@ -6,15 +6,15 @@
// The freetype package provides a convenient API to draw text onto an image.
// Use the freetype/raster and freetype/truetype packages for lower level
// control over rasterization and TrueType parsing.
package freetype // import "github.com/golang/freetype"
package freetype // import "github.com/tdewolff/freetype"
import (
"errors"
"image"
"image/draw"
"github.com/golang/freetype/raster"
"github.com/golang/freetype/truetype"
"github.com/tdewolff/freetype/raster"
"github.com/tdewolff/freetype/truetype"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)

View file

@ -13,7 +13,7 @@
// the Freetype "smooth" module, and the Anti-Grain Geometry library. A
// description of the area/coverage algorithm is at
// http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm
package raster // import "github.com/golang/freetype/raster"
package raster // import "github.com/tdewolff/freetype/raster"
import (
"strconv"

View file

@ -9,7 +9,7 @@ import (
"image"
"math"
"github.com/golang/freetype/raster"
"github.com/tdewolff/freetype/raster"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)
@ -66,6 +66,8 @@ type Options struct {
//
// A zero value means to use 1 sub-pixel location.
SubPixelsY int
Stroke int
}
func (o *Options) size() float64 {
@ -182,6 +184,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 +210,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 +227,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
@ -329,6 +337,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,
@ -364,6 +376,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
@ -434,7 +450,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{
@ -444,9 +461,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 {
@ -456,16 +473,23 @@ 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 {
path.Add1(start)
a.r.AddStroke(path, a.stroke, raster.RoundCapper, raster.RoundJoiner)
}
}

View file

@ -15,7 +15,7 @@
//
// To measure a TrueType font in ideal FUnit space, use scale equal to
// font.FUnitsPerEm().
package truetype // import "github.com/golang/freetype/truetype"
package truetype // import "github.com/tdewolff/freetype/truetype"
import (
"fmt"