22// Use of this source code is governed by GNU General Public License (GPL-2.0) that can be found in the COPYING file.
33
44using System ;
5+ using System . Globalization ;
56using System . IO ;
67using System . Reflection ;
78using System . Text ;
9+ using System . Xml ;
810using Svg ;
911
1012namespace SvgFileTypePlugin . Extensions ;
@@ -51,16 +53,29 @@ public static string GetXML_QuotedFuncIRIHack(this SvgElement svg)
5153 {
5254 ArgumentNullException . ThrowIfNull ( svg ) ;
5355
54- return svg . GetXML ( ) . Replace ( """ , string . Empty ) ;
56+ using InvariantUtf8StringWriter writer = new InvariantUtf8StringWriter ( ) ;
57+ XmlWriterSettings xmlWriterSettings = new ( ) { Encoding = Encoding . UTF8 } ;
58+ using ( XmlWriter xmlWriter = new CustomXmlWriter ( XmlWriter . Create ( writer , xmlWriterSettings ) ) )
59+ {
60+ svg . Write ( xmlWriter ) ;
61+ xmlWriter . Flush ( ) ;
62+ }
63+ writer . Flush ( ) ;
64+ return writer . ToString ( ) ;
5565 }
5666
57- public static Stream GetXMLAsStream ( this SvgElement svg )
67+ public static void WriteXML_QuotedFuncIRIHack ( this SvgElement svg , Stream output )
5868 {
5969 ArgumentNullException . ThrowIfNull ( svg ) ;
6070
61- string xml = svg . GetXML_QuotedFuncIRIHack ( ) ;
62- byte [ ] bytes = Encoding . UTF8 . GetBytes ( xml ) ;
63- return new MemoryStream ( bytes ) ;
71+ using InvariantUtf8StreamWriter writer = new InvariantUtf8StreamWriter ( output ) ;
72+ XmlWriterSettings xmlWriterSettings = new ( ) { Encoding = Encoding . UTF8 } ;
73+ using ( XmlWriter xmlWriter = new CustomXmlWriter ( XmlWriter . Create ( writer , xmlWriterSettings ) ) )
74+ {
75+ svg . Write ( xmlWriter ) ;
76+ xmlWriter . Flush ( ) ;
77+ }
78+ writer . Flush ( ) ;
6479 }
6580
6681 private static T CreateGetterDelegate < T > ( string propertyName ) where T : Delegate
@@ -71,4 +86,56 @@ private static T CreateGetterDelegate<T>(string propertyName) where T : Delegate
7186 ?? throw new MissingMemberException ( nameof ( SvgElement ) , propertyName ) ;
7287 return getter . CreateDelegate < T > ( ) ;
7388 }
89+
90+ private sealed class InvariantUtf8StreamWriter ( Stream stream ) : StreamWriter ( stream , Encoding . UTF8 , leaveOpen : true )
91+ {
92+ private readonly Stream stream = stream ;
93+
94+ public override Encoding Encoding => Encoding . UTF8 ;
95+ public override IFormatProvider FormatProvider => CultureInfo . InvariantCulture ;
96+
97+ protected override void Dispose ( bool disposing )
98+ {
99+ base . Dispose ( disposing ) ;
100+ if ( disposing )
101+ stream . Position = 0 ;
102+ }
103+ }
104+
105+ private sealed class InvariantUtf8StringWriter ( ) : StringWriter ( CultureInfo . InvariantCulture )
106+ {
107+ public override Encoding Encoding => Encoding . UTF8 ;
108+ }
109+
110+ private sealed class CustomXmlWriter ( XmlWriter writer ) : XmlWriter
111+ {
112+ private readonly XmlWriter writer = writer ;
113+ public override WriteState WriteState => writer . WriteState ;
114+ public override void Flush ( ) => writer . Flush ( ) ;
115+ public override string ? LookupPrefix ( string ns ) => writer . LookupPrefix ( ns ) ;
116+ public override void WriteBase64 ( byte [ ] buffer , int index , int count ) => writer . WriteBase64 ( buffer , index , count ) ;
117+ public override void WriteCData ( string ? text ) => writer . WriteCData ( text ) ;
118+ public override void WriteCharEntity ( char ch ) => writer . WriteCharEntity ( ch ) ;
119+ public override void WriteChars ( char [ ] buffer , int index , int count ) => writer . WriteChars ( buffer , index , count ) ;
120+ public override void WriteComment ( string ? text ) => writer . WriteComment ( text ) ;
121+ public override void WriteDocType ( string name , string ? pubid , string ? sysid , string ? subset ) => writer . WriteDocType ( name , pubid , sysid , subset ) ;
122+ public override void WriteEndAttribute ( ) => writer . WriteEndAttribute ( ) ;
123+ public override void WriteEndDocument ( ) => writer . WriteEndDocument ( ) ;
124+ public override void WriteEndElement ( ) => writer . WriteEndElement ( ) ;
125+ public override void WriteEntityRef ( string name ) => writer . WriteEntityRef ( name ) ;
126+ public override void WriteFullEndElement ( ) => writer . WriteFullEndElement ( ) ;
127+ public override void WriteProcessingInstruction ( string name , string ? text ) => writer . WriteProcessingInstruction ( name , text ) ;
128+ public override void WriteRaw ( char [ ] buffer , int index , int count ) => writer . WriteRaw ( buffer , index , count ) ;
129+ public override void WriteRaw ( string data ) => writer . WriteRaw ( data ) ;
130+ public override void WriteStartAttribute ( string ? prefix , string localName , string ? ns ) => writer . WriteStartAttribute ( prefix , localName , ns ) ;
131+ public override void WriteStartDocument ( ) => writer . WriteStartDocument ( ) ;
132+ public override void WriteStartDocument ( bool standalone ) => writer . WriteStartDocument ( standalone ) ;
133+ public override void WriteStartElement ( string ? prefix , string localName , string ? ns ) => writer . WriteStartElement ( prefix , localName , ns ) ;
134+ public override void WriteString ( string ? text )
135+ {
136+ writer . WriteString ( text ? . Replace ( "\" " , string . Empty ) . Replace ( "\' " , string . Empty ) ) ;
137+ }
138+ public override void WriteSurrogateCharEntity ( char lowChar , char highChar ) => writer . WriteSurrogateCharEntity ( lowChar , highChar ) ;
139+ public override void WriteWhitespace ( string ? ws ) => writer . WriteWhitespace ( ws ) ;
140+ }
74141}
0 commit comments