126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package sfnt_test
|
||
|
|
||
|
import (
|
||
|
"image"
|
||
|
"image/draw"
|
||
|
"log"
|
||
|
"os"
|
||
|
|
||
|
"golang.org/x/image/font/gofont/goregular"
|
||
|
"golang.org/x/image/font/sfnt"
|
||
|
"golang.org/x/image/math/fixed"
|
||
|
"golang.org/x/image/vector"
|
||
|
)
|
||
|
|
||
|
func ExampleRasterizeGlyph() {
|
||
|
const (
|
||
|
ppem = 32
|
||
|
width = 24
|
||
|
height = 32
|
||
|
originX = 0
|
||
|
originY = 28
|
||
|
)
|
||
|
|
||
|
f, err := sfnt.Parse(goregular.TTF)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Parse: %v", err)
|
||
|
}
|
||
|
var b sfnt.Buffer
|
||
|
x, err := f.GlyphIndex(&b, 'G')
|
||
|
if err != nil {
|
||
|
log.Fatalf("GlyphIndex: %v", err)
|
||
|
}
|
||
|
if x == 0 {
|
||
|
log.Fatalf("GlyphIndex: no glyph index found for the rune 'G'")
|
||
|
}
|
||
|
segments, err := f.LoadGlyph(&b, x, fixed.I(ppem), nil)
|
||
|
|
||
|
r := vector.NewRasterizer(width, height)
|
||
|
r.DrawOp = draw.Src
|
||
|
for _, seg := range segments {
|
||
|
// The divisions by 64 below is because the seg.Args values have type
|
||
|
// fixed.Int26_6, a 26.6 fixed point number, and 1<<6 == 64.
|
||
|
switch seg.Op {
|
||
|
case sfnt.SegmentOpMoveTo:
|
||
|
r.MoveTo(
|
||
|
originX+float32(seg.Args[0])/64,
|
||
|
originY-float32(seg.Args[1])/64,
|
||
|
)
|
||
|
case sfnt.SegmentOpLineTo:
|
||
|
r.LineTo(
|
||
|
originX+float32(seg.Args[0])/64,
|
||
|
originY-float32(seg.Args[1])/64,
|
||
|
)
|
||
|
case sfnt.SegmentOpQuadTo:
|
||
|
r.QuadTo(
|
||
|
originX+float32(seg.Args[0])/64,
|
||
|
originY-float32(seg.Args[1])/64,
|
||
|
originX+float32(seg.Args[2])/64,
|
||
|
originY-float32(seg.Args[3])/64,
|
||
|
)
|
||
|
case sfnt.SegmentOpCubeTo:
|
||
|
r.CubeTo(
|
||
|
originX+float32(seg.Args[0])/64,
|
||
|
originY-float32(seg.Args[1])/64,
|
||
|
originX+float32(seg.Args[2])/64,
|
||
|
originY-float32(seg.Args[3])/64,
|
||
|
originX+float32(seg.Args[4])/64,
|
||
|
originY-float32(seg.Args[5])/64,
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
// TODO: call ClosePath? Once overall or once per contour (i.e. MoveTo)?
|
||
|
|
||
|
dst := image.NewAlpha(image.Rect(0, 0, width, height))
|
||
|
r.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
|
||
|
|
||
|
const asciiArt = ".++8"
|
||
|
buf := make([]byte, 0, height*(width+1))
|
||
|
for y := 0; y < height; y++ {
|
||
|
for x := 0; x < width; x++ {
|
||
|
a := dst.AlphaAt(x, y).A
|
||
|
buf = append(buf, asciiArt[a>>6])
|
||
|
}
|
||
|
buf = append(buf, '\n')
|
||
|
}
|
||
|
os.Stdout.Write(buf)
|
||
|
|
||
|
// Output:
|
||
|
// ........................
|
||
|
// ........................
|
||
|
// ........................
|
||
|
// ........................
|
||
|
// ..........+++++++++.....
|
||
|
// .......+8888888888888+..
|
||
|
// ......8888888888888888..
|
||
|
// ....+8888+........++88..
|
||
|
// ....8888................
|
||
|
// ...8888.................
|
||
|
// ..+888+.................
|
||
|
// ..+888..................
|
||
|
// ..888+..................
|
||
|
// .+888+..................
|
||
|
// .+888...................
|
||
|
// .+888...................
|
||
|
// .+888...................
|
||
|
// .+888..........+++++++..
|
||
|
// .+888..........8888888..
|
||
|
// .+888+.........+++8888..
|
||
|
// ..888+............+888..
|
||
|
// ..8888............+888..
|
||
|
// ..+888+...........+888..
|
||
|
// ...8888+..........+888..
|
||
|
// ...+8888+.........+888..
|
||
|
// ....+88888+.......+888..
|
||
|
// .....+8888888888888888..
|
||
|
// .......+888888888888++..
|
||
|
// ..........++++++++......
|
||
|
// ........................
|
||
|
// ........................
|
||
|
// ........................
|
||
|
}
|