-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
png.go
109 lines (98 loc) · 2.64 KB
/
png.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package fonts
import (
"errors"
"log"
"github.com/fogleman/gg"
)
func SavePNG(filename string, width, height int, renders ...*Render) error {
if len(renders) == 0 {
return errors.New("must have at least one render")
}
mbb := MBB{}
for i, render := range renders {
if i == 0 {
mbb = render.MBB
} else {
mbb.Join(&render.MBB)
}
}
var scale float64
scale, width, height = maximize(&mbb, width, height)
log.Printf("MBB: %v, scale=%.2f, size=(%v,%v)", mbb, scale, width, height)
dc := gg.NewContext(width, height)
background(dc, renders[0])
dc.Clear()
for _, r := range renders {
for _, poly := range r.Polygons {
if poly.Dark {
foreground(dc, r)
} else {
background(dc, r)
}
for i, pt := range poly.Pts {
if i == 0 {
dc.MoveTo(scale*(pt[0]-mbb.Min[0]), float64(height)-scale*(pt[1]-mbb.Min[1]))
} else {
dc.LineTo(scale*(pt[0]-mbb.Min[0]), float64(height)-scale*(pt[1]-mbb.Min[1]))
}
}
dc.Fill()
}
}
return dc.SavePNG(filename)
}
func background(dc *gg.Context, render *Render) {
const max = 0xffff
if render.Background != nil {
r, g, b, a := render.Background.RGBA()
dc.SetRGBA(float64(r)/max, float64(g)/max, float64(b)/max, float64(a)/max)
} else {
dc.SetRGB(1, 1, 1)
}
}
func foreground(dc *gg.Context, render *Render) {
const max = 0xffff
if render.Foreground != nil {
r, g, b, a := render.Foreground.RGBA()
dc.SetRGBA(float64(r)/max, float64(g)/max, float64(b)/max, float64(a)/max)
} else {
dc.SetRGB(0, 0, 0)
}
}
func maximize(mbb *MBB, width, height int) (float64, int, int) {
scale := float64(width) / (mbb.Max[0] - mbb.Min[0])
if yScale := float64(height) / (mbb.Max[1] - mbb.Min[1]); yScale < scale {
scale = yScale
width = int(0.5 + scale*(mbb.Max[0]-mbb.Min[0]))
} else {
height = int(0.5 + scale*(mbb.Max[1]-mbb.Min[1]))
}
return scale, width, height
}
func (r *Render) SavePNG(filename string, width, height int) error {
var scale float64
scale, width, height = maximize(&r.MBB, width, height)
log.Printf("MBB: %v, scale=%.2f, size=(%v,%v)", r.MBB, scale, width, height)
dc := gg.NewContext(width, height)
background(dc, r)
dc.Clear()
r.RenderToDC(dc, 0, 0, scale, height)
return dc.SavePNG(filename)
}
func (r *Render) RenderToDC(dc *gg.Context, dx, dy, scale float64, height int) {
for _, poly := range r.Polygons {
if poly.Dark {
foreground(dc, r)
} else {
background(dc, r)
}
for i, pt := range poly.Pts {
if i == 0 {
dc.MoveTo(dx+scale*(pt[0]-r.MBB.Min[0]), dy+float64(height)-scale*(pt[1]-r.MBB.Min[1]))
} else {
dc.LineTo(dx+scale*(pt[0]-r.MBB.Min[0]), dy+float64(height)-scale*(pt[1]-r.MBB.Min[1]))
}
}
dc.Fill()
}
}