SourceCode/PROMS/fmtxml/RtfToSvg.cs
Rich 5a7af006a8 Only convert Page and Document formats is the related Format file exists.
Skip commented lines in INI file.
Remove inline comments before processing INI file.
Use more explicit comparisons to determine type of command.
Replace spaces with {sp}.
2011-06-23 21:29:00 +00:00

341 lines
11 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 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);
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("</svg>\r\n"));
}
private static bool AndGroupEnd(StringBuilder sb, bool group)
{
if (group) sb.Append(" </g>\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(" <g id=\"{0}\">\r\n", grpID));
return grpID;
}
private static void AddC0(StringBuilder sb)
{
sb.Append(" <g id=\"C0\">\r\n");
sb.Append(" <ellipse cx=\"-3.8\" cy=\"-15.3\" rx=\"25.2\" ry=\"25.2\" fill=\"none\" stroke=\"black\" stroke-width=\"1.95\" />\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("<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 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(" <image x=\"{0}\" y=\"{1}\" width=\"{2}\" height=\"{3}\" bname=\"{4}\"/>\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(" <text x=\"{0}\" y=\"{1}\" font-family=\"{3}\" font-size=\"{2}\" {4}>{5}</text>\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(" <ellipse cx=\"{0}\" cy=\"{1}\" rx=\"{2}\" ry=\"{3}\" fill=\"none\" stroke=\"black\" stroke-width=\"{4}\" />\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(" <rect x=\"{0}\" y=\"{1}\" width=\"{2}\" height=\"{3}\" fill=\"none\" stroke=\"black\" stroke-width=\"{4}\" />\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(" <line x1=\"{0}\" y1=\"{1}\" x2=\"{2}\" y2=\"{3}\" stroke=\"black\" stroke-width=\"{4}\" />\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("&", "&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}");
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);
}
}
}