@@ -184,27 +184,27 @@ public UnmanagedMemoryStream GetUnmanagedStream()
184184 {
185185 WebResponse response = WpfWebRequestHelper . CreateRequestAndGetResponse ( _fontUri ) ;
186186 fontStream = response . GetResponseStream ( ) ;
187- if ( String . Equals ( response . ContentType , ObfuscatedContentType , StringComparison . Ordinal ) )
187+ if ( string . Equals ( response . ContentType , ObfuscatedContentType , StringComparison . Ordinal ) )
188188 {
189189 // The third parameter makes sure the original stream is closed
190190 // when the deobfuscating stream is disposed.
191191 fontStream = new DeobfuscatingStream ( fontStream , _fontUri , false ) ;
192192 }
193193 }
194194
195- UnmanagedMemoryStream unmanagedStream = fontStream as UnmanagedMemoryStream ;
196-
197- if ( unmanagedStream != null )
198- return unmanagedStream ;
195+ // We don't want any memory leaks
196+ // TODO: Remove FinalizableUnmanagedStream once FontFileStream is migrated from C++/CLI.
197+ if ( fontStream is UnmanagedMemoryStream unmanagedMemoryStream )
198+ return new FinalizableUnmanagedStream ( unmanagedMemoryStream ) ;
199199
200+ // Convert the DeobfuscatingStream to byte[]; add it to our cache, dispose it
200201 bits = StreamToByteArray ( fontStream ) ;
202+ lock ( s_resourceCache )
203+ {
204+ s_resourceCache . Add ( _fontUri , bits , false ) ;
205+ }
201206
202- fontStream ? . Close ( ) ;
203- }
204-
205- lock ( s_resourceCache )
206- {
207- s_resourceCache . Add ( _fontUri , bits , false ) ;
207+ fontStream . Close ( ) ;
208208 }
209209
210210 return ByteArrayToUnmanagedStream ( bits ) ;
@@ -358,7 +358,7 @@ private Stream GetCompositeFontResourceStream()
358358 Assembly fontResourceAssembly = Assembly . GetExecutingAssembly ( ) ;
359359 ResourceManager rm = new ( $ "{ ReflectionUtils . GetAssemblyPartialName ( fontResourceAssembly ) } .g", fontResourceAssembly ) ;
360360
361- return rm ? . GetStream ( $ "fonts/{ fontFilename } ") ;
361+ return rm . GetStream ( $ "fonts/{ fontFilename } ") ;
362362 }
363363
364364 #endregion Private Methods
@@ -371,6 +371,26 @@ private Stream GetCompositeFontResourceStream()
371371
372372 #region Private Classes
373373
374+ /// <summary>
375+ /// Calls <see cref="UnmanagedMemoryStream.Dispose"/> from the destructor.
376+ /// </summary>
377+ // TODO: Remove this once FontFileStream is migrated from C++/CLI.
378+ private sealed class FinalizableUnmanagedStream : UnmanagedMemoryStream
379+ {
380+ private readonly UnmanagedMemoryStream _unmanaged ;
381+
382+ internal unsafe FinalizableUnmanagedStream ( UnmanagedMemoryStream unmanagedStream )
383+ {
384+ _unmanaged = unmanagedStream ;
385+ Initialize ( _unmanaged . PositionPointer , _unmanaged . Length , _unmanaged . Length , FileAccess . Read ) ;
386+ }
387+
388+ ~ FinalizableUnmanagedStream ( )
389+ {
390+ _unmanaged . Dispose ( ) ;
391+ }
392+ }
393+
374394 private class PinnedByteArrayStream : UnmanagedMemoryStream
375395 {
376396 internal PinnedByteArrayStream ( byte [ ] bits )
0 commit comments