Skip to content

Commit 176e3a0

Browse files
fix(font): only notify on font change when necessary
1 parent 8a2db6e commit 176e3a0

File tree

1 file changed

+39
-16
lines changed

1 file changed

+39
-16
lines changed

src/font/install_windows.go

+39-16
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ func install(font *Font, admin bool) error {
2323
// - Copy the file to the fonts directory
2424
// - Add registry entry
2525
// - Call AddFontResourceW to set the font
26-
// - Notify other applications that the fonts have changed
2726
fontsDir := filepath.Join(os.Getenv("WINDIR"), "Fonts")
2827
if !admin {
2928
fontsDir = filepath.Join(os.Getenv("USERPROFILE"), "AppData", "Local", "Microsoft", "Windows", "Fonts")
@@ -32,21 +31,21 @@ func install(font *Font, admin bool) error {
3231
// check if the Fonts folder exists, if not, create it
3332
if _, err := os.Stat(fontsDir); os.IsNotExist(err) {
3433
if err = os.MkdirAll(fontsDir, 0755); err != nil {
35-
return fmt.Errorf("Unable to create fonts directory: %s", err.Error())
34+
return fmt.Errorf("unable to create fonts directory: %s", err.Error())
3635
}
3736
}
3837

3938
fullPath := filepath.Join(fontsDir, font.FileName)
40-
// validate if font is already installed, remove it in case it is
39+
// validate if the font is already installed, remove it in case it is
4140
if _, err := os.Stat(fullPath); err == nil {
4241
if err = os.Remove(fullPath); err != nil {
43-
return fmt.Errorf("Unable to remove existing font file: %s", err.Error())
42+
return fmt.Errorf("unable to remove existing font file: %s", err.Error())
4443
}
4544
}
4645

4746
err := os.WriteFile(fullPath, font.Data, 0644)
4847
if err != nil {
49-
return fmt.Errorf("Unable to write font file: %s", err.Error())
48+
return fmt.Errorf("unable to write font file: %s", err.Error())
5049
}
5150

5251
// Add registry entry
@@ -61,34 +60,58 @@ func install(font *Font, admin bool) error {
6160
if err != nil {
6261
// If this fails, remove the font file as well.
6362
if nexterr := os.Remove(fullPath); nexterr != nil {
64-
return errors.New("Unable to delete font file after registry key open error")
63+
return errors.New("unable to delete font file after registry key open error")
6564
}
6665

67-
return fmt.Errorf("Unable to open registry key: %s", err.Error())
66+
return fmt.Errorf("unable to open registry key: %s", err.Error())
6867
}
68+
6969
defer k.Close()
7070

71-
name := fmt.Sprintf("%v (TrueType)", font.Name)
72-
if err = k.SetStringValue(name, regValue); err != nil {
71+
fontName := fmt.Sprintf("%v (TrueType)", font.Name)
72+
var alreadyInstalled, newFontType bool
73+
74+
// check if we already had this key set
75+
oldFullPath, _, err := k.GetStringValue(fontName)
76+
if err == nil {
77+
alreadyInstalled = true
78+
newFontType = oldFullPath != fullPath
79+
}
80+
81+
// do not call AddFontResourceW if the font was already installed
82+
if alreadyInstalled && !newFontType {
83+
return nil
84+
}
85+
86+
gdi32 := syscall.NewLazyDLL("gdi32.dll")
87+
addFontResourceW := gdi32.NewProc("AddFontResourceW")
88+
89+
// remove the old font resource in case we have a new font type with the same name
90+
if newFontType {
91+
fontPtr, err := syscall.UTF16PtrFromString(oldFullPath)
92+
if err == nil {
93+
removeFontResourceW := gdi32.NewProc("RemoveFontResourceW")
94+
_, _, _ = removeFontResourceW.Call(uintptr(unsafe.Pointer(fontPtr)))
95+
}
96+
}
97+
98+
if err = k.SetStringValue(fontName, regValue); err != nil {
7399
// If this fails, remove the font file as well.
74100
if nexterr := os.Remove(fullPath); nexterr != nil {
75-
return errors.New("Unable to delete font file after registry key set error")
101+
return errors.New("unable to delete font file after registry key set error")
76102
}
77103

78-
return fmt.Errorf("Unable to set registry value: %s", err.Error())
104+
return fmt.Errorf("unable to set registry value: %s", err.Error())
79105
}
80106

81-
gdi32 := syscall.NewLazyDLL("gdi32.dll")
82-
proc := gdi32.NewProc("AddFontResourceW")
83-
84107
fontPtr, err := syscall.UTF16PtrFromString(fullPath)
85108
if err != nil {
86109
return err
87110
}
88111

89-
ret, _, _ := proc.Call(uintptr(unsafe.Pointer(fontPtr)))
112+
ret, _, _ := addFontResourceW.Call(uintptr(unsafe.Pointer(fontPtr)))
90113
if ret == 0 {
91-
return errors.New("Unable to add font resource using AddFontResourceW")
114+
return errors.New("unable to add font resource using AddFontResourceW")
92115
}
93116

94117
return nil

0 commit comments

Comments
 (0)