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(); } } }