mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-26 11:34:04 -08:00
feat(image): cache font instead of embedding
This commit is contained in:
parent
b51d1de205
commit
0f7c10328f
|
@ -85,12 +85,18 @@ Exports the config to an image file using customized output options.`,
|
||||||
BgColor: bgColor,
|
BgColor: bgColor,
|
||||||
Ansi: writer,
|
Ansi: writer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if outputImage != "" {
|
if outputImage != "" {
|
||||||
imageCreator.Path = cleanOutputPath(outputImage, env)
|
imageCreator.Path = cleanOutputPath(outputImage, env)
|
||||||
}
|
}
|
||||||
imageCreator.Init(env.Flags().Config)
|
|
||||||
err := imageCreator.SavePNG()
|
|
||||||
|
|
||||||
|
err := imageCreator.Init(env)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Print(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imageCreator.SavePNG()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err.Error())
|
fmt.Print(err.Error())
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -23,14 +23,20 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||||
|
fontCLI "github.com/jandedobbeleer/oh-my-posh/src/font"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
||||||
|
|
||||||
"github.com/esimov/stackblur-go"
|
"github.com/esimov/stackblur-go"
|
||||||
|
@ -74,15 +80,6 @@ const (
|
||||||
link = "link"
|
link = "link"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed font/Hack-Nerd-Bold.ttf
|
|
||||||
var hackBold []byte
|
|
||||||
|
|
||||||
//go:embed font/Hack-Nerd-Regular.ttf
|
|
||||||
var hackRegular []byte
|
|
||||||
|
|
||||||
//go:embed font/Hack-Nerd-Italic.ttf
|
|
||||||
var hackItalic []byte
|
|
||||||
|
|
||||||
type RGB struct {
|
type RGB struct {
|
||||||
r int
|
r int
|
||||||
g int
|
g int
|
||||||
|
@ -109,6 +106,8 @@ type ImageRenderer struct {
|
||||||
BgColor string
|
BgColor string
|
||||||
Ansi *ansi.Writer
|
Ansi *ansi.Writer
|
||||||
|
|
||||||
|
env platform.Environment
|
||||||
|
|
||||||
Path string
|
Path string
|
||||||
|
|
||||||
factor float64
|
factor float64
|
||||||
|
@ -139,40 +138,35 @@ type ImageRenderer struct {
|
||||||
ansiSequenceRegexMap map[string]string
|
ansiSequenceRegexMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ir *ImageRenderer) Init(config string) {
|
func (ir *ImageRenderer) Init(env platform.Environment) error {
|
||||||
|
ir.env = env
|
||||||
|
|
||||||
if ir.Path == "" {
|
if ir.Path == "" {
|
||||||
match := regex.FindNamedRegexMatch(`.*(\/|\\)(?P<STR>.+)\.(json|yaml|yml|toml)`, config)
|
match := regex.FindNamedRegexMatch(`.*(\/|\\)(?P<STR>.+)\.(json|yaml|yml|toml)`, env.Flags().Config)
|
||||||
ir.Path = fmt.Sprintf("%s.png", strings.TrimSuffix(match[str], ".omp"))
|
ir.Path = fmt.Sprintf("%s.png", strings.TrimSuffix(match[str], ".omp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
f := 2.0
|
|
||||||
|
|
||||||
ir.cleanContent()
|
ir.cleanContent()
|
||||||
|
|
||||||
fontRegular, _ := truetype.Parse(hackRegular)
|
if err := ir.loadFonts(); err != nil {
|
||||||
fontBold, _ := truetype.Parse(hackBold)
|
return err
|
||||||
fontItalic, _ := truetype.Parse(hackItalic)
|
}
|
||||||
fontFaceOptions := &truetype.Options{Size: f * 12, DPI: 144}
|
|
||||||
|
|
||||||
ir.defaultForegroundColor = &RGB{255, 255, 255}
|
ir.defaultForegroundColor = &RGB{255, 255, 255}
|
||||||
ir.defaultBackgroundColor = &RGB{21, 21, 21}
|
ir.defaultBackgroundColor = &RGB{21, 21, 21}
|
||||||
|
|
||||||
ir.factor = f
|
ir.factor = 2.0
|
||||||
|
|
||||||
ir.columns = 80
|
ir.columns = 80
|
||||||
ir.rows = 25
|
ir.rows = 25
|
||||||
|
|
||||||
ir.margin = f * 48
|
ir.margin = ir.factor * 48
|
||||||
ir.padding = f * 24
|
ir.padding = ir.factor * 24
|
||||||
|
|
||||||
ir.shadowBaseColor = "#10101066"
|
ir.shadowBaseColor = "#10101066"
|
||||||
ir.shadowRadius = uint8(math.Min(f*16, 255))
|
ir.shadowRadius = uint8(math.Min(ir.factor*16, 255))
|
||||||
ir.shadowOffsetX = f * 16
|
ir.shadowOffsetX = ir.factor * 16
|
||||||
ir.shadowOffsetY = f * 16
|
ir.shadowOffsetY = ir.factor * 16
|
||||||
|
|
||||||
ir.regular = truetype.NewFace(fontRegular, fontFaceOptions)
|
|
||||||
ir.bold = truetype.NewFace(fontBold, fontFaceOptions)
|
|
||||||
ir.italic = truetype.NewFace(fontItalic, fontFaceOptions)
|
|
||||||
ir.lineSpacing = 1.2
|
ir.lineSpacing = 1.2
|
||||||
|
|
||||||
ir.ansiSequenceRegexMap = map[string]string{
|
ir.ansiSequenceRegexMap = map[string]string{
|
||||||
|
@ -198,6 +192,81 @@ func (ir *ImageRenderer) Init(config string) {
|
||||||
consoleTitle: `^(?P<STR>\x1b\]0;(.+)\007)`,
|
consoleTitle: `^(?P<STR>\x1b\]0;(.+)\007)`,
|
||||||
link: fmt.Sprintf(`^%s`, regex.LINK),
|
link: fmt.Sprintf(`^%s`, regex.LINK),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ir *ImageRenderer) loadFonts() error {
|
||||||
|
var data []byte
|
||||||
|
|
||||||
|
fontCachePath := filepath.Join(ir.env.CachePath(), "Hack.zip")
|
||||||
|
if _, err := os.Stat(fontCachePath); err == nil {
|
||||||
|
data, _ = os.ReadFile(fontCachePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download font if not cached
|
||||||
|
if data == nil {
|
||||||
|
url := "https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Hack.zip"
|
||||||
|
var err error
|
||||||
|
|
||||||
|
data, err = fontCLI.Download(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(fontCachePath, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesReader := bytes.NewReader(data)
|
||||||
|
zipReader, err := zip.NewReader(bytesReader, int64(bytesReader.Len()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fontFaceOptions := &truetype.Options{Size: 2.0 * 12, DPI: 144}
|
||||||
|
|
||||||
|
parseFont := func(file *zip.File) (font.Face, error) {
|
||||||
|
rc, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rc.Close()
|
||||||
|
|
||||||
|
data, err := io.ReadAll(rc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
font, err := truetype.Parse(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return truetype.NewFace(font, fontFaceOptions), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range zipReader.File {
|
||||||
|
switch file.Name {
|
||||||
|
case "HackNerdFont-Regular.ttf":
|
||||||
|
if regular, err := parseFont(file); err == nil {
|
||||||
|
ir.regular = regular
|
||||||
|
}
|
||||||
|
case "HackNerdFont-Bold.ttf":
|
||||||
|
if bold, err := parseFont(file); err == nil {
|
||||||
|
ir.bold = bold
|
||||||
|
}
|
||||||
|
case "HackNerdFont-Italic.ttf":
|
||||||
|
if italic, err := parseFont(file); err == nil {
|
||||||
|
ir.italic = italic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ir *ImageRenderer) fontHeight() float64 {
|
func (ir *ImageRenderer) fontHeight() float64 {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -33,13 +34,21 @@ func runImageTest(config, content string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer os.Remove(file.Name())
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
writer := &ansi.Writer{}
|
writer := &ansi.Writer{}
|
||||||
writer.Init(shell.GENERIC)
|
writer.Init(shell.GENERIC)
|
||||||
image := &ImageRenderer{
|
image := &ImageRenderer{
|
||||||
AnsiString: content,
|
AnsiString: content,
|
||||||
Ansi: writer,
|
Ansi: writer,
|
||||||
}
|
}
|
||||||
image.Init(config)
|
|
||||||
|
env := &platform.Shell{
|
||||||
|
CmdFlags: &platform.Flags{
|
||||||
|
Config: config,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = image.Init(env)
|
||||||
err = image.SavePNG()
|
err = image.SavePNG()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
os.Remove(image.Path)
|
os.Remove(image.Path)
|
||||||
|
|
Loading…
Reference in a new issue