2010-04-02 01:07:24 +02: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 03:07:23 +02: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-04-02 01:07:24 +02:00
|
|
|
|
2016-04-10 07:05:36 +02:00
|
|
|
// +build example
|
2015-08-12 06:41:46 +02:00
|
|
|
//
|
|
|
|
// This build tag means that "go install github.com/golang/freetype/..."
|
2016-04-10 07:05:36 +02: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 06:41:46 +02:00
|
|
|
|
2010-04-02 01:07:24 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
|
|
|
"image"
|
2011-10-06 04:55:02 +02:00
|
|
|
"image/color"
|
2011-06-16 04:25:21 +02:00
|
|
|
"image/draw"
|
2010-04-02 01:07:24 +02:00
|
|
|
"image/png"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
|
2015-08-12 06:30:01 +02:00
|
|
|
"github.com/golang/freetype/raster"
|
2018-12-06 16:58:32 +01:00
|
|
|
"git.gutmet.org/golang-image.git/math/fixed"
|
2010-04-02 01:07:24 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type node struct {
|
|
|
|
x, y, degree int
|
|
|
|
}
|
|
|
|
|
2015-08-18 08:33:14 +02:00
|
|
|
// These contours "outside" and "inside" are from the 'A' glyph from the Droid
|
2010-04-02 01:07:24 +02:00
|
|
|
// Serif Regular font.
|
|
|
|
|
|
|
|
var outside = []node{
|
|
|
|
node{414, 489, 1},
|
|
|
|
node{336, 274, 2},
|
|
|
|
node{327, 250, 0},
|
|
|
|
node{322, 226, 2},
|
|
|
|
node{317, 203, 0},
|
|
|
|
node{317, 186, 2},
|
|
|
|
node{317, 134, 0},
|
|
|
|
node{350, 110, 2},
|
|
|
|
node{384, 86, 0},
|
|
|
|
node{453, 86, 1},
|
|
|
|
node{500, 86, 1},
|
|
|
|
node{500, 0, 1},
|
|
|
|
node{0, 0, 1},
|
|
|
|
node{0, 86, 1},
|
|
|
|
node{39, 86, 2},
|
|
|
|
node{69, 86, 0},
|
|
|
|
node{90, 92, 2},
|
|
|
|
node{111, 99, 0},
|
|
|
|
node{128, 117, 2},
|
|
|
|
node{145, 135, 0},
|
|
|
|
node{160, 166, 2},
|
|
|
|
node{176, 197, 0},
|
|
|
|
node{195, 246, 1},
|
|
|
|
node{649, 1462, 1},
|
|
|
|
node{809, 1462, 1},
|
|
|
|
node{1272, 195, 2},
|
|
|
|
node{1284, 163, 0},
|
|
|
|
node{1296, 142, 2},
|
|
|
|
node{1309, 121, 0},
|
|
|
|
node{1326, 108, 2},
|
|
|
|
node{1343, 96, 0},
|
|
|
|
node{1365, 91, 2},
|
|
|
|
node{1387, 86, 0},
|
|
|
|
node{1417, 86, 1},
|
|
|
|
node{1444, 86, 1},
|
|
|
|
node{1444, 0, 1},
|
|
|
|
node{881, 0, 1},
|
|
|
|
node{881, 86, 1},
|
|
|
|
node{928, 86, 2},
|
|
|
|
node{1051, 86, 0},
|
|
|
|
node{1051, 184, 2},
|
|
|
|
node{1051, 201, 0},
|
|
|
|
node{1046, 219, 2},
|
|
|
|
node{1042, 237, 0},
|
|
|
|
node{1034, 260, 1},
|
|
|
|
node{952, 489, 1},
|
|
|
|
node{414, 489, -1},
|
|
|
|
}
|
|
|
|
|
|
|
|
var inside = []node{
|
|
|
|
node{686, 1274, 1},
|
|
|
|
node{453, 592, 1},
|
|
|
|
node{915, 592, 1},
|
|
|
|
node{686, 1274, -1},
|
|
|
|
}
|
|
|
|
|
2015-08-17 02:26:09 +02:00
|
|
|
func p(n node) fixed.Point26_6 {
|
2010-04-02 01:07:24 +02:00
|
|
|
x, y := 20+n.x/4, 380-n.y/4
|
2015-08-17 02:26:09 +02:00
|
|
|
return fixed.Point26_6{
|
|
|
|
X: fixed.Int26_6(x << 6),
|
|
|
|
Y: fixed.Int26_6(y << 6),
|
2012-05-07 14:52:01 +02:00
|
|
|
}
|
2010-04-02 01:07:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func contour(r *raster.Rasterizer, ns []node) {
|
|
|
|
if len(ns) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
i := 0
|
|
|
|
r.Start(p(ns[i]))
|
|
|
|
for {
|
|
|
|
switch ns[i].degree {
|
|
|
|
case -1:
|
|
|
|
// -1 signifies end-of-contour.
|
|
|
|
return
|
|
|
|
case 1:
|
|
|
|
i += 1
|
2010-04-06 13:25:48 +02:00
|
|
|
r.Add1(p(ns[i]))
|
2010-04-02 01:07:24 +02:00
|
|
|
case 2:
|
|
|
|
i += 2
|
2010-04-06 13:25:48 +02:00
|
|
|
r.Add2(p(ns[i-1]), p(ns[i]))
|
2010-04-02 01:07:24 +02:00
|
|
|
default:
|
|
|
|
panic("bad degree")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func showNodes(m *image.RGBA, ns []node) {
|
|
|
|
for _, n := range ns {
|
|
|
|
p := p(n)
|
2015-08-17 02:26:09 +02:00
|
|
|
x, y := int(p.X)/64, int(p.Y)/64
|
2011-06-16 04:25:21 +02:00
|
|
|
if !(image.Point{x, y}).In(m.Bounds()) {
|
2010-04-02 01:07:24 +02:00
|
|
|
continue
|
|
|
|
}
|
2011-10-06 04:55:02 +02:00
|
|
|
var c color.Color
|
2010-04-02 01:07:24 +02:00
|
|
|
switch n.degree {
|
|
|
|
case 0:
|
2011-10-06 04:55:02 +02:00
|
|
|
c = color.RGBA{0, 255, 255, 255}
|
2010-04-02 01:07:24 +02:00
|
|
|
case 1:
|
2011-10-06 04:55:02 +02:00
|
|
|
c = color.RGBA{255, 0, 0, 255}
|
2010-04-02 01:07:24 +02:00
|
|
|
case 2:
|
2011-10-06 04:55:02 +02:00
|
|
|
c = color.RGBA{255, 0, 0, 255}
|
2010-04-02 01:07:24 +02:00
|
|
|
}
|
|
|
|
if c != nil {
|
|
|
|
m.Set(x, y, c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
// Rasterize the contours to a mask image.
|
|
|
|
const (
|
|
|
|
w = 400
|
|
|
|
h = 400
|
|
|
|
)
|
2010-05-14 05:29:53 +02:00
|
|
|
r := raster.NewRasterizer(w, h)
|
2010-04-02 01:07:24 +02:00
|
|
|
contour(r, outside)
|
|
|
|
contour(r, inside)
|
2011-09-14 14:02:41 +02:00
|
|
|
mask := image.NewAlpha(image.Rect(0, 0, w, h))
|
2010-10-12 07:55:01 +02:00
|
|
|
p := raster.NewAlphaSrcPainter(mask)
|
2010-05-14 05:29:53 +02:00
|
|
|
r.Rasterize(p)
|
2010-04-02 01:07:24 +02:00
|
|
|
|
|
|
|
// Draw the mask image (in gray) onto an RGBA image.
|
2011-09-14 14:02:41 +02:00
|
|
|
rgba := image.NewRGBA(image.Rect(0, 0, w, h))
|
2011-10-06 04:55:02 +02:00
|
|
|
gray := image.NewUniform(color.Alpha{0x1f})
|
2011-06-16 04:25:21 +02:00
|
|
|
draw.Draw(rgba, rgba.Bounds(), image.Black, image.ZP, draw.Src)
|
2010-08-27 02:47:48 +02:00
|
|
|
draw.DrawMask(rgba, rgba.Bounds(), gray, image.ZP, mask, image.ZP, draw.Over)
|
2010-04-02 01:07:24 +02:00
|
|
|
showNodes(rgba, outside)
|
|
|
|
showNodes(rgba, inside)
|
|
|
|
|
|
|
|
// Save that RGBA image to disk.
|
2015-08-20 08:07:51 +02:00
|
|
|
outFile, err := os.Create("out.png")
|
2010-04-02 01:07:24 +02:00
|
|
|
if err != nil {
|
2010-10-15 05:02:11 +02:00
|
|
|
log.Println(err)
|
2010-04-13 14:26:10 +02:00
|
|
|
os.Exit(1)
|
2010-04-02 01:07:24 +02:00
|
|
|
}
|
2015-08-20 08:07:51 +02:00
|
|
|
defer outFile.Close()
|
|
|
|
b := bufio.NewWriter(outFile)
|
2010-04-02 01:07:24 +02:00
|
|
|
err = png.Encode(b, rgba)
|
|
|
|
if err != nil {
|
2010-10-15 05:02:11 +02:00
|
|
|
log.Println(err)
|
2010-04-13 14:26:10 +02:00
|
|
|
os.Exit(1)
|
2010-04-02 01:07:24 +02:00
|
|
|
}
|
|
|
|
err = b.Flush()
|
|
|
|
if err != nil {
|
2010-10-15 05:02:11 +02:00
|
|
|
log.Println(err)
|
2010-04-13 14:26:10 +02:00
|
|
|
os.Exit(1)
|
2010-04-02 01:07:24 +02:00
|
|
|
}
|
|
|
|
fmt.Println("Wrote out.png OK.")
|
|
|
|
}
|