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 fontssubpath string } 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, fontssubpath} } func (f FileSvgStorage) Create(id string, svg io.Reader) (string, error) { file, err := os.Create(filepath.Join(f.basepath, id+".svg")) if err != nil { return "", err } defer file.Close() _, err = io.Copy(file, svg) if err != nil { return "", err } log.Println("Created File: ", file.Name()) return file.Name(), nil } func (f FileSvgStorage) Get(id string) (io.Reader, error) { file, err := os.Open(filepath.Join(f.basepath, "svg", id+".svg")) if err != nil { return nil, err } 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 }