From 7a9cf7ab9357cf3fe6c1d747c7dc9b0d63a46200 Mon Sep 17 00:00:00 2001 From: Tueem Date: Thu, 12 Feb 2026 14:16:37 +0100 Subject: [PATCH] feat(fonts): add fonts storage --- go.mod | 4 +- go.sum | 4 ++ internal/command/commandline.go | 2 +- internal/routes/font.go | 12 +++++ pkg/svg/storage.go | 77 +++++++++++++++++++++++++++++++-- 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 internal/routes/font.go diff --git a/go.mod b/go.mod index 231ae21..cbc3ca9 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,13 @@ go 1.24.9 require ( github.com/dustin/go-humanize v1.0.1 // indirect - github.com/glebarez/go-sqlite v1.22.0 // indirect + github.com/glebarez/go-sqlite v1.22.0 github.com/google/uuid v1.5.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/image v0.36.0 golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.34.0 // indirect modernc.org/libc v1.37.6 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.7.2 // indirect diff --git a/go.sum b/go.sum index 6c1a0f6..0d3af12 100644 --- a/go.sum +++ b/go.sum @@ -8,9 +8,13 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc= +golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= diff --git a/internal/command/commandline.go b/internal/command/commandline.go index 32b528b..d6ba717 100644 --- a/internal/command/commandline.go +++ b/internal/command/commandline.go @@ -30,7 +30,7 @@ func HandleCommandline() { } else if help { flag.PrintDefaults() } else { - svg.Storage = svg.NewFileStorage(datapath) + svg.Storage = svg.NewFileStorage(datapath, "fonts") server.PrepareHTTP() server.Start() } diff --git a/internal/routes/font.go b/internal/routes/font.go new file mode 100644 index 0000000..89fa75f --- /dev/null +++ b/internal/routes/font.go @@ -0,0 +1,12 @@ +package routes + +import "net/http" + +func AddFont(w http.ResponseWriter, r *http.Request) { + + if r.Header.Get("Content-Type") != "font/ttf" { + http.Error(w, "", http.StatusUnsupportedMediaType) + return + } + +} diff --git a/pkg/svg/storage.go b/pkg/svg/storage.go index 0531469..93e9cd8 100644 --- a/pkg/svg/storage.go +++ b/pkg/svg/storage.go @@ -1,28 +1,40 @@ package svg import ( + "errors" "io" "log" "os" "path/filepath" + "strings" + + "golang.org/x/image/font/sfnt" ) type SvgStorage interface { Create(id string, svg io.Reader) (string, error) Get(id string) (io.Reader, error) + AddFont(reader io.Reader, format string) error + GetFonts() ([]string, error) + GetFontsDir() (string, error) } type FileSvgStorage struct { - basepath string + basepath string + fontssubpath string } -func NewFileStorage(path string) *FileSvgStorage { +func NewFileStorage(path string, fontssubpath string) *FileSvgStorage { err := os.MkdirAll(path, 0755) if err != nil { panic(err) } + err = os.MkdirAll(filepath.Join(path, fontssubpath), 0755) + if err != nil { + panic(err) + } log.Println("Initialized file storage handler") - return &FileSvgStorage{path} + return &FileSvgStorage{path, fontssubpath} } func (f FileSvgStorage) Create(id string, svg io.Reader) (string, error) { @@ -49,3 +61,62 @@ func (f FileSvgStorage) Get(id string) (io.Reader, error) { } return file, nil } + +func (f FileSvgStorage) AddFont(fontreader io.Reader, format string) error { + fontblob, err := io.ReadAll(fontreader) + if err != nil { + return err + } + if format != "ttf" && format != "otf" { + return errors.New("Format not supported") + } + file, err := os.CreateTemp(filepath.Join(f.basepath, f.fontssubpath), "*."+format) + if err != nil { + return err + } + defer file.Close() + file.Write(fontblob) + return nil +} + +func (f FileSvgStorage) GetFonts() ([]string, error) { + path := filepath.Join(f.basepath, f.fontssubpath) + entries, err := os.ReadDir(path) + if err != nil { + return nil, err + } + fonts := make([]string, len(entries)) + for i, entry := range entries { + if entry.IsDir() { + continue + } + if strings.HasSuffix(entry.Name(), ".ttf") || strings.HasSuffix(entry.Name(), ".otf") { + fontblob, err := os.ReadFile(filepath.Join(path, entry.Name())) + if err != nil { + return nil, err + } + fontname, err := getFontName(fontblob) + if err != nil { + return nil, err + } + fonts[i] = fontname + } + } + return fonts, nil +} + +func (f FileSvgStorage) GetFontsDir() (string, error) { + return filepath.Join(f.basepath, f.fontssubpath), nil +} + +func getFontName(svgblob []byte) (string, error) { + font, err := sfnt.Parse(svgblob) + if err != nil { + return "", err + } + name, err := font.Name(nil, sfnt.NameIDFull) + if err != nil { + return "", err + } + return name, nil +}