mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-17 22:14:53 +02:00
Load font variable data on demand
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/tty"
|
||||
@@ -36,6 +37,20 @@ func to_kitty(v any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var query_kitty_lock sync.Mutex
|
||||
|
||||
func query_kitty(action string, cmd map[string]any, result any) error {
|
||||
query_kitty_lock.Lock()
|
||||
defer query_kitty_lock.Unlock()
|
||||
if action != "" {
|
||||
cmd["action"] = action
|
||||
if err := to_kitty(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return json_decode(result)
|
||||
}
|
||||
|
||||
func main() (rc int, err error) {
|
||||
json_decoder = json.NewDecoder(os.Stdin)
|
||||
lp, err := loop.New()
|
||||
|
||||
@@ -2,6 +2,7 @@ package list_fonts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
@@ -42,6 +43,15 @@ type MultiAxisStyle struct {
|
||||
Values []AxisValue `json:"values"`
|
||||
}
|
||||
|
||||
type ListedFont struct {
|
||||
Family string `json:"family"`
|
||||
Fullname string `json:"full_name"`
|
||||
Postscript_name string `json:"postscript_name"`
|
||||
Is_monospace bool `json:"is_monospace"`
|
||||
Is_variable bool `json:"is_variable"`
|
||||
Descriptor map[string]any `json:"descriptor"`
|
||||
}
|
||||
|
||||
type VariableData struct {
|
||||
Axes []VariableAxis `json:"axes"`
|
||||
Named_styles []NamedStyle `json:"named_styles"`
|
||||
@@ -51,12 +61,68 @@ type VariableData struct {
|
||||
Multi_axis_styles []MultiAxisStyle `json:"multi_axis_styles"`
|
||||
}
|
||||
|
||||
type ListedFont struct {
|
||||
Family string `json:"family"`
|
||||
Fullname string `json:"full_name"`
|
||||
Postscript_name string `json:"postscript_name"`
|
||||
Is_monospace bool `json:"is_monospace"`
|
||||
Is_variable bool `json:"is_variable"`
|
||||
Variable_data VariableData `json:"variable_data"`
|
||||
Descriptor map[string]any `json:"descriptor"`
|
||||
var variable_data_cache map[string]VariableData
|
||||
var variable_data_cache_mutex sync.Mutex
|
||||
|
||||
func (f ListedFont) cache_key() string {
|
||||
key := f.Postscript_name
|
||||
if key == "" {
|
||||
key = "path:" + f.Descriptor["path"].(string)
|
||||
} else {
|
||||
key = "psname:" + key
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func ensure_variable_data_for_fonts(fonts ...ListedFont) error {
|
||||
descriptors := make([]map[string]any, 0, len(fonts))
|
||||
keys := make([]string, 0, len(fonts))
|
||||
variable_data_cache_mutex.Lock()
|
||||
for _, f := range fonts {
|
||||
key := f.cache_key()
|
||||
if _, found := variable_data_cache[key]; !found {
|
||||
descriptors = append(descriptors, f.Descriptor)
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
variable_data_cache_mutex.Unlock()
|
||||
var data []VariableData
|
||||
if err := query_kitty("read_variable_data", map[string]any{"descriptors": descriptors}, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
variable_data_cache_mutex.Lock()
|
||||
for i, key := range keys {
|
||||
variable_data_cache[key] = data[i]
|
||||
}
|
||||
variable_data_cache_mutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func initialize_variable_data_cache() {
|
||||
variable_data_cache = make(map[string]VariableData)
|
||||
}
|
||||
|
||||
func _cached_vd(key string) (ans VariableData, found bool) {
|
||||
variable_data_cache_mutex.Lock()
|
||||
defer variable_data_cache_mutex.Unlock()
|
||||
ans, found = variable_data_cache[key]
|
||||
return
|
||||
}
|
||||
|
||||
func variable_data_for(f ListedFont) VariableData {
|
||||
key := f.cache_key()
|
||||
ans, found := _cached_vd(key)
|
||||
if found {
|
||||
return ans
|
||||
}
|
||||
if err := ensure_variable_data_for_fonts(f); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ans, found = _cached_vd(key)
|
||||
return ans
|
||||
}
|
||||
|
||||
func has_variable_data_for_font(font ListedFont) bool {
|
||||
_, found := _cached_vd(font.cache_key())
|
||||
return found
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ type handler struct {
|
||||
err_in_worker_thread error
|
||||
|
||||
// Listing
|
||||
rl *readline.Readline
|
||||
family_list FamilyList
|
||||
rl *readline.Readline
|
||||
family_list FamilyList
|
||||
variable_data_requested_for *utils.Set[string]
|
||||
}
|
||||
|
||||
func (h *handler) set_worker_error(err error) {
|
||||
@@ -77,6 +78,22 @@ func (h *handler) draw_family_summary(start_x int, sz loop.ScreenSize) (err erro
|
||||
h.lp.SprintStyled("fg=green bold", center_string(family, int(sz.WidthCells)-start_x)),
|
||||
"",
|
||||
}
|
||||
fonts := h.fonts[family]
|
||||
if len(fonts) == 0 {
|
||||
return fmt.Errorf("The family: %s has no fonts", family)
|
||||
}
|
||||
if has_variable_data_for_font(fonts[0]) {
|
||||
} else {
|
||||
lines = append(lines, "Reading font data, please wait…")
|
||||
key := fonts[0].cache_key()
|
||||
if !h.variable_data_requested_for.Has(key) {
|
||||
h.variable_data_requested_for.Add(key)
|
||||
go func() {
|
||||
h.set_worker_error(ensure_variable_data_for_fonts(fonts...))
|
||||
h.lp.WakeupMainThread()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
for i, line := range lines {
|
||||
if i >= int(sz.HeightCells)-1 {
|
||||
@@ -115,7 +132,7 @@ func (h *handler) draw_listing_screen() (err error) {
|
||||
h.lp.Println(SEPARATOR)
|
||||
}
|
||||
if h.family_list.Len() > 0 {
|
||||
if err = h.draw_family_summary(mw+2, sz); err != nil {
|
||||
if err = h.draw_family_summary(mw+3, sz); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -207,9 +224,11 @@ func (h *handler) handle_listing_text(text string, from_key_event bool, in_brack
|
||||
func (h *handler) initialize() {
|
||||
h.lp.SetCursorVisible(false)
|
||||
h.rl = readline.New(h.lp, readline.RlInit{DontMarkPrompts: true, Prompt: "Family: "})
|
||||
h.variable_data_requested_for = utils.NewSet[string](256)
|
||||
h.draw_screen()
|
||||
initialize_variable_data_cache()
|
||||
go func() {
|
||||
h.set_worker_error(json_decode(&h.fonts))
|
||||
h.set_worker_error(query_kitty("", nil, &h.fonts))
|
||||
h.lp.WakeupMainThread()
|
||||
}()
|
||||
}
|
||||
@@ -243,6 +262,8 @@ func (h *handler) on_wakeup() (err error) {
|
||||
h.state = LISTING_FAMILIES
|
||||
h.family_list.UpdateFamilies(utils.StableSortWithKey(maps.Keys(h.fonts), strings.ToLower))
|
||||
return h.draw_screen()
|
||||
case LISTING_FAMILIES:
|
||||
return h.draw_screen()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user