2010-05-03 23:54:43 +00:00
|
|
|
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by your choice of either the
|
2010-08-03 01:07:23 +00:00
|
|
|
// FreeType License or the GNU General Public License version 2 (or
|
|
|
|
// any later version), both of which can be found in the LICENSE file.
|
2010-05-03 23:54:43 +00:00
|
|
|
|
2016-04-10 05:05:36 +00:00
|
|
|
// +build example
|
2015-08-12 04:41:46 +00:00
|
|
|
//
|
|
|
|
// This build tag means that "go install github.com/golang/freetype/..."
|
2016-04-10 05:05:36 +00:00
|
|
|
// doesn't install this example program. Use "go run main.go" to run it or "go
|
|
|
|
// install -tags=example" to install it.
|
2015-08-12 04:41:46 +00:00
|
|
|
|
2010-05-03 23:54:43 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
|
2015-08-12 04:30:01 +00:00
|
|
|
"github.com/golang/freetype/truetype"
|
2015-09-01 05:49:46 +00:00
|
|
|
"golang.org/x/image/font"
|
2015-08-18 06:30:37 +00:00
|
|
|
"golang.org/x/image/math/fixed"
|
2010-05-03 23:54:43 +00:00
|
|
|
)
|
|
|
|
|
2013-10-04 07:03:59 +00:00
|
|
|
var fontfile = flag.String("fontfile", "../../testdata/luxisr.ttf", "filename of the ttf font")
|
2010-05-03 23:54:43 +00:00
|
|
|
|
Use fixed.Rectangle26_6 instead of truetype.Bounds.
The previous "the endpoints are inclusive" comment seems confusing. It's true
that the bounding box's max X equals the right-most coordinate, which suggests
<= instead of <, but that node's coordinate is itself exclusive. Consider the
solid 1-pixel square: (0, 0), (64, 0), (64, 64), (0, 64) in fixed.Point26_6
coordinates. The right-most coordinate is 64, and the bounding box's max X
equals 64, but rasterizing that square only affects sub-pixels up to but not
including 64.
Instead, it seems accurate to follow the fixed.Rectangle26_6 description, in
that the max values are exclusive.
2015-08-30 12:06:37 +00:00
|
|
|
func printBounds(b fixed.Rectangle26_6) {
|
|
|
|
fmt.Printf("Min.X:%d Min.Y:%d Max.X:%d Max.Y:%d\n", b.Min.X, b.Min.Y, b.Max.X, b.Max.Y)
|
2010-05-03 23:54:43 +00:00
|
|
|
}
|
|
|
|
|
2010-05-14 03:29:53 +00:00
|
|
|
func printGlyph(g *truetype.GlyphBuf) {
|
Use fixed.Rectangle26_6 instead of truetype.Bounds.
The previous "the endpoints are inclusive" comment seems confusing. It's true
that the bounding box's max X equals the right-most coordinate, which suggests
<= instead of <, but that node's coordinate is itself exclusive. Consider the
solid 1-pixel square: (0, 0), (64, 0), (64, 64), (0, 64) in fixed.Point26_6
coordinates. The right-most coordinate is 64, and the bounding box's max X
equals 64, but rasterizing that square only affects sub-pixels up to but not
including 64.
Instead, it seems accurate to follow the fixed.Rectangle26_6 description, in
that the max values are exclusive.
2015-08-30 12:06:37 +00:00
|
|
|
printBounds(g.Bounds)
|
2010-05-03 23:54:43 +00:00
|
|
|
fmt.Print("Points:\n---\n")
|
|
|
|
e := 0
|
2015-08-30 12:27:18 +00:00
|
|
|
for i, p := range g.Points {
|
2010-05-03 23:54:43 +00:00
|
|
|
fmt.Printf("%4d, %4d", p.X, p.Y)
|
|
|
|
if p.Flags&0x01 != 0 {
|
|
|
|
fmt.Print(" on\n")
|
|
|
|
} else {
|
|
|
|
fmt.Print(" off\n")
|
|
|
|
}
|
2015-08-30 12:27:18 +00:00
|
|
|
if i+1 == int(g.Ends[e]) {
|
2010-05-03 23:54:43 +00:00
|
|
|
fmt.Print("---\n")
|
|
|
|
e++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
fmt.Printf("Loading fontfile %q\n", *fontfile)
|
|
|
|
b, err := ioutil.ReadFile(*fontfile)
|
|
|
|
if err != nil {
|
2010-10-15 03:02:11 +00:00
|
|
|
log.Println(err)
|
2010-05-03 23:54:43 +00:00
|
|
|
return
|
|
|
|
}
|
2015-08-20 06:07:51 +00:00
|
|
|
f, err := truetype.Parse(b)
|
2010-05-03 23:54:43 +00:00
|
|
|
if err != nil {
|
2010-10-15 03:02:11 +00:00
|
|
|
log.Println(err)
|
2010-05-03 23:54:43 +00:00
|
|
|
return
|
|
|
|
}
|
2015-08-20 06:07:51 +00:00
|
|
|
fupe := fixed.Int26_6(f.FUnitsPerEm())
|
|
|
|
printBounds(f.Bounds(fupe))
|
2012-07-25 12:10:25 +00:00
|
|
|
fmt.Printf("FUnitsPerEm:%d\n\n", fupe)
|
2010-05-03 23:54:43 +00:00
|
|
|
|
|
|
|
c0, c1 := 'A', 'V'
|
|
|
|
|
2015-08-20 06:07:51 +00:00
|
|
|
i0 := f.Index(c0)
|
|
|
|
hm := f.HMetric(fupe, i0)
|
2015-08-30 11:35:58 +00:00
|
|
|
g := &truetype.GlyphBuf{}
|
2015-08-20 06:07:51 +00:00
|
|
|
err = g.Load(f, fupe, i0, font.HintingNone)
|
2010-05-03 23:54:43 +00:00
|
|
|
if err != nil {
|
2010-10-15 03:02:11 +00:00
|
|
|
log.Println(err)
|
2010-05-03 23:54:43 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
fmt.Printf("'%c' glyph\n", c0)
|
|
|
|
fmt.Printf("AdvanceWidth:%d LeftSideBearing:%d\n", hm.AdvanceWidth, hm.LeftSideBearing)
|
|
|
|
printGlyph(g)
|
2015-08-20 06:07:51 +00:00
|
|
|
i1 := f.Index(c1)
|
2015-08-24 06:17:16 +00:00
|
|
|
fmt.Printf("\n'%c', '%c' Kern:%d\n", c0, c1, f.Kern(fupe, i0, i1))
|
2016-03-24 00:05:48 +00:00
|
|
|
|
|
|
|
fmt.Printf("\nThe numbers above are in FUnits.\n" +
|
|
|
|
"The numbers below are in 26.6 fixed point pixels, at 12pt and 72dpi.\n\n")
|
|
|
|
a := truetype.NewFace(f, &truetype.Options{
|
|
|
|
Size: 12,
|
|
|
|
DPI: 72,
|
|
|
|
})
|
|
|
|
fmt.Printf("%#v\n", a.Metrics())
|
2010-05-03 23:54:43 +00:00
|
|
|
}
|