@@ -23,7 +23,6 @@ func install(font *Font, admin bool) error {
23
23
// - Copy the file to the fonts directory
24
24
// - Add registry entry
25
25
// - Call AddFontResourceW to set the font
26
- // - Notify other applications that the fonts have changed
27
26
fontsDir := filepath .Join (os .Getenv ("WINDIR" ), "Fonts" )
28
27
if ! admin {
29
28
fontsDir = filepath .Join (os .Getenv ("USERPROFILE" ), "AppData" , "Local" , "Microsoft" , "Windows" , "Fonts" )
@@ -32,21 +31,21 @@ func install(font *Font, admin bool) error {
32
31
// check if the Fonts folder exists, if not, create it
33
32
if _ , err := os .Stat (fontsDir ); os .IsNotExist (err ) {
34
33
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 ())
36
35
}
37
36
}
38
37
39
38
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
41
40
if _ , err := os .Stat (fullPath ); err == nil {
42
41
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 ())
44
43
}
45
44
}
46
45
47
46
err := os .WriteFile (fullPath , font .Data , 0644 )
48
47
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 ())
50
49
}
51
50
52
51
// Add registry entry
@@ -61,34 +60,58 @@ func install(font *Font, admin bool) error {
61
60
if err != nil {
62
61
// If this fails, remove the font file as well.
63
62
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" )
65
64
}
66
65
67
- return fmt .Errorf ("Unable to open registry key: %s" , err .Error ())
66
+ return fmt .Errorf ("unable to open registry key: %s" , err .Error ())
68
67
}
68
+
69
69
defer k .Close ()
70
70
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 {
73
99
// If this fails, remove the font file as well.
74
100
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" )
76
102
}
77
103
78
- return fmt .Errorf ("Unable to set registry value: %s" , err .Error ())
104
+ return fmt .Errorf ("unable to set registry value: %s" , err .Error ())
79
105
}
80
106
81
- gdi32 := syscall .NewLazyDLL ("gdi32.dll" )
82
- proc := gdi32 .NewProc ("AddFontResourceW" )
83
-
84
107
fontPtr , err := syscall .UTF16PtrFromString (fullPath )
85
108
if err != nil {
86
109
return err
87
110
}
88
111
89
- ret , _ , _ := proc .Call (uintptr (unsafe .Pointer (fontPtr )))
112
+ ret , _ , _ := addFontResourceW .Call (uintptr (unsafe .Pointer (fontPtr )))
90
113
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" )
92
115
}
93
116
94
117
return nil
0 commit comments