sources/Google.Solutions.Mvvm/Format/RtfWriter.cs (182 lines of code) (raw):
//
// Copyright 2023 Google LLC
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
using Google.Solutions.Common.Util;
using System;
using System.Drawing;
using System.IO;
namespace Google.Solutions.Mvvm.Format
{
/// <summary>
/// Simple RTF writer.
/// </summary>
internal class RtfWriter : IDisposable
{
//
// NB. For a concise summary of RTF syntax, see
// https://metacpan.org/dist/RTF-Writer/view/lib/RTF/Cookbook.pod.
//
private readonly TextWriter writer;
public RtfWriter(TextWriter writer)
{
this.writer = writer.ExpectNotNull(nameof(writer));
}
public void Text(string s)
{
foreach (var c in s)
{
if (c == '\\' || c == '{' || c == '}')
{
//
// These characters need to be escaped.
//
this.writer.Write('\\');
this.writer.Write(c);
}
else if (c == '\r')
{
//
// Ignore.
//
}
else if (c == '\n')
{
this.writer.Write("\\line ");
}
else if (c >= 0x80)
{
this.writer.Write("\\u");
this.writer.Write(Convert.ToUInt32(c));
this.writer.Write("?");
}
else
{
this.writer.Write(c);
}
}
}
public void StartDocument()
{
this.writer.Write(@"{\rtf1\ansi\deff0\deflang1033\widowctrl");
}
public void EndDocument()
{ }
public void FontTable(FontFamily[] fonts)
{
this.writer.Write("{\\fonttbl");
for (var i = 0; i < fonts.Length; i++)
{
this.writer.Write("{\\f");
this.writer.Write(i.ToString());
this.writer.Write(" ");
this.writer.Write(fonts[i].Name);
this.writer.Write(";}");
}
this.writer.Write("}");
this.writer.WriteLine();
}
public void ColorTable(Color[] colors)
{
if (colors == null || colors.Length == 0)
{
return;
}
this.writer.WriteLine();
this.writer.Write("{\\colortbl");
foreach (var c in colors)
{
this.writer.Write("\\red" + c.R);
this.writer.Write("\\green" + c.G);
this.writer.Write("\\blue" + c.B);
this.writer.Write(";");
}
this.writer.Write("}");
this.writer.WriteLine();
}
public void StartParagraph()
{
this.writer.WriteLine();
this.writer.Write("{\\pard");
}
public void EndParagraph()
{
this.writer.WriteLine("\\par}");
this.writer.WriteLine();
}
public void SetSpaceBefore(uint sb)
{
this.writer.Write("\\sb");
this.writer.Write(sb.ToString());
this.writer.WriteLine();
}
public void SetSpaceAfter(uint sa)
{
this.writer.Write("\\sa");
this.writer.Write(sa.ToString());
this.writer.WriteLine();
}
public void SetFontColor(uint index = 0)
{
this.writer.Write("\\cf");
this.writer.Write(index.ToString());
this.writer.Write(" ");
}
public void SetHighlightColor(uint index = 0)
{
this.writer.Write("\\highlight");
this.writer.Write(index.ToString());
this.writer.Write(" ");
}
public void SetFont(uint index = 0)
{
this.writer.Write("\\f");
this.writer.Write(index.ToString());
this.writer.Write(" ");
}
public void SetFontSize(uint size)
{
this.writer.Write("\\fs");
this.writer.Write((size * 2).ToString());
this.writer.Write(" ");
}
public void SetBold(bool bold)
{
this.writer.Write(bold ? "\\b " : "\\b0 ");
}
public void SetUnderline(bool bold)
{
this.writer.Write(bold ? "\\ul " : "\\ul0 ");
}
public void SetItalic(bool bold)
{
this.writer.Write(bold ? "\\i " : "\\i0 ");
}
public void Hyperlink(string text, string href)
{
StartHyperlink(href);
Text(text);
EndHyperlink();
}
public void StartHyperlink(string href)
{
this.writer.Write("{\\field{\\*\\fldinst{HYPERLINK \"");
this.writer.Write(href);
this.writer.Write("\"}}{\\fldrslt{");
}
public void EndHyperlink()
{
this.writer.Write("}}}");
this.writer.WriteLine();
}
public void UnorderedListItem(
int firstLineIndent,
int blockIndent,
uint symbolFont)
{
this.writer.Write("{\\pntext\\f" + symbolFont + "\\'B7\\f0\\tab}");
this.writer.Write("{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\bullet}}");
this.writer.Write("\\fi");
this.writer.Write(firstLineIndent.ToString());
this.writer.Write("\\li");
this.writer.Write(blockIndent.ToString());
}
public void OrderedListItem(int firstLineIndent, int blockIndent, int number)
{
this.writer.Write("{\\pntext\\" + number + ".\\tab}");
this.writer.Write("{\\*\\pn\\pnlvlbody\\pnf0\\pnindent0\\pnstart1\\pndec{\\pntxta.}}");
this.writer.Write("\\fi");
this.writer.Write(firstLineIndent.ToString());
this.writer.Write("\\li");
this.writer.Write(blockIndent.ToString());
}
//---------------------------------------------------------------------
// IDisposable.
//---------------------------------------------------------------------
public void Dispose()
{
this.writer.Dispose();
}
}
}