From d70502db33a472c45a4b4dfdeb8a84ccf1777cc9 Mon Sep 17 00:00:00 2001 From: Taco de Wolff Date: Wed, 17 May 2017 00:07:36 +0200 Subject: [PATCH] Add stroke functionality --- README | 2 +- example/capjoin/main.go | 4 ++-- example/drawer/main.go | 4 ++-- example/freetype/main.go | 4 ++-- example/gamma/main.go | 4 ++-- example/genbasicfont/main.go | 4 ++-- example/raster/main.go | 4 ++-- example/round/main.go | 4 ++-- example/truetype/main.go | 4 ++-- freetype.go | 6 +++--- raster/raster.go | 2 +- truetype/face.go | 38 +++++++++++++++++++++++++++++------- truetype/truetype.go | 2 +- 13 files changed, 53 insertions(+), 29 deletions(-) diff --git a/README b/README index 39b3d82..a0d70bc 100644 --- a/README +++ b/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. diff --git a/example/capjoin/main.go b/example/capjoin/main.go index 71f3356..4cc4f0f 100644 --- a/example/capjoin/main.go +++ b/example/capjoin/main.go @@ -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" ) diff --git a/example/drawer/main.go b/example/drawer/main.go index d26d066..1c3d495 100644 --- a/example/drawer/main.go +++ b/example/drawer/main.go @@ -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" ) diff --git a/example/freetype/main.go b/example/freetype/main.go index dfbde9a..4c817ad 100644 --- a/example/freetype/main.go +++ b/example/freetype/main.go @@ -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" ) diff --git a/example/gamma/main.go b/example/gamma/main.go index cdd50bc..59fd1b3 100644 --- a/example/gamma/main.go +++ b/example/gamma/main.go @@ -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" ) diff --git a/example/genbasicfont/main.go b/example/genbasicfont/main.go index 5b2f2bc..526cb4a 100644 --- a/example/genbasicfont/main.go +++ b/example/genbasicfont/main.go @@ -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" ) diff --git a/example/raster/main.go b/example/raster/main.go index 3e572e1..0eb5b7a 100644 --- a/example/raster/main.go +++ b/example/raster/main.go @@ -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" ) diff --git a/example/round/main.go b/example/round/main.go index 2920e83..09dae99 100644 --- a/example/round/main.go +++ b/example/round/main.go @@ -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" ) diff --git a/example/truetype/main.go b/example/truetype/main.go index e7db2d0..0fec191 100644 --- a/example/truetype/main.go +++ b/example/truetype/main.go @@ -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" ) diff --git a/freetype.go b/freetype.go index 9603586..f9f0e11 100644 --- a/freetype.go +++ b/freetype.go @@ -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" ) diff --git a/raster/raster.go b/raster/raster.go index 7e6cd4e..7c8038e 100644 --- a/raster/raster.go +++ b/raster/raster.go @@ -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" diff --git a/truetype/face.go b/truetype/face.go index 099006f..ceedf4b 100644 --- a/truetype/face.go +++ b/truetype/face.go @@ -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) } } diff --git a/truetype/truetype.go b/truetype/truetype.go index 7270bbf..0bd9a6c 100644 --- a/truetype/truetype.go +++ b/truetype/truetype.go @@ -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"