@@ -27,72 +27,162 @@ void InitImGui()
2727 ImGui . SetCurrentContext ( ImGui . CreateContext ( ) ) ;
2828 var io = ImGui . GetIO ( ) ;
2929 io . ConfigFlags |= ImGuiConfigFlags . NavEnableKeyboard | ImGuiConfigFlags . DockingEnable ;
30- LoadIconFont ( io ) ;
31- LoadEmbeddedFont ( io ) ;
32- // 注意:AddFontFromMemoryTTF 只存指针,Build() 时才真正读取数据
33- io . Fonts . Build ( ) ;
34- // Build() 之后才能安全释放字体内存
35- FreeFontMemory ( ) ;
30+
31+ try
32+ {
33+ var hasBaseFont = LoadEmbeddedFont (
34+ io ,
35+ "StArray.ModManager.Resources.NotoSansCJK-Regular.otf" ,
36+ ref _cjkFontPtr ,
37+ merge : false ,
38+ GetAllUnicodeRanges ( ) ) ;
39+
40+ var latinFontIsBase = false ;
41+ if ( ! hasBaseFont )
42+ {
43+ latinFontIsBase = LoadEmbeddedFont (
44+ io ,
45+ "StArray.ModManager.Resources.NotoSans-Regular.ttf" ,
46+ ref _latinFontPtr ,
47+ merge : false ,
48+ GetAllUnicodeRanges ( ) ) ;
49+ hasBaseFont = latinFontIsBase ;
50+ }
51+
52+ if ( ! hasBaseFont )
53+ {
54+ io . Fonts . AddFontDefault ( ) ;
55+ hasBaseFont = true ;
56+ }
57+
58+ if ( ! latinFontIsBase )
59+ {
60+ LoadEmbeddedFont (
61+ io ,
62+ "StArray.ModManager.Resources.NotoSans-Regular.ttf" ,
63+ ref _latinFontPtr ,
64+ merge : true ,
65+ GetAllUnicodeRanges ( ) ) ;
66+ }
67+ LoadEmbeddedFont (
68+ io ,
69+ "StArray.ModManager.Resources.NotoSansSymbols2-Regular.ttf" ,
70+ ref _symbolsFontPtr ,
71+ merge : true ,
72+ GetAllUnicodeRanges ( ) ) ;
73+ LoadEmbeddedFont (
74+ io ,
75+ "StArray.ModManager.Resources.OpenMoji-black-glyf.ttf" ,
76+ ref _emojiFontPtr ,
77+ merge : true ,
78+ GetAllUnicodeRanges ( ) ) ;
79+ LoadEmbeddedFont (
80+ io ,
81+ "StArray.ModManager.Resources.fa-solid-900.ttf" ,
82+ ref _iconFontPtr ,
83+ merge : true ,
84+ GetIconRanges ( ) ) ;
85+
86+ // AddFontFromMemoryTTF 只保存指针,Build() 时才真正读取数据。
87+ io . Fonts . Build ( ) ;
88+ }
89+ finally
90+ {
91+ FreeFontMemory ( ) ;
92+ }
3693 }
3794
38- private static nint _fontPtr1 , _fontPtr2 ;
95+ private static nint _cjkFontPtr ;
96+ private static nint _latinFontPtr ;
97+ private static nint _symbolsFontPtr ;
98+ private static nint _emojiFontPtr ;
99+ private static nint _iconFontPtr ;
100+ private static nint _allUnicodeRangesPtr ;
101+ private static nint _iconRangesPtr ;
39102
40103 private static void FreeFontMemory ( )
41104 {
42- if ( _fontPtr1 != 0 ) { Marshal . FreeHGlobal ( _fontPtr1 ) ; _fontPtr1 = 0 ; }
43- if ( _fontPtr2 != 0 ) { Marshal . FreeHGlobal ( _fontPtr2 ) ; _fontPtr2 = 0 ; }
105+ Free ( ref _cjkFontPtr ) ;
106+ Free ( ref _latinFontPtr ) ;
107+ Free ( ref _symbolsFontPtr ) ;
108+ Free ( ref _emojiFontPtr ) ;
109+ Free ( ref _iconFontPtr ) ;
110+ Free ( ref _allUnicodeRangesPtr ) ;
111+ Free ( ref _iconRangesPtr ) ;
44112 }
45113
46- private static unsafe void LoadEmbeddedFont ( ImGuiIOPtr io )
114+ private static void Free ( ref nint ptr )
47115 {
48- try
49- {
50- var asm = typeof ( IImGuiRenderer ) . Assembly ;
51- using var stream = asm . GetManifestResourceStream (
52- "StArray.ModManager.Resources.NotoSansCJK-Regular.otf" ) ;
53- if ( stream == null ) return ;
116+ if ( ptr == 0 ) return ;
117+ Marshal . FreeHGlobal ( ptr ) ;
118+ ptr = 0 ;
119+ }
54120
55- var ttf = new byte [ stream . Length ] ;
56- stream . ReadExactly ( ttf ) ;
57- _fontPtr1 = Marshal . AllocHGlobal ( ttf . Length ) ;
58- Marshal . Copy ( ttf , 0 , _fontPtr1 , ttf . Length ) ;
121+ private static nint GetAllUnicodeRanges ( )
122+ {
123+ if ( _allUnicodeRangesPtr != 0 ) return _allUnicodeRangesPtr ;
124+ _allUnicodeRangesPtr = AllocateRanges ( 0x0001 , 0xFFFF ) ;
125+ return _allUnicodeRangesPtr ;
126+ }
59127
60- // MergeMode: 中文字形合并到图标基础字体
61- var cfg = ImGuiNative . ImFontConfig_ImFontConfig ( ) ;
62- cfg ->MergeMode = 1 ;
63- cfg ->FontDataOwnedByAtlas = 0 ; // 自己管理内存,Build() 后释放
128+ private static nint GetIconRanges ( )
129+ {
130+ if ( _iconRangesPtr != 0 ) return _iconRangesPtr ;
131+ _iconRangesPtr = AllocateRanges ( 0xE000 , 0xF8FF ) ;
132+ return _iconRangesPtr ;
133+ }
64134
65- var glyphRanges = io . Fonts . GetGlyphRangesChineseSimplifiedCommon ( ) ;
66- io . Fonts . AddFontFromMemoryTTF ( _fontPtr1 , ttf . Length , 16f , cfg , glyphRanges ) ;
67- ImGuiNative . ImFontConfig_destroy ( cfg ) ;
68- }
69- catch { /* 静默跳过 */ }
135+ private static nint AllocateRanges ( ushort first , ushort last )
136+ {
137+ var ptr = Marshal . AllocHGlobal ( sizeof ( ushort ) * 3 ) ;
138+ Marshal . WriteInt16 ( ptr , 0 , ( short ) first ) ;
139+ Marshal . WriteInt16 ( ptr , sizeof ( ushort ) , ( short ) last ) ;
140+ Marshal . WriteInt16 ( ptr , sizeof ( ushort ) * 2 , 0 ) ;
141+ return ptr ;
70142 }
71143
72- private static unsafe void LoadIconFont ( ImGuiIOPtr io )
144+ private static unsafe bool LoadEmbeddedFont (
145+ ImGuiIOPtr io ,
146+ string resourceName ,
147+ ref nint fontPtr ,
148+ bool merge ,
149+ nint glyphRanges )
73150 {
74151 try
75152 {
76153 var asm = typeof ( IImGuiRenderer ) . Assembly ;
77- using var stream = asm . GetManifestResourceStream (
78- "StArray.ModManager.Resources.fa-solid-900.ttf" ) ;
79- if ( stream == null ) return ;
154+ using var stream = asm . GetManifestResourceStream ( resourceName ) ;
155+ if ( stream == null ) return false ;
80156
81- var ttf = new byte [ stream . Length ] ;
82- stream . ReadExactly ( ttf ) ;
83- _fontPtr2 = Marshal . AllocHGlobal ( ttf . Length ) ;
84- Marshal . Copy ( ttf , 0 , _fontPtr2 , ttf . Length ) ;
157+ var fontData = new byte [ checked ( ( int ) stream . Length ) ] ;
158+ stream . ReadExactly ( fontData ) ;
159+ fontPtr = Marshal . AllocHGlobal ( fontData . Length ) ;
160+ Marshal . Copy ( fontData , 0 , fontPtr , fontData . Length ) ;
85161
86- // 基础字体:FontAwesome 7 图标
87162 var cfg = ImGuiNative . ImFontConfig_ImFontConfig ( ) ;
88- cfg ->FontDataOwnedByAtlas = 0 ; // 自己管理内存
163+ try
164+ {
165+ cfg ->MergeMode = merge ? ( byte ) 1 : ( byte ) 0 ;
166+ cfg ->FontDataOwnedByAtlas = 0 ;
167+ io . Fonts . AddFontFromMemoryTTF (
168+ fontPtr ,
169+ fontData . Length ,
170+ 16f ,
171+ cfg ,
172+ glyphRanges ) ;
173+ }
174+ finally
175+ {
176+ ImGuiNative . ImFontConfig_destroy ( cfg ) ;
177+ }
89178
90- ushort [ ] iconRange = [ 0xe005 , 0xf8ff , 0 ] ;
91- fixed ( ushort * r = iconRange )
92- io . Fonts . AddFontFromMemoryTTF ( _fontPtr2 , ttf . Length , 16f , cfg , ( IntPtr ) r ) ;
93- ImGuiNative . ImFontConfig_destroy ( cfg ) ;
179+ return true ;
180+ }
181+ catch
182+ {
183+ Free ( ref fontPtr ) ;
184+ return false ;
94185 }
95- catch { /* 静默跳过 */ }
96186 }
97187
98188 /// <summary>
0 commit comments