✨ initial commit
This commit is contained in:
BIN
font/JetBrainsMono-Regular.ttf
Normal file
BIN
font/JetBrainsMono-Regular.ttf
Normal file
Binary file not shown.
BIN
font/JetBrainsMonoNL-Regular.ttf
Normal file
BIN
font/JetBrainsMonoNL-Regular.ttf
Normal file
Binary file not shown.
165
font/font.go
Normal file
165
font/font.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package font
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
formatter "github.com/alecthomas/chroma/v2/formatters/svg"
|
||||
)
|
||||
|
||||
//go:embed *.ttf
|
||||
var fonts embed.FS
|
||||
|
||||
// JetBrainsMonoTTF contains the JetBrains Mono font data
|
||||
var JetBrainsMonoTTF []byte
|
||||
|
||||
// JetBrainsMonoNLTTF contains the JetBrains Mono NL font data
|
||||
var JetBrainsMonoNLTTF []byte
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
JetBrainsMonoTTF, err = fonts.ReadFile("JetBrainsMono-Regular.ttf")
|
||||
if err != nil {
|
||||
// If embedded font is not available, use empty slice
|
||||
JetBrainsMonoTTF = []byte{}
|
||||
}
|
||||
|
||||
JetBrainsMonoNLTTF, err = fonts.ReadFile("JetBrainsMonoNL-Regular.ttf")
|
||||
if err != nil {
|
||||
// If embedded font is not available, use empty slice
|
||||
JetBrainsMonoNLTTF = []byte{}
|
||||
}
|
||||
}
|
||||
|
||||
// FontOptions creates formatter options for the given font configuration
|
||||
func FontOptions(family string, size float64, ligatures bool, fontFile string) ([]formatter.Option, error) {
|
||||
var options []formatter.Option
|
||||
|
||||
// Set font family
|
||||
if family != "" {
|
||||
options = append(options, formatter.FontFamily(family))
|
||||
}
|
||||
|
||||
// Embed font file if specified
|
||||
if fontFile != "" {
|
||||
option, err := formatter.EmbedFontFile(family, fontFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to embed font file: %w", err)
|
||||
}
|
||||
options = append(options, option)
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// GetDefaultFontFamily returns the default font family
|
||||
func GetDefaultFontFamily() string {
|
||||
return "JetBrains Mono"
|
||||
}
|
||||
|
||||
// GetDefaultFontSize returns the default font size
|
||||
func GetDefaultFontSize() float64 {
|
||||
return 14.0
|
||||
}
|
||||
|
||||
// IsMonospaceFont checks if a font family is monospace
|
||||
func IsMonospaceFont(family string) bool {
|
||||
monospaceFonts := map[string]bool{
|
||||
"JetBrains Mono": true,
|
||||
"Fira Code": true,
|
||||
"Source Code Pro": true,
|
||||
"Monaco": true,
|
||||
"Menlo": true,
|
||||
"Consolas": true,
|
||||
"Courier New": true,
|
||||
"monospace": true,
|
||||
"SF Mono": true,
|
||||
"Cascadia Code": true,
|
||||
"Ubuntu Mono": true,
|
||||
"DejaVu Sans Mono": true,
|
||||
"Liberation Mono": true,
|
||||
"Inconsolata": true,
|
||||
"Roboto Mono": true,
|
||||
}
|
||||
return monospaceFonts[family]
|
||||
}
|
||||
|
||||
// ValidateFontFamily validates if a font family name is valid
|
||||
func ValidateFontFamily(family string) error {
|
||||
if family == "" {
|
||||
return fmt.Errorf("font family cannot be empty")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateFontSize validates if a font size is valid
|
||||
func ValidateFontSize(size float64) error {
|
||||
if size <= 0 {
|
||||
return fmt.Errorf("font size must be positive, got %.2f", size)
|
||||
}
|
||||
if size > 100 {
|
||||
return fmt.Errorf("font size too large, got %.2f", size)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFontHeightToWidthRatio returns the typical height to width ratio for monospace fonts
|
||||
func GetFontHeightToWidthRatio() float64 {
|
||||
return 1.68
|
||||
}
|
||||
|
||||
// CalculateTextWidth estimates the width of text in pixels
|
||||
func CalculateTextWidth(text string, fontSize float64) float64 {
|
||||
return float64(len(text)) * (fontSize / GetFontHeightToWidthRatio())
|
||||
}
|
||||
|
||||
// CalculateLineHeight calculates the line height in pixels
|
||||
func CalculateLineHeight(fontSize, lineHeightRatio float64) float64 {
|
||||
return fontSize * lineHeightRatio
|
||||
}
|
||||
|
||||
// GetEmbeddedFontData returns embedded font data if available
|
||||
func GetEmbeddedFontData(fontName string) []byte {
|
||||
switch fontName {
|
||||
case "JetBrains Mono", "JetBrainsMono":
|
||||
return JetBrainsMonoTTF
|
||||
case "JetBrains Mono NL", "JetBrainsMonoNL":
|
||||
return JetBrainsMonoNLTTF
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// FontConfig represents font configuration
|
||||
type FontConfig struct {
|
||||
Family string
|
||||
Size float64
|
||||
Ligatures bool
|
||||
File string
|
||||
}
|
||||
|
||||
// NewFontConfig creates a new font configuration with defaults
|
||||
func NewFontConfig() *FontConfig {
|
||||
return &FontConfig{
|
||||
Family: GetDefaultFontFamily(),
|
||||
Size: GetDefaultFontSize(),
|
||||
Ligatures: true,
|
||||
File: "",
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates the font configuration
|
||||
func (fc *FontConfig) Validate() error {
|
||||
if err := ValidateFontFamily(fc.Family); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ValidateFontSize(fc.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToFormatterOptions converts font config to formatter options
|
||||
func (fc *FontConfig) ToFormatterOptions() ([]formatter.Option, error) {
|
||||
return FontOptions(fc.Family, fc.Size, fc.Ligatures, fc.File)
|
||||
}
|
Reference in New Issue
Block a user