Added header information to xml for image link Replace bname with xlink:href for image references Added RNOWidthAdj flag for Braidwood
		
			
				
	
	
		
			388 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
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 partial 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;
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Load the file into a string by bytes
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="file"></param>
 | 
						|
		/// <returns></returns>
 | 
						|
		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);
 | 
						|
 | 
						|
		// If processing any of the RGE (except RGEDEV) C0 macros, adjust the x location of the ellipse, so that
 | 
						|
		// 32bit printing matches 16bit.  This flag shows that we're in a format that needs this adjustment.
 | 
						|
		private static bool _InRge = false;
 | 
						|
		private static bool _DoingRgeC0 = false;
 | 
						|
		private string CreateSvg(FileInfo file, string buff)
 | 
						|
		{
 | 
						|
			IsGenMac = (buff.Substring(0, 5) == _TripleBang);
 | 
						|
			if(!IsGenMac)
 | 
						|
				return null;
 | 
						|
			_InRge = (file.Name.ToUpper().Contains("RGE") && !file.Name.ToUpper().Contains("RGEDEV"));
 | 
						|
			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";
 | 
						|
					_DoingRgeC0 = (hasC0 && _InRge);
 | 
						|
				}
 | 
						|
				else if (text == "END")
 | 
						|
				{
 | 
						|
					group = AddGroupEnd(sb, group);
 | 
						|
					_DoingRgeC0 = false;
 | 
						|
				}
 | 
						|
				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("</svg>\r\n"));
 | 
						|
		}
 | 
						|
		private static bool AddGroupEnd(StringBuilder sb, bool group)
 | 
						|
		{
 | 
						|
			if (group) sb.Append("  </g>\r\n");
 | 
						|
			group = false;
 | 
						|
			_Xoff = 0;
 | 
						|
			_Yoff = 0;
 | 
						|
			return group;
 | 
						|
		}
 | 
						|
		private static string AddGroupStart(StringBuilder sb, ref bool group, string text)
 | 
						|
		{
 | 
						|
			AddGroupEnd(sb, group);
 | 
						|
			group = true;
 | 
						|
			string grpID = text.Substring(2).ToUpper();
 | 
						|
			sb.Append(string.Format("  <g id=\"{0}\">\r\n", grpID));
 | 
						|
			return grpID;
 | 
						|
		}
 | 
						|
		private static void AddC0(StringBuilder sb)
 | 
						|
		{
 | 
						|
			// note that cx = 1 has been tested with NSP.
 | 
						|
			sb.Append("  <g id=\"C0\">\r\n");
 | 
						|
			sb.Append("    <ellipse cx=\"1\" cy=\"-3.2\" rx=\"11.1\" ry=\"11.1\" fill=\"none\" stroke=\"black\" stroke-width=\"1.9\" />\r\n");
 | 
						|
			sb.Append("  </g>\r\n");
 | 
						|
		}
 | 
						|
		private static bool AddSvgPrefix(FileInfo file, StringBuilder sb, bool svg)
 | 
						|
		{
 | 
						|
			sb.Append("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n");
 | 
						|
			sb.Append("<!--Proprietary Information - Copyright 2012 - Volian Enterprises, Inc. All rights reserved.-->\r\n");
 | 
						|
			sb.Append("<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" width=\"8in\" height=\"10in\" viewBox=\"0 0 576 720\">\r\n");
 | 
						|
			sb.Append(string.Format("  <desc>{0}</desc>\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 Regex regGdiAdj = new Regex(@"GDIADJ ([-0-9]*) ([-0-9]*)$", RegexOptions.Multiline);
 | 
						|
		private static void AddGdiAdj(StringBuilder sb, string text)
 | 
						|
		{
 | 
						|
			Match gdiadjMatch = regGdiAdj.Match(text);
 | 
						|
			_Xoff = int.Parse(gdiadjMatch.Groups[1].Value);
 | 
						|
			_Yoff = int.Parse(gdiadjMatch.Groups[2].Value);
 | 
						|
		}
 | 
						|
		private static void AddAbsolute(StringBuilder sb, string text)
 | 
						|
		{
 | 
						|
			sb.Append("  <desc>ABSOLUTE</desc>");
 | 
						|
		}
 | 
						|
		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("    <image x=\"{0}\" y=\"{1}\" width=\"{2}\" height=\"{3}\" xlink:href=\"{4}\"/>\r\n",
 | 
						|
				TwipsToPointsX(bitmapMatch.Groups[1].Value),
 | 
						|
				TwipsToPointsY(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);
 | 
						|
			
 | 
						|
			sb.Append(string.Format("    <text x=\"{0}\" y=\"{1}\" font-family=\"{3}\" font-size=\"{2}\" {4}>{5}</text>\r\n",
 | 
						|
				TwipsToPointsX(textMatch.Groups[1].Value),
 | 
						|
				TwipsToPointsY(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);
 | 
						|
			// code in the new veproms that draws the ellipse must use the 'y' location differently.  So
 | 
						|
			// add in the radius to the 'y' to get the correct value.
 | 
						|
			float yadj = TwipsToPointsEllipse(ellipseMatch.Groups[4].Value);
 | 
						|
			sb.Append(string.Format("    <ellipse cx=\"{0}\" cy=\"{1}\" rx=\"{2}\" ry=\"{3}\" fill=\"none\" stroke=\"black\" stroke-width=\"{4}\" />\r\n",
 | 
						|
				_DoingRgeC0?6.5:TwipsToPointsX(ellipseMatch.Groups[1].Value),
 | 
						|
				yadj + TwipsToPointsY(ellipseMatch.Groups[2].Value),
 | 
						|
				TwipsToPointsEllipse(ellipseMatch.Groups[3].Value),
 | 
						|
				TwipsToPointsEllipse(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("    <rect x=\"{0}\" y=\"{1}\" width=\"{2}\" height=\"{3}\" fill=\"none\" stroke=\"black\" stroke-width=\"{4}\" />\r\n",
 | 
						|
				TwipsToPointsX(boxMatch.Groups[1].Value),
 | 
						|
				TwipsToPointsY(boxMatch.Groups[2].Value),
 | 
						|
				TwipsToPoints(boxMatch.Groups[3].Value),
 | 
						|
				TwipsToPoints(boxMatch.Groups[4].Value),
 | 
						|
				TwipsToPoints(boxMatch.Groups[5].Value)));
 | 
						|
		}
 | 
						|
		private static int _Xoff = 0;
 | 
						|
		private static int _Yoff = 0;
 | 
						|
		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("    <line x1=\"{0}\" y1=\"{1}\" x2=\"{2}\" y2=\"{3}\" stroke=\"black\" stroke-width=\"{4}\" />\r\n",
 | 
						|
				TwipsToPointsX(lineMatch.Groups[1].Value),
 | 
						|
				TwipsToPointsY(lineMatch.Groups[2].Value),
 | 
						|
				TwipsToPoints(lineMatch.Groups[3].Value) + TwipsToPointsX(lineMatch.Groups[1].Value),
 | 
						|
				TwipsToPoints(lineMatch.Groups[4].Value) + TwipsToPointsY(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", "");
 | 
						|
			str = str.Replace(" ", "{sp}");
 | 
						|
			str = str.Replace("\xAE",@"\u8594?"); // Turkey Point uses a Right Arrow from VESYMB
 | 
						|
			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 TwipsToPointsEllipse(string twips)
 | 
						|
		{
 | 
						|
			// divide the ellipse by 40.  This is the 20 to convert from twips to points
 | 
						|
			// and an addition divide by 2 since the definition in 16bit is diameter &
 | 
						|
			// in 32 is radius.
 | 
						|
			return float.Parse(twips) / 40;
 | 
						|
		}
 | 
						|
		private static float TwipsToPointsX(string twips)
 | 
						|
		{
 | 
						|
			return (_Xoff + float.Parse(twips)) / 20;
 | 
						|
		}
 | 
						|
		private static float TwipsToPointsY(string twips)
 | 
						|
		{
 | 
						|
			return (_Yoff + 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();
 | 
						|
			try
 | 
						|
			{
 | 
						|
				//if (svgFileName.Contains("nsppe"))
 | 
						|
				//    Console.WriteLine("stop");
 | 
						|
				xDoc.LoadXml(Svg);
 | 
						|
			AppendPlantSpecific(svgFileName, xDoc);
 | 
						|
			xDoc.Save(outFile.FullName);
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				Console.WriteLine("Error generating {0}", svgFileName);
 | 
						|
				Console.WriteLine("ex = {0}", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |