-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautoText2pictrue.go
109 lines (87 loc) · 2.59 KB
/
autoText2pictrue.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 text2picture
import (
"bytes"
"image"
"image/draw"
"github.com/golang/freetype"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)
type autoPicture struct {
width int
dpi float64
font *truetype.Font
// font size in points
fontSize float64
line_spacing int
face font.Face
// text left and right padding
padding int
rgba *image.RGBA
pt fixed.Point26_6
c *freetype.Context
}
func AutoNewPicture(width int, dpi float64, padding int, fontSize float64) *autoPicture {
p := autoPicture{width: width, dpi: dpi, padding: padding, fontSize: fontSize, font: defaultFont}
p.rgba = NewColorPicture(width, fixed.Int26_6(fontSize*dpi*(64.0/72.0)*1.2).Round(), Transparent)
p.c = freetype.NewContext()
p.c.SetDPI(p.dpi)
p.c.SetClip(p.rgba.Bounds())
p.c.SetDst(p.rgba)
p.c.SetHinting(font.HintingFull)
p.c.SetFont(p.font)
p.c.SetFontSize(p.fontSize)
p.face = truetype.NewFace(p.font, &truetype.Options{Size: p.fontSize, DPI: p.dpi})
p.pt = freetype.Pt(padding, p.c.PointToFixed(fontSize).Round())
return &p
}
// Set line spacing (line height)
func (p *autoPicture) SetLineSpacing(line_spacing int) *autoPicture {
p.line_spacing = line_spacing
return p
}
func (p *autoPicture) NextLineDistance() int {
return p.c.PointToFixed(p.fontSize + float64(p.line_spacing)).Round()
}
func (p *autoPicture) Draw(text string) *autoPicture {
// font color
p.c.SetSrc(Black)
p.handleText(&text)
return p
}
func (p *autoPicture) handleText(text *string) {
for _, x := range *text {
w, _ := p.face.GlyphAdvance(x)
if x == '\n' {
p.newline()
continue
} else if x == '\t' {
x = ' '
} else if p.font.Index(x) == 0 {
continue
} else if p.pt.X.Round()+w.Round() > p.rgba.Bounds().Max.X-p.padding {
p.newline()
}
p.pt, _ = p.c.DrawString(string(x), p.pt)
}
}
func (p *autoPicture) newline() {
if p.pt.Y.Round()+p.NextLineDistance() > p.rgba.Bounds().Max.Y {
p.addnewline()
}
p.pt.X = fixed.Int26_6(p.padding) << 6
p.pt.Y += p.c.PointToFixed(p.fontSize + float64(p.line_spacing))
}
func (p *autoPicture) addnewline() {
rgba := NewColorPicture(p.width, p.pt.Y.Round()+fixed.Int26_6((p.fontSize+float64(p.line_spacing))*p.dpi*(64.0/72.0)*1.2).Round(), Transparent)
draw.Draw(rgba, p.rgba.Rect, p.rgba, p.rgba.Rect.Min, draw.Src)
p.rgba = rgba
p.c.SetClip(p.rgba.Bounds())
p.c.SetDst(p.rgba)
}
func (p *autoPicture) GeneratePicture() (*bytes.Buffer, error) {
src := NewColorPicture(p.rgba.Bounds().Max.X, p.rgba.Bounds().Max.Y, image.White)
draw.Draw(src, p.rgba.Rect, p.rgba, p.rgba.Rect.Min, draw.Over)
return saveImage(src)
}