-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtextpic.go
128 lines (113 loc) · 3.07 KB
/
textpic.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* Copyright © 2021 A Bunch Tell LLC.
*
* This file is part of text-pic.
*
* text-pic is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, included
* in the LICENSE file in this source code package.
*/
package textpic
import (
"fmt"
"image/color"
"path/filepath"
"github.com/fogleman/gg"
)
func loadFont(dc *gg.Context, fontFace string, bold bool, points float64) error {
fontBoldPath := filepath.Join("fonts", fontFace, fontFace+"-Bold.ttf")
fontRegularPath := filepath.Join("fonts", fontFace, fontFace+"-Regular.ttf")
path := fontRegularPath
if bold {
path = fontBoldPath
}
err := dc.LoadFontFace(path, points)
if err != nil {
return fmt.Errorf("load font: %s", err)
}
return nil
}
func GenerateImage(opt *ContentOptions, w, h int, outputFilename string) error {
wf := float64(w)
hf := float64(h)
dc := gg.NewContext(w, h)
dc.DrawRectangle(0, 0, wf, hf)
dc.SetRGB(1, 1, 1)
dc.Fill()
// Define margins for footer text
footerFontSize := 32.0
footerMargin := 20.0
x := footerMargin
y := footerMargin
footerMarginY := 20.0
// Content parameters
contentFontSize := 48.0
lineSpacing := 1.8
contentBottomMargin := 100.0
contentRightMargin := 50.0
contentTopMargin := 50.0
contentWidth := wf - contentRightMargin - contentRightMargin
// Create bold instance name
err := loadFont(dc, "Lora", true, footerFontSize)
if err != nil {
return err
}
instance := opt.Instance
baseTextWidth, textHeight := dc.MeasureString(instance)
// Create user path
err = loadFont(dc, "Lora", false, footerFontSize)
if err != nil {
return err
}
dc.SetColor(color.Black)
var userPath = ""
if opt.Username != "" {
userPath = "/" + opt.Username
}
userTextWidth, _ := dc.MeasureString(userPath)
// x = canvas halfway point - total text width halfway point
x = wf/2 - (baseTextWidth+userTextWidth)/2
y = hf - textHeight - footerMarginY
err = loadFont(dc, "Lora", true, footerFontSize)
if err != nil {
return err
}
dc.DrawString(instance, x, y)
// x = original x coordinate + base text width
x += baseTextWidth
y = hf - textHeight - footerMarginY
err = loadFont(dc, "Lora", false, footerFontSize)
if err != nil {
return err
}
dc.DrawString(userPath, x, y)
// Draw the content
err = loadFont(dc, fonts[opt.UserFont], false, contentFontSize)
if err != nil {
return err
}
s := opt.Content
lines := dc.WordWrap(s, contentWidth)
// Center-align text by default for short content
alignment := gg.AlignCenter
linesStr := ""
for i, str := range lines {
linesStr += str
if i != len(lines)-1 {
linesStr += "\n"
if alignment == gg.AlignCenter {
// Since content uses multiple lines, left-align it.
alignment = gg.AlignLeft
}
}
}
_, contentTextHeight := dc.MeasureMultilineString(linesStr, lineSpacing)
x = contentRightMargin
y = contentTopMargin - contentBottomMargin + hf/2 - contentTextHeight/2
dc.DrawStringWrapped(s, x, y, 0, 0, contentWidth, lineSpacing, alignment)
err = dc.SavePNG(outputFilename)
if err != nil {
return fmt.Errorf("save png: %s", err)
}
return nil
}