SourceCode/PROMS/fmtxml/RtfToSvg.cs
John 8284c66da2 added code to put a copyright notice in each format file
added code to put a copyright notice in each genmac file
2012-10-25 18:48:42 +00:00

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=\"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}\" bname=\"{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("&", "&amp;");
str = str.Replace("'", "&apos;");
str = str.Replace("\"", "&quot;");
str = str.Replace("<", "&lt;");
str = str.Replace(">", "&gt;");
str = str.Replace("\x0B", "&#11;");
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);
}
}
}
}