166 lines
4.1 KiB
Go
166 lines
4.1 KiB
Go
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)
|
|
}
|