using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Text.RegularExpressions; using System.Drawing; using System.Xml; namespace fmtxml { public class RtfToSvg { public RtfToSvg(string rtfFileName) { RtfFileName = rtfFileName; _FormatFolder = RtfFile.Directory; } private static DirectoryInfo _FormatFolder; public RtfToSvg(FileInfo rtfFile) { RtfFile = rtfFile; _FormatFolder = RtfFile.Directory; } private bool? _IsGenMac; public bool IsGenMac { get { if (_IsGenMac == null) Convert(); return (bool)_IsGenMac; } set { _IsGenMac = value; } } private string _RtfFileName; public string RtfFileName { get { return _RtfFileName; } set { _RtfFileName = value; _RtfFile = new FileInfo(_RtfFileName); } } private FileInfo _RtfFile; public FileInfo RtfFile { get { return _RtfFile; } set { _RtfFile = value; _RtfFileName = _RtfFile.FullName; } } private string _Svg; public string Svg { get { if (_Svg == null) Convert(); return _Svg; } } private string Convert() { string buff = LoadFile(RtfFile);// Load Text _Svg = CreateSvg(RtfFile, buff);// Convert to SVG return _Svg; } /// /// Load the file into a string by bytes /// /// /// private static string LoadFile(FileInfo file) { byte[] bytes = new byte[file.Length]; using (FileStream fs = file.OpenRead()) { fs.Read(bytes, 0, (int)file.Length); fs.Close(); } StringBuilder sb = new StringBuilder(); foreach (byte byt in bytes) sb.Append((char)byt); return sb.ToString(); } private const string _TripleBang = "\xAD\xAD\xAD\xA8\xA8"; Regex regLines = new Regex(@"([^\r\n]*)?\r?\n", RegexOptions.Singleline); private string CreateSvg(FileInfo file, string buff) { IsGenMac = (buff.Substring(0, 5) == _TripleBang); if(!IsGenMac) return null; StringBuilder sb = new StringBuilder(); MatchCollection lines = regLines.Matches(buff); bool svg = false; bool group = false; bool hasC0 = false; foreach (Match line in lines) { string text = line.Groups[1].Value; if (text == _TripleBang) if (!svg) svg = AddSvgPrefix(file, sb, svg); else AddSvgSuffix(sb, hasC0); else if (text.StartsWith("\xAD\xAD")) hasC0 |= AddGroupStart(sb, ref group, text).ToLower() == "c0"; else if (text == "END") group = AndGroupEnd(sb, group); else if (text != "") ProcessCommand(sb, text, file); } return sb.ToString(); } private static void AddSvgSuffix(StringBuilder sb, bool hasC0) { if (!hasC0) { AddC0(sb); } sb.Append(string.Format("\r\n")); } private static bool AndGroupEnd(StringBuilder sb, bool group) { if (group) sb.Append(" \r\n"); group = false; return group; } private static string AddGroupStart(StringBuilder sb, ref bool group, string text) { AndGroupEnd(sb, group); group = true; string grpID = text.Substring(2).ToUpper(); sb.Append(string.Format(" \r\n", grpID)); return grpID; } private static void AddC0(StringBuilder sb) { sb.Append(" \r\n"); sb.Append(" \r\n"); sb.Append(" \r\n"); } private static bool AddSvgPrefix(FileInfo file, StringBuilder sb, bool svg) { sb.Append("\r\n"); sb.Append("\r\n"); sb.Append(string.Format(" {0}\r\n", file.Name.ToLower().Replace(".rtf", ""))); svg = true; return svg; } private static Regex regCommand = new Regex(@"^[A-Z][^ \r\n]*", RegexOptions.Multiline); private static void ProcessCommand(StringBuilder sb, string text, FileInfo file) { Match commandMatch = regCommand.Match(text); ECommand command = (ECommand)Enum.Parse(typeof(ECommand), commandMatch.Value); Converters[(int)command](sb, text); } private enum ECommand : int { LINE, BOX, ELLIPSE, TEXT, BITMAP, GDIADJ, RTFADJ, ABSOLUTE } private delegate void Converter(StringBuilder sb, string text); private static Converter[] _Converters; private static Converter[] Converters { get { if (_Converters == null) SetupConverters(); return RtfToSvg._Converters; } set { _Converters = value; } } private static void SetupConverters() { Converters = new Converter[Enum.GetNames(typeof(ECommand)).Length]; Converters[(int)ECommand.LINE] = new Converter(AddLine); Converters[(int)ECommand.BOX] = new Converter(AddRect); Converters[(int)ECommand.ELLIPSE] = new Converter(AddEllipse); Converters[(int)ECommand.TEXT] = new Converter(AddText); Converters[(int)ECommand.BITMAP] = new Converter(AddImage); Converters[(int)ECommand.GDIADJ] = new Converter(AddGdiAdj); Converters[(int)ECommand.RTFADJ] = new Converter(AddRtfAdj); Converters[(int)ECommand.ABSOLUTE] = new Converter(AddAbsolute); } private static void AddGdiAdj(StringBuilder sb, string text) { // May need to do something with this } private static void AddAbsolute(StringBuilder sb, string text) { // May need to do something with this } private static void AddRtfAdj(StringBuilder sb, string text) { // Not needed } private static Regex regBitmap = new Regex(@"BITMAP ([-0-9]*) ([-0-9]*) (.*)$", RegexOptions.Multiline); private static void AddImage(StringBuilder sb, string text) { Match bitmapMatch = regBitmap.Match(text); //string bmFileName = FixXmlText(bitmapMatch.Groups[3].Value); string bmFileName = FixFileName(bitmapMatch.Groups[3].Value); Bitmap bmp = new Bitmap(bmFileName); string bmWidth = bmp.Width.ToString() + "px"; string bmHeight = bmp.Height.ToString() + "px"; //Console.WriteLine("'{0}'", bmFileName); sb.Append(string.Format(" \r\n", TwipsToPoints(bitmapMatch.Groups[1].Value), TwipsToPoints(bitmapMatch.Groups[2].Value), bmWidth, bmHeight, bmFileName)); } private static Regex regText = new Regex(@"TEXT ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ""([^""]*)""", RegexOptions.Multiline); private static void AddText(StringBuilder sb, string text) { Match textMatch = regText.Match(text); //if (!_FontStyles.Contains(textMatch.Groups[5].Value)) //{ // Console.WriteLine("{0} - {1}", textMatch.Groups[5].Value, file.Name); // _FontStyles.Add(textMatch.Groups[5].Value); //} sb.Append(string.Format(" {5}\r\n", TwipsToPoints(textMatch.Groups[1].Value), TwipsToPoints(textMatch.Groups[2].Value), FontSizeToPoints(textMatch.Groups[3].Value), FontToFamily(textMatch.Groups[4].Value), FontStyle(textMatch.Groups[5].Value), FixXmlText(textMatch.Groups[6].Value))); } private static Regex regEllipse = new Regex(@"ELLIPSE ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*)", RegexOptions.Multiline); private static void AddEllipse(StringBuilder sb, string text) { Match ellipseMatch = regEllipse.Match(text); sb.Append(string.Format(" \r\n", TwipsToPoints(ellipseMatch.Groups[1].Value), TwipsToPoints(ellipseMatch.Groups[2].Value), TwipsToPoints(ellipseMatch.Groups[3].Value), TwipsToPoints(ellipseMatch.Groups[4].Value), TwipsToPoints(ellipseMatch.Groups[5].Value))); } private static Regex regBox = new Regex(@"BOX ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*)", RegexOptions.Multiline); private static void AddRect(StringBuilder sb, string text) { Match boxMatch = regBox.Match(text); sb.Append(string.Format(" \r\n", TwipsToPoints(boxMatch.Groups[1].Value), TwipsToPoints(boxMatch.Groups[2].Value), TwipsToPoints(boxMatch.Groups[3].Value), TwipsToPoints(boxMatch.Groups[4].Value), TwipsToPoints(boxMatch.Groups[5].Value))); } private static Regex regLine = new Regex(@"LINE ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*)", RegexOptions.Multiline); private static void AddLine(StringBuilder sb, string text) { Match lineMatch = regLine.Match(text); sb.Append(string.Format(" \r\n", TwipsToPoints(lineMatch.Groups[1].Value), TwipsToPoints(lineMatch.Groups[2].Value), TwipsToPoints(lineMatch.Groups[3].Value) + TwipsToPoints(lineMatch.Groups[1].Value), TwipsToPoints(lineMatch.Groups[4].Value) + TwipsToPoints(lineMatch.Groups[2].Value), TwipsToPoints(lineMatch.Groups[5].Value))); } private static string FontStyle(string style) { StringBuilder sb = new StringBuilder(); int iStyle = int.Parse(style); if ((iStyle & 1) == 1) sb.Append("font-weight=\"bold\" "); if ((iStyle & 2) == 2) sb.Append("text-decoration=\"underline\" "); if ((iStyle & 4) == 4) sb.Append("font-style=\"italic\" "); return sb.ToString(); } private static string FixFileName(string fileName) { return Regex.Replace(fileName, @"^.*FORMAT\\", _FormatFolder.FullName + @"\"); } private static string FixXmlText(string str) { str = str.Replace("&", "&"); str = str.Replace("'", "'"); str = str.Replace("\"", """); str = str.Replace("<", "<"); str = str.Replace(">", ">"); str = str.Replace("\x0B", " "); return str; } private static string[] FontChoice = { "Times New Roman", "VESymb XXXXXX", "VolianDraw XXXXXX", "Prestige Elite Tall", "Courier New", "Arial", "Letter Gothic", "Times New Roman", "Letter Gothic Tall", "Letter Gothic Tall", "Gothic Ultra", "VolianScript" }; private static float TwipsToPoints(string twips) { return float.Parse(twips) / 20; } private static float FontSizeToPoints(string fontSize) { return float.Parse(fontSize) / 2; } private static string FontToFamily(string fontID) { if (int.Parse(fontID) >= FontChoice.Length) return "Font-" + fontID; return FontChoice[int.Parse(fontID)]; } public void Save(string svgFileName) { FileInfo outFile = new FileInfo(svgFileName); if (outFile.Exists) outFile.Delete(); XmlDocument xDoc = new XmlDocument(); xDoc.LoadXml(Svg); xDoc.Save(outFile.FullName); } } }