Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
2.7 kB · 111 lines
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112package media
import ( "bytes" "fmt" "image" "image/color" "image/draw" "image/png" "io" "strings"
"github.com/golang/freetype" "github.com/golang/freetype/truetype" "golang.org/x/image/font" "stream.place/streamplace/js/app")
type TextRenderer struct { font *truetype.Font}
func NewTextRenderer() (*TextRenderer, error) { font, err := loadFont() if err != nil { return nil, err } return &TextRenderer{font: font}, nil}
func loadFont() (*truetype.Font, error) { entries, err := app.AllFiles.ReadDir("dist/assets/assets/fonts") if err != nil { return nil, err } var fontFile string for _, entry := range entries { if strings.HasPrefix(entry.Name(), "AtkinsonHyperlegibleM") { fontFile = fmt.Sprintf("dist/assets/assets/fonts/%s", entry.Name()) break } } if fontFile == "" { return nil, fmt.Errorf("could not find AtkinsonHyperlegibleMono-Regular font") } fd, err := app.AllFiles.Open(fontFile) if err != nil { return nil, err } fontBytes, err := io.ReadAll(fd) if err != nil { return nil, err } f, err := freetype.ParseFont(fontBytes) if err != nil { return nil, err } return f, nil}
func (tr *TextRenderer) GenerateImage(textContent string, fgColorHex string, bgColorHex string, fontSize float64) ([]byte, error) { fgColor := color.RGBA{0xff, 0xff, 0xff, 0xff} if len(fgColorHex) == 7 { _, err := fmt.Sscanf(fgColorHex, "#%02x%02x%02x", &fgColor.R, &fgColor.G, &fgColor.B) if err != nil { return nil, err } }
bgColor := color.RGBA{0x30, 0x0a, 0x24, 0xcc} if len(bgColorHex) == 7 { _, err := fmt.Sscanf(bgColorHex, "#%02x%02x%02x", &bgColor.R, &bgColor.G, &bgColor.B) if err != nil { return nil, err } }
code := strings.ReplaceAll(textContent, "\t", " ") // convert tabs into spaces text := strings.Split(code, "\n") // split newlines into arrays
fg := image.NewUniform(fgColor) bg := image.NewUniform(bgColor) rgba := image.NewRGBA(image.Rect(0, 0, 540, 55)) draw.Draw(rgba, rgba.Bounds(), bg, image.Pt(0, 0), draw.Src) c := freetype.NewContext() c.SetDPI(72) c.SetFont(tr.font) c.SetFontSize(fontSize) c.SetClip(rgba.Bounds()) c.SetDst(rgba) c.SetSrc(fg) c.SetHinting(font.HintingNone)
textXOffset := 10 textYOffset := 5 + int(c.PointToFixed(fontSize)>>6) // Note shift/truncate 6 bits first
pt := freetype.Pt(textXOffset, textYOffset) for _, s := range text { _, err := c.DrawString(strings.ReplaceAll(s, "\r", ""), pt) if err != nil { return nil, err } pt.Y += c.PointToFixed(fontSize * 1.5) }
b := new(bytes.Buffer) if err := png.Encode(b, rgba); err != nil { return nil, err } return b.Bytes(), nil}