From 8f9cad84170b7f47a98f56b98180605dcc06b48d Mon Sep 17 00:00:00 2001 From: emazv72 Date: Fri, 6 Jul 2018 18:17:35 +0200 Subject: [PATCH 01/25] Introduce xml format for serialization and deserialzion --- MigraDoc/src/BuildAll-MigraDoc.sln | 7 +- .../MigraDoc.DocumentObjectModel-gdi.csproj | 24 + .../MigraDoc.DocumentObjectModel-wpf.csproj | 25 + .../BookmarkField.cs | 15 + .../DocumentObjectModel.Fields/DateField.cs | 13 + .../DocumentObjectModel.Fields/InfoField.cs | 17 + .../NumPagesField.cs | 11 + .../DocumentObjectModel.Fields/PageField.cs | 11 + .../PageRefField.cs | 15 + .../SectionField.cs | 11 + .../SectionPagesField.cs | 12 + .../AttributeScanner.cs | 117 + .../DocumentObjectModel.IO.Xml/DdlParser.cs | 2609 +++++++++++++++++ .../DocumentObjectModel.IO.Xml/DdlReader.cs | 278 ++ .../DocumentObjectModel.IO.Xml/DdlWriter.cs | 312 ++ .../DocumentObjectModel.IO.Xml/Elements.cs | 218 ++ .../enums/XmlSymbol.cs | 154 + .../DocumentObjectModel.IO/DdlParser.cs | 1 + .../DocumentObjectModel.Shapes.Charts/Axis.cs | 50 + .../AxisTitle.cs | 28 + .../Chart.cs | 60 + .../ChartObject.cs | 6 + .../DataLabel.cs | 20 + .../Gridlines.cs | 17 + .../Legend.cs | 22 + .../PlotArea.cs | 28 + .../Point.cs | 32 + .../Series.cs | 46 + .../SeriesCollection.cs | 10 + .../SeriesElements.cs | 13 + .../TextArea.cs | 49 + .../TickLabels.cs | 18 + .../XSeries.cs | 12 + .../XSeriesElements.cs | 14 + .../XValue.cs | 6 + .../XValues.cs | 11 + .../DocumentObjectModel.Shapes/Barcode.cs | 34 + .../DocumentObjectModel.Shapes/FillFormat.cs | 15 + .../DocumentObjectModel.Shapes/Image.cs | 28 + .../LeftPosition.cs | 9 + .../DocumentObjectModel.Shapes/LineFormat.cs | 21 + .../PictureFormat.cs | 19 + .../DocumentObjectModel.Shapes/Shape.cs | 27 + .../DocumentObjectModel.Shapes/TextFrame.cs | 31 + .../DocumentObjectModel.Shapes/TopPosition.cs | 9 + .../DocumentObjectModel.Shapes/WrapFormat.cs | 22 + .../DocumentObjectModel.Tables/Cell.cs | 49 + .../DocumentObjectModel.Tables/Cells.cs | 8 + .../DocumentObjectModel.Tables/Column.cs | 47 + .../DocumentObjectModel.Tables/Columns.cs | 30 + .../DocumentObjectModel.Tables/Row.cs | 57 + .../DocumentObjectModel.Tables/Rows.cs | 42 + .../DocumentObjectModel.Tables/Table.cs | 49 + .../DocumentObjectModel/Border.cs | 33 + .../DocumentObjectModel/Borders.cs | 61 + .../DocumentObjectModel/Character.cs | 74 + .../DocumentObjectModel/Document.cs | 50 + .../DocumentObjectModel/DocumentElements.cs | 22 + .../DocumentObjectModel/DocumentInfo.cs | 24 + .../DocumentObjectModel/DocumentObject.cs | 17 + .../DocumentObjectModel/Font.cs | 159 + .../DocumentObjectModel/Footnote.cs | 27 + .../DocumentObjectModel/FormattedText.cs | 47 +- .../DocumentObjectModel/HeaderFooter.cs | 38 +- .../DocumentObjectModel/HeadersFooters.cs | 19 + .../DocumentObjectModel/Hyperlink.cs | 27 + .../DocumentObjectModel/ListInfo.cs | 11 + .../DocumentObjectModel/PageBreak.cs | 5 + .../DocumentObjectModel/PageSetup.cs | 60 + .../DocumentObjectModel/Paragraph.cs | 1197 ++++---- .../DocumentObjectModel/ParagraphElements.cs | 11 + .../DocumentObjectModel/ParagraphFormat.cs | 86 + .../DocumentObjectModel/Section.cs | 28 + .../DocumentObjectModel/Sections.cs | 15 + .../DocumentObjectModel/Shading.cs | 22 + .../DocumentObjectModel/Style.cs | 114 + .../DocumentObjectModel/Styles.cs | 79 + .../DocumentObjectModel/TabStop.cs | 28 + .../DocumentObjectModel/TabStops.cs | 19 + .../DocumentObjectModel/Text.cs | 12 + .../DocumentObjectModel/XmlSerializer.cs | 709 +++++ .../enums/SerializationFormat.cs | 45 + .../MigraDoc.DocumentObjectModel.csproj | 8 + 83 files changed, 7249 insertions(+), 587 deletions(-) create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/AttributeScanner.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlReader.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlWriter.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs create mode 100644 MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/SerializationFormat.cs diff --git a/MigraDoc/src/BuildAll-MigraDoc.sln b/MigraDoc/src/BuildAll-MigraDoc.sln index 59cbf21..60dd51b 100644 --- a/MigraDoc/src/BuildAll-MigraDoc.sln +++ b/MigraDoc/src/BuildAll-MigraDoc.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2003 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "!PDFsharp", "!PDFsharp", "{603BA43F-715B-471B-897B-871FD0EC35A8}" EndProject @@ -270,4 +270,7 @@ Global {6F98A822-41B0-4C7A-85A6-E95C1D3E88EF} = {603BA43F-715B-471B-897B-871FD0EC35A8} {CFDB7D46-EA8D-47DE-B10A-9E755A1B48BA} = {603BA43F-715B-471B-897B-871FD0EC35A8} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2B658173-198E-4C79-95CC-9C7FE8C6BCB7} + EndGlobalSection EndGlobal diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel-gdi/MigraDoc.DocumentObjectModel-gdi.csproj b/MigraDoc/src/MigraDoc.DocumentObjectModel-gdi/MigraDoc.DocumentObjectModel-gdi.csproj index 3815c11..e98624c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel-gdi/MigraDoc.DocumentObjectModel-gdi.csproj +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel-gdi/MigraDoc.DocumentObjectModel-gdi.csproj @@ -172,6 +172,24 @@ DocumentObjectModel.Internals\ValueDescriptor.cs + + DocumentObjectModel.IO.Xml\AttributeScanner.cs + + + DocumentObjectModel.IO.Xml\DdlParser.cs + + + DocumentObjectModel.IO.Xml\DdlReader.cs + + + DocumentObjectModel.IO.Xml\DdlWriter.cs + + + DocumentObjectModel.IO.Xml\Elements.cs + + + DocumentObjectModel.IO.Xml\enums\XmlSymbol.cs + DocumentObjectModel.IO\DdlParser.cs @@ -490,6 +508,9 @@ DocumentObjectModel\enums\ParagraphAlignment.cs + + DocumentObjectModel\enums\SerializationFormat.cs + DocumentObjectModel\enums\StyleType.cs @@ -589,6 +610,9 @@ DocumentObjectModel\VersionInfo.cs + + DocumentObjectModel\XmlSerializer.cs + Properties\AssemblyInfo.cs diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel-wpf/MigraDoc.DocumentObjectModel-wpf.csproj b/MigraDoc/src/MigraDoc.DocumentObjectModel-wpf/MigraDoc.DocumentObjectModel-wpf.csproj index b9f1b2a..dee2a91 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel-wpf/MigraDoc.DocumentObjectModel-wpf.csproj +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel-wpf/MigraDoc.DocumentObjectModel-wpf.csproj @@ -168,6 +168,24 @@ DocumentObjectModel.Internals\ValueDescriptor.cs + + DocumentObjectModel.IO.Xml\AttributeScanner.cs + + + DocumentObjectModel.IO.Xml\DdlParser.cs + + + DocumentObjectModel.IO.Xml\DdlReader.cs + + + DocumentObjectModel.IO.Xml\DdlWriter.cs + + + DocumentObjectModel.IO.Xml\Elements.cs + + + DocumentObjectModel.IO.Xml\enum\XmlSymbol.cs + DocumentObjectModel.IO\DdlParser.cs @@ -486,6 +504,9 @@ DocumentObjectModel\enums\ParagraphAlignment.cs + + DocumentObjectModel\enums\SerializationFormat.cs + DocumentObjectModel\enums\StyleType.cs @@ -585,6 +606,9 @@ DocumentObjectModel\VersionInfo.cs + + DocumentObjectModel\XmlSerializer.cs + Properties\AssemblyInfo.cs @@ -630,6 +654,7 @@ false + diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs index 0caf540..e79fe00 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs @@ -96,6 +96,21 @@ internal override void Serialize(Serializer serializer) serializer.Write("\\field(Bookmark)[Name = \"" + Name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"]"); } + internal override void Serialize(XmlSerializer serializer) + { + if (_name.Value == string.Empty) + throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "BookmarkField")); + + //serializer.Write("\\field(Bookmark)[Name = \"" + Name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"]"); + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Name", Name); + serializer.WriteSimpleAttribute("Type", "Bookmark"); + + serializer.WriteEndElement(); + } + + /// /// Determines whether this instance is null (not set). /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/DateField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/DateField.cs index 7029ce7..0c0d8cc 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/DateField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/DateField.cs @@ -88,6 +88,19 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "Date"); + if (_format.Value != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + + serializer.WriteEndElement(); + } + + /// /// Determines whether this instance is null (not set). /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs index 2ba8be1..1a2bef6 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs @@ -132,6 +132,23 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "Info"); + + //string str = "\\field(Info)"; + if (Name == "") + throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "InfoField")); + //str += "[Name = \"" + Name + "\"]"; + serializer.WriteSimpleAttribute("Name", Name); + + //serializer.Write(str); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumPagesField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumPagesField.cs index dcdeebf..5a9fda4 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumPagesField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumPagesField.cs @@ -76,6 +76,17 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "NumPages"); + if (_format.Value != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageField.cs index c626ff0..7264731 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageField.cs @@ -76,6 +76,17 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "Page"); + if (_format.Value != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageRefField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageRefField.cs index 27e2c2f..36e19d1 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageRefField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/PageRefField.cs @@ -98,6 +98,21 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "PageRef"); + + serializer.WriteSimpleAttribute("Name", Name); + + if (_format.Value != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + + serializer.WriteEndElement(); + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionField.cs index dac7e0d..2ad0539 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionField.cs @@ -76,6 +76,17 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "Section"); + if (_format.Value != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionPagesField.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionPagesField.cs index fd204ae..a61855c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionPagesField.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/SectionPagesField.cs @@ -76,6 +76,18 @@ internal override void Serialize(Serializer serializer) serializer.Write(str); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Field"); + + serializer.WriteSimpleAttribute("Type", "SectionPages"); + if (_format.Value != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + + serializer.WriteEndElement(); + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/AttributeScanner.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/AttributeScanner.cs new file mode 100644 index 0000000..c1efad2 --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/AttributeScanner.cs @@ -0,0 +1,117 @@ + + +using System; +using System.Globalization; + +namespace MigraDoc.DocumentObjectModel.IO.Xml +{ + internal class AttributeScanner + { + public string Token { get; private set; } + + private bool ignoreBlank; + private string text; + private int idx; + + public AttributeScanner(string text, bool ignoreBlank = true) + { + this.text = text; + this.Token = ""; + this.idx = 0; + this.ignoreBlank = ignoreBlank; + } + + internal void Scan(char separator) + { + this.Token = ""; + + while (idx < text.Length) + { + if (text[idx] == separator) + { + idx++; + break; + } + else + { + if (ignoreBlank) + { + if (!IsWhiteSpace(text[idx])) + this.Token += text[idx]; + } + else + this.Token += text[idx]; + + idx++; + } + } + + //Text.Remove(0, i); + } + + internal bool PeekChar(char ch) + { + var i = idx; + + while (i < text.Length) + { + if (ignoreBlank) + { + if (!IsWhiteSpace(text[i])) + if (text[i] == ch) + return true; + + } + else + if (text[i] == ch) + return true; + + i++; + + } + + return false; + + } + + + + + internal uint GetTokenValueAsUInt() + { + if (Token.Length > 2 && Token.ToLower().StartsWith("0x")) + { + string number = Token.Substring(2); + return UInt32.Parse(number, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); + } + + if (IsIntegerLiteral(Token)) + return UInt32.Parse(Token, CultureInfo.InvariantCulture); + + return 0; + } + + internal static bool IsWhiteSpace(char ch) + { + return Char.IsWhiteSpace(ch); + } + + internal static bool IsIntegerLiteral(string value) + { + UInt32 i; + return UInt32.TryParse(value, out i); + } + + internal static bool IsHexIntegerLiteral(string value) + { + if (value.Length > 2 && value.ToLower().StartsWith("0x")) + { + string number = value.Substring(2); + UInt32 i; + return UInt32.TryParse(number, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out i); + } + else + return false; + } + } +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs new file mode 100644 index 0000000..25740ca --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -0,0 +1,2609 @@ +#region MigraDoc - Creating Documents on the Fly +// +// Authors: +// Stefan Lange +// Klaus Potzesny +// David Stephensen +// +// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany) +// +// http://www.pdfsharp.com +// http://www.migradoc.com +// http://sourceforge.net/projects/pdfsharp +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Diagnostics; +using System.Globalization; +using MigraDoc.DocumentObjectModel.Internals; +using MigraDoc.DocumentObjectModel.Tables; +using MigraDoc.DocumentObjectModel.Shapes; +using MigraDoc.DocumentObjectModel.Shapes.Charts; +using System.Xml; +using System.Collections.Generic; +using AttrDictionary = System.Collections.Generic.Dictionary; +using AttributePair = System.Collections.Generic.KeyValuePair; + +namespace MigraDoc.DocumentObjectModel.IO.Xml +{ + /// + /// An Xml parser for MigraDoc DDL. + /// + internal class DdlParser + { + /// + /// Initializes a new instance of the DdlParser class. + /// + internal DdlParser(string ddl, DdlReaderErrors errors) + : this(String.Empty, ddl, errors) + { } + + /// + /// Initializes a new instance of the DdlParser class. + /// + internal DdlParser(string fileName, string ddl, DdlReaderErrors errors) + { + _errors = errors ?? new DdlReaderErrors(); + + _fileName = fileName; + + var readerSettings = new XmlReaderSettings() + { + IgnoreComments = true, + IgnoreProcessingInstructions = true, + IgnoreWhitespace = true, + }; + + if (_fileName == String.Empty) + _reader = XmlReader.Create(new System.IO.StringReader(ddl), readerSettings); + else + _reader = XmlReader.Create(_fileName, readerSettings); + } + + /// + /// Parses the keyword «». + /// + internal Document ParseDocument(Document document) + { + + if (document == null) + document = new Document(); + + AssertSymbol(XmlSymbol.Document); + + ParseAttributes(document); + + // Styles come first + if (XmlSymbol == XmlSymbol.Styles) + ParseStyles(document.Styles); + + // A document with no sections is valid and has zero pages. + if (XmlSymbol == XmlSymbol.Sections) + ParseSections(document.Sections); + + MoveNext(); + AssertCondition(XmlSymbol == XmlSymbol.Eof, DomMsgID.EndOfFileExpected); + + return document; + } + + /// + /// Parses one of the keywords «\document», «\styles», «\section», «\table», «\textframe», «\chart» + /// and «\paragraph» and returns the corresponding DocumentObject or DocumentObjectCollection. + /// + internal DocumentObject ParseDocumentObject() + { + DocumentObject obj = null; + + // MoveToCode(); + switch (XmlSymbol) + { + case XmlSymbol.Document: + obj = ParseDocument(null); + break; + + case XmlSymbol.Styles: + obj = ParseStyles(new Styles()); + break; + + case XmlSymbol.Section: + obj = ParseSection(new Sections()); + break; + + case XmlSymbol.Table: + obj = new Table(); + ParseTable(null, (Table)obj); + break; + + case XmlSymbol.TextFrame: + DocumentElements elems = new DocumentElements(); + ParseTextFrame(elems); + obj = elems[0]; + break; + + case XmlSymbol.Chart: + throw new NotImplementedException(); + + case XmlSymbol.Paragraph: + obj = new DocumentElements(); + ParseParagraph((DocumentElements)obj); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol); + break; + } + + MoveNext(); + AssertCondition(XmlSymbol == XmlSymbol.Eof, DomMsgID.EndOfFileExpected); + + return obj; + } + + /// + /// Parses the keyword «\styles». + /// + private Styles ParseStyles(Styles styles) + { + AssertSymbol(XmlSymbol.Styles); + MoveNext(); + + while (!IsEndElement(XmlSymbol.Styles)) + ParseStyleDefinition(styles); + + AssertSymbol(XmlSymbol.Styles, true); + MoveNext(); + + return styles; + } + + /// + /// Parses the keyword «\sections». + /// + private Sections ParseSections(Sections sections) + { + AssertSymbol(XmlSymbol.Sections); + MoveNext(); + + while (!IsEndElement(XmlSymbol.Sections)) + ParseSection(sections); + + AssertSymbol(XmlSymbol.Sections, true); + MoveNext(); + + return sections; + } + + /// + /// Parses a style definition block within the keyword «\styles». + /// + private Style ParseStyleDefinition(Styles styles) + { + // + + AssertSymbol(XmlSymbol.Style); + var attributes = ParseElementAttributes(); + + Style style = null; + try + { + var styleName = GetAttributeValue(attributes, "Name", true); + var baseStyleName = GetAttributeValue(attributes, "BaseStyle", true); + + if (String.IsNullOrEmpty(styleName)) + ThrowParserException(DomMsgID.StyleNameExpected, styleName); + + if (!String.IsNullOrEmpty(baseStyleName)) + { + if (styles.GetIndex(baseStyleName) == -1) + { + ReportParserInfo(DdlErrorLevel.Warning, DomMsgID.UseOfUndefinedBaseStyle, baseStyleName); + baseStyleName = StyleNames.InvalidStyleName; + } + } + + // Get or create style. + style = styles[styleName]; + if (style != null) + { + // Reset base style. + if (baseStyleName != null) + style.BaseStyle = baseStyleName; + } + else + { + // Style does not exist and no base style is given, choose InvalidStyleName by default. + if (String.IsNullOrEmpty(baseStyleName)) + { + baseStyleName = StyleNames.InvalidStyleName; + ReportParserInfo(DdlErrorLevel.Warning, DomMsgID.UseOfUndefinedStyle, styleName); + } + + style = styles.AddStyle(styleName, baseStyleName); + } + + // Parse definition (if any). + if (IsStartElement()) + { + + MoveNext(); + + while (!IsEndElement(XmlSymbol.Style)) + ParseAttributeBlock(style); + + AssertSymbol(XmlSymbol.Style, true); + } + + MoveNext(); + + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(XmlSymbol.Style); + } + + return style; + } + + /// + /// Determines if the current symbol is a header or footer. + /// + private bool IsHeaderFooter() + { + XmlSymbol sym = XmlSymbol; + return (sym == XmlSymbol.Header || sym == XmlSymbol.Footer || + sym == XmlSymbol.PrimaryHeader || sym == XmlSymbol.PrimaryFooter || + sym == XmlSymbol.EvenPageHeader || sym == XmlSymbol.EvenPageFooter || + sym == XmlSymbol.FirstPageHeader || sym == XmlSymbol.FirstPageFooter); + } + + /// + /// Parses the keyword «\section». + /// + private Section ParseSection(Sections sections) + { + Debug.Assert(sections != null); + + AssertSymbol(XmlSymbol.Section); + + Section section = null; + try + { + section = sections.AddSection(); + + ParseAttributes(section); + + // TODO + // Consider the case that the keyword «\paragraph» can be omitted. + + // 1st parse headers and footers + while (IsHeaderFooter()) + ParseHeaderFooter(section); + + // 2nd parse all other stuff + ParseDocumentElements(section.Elements, XmlSymbol.Section); + + AssertSymbol(XmlSymbol.Section, true); + MoveNext(); + + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(XmlSymbol.Section); + } + return section; + } + + /// + /// Parses the keywords «\header». + /// + private void ParseHeaderFooter(Section section) + { + if (section == null) + throw new ArgumentNullException("section"); + + XmlSymbol hdrFtrSym = XmlSymbol; + + try + { + bool isHeader = hdrFtrSym == XmlSymbol.Header || + hdrFtrSym == XmlSymbol.PrimaryHeader || + hdrFtrSym == XmlSymbol.FirstPageHeader || + hdrFtrSym == XmlSymbol.EvenPageHeader; + + // Recall that the styles "Header" resp. "Footer" are used as default if + // no other style was given. But this belongs to the rendering process, + // not to the DDL parser. Therefore no code here belongs to that. + HeaderFooter headerFooter = new HeaderFooter(); + + ParseAttributes(headerFooter); + + ParseDocumentElements(headerFooter.Elements, hdrFtrSym); + + HeadersFooters headersFooters = isHeader ? section.Headers : section.Footers; + if (hdrFtrSym == XmlSymbol.Header || hdrFtrSym == XmlSymbol.Footer) + { + headersFooters.Primary = headerFooter.Clone(); + headersFooters.EvenPage = headerFooter.Clone(); + headersFooters.FirstPage = headerFooter.Clone(); + } + else + { + switch (hdrFtrSym) + { + case XmlSymbol.PrimaryHeader: + case XmlSymbol.PrimaryFooter: + headersFooters.Primary = headerFooter; + break; + + case XmlSymbol.EvenPageHeader: + case XmlSymbol.EvenPageFooter: + headersFooters.EvenPage = headerFooter; + break; + + case XmlSymbol.FirstPageHeader: + case XmlSymbol.FirstPageFooter: + headersFooters.FirstPage = headerFooter; + break; + } + } + + AssertSymbol(hdrFtrSym, true); + MoveNext(); + + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(hdrFtrSym); + } + } + + // TODO + + /// + /// Determines whether the next text is paragraph content or document element. + /// + /*private bool IsParagraphContent() + { + + if (MoveToParagraphContent()) + { + if (_scanner.Char == Chars.BackSlash) + { + XmlSymbol symbol = _scanner.PeekKeyword(); + switch (symbol) + { + case XmlSymbol.Bold: + case XmlSymbol.Italic: + case XmlSymbol.Underline: + case XmlSymbol.Field: + case XmlSymbol.Font: + case XmlSymbol.FontColor: + case XmlSymbol.FontSize: + case XmlSymbol.Footnote: + case XmlSymbol.Hyperlink: + case XmlSymbol.Symbol: + case XmlSymbol.Chr: + case XmlSymbol.Tab: + case XmlSymbol.LineBreak: + case XmlSymbol.Space: + case XmlSymbol.SoftHyphen: + return true; + } + return false; + } + return true; + } + return false; + + + + }*/ + + /// + /// Parses the document elements of a «\paragraph», «\cell» or comparable. + /// + private DocumentElements ParseDocumentElements(DocumentElements elements, XmlSymbol context) + { + // + // This is clear: + // \section { Hallo World! } + // All section content will be treated as paragraph content. + // + // but this is ambiguous: + // \section { \image(...) } + // It could be an image inside a paragraph or at the section level. + // In this case it will be treated as an image on section level. + // + // If this is not your intention it must be like this: + // \section { \paragraph { \image(...) } } + // + + while (!IsEndElement(context)) + { + + switch (XmlSymbol) + { + case XmlSymbol.Paragraph: + ParseParagraph(elements); + break; + + case XmlSymbol.PageBreak: + ParsePageBreak(elements); + break; + + case XmlSymbol.Table: + ParseTable(elements, null); + break; + + case XmlSymbol.TextFrame: + ParseTextFrame(elements); + break; + + case XmlSymbol.Image: + ParseImage(elements.AddImage(""), false); + break; + + case XmlSymbol.Chart: + ParseChart(elements); + break; + + case XmlSymbol.Barcode: + ParseBarcode(elements); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + + } + + return elements; + } + + /// + /// Parses the keyword «\paragraph». + /// + private void ParseParagraph(DocumentElements elements) + { + AssertSymbol(XmlSymbol.Paragraph); + + Paragraph paragraph = elements.AddParagraph(); + + try + { + + var hasContent = IsStartElement(); + + ParseAttributes(paragraph, null, false); + + if (hasContent) + { + ParseParagraphContent(elements, paragraph); + + AssertSymbol(XmlSymbol.Paragraph, true); + } + + MoveNext(); + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(XmlSymbol.Paragraph); + } + + } + + /// + /// Parses the inner text of a paragraph, i.e. stops on BraceRight and treats empty + /// line as paragraph separator. + /// + + + private void ParseParagraphContent(DocumentElements elements, Paragraph paragraph) + { + + Paragraph para = paragraph ?? elements.AddParagraph(); + + while (!IsEndElement(XmlSymbol.Paragraph)) + ParseFormattedText(para.Elements); + + } + + + /// + /// Removes the last blank from the text. Used before a tab, a linebreak or a space will be + /// added to the text. + /// + private void RemoveTrailingBlank(ParagraphElements elements) + { + DocumentObject dom = elements.LastObject; + Text text = dom as Text; + if (text != null) + { + if (text.Content.EndsWith(" ")) + text.Content = text.Content.Remove(text.Content.Length - 1, 1); + } + } + + /// + /// Parses the inner text of a paragraph. Parsing ends if '}' is reached or an empty + /// line occurs on nesting level 0. + /// + + private void ParseFormattedText(ParagraphElements elements) + { + string text; + + bool loop = true; + while (loop) + { + switch (_reader.NodeType) + { + case XmlNodeType.Element: + + switch (XmlSymbol) + { + // TODO + /* + case XmlSymbol.EmptyLine: + elements.AddCharacter(SymbolName.ParaBreak); + ReadText(rootLevel); + break;*/ + + /* + case XmlSymbol.Comment: + // Ignore comments. + ReadText(rootLevel); + break; + */ + + case XmlSymbol.Tab: + RemoveTrailingBlank(elements); + elements.AddTab(); + MoveNext(false); + break; + + case XmlSymbol.LineBreak: + RemoveTrailingBlank(elements); + elements.AddLineBreak(); + MoveNext(false); + break; + + case XmlSymbol.Bold: + ParseBoldItalicEtc(elements.AddFormattedText(TextFormat.Bold), XmlSymbol.Bold); + break; + + case XmlSymbol.Italic: + ParseBoldItalicEtc(elements.AddFormattedText(TextFormat.Italic), XmlSymbol.Italic); + break; + + case XmlSymbol.Underline: + ParseBoldItalicEtc(elements.AddFormattedText(TextFormat.Underline), XmlSymbol.Underline); + + break; + + case XmlSymbol.Font: + ParseFont(elements.AddFormattedText()); + + break; + + case XmlSymbol.FontSize: + ParseFontSize(elements.AddFormattedText()); + + break; + + case XmlSymbol.FontColor: + ParseFontColor(elements.AddFormattedText()); + + break; + + case XmlSymbol.Image: + ParseImage(elements.AddImage(""), true); + + break; + + case XmlSymbol.Field: + ParseField(elements); + + break; + + case XmlSymbol.Footnote: + ParseFootnote(elements); + + break; + + case XmlSymbol.Hyperlink: + ParseHyperlink(elements); + + break; + + case XmlSymbol.Space: + RemoveTrailingBlank(elements); + ParseSpace(elements); + + break; + + case XmlSymbol.Symbol: + ParseSymbol(elements); + break; + + case XmlSymbol.Chr: + ParseChr(elements); + + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + break; + case XmlNodeType.EndElement: + + loop = false; + break; + case XmlNodeType.Text: + + text = RemoveTrailingWhiteSpace(RemoveLeadingWhiteSpace(_reader.Value)); + + if (text != String.Empty) + elements.AddText(text); + + MoveNext(); + break; + case XmlNodeType.CDATA: + + text = _reader.Value; + + if (text != String.Empty) + elements.AddText(text); + + MoveNext(); + break; + default: + break; + } + } + } + + /// + /// Parses the keywords «\bold», «\italic», and «\underline». + /// + private void ParseBoldItalicEtc(FormattedText formattedText, XmlSymbol symbol) + { + + AssertSymbol(symbol); + + if (IsStartElement()) + { + ParseFormattedText(formattedText.Elements); + + AssertSymbol(symbol, true); + } + + MoveNext(false); + + } + + /// + /// Parses the keyword «\font». + /// + private void ParseFont(FormattedText formattedText) + { + AssertSymbol(XmlSymbol.Font); + + var hasContent = IsStartElement(); + ParseAttributes(formattedText, null, false); + + if (hasContent) + { + ParseFormattedText(formattedText.Elements); + + AssertSymbol(XmlSymbol.Font, true); + } + + MoveNext(false); + } + + /// + /// Parses the keyword «\fontsize». + /// + private void ParseFontSize(FormattedText formattedText) + { + AssertSymbol(XmlSymbol.FontSize); + + var hasContent = IsStartElement(); + var attributes = ParseElementAttributes(); + + var size = GetAttributeValue(attributes, "Size"); + if (size != null) + //NYI: Check token for correct Unit format + formattedText.Font.Size = size; + + if (hasContent) + { + MoveNext(false); + + ParseFormattedText(formattedText.Elements); + AssertSymbol(XmlSymbol.FontSize, true); + } + + MoveNext(false); + } + + /// + /// Parses the keyword «\fontcolor». + /// + private void ParseFontColor(FormattedText formattedText/*, string value*/) + { + + AssertSymbol(XmlSymbol.FontColor); + + var hasContent = IsStartElement(); + var attributes = ParseElementAttributes(); + + var color = GetAttributeValue(attributes, "Color"); + if (color != null) + { + Color c = ParseColor(color); + formattedText.Font.Color = c; + } + + if (hasContent) + { + MoveNext(false); + + ParseFormattedText(formattedText.Elements); + AssertSymbol(XmlSymbol.FontColor, true); + } + + MoveNext(false); + } + + // TODO + /// + /// Parses the keyword «\symbol» resp. «\(». + /// + private void ParseSymbol(ParagraphElements elements) + { + throw new NotImplementedException(); + } + + // TODO + /// + /// Parses the keyword «\chr». + /// + private void ParseChr(ParagraphElements elements) + { + throw new NotImplementedException(); + + } + + /// + /// Parses the keyword «\field». + /// + private void ParseField(ParagraphElements elements) + { + + AssertSymbol(XmlSymbol.Field); + + var attributes = ParseElementAttributes(); + + string fieldType = GetAttributeValue(attributes, "Type", true); + AssertCondition(fieldType != null, DomMsgID.MissingObligatoryProperty, "Type"); + + DocumentObject field = null; + switch (fieldType.ToLower()) + { + case "date": + field = elements.AddDateField(); + break; + + case "page": + field = elements.AddPageField(); + break; + + case "numpages": + field = elements.AddNumPagesField(); + break; + + case "info": + field = elements.AddInfoField(0); + break; + + case "sectionpages": + field = elements.AddSectionPagesField(); + break; + + case "section": + field = elements.AddSectionField(); + break; + + case "bookmark": + field = elements.AddBookmark(""); + break; + + case "pageref": + field = elements.AddPageRefField(""); + break; + } + + AssertCondition(field != null, DomMsgID.InvalidFieldType, fieldType); + + ParseAttributes(field, attributes); + + MoveNext(false); + } + + /// + /// Parses the keyword «\footnote». + /// + private void ParseFootnote(ParagraphElements elements) + { + AssertSymbol(XmlSymbol.Footnote); + + Footnote footnote = elements.AddFootnote(); + + ParseAttributes(footnote); + ParseDocumentElements(footnote.Elements, XmlSymbol.Footnote); + + AssertSymbol(XmlSymbol.Footnote, true); + MoveNext(false); + + } + + /// + /// Parses the keyword «\hyperlink». + /// + private void ParseHyperlink(ParagraphElements elements) + { + AssertSymbol(XmlSymbol.Hyperlink); + + Hyperlink hyperlink = elements.AddHyperlink(""); + //NYI: Without name and type the hyperlink is senseless, so attributes need to be checked + + var hasContent = IsStartElement(); + ParseAttributes(hyperlink, null, false); + + if (hasContent) + { + while (!IsEndElement(XmlSymbol.Hyperlink)) + ParseFormattedText(hyperlink.Elements); + + AssertSymbol(XmlSymbol.Hyperlink, true); + } + + MoveNext(false); + } + + + // TODO + /// + /// + /// Parses the keyword «\space». + /// + private void ParseSpace(ParagraphElements elements) + { + // Samples + // + // + // + // + + AssertSymbol(XmlSymbol.Space); + + Character space = elements.AddSpace(1); + + var attributes = ParseElementAttributes(); + + var type = GetAttributeValue(attributes, "Type"); + if (type != null) + { + if (!IsSpaceType(type)) + ThrowParserException(DomMsgID.InvalidEnum, type); + + space.SymbolName = (SymbolName)Enum.Parse(typeof(SymbolName), type, true); + } + + var count = GetAttributeValue(attributes, "Count"); + if (count != null) + space.Count = Int32.Parse(count); + + MoveNext(); + } + + + /// + /// Parses a page break in a document elements container. + /// + private void ParsePageBreak(DocumentElements elements) + { + AssertSymbol(XmlSymbol.PageBreak); + elements.AddPageBreak(); + + AssertSymbol(XmlSymbol.PageBreak, true); + MoveNext(false); + } + + /// + /// Parses the keyword «\table». + /// + private void ParseTable(DocumentElements elements, Table table) + { + Table tbl = table; + try + { + if (tbl == null) + tbl = elements.AddTable(); + + AssertSymbol(XmlSymbol.Table); + var attributes = ParseElementAttributes(); + + ParseAttributes(tbl, attributes); + + // Table must start with «\columns»... + AssertSymbol(XmlSymbol.Columns); + ParseColumns(tbl); + + // ...followed by «\rows». + AssertSymbol(XmlSymbol.Rows); + ParseRows(tbl); + + AssertSymbol(XmlSymbol.Table, true); + MoveNext(); + + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(XmlSymbol.Table); + } + } + + /// + /// Parses the keyword «\columns». + /// + private void ParseColumns(Table table) + { + Debug.Assert(table != null); + Debug.Assert(XmlSymbol == XmlSymbol.Columns); + + ParseAttributes(table.Columns); + + while (!IsEndElement(XmlSymbol.Columns)) + { + switch (XmlSymbol) + { + case XmlSymbol.Column: + ParseColumn(table.AddColumn()); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + + } + } + + AssertSymbol(XmlSymbol.Columns, true); + MoveNext(); + } + + /// + /// Parses the keyword «\column». + /// + private void ParseColumn(Column column) + { + Debug.Assert(column != null); + Debug.Assert(XmlSymbol == XmlSymbol.Column); + + ParseAttributes(column); + + AssertSymbol(XmlSymbol.Column, true); + MoveNext(); + } + + /// + /// Parses the keyword «\rows». + /// + private void ParseRows(Table table) + { + Debug.Assert(table != null); + Debug.Assert(XmlSymbol == XmlSymbol.Rows); + + ParseAttributes(table.Rows); + + while (!IsEndElement(XmlSymbol.Rows)) + { + + switch (XmlSymbol) + { + case XmlSymbol.Row: + ParseRow(table.AddRow()); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + } + + AssertSymbol(XmlSymbol.Rows, true); + MoveNext(); + } + + /// + /// Parses the keyword «\row». + /// + private void ParseRow(Row row) + { + Debug.Assert(row != null); + Debug.Assert(XmlSymbol == XmlSymbol.Row); + + ParseAttributes(row); + + int idx = 0; + + while (!IsEndElement(XmlSymbol.Row)) + { + + switch (XmlSymbol) + { + + case XmlSymbol.Cell: + ParseCell(row[idx]); + idx++; + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + } + + AssertSymbol(XmlSymbol.Row, true); + MoveNext(); + } + + /// + /// Parses the keyword «\cell». + /// + private void ParseCell(Cell cell) + { + Debug.Assert(cell != null); + Debug.Assert(XmlSymbol == XmlSymbol.Cell); + + var hasContent = IsStartElement(); + + ParseAttributes(cell); + + if (hasContent) + { + ParseDocumentElements(cell.Elements, XmlSymbol.Cell); + AssertSymbol(XmlSymbol.Cell, true); + } + + MoveNext(); + + } + + /// + /// Parses the keyword «\image». + /// + private void ParseImage(Image image, bool paragraphContent) + { + // Future syntax by example + // \image("Name") + // \image("Name")[...] + // \image{base64...} //NYI + // \image[...]{base64...} //NYI + Debug.Assert(image != null); + + try + { + + AssertSymbol(XmlSymbol.Image); + + var attributes = ParseElementAttributes(); + image.Name = GetAttributeValue(attributes, "Name", true); + + ParseAttributes(image, attributes); + + AssertSymbol(XmlSymbol.Image, true); + MoveNext(false); + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(XmlSymbol.Image); + } + } + + /// + /// Parses the keyword «\textframe». + /// + private void ParseTextFrame(DocumentElements elements) + { + Debug.Assert(elements != null); + + TextFrame textFrame = elements.AddTextFrame(); + try + { + var hasContent = IsStartElement(); + + ParseAttributes(textFrame); + + if (hasContent) + { + ParseDocumentElements(textFrame.Elements, XmlSymbol.TextFrame); + AssertSymbol(XmlSymbol.TextFrame, true); + } + + MoveNext(); + + } + catch (DdlParserException ex) + { + ReportParserException(ex); + AdjustToNextBlock(XmlSymbol.TextFrame); + } + } + + // TODO + private void ParseBarcode(DocumentElements elements) + { + // Syntax: + // 1. \barcode(Code) + // 2. \barcode(Code)[...] + // 3. \barcode(Code, Type) + // 4. \barcode(Code, Type)[...] + + try + { + AssertSymbol(XmlSymbol.Barcode); + + Barcode barcode = elements.AddBarcode(); + + ParseAttributes(barcode); + + AssertSymbol(XmlSymbol.Barcode, true); + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.Barcode); + } + } + + + // TODO + /// + /// Parses the keyword «\chart». + /// + private void ParseChart(DocumentElements elements) + { + // Syntax: + // 1. \chartarea(Type){...} + // 2. \chartarea(Type)[...]{...} + // + // Usage of header-, bottom-, footer-, left- and rightarea are similar. + + ChartType chartType = 0; + try + { + AssertSymbol(XmlSymbol.Chart); + + var attributes = ParseElementAttributes(); + + string chartTypeName = GetAttributeValue(attributes, "Type", true); + + try + { + chartType = (ChartType)Enum.Parse(typeof(ChartType), chartTypeName, true); + } + catch (Exception ex) + { + ThrowParserException(ex, DomMsgID.UnknownChartType, chartTypeName); + } + + Chart chart = elements.AddChart(chartType); + + ParseAttributes(chart, attributes); + + while (!IsEndElement(XmlSymbol.Chart)) + { + switch (XmlSymbol) + { + case XmlSymbol.PlotArea: + ParseArea(chart.PlotArea); + break; + + case XmlSymbol.HeaderArea: + ParseArea(chart.HeaderArea); + break; + + case XmlSymbol.FooterArea: + ParseArea(chart.FooterArea); + break; + + case XmlSymbol.TopArea: + ParseArea(chart.TopArea); + break; + + case XmlSymbol.BottomArea: + ParseArea(chart.BottomArea); + break; + + case XmlSymbol.LeftArea: + ParseArea(chart.LeftArea); + break; + + case XmlSymbol.RightArea: + ParseArea(chart.RightArea); + break; + + case XmlSymbol.XAxis: + ParseAxes(chart.XAxis, XmlSymbol); + break; + + case XmlSymbol.YAxis: + ParseAxes(chart.YAxis, XmlSymbol); + break; + + case XmlSymbol.ZAxis: + ParseAxes(chart.ZAxis, XmlSymbol); + break; + + case XmlSymbol.Series: + ParseSeries(chart.SeriesCollection.AddSeries()); + break; + + case XmlSymbol.XSeries: + ParseSeries(chart.XValues.AddXSeries()); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + } + + AssertSymbol(XmlSymbol.Chart, true); + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.Chart); + } + } + + /// + /// Parses the keyword «\plotarea» inside a chart. + /// + private void ParseArea(PlotArea area) + { + // Syntax: + // 1. \plotarea{...} + // 2. \plotarea[...]{...} //??? + + try + { + ParseAttributes(area); + MoveNext(); + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.PlotArea); + } + } + + /// + /// Parses the keywords «\headerarea», «\toparea», «\bottomarea», «\footerarea», + /// «\leftarea» or «\rightarea» inside a chart. + /// + private void ParseArea(TextArea area) + { + // Syntax: + // 1. \toparea{...} + // 2. \toparea[...]{...} + // + // Usage of header-, bottom-, footer-, left- and rightarea are similar. + + string name = _reader.Name; + + try + { + + ParseAttributes(area); + + switch (XmlSymbol) + { + case XmlSymbol.Legend: + ParseLegend(area.AddLegend()); + break; + + case XmlSymbol.Paragraph: + ParseParagraph(area.Elements); + break; + + case XmlSymbol.Table: + ParseTable(null, area.AddTable()); + break; + + case XmlSymbol.TextFrame: + ParseTextFrame(area.Elements); + break; + + case XmlSymbol.Image: + Image image = new Image(); + ParseImage(image, false); + area.Elements.Add(image); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + + MoveNext(); + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(name); + } + } + + /// + /// Parses the keywords «\xaxis», «\yaxis» or «\zaxis» inside a chart. + /// + private void ParseAxes(Axis axis, XmlSymbol symbolAxis) + { + // Syntax: + // 1. \xaxis[...] + // 2. \xaxis[...]{...} //??? + // + // Usage of yaxis and zaxis are similar. + + string name = _reader.Name; + + try + { + ParseAttributes(axis); + + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(name); + } + } + + // TODO + + /// + /// Parses the keyword «\series» inside a chart. + /// + private void ParseSeries(Series series) + { + // Syntax: + // 1. \series{...} + // 2. \series[...]{...} + + try + { + AssertSymbol(XmlSymbol.Series); + + ParseAttributes(series); + + while (!IsEndElement(XmlSymbol.Series)) + { + switch (XmlSymbol) + { + case XmlSymbol.Point: + ParsePoint(series.Add(0.0)); + break; + + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + } + + AssertSymbol(XmlSymbol.Series, true); + MoveNext(); + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.Series); + } + } + + // TODO + + /// + /// Parses the keyword «\xvalues» inside a chart. + /// + private void ParseSeries(XSeries series) + { + // Syntax: + // 1. \xvalues{...} + + try + { + + AssertSymbol(XmlSymbol.XSeries); + + ParseAttributes(series); + + while (!IsEndElement(XmlSymbol.XSeries)) + { + switch (XmlSymbol) + { + case XmlSymbol.XValue: + ParseXValue(series.Add(String.Empty)); + break; + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + } + + AssertSymbol(XmlSymbol.XSeries, true); + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.XSeries); + } + } + + // TODO + + /// + /// Parses the keyword «\point» inside a series. + /// + private void ParsePoint(Point point) + { + // Syntax: + // 1. \point{...} + // 2. \point[...]{...} + + try + { + AssertSymbol(XmlSymbol.Point); + + var hasContent = IsStartElement(); + ParseAttributes(point, null, false); + + if (hasContent) + { + point.Value = Double.Parse(ReadText()); + AssertSymbol(XmlSymbol.Point, true); + } + + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.Point); + } + } + + + private void ParseXValue(XValue xValue) + { + try + { + AssertSymbol(XmlSymbol.XValue); + + var hasContent = IsStartElement(); + ParseAttributes(xValue, null, false); + + if (hasContent) + { + xValue.Value = ReadText(); + + AssertSymbol(XmlSymbol.XValue, true); + } + + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.XValue); + } + } + + + /// + /// Parses the keyword «\legend» inside a textarea. + /// + private void ParseLegend(Legend legend) + { + // Syntax: + // 1. \legend + // 2. \legend[...] + // 3. \legend[...]{...} + + try + { + ParseAttributes(legend); + MoveNext(); + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.Legend); + } + } + + /// + /// Parses an attribute declaration block enclosed in brackets «[…]». + /// + private void ParseAttributes(DocumentObject element, AttrDictionary attributes = null, bool skipText = true) + { + + if (attributes == null) + attributes = ParseElementAttributes(); + + foreach (var attribute in attributes) + ParseAttributeStatement(element, attribute); + + if (IsStartElement()) + { + //bool hasAttributes = ; + MoveNext(skipText); + + while (IsStartElement(XmlSymbol.Attributes) || IsEmptyElement(XmlSymbol.Attributes)) + { + if (IsStartElement(XmlSymbol.Attributes)) + { + MoveNext(); + while (!IsEndElement(XmlSymbol.Attributes)) + ParseAttributeBlock(element); + + AssertSymbol(XmlSymbol.Attributes, true); + MoveNext(skipText); + } + else if (IsEmptyElement(XmlSymbol.Attributes)) + MoveNext(skipText); + } + + } + + } + + /// + /// Parses a single statement in an attribute declaration block. + /// + private void ParseAttributeStatement(DocumentObject doc, AttributePair attribute) + { + + // Syntax is easy + // identifier: xxxxx + // or + // sequence of identifiers: xxx.yyy.zzz + // + // followed by: «=», «+=», «-=», or «{» + // + // Parser of rhs depends on the type of the l-value. + + if (doc == null) + throw new ArgumentNullException("doc"); + + string valueName = ""; + try + { + valueName = attribute.Key; + + // Assign + //DomValueDescriptor is needed from assignment routine. + + // TODO + // Assert doc.Meta[valueName] + + ValueDescriptor pvd = null; + + try + { + pvd = doc.Meta[valueName]; + } + catch + { + } + + AssertCondition(pvd != null, DomMsgID.InvalidValueName, valueName); + ParseAssign(doc, pvd, attribute); + } + catch (DdlParserException ex) + { + ReportParserException(ex); + //AdjustToNextBlock(); + } + catch (ArgumentException e) + { + ReportParserException(e, DomMsgID.InvalidAssignment, valueName); + } + } + + /// + /// Parses an attribute declaration block enclosed in braces «{…}». + /// + private void ParseAttributeBlock(DocumentObject element) + { + var valueName = _reader.Name; + + //hack + if (String.Compare(valueName, "TabStops", StringComparison.OrdinalIgnoreCase) == 0) + { + + if (!(element is ParagraphFormat)) + ThrowParserException(DomMsgID.SymbolNotAllowed, valueName); + + ParseTabStops((element as ParagraphFormat).TabStops); + + } + else + { + try + { + object val = null; + try + { + val = element.GetValue(valueName); + } + catch + { + } + + AssertCondition(val != null, DomMsgID.InvalidValueName, valueName); + + DocumentObject child = val as DocumentObject; + if (child != null) + { + + AttrDictionary attributes = ParseElementAttributes(); + + foreach (var attribute in attributes) + ParseAttributeStatement(child, attribute); + + // parse child elements if any + if (IsStartElement()) + { + string name = _reader.Name; + MoveNext(); + while (!IsEndElement(name)) + ParseAttributeBlock(child); + } + + MoveNext(); + + } + else + ThrowParserException(DomMsgID.SymbolIsNotAnObject, valueName); + } + catch (DdlParserException ex) + { + ReportParserException(ex); + + AdjustToNextBlock(valueName); + } + catch (ArgumentException e) + { + ReportParserException(e, DomMsgID.InvalidAssignment, valueName); + } + + } + + } + + /// + /// Parses the keyword «\tabstops» inside a paragraph. + /// + private void ParseTabStops(TabStops tabStops) + { + try + { + AssertSymbol(XmlSymbol.TabStops); + MoveNext(); + + while (!IsEndElement(XmlSymbol.TabStops)) + { + switch (XmlSymbol) + { + case XmlSymbol.TabStop: + ParseTabStop(tabStops); + break; + default: + ThrowParserException(DomMsgID.UnexpectedSymbol, _reader.Name); + break; + } + } + + AssertSymbol(XmlSymbol.TabStops, true); + MoveNext(); + + } + catch (DdlParserException pe) + { + ReportParserException(pe); + AdjustToNextBlock(XmlSymbol.TabStops); + } + } + + private void ParseTabStop(TabStops tabStops) + { + AssertSymbol(XmlSymbol.TabStop); + + var attributes = ParseElementAttributes(); + bool fAddItem = GetAttributeValueAsBool(attributes, "Add", true); + + TabStop tabStop = new TabStop(); + + ParseAttributes(tabStop, attributes); + + if (fAddItem) + tabStops.AddTabStop(tabStop); + else + tabStops.RemoveTabStop(tabStop.Position); + + MoveNext(); + + // TODO + // Special hack for tab stops... + //Unit unit = Token; + //tabStop.SetValue("Position", unit); + + } + + + /// + /// Parses an assign statement in an attribute declaration block. + /// + private void ParseAssign(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + if (dom == null) + throw new ArgumentNullException("dom"); + if (vd == null) + throw new ArgumentNullException("vd"); + + Type valType = vd.ValueType; + try + { + if (valType == typeof(string)) + ParseStringAssignment(dom, vd, attribute); + else if (valType == typeof(int)) + ParseIntegerAssignment(dom, vd, attribute); + else if (valType == typeof(Unit)) + ParseUnitAssignment(dom, vd, attribute); + else if (valType == typeof(double) || valType == typeof(float)) + ParseRealAssignment(dom, vd, attribute); + else if (valType == typeof(bool)) + ParseBoolAssignment(dom, vd, attribute); +#if !NETFX_CORE + else if (typeof(Enum).IsAssignableFrom(valType)) +#else + else if (typeof(Enum).GetTypeInfo().IsAssignableFrom(valType.GetTypeInfo())) +#endif + ParseEnumAssignment(dom, vd, attribute); + else if (valType == typeof(Color)) + ParseColorAssignment(dom, vd, attribute); +#if !NETFX_CORE + else if (typeof(ValueType).IsAssignableFrom(valType)) +#else + else if (typeof(ValueType).GetTypeInfo().IsAssignableFrom(valType.GetTypeInfo())) +#endif + { + ParseValueTypeAssignment(dom, vd, attribute); + } +#if !NETFX_CORE + else if (typeof(DocumentObject).IsAssignableFrom(valType)) +#else + else if (typeof(DocumentObject).GetTypeInfo().IsAssignableFrom(valType.GetTypeInfo())) +#endif + { + ParseDocumentObjectAssignment(dom, vd, attribute); + } + else + { + //AdjustToNextStatement(); + ThrowParserException(DomMsgID.InvalidType, vd.ValueType.Name, vd.ValueName); + } + } + catch (Exception ex) + { + ReportParserException(ex, DomMsgID.InvalidAssignment, vd.ValueName); + } + } + + + // TODO parser attributi numerici check tipo + + /// + /// Parses the assignment to a boolean l-value. + /// + private void ParseBoolAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + var symbol = XmlKeyWords.SymbolFromName(attribute.Value); + + AssertCondition(symbol == XmlSymbol.True || symbol == XmlSymbol.False, DomMsgID.BoolExpected, + attribute.Value); + + dom.SetValue(vd.ValueName, symbol == XmlSymbol.True); + // ReadCode(); + } + + /// + /// Parses the assignment to an integer l-value. + /// + private void ParseIntegerAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + //AssertCondition(XmlSymbol == XmlSymbol.IntegerLiteral || XmlSymbol == XmlSymbol.HexIntegerLiteral || XmlSymbol == XmlSymbol.StringLiteral, + // DomMsgID.IntegerExpected, _reader.Name); + + int n = Int32.Parse(attribute.Value, CultureInfo.InvariantCulture); + dom.SetValue(vd.ValueName, n); + + // ReadCode(); + } + + /// + /// Parses the assignment to a floating point l-value. + /// + private void ParseRealAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + double r = double.Parse(attribute.Value, CultureInfo.InvariantCulture); + dom.SetValue(vd.ValueName, r); + + } + + /// + /// Parses the assignment to a Unit l-value. + /// + private void ParseUnitAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + Unit unit = attribute.Value; + dom.SetValue(vd.ValueName, unit); + + } + + /// + /// Parses the assignment to a string l-value. + /// + private void ParseStringAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + //AssertCondition(XmlSymbol == XmlSymbol.StringLiteral, DomMsgID.StringExpected, _scanner.Token); + + vd.SetValue(dom, attribute.Value); //dom.SetValue(vd.ValueName, scanner.Token); + + // ReadCode(); // read next token + } + + /// + /// Parses the assignment to an enum l-value. + /// + private void ParseEnumAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + + try + { + object val = Enum.Parse(vd.ValueType, attribute.Value, true); + dom.SetValue(vd.ValueName, val); + } + catch (Exception ex) + { + ThrowParserException(ex, DomMsgID.InvalidEnum, attribute.Value, vd.ValueName); + } + + } + + /// + /// Parses the assignment to a struct (i.e. LeftPosition) l-value. + /// + private void ParseValueTypeAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + object val = vd.GetValue(dom, GV.ReadWrite); + try + { + INullableValue ival = (INullableValue)val; + ival.SetValue(attribute.Value); + dom.SetValue(vd.ValueName, val); + // ReadCode(); + } + catch (Exception ex) + { + ReportParserException(ex, DomMsgID.InvalidAssignment, vd.ValueName); + } + } + + + // TODO + + /// + /// Parses the assignment to a DocumentObject l-value. + /// + private void ParseDocumentObjectAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + object val = vd.GetValue(dom, GV.ReadWrite); + + try + { + //if (XmlSymbol == XmlSymbol.Null) + //{ + //string name = vd.ValueName; + Type type = vd.ValueType; + if (typeof(Border) == type) + ((Border)val).Clear(); + else if (typeof(Borders) == type) + ((Borders)val).ClearAll(); + else if (typeof(Shading) == type) + ((Shading)val).Clear(); + else if (typeof(TabStops) == type) + { + TabStops tabStops = (TabStops)vd.GetValue(dom, GV.ReadWrite); + tabStops.ClearAll(); + } + else + ThrowParserException(DomMsgID.NullAssignmentNotSupported, vd.ValueName); + + } + catch (Exception ex) + { + ReportParserException(ex, DomMsgID.InvalidAssignment, vd.ValueName); + } + } + + + /// + /// Parses the assignment to a Color l-value. + /// + private void ParseColorAssignment(DocumentObject dom, ValueDescriptor vd, AttributePair attribute) + { + object val = vd.GetValue(dom, GV.ReadWrite); + Color color = ParseColor(attribute.Value); + dom.SetValue(vd.ValueName, color); + } + + // TODO literal, hexliteral, cmyk + + /// + /// Parses a color. It can be «green», «123456», «0xFFABCDEF», + /// «RGB(r, g, b)», «CMYK(c, m, y, k)», «CMYK(a, c, m, y, k)», «GRAY(g)», or «"MyColor"». + /// + private Color ParseColor(String value) + { + Color color = Color.Empty; + + var scanner = new AttributeScanner(value); + + scanner.Scan('('); + + switch (scanner.Token.ToUpper()) + { + case "RGB": + color = ParseRGB(scanner); + break; + case "CMYK": + color = ParseCMYK(); + break; + + case "HSB": + throw new NotImplementedException("ParseColor(HSB)"); + + case "Lab": + throw new NotImplementedException("ParseColor(Lab)"); + + case "GRAY": + color = ParseGray(); + break; + + default: // Must be color enum + try + { + color = Color.Parse(scanner.Token); + } + catch (Exception ex) + { + ThrowParserException(ex, DomMsgID.InvalidColor, scanner.Token); + } + break; + } + + return color; + } + + /// + /// Parses «RGB(r, g, b)». + /// + private Color ParseRGB(AttributeScanner scanner) + { + uint r, g, b; + + // read red value + scanner.Scan(','); + + AssertCondition(AttributeScanner.IsHexIntegerLiteral(scanner.Token) || AttributeScanner.IsIntegerLiteral(scanner.Token), + DomMsgID.IntegerExpected, scanner.Token); + + r = scanner.GetTokenValueAsUInt(); + AssertCondition(r >= 0 && r <= 255, DomMsgID.InvalidRange, "0 - 255"); + + AssertCondition(scanner.PeekChar(','), DomMsgID.MissingComma, scanner.Token); + + // read green value + scanner.Scan(','); + + AssertCondition(AttributeScanner.IsHexIntegerLiteral(scanner.Token) || AttributeScanner.IsIntegerLiteral(scanner.Token), + DomMsgID.IntegerExpected, scanner.Token); + + g = scanner.GetTokenValueAsUInt(); + AssertCondition(g >= 0 && g <= 255, DomMsgID.InvalidRange, "0 - 255"); + + scanner.Scan(')'); + + // read blue value + + AssertCondition(AttributeScanner.IsHexIntegerLiteral(scanner.Token) || AttributeScanner.IsIntegerLiteral(scanner.Token), + DomMsgID.IntegerExpected, scanner.Token); + + b = scanner.GetTokenValueAsUInt(); + AssertCondition(b >= 0 && b <= 255, DomMsgID.InvalidRange, "0 - 255"); + + return new Color(0xFF000000 | (r << 16) | (g << 8) | b); + } + + + /// + /// Parses «CMYK(c, m, y, k)» or «CMYK(a, c, m, y, k)». + /// + private Color ParseCMYK() + { + throw new NotImplementedException(); + } + + + /// + /// Parses «GRAY(g)». + /// + private Color ParseGray() + { + throw new NotImplementedException(); + } + + + /// + /// Determines the name/text of the given symbol. + /// + private string GetSymbolText(XmlSymbol docSym) + { + return XmlKeyWords.NameFromSymbol(docSym); + } + + /// + /// Returns whether the specified type is a valid SpaceType. + /// + private bool IsSpaceType(string type) + { + if (type == null) + throw new ArgumentNullException("type"); + if (type == "") + throw new ArgumentException("type"); + + if (Enum.IsDefined(typeof(SymbolName), type)) + { + SymbolName symbolName = (SymbolName)Enum.Parse(typeof(SymbolName), type, false); // symbols are case sensitive + switch (symbolName) + { + case SymbolName.Blank: + case SymbolName.Em: + //case SymbolName.Em4: // same as SymbolName.EmQuarter + case SymbolName.EmQuarter: + case SymbolName.En: + return true; + } + } + + return false; + } + + /// + /// Returns whether the specified type is a valid enum for \symbol. + /// + private bool IsSymbolType(string type) + { + if (type == null) + throw new ArgumentNullException("type"); + if (type == "") + throw new ArgumentException("type"); + + if (Enum.IsDefined(typeof(SymbolName), type)) + { + SymbolName symbolName = (SymbolName)Enum.Parse(typeof(SymbolName), type, false); // symbols are case sensitive + switch (symbolName) + { + case SymbolName.Euro: + case SymbolName.Copyright: + case SymbolName.Trademark: + case SymbolName.RegisteredTrademark: + case SymbolName.Bullet: + case SymbolName.Not: + case SymbolName.EmDash: + case SymbolName.EnDash: + case SymbolName.NonBreakableBlank: + //case SymbolName.HardBlank: //same as SymbolName.NonBreakableBlank: + return true; + } + } + + return false; + } + + /// + /// If cond is evaluated to false, a DdlParserException with the specified error will be thrown. + /// + private void AssertCondition(bool cond, DomMsgID error, params object[] args) + { + if (!cond) + ThrowParserException(error, args); + } + + + /// + /// If current symbol is not equal symbol a DdlParserException will be thrown. + /// + private void AssertSymbol(XmlSymbol symbol, bool endElement = false) + { + + bool assert; + if (endElement) + assert = IsEndElement(symbol) || IsEmptyElement(symbol); + else + assert = IsStartElement(symbol) || IsEmptyElement(symbol); + + if (!assert) + ThrowParserException(DomMsgID.SymbolExpected, endElement ? "/" : "" + XmlKeyWords.NameFromSymbol(symbol), _reader.Name); + } + + /// + /// If current symbol is not equal symbol a DdlParserException with the specified message id + /// will be thrown. + /// + private void AssertSymbol(XmlSymbol symbol, DomMsgID err, bool endElement = false) + { + bool assert; + if (endElement) + assert = IsEndElement(symbol) || IsEmptyElement(symbol); + else + assert = IsStartElement(symbol) || IsEmptyElement(symbol); + + if (!assert) + ThrowParserException(err, XmlKeyWords.NameFromSymbol(symbol), _reader.Name); + } + + /// + /// If current symbol is not equal symbol a DdlParserException with the specified message id + /// will be thrown. + /// + private void AssertSymbol(XmlSymbol symbol, DomMsgID err, bool endElement = false, params object[] parms) + { + bool assert; + if (endElement) + assert = IsEndElement(symbol) || IsEmptyElement(symbol); + else + assert = IsStartElement(symbol) || IsEmptyElement(symbol); + + if (!assert) + ThrowParserException(err, XmlKeyWords.NameFromSymbol(symbol), parms); + } + + + /// + /// Creates an ErrorInfo based on the given errorlevel, error and parms and adds it to the ErrorManager2. + /// + private void ReportParserInfo(DdlErrorLevel level, DomMsgID errorCode, params string[] parms) + { + string message = DomSR.FormatMessage(errorCode, parms); + + int currentLine = 0; + int currentLinePos = 0; + if (_reader is IXmlLineInfo) + { + var lineInfo = _reader as IXmlLineInfo; + currentLine = lineInfo.LineNumber; + currentLinePos = lineInfo.LinePosition; + } + + DdlReaderError error = new DdlReaderError(level, message, (int)errorCode, + _fileName, currentLine, currentLinePos); + + _errors.AddError(error); + } + + /// + /// Creates an ErrorInfo based on the given error and parms and adds it to the ErrorManager2. + /// + private void ReportParserException(DomMsgID error, params string[] parms) + { + ReportParserException(null, error, parms); + } + + /// + /// Adds the ErrorInfo from the ErrorInfoException2 to the ErrorManager2. + /// + private void ReportParserException(DdlParserException ex) + { + _errors.AddError(ex.Error); + } + + /// + /// Creates an ErrorInfo based on the given inner exception, error and parms and adds it to the ErrorManager2. + /// + private void ReportParserException(Exception innerException, DomMsgID errorCode, params string[] parms) + { + string message = ""; + if (innerException != null) + message = ": " + innerException; + + message += DomSR.FormatMessage(errorCode, parms); + + int currentLine = 0; + int currentLinePos = 0; + if (_reader is IXmlLineInfo) + { + var lineInfo = _reader as IXmlLineInfo; + currentLine = lineInfo.LineNumber; + currentLinePos = lineInfo.LinePosition; + } + + DdlReaderError error = new DdlReaderError(DdlErrorLevel.Error, message, (int)errorCode, + _fileName, currentLine, currentLinePos); + + _errors.AddError(error); + } + + /// + /// Creates an ErrorInfo based on the DomMsgID and the specified parameters. + /// Throws a DdlParserException with that ErrorInfo. + /// + private void ThrowParserException(DomMsgID errorCode, params object[] parms) + { + string message = DomSR.FormatMessage(errorCode, parms); + + int currentLine = 0; + int currentLinePos = 0; + if (_reader is IXmlLineInfo) + { + var lineInfo = _reader as IXmlLineInfo; + currentLine = lineInfo.LineNumber; + currentLinePos = lineInfo.LinePosition; + } + + DdlReaderError error = new DdlReaderError(DdlErrorLevel.Error, message, (int)errorCode, + _fileName, currentLine, currentLinePos + ); + + throw new DdlParserException(error); + } + + /// + /// Determines the error message based on the DomMsgID and the parameters. + /// Throws a DdlParserException with that error message and the Exception as the inner exception. + /// + private void ThrowParserException(Exception innerException, DomMsgID errorCode, params object[] parms) + { + string message = DomSR.FormatMessage(errorCode, parms); + throw new DdlParserException(message, innerException); + } + + /// + /// Used for exception handling. Sets the DDL stream to the next valid position behind + /// the current block. + /// + private void AdjustToNextBlock(XmlSymbol symbol) + { + + if (!IsEmptyElement()) + MoveToEndElement(symbol); + + MoveNext(); + + if (_reader.EOF) + ThrowParserException(DomMsgID.UnexpectedEndOfFile); + + } + + private void AdjustToNextBlock(String name) + { + if (!IsEmptyElement()) + MoveToEndElement(name); + + MoveNext(); + + if (_reader.EOF) + ThrowParserException(DomMsgID.UnexpectedEndOfFile); + } + + /// + /// Shortcut for scanner.ReadText(). + /// Reads either text or \keyword from current position. + /// + private string ReadText() + { + + string text = String.Empty; + + _reader.MoveToContent(); + + bool loop = true; + while (loop) + { + + if (_reader.NodeType == XmlNodeType.CDATA || _reader.NodeType == XmlNodeType.Text) + { + text += _reader.Value; + MoveNext(true); + } + else + if (_reader.NodeType == XmlNodeType.EndElement) + loop = false; + } + + return text; + + } + + + + + /// + /// Gets the current symbol from the scanner. + /// + private XmlSymbol XmlSymbol + { + get + { + XmlSymbol symbol; + + if (_reader.EOF) + symbol = XmlSymbol.Eof; + else + { + _reader.MoveToContent(); + + if (_reader.NodeType == XmlNodeType.Element || _reader.NodeType == XmlNodeType.EndElement) + symbol = XmlKeyWords.SymbolFromName(_reader.Name); + else + symbol = XmlSymbol.None; + } + return symbol; + } + } + + + private readonly XmlReader _reader; + private readonly DdlReaderErrors _errors; + + private readonly string _fileName; + + /* Xml functionality, might be moved to an helper class*/ + + + private bool MoveToEndElement(XmlSymbol symbol) + { + _reader.MoveToContent(); + + do + { + if ((_reader.NodeType == XmlNodeType.EndElement || (_reader.NodeType == XmlNodeType.Element + && _reader.IsEmptyElement)) + && (symbol == XmlKeyWords.SymbolFromName(_reader.Name))) + return true; + + MoveNext(); + + } while (!_reader.EOF); + + return false; + } + + + private bool MoveToEndElement(string name) + { + _reader.MoveToContent(); + + do + { + if ((_reader.NodeType == XmlNodeType.EndElement || + (_reader.NodeType == XmlNodeType.Element && _reader.IsEmptyElement)) + && (_reader.Name.Equals(name, StringComparison.OrdinalIgnoreCase))) + return true; + + MoveNext(); + + } while (!_reader.EOF); + + + + return false; + } + + + + private bool MoveNext(bool skipText = true) + { + _reader.MoveToContent(); + + while (_reader.Read()) + { + if (_reader.NodeType == XmlNodeType.EndElement + || _reader.NodeType == XmlNodeType.Element + || (!skipText + && (_reader.NodeType == XmlNodeType.Text + || _reader.NodeType == XmlNodeType.CDATA))) + return true; + } + + return false; + } + + private bool IsStartElement(XmlSymbol symbol = XmlSymbol.None) + { + _reader.MoveToContent(); + return ((_reader.NodeType == XmlNodeType.Element && !_reader.IsEmptyElement) + && (symbol == XmlSymbol.None ? true : XmlKeyWords.SymbolFromName(_reader.Name) == symbol)); + } + + private bool IsTextElement() + { + _reader.MoveToContent(); + return (_reader.NodeType == XmlNodeType.Text || _reader.NodeType == XmlNodeType.CDATA); + } + + private bool IsEmptyElement(XmlSymbol symbol = XmlSymbol.None) + { + _reader.MoveToContent(); + return ((_reader.NodeType == XmlNodeType.Element && _reader.IsEmptyElement) + && (symbol == XmlSymbol.None ? true : XmlKeyWords.SymbolFromName(_reader.Name) == symbol)); + } + + + private bool IsEndElement(XmlSymbol symbol = XmlSymbol.None) + { + _reader.MoveToContent(); + return (_reader.NodeType == XmlNodeType.EndElement + && (symbol == XmlSymbol.None ? true : XmlKeyWords.SymbolFromName(_reader.Name) == symbol)); + } + + private bool IsEndElement(string name) + { + _reader.MoveToContent(); + return (_reader.NodeType == XmlNodeType.EndElement && _reader.Name.Equals(name, StringComparison.OrdinalIgnoreCase)); + + } + + private AttrDictionary ParseElementAttributes() + { + + AttrDictionary attributes = new AttrDictionary(StringComparer.OrdinalIgnoreCase); + + _reader.MoveToContent(); + if (_reader.HasAttributes) + { + while (_reader.MoveToNextAttribute()) + + attributes[_reader.Name] = _reader.Value; + + + } + + return attributes; + } + + private static string GetAttributeValue(AttrDictionary attributes, string key, bool remove = false) + { + string value = null; + if (attributes.ContainsKey(key)) + { + value = attributes[key]; + + if (remove) + attributes.Remove(key); + } + + return value; + } + + private static bool GetAttributeValueAsBool(AttrDictionary attributes, string key, bool remove = false) + { + var value = GetAttributeValue(attributes, key, remove); + if (value == null) + return false; + else + return value.ToLower() == "true"; + } + + + private string RemoveLeadingWhiteSpace(string text) + { + if (text != null) + { + int idx = 0; + while (idx < text.Length) + { + var ch = text[idx]; + if (!Char.IsWhiteSpace(ch)) + break; + idx++; + } + + if (idx > 0) + text = text.Remove(0, idx); + + } + + return text; + } + + private string RemoveTrailingWhiteSpace(string text) + { + if (text != null) + { + int idx = text.Length - 1; + while (idx > 0) + { + var ch = text[idx]; + if (!Char.IsWhiteSpace(ch)) + break; + idx--; + } + + if (idx + 1 < text.Length) + text = text.Remove(idx + 1); + + } + + return text; + } + } +} \ No newline at end of file diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlReader.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlReader.cs new file mode 100644 index 0000000..5d509ec --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlReader.cs @@ -0,0 +1,278 @@ +#region MigraDoc - Creating Documents on the Fly +// +// Authors: +// Stefan Lange +// Klaus Potzesny +// David Stephensen +// +// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany) +// +// http://www.pdfsharp.com +// http://www.migradoc.com +// http://sourceforge.net/projects/pdfsharp +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.IO; +using System.Text; + +namespace MigraDoc.DocumentObjectModel.IO.Xml +{ + /// + /// Represents a reader that provides access to DDL data. + /// + public class DdlReader + { + /// + /// Initializes a new instance of the DdlReader class with the specified Stream. + /// + public DdlReader(Stream stream) + : this(stream, null) + { } + + /// + /// Initializes a new instance of the DdlReader class with the specified Stream and ErrorManager2. + /// + public DdlReader(Stream stream, DdlReaderErrors errors) + { + _errorManager = errors; + _reader = new StreamReader(stream); + } + + /// + /// Initializes a new instance of the DdlReader class with the specified filename. + /// + public DdlReader(string filename) + : this(filename, null) + { } + + /// + /// Initializes a new instance of the DdlReader class with the specified filename and ErrorManager2. + /// + public DdlReader(string filename, DdlReaderErrors errors) + { + _fileName = filename; + _errorManager = errors; +#if !NETFX_CORE + _reader = new StreamReader(filename, Encoding.UTF8); +#else + _reader = new StreamReader(null, Encoding.UTF8); +#endif + //#if SILVERLIGHT + // _reader = new StreamReader(filename, Encoding.UTF8); + //#else + // _reader = new StreamReader(filename, Encoding.Default); + //#endif + } + + /// + /// Initializes a new instance of the DdlReader class with the specified TextReader. + /// + public DdlReader(TextReader reader) + : this(reader, null) + { } + + /// + /// Initializes a new instance of the DdlReader class with the specified TextReader and ErrorManager2. + /// + public DdlReader(TextReader reader, DdlReaderErrors errors) + { + _doClose = false; + _errorManager = errors; + _reader = reader; + } + + /// + /// Closes the underlying stream or text writer. + /// + public void Close() + { + if (_doClose && _reader != null) + { +#if !NETFX_CORE + _reader.Close(); +#else + _reader.Dispose(); +#endif + _reader = null; + } + } + + /// + /// Reads and returns a Document from a file or a DDL string. + /// + public Document ReadDocument() + { + string ddl = _reader.ReadToEnd(); + + Document document; + if (!String.IsNullOrEmpty(_fileName)) + { + DdlParser parser = new DdlParser(_fileName, ddl, _errorManager); + document = parser.ParseDocument(null); + document._ddlFile = _fileName; + } + else + { + DdlParser parser = new DdlParser(ddl, _errorManager); + document = parser.ParseDocument(null); + } + + return document; + } + + /// + /// Reads and returns a DocumentObject from a file or a DDL string. + /// + public DocumentObject ReadObject() + { + string ddl = _reader.ReadToEnd(); + DdlParser parser = !String.IsNullOrEmpty(_fileName) ? + new DdlParser(_fileName, ddl, _errorManager) : + new DdlParser(ddl, _errorManager); + return parser.ParseDocumentObject(); + } + + /// + /// Reads and returns a Document from the specified file. + /// + public static Document DocumentFromFile(string documentFileName) //, ErrorManager2 _errorManager) + { + Document document; + DdlReader reader = null; + try + { + reader = new DdlReader(documentFileName); //, _errorManager); + document = reader.ReadDocument(); + } + finally + { + if (reader != null) + reader.Close(); + } + return document; + } + + /// + /// Reads and returns a Document from the specified DDL string. + /// + public static Document DocumentFromString(string ddl) + { + StringReader stringReader = null; + Document document; + DdlReader reader = null; + try + { + stringReader = new StringReader(ddl); + + reader = new DdlReader(stringReader); + document = reader.ReadDocument(); + } + finally + { + if (stringReader != null) + { +#if !NETFX_CORE + stringReader.Close(); +#else + stringReader.Dispose(); +#endif + } + + if (reader != null) + reader.Close(); + } + return document; + } + + /// + /// Reads and returns a domain object from the specified file. + /// + public static DocumentObject ObjectFromFile(string documentFileName, DdlReaderErrors errors) + { + DdlReader reader = null; + DocumentObject domObj; + try + { + reader = new DdlReader(documentFileName, errors); + domObj = reader.ReadObject(); + } + finally + { + if (reader != null) + reader.Close(); + } + return domObj; + } + + /// + /// Reads and returns a domain object from the specified file. + /// + public static DocumentObject ObjectFromFile(string documentFileName) + { + return ObjectFromFile(documentFileName, null); + } + + /// + /// Reads and returns a domain object from the specified DDL string. + /// + public static DocumentObject ObjectFromString(string ddl, DdlReaderErrors errors) + { + StringReader stringReader = null; + DocumentObject domObj; + DdlReader reader = null; + try + { + stringReader = new StringReader(ddl); + + reader = new DdlReader(stringReader); + domObj = reader.ReadObject(); + } + finally + { + if (stringReader != null) + { +#if !NETFX_CORE + stringReader.Close(); +#else + stringReader.Dispose(); +#endif + } + if (reader != null) + reader.Close(); + } + return domObj; + } + + /// + /// Reads and returns a domain object from the specified DDL string. + /// + public static DocumentObject ObjectFromString(string ddl) + { + return ObjectFromString(ddl, null); + } + + readonly bool _doClose = true; + TextReader _reader; + readonly DdlReaderErrors _errorManager; + readonly string _fileName; + } +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlWriter.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlWriter.cs new file mode 100644 index 0000000..af9fffc --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlWriter.cs @@ -0,0 +1,312 @@ +#region MigraDoc - Creating Documents on the Fly +// +// Authors: +// Stefan Lange +// Klaus Potzesny +// David Stephensen +// +// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany) +// +// http://www.pdfsharp.com +// http://www.migradoc.com +// http://sourceforge.net/projects/pdfsharp +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.IO; +using System.Text; +using System.Xml; + +namespace MigraDoc.DocumentObjectModel.IO.Xml +{ + /// + /// Represents the MigraDoc DDL writer. + /// + public class DdlWriter + { + /// + /// Initializes a new instance of the DdlWriter class with the specified Stream. + /// + public DdlWriter(Stream stream) + { + _writer = new StreamWriter(stream); + _serializer = new XmlSerializer(_writer); + } + +#if !NETFX_CORE + /// + /// Initializes a new instance of the DdlWriter class with the specified filename. + /// + public DdlWriter(string filename) + { + _writer = new StreamWriter(filename, false, Encoding.UTF8); + _serializer = new XmlSerializer(_writer); + } +#endif + + /// + /// Initializes a new instance of the DdlWriter class with the specified TextWriter. + /// + public DdlWriter(TextWriter writer) + { + _serializer = new XmlSerializer(writer); + } + + /// + /// Closes the underlying serializer and text writer. + /// + public void Close() + { + _serializer = null; + + if (_writer != null) + { + _writer.Close(); + _writer = null; + } + } + + /// + /// Flushes the underlying TextWriter. + /// + public void Flush() + { + _serializer.Flush(); + } + + /// + /// Gets or sets the indentation for the DDL file. + /// + public int Indent + { + get { return _serializer.Indent; } + set { _serializer.Indent = value; } + } + + /// + /// Gets or sets the initial indentation for the DDL file. + /// + public int InitialIndent + { + get { return _serializer.InitialIndent; } + set { _serializer.InitialIndent = value; } + } + + /// + /// Writes the specified DocumentObject to DDL. + /// + public void WriteDocument(DocumentObject documentObject) + { + documentObject.Serialize(_serializer); + _serializer.Flush(); + } + + /// + /// Writes the specified DocumentObjectCollection to DDL. + /// + public void WriteDocument(DocumentObjectCollection documentObjectContainer) + { + documentObjectContainer.Serialize(_serializer); + _serializer.Flush(); + } + + /// + /// Writes a DocumentObject type object to string. + /// + public static string WriteToString(DocumentObject docObject) + { + return WriteToString(docObject, 2, 0); + } + + /// + /// Writes a DocumentObject type object to string. Indent a new block by indent characters. + /// + public static string WriteToString(DocumentObject docObject, int indent) + { + return WriteToString(docObject, indent, 0); + } + + /// + /// Writes a DocumentObject type object to string. Indent a new block by indent + initialIndent characters. + /// + public static string WriteToString(DocumentObject docObject, int indent, int initialIndent) + { + StringBuilder strBuilder = new StringBuilder(); + StringWriter writer = null; + DdlWriter wrt = null; + try + { + writer = new StringWriter(strBuilder); + + wrt = new DdlWriter(writer); + wrt.Indent = indent; + wrt.InitialIndent = initialIndent; + + wrt.WriteDocument(docObject); + wrt.Close(); + } + finally + { + if (wrt != null) + wrt.Close(); + if (writer != null) + { +#if !NETFX_CORE + writer.Close(); +#else + writer.Dispose(); +#endif + } + } + return strBuilder.ToString(); + } + + /// + /// Writes a DocumentObjectCollection type object to string. + /// + public static string WriteToString(DocumentObjectCollection docObjectContainer) + { + return WriteToString(docObjectContainer, 2, 0); + } + + /// + /// Writes a DocumentObjectCollection type object to string. Indent a new block by _indent characters. + /// + public static string WriteToString(DocumentObjectCollection docObjectContainer, int indent) + { + return WriteToString(docObjectContainer, indent, 0); + } + + /// + /// Writes a DocumentObjectCollection type object to string. Indent a new block by + /// indent + initialIndent characters. + /// + public static string WriteToString(DocumentObjectCollection docObjectContainer, int indent, int initialIndent) + { + StringBuilder strBuilder = new StringBuilder(); + StringWriter writer = null; + DdlWriter wrt = null; + try + { + writer = new StringWriter(strBuilder); + + wrt = new DdlWriter(writer); + wrt.Indent = indent; + wrt.InitialIndent = initialIndent; + + wrt.WriteDocument(docObjectContainer); + wrt.Close(); + } + finally + { + if (wrt != null) + wrt.Close(); + if (writer != null) + { +#if !NETFX_CORE + writer.Close(); +#else + writer.Dispose(); +#endif + } + } + return strBuilder.ToString(); + } + + /// + /// Writes a document object to a DDL file. + /// + public static void WriteToFile(DocumentObject docObject, string filename) + { + WriteToFile(docObject, filename, 2, 0); + } + + /// + /// Writes a document object to a DDL file. Indent a new block by the specified number of characters. + /// + public static void WriteToFile(DocumentObject docObject, string filename, int indent) + { + WriteToFile(docObject, filename, indent, 0); + } + + /// + /// Writes a DocumentObject type object to a DDL file. Indent a new block by indent + initialIndent characters. + /// + public static void WriteToFile(DocumentObject docObject, string filename, int indent, int initialIndent) + { + DdlWriter wrt = null; + try + { + wrt = new DdlWriter(filename); + wrt.Indent = indent; + wrt.InitialIndent = initialIndent; + + wrt.WriteDocument(docObject); + } + finally + { + if (wrt != null) + wrt.Close(); + } + } + + /// + /// Writes a DocumentObjectCollection type object to a DDL file. + /// + public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename) + { + WriteToFile(docObjectContainer, filename, 2, 0); + } + + /// + /// Writes a DocumentObjectCollection type object to a DDL file. Indent a new block by + /// indent + initialIndent characters. + /// + public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename, int indent) + { + WriteToFile(docObjectContainer, filename, indent, 0); + } + + /// + /// Writes a DocumentObjectCollection type object to a DDL file. Indent a new block by + /// indent + initialIndent characters. + /// + public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename, int indent, int initialIndent) + { + DdlWriter wrt = null; + try + { + wrt = new DdlWriter(filename); + wrt.Indent = indent; + wrt.InitialIndent = initialIndent; + + wrt.WriteDocument(docObjectContainer); + } + finally + { + if (wrt != null) + wrt.Close(); + } + } + + StreamWriter _writer; + XmlSerializer _serializer; + } +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs new file mode 100644 index 0000000..aa34669 --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MigraDoc.DocumentObjectModel.IO.Xml +{ + internal class XmlKeyWords + { + static XmlKeyWords() + { + EnumToName.Add(XmlSymbol.True, "true"); + EnumToName.Add(XmlSymbol.False, "false"); + //EnumToName.Add(XmlSymbol.Null, "null"); + + EnumToName.Add(XmlSymbol.Attributes, "attributes"); + EnumToName.Add(XmlSymbol.Styles, "styles"); + EnumToName.Add(XmlSymbol.Style, "style"); + EnumToName.Add(XmlSymbol.Document, "document"); + EnumToName.Add(XmlSymbol.Sections, "sections"); + EnumToName.Add(XmlSymbol.Section, "section"); + EnumToName.Add(XmlSymbol.Paragraph, "p"); // paragraph + EnumToName.Add(XmlSymbol.Header, "header"); + EnumToName.Add(XmlSymbol.Footer, "footer"); + EnumToName.Add(XmlSymbol.PrimaryHeader, "primaryheader"); + EnumToName.Add(XmlSymbol.PrimaryFooter, "primaryfooter"); + EnumToName.Add(XmlSymbol.FirstPageHeader, "firstpageheader"); + EnumToName.Add(XmlSymbol.FirstPageFooter, "firstpagefooter"); + EnumToName.Add(XmlSymbol.EvenPageHeader, "evenpageheader"); + EnumToName.Add(XmlSymbol.EvenPageFooter, "evenpagefooter"); + EnumToName.Add(XmlSymbol.Table, "table"); + EnumToName.Add(XmlSymbol.Columns, "columns"); + EnumToName.Add(XmlSymbol.Column, "column"); + EnumToName.Add(XmlSymbol.Rows, "rows"); + EnumToName.Add(XmlSymbol.Row, "row"); + EnumToName.Add(XmlSymbol.Cell, "cell"); + EnumToName.Add(XmlSymbol.Image, "image"); + // EnumToName.Add(XmlSymbol.Text, "text"); + EnumToName.Add(XmlSymbol.TextFrame, "textframe"); + EnumToName.Add(XmlSymbol.PageBreak, "pagebreak"); + EnumToName.Add(XmlSymbol.Barcode, "barcode"); + EnumToName.Add(XmlSymbol.Chart, "chart"); + EnumToName.Add(XmlSymbol.HeaderArea, "headerarea"); + EnumToName.Add(XmlSymbol.FooterArea, "footerarea"); + EnumToName.Add(XmlSymbol.TopArea, "toparea"); + EnumToName.Add(XmlSymbol.BottomArea, "bottomarea"); + EnumToName.Add(XmlSymbol.LeftArea, "leftarea"); + EnumToName.Add(XmlSymbol.RightArea, "rightarea"); + EnumToName.Add(XmlSymbol.PlotArea, "plotarea"); + EnumToName.Add(XmlSymbol.Legend, "legend"); + EnumToName.Add(XmlSymbol.XAxis, "xaxis"); + EnumToName.Add(XmlSymbol.YAxis, "yaxis"); + EnumToName.Add(XmlSymbol.ZAxis, "zaxis"); + EnumToName.Add(XmlSymbol.Series, "series"); + EnumToName.Add(XmlSymbol.XSeries, "xseries"); + EnumToName.Add(XmlSymbol.XValue, "xvalue"); + EnumToName.Add(XmlSymbol.Point, "point"); + + EnumToName.Add(XmlSymbol.TabStops, "tabstops"); + EnumToName.Add(XmlSymbol.TabStop, "tabstop"); + + EnumToName.Add(XmlSymbol.Bold, "b"); + EnumToName.Add(XmlSymbol.Italic, "i"); + EnumToName.Add(XmlSymbol.Underline, "u"); + EnumToName.Add(XmlSymbol.FontSize, "fontsize"); + EnumToName.Add(XmlSymbol.FontColor, "fontcolor"); + EnumToName.Add(XmlSymbol.Font, "font"); + // + EnumToName.Add(XmlSymbol.Field, "field"); + EnumToName.Add(XmlSymbol.Symbol, "symbol"); + EnumToName.Add(XmlSymbol.Chr, "chr"); + // + EnumToName.Add(XmlSymbol.Footnote, "footnote"); + EnumToName.Add(XmlSymbol.Hyperlink, "hyperlink"); + // + EnumToName.Add(XmlSymbol.SoftHyphen, "-"); + EnumToName.Add(XmlSymbol.Tab, "tab"); + EnumToName.Add(XmlSymbol.LineBreak, "br"); + EnumToName.Add(XmlSymbol.Space, "space"); + EnumToName.Add(XmlSymbol.NoSpace, "nospace"); + + // + // + + /*EnumToName.Add(XmlSymbol.BraceLeft, "{"); + EnumToName.Add(XmlSymbol.BraceRight, "}"); + EnumToName.Add(XmlSymbol.BracketLeft, "["); + EnumToName.Add(XmlSymbol.BracketRight, "]"); + EnumToName.Add(XmlSymbol.ParenLeft, "("); + EnumToName.Add(XmlSymbol.ParenRight, ")"); + EnumToName.Add(XmlSymbol.Colon, ":"); + EnumToName.Add(XmlSymbol.Semicolon, ";"); //??? id DDL? + EnumToName.Add(XmlSymbol.Dot, "."); + EnumToName.Add(XmlSymbol.Comma, ","); + EnumToName.Add(XmlSymbol.Percent, "%"); //??? id DDL? + EnumToName.Add(XmlSymbol.Dollar, "$"); //??? id DDL? + //enumToName.Add(XmlSymbol.At, "@"); + EnumToName.Add(XmlSymbol.Hash, "#"); //??? id DDL? + //enumToName.Add(XmlSymbol.Question, "?"); //??? id DDL? + //enumToName.Add(XmlSymbol.Bar, "|"); //??? id DDL? + EnumToName.Add(XmlSymbol.Assign, "="); + EnumToName.Add(XmlSymbol.Slash, "/"); //??? id DDL? + EnumToName.Add(XmlSymbol.BackSlash, "\\"); + EnumToName.Add(XmlSymbol.Plus, "+"); //??? id DDL? + EnumToName.Add(XmlSymbol.PlusAssign, "+="); + EnumToName.Add(XmlSymbol.Minus, "-"); //??? id DDL? + EnumToName.Add(XmlSymbol.MinusAssign, "-="); + EnumToName.Add(XmlSymbol.Blank, " "); + */ + //--------------------------------------------------------------- + //--------------------------------------------------------------- + //--------------------------------------------------------------- + + NameToEnum.Add("true", XmlSymbol.True); + NameToEnum.Add("false", XmlSymbol.False); + //NameToEnum.Add("null", XmlSymbol.Null); + // + NameToEnum.Add("attributes", XmlSymbol.Attributes); + NameToEnum.Add("styles", XmlSymbol.Styles); + NameToEnum.Add("style", XmlSymbol.Style); + NameToEnum.Add("document", XmlSymbol.Document); + NameToEnum.Add("info", XmlSymbol.Info); + NameToEnum.Add("sections", XmlSymbol.Sections); + NameToEnum.Add("section", XmlSymbol.Section); + NameToEnum.Add("p", XmlSymbol.Paragraph); + NameToEnum.Add("header", XmlSymbol.Header); + NameToEnum.Add("footer", XmlSymbol.Footer); + NameToEnum.Add("primaryheader", XmlSymbol.PrimaryHeader); + NameToEnum.Add("primaryfooter", XmlSymbol.PrimaryFooter); + NameToEnum.Add("firstpageheader", XmlSymbol.FirstPageHeader); + NameToEnum.Add("firstpagefooter", XmlSymbol.FirstPageFooter); + NameToEnum.Add("evenpageheader", XmlSymbol.EvenPageHeader); + NameToEnum.Add("evenpagefooter", XmlSymbol.EvenPageFooter); + NameToEnum.Add("table", XmlSymbol.Table); + NameToEnum.Add("columns", XmlSymbol.Columns); + NameToEnum.Add("column", XmlSymbol.Column); + NameToEnum.Add("rows", XmlSymbol.Rows); + NameToEnum.Add("row", XmlSymbol.Row); + NameToEnum.Add("cell", XmlSymbol.Cell); + NameToEnum.Add("image", XmlSymbol.Image); + //NameToEnum.Add("text", XmlSymbol.Text); + NameToEnum.Add("textframe", XmlSymbol.TextFrame); + NameToEnum.Add("pagebreak", XmlSymbol.PageBreak); + NameToEnum.Add("barcode", XmlSymbol.Barcode); + NameToEnum.Add("chart", XmlSymbol.Chart); + NameToEnum.Add("headerarea", XmlSymbol.HeaderArea); + NameToEnum.Add("footerarea", XmlSymbol.FooterArea); + NameToEnum.Add("toparea", XmlSymbol.TopArea); + NameToEnum.Add("bottomarea", XmlSymbol.BottomArea); + NameToEnum.Add("leftarea", XmlSymbol.LeftArea); + NameToEnum.Add("rightarea", XmlSymbol.RightArea); + NameToEnum.Add("plotarea", XmlSymbol.PlotArea); + NameToEnum.Add("legend", XmlSymbol.Legend); + NameToEnum.Add("xaxis", XmlSymbol.XAxis); + NameToEnum.Add("yaxis", XmlSymbol.YAxis); + NameToEnum.Add("zaxis", XmlSymbol.ZAxis); + NameToEnum.Add("series", XmlSymbol.Series); + NameToEnum.Add("xseries", XmlSymbol.XSeries); + NameToEnum.Add("xvalue", XmlSymbol.XValue); + NameToEnum.Add("point", XmlSymbol.Point); + + NameToEnum.Add("tabstops", XmlSymbol.TabStops); + NameToEnum.Add("tabstop", XmlSymbol.TabStop); + + NameToEnum.Add("b", XmlSymbol.Bold); + NameToEnum.Add("i", XmlSymbol.Italic); + NameToEnum.Add("u", XmlSymbol.Underline); + NameToEnum.Add("fontsize", XmlSymbol.FontSize); + NameToEnum.Add("fontcolor", XmlSymbol.FontColor); + NameToEnum.Add("font", XmlSymbol.Font); + // + NameToEnum.Add("field", XmlSymbol.Field); + NameToEnum.Add("symbol", XmlSymbol.Symbol); + NameToEnum.Add("chr", XmlSymbol.Chr); + // + NameToEnum.Add("footnote", XmlSymbol.Footnote); + NameToEnum.Add("hyperlink", XmlSymbol.Hyperlink); + // + NameToEnum.Add("-", XmlSymbol.SoftHyphen); //??? \( is another special case. + NameToEnum.Add("tab", XmlSymbol.Tab); + NameToEnum.Add("br", XmlSymbol.LineBreak); + NameToEnum.Add("space", XmlSymbol.Space); + NameToEnum.Add("nospace", XmlSymbol.NoSpace); + } + + /// + /// Returns XmlSymbol value from name, or XmlSymbol.None if no such XmlSymbol exists. + /// + internal static XmlSymbol SymbolFromName(string name) + { + XmlSymbol XmlSymbol; + if (!NameToEnum.TryGetValue(name.ToLower(), out XmlSymbol)) + { + // Check for case sensitive keywords. Allow first character upper case only. + if (string.Compare(name, "True", StringComparison.OrdinalIgnoreCase) == 0) + XmlSymbol = XmlSymbol.True; + else if (string.Compare(name, "False", StringComparison.OrdinalIgnoreCase) == 0) + XmlSymbol = XmlSymbol.False; + /*else if (string.Compare(name, "Null", StringComparison.OrdinalIgnoreCase) == 0) + XmlSymbol = XmlSymbol.Null;*/ + else + XmlSymbol = XmlSymbol.None; + } + return XmlSymbol; + } + + /// + /// Returns string from XmlSymbol value. + /// + internal static string NameFromSymbol(XmlSymbol XmlSymbol) + { + return EnumToName[XmlSymbol]; + } + + static readonly Dictionary EnumToName = new Dictionary(); + static readonly Dictionary NameToEnum = new Dictionary(); + } + +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs new file mode 100644 index 0000000..753fe60 --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MigraDoc.DocumentObjectModel.IO.Xml +{ + enum XmlSymbol + { + // TokenType.None + None, + Eof, + //Eol, // End of line + // TokenType.Keyword + True, + False, + //Null, + + // TokenType.Identifier + //Identifier, + //Comment, + + // TokenType.IntegerLiteral + //IntegerLiteral, + //HexIntegerLiteral, + //OctIntegerLiteral, + + // TokenType.StringLiteral + //StringLiteral, + + // TokenType.RealLiteral + //RealLiteral, + + // TokenType.OperatorOrPunctuator + //Slash, // / + //BackSlash, // \ + //ParenLeft, // ( + //ParenRight, // ) + //BraceLeft, // { + //BraceRight, // } + //BracketLeft, // [ + //BracketRight, // ] + //EmptyLine, //CR LF CR LF + //Colon, // : + //Semicolon, // ; + //Assign, // = + //Plus, // + + //Minus, // - + //Dot, // . + //Comma, // , + //Percent, // % + //Dollar, // $ + //Hash, // # + //Currency, // ¤ + //Questionmark, // ? + //Quotationmark, // " + //At, // @ + //Bar, // | + //PlusAssign, // += + //MinusAssign, // -= + //CR, // 0x0D + //LF, // 0x0A + + // TokenType.Keyword + Attributes, + Styles, + Style, + Document, + Info, + Sections, + Section, + TableTemplates, + TableTemplate, + Paragraph, + HeaderOrFooter, // Only used as context in ParseDocumentElements + Header, + PrimaryHeader, + FirstPageHeader, + EvenPageHeader, + Footer, + PrimaryFooter, + FirstPageFooter, + EvenPageFooter, + Table, + Columns, + Column, + Rows, + Row, + Cell, + Image, + TextFrame, + Chart, + Footnote, + PageBreak, + Barcode, + + // Diagramms + HeaderArea, + FooterArea, + TopArea, + BottomArea, + LeftArea, + RightArea, + PlotArea, + Legend, + XAxis, + YAxis, + ZAxis, + Series, + XSeries, + XValue, + Point, + + TabStops, + TabStop, + + // paragraph formats + Bold, + Italic, + Underline, + FontSize, + FontColor, + Font, + + // Hyperlink used by ParagraphParser + Hyperlink, + + // Token used by ParagraphParser + //Text, // Plain text in a paragraph. + Blank, + Tab, + NonBreakeableBlank, + SoftHyphen, + LineBreak, + Space, + NoSpace, + + // Field used by ParagraphParser + Field, + + // Field types used by ParagraphParser + DateField, + PageField, + NumPagesField, + InfoField, + SectionField, + SectionPagesField, + BookmarkField, + PageRefField, + + Character, //??? + Symbol, + Chr + } +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs index 287c699..9926d86 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs @@ -176,6 +176,7 @@ private Style ParseStyleDefinition(Styles styles) // { // ... // } + Style style = null; try { diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Axis.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Axis.cs index 24bc703..44085b1 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Axis.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Axis.cs @@ -318,6 +318,56 @@ internal override void Serialize(Serializer serializer) serializer.EndAttributes(pos); } + internal override void Serialize(XmlSerializer serializer) + { + Chart chartObject = _parent as Chart; + + serializer.WriteStartElement(chartObject.CheckAxis(this)); + + //serializer.WriteSimpleAttribute("Type", chartObject.CheckAxis(this)); + + //serializer.WriteLine("\\" + chartObject.CheckAxis(this)); + + if (!_minimumScale.IsNull) + serializer.WriteSimpleAttribute("MinimumScale", MinimumScale); + if (!_maximumScale.IsNull) + serializer.WriteSimpleAttribute("MaximumScale", MaximumScale); + if (!_majorTick.IsNull) + serializer.WriteSimpleAttribute("MajorTick", MajorTick); + if (!_minorTick.IsNull) + serializer.WriteSimpleAttribute("MinorTick", MinorTick); + if (!_hasMajorGridlines.IsNull) + serializer.WriteSimpleAttribute("HasMajorGridLines", HasMajorGridlines); + if (!_hasMinorGridlines.IsNull) + serializer.WriteSimpleAttribute("HasMinorGridLines", HasMinorGridlines); + if (!_majorTickMark.IsNull) + serializer.WriteSimpleAttribute("MajorTickMark", MajorTickMark); + if (!_minorTickMark.IsNull) + serializer.WriteSimpleAttribute("MinorTickMark", MinorTickMark); + + serializer.BeginAttributes(); + + if (!IsNull("Title")) + _title.Serialize(serializer); + + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + + if (!IsNull("MajorGridlines")) + _majorGridlines.Serialize(serializer); + + if (!IsNull("MinorGridlines")) + _minorGridlines.Serialize(serializer); + + if (!IsNull("TickLabels")) + _tickLabels.Serialize(serializer); + + serializer.EndAttributes(); + + serializer.WriteEndElement(); + + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/AxisTitle.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/AxisTitle.cs index a038ece..b3e58fa 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/AxisTitle.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/AxisTitle.cs @@ -177,6 +177,34 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //int pos = serializer.BeginContent("Title"); + + serializer.WriteStartElement("Title"); + + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + + if (!IsNull("Font")) + _font.Serialize(serializer); + + if (!_orientation.IsNull) + serializer.WriteSimpleAttribute("Orientation", Orientation); + + if (!_alignment.IsNull) + serializer.WriteSimpleAttribute("Alignment", Alignment); + + if (!_verticalAlignment.IsNull) + serializer.WriteSimpleAttribute("VerticalAlignment", VerticalAlignment); + + if (!_caption.IsNull) + serializer.WriteSimpleAttribute("Caption", Caption); + + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Chart.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Chart.cs index ef66cd2..4a3824a 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Chart.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Chart.cs @@ -511,6 +511,66 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\chart(" + Type + ")"); + serializer.WriteStartElement("Chart"); + + serializer.WriteSimpleAttribute("Type", Type); + + base.Serialize(serializer); + if (!_displayBlanksAs.IsNull) + serializer.WriteSimpleAttribute("DisplayBlanksAs", DisplayBlanksAs); + if (!_pivotChart.IsNull) + serializer.WriteSimpleAttribute("PivotChart", PivotChart); + if (!_hasDataLabel.IsNull) + serializer.WriteSimpleAttribute("HasDataLabel", HasDataLabel); + + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + + serializer.BeginAttributes(); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + if (!IsNull("DataLabel")) + _dataLabel.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + + if (!IsNull("PlotArea")) + _plotArea.Serialize(serializer); + if (!IsNull("HeaderArea")) + _headerArea.Serialize(serializer); + if (!IsNull("FooterArea")) + _footerArea.Serialize(serializer); + if (!IsNull("TopArea")) + _topArea.Serialize(serializer); + if (!IsNull("BottomArea")) + _bottomArea.Serialize(serializer); + if (!IsNull("LeftArea")) + _leftArea.Serialize(serializer); + if (!IsNull("RightArea")) + _rightArea.Serialize(serializer); + + if (!IsNull("XAxis")) + _xAxis.Serialize(serializer); + if (!IsNull("YAxis")) + _yAxis.Serialize(serializer); + if (!IsNull("ZAxis")) + _zAxis.Serialize(serializer); + + if (!IsNull("SeriesCollection")) + _seriesCollection.Serialize(serializer); + if (!IsNull("XValues")) + _xValues.Serialize(serializer); + + //serializer.EndContent(); + serializer.WriteEndElement(); + + } /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/ChartObject.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/ChartObject.cs index c454191..4bc11fc 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/ChartObject.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/ChartObject.cs @@ -60,6 +60,12 @@ internal override void Serialize(Serializer _serializer) // Nothing to do } + internal override void Serialize(XmlSerializer serializer) + { + // Nothing to do + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/DataLabel.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/DataLabel.cs index 68203be..3f571aa 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/DataLabel.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/DataLabel.cs @@ -159,6 +159,26 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + //int pos = serializer.BeginContent("DataLabel"); + serializer.WriteStartElement("DataLabel"); + + if (Style != string.Empty) + serializer.WriteSimpleAttribute("Style", Style); + if (Format != string.Empty) + serializer.WriteSimpleAttribute("Format", Format); + if (!_position.IsNull) + serializer.WriteSimpleAttribute("Position", Position); + if (!_type.IsNull) + serializer.WriteSimpleAttribute("Type", Type); + if (!IsNull("Font")) + _font.Serialize(serializer); + + //serializer.EndContent(pos); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs index 8794158..c47ee4f 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs @@ -108,6 +108,23 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + Axis axisObject = _parent as Axis; + + //int pos = serializer.BeginContent(axisObject.CheckGridlines(this)); + serializer.WriteStartElement("GridLines"); + + serializer.WriteElement("Type", axisObject.CheckGridlines(this)); + + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + + serializer.WriteEndElement(); + + //serializer.EndContent(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Legend.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Legend.cs index bd33417..7dcfdf0 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Legend.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Legend.cs @@ -144,6 +144,28 @@ internal override void Serialize(Serializer serializer) serializer.EndAttributes(pos); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\legend"); + + serializer.WriteStartElement("Legend"); + + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + + serializer.BeginAttributes(); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + + serializer.EndAttributes(); + + serializer.WriteEndElement(); + } + /// /// Determines whether this instance is null (not set). /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/PlotArea.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/PlotArea.cs index 79e1523..95de15e 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/PlotArea.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/PlotArea.cs @@ -185,6 +185,34 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\plotarea"); + serializer.WriteStartElement("PlotArea"); + + + if (!_topPadding.IsNull) + serializer.WriteSimpleAttribute("TopPadding", TopPadding); + if (!_leftPadding.IsNull) + serializer.WriteSimpleAttribute("LeftPadding", LeftPadding); + if (!_rightPadding.IsNull) + serializer.WriteSimpleAttribute("RightPadding", RightPadding); + if (!_bottomPadding.IsNull) + serializer.WriteSimpleAttribute("BottomPadding", BottomPadding); + + serializer.BeginAttributes(); + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + if (!IsNull("FillFormat")) + _fillFormat.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Point.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Point.cs index 0e422ea..f746204 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Point.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Point.cs @@ -154,6 +154,38 @@ internal override void Serialize(Serializer serializer) serializer.Write(", "); } + internal override void Serialize(XmlSerializer serializer) + { + if (!IsNull("LineFormat") || !IsNull("FillFormat")) + { + //serializer.WriteLine(""); + //serializer.WriteLine("\\point"); + + serializer.WriteStartElement("Point"); + + serializer.BeginAttributes(); + + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + if (!IsNull("FillFormat")) + _fillFormat.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + //serializer.WriteLine(Value.ToString(System.Globalization.CultureInfo.InvariantCulture)); + serializer.WriteElement("Value", Value.ToString(System.Globalization.CultureInfo.InvariantCulture)); + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + else + //serializer.Write(Value.ToString(System.Globalization.CultureInfo.InvariantCulture)); + serializer.WriteElement("Point", Value.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + //serializer.Write(", "); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Series.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Series.cs index a9514af..99ed672 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Series.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Series.cs @@ -305,6 +305,52 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\series"); + + serializer.WriteStartElement("Series"); + + + if (!_name.IsNull) + serializer.WriteSimpleAttribute("Name", Name); + + if (!_markerSize.IsNull) + serializer.WriteSimpleAttribute("MarkerSize", MarkerSize); + if (!_markerStyle.IsNull) + serializer.WriteSimpleAttribute("MarkerStyle", MarkerStyle); + + if (!_markerBackgroundColor.IsNull) + serializer.WriteSimpleAttribute("MarkerBackgroundColor", MarkerBackgroundColor); + if (!_markerForegroundColor.IsNull) + serializer.WriteSimpleAttribute("MarkerForegroundColor", MarkerForegroundColor); + + if (!_chartType.IsNull) + serializer.WriteSimpleAttribute("ChartType", ChartType); + + if (!_hasDataLabel.IsNull) + serializer.WriteSimpleAttribute("HasDataLabel", HasDataLabel); + + serializer.BeginAttributes(); + + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + if (!IsNull("FillFormat")) + _fillFormat.Serialize(serializer); + if (!IsNull("DataLabel")) + _dataLabel.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + _seriesElements.Serialize(serializer); + //serializer.WriteLine(""); + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs index e43f512..5a02c15 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs @@ -93,6 +93,16 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + int count = Count; + for (int index = 0; index < count; ++index) + { + Series series = this[index]; + series.Serialize(serializer); + } + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs index 1cde45c..59458a3 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs @@ -104,6 +104,19 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + int count = Count; + for (int index = 0; index < count; ++index) + { + Point point = this[index] as Point; + if (point == null) + serializer.WriteElement("Point"); + else + point.Serialize(serializer); + } + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TextArea.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TextArea.cs index 019e07e..d1ef8d7 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TextArea.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TextArea.cs @@ -359,6 +359,55 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + Chart chartObject = _parent as Chart; + + //serializer.WriteLine("\\" + chartObject.CheckTextArea(this)); + + serializer.WriteStartElement("TextArea"); + + serializer.WriteSimpleAttribute("Type", chartObject.CheckTextArea(this)); + + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + if (!_topPadding.IsNull) + serializer.WriteSimpleAttribute("TopPadding", TopPadding); + if (!_leftPadding.IsNull) + serializer.WriteSimpleAttribute("LeftPadding", LeftPadding); + if (!_rightPadding.IsNull) + serializer.WriteSimpleAttribute("RightPadding", RightPadding); + if (!_bottomPadding.IsNull) + serializer.WriteSimpleAttribute("BottomPadding", BottomPadding); + + if (!_width.IsNull) + serializer.WriteSimpleAttribute("Width", Width); + if (!_height.IsNull) + serializer.WriteSimpleAttribute("Height", Height); + + if (!_verticalAlignment.IsNull) + serializer.WriteSimpleAttribute("VerticalAlignment", VerticalAlignment); + + serializer.BeginAttributes(); + + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + if (!IsNull("FillFormat")) + _fillFormat.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + if (_elements != null) + _elements.Serialize(serializer); + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TickLabels.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TickLabels.cs index ef2bd31..7001ac4 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TickLabels.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/TickLabels.cs @@ -133,6 +133,24 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //int pos = serializer.BeginContent("TickLabels"); + serializer.WriteStartElement("TickLabels"); + + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + + if (_font != null) + _font.Serialize(serializer); + + if (!_format.IsNull) + serializer.WriteSimpleAttribute("Format", Format); + + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeries.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeries.cs index fb39269..a089838 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeries.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeries.cs @@ -115,6 +115,18 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\xvalues"); + serializer.WriteStartElement("XSeries"); + + //serializer.BeginContent(); + _xSeriesElements.Serialize(serializer); + //serializer.WriteLine(""); + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeriesElements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeriesElements.cs index a2bfb04..abb0744 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeriesElements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XSeriesElements.cs @@ -99,6 +99,20 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + int count = Count; + for (int index = 0; index < count; index++) + { + XValue xValue = this[index] as XValue; + if (xValue == null) + //serializer.Write("null, "); + serializer.WriteElement("XValue"); + else + xValue.Serialize(serializer); + } + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValue.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValue.cs index b1a2164..4a876e4 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValue.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValue.cs @@ -83,6 +83,12 @@ internal override void Serialize(Serializer serializer) serializer.Write("\"" + Value + "\", "); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.Write("\"" + Value + "\", "); + serializer.WriteElement("XValue", Value); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs index 4648129..c0012d3 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs @@ -93,6 +93,17 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + int count = Count; + for (int index = 0; index < count; ++index) + { + XSeries xSeries = this[index] as XSeries; + xSeries.Serialize(serializer); + } + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs index 484eb0f..42cd756 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs @@ -184,6 +184,40 @@ internal override void Serialize(Serializer serializer) serializer.EndAttributes(pos); } + internal override void Serialize(XmlSerializer serializer) + { + if (_code.Value == "") + throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "BookmarkField")); + + serializer.WriteStartElement("Barcode"); + + serializer.WriteElement("Code", Code); + //serializer.WriteLine("\\barcode(\"" + Code + "\")"); + + // int pos = serializer.BeginAttributes(); + + base.Serialize(serializer); + + if (!_orientation.IsNull) + serializer.WriteSimpleAttribute("Orientation", Orientation); + if (!_bearerBars.IsNull) + serializer.WriteSimpleAttribute("BearerBars", BearerBars); + if (!_text.IsNull) + serializer.WriteSimpleAttribute("Text", Text); + if (!_type.IsNull) + serializer.WriteSimpleAttribute("Type", Type); + if (!_lineRatio.IsNull) + serializer.WriteSimpleAttribute("LineRatio", LineRatio); + if (!_lineHeight.IsNull) + serializer.WriteSimpleAttribute("LineHeight", LineHeight); + if (!_narrowLineWidth.IsNull) + serializer.WriteSimpleAttribute("NarrowLineWidth", NarrowLineWidth); + + serializer.WriteEndElement(); // barcode + + //serializer.EndAttributes(pos); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/FillFormat.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/FillFormat.cs index a68f9d1..3f06376 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/FillFormat.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/FillFormat.cs @@ -98,6 +98,21 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.BeginContent("FillFormat"); + + serializer.WriteStartElement("FillFormat"); + + if (!_visible.IsNull) + serializer.WriteSimpleAttribute("Visible", Visible); + if (!_color.IsNull) + serializer.WriteSimpleAttribute("Color", Color); + + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs index e895d6b..9da5c84 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs @@ -185,6 +185,34 @@ internal override void Serialize(Serializer serializer) serializer.EndAttributes(pos); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\image(\"" + _name.Value.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\")"); + serializer.WriteStartElement("Image"); + + serializer.WriteSimpleAttribute("Name", _name.Value); + + if (!_scaleWidth.IsNull) + serializer.WriteSimpleAttribute("ScaleWidth", ScaleWidth); + if (!_scaleHeight.IsNull) + serializer.WriteSimpleAttribute("ScaleHeight", ScaleHeight); + if (!_lockAspectRatio.IsNull) + serializer.WriteSimpleAttribute("LockAspectRatio", LockAspectRatio); + if (!_resolution.IsNull) + serializer.WriteSimpleAttribute("Resolution", Resolution); + + base.Serialize(serializer); + + serializer.BeginAttributes(); + + if (!IsNull("PictureFormat")) + _pictureFormat.Serialize(serializer); + + serializer.EndAttributes(); + + serializer.WriteEndElement(); + } + /// /// Gets the concrete image path, taking into account the DOM document's DdlFile and /// ImagePath properties as well as the given working directory (which can be null). diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs index 6cb7811..1a541ac 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs @@ -234,6 +234,15 @@ internal void Serialize(Serializer serializer) else serializer.WriteSimpleAttribute("Left", ShapePosition); } + + internal void Serialize(XmlSerializer serializer) + { + if (_shapePosition == ShapePosition.Undefined) + serializer.WriteSimpleAttribute("Left", Position); + else + serializer.WriteSimpleAttribute("Left", ShapePosition); + } + #endregion /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LineFormat.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LineFormat.cs index 1256cb7..b3d59a1 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LineFormat.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LineFormat.cs @@ -137,6 +137,27 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //int pos = serializer.BeginContent("LineFormat"); + + serializer.WriteStartElement("LineFormat"); + + if (!_visible.IsNull) + serializer.WriteSimpleAttribute("Visible", Visible); + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + if (!_dashStyle.IsNull) + serializer.WriteSimpleAttribute("DashStyle", DashStyle); + if (!_width.IsNull) + serializer.WriteSimpleAttribute("Width", Width); + if (!_color.IsNull) + serializer.WriteSimpleAttribute("Color", Color); + + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/PictureFormat.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/PictureFormat.cs index 4561845..d9c1def 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/PictureFormat.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/PictureFormat.cs @@ -127,6 +127,25 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.BeginContent("PictureFormat"); + serializer.WriteStartElement("PictureFormat"); + + if (!_cropLeft.IsNull) + serializer.WriteSimpleAttribute("CropLeft", CropLeft); + if (!_cropRight.IsNull) + serializer.WriteSimpleAttribute("CropRight", CropRight); + if (!_cropTop.IsNull) + serializer.WriteSimpleAttribute("CropTop", CropTop); + if (!_cropBottom.IsNull) + serializer.WriteSimpleAttribute("CropBottom", CropBottom); + + //serializer.EndContent(); + serializer.WriteEndElement(); + + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Shape.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Shape.cs index 555906f..854b71c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Shape.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Shape.cs @@ -223,6 +223,33 @@ internal override void Serialize(Serializer serializer) _fillFormat.Serialize(serializer); } + internal override void Serialize(XmlSerializer serializer) + { + if (!_height.IsNull) + serializer.WriteSimpleAttribute("Height", Height); + if (!_width.IsNull) + serializer.WriteSimpleAttribute("Width", Width); + if (!_relativeHorizontal.IsNull) + serializer.WriteSimpleAttribute("RelativeHorizontal", RelativeHorizontal); + if (!_relativeVertical.IsNull) + serializer.WriteSimpleAttribute("RelativeVertical", RelativeVertical); + if (!IsNull("Left")) + _left.Serialize(serializer); + if (!IsNull("Top")) + _top.Serialize(serializer); + + serializer.BeginAttributes(); + + if (!IsNull("WrapFormat")) + _wrapFormat.Serialize(serializer); + if (!IsNull("LineFormat")) + _lineFormat.Serialize(serializer); + if (!IsNull("FillFormat")) + _fillFormat.Serialize(serializer); + + serializer.EndAttributes(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TextFrame.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TextFrame.cs index d4dbfbb..88878fe 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TextFrame.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TextFrame.cs @@ -281,6 +281,37 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\textframe"); + + serializer.WriteStartElement("TextFrame"); + + // int pos = serializer.BeginAttributes(); + + base.Serialize(serializer); + if (!_marginLeft.IsNull) + serializer.WriteSimpleAttribute("MarginLeft", MarginLeft); + if (!_marginRight.IsNull) + serializer.WriteSimpleAttribute("MarginRight", MarginRight); + if (!_marginTop.IsNull) + serializer.WriteSimpleAttribute("MarginTop", MarginTop); + if (!_marginBottom.IsNull) + serializer.WriteSimpleAttribute("MarginBottom", MarginBottom); + if (!_orientation.IsNull) + serializer.WriteSimpleAttribute("Orientation", Orientation); + + //serializer.EndAttributes(pos); + + + //serializer.BeginContent(); + if (_elements != null) + _elements.Serialize(serializer); + + //serializer.EndContent(); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs index 9fccc95..ada558d 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs @@ -230,6 +230,15 @@ internal void Serialize(Serializer serializer) else serializer.WriteSimpleAttribute("Top", ShapePosition); } + + internal void Serialize(XmlSerializer serializer) + { + if (_shapePosition == ShapePosition.Undefined) + serializer.WriteSimpleAttribute("Top", Position); + else + serializer.WriteSimpleAttribute("Top", ShapePosition); + } + #endregion /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/WrapFormat.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/WrapFormat.cs index 53bcd6a..0940e04 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/WrapFormat.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/WrapFormat.cs @@ -137,6 +137,28 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + //int pos = serializer.BeginContent("WrapFormat"); + + serializer.WriteStartElement("WrapFormat"); + + if (!_style.IsNull) + serializer.WriteSimpleAttribute("Style", Style); + if (!_distanceTop.IsNull) + serializer.WriteSimpleAttribute("DistanceTop", DistanceTop); + if (!_distanceLeft.IsNull) + serializer.WriteSimpleAttribute("DistanceLeft", DistanceLeft); + if (!_distanceRight.IsNull) + serializer.WriteSimpleAttribute("DistanceRight", DistanceRight); + if (!_distanceBottom.IsNull) + serializer.WriteSimpleAttribute("DistanceBottom", DistanceBottom); + + //serializer.EndContent(); + serializer.WriteEndElement(); + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs index 12b9d0f..21c3887 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs @@ -426,6 +426,55 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Cell"); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\cell"); + + if (_style.Value != String.Empty) + serializer.WriteSimpleAttribute("Style", Style); + + // if (!IsNull("Format")) + // _format.Serialize(serializer, "Format", null); + + if (!_mergeDown.IsNull) + serializer.WriteSimpleAttribute("MergeDown", MergeDown); + + if (!_mergeRight.IsNull) + serializer.WriteSimpleAttribute("MergeRight", MergeRight); + + if (!_verticalAlignment.IsNull) + serializer.WriteSimpleAttribute("VerticalAlignment", VerticalAlignment); + + if (_roundedCorner != RoundedCorner.None) + serializer.WriteSimpleAttribute("RoundedCorner", RoundedCorner); + + serializer.BeginAttributes(); + + if (!IsNull("Borders")) + _borders.Serialize(serializer, null); + + if (!IsNull("Shading")) + _shading.Serialize(serializer); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + serializer.EndAttributes(); + + //pos = serializer.BeginContent(); + if (!IsNull("Elements")) + _elements.Serialize(serializer); + + //serializer.EndContent(pos); + + serializer.WriteEndElement(); // cell + } + + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cells.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cells.cs index 66fa212..210c8a5 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cells.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cells.cs @@ -137,6 +137,14 @@ internal override void Serialize(Serializer serializer) this[cell].Serialize(serializer); } + internal override void Serialize(XmlSerializer serializer) + { + int cells = Count; + for (int cell = 0; cell < cells; cell++) + this[cell].Serialize(serializer); + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs index 0fa0636..5c4834f 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs @@ -316,6 +316,53 @@ internal override void Serialize(Serializer serializer) // columns has no content } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Column"); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\column"); + + if (_style.Value != String.Empty) + serializer.WriteSimpleAttribute("Style", Style); + + //if (!IsNull("Format")) + //_format.Serialize(serializer, "Format", null); + + if (!_headingFormat.IsNull) + serializer.WriteSimpleAttribute("HeadingFormat", HeadingFormat); + + if (!_leftPadding.IsNull) + serializer.WriteSimpleAttribute("LeftPadding", LeftPadding); + + if (!_rightPadding.IsNull) + serializer.WriteSimpleAttribute("RightPadding", RightPadding); + + if (!_width.IsNull) + serializer.WriteSimpleAttribute("Width", Width); + + if (!_keepWith.IsNull) + serializer.WriteSimpleAttribute("KeepWith", KeepWith); + + serializer.BeginAttributes(); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + if (!IsNull("Borders")) + _borders.Serialize(serializer, null); + + if (!IsNull("Shading")) + _shading.Serialize(serializer); + + serializer.EndAttributes(); + + serializer.WriteEndElement(); // column + + // columns has no content + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Columns.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Columns.cs index a1cc338..cc1949c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Columns.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Columns.cs @@ -156,6 +156,36 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Columns"); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\columns"); + + //int pos = serializer.BeginAttributes(); + + if (!_width.IsNull) + serializer.WriteSimpleAttribute("Width", Width); + + //serializer.EndAttributes(pos); + + //serializer.BeginContent(); + int clms = Count; + if (clms > 0) + { + for (int clm = 0; clm < clms; clm++) + this[clm].Serialize(serializer); + } + else + serializer.WriteComment("Invalid - no columns defined. Table will not render."); + + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs index 151f14d..c5fcb81 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs @@ -365,6 +365,63 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Row"); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\row"); + + if (_style.Value != String.Empty) + serializer.WriteSimpleAttribute("Style", Style); + + //if (!IsNull("Format")) + // _format.Serialize(serializer, "Format", null); + + if (!_height.IsNull) + serializer.WriteSimpleAttribute("Height", Height); + + if (!_heightRule.IsNull) + serializer.WriteSimpleAttribute("HeightRule", HeightRule); + + if (!_topPadding.IsNull) + serializer.WriteSimpleAttribute("TopPadding", TopPadding); + + if (!_bottomPadding.IsNull) + serializer.WriteSimpleAttribute("BottomPadding", BottomPadding); + + if (!_headingFormat.IsNull) + serializer.WriteSimpleAttribute("HeadingFormat", HeadingFormat); + + if (!_verticalAlignment.IsNull) + serializer.WriteSimpleAttribute("VerticalAlignment", VerticalAlignment); + + if (!_keepWith.IsNull) + serializer.WriteSimpleAttribute("KeepWith", KeepWith); + + serializer.BeginAttributes(); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + //Borders & Shading + if (!IsNull("Borders")) + _borders.Serialize(serializer, null); + + if (!IsNull("Shading")) + _shading.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + if (!IsNull("Cells")) + _cells.Serialize(serializer); + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Rows.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Rows.cs index 18cd99d..3211b56 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Rows.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Rows.cs @@ -200,6 +200,48 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Rows"); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\rows"); + + //int pos = serializer.BeginAttributes(); + + if (!_alignment.IsNull) + serializer.WriteSimpleAttribute("Alignment", Alignment); + + if (!_height.IsNull) + serializer.WriteSimpleAttribute("Height", Height); + + if (!_heightRule.IsNull) + serializer.WriteSimpleAttribute("HeightRule", HeightRule); + + if (!_leftIndent.IsNull) + serializer.WriteSimpleAttribute("LeftIndent", LeftIndent); + + if (!_verticalAlignment.IsNull) + serializer.WriteSimpleAttribute("VerticalAlignment", VerticalAlignment); + + //serializer.EndAttributes(pos); + + //serializer.BeginContent(); + int rows = Count; + if (rows > 0) + { + for (int row = 0; row < rows; row++) + this[row].Serialize(serializer); + } + else + serializer.WriteComment("Invalid - no rows defined. Table will not render."); + + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Table.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Table.cs index ab5ed7c..a5386dd 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Table.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Table.cs @@ -451,6 +451,55 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Table"); + + serializer.WriteComment(_comment.Value); + + //serializer.WriteLine("\\table"); + + if (_style.Value != String.Empty) + serializer.WriteSimpleAttribute("Style", Style); + + //if (!IsNull("Format")) + // _format.Serialize(serializer, "Format", null); + + if (!_topPadding.IsNull) + serializer.WriteSimpleAttribute("TopPadding", TopPadding); + + if (!_leftPadding.IsNull) + serializer.WriteSimpleAttribute("LeftPadding", LeftPadding); + + if (!_rightPadding.IsNull) + serializer.WriteSimpleAttribute("RightPadding", RightPadding); + + if (!_bottomPadding.IsNull) + serializer.WriteSimpleAttribute("BottomPadding", BottomPadding); + + serializer.BeginAttributes(); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + if (!IsNull("Borders")) + _borders.Serialize(serializer, null); + + if (!IsNull("Shading")) + _shading.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + Columns.Serialize(serializer); + Rows.Serialize(serializer); + //serializer.EndContent(); + + serializer.WriteEndElement(); + } + + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Border.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Border.cs index 887fd3a..4ce4986 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Border.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Border.cs @@ -144,6 +144,12 @@ internal override void Serialize(Serializer serializer) throw new Exception("A Border cannot be serialized alone."); } + internal override void Serialize(XmlSerializer serializer) + { + throw new Exception("A Border cannot be serialized alone."); + } + + /// /// Converts Border into DDL. /// @@ -169,6 +175,33 @@ internal void Serialize(Serializer serializer, string name, Border refBorder) serializer.EndContent(pos); } + internal void Serialize(XmlSerializer serializer, string name, Border refBorder) + { + serializer.WriteStartElement(name); + + if (_fClear.Value) + //serializer.WriteLine(name + " = null"); + serializer.WriteSimpleAttribute("Clear",true); + + //int pos = serializer.BeginContent(name); + + if (!_visible.IsNull && (refBorder == null || (Visible != refBorder.Visible))) + serializer.WriteSimpleAttribute("Visible", Visible); + + if (!_style.IsNull && (refBorder == null || (Style != refBorder.Style))) + serializer.WriteSimpleAttribute("Style", Style); + + if (!_width.IsNull && (refBorder == null || (Width != refBorder.Width))) + serializer.WriteSimpleAttribute("Width", Width); + + if (!_color.IsNull && (refBorder == null || (Color != refBorder.Color))) + serializer.WriteSimpleAttribute("Color", Color); + + //serializer.EndContent(pos); + + serializer.WriteEndElement(); // + } + /// /// Returns the _meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs index f2bdf90..17cdc6f 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs @@ -379,9 +379,15 @@ internal override void Serialize(Serializer serializer) Serialize(serializer, null); } + internal override void Serialize(XmlSerializer serializer) + { + Serialize(serializer, null); + } + /// /// Converts Borders into DDL. /// + internal void Serialize(Serializer serializer, Borders refBorders) { if (_clearAll) @@ -434,6 +440,61 @@ internal void Serialize(Serializer serializer, Borders refBorders) serializer.EndContent(pos); } + internal void Serialize(XmlSerializer serializer, Borders refBorders) + { + //int pos = serializer.BeginContent("Borders"); + serializer.WriteStartElement("Borders"); + + // TODO era esterno + if (_clearAll) + serializer.WriteSimpleAttribute("Clear", true); + + if (!_visible.IsNull && (refBorders == null || refBorders._visible.IsNull || (Visible != refBorders.Visible))) + serializer.WriteSimpleAttribute("Visible", Visible); + + if (!_style.IsNull && (refBorders == null || (Style != refBorders.Style))) + serializer.WriteSimpleAttribute("Style", Style); + + if (!_width.IsNull && (refBorders == null || (_width.Value != refBorders._width.Value))) + serializer.WriteSimpleAttribute("Width", Width); + + if (!_color.IsNull && (refBorders == null || ((Color.Argb != refBorders.Color.Argb)))) + serializer.WriteSimpleAttribute("Color", Color); + + if (!_distanceFromTop.IsNull && (refBorders == null || (DistanceFromTop.Point != refBorders.DistanceFromTop.Point))) + serializer.WriteSimpleAttribute("DistanceFromTop", DistanceFromTop); + + if (!_distanceFromBottom.IsNull && (refBorders == null || (DistanceFromBottom.Point != refBorders.DistanceFromBottom.Point))) + serializer.WriteSimpleAttribute("DistanceFromBottom", DistanceFromBottom); + + if (!_distanceFromLeft.IsNull && (refBorders == null || (DistanceFromLeft.Point != refBorders.DistanceFromLeft.Point))) + serializer.WriteSimpleAttribute("DistanceFromLeft", DistanceFromLeft); + + if (!_distanceFromRight.IsNull && (refBorders == null || (DistanceFromRight.Point != refBorders.DistanceFromRight.Point))) + serializer.WriteSimpleAttribute("DistanceFromRight", DistanceFromRight); + + if (!IsNull("Top")) + _top.Serialize(serializer, "Top", null); + + if (!IsNull("Left")) + _left.Serialize(serializer, "Left", null); + + if (!IsNull("Bottom")) + _bottom.Serialize(serializer, "Bottom", null); + + if (!IsNull("Right")) + _right.Serialize(serializer, "Right", null); + + if (!IsNull("DiagonalDown")) + _diagonalDown.Serialize(serializer, "DiagonalDown", null); + + if (!IsNull("DiagonalUp")) + _diagonalUp.Serialize(serializer, "DiagonalUp", null); + + //serializer.EndContent(pos); + serializer.WriteEndElement(); // borders + } + /// /// Gets a name of a border. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs index addbe25..ffa9339 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs @@ -186,6 +186,80 @@ internal override void Serialize(Serializer serializer) serializer.Write(text); } + internal override void Serialize(XmlSerializer serializer) + { + + string text = String.Empty; + if (_count == 1) + { + if ((SymbolName)_symbolName.Value == SymbolName.Tab) + text = "tab"; + else if ((SymbolName)_symbolName.Value == SymbolName.LineBreak) + text = "br"; + else if ((SymbolName)_symbolName.Value == SymbolName.ParaBreak) + //text = "ParagraphBreak"; + throw new NotImplementedException("ParagraphBreak"); + //else if (symbolType == SymbolName.MarginBreak) + // text = "\\marginbreak "; + + if (text != "") + { + /*serializer.WriteStartElement("Chr"); + serializer.WriteSimpleAttribute("Value", text); + serializer.WriteEndElement();*/ + serializer.WriteElement(text); + return; + } + } + + serializer.WriteStartElement("Chr"); + + if (((uint)_symbolName.Value & 0xF0000000) == 0xF0000000) + { + // SymbolName == SpaceType? + if (((uint)_symbolName.Value & 0xF1000000) == 0xF1000000) + { + if ((SymbolName)_symbolName.Value == SymbolName.Blank) + { + //Note: Don't try to optimize it by leaving away the braces in case a single space is added. + //This would lead to confusion with '(' in directly following text. + //text = "\\space(" + Count + ")"; + serializer.WriteSimpleAttribute("Value", "Space"); + serializer.WriteSimpleAttribute("Count", Count); + } + else + { + if (_count == 1) + //text = "\\space(" + SymbolName + ")"; + { + serializer.WriteSimpleAttribute("Value", "Space"); + serializer.WriteSimpleAttribute("Symbol", SymbolName); + } + else + //text = "\\space(" + SymbolName + ", " + Count + ")"; + { + serializer.WriteSimpleAttribute("Value", "Space"); + serializer.WriteSimpleAttribute("Symbol", SymbolName); + serializer.WriteSimpleAttribute("Count", Count); + } + } + } + else + { + //text = "\\symbol(" + SymbolName + ")"; + serializer.WriteSimpleAttribute("Symbol", SymbolName); + } + } + else + { + // symbolType is a (unicode) character + //text = " \\chr(0x" + _symbolName.Value.ToString("X") + ")"; + serializer.WriteSimpleAttribute("Value", "0x" + _symbolName.Value.ToString("X")); + } + + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs index 3df47e8..66a9576 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs @@ -349,6 +349,56 @@ internal override void Serialize(Serializer serializer) serializer.Flush(); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartDocument(); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\document"); + serializer.WriteStartElement("Document"); + + + + //if (!IsNull("Info")) + // Info.Serialize(serializer); + + if (!_defaultTabStop.IsNull) + serializer.WriteSimpleAttribute("DefaultTabStop", DefaultTabStop); + if (!_footnoteLocation.IsNull) + serializer.WriteSimpleAttribute("FootnoteLocation", FootnoteLocation); + if (!_footnoteNumberingRule.IsNull) + serializer.WriteSimpleAttribute("FootnoteNumberingRule", FootnoteNumberingRule); + if (!_footnoteNumberStyle.IsNull) + serializer.WriteSimpleAttribute("FootnoteNumberStyle", FootnoteNumberStyle); + if (!_footnoteStartingNumber.IsNull) + serializer.WriteSimpleAttribute("FootnoteStartingNumber", FootnoteStartingNumber); + if (!_imagePath.IsNull) + serializer.WriteSimpleAttribute("ImagePath", ImagePath); + if (!_useCmykColor.IsNull) + serializer.WriteSimpleAttribute("UseCmykColor", UseCmykColor); + + serializer.BeginAttributes(); + + if (!IsNull("Info")) + Info.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + Styles.Serialize(serializer); + + if (!IsNull("Sections")) + Sections.Serialize(serializer); + + //serializer.EndContent(); + + serializer.WriteEndElement(); // document + + serializer.WriteEndDocument(); + + serializer.Flush(); + } + /// /// Allows the visitor object to visit the document object and all its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentElements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentElements.cs index c5addc4..9eb0013 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentElements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentElements.cs @@ -212,6 +212,28 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + int count = Count; + if (count == 1 && this[0] is Paragraph) + { + // Omit keyword if paragraph has no attributes set. + Paragraph paragraph = (Paragraph)this[0]; + if (paragraph.Style == "" && paragraph.IsNull("Format")) + { + paragraph.SerializeContentOnly = true; + paragraph.Serialize(serializer); + paragraph.SerializeContentOnly = false; + return; + } + } + for (int index = 0; index < count; index++) + { + DocumentObject documentElement = this[index]; + documentElement.Serialize(serializer); + } + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentInfo.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentInfo.cs index 3b74829..8422e08 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentInfo.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentInfo.cs @@ -142,6 +142,30 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Info"); + + serializer.WriteComment(_comment.Value); + //int pos = serializer.BeginContent("Info"); + + if (Title != String.Empty) + serializer.WriteSimpleAttribute("Title", Title); + + if (Subject != String.Empty) + serializer.WriteSimpleAttribute("Subject", Subject); + + if (Author != String.Empty) + serializer.WriteSimpleAttribute("Author", Author); + + if (Keywords != String.Empty) + serializer.WriteSimpleAttribute("Keywords", Keywords); + + //serializer.EndContent(pos); + serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs index ef8b2cf..d1ee40e 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs @@ -141,11 +141,28 @@ public Section Section } private Section _section; + /// + /// Gets or sets the serialization format. + /// + public SerializationFormat SerializationFormat + { + get { return _serializationFormat; } + set { _serializationFormat = value; } + } + + internal SerializationFormat _serializationFormat = SerializationFormat.DDL; + + /// /// Converts DocumentObject into DDL. /// internal abstract void Serialize(Serializer serializer); + /// + /// Converts DocumentObject into XML DDL. + /// + internal abstract void Serialize(XmlSerializer serializer); + /// /// Returns the value with the specified name. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs index 907736a..07bf0f6 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs @@ -451,6 +451,165 @@ internal void Serialize(Serializer serializer, Font font) } } + internal override void Serialize(XmlSerializer serializer) + { + Serialize(serializer, null); + } + + internal void Serialize(XmlSerializer serializer, Font font) + { + if (Parent is FormattedText) + { + string fontStyle = ""; + if (((FormattedText)Parent)._style.IsNull) + { + // Check if we can use a DDL keyword. + FontProperties notNull = CheckWhatIsNotNull(); + if (notNull == FontProperties.Size) + { + //serializer.Write("\\fontsize(" + _size + ")"); + serializer.WriteStartElement("Font"); + serializer.WriteSimpleAttribute("Size", _size); + //serializer.WriteEndElement(); // font + return; + } + if (notNull == FontProperties.Bold && _bold.Value) + { + //serializer.Write("\\bold"); + serializer.WriteStartElement("Font"); + serializer.WriteSimpleAttribute("Bold", true); + //serializer.WriteEndElement(); // font + return; + } + if (notNull == FontProperties.Italic && _italic.Value) + { + //serializer.Write("\\italic"); + serializer.WriteStartElement("Font"); + serializer.WriteSimpleAttribute("Italic", true); + //serializer.WriteEndElement(); // font + return; + } + if (notNull == FontProperties.Color) + { + //serializer.Write("\\fontcolor(" + _color + ")"); + serializer.WriteStartElement("Font"); + serializer.WriteSimpleAttribute("Color", _color); + //serializer.WriteEndElement(); // font + return; + } + } + else + // fontStyle = "(\"" + ((FormattedText)Parent).Style + "\")"; + fontStyle = ((FormattedText)Parent).Style; + + //bool needBlank = false; // nice, but later... + //serializer.Write("\\font" + fontStyle + "["); + + serializer.WriteStartElement("Font"); + + if (fontStyle != "") + serializer.WriteSimpleAttribute("Style", fontStyle); + + if (!_name.IsNull && _name.Value != "") + serializer.WriteSimpleAttribute("Name", Name); + +#if DEBUG_ // Test + if (!_size.IsNull && Size != 0 && Size.Point == 0) + GetType(); +#endif + if ((!_size.IsNull)) + serializer.WriteSimpleAttribute("Size", Size); + + if (!_bold.IsNull) + serializer.WriteSimpleAttribute("Bold", Bold); + + if (!_italic.IsNull) + serializer.WriteSimpleAttribute("Italic", Italic); + + if (!_underline.IsNull) + serializer.WriteSimpleAttribute("Underline", Underline); + + if (!_superscript.IsNull) + serializer.WriteSimpleAttribute("Superscript", Superscript); + + if (!_subscript.IsNull) + serializer.WriteSimpleAttribute("Subscript", Subscript); + + if (!_color.IsNull) + serializer.WriteSimpleAttribute("Color", Color); + + //serializer.Write("]"); + //serializer.WriteEndElement(); // font + } + else + { + //int pos = serializer.BeginContent("Font"); + serializer.WriteStartElement("Font"); + +#if true + // Don't write null values if font is null. + // Do write null values if font is not null! + if ((!_name.IsNull && Name != String.Empty && font == null) || + (font != null && !_name.IsNull && Name != String.Empty && Name != font.Name)) + serializer.WriteSimpleAttribute("Name", Name); + +#if DEBUG_ + // Test + if (!_size.IsNull && Size != 0 && Size.Point == 0) + GetType(); +#endif + + if (!_size.IsNull && + (font == null || Size != font.Size)) + serializer.WriteSimpleAttribute("Size", Size); + // NBool and NEnum have to be compared directly to check whether the value Null is. + if (!_bold.IsNull && (font == null || Bold != font.Bold || font._bold.IsNull)) + serializer.WriteSimpleAttribute("Bold", Bold); + + if (!_italic.IsNull && (font == null || Italic != font.Italic || font._italic.IsNull)) + serializer.WriteSimpleAttribute("Italic", Italic); + + if (!_underline.IsNull && (font == null || Underline != font.Underline || font._underline.IsNull)) + serializer.WriteSimpleAttribute("Underline", Underline); + + if (!_superscript.IsNull && (font == null || Superscript != font.Superscript || font._superscript.IsNull)) + serializer.WriteSimpleAttribute("Superscript", Superscript); + + if (!_subscript.IsNull && (font == null || Subscript != font.Subscript || font._subscript.IsNull)) + serializer.WriteSimpleAttribute("Subscript", Subscript); + + if (!_color.IsNull && (font == null || Color.Argb != font.Color.Argb))// && Color.RGB != Color.Transparent.RGB) + serializer.WriteSimpleAttribute("Color", Color); +#else + if ((!this .name.IsNull && Name != String.Empty) && (font == null || Name != font.Name)) + serializer.WriteSimpleAttribute("Name", Name); + + if (!this .size.IsNull && (font == null || Size != font.Size)) + serializer.WriteSimpleAttribute("Size", Size); + //NBool and NEnum have to be compared directly to check whether the value Null is + if (!this .bold.IsNull && (font == null || Bold != font.Bold)) + serializer.WriteSimpleAttribute("Bold", Bold); + + if (!this .italic.IsNull && (font == null || Italic != font.Italic)) + serializer.WriteSimpleAttribute("Italic", Italic); + + if (!this .underline.IsNull && (font == null || Underline != font.Underline)) + serializer.WriteSimpleAttribute("Underline", Underline); + + if (!this .superscript.IsNull && (font == null || Superscript != font.Superscript)) + serializer.WriteSimpleAttribute("Superscript", Superscript); + + if (!this .subscript.IsNull && (font == null || Subscript != font.Subscript)) + serializer.WriteSimpleAttribute("Subscript", Subscript); + + if (!this .color.IsNull && (font == null || Color.Argb != font.Color.Argb))// && Color.RGB != Color.Transparent.RGB) + serializer.WriteSimpleAttribute("Color", Color); +#endif + //serializer.EndContent(pos); + serializer.WriteEndElement(); // font + } + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Footnote.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Footnote.cs index 0aba094..abaa56f 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Footnote.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Footnote.cs @@ -228,6 +228,33 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + //serializer.WriteLine("\\footnote"); + serializer.WriteStartElement("Footnote"); + + //int pos = serializer.BeginAttributes(); + + if (_reference.Value != string.Empty) + serializer.WriteSimpleAttribute("Reference", Reference); + if (_style.Value != string.Empty) + serializer.WriteSimpleAttribute("Style", Style); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + //serializer.EndAttributes(pos); + + //pos = serializer.BeginContent(); + + if (!IsNull("Elements")) + _elements.Serialize(serializer); + + //serializer.EndContent(pos); + + serializer.WriteEndElement(); // footnote + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/FormattedText.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/FormattedText.cs index b3c47e9..69f9520 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/FormattedText.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/FormattedText.cs @@ -610,10 +610,49 @@ internal override void Serialize(Serializer serializer) serializer.Write("}"); } - /// - /// Allows the visitor object to visit the document object and its child objects. - /// - void IVisitable.AcceptVisitor(DocumentObjectVisitor visitor, bool visitChildren) + internal override void Serialize(XmlSerializer serializer) + { + + //serializer.WriteStartElement("Text"); + + bool isFormatted = false; + if (!IsNull("Font")) + { + Font.Serialize(serializer); + isFormatted = true; + } + else + { + if (!_style.IsNull) + { + //serializer.Write("\\font(\"" + Style + "\")"); + //serializer.WriteSimpleAttribute("Font", Style); + serializer.WriteStartElement("Font"); + serializer.WriteSimpleAttribute("Style", Style); + isFormatted = true; + } + } + + //if (isFormatted) + //serializer.Write("{"); + // serializer.WriteStartElement("p"); + + if (!IsNull("Elements")) + Elements.Serialize(serializer); + + //if (isFormatted) + //serializer.Write("}"); + //serializer.WriteEndElement(); + + if (isFormatted) + serializer.WriteEndElement(); + } + + + /// + /// Allows the visitor object to visit the document object and its child objects. + /// + void IVisitable.AcceptVisitor(DocumentObjectVisitor visitor, bool visitChildren) { visitor.VisitFormattedText(this); diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs index 3b985be..71a803d 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs @@ -295,7 +295,7 @@ internal override void Serialize(Serializer serializer) Serialize(serializer, "evenpage"); else if (headersfooters.FirstPage == this) Serialize(serializer, "firstpage"); - } + } /// /// Converts HeaderFooter into DDL. @@ -316,6 +316,42 @@ internal void Serialize(Serializer serializer, string prefix) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + HeadersFooters headersfooters = (HeadersFooters)_parent; + if (headersfooters.Primary == this) + Serialize(serializer, "Primary"); + else if (headersfooters.EvenPage == this) + Serialize(serializer, "Evenpage"); + else if (headersfooters.FirstPage == this) + Serialize(serializer, "Firstpage"); + } + + internal void Serialize(XmlSerializer serializer, string prefix) + { + + //serializer.WriteLine("\\" + prefix + (IsHeader ? "header" : "footer")); + serializer.WriteStartElement(prefix + (IsHeader ? "Header" : "Footer")); + + serializer.WriteComment(_comment.Value); + + serializer.BeginAttributes(); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + + if (!IsNull("Elements")) + _elements.Serialize(serializer); + + //serializer.EndContent(); + + serializer.WriteEndElement(); // header/footer + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs index 9d50703..b91e3d1 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs @@ -183,6 +183,25 @@ internal override void Serialize(Serializer serializer) FirstPage.Serialize(serializer, "firstpage"); } + internal override void Serialize(XmlSerializer serializer) + { + bool hasPrimary = HasHeaderFooter(HeaderFooterIndex.Primary); + bool hasEvenPage = HasHeaderFooter(HeaderFooterIndex.EvenPage); + bool hasFirstPage = HasHeaderFooter(HeaderFooterIndex.FirstPage); + + // \primary... + if (hasPrimary) + Primary.Serialize(serializer, "Primary"); + + // \even... + if (hasEvenPage) + EvenPage.Serialize(serializer, "Evenpage"); + + // \firstpage... + if (hasFirstPage) + FirstPage.Serialize(serializer, "Firstpage"); + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs index 145c0fe..9326ab2 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs @@ -502,6 +502,33 @@ internal override void Serialize(Serializer serializer) serializer.Write("}"); } + internal override void Serialize(XmlSerializer serializer) + { + if (_name.Value == string.Empty) + throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "Hyperlink")); + + //serializer.Write("\\hyperlink"); + serializer.WriteStartElement("Hyperlink"); + + //string str = "[Name = \"" + Name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""; + serializer.WriteSimpleAttribute("Name", Name); + + if (!_type.IsNull) + //str += " Type = " + Type; + serializer.WriteSimpleAttribute("Type", Type); + //str += "]"; + + //serializer.Write(str); + //serializer.Write("{"); + + if (_elements != null) + _elements.Serialize(serializer); + + //serializer.Write("}"); + serializer.WriteEndElement(); // + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs index b78aff8..84e6771 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs @@ -110,6 +110,17 @@ internal override void Serialize(Serializer serializer) serializer.WriteSimpleAttribute("ListInfo.ContinuePreviousList", ContinuePreviousList); } + internal override void Serialize(XmlSerializer serializer) + { + + if (!_listType.IsNull) + serializer.WriteSimpleAttribute("ListInfo.ListType", ListType); + if (!_numberPosition.IsNull) + serializer.WriteSimpleAttribute("ListInfo.NumberPosition", NumberPosition); + if (!_continuePreviousList.IsNull) + serializer.WriteSimpleAttribute("ListInfo.ContinuePreviousList", ContinuePreviousList); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageBreak.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageBreak.cs index 665af4f..71008fb 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageBreak.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageBreak.cs @@ -66,6 +66,11 @@ internal override void Serialize(Serializer serializer) serializer.WriteLine("\\pagebreak"); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteElement("Pagebreak"); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs index 6f36692..ad0441b 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs @@ -454,6 +454,66 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("PageSetup"); + + serializer.WriteComment(_comment.Value); + //int pos = serializer.BeginContent("PageSetup"); + + if (!_pageHeight.IsNull) + serializer.WriteSimpleAttribute("PageHeight", PageHeight); + + if (!_pageWidth.IsNull) + serializer.WriteSimpleAttribute("PageWidth", PageWidth); + + if (!_orientation.IsNull) + serializer.WriteSimpleAttribute("Orientation", Orientation); + + if (!_leftMargin.IsNull) + serializer.WriteSimpleAttribute("LeftMargin", LeftMargin); + + if (!_rightMargin.IsNull) + serializer.WriteSimpleAttribute("RightMargin", RightMargin); + + if (!_topMargin.IsNull) + serializer.WriteSimpleAttribute("TopMargin", TopMargin); + + if (!_bottomMargin.IsNull) + serializer.WriteSimpleAttribute("BottomMargin", BottomMargin); + + if (!_footerDistance.IsNull) + serializer.WriteSimpleAttribute("FooterDistance", FooterDistance); + + if (!_headerDistance.IsNull) + serializer.WriteSimpleAttribute("HeaderDistance", HeaderDistance); + + if (!_oddAndEvenPagesHeaderFooter.IsNull) + serializer.WriteSimpleAttribute("OddAndEvenPagesHeaderFooter", OddAndEvenPagesHeaderFooter); + + if (!_differentFirstPageHeaderFooter.IsNull) + serializer.WriteSimpleAttribute("DifferentFirstPageHeaderFooter", DifferentFirstPageHeaderFooter); + + if (!_sectionStart.IsNull) + serializer.WriteSimpleAttribute("SectionStart", SectionStart); + + if (!_pageFormat.IsNull) + serializer.WriteSimpleAttribute("PageFormat", PageFormat); + + if (!_mirrorMargins.IsNull) + serializer.WriteSimpleAttribute("MirrorMargins", MirrorMargins); + + if (!_horizontalPageBreak.IsNull) + serializer.WriteSimpleAttribute("HorizontalPageBreak", HorizontalPageBreak); + + if (!_startingNumber.IsNull) + serializer.WriteSimpleAttribute("StartingNumber", StartingNumber); + + //serializer.EndContent(pos); + serializer.WriteEndElement(); // PageSetup + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs index ce01027..455684a 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs @@ -39,584 +39,621 @@ namespace MigraDoc.DocumentObjectModel { - /// - /// Represents a paragraph which is used to build up a document with text. - /// - public class Paragraph : DocumentObject, IVisitable - { - /// - /// Initializes a new instance of the Paragraph class. - /// - public Paragraph() - { } - - /// - /// Initializes a new instance of the Paragraph class with the specified parent. - /// - internal Paragraph(DocumentObject parent) : base(parent) { } - - #region Methods - /// - /// Creates a deep copy of this object. - /// - public new Paragraph Clone() - { - return (Paragraph)DeepCopy(); - } - - /// - /// Implements the deep copy of the object. - /// - protected override object DeepCopy() - { - Paragraph paragraph = (Paragraph)base.DeepCopy(); - if (paragraph._format != null) - { - paragraph._format = paragraph._format.Clone(); - paragraph._format._parent = paragraph; - } - if (paragraph._elements != null) - { - paragraph._elements = paragraph._elements.Clone(); - paragraph._elements._parent = paragraph; - } - return paragraph; - } - - /// - /// Adds a text phrase to the paragraph. - /// - public Text AddText(String text) - { - return Elements.AddText(text); - } - - /// - /// Adds a single character repeated the specified number of times to the paragraph. - /// - public Text AddChar(char ch, int count) - { - return Elements.AddChar(ch, count); - } - - /// - /// Adds a single character to the paragraph. - /// - public Text AddChar(char ch) - { - return Elements.AddChar(ch); - } - - /// - /// Adds one or more Symbol objects. - /// - public Character AddCharacter(SymbolName symbolType, int count) - { - return Elements.AddCharacter(symbolType, count); - } - - /// - /// Adds a Symbol object. - /// - public Character AddCharacter(SymbolName symbolType) - { - return Elements.AddCharacter(symbolType); - } - - /// - /// Adds one or more Symbol objects defined by a character. - /// - public Character AddCharacter(char ch, int count) - { - return Elements.AddCharacter(ch, count); - } - - /// - /// Adds a Symbol object defined by a character. - /// - public Character AddCharacter(char ch) - { - return Elements.AddCharacter(ch); - } - - /// - /// Adds a space character as many as count. - /// - public Character AddSpace(int count) - { - return Elements.AddSpace(count); - } - - /// - /// Adds a horizontal tab. - /// - public void AddTab() - { - Elements.AddTab(); - } - - /// - /// Adds a line break. - /// - public void AddLineBreak() - { - Elements.AddLineBreak(); - } - - /// - /// Adds a new FormattedText. - /// - public FormattedText AddFormattedText() - { - return Elements.AddFormattedText(); - } - - /// - /// Adds a new FormattedText object with the given format. - /// - public FormattedText AddFormattedText(TextFormat textFormat) - { - return Elements.AddFormattedText(textFormat); - } - - /// - /// Adds a new FormattedText with the given Font. - /// - public FormattedText AddFormattedText(Font font) - { - return Elements.AddFormattedText(font); - } - - /// - /// Adds a new FormattedText with the given text. - /// - public FormattedText AddFormattedText(string text) - { - return Elements.AddFormattedText(text); - } - - /// - /// Adds a new FormattedText object with the given text and format. - /// - public FormattedText AddFormattedText(string text, TextFormat textFormat) - { - return Elements.AddFormattedText(text, textFormat); - } - - /// - /// Adds a new FormattedText object with the given text and font. - /// - public FormattedText AddFormattedText(string text, Font font) - { - return Elements.AddFormattedText(text, font); - } - - /// - /// Adds a new FormattedText object with the given text and style. - /// - public FormattedText AddFormattedText(string text, string style) - { - return Elements.AddFormattedText(text, style); - } - - /// - /// Adds a new Hyperlink of Type "Local", - /// i.e. the Target is a Bookmark within the Document - /// - public Hyperlink AddHyperlink(string name) - { - return Elements.AddHyperlink(name); - } - - /// - /// Adds a new Hyperlink - /// - public Hyperlink AddHyperlink(string name, HyperlinkType type) - { - return Elements.AddHyperlink(name, type); - } - - /// - /// Adds a new Bookmark. - /// - public BookmarkField AddBookmark(string name) - { - return Elements.AddBookmark(name); - } - - /// - /// Adds a new PageField. - /// - public PageField AddPageField() - { - return Elements.AddPageField(); - } - - /// - /// Adds a new PageRefField. - /// - public PageRefField AddPageRefField(string name) - { - return Elements.AddPageRefField(name); - } - - /// - /// Adds a new NumPagesField. - /// - public NumPagesField AddNumPagesField() - { - return Elements.AddNumPagesField(); - } - - /// - /// Adds a new SectionField. - /// - public SectionField AddSectionField() - { - return Elements.AddSectionField(); - } - - /// - /// Adds a new SectionPagesField. - /// - public SectionPagesField AddSectionPagesField() - { - return Elements.AddSectionPagesField(); - } - - /// - /// Adds a new DateField. - /// - public DateField AddDateField() - { - return Elements.AddDateField(); - } - - /// - /// Adds a new DateField. - /// - public DateField AddDateField(string format) - { - return Elements.AddDateField(format); - } - - /// - /// Adds a new InfoField. - /// - public InfoField AddInfoField(InfoFieldType iType) - { - return Elements.AddInfoField(iType); - } - - /// - /// Adds a new Footnote with the specified text. - /// - public Footnote AddFootnote(string text) - { - return Elements.AddFootnote(text); - } - - /// - /// Adds a new Footnote. - /// - public Footnote AddFootnote() - { - return Elements.AddFootnote(); - } - - /// - /// Adds a new Image object - /// - public Image AddImage(string fileName) - { - return Elements.AddImage(fileName); - } - - /// - /// Adds a new Bookmark - /// - public void Add(BookmarkField bookmark) - { - Elements.Add(bookmark); - } - - /// - /// Adds a new PageField - /// - public void Add(PageField pageField) - { - Elements.Add(pageField); - } - - /// - /// Adds a new PageRefField - /// - public void Add(PageRefField pageRefField) - { - Elements.Add(pageRefField); - } - - /// - /// Adds a new NumPagesField - /// - public void Add(NumPagesField numPagesField) - { - Elements.Add(numPagesField); - } - - /// - /// Adds a new SectionField - /// - public void Add(SectionField sectionField) - { - Elements.Add(sectionField); - } - - /// - /// Adds a new SectionPagesField - /// - public void Add(SectionPagesField sectionPagesField) - { - Elements.Add(sectionPagesField); - } - - /// - /// Adds a new DateField - /// - public void Add(DateField dateField) - { - Elements.Add(dateField); - } - - /// - /// Adds a new InfoField - /// - public void Add(InfoField infoField) - { - Elements.Add(infoField); - } - - /// - /// Adds a new Footnote - /// - public void Add(Footnote footnote) - { - Elements.Add(footnote); - } - - /// - /// Adds a new Text - /// - public void Add(Text text) - { - Elements.Add(text); - } - - /// - /// Adds a new FormattedText - /// - public void Add(FormattedText formattedText) - { - Elements.Add(formattedText); - } - - /// - /// Adds a new Hyperlink - /// - public void Add(Hyperlink hyperlink) - { - Elements.Add(hyperlink); - } - - /// - /// Adds a new Image - /// - public void Add(Image image) - { - Elements.Add(image); - } - - /// - /// Adds a new Character - /// - public void Add(Character character) - { - Elements.Add(character); - } - #endregion - - #region Properties - /// - /// Gets or sets the style name. - /// - public string Style - { - get { return _style.Value; } - set { _style.Value = value; } - } - [DV] - internal NString _style = NString.NullValue; - - /// - /// Gets or sets the ParagraphFormat object of the paragraph. - /// - public ParagraphFormat Format - { - get { return _format ?? (_format = new ParagraphFormat(this)); } - set - { - SetParent(value); - _format = value; - } - } - [DV] - internal ParagraphFormat _format; - - /// - /// Gets the collection of document objects that defines the paragraph. - /// - public ParagraphElements Elements - { - get { return _elements ?? (_elements = new ParagraphElements(this)); } - set - { - SetParent(value); - _elements = value; - } - } - [DV] - internal ParagraphElements _elements; - - /// - /// Gets or sets a comment associated with this object. - /// - public string Comment - { - get { return _comment.Value; } - set { _comment.Value = value; } - } - [DV] - internal NString _comment = NString.NullValue; - #endregion - - #region Internal - /// - /// Allows the visitor object to visit the document object and its child objects. - /// - void IVisitable.AcceptVisitor(DocumentObjectVisitor visitor, bool visitChildren) - { - visitor.VisitParagraph(this); - - if (visitChildren && _elements != null) - ((IVisitable)_elements).AcceptVisitor(visitor, true); - } - - /// - /// For internal use only. - /// - internal bool SerializeContentOnly - { - get { return _serializeContentOnly; } - set { _serializeContentOnly = value; } - } - bool _serializeContentOnly; - - /// - /// Converts Paragraph into DDL. - /// - internal override void Serialize(Serializer serializer) - { - if (!_serializeContentOnly) - { - serializer.WriteComment(_comment.Value); - serializer.WriteLine("\\paragraph"); - - int pos = serializer.BeginAttributes(); - - if (_style.Value != "") - serializer.WriteLine("Style = \"" + _style.Value + "\""); - - if (!IsNull("Format")) - _format.Serialize(serializer, "Format", null); - - serializer.EndAttributes(pos); - - serializer.BeginContent(); - if (!IsNull("Elements")) - Elements.Serialize(serializer); - serializer.CloseUpLine(); - serializer.EndContent(); - } - else - { - Elements.Serialize(serializer); - serializer.CloseUpLine(); - } - } - - /// - /// Returns the meta object of this instance. - /// - internal override Meta Meta - { - get { return _meta ?? (_meta = new Meta(typeof(Paragraph))); } - } - - /// - /// Returns an array of Paragraphs that are separated by parabreaks. Null if no parabreak is found. - /// - internal Paragraph[] SplitOnParaBreak() - { - if (_elements == null) - return null; - - int startIdx = 0; - List paragraphs = new List(); - for (int idx = 0; idx < Elements.Count; ++idx) - { - DocumentObject element = Elements[idx]; - if (element is Character) - { - Character character = (Character)element; - if (character.SymbolName == SymbolName.ParaBreak) - { - Paragraph paragraph = new Paragraph(); - paragraph.Format = Format.Clone(); - paragraph.Style = Style; - paragraph.Elements = SubsetElements(startIdx, idx - 1); - startIdx = idx + 1; - paragraphs.Add(paragraph); - } - } - } - if (startIdx == 0) //No paragraph breaks given. - return null; - else - { - Paragraph paragraph = new Paragraph(); - paragraph.Format = Format.Clone(); - paragraph.Style = Style; - paragraph.Elements = SubsetElements(startIdx, _elements.Count - 1); - paragraphs.Add(paragraph); - - return paragraphs.ToArray(); - } - } - - /// - /// Gets a subset of the paragraphs elements. - /// - /// Start index of the required subset. - /// End index of the required subset. - /// A ParagraphElements object with cloned elements. - private ParagraphElements SubsetElements(int startIdx, int endIdx) - { - ParagraphElements paragraphElements = new ParagraphElements(); - for (int idx = startIdx; idx <= endIdx; ++idx) - paragraphElements.Add((DocumentObject)_elements[idx].Clone()); - return paragraphElements; - } - static Meta _meta; - #endregion - } + /// + /// Represents a paragraph which is used to build up a document with text. + /// + public class Paragraph : DocumentObject, IVisitable + { + /// + /// Initializes a new instance of the Paragraph class. + /// + public Paragraph() + { } + + /// + /// Initializes a new instance of the Paragraph class with the specified parent. + /// + internal Paragraph(DocumentObject parent) : base(parent) { } + + #region Methods + /// + /// Creates a deep copy of this object. + /// + public new Paragraph Clone() + { + return (Paragraph)DeepCopy(); + } + + /// + /// Implements the deep copy of the object. + /// + protected override object DeepCopy() + { + Paragraph paragraph = (Paragraph)base.DeepCopy(); + if (paragraph._format != null) + { + paragraph._format = paragraph._format.Clone(); + paragraph._format._parent = paragraph; + } + if (paragraph._elements != null) + { + paragraph._elements = paragraph._elements.Clone(); + paragraph._elements._parent = paragraph; + } + return paragraph; + } + + /// + /// Adds a text phrase to the paragraph. + /// + public Text AddText(String text) + { + return Elements.AddText(text); + } + + /// + /// Adds a single character repeated the specified number of times to the paragraph. + /// + public Text AddChar(char ch, int count) + { + return Elements.AddChar(ch, count); + } + + /// + /// Adds a single character to the paragraph. + /// + public Text AddChar(char ch) + { + return Elements.AddChar(ch); + } + + /// + /// Adds one or more Symbol objects. + /// + public Character AddCharacter(SymbolName symbolType, int count) + { + return Elements.AddCharacter(symbolType, count); + } + + /// + /// Adds a Symbol object. + /// + public Character AddCharacter(SymbolName symbolType) + { + return Elements.AddCharacter(symbolType); + } + + /// + /// Adds one or more Symbol objects defined by a character. + /// + public Character AddCharacter(char ch, int count) + { + return Elements.AddCharacter(ch, count); + } + + /// + /// Adds a Symbol object defined by a character. + /// + public Character AddCharacter(char ch) + { + return Elements.AddCharacter(ch); + } + + /// + /// Adds a space character as many as count. + /// + public Character AddSpace(int count) + { + return Elements.AddSpace(count); + } + + /// + /// Adds a horizontal tab. + /// + public void AddTab() + { + Elements.AddTab(); + } + + /// + /// Adds a line break. + /// + public void AddLineBreak() + { + Elements.AddLineBreak(); + } + + /// + /// Adds a new FormattedText. + /// + public FormattedText AddFormattedText() + { + return Elements.AddFormattedText(); + } + + /// + /// Adds a new FormattedText object with the given format. + /// + public FormattedText AddFormattedText(TextFormat textFormat) + { + return Elements.AddFormattedText(textFormat); + } + + /// + /// Adds a new FormattedText with the given Font. + /// + public FormattedText AddFormattedText(Font font) + { + return Elements.AddFormattedText(font); + } + + /// + /// Adds a new FormattedText with the given text. + /// + public FormattedText AddFormattedText(string text) + { + return Elements.AddFormattedText(text); + } + + /// + /// Adds a new FormattedText object with the given text and format. + /// + public FormattedText AddFormattedText(string text, TextFormat textFormat) + { + return Elements.AddFormattedText(text, textFormat); + } + + /// + /// Adds a new FormattedText object with the given text and font. + /// + public FormattedText AddFormattedText(string text, Font font) + { + return Elements.AddFormattedText(text, font); + } + + /// + /// Adds a new FormattedText object with the given text and style. + /// + public FormattedText AddFormattedText(string text, string style) + { + return Elements.AddFormattedText(text, style); + } + + /// + /// Adds a new Hyperlink of Type "Local", + /// i.e. the Target is a Bookmark within the Document + /// + public Hyperlink AddHyperlink(string name) + { + return Elements.AddHyperlink(name); + } + + /// + /// Adds a new Hyperlink + /// + public Hyperlink AddHyperlink(string name, HyperlinkType type) + { + return Elements.AddHyperlink(name, type); + } + + /// + /// Adds a new Bookmark. + /// + public BookmarkField AddBookmark(string name) + { + return Elements.AddBookmark(name); + } + + /// + /// Adds a new PageField. + /// + public PageField AddPageField() + { + return Elements.AddPageField(); + } + + /// + /// Adds a new PageRefField. + /// + public PageRefField AddPageRefField(string name) + { + return Elements.AddPageRefField(name); + } + + /// + /// Adds a new NumPagesField. + /// + public NumPagesField AddNumPagesField() + { + return Elements.AddNumPagesField(); + } + + /// + /// Adds a new SectionField. + /// + public SectionField AddSectionField() + { + return Elements.AddSectionField(); + } + + /// + /// Adds a new SectionPagesField. + /// + public SectionPagesField AddSectionPagesField() + { + return Elements.AddSectionPagesField(); + } + + /// + /// Adds a new DateField. + /// + public DateField AddDateField() + { + return Elements.AddDateField(); + } + + /// + /// Adds a new DateField. + /// + public DateField AddDateField(string format) + { + return Elements.AddDateField(format); + } + + /// + /// Adds a new InfoField. + /// + public InfoField AddInfoField(InfoFieldType iType) + { + return Elements.AddInfoField(iType); + } + + /// + /// Adds a new Footnote with the specified text. + /// + public Footnote AddFootnote(string text) + { + return Elements.AddFootnote(text); + } + + /// + /// Adds a new Footnote. + /// + public Footnote AddFootnote() + { + return Elements.AddFootnote(); + } + + /// + /// Adds a new Image object + /// + public Image AddImage(string fileName) + { + return Elements.AddImage(fileName); + } + + /// + /// Adds a new Bookmark + /// + public void Add(BookmarkField bookmark) + { + Elements.Add(bookmark); + } + + /// + /// Adds a new PageField + /// + public void Add(PageField pageField) + { + Elements.Add(pageField); + } + + /// + /// Adds a new PageRefField + /// + public void Add(PageRefField pageRefField) + { + Elements.Add(pageRefField); + } + + /// + /// Adds a new NumPagesField + /// + public void Add(NumPagesField numPagesField) + { + Elements.Add(numPagesField); + } + + /// + /// Adds a new SectionField + /// + public void Add(SectionField sectionField) + { + Elements.Add(sectionField); + } + + /// + /// Adds a new SectionPagesField + /// + public void Add(SectionPagesField sectionPagesField) + { + Elements.Add(sectionPagesField); + } + + /// + /// Adds a new DateField + /// + public void Add(DateField dateField) + { + Elements.Add(dateField); + } + + /// + /// Adds a new InfoField + /// + public void Add(InfoField infoField) + { + Elements.Add(infoField); + } + + /// + /// Adds a new Footnote + /// + public void Add(Footnote footnote) + { + Elements.Add(footnote); + } + + /// + /// Adds a new Text + /// + public void Add(Text text) + { + Elements.Add(text); + } + + /// + /// Adds a new FormattedText + /// + public void Add(FormattedText formattedText) + { + Elements.Add(formattedText); + } + + /// + /// Adds a new Hyperlink + /// + public void Add(Hyperlink hyperlink) + { + Elements.Add(hyperlink); + } + + /// + /// Adds a new Image + /// + public void Add(Image image) + { + Elements.Add(image); + } + + /// + /// Adds a new Character + /// + public void Add(Character character) + { + Elements.Add(character); + } + #endregion + + #region Properties + /// + /// Gets or sets the style name. + /// + public string Style + { + get { return _style.Value; } + set { _style.Value = value; } + } + [DV] + internal NString _style = NString.NullValue; + + /// + /// Gets or sets the ParagraphFormat object of the paragraph. + /// + public ParagraphFormat Format + { + get { return _format ?? (_format = new ParagraphFormat(this)); } + set + { + SetParent(value); + _format = value; + } + } + [DV] + internal ParagraphFormat _format; + + /// + /// Gets the collection of document objects that defines the paragraph. + /// + public ParagraphElements Elements + { + get { return _elements ?? (_elements = new ParagraphElements(this)); } + set + { + SetParent(value); + _elements = value; + } + } + [DV] + internal ParagraphElements _elements; + + /// + /// Gets or sets a comment associated with this object. + /// + public string Comment + { + get { return _comment.Value; } + set { _comment.Value = value; } + } + [DV] + internal NString _comment = NString.NullValue; + #endregion + + #region Internal + /// + /// Allows the visitor object to visit the document object and its child objects. + /// + void IVisitable.AcceptVisitor(DocumentObjectVisitor visitor, bool visitChildren) + { + visitor.VisitParagraph(this); + + if (visitChildren && _elements != null) + ((IVisitable)_elements).AcceptVisitor(visitor, true); + } + + /// + /// For internal use only. + /// + internal bool SerializeContentOnly + { + get { return _serializeContentOnly; } + set { _serializeContentOnly = value; } + } + bool _serializeContentOnly; + + /// + /// Converts Paragraph into DDL. + /// + internal override void Serialize(Serializer serializer) + { + if (!_serializeContentOnly) + { + serializer.WriteComment(_comment.Value); + serializer.WriteLine("\\paragraph"); + + int pos = serializer.BeginAttributes(); + + if (_style.Value != "") + serializer.WriteLine("Style = \"" + _style.Value + "\""); + + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + serializer.EndAttributes(pos); + + serializer.BeginContent(); + if (!IsNull("Elements")) + Elements.Serialize(serializer); + serializer.CloseUpLine(); + serializer.EndContent(); + } + else + { + Elements.Serialize(serializer); + serializer.CloseUpLine(); + } + } + + internal override void Serialize(XmlSerializer serializer) + { + /* + if (!_serializeContentOnly) + { + */ + + serializer.WriteStartElement("p"); + + serializer.WriteComment(_comment.Value); + //serializer.WriteLine("\\paragraph"); + + if (_style.Value != "") + //serializer.WriteLine("Style = \"" + _style.Value + "\""); + serializer.WriteSimpleAttribute("Style", _style.Value); + + serializer.BeginAttributes(); + if (!IsNull("Format")) + _format.Serialize(serializer, "Format", null); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + if (!IsNull("Elements")) + Elements.Serialize(serializer); + //serializer.CloseUpLine(); + //serializer.EndContent(); + + serializer.WriteEndElement(); // paragraph + /*} + else + { + Elements.Serialize(serializer); + //serializer.CloseUpLine(); + }*/ + } + + /// + /// Returns the meta object of this instance. + /// + internal override Meta Meta + { + get { return _meta ?? (_meta = new Meta(typeof(Paragraph))); } + } + + /// + /// Returns an array of Paragraphs that are separated by parabreaks. Null if no parabreak is found. + /// + internal Paragraph[] SplitOnParaBreak() + { + if (_elements == null) + return null; + + int startIdx = 0; + List paragraphs = new List(); + for (int idx = 0; idx < Elements.Count; ++idx) + { + DocumentObject element = Elements[idx]; + if (element is Character) + { + Character character = (Character)element; + if (character.SymbolName == SymbolName.ParaBreak) + { + Paragraph paragraph = new Paragraph(); + paragraph.Format = Format.Clone(); + paragraph.Style = Style; + paragraph.Elements = SubsetElements(startIdx, idx - 1); + startIdx = idx + 1; + paragraphs.Add(paragraph); + } + } + } + if (startIdx == 0) //No paragraph breaks given. + return null; + else + { + Paragraph paragraph = new Paragraph(); + paragraph.Format = Format.Clone(); + paragraph.Style = Style; + paragraph.Elements = SubsetElements(startIdx, _elements.Count - 1); + paragraphs.Add(paragraph); + + return paragraphs.ToArray(); + } + } + + /// + /// Gets a subset of the paragraphs elements. + /// + /// Start index of the required subset. + /// End index of the required subset. + /// A ParagraphElements object with cloned elements. + private ParagraphElements SubsetElements(int startIdx, int endIdx) + { + ParagraphElements paragraphElements = new ParagraphElements(); + for (int idx = startIdx; idx <= endIdx; ++idx) + paragraphElements.Add((DocumentObject)_elements[idx].Clone()); + return paragraphElements; + } + static Meta _meta; + #endregion + } } diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs index 12a5280..247d64d 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs @@ -444,6 +444,17 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + int count = Count; + for (int index = 0; index < count; ++index) + { + DocumentObject element = this[index]; + element.Serialize(serializer); + } + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphFormat.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphFormat.cs index 3d23766..28aa09d 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphFormat.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphFormat.cs @@ -392,6 +392,15 @@ internal override void Serialize(Serializer serializer) Serialize(serializer, "Format", null); } + internal override void Serialize(XmlSerializer serializer) + { + if (_parent is Style) + Serialize(serializer, "ParagraphFormat", null); + else + Serialize(serializer, "Format", null); + } + + /// /// Converts ParagraphFormat into DDL. /// @@ -466,6 +475,83 @@ internal void Serialize(Serializer serializer, string name, ParagraphFormat refF serializer.EndContent(pos); } + internal void Serialize(XmlSerializer serializer, string name, ParagraphFormat refFormat) + { + serializer.WriteStartElement(name); + + //int pos = serializer.BeginContent(name); + +// if (!IsNull("Font") && Parent.GetType() != typeof(Style)) + //Font.Serialize(serializer); + + // If a refFormat is specified, it is important to compare the fields and not the properties. + // Only the fields holds the internal information whether a value is NULL. In contrast to the + // Efw.Application framework the nullable values and all the meta stuff is kept internal to + // give the user the illusion of simplicity. + + if (!_alignment.IsNull && (refFormat == null || (_alignment != refFormat._alignment))) + serializer.WriteSimpleAttribute("Alignment", Alignment); + + if (!_leftIndent.IsNull && (refFormat == null || (_leftIndent != refFormat._leftIndent))) + serializer.WriteSimpleAttribute("LeftIndent", LeftIndent); + + if (!_firstLineIndent.IsNull && (refFormat == null || _firstLineIndent != refFormat._firstLineIndent)) + serializer.WriteSimpleAttribute("FirstLineIndent", FirstLineIndent); + + if (!_rightIndent.IsNull && (refFormat == null || _rightIndent != refFormat._rightIndent)) + serializer.WriteSimpleAttribute("RightIndent", RightIndent); + + if (!_spaceBefore.IsNull && (refFormat == null || _spaceBefore != refFormat._spaceBefore)) + serializer.WriteSimpleAttribute("SpaceBefore", SpaceBefore); + + if (!_spaceAfter.IsNull && (refFormat == null || _spaceAfter != refFormat._spaceAfter)) + serializer.WriteSimpleAttribute("SpaceAfter", SpaceAfter); + + if (!_lineSpacingRule.IsNull && (refFormat == null || _lineSpacingRule != refFormat._lineSpacingRule)) + serializer.WriteSimpleAttribute("LineSpacingRule", LineSpacingRule); + + if (!_lineSpacing.IsNull && (refFormat == null || _lineSpacing != refFormat._lineSpacing)) + serializer.WriteSimpleAttribute("LineSpacing", LineSpacing); + + if (!_keepTogether.IsNull && (refFormat == null || _keepTogether != refFormat._keepTogether)) + serializer.WriteSimpleAttribute("KeepTogether", KeepTogether); + + if (!_keepWithNext.IsNull && (refFormat == null || _keepWithNext != refFormat._keepWithNext)) + serializer.WriteSimpleAttribute("KeepWithNext", KeepWithNext); + + if (!_widowControl.IsNull && (refFormat == null || _widowControl != refFormat._widowControl)) + serializer.WriteSimpleAttribute("WidowControl", WidowControl); + + if (!_pageBreakBefore.IsNull && (refFormat == null || _pageBreakBefore != refFormat._pageBreakBefore)) + serializer.WriteSimpleAttribute("PageBreakBefore", PageBreakBefore); + + if (!_outlineLevel.IsNull && (refFormat == null || _outlineLevel != refFormat._outlineLevel)) + serializer.WriteSimpleAttribute("OutlineLevel", OutlineLevel); + + if (!IsNull("Font") && Parent.GetType() != typeof(Style)) + Font.Serialize(serializer); + + if (!IsNull("ListInfo")) + ListInfo.Serialize(serializer); + + if (!IsNull("TabStops")) + _tabStops.Serialize(serializer); + + if (!IsNull("Borders")) + { + if (refFormat != null) + _borders.Serialize(serializer, refFormat.Borders); + else + _borders.Serialize(serializer, null); + } + + if (!IsNull("Shading")) + _shading.Serialize(serializer); + + //serializer.EndContent(pos); + serializer.WriteEndElement(); // paragraphFormat + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Section.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Section.cs index 9c302ca..1a0ef69 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Section.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Section.cs @@ -350,6 +350,34 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Section"); + + serializer.WriteComment(_comment.Value); + + serializer.BeginAttributes(); + + if (!IsNull("PageSetup")) + PageSetup.Serialize(serializer); + + serializer.EndAttributes(); + + //serializer.BeginContent(); + if (!IsNull("headers")) + _headers.Serialize(serializer); + if (!IsNull("footers")) + _footers.Serialize(serializer); + if (!IsNull("elements")) + _elements.Serialize(serializer); + + //serializer.EndContent(); + + serializer.WriteEndElement(); // section + + } + + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs index 7c95660..a07af3e 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs @@ -93,6 +93,21 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Sections"); + + int count = Count; + for (int index = 0; index < count; ++index) + { + Section section = this[index]; + section.Serialize(serializer); + } + + serializer.WriteEndElement(); + } + + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Shading.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Shading.cs index da84cd3..ae8c3ce 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Shading.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Shading.cs @@ -123,6 +123,28 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Shading"); + + if (_isCleared) + //serializer.WriteLine("Shading = null"); + serializer.WriteSimpleAttribute("Clear", true); + + //int pos = serializer.BeginContent("Shading"); + + if (!_visible.IsNull) + serializer.WriteSimpleAttribute("Visible", Visible); + + if (!_color.IsNull) + serializer.WriteSimpleAttribute("Color", Color); + + //serializer.EndContent(pos); + serializer.WriteEndElement(); // shading + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs index 2f5821c..e5b4ef2 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs @@ -428,6 +428,120 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(); } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("Style"); + +#if DEBUG_ // Test + if (Name == StyleNames.Heading1 || Name == StyleNames.Heading2) + Name.GetType(); +#endif + + // For build-in styles all properties that differ from their default values + // are serialized. + // For user-defined styles all non-null properties are serialized. + Styles buildInStyles = Styles.BuildInStyles; + Style refStyle = null; + Font refFont = null; + ParagraphFormat refFormat = null; + + serializer.WriteComment(_comment.Value); + if (_buildIn.Value) + { + // BaseStyle is never null, but empty only for "Normal" and "DefaultParagraphFont" + if (BaseStyle == "") + { + // case: style is "Normal" + if (String.Compare(_name.Value, DefaultParagraphName, StringComparison.OrdinalIgnoreCase) != 0) + throw new ArgumentException("Internal Error: BaseStyle not set."); + + refStyle = buildInStyles[buildInStyles.GetIndex(Name)]; + refFormat = refStyle.ParagraphFormat; + refFont = refFormat.Font; + //string name = DdlEncoder.QuoteIfNameContainsBlanks(Name); + //serializer.WriteLineNoCommit(name); + + serializer.WriteSimpleAttribute("Name", Name); + } + else + { + // case: any build-in style except "Normal" + refStyle = buildInStyles[buildInStyles.GetIndex(Name)]; + refFormat = refStyle.ParagraphFormat; + refFont = refFormat.Font; + if (String.Compare(BaseStyle, refStyle.BaseStyle, StringComparison.OrdinalIgnoreCase) == 0) + { + // case: build-in style with unmodified base style name + // string name = DdlEncoder.QuoteIfNameContainsBlanks(Name); + //serializer.WriteLineNoCommit(name); + + serializer.WriteSimpleAttribute("Name", Name); + + // It's fine if we have the predefined base style, but ... + // ... the base style may have been modified or may even have a modified base style. + // Methinks it's wrong to compare with the built-in style, so let's compare with the + // real base style: + refStyle = Document.Styles[Document.Styles.GetIndex(_baseStyle.Value)]; + refFormat = refStyle.ParagraphFormat; + refFont = refFormat.Font; + // Note: we must write "Underline = none" if the base style has "Underline = single" - we cannot + // detect this if we compare with the built-in style that has no underline. + // Known problem: Default values like "OutlineLevel = Level1" will now be serialized + // TODO: optimize... + } + else + { + // case: build-in style with modified base style name + //string name = DdlEncoder.QuoteIfNameContainsBlanks(Name); + //string baseName = DdlEncoder.QuoteIfNameContainsBlanks(BaseStyle); + + //serializer.WriteLine(name + " : " + baseName); + serializer.WriteSimpleAttribute("Name", Name); + serializer.WriteSimpleAttribute("BaseStyle", BaseStyle); + + refStyle = Document.Styles[Document.Styles.GetIndex(_baseStyle.Value)]; + refFormat = refStyle.ParagraphFormat; + refFont = refFormat.Font; + } + } + } + else + { + // case: user-defined style; base style always exists + + //string name = DdlEncoder.QuoteIfNameContainsBlanks(Name); + //string baseName = DdlEncoder.QuoteIfNameContainsBlanks(BaseStyle); + //serializer.WriteLine(name + " : " + baseName); + serializer.WriteSimpleAttribute("Name", Name); + serializer.WriteSimpleAttribute("BaseStyle", BaseStyle); + + +#if true + Style refStyle0 = Document.Styles[Document.Styles.GetIndex(_baseStyle.Value)]; + refStyle = Document.Styles[_baseStyle.Value]; + refFormat = refStyle != null ? refStyle.ParagraphFormat : null; +#else + refFormat = null; +#endif + } + + //serializer.BeginContent(); + + if (!IsNull("ParagraphFormat")) + { + if (!ParagraphFormat.IsNull("Font")) + Font.Serialize(serializer, refFormat != null ? refFormat.Font : null); + + if (Type == StyleType.Paragraph) + ParagraphFormat.Serialize(serializer, "ParagraphFormat", refFormat); + } + + //serializer.EndContent(); + serializer.WriteEndElement(); // style + + } + /// /// Sets all properties to Null that have the same value as the base style. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs index b8d965d..79b398d 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs @@ -362,6 +362,43 @@ internal override void Serialize(Serializer serializer) serializer.EndContent(pos); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("Styles"); + + serializer.WriteComment(_comment.Value); + + //int pos = serializer.BeginContent("\\styles"); + + //int pos = serializer.BeginContent("styles"); + + // A style can only be added to Styles if its base style exists. Therefore the + // styles collection is consistent at any one time by definition. But because it + // is possible to change the base style of a style, the sequence of the styles + // in the styles collection can be in an order that a style comes before its base + // style. The styles in an DDL file must be ordered such that each style appears + // after its base style. We cannot simply reorder the styles collection, because + // the predefined styles are expected at a fixed position. + // The solution is to reorder the styles during serialization. + int count = Count; + bool[] fSerialized = new bool[count]; // already serialized + fSerialized[0] = true; // consider DefaultParagraphFont as serialized + bool[] fSerializePending = new bool[count]; // currently serializing + bool newLine = false; // gets true if at least one style was written + //Start from 1 and do not serialize DefaultParagraphFont + for (int index = 1; index < count; index++) + { + if (!fSerialized[index]) + { + Style style = this[index]; + SerializeStyle(serializer, index, ref fSerialized, ref fSerializePending, ref newLine); + } + } + + //serializer.EndContent(pos); + serializer.WriteEndElement(); + } + /// /// Serialize a style, but serialize its base style first (if that was not yet done). /// @@ -405,6 +442,48 @@ void SerializeStyle(Serializer serializer, int index, ref bool[] fSerialized, re fSerialized[index] = true; } + void SerializeStyle(XmlSerializer serializer, int index, ref bool[] fSerialized, ref bool[] fSerializePending, + ref bool newLine) + { + Style style = this[index]; + + // It is not possible to modify the default paragraph font + if (style.Name == Style.DefaultParagraphFontName) + return; + + // Circular dependencies cannot occur if changing the base style is implemented + // correctly. But before we proof that, we check it here. + if (fSerializePending[index]) + { + string message = String.Format("Circular dependency detected according to style '{0}'.", style.Name); + throw new InvalidOperationException(message); + } + + // Only style 'Normal' has no base style + if (style.BaseStyle != "") + { + int idxBaseStyle = GetIndex(style.BaseStyle); + if (idxBaseStyle != -1) + { + if (!fSerialized[idxBaseStyle]) + { + fSerializePending[index] = true; + SerializeStyle(serializer, idxBaseStyle, ref fSerialized, ref fSerializePending, ref newLine); + fSerializePending[index] = false; + } + } + } + //int pos2 = serializer.BeginBlock(); + + // TODo + //if (newLine) + //serializer.WriteLineNoCommit(); + style.Serialize(serializer); + //if (serializer.EndBlock(pos2)) + // newLine = true; + fSerialized[index] = true; + } + /// /// Allows the visitor object to visit the document object and its child objects. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStop.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStop.cs index 1e07465..54076a8 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStop.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStop.cs @@ -130,6 +130,34 @@ internal override void Serialize(Serializer serializer) serializer.WriteLine("TabStops -= \"" + Position + "\""); } + internal override void Serialize(XmlSerializer serializer) + { + serializer.WriteStartElement("TabStop"); + + if (AddTab) + { + //serializer.WriteLine("TabStops +="); + serializer.WriteSimpleAttribute("Add", true); + + //serializer.BeginContent(); + serializer.WriteSimpleAttribute("Position", Position); + if (!_alignment.IsNull) + serializer.WriteSimpleAttribute("Alignment", Alignment); + if (!_leader.IsNull) + serializer.WriteSimpleAttribute("Leader", Leader); + //serializer.EndContent(); + } + else + { + serializer.WriteSimpleAttribute("Remove", true); + //serializer.WriteLine("TabStops -= \"" + Position + "\""); + serializer.WriteSimpleAttribute("Position", Position); + } + + serializer.WriteEndElement(); // tabstop + } + + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs index 2bd01c7..c81f4d4 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs @@ -223,6 +223,25 @@ internal override void Serialize(Serializer serializer) } } + internal override void Serialize(XmlSerializer serializer) + { + + serializer.WriteStartElement("TabStops"); + + if (_fClearAll) + //serializer.WriteLine("TabStops = null"); + serializer.WriteSimpleAttribute("Clear", true); + + int count = Count; + for (int index = 0; index < count; index++) + { + TabStop tabstop = this[index]; + tabstop.Serialize(serializer); + } + + serializer.WriteEndElement(); + } + /// /// Determines whether this instance is null (not set). /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Text.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Text.cs index ad805cd..50a16f7 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Text.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Text.cs @@ -89,6 +89,18 @@ internal override void Serialize(Serializer serializer) serializer.Write(text); } + internal override void Serialize(XmlSerializer serializer) + { + //string text = DdlEncoder.StringToText(_content.Value); + // To make DDL more readable write soft hypens as keywords. + //text = text.Replace(new string((char)173, 1), "\\-"); + //serializer.Write(text); + + //serializer.WriteStartElement("Content"); + serializer.WriteContent(_content.Value); + //serializer.WriteEndElement(); + } + /// /// Returns the meta object of this instance. /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs new file mode 100644 index 0000000..c19b281 --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs @@ -0,0 +1,709 @@ +#region MigraDoc - Creating Documents on the Fly +// +// Authors: +// Stefan Lange +// Klaus Potzesny +// David Stephensen +// +// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany) +// +// http://www.pdfsharp.com +// http://www.migradoc.com +// http://sourceforge.net/projects/pdfsharp +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Xml; +using MigraDoc.DocumentObjectModel.Internals; + +namespace MigraDoc.DocumentObjectModel +{ + /// + /// Object to be passed to the Serialize function of a DocumentObject to convert + /// it into DDL. + /// + internal sealed class XmlSerializer + { + /// + /// A Serializer object for converting MDDOM into DDL. + /// + /// A TextWriter to write DDL in. + /// Indent of a new block. Default is 2. + /// Initial indent to start with. + internal XmlSerializer(TextWriter textWriter, int indent, int initialIndent) + { + if (textWriter == null) + throw new ArgumentNullException("textWriter"); + + _textWriter = textWriter; + _indent = indent; + _writeIndent = initialIndent; + + _xmlWriter = XmlWriter.Create(_textWriter, new XmlWriterSettings() { Encoding = Encoding.UTF8 }); + + // todo + //if (textWriter is StreamWriter) + // WriteStamp(); + } + + /// + /// Initializes a new instance of the Serializer class with the specified TextWriter. + /// + internal XmlSerializer(TextWriter textWriter) : this(textWriter, 2, 0) { } + + /// + /// Initializes a new instance of the Serializer class with the specified TextWriter and indentation. + /// + internal XmlSerializer(TextWriter textWriter, int indent) : this(textWriter, indent, 0) { } + + readonly TextWriter _textWriter; + + /// + /// Gets or sets the indentation for a new indentation level. + /// + internal int Indent + { + get { return _indent; } + set { _indent = value; } + } + int _indent = 2; + + /// + /// Gets or sets the initial indentation which precede every line. + /// + internal int InitialIndent + { + get { return _writeIndent; } + set { _writeIndent = value; } + } + int _writeIndent; + + /// + /// Increases indent of DDL code. + /// + void IncreaseIndent() + { + _writeIndent += _indent; + } + + /// + /// Decreases indent of DDL code. + /// + void DecreaseIndent() + { + _writeIndent -= _indent; + } + + /// + /// Writes the header for a DDL file containing copyright and creation time information. + /// + internal void WriteStamp() + { + if (_fWriteStamp) + { + WriteComment("Created by empira MigraDoc Document Object Model"); + WriteComment(String.Format("generated file created {0:d} at {0:t}", DateTime.Now)); + } + } + + /// + /// Appends a string indented without line feed. + /// + /*internal void Write(string str) + { + string wrappedStr = DoWordWrap(str); + if (wrappedStr.Length < str.Length && wrappedStr != "") + { + WriteLineToStream(wrappedStr); + Write(str.Substring(wrappedStr.Length)); + } + else + WriteToStream(str); + CommitText(); + }*/ + + /// + /// Writes a string indented with line feed. + /// + /*internal void WriteLine(string str) + { + string wrappedStr = DoWordWrap(str); + if (wrappedStr.Length < str.Length) + { + WriteLineToStream(wrappedStr); + WriteLine(str.Substring(wrappedStr.Length)); + } + else + WriteLineToStream(wrappedStr); + CommitText(); + }*/ + + /// + /// Returns the part of the string str that fits into the line (up to 80 chars). + /// If Wordwrap is impossible it returns the input-string str itself. + /// + /*string DoWordWrap(string str) + { + if (str.Length + _writeIndent < LineBreakBeyond) + return str; + + int idxCRLF = str.IndexOf("\x0D\x0A", StringComparison.Ordinal); + if (idxCRLF > 0 && idxCRLF + _writeIndent <= LineBreakBeyond) + return str.Substring(0, idxCRLF + 1); + + int splitIndexBlank = str.Substring(0, LineBreakBeyond - _writeIndent).LastIndexOf(" ", StringComparison.Ordinal); + int splitIndexCRLF = str.Substring(0, LineBreakBeyond - _writeIndent).LastIndexOf("\x0D\x0A", StringComparison.Ordinal); + int splitIndex = Math.Max(splitIndexBlank, splitIndexCRLF); + if (splitIndex == -1) + splitIndex = Math.Min(str.IndexOf(" ", LineBreakBeyond - _writeIndent + 1, StringComparison.Ordinal), + str.IndexOf("\x0D\x0A", LineBreakBeyond - _writeIndent + 1, StringComparison.Ordinal)); + return splitIndex > 0 ? str.Substring(0, splitIndex) : str; + + }*/ + + /// + /// Writes an empty line. + /// + /*internal void WriteLine() + { + WriteLine(String.Empty); + }*/ + + /// + /// Write a line without committing (without marking the text as serialized). + /// + /*internal void WriteLineNoCommit(string str) + { + WriteLineToStream(str); + }*/ + + /// + /// Write a line without committing (without marking the text as serialized). + /// + /*internal void WriteLineNoCommit() + { + WriteLineNoCommit(String.Empty); + }*/ + + /// + /// Writes a text as comment and automatically word-wraps it. + /// + /*internal void WriteComment(string comment) + { + if (String.IsNullOrEmpty(comment)) + return; + + // if string contains CR/LF, split up recursively + int crlf = comment.IndexOf("\x0D\x0A", StringComparison.Ordinal); + if (crlf != -1) + { + WriteComment(comment.Substring(0, crlf)); + WriteComment(comment.Substring(crlf + 2)); + return; + } + CloseUpLine(); + int len; + int chopBeyond = LineBreakBeyond - _indent - "// ".Length; + while ((len = comment.Length) > 0) + { + string wrt; + if (len <= chopBeyond) + { + wrt = "// " + comment; + comment = String.Empty; + } + else + { + int idxChop; + if ((idxChop = comment.LastIndexOf(' ', chopBeyond)) == -1 && + (idxChop = comment.IndexOf(' ', chopBeyond)) == -1) + { + wrt = "// " + comment; + comment = String.Empty; + } + else + { + wrt = "// " + comment.Substring(0, idxChop); + comment = comment.Substring(idxChop + 1); + } + } + WriteLineToStream(wrt); + CommitText(); + } + }*/ + + + internal void WriteComment(string comment) + { + if (String.IsNullOrEmpty(comment)) + return; + + WriteSimpleAttribute("Comment", comment); + } + + + /// + /// Writes a line break if the current position is not at the beginning + /// of a new line. + /// + /*internal void CloseUpLine() + { + if (_linePos > 0) + WriteLine(); + }*/ + + /// + /// Effectively writes text to the stream. The text is automatically indented and + /// word-wrapped. A given text gets never word-wrapped to keep comments or string + /// literals unbroken. + /// + /*void WriteToStream(string text, bool fLineBreak, bool fAutoIndent) + { + // if string contains CR/LF, split up recursively + int crlf = text.IndexOf("\x0D\x0A", StringComparison.Ordinal); + if (crlf != -1) + { + WriteToStream(text.Substring(0, crlf), true, fAutoIndent); + WriteToStream(text.Substring(crlf + 2), fLineBreak, fAutoIndent); + return; + } + + int len = text.Length; + if (len > 0) + { + if (_linePos > 0) + { + // does not work + // if (IsBlankRequired(this .lastChar, _text[0])) + // _text = "·" + _text; + } + else + { + if (fAutoIndent) + { + text = Indentation + text; + len += _writeIndent; + } + } + _textWriter.Write(text); + _linePos += len; + // wordwrap required? + if (_linePos > LineBreakBeyond) + { + fLineBreak = true; + //this .textWriter.Write("//¶"); // for debugging only + } + else + _lastChar = text[len - 1]; + } + + if (fLineBreak) + { + _textWriter.WriteLine(String.Empty); // what a line break is may depend on encoding + _linePos = 0; + _lastChar = '\x0A'; + } + }*/ + + /// + /// Write the text into the stream without breaking it and adds an indentation to it. + /// + /*void WriteToStream(string text) + { + WriteToStream(text, false, true); + }*/ + + /// + /// Write a line to the stream. + /// + /*void WriteLineToStream(string text) + { + WriteToStream(text, true, true); + }*/ + + ///// + ///// Mighty function to figure out if a blank is required as separator. + ///// // Does not work without context... + ///// + //bool IsBlankRequired(char left, char right) + //{ + // if (left == ' ' || right == ' ') + // return false; + + // // 1st try + // bool leftLetterOrDigit = Char.IsLetterOrDigit(left); + // bool rightLetterOrDigit = Char.IsLetterOrDigit(right); + + // if (leftLetterOrDigit && rightLetterOrDigit) + // return true; + + // return false; + //} + + /// + /// Start attribute part. + /// + /*internal int BeginAttributes() + { + int pos = Position; + WriteLineNoCommit("["); + IncreaseIndent(); + BeginBlock(); + return pos; + + }*/ + + /// + /// Start attribute part. + /// + /*internal int BeginAttributes(string str) + { + int pos = Position; + WriteLineNoCommit(str); + WriteLineNoCommit("["); + IncreaseIndent(); + BeginBlock(); + return pos; + }*/ + + + + /// + /// End attribute part. + /// + /*internal bool EndAttributes() + { + DecreaseIndent(); + WriteLineNoCommit("]"); + return EndBlock(); + + }*/ + + /// + /// End attribute part. + /// + /*internal bool EndAttributes(int pos) + { + bool commit = EndAttributes(); + if (!commit) + Position = pos; + return commit; + }*/ + + /// + /// Write attribute of type Unit, Color, int, float, double, bool, string or enum. + /// + internal void WriteSimpleAttribute(string valueName, object value) + { + INullableValue ival = value as INullableValue; + if (ival != null) + value = ival.GetValue(); + + Type type = value.GetType(); + + if (type == typeof(Unit)) + { + string strUnit = value.ToString(); + if (((Unit)value).Type == UnitType.Point) + //WriteLine(valueName + " = " + strUnit); + _xmlWriter.WriteAttributeString(valueName, strUnit); + else + //WriteLine(valueName + " = \"" + strUnit + "\""); + _xmlWriter.WriteAttributeString(valueName, strUnit); + } + else if (type == typeof(float)) + { + //WriteLine(valueName + " = " + ((float)value).ToString(CultureInfo.InvariantCulture)); + _xmlWriter.WriteAttributeString(valueName, ((float)value).ToString(CultureInfo.InvariantCulture)); + } + else if (type == typeof(double)) + { + //WriteLine(valueName + " = " + ((double)value).ToString(CultureInfo.InvariantCulture)); + _xmlWriter.WriteAttributeString(valueName, ((double)value).ToString(CultureInfo.InvariantCulture)); + } + else if (type == typeof(bool)) + { + //WriteLine(valueName + " = " + value.ToString().ToLower()); + _xmlWriter.WriteAttributeString(valueName, value.ToString().ToLower()); + } + else if (type == typeof(string)) + { + //StringBuilder sb = new StringBuilder(value.ToString()); + + //sb.Replace("\\", "\\\\"); + //sb.Replace("\"", "\\\""); + //WriteLine(valueName + " = \"" + sb + "\""); + _xmlWriter.WriteAttributeString(valueName, value.ToString()); + } +#if !NETFX_CORE + else if (type == typeof(int) || type.BaseType == typeof(Enum) || type == typeof(Color)) +#else + else if (type == typeof(int) || type.GetTypeInfo().BaseType == typeof(Enum) || type == typeof(Color)) +#endif + { + //WriteLine(valueName + " = " + value); + _xmlWriter.WriteAttributeString(valueName, value.ToString()); + } + else + { + string message = String.Format("Type '{0}' of value '{1}' not supported", type, valueName); + Debug.Assert(false, message); + } + } + + /// + /// Start content part. + /// + /*internal int BeginContent() + { + int pos = Position; + WriteLineNoCommit("{"); + IncreaseIndent(); + BeginBlock(); + return pos; + + }*/ + + /// + /// Start content part. + /// + /*internal int BeginContent(string str) + { + int pos = Position; + WriteLineNoCommit(str); + WriteLineNoCommit("{"); + IncreaseIndent(); + BeginBlock(); + return pos; + }*/ + + /// + /// End content part. + /// + /*internal bool EndContent() + { + DecreaseIndent(); + WriteLineNoCommit("}"); + return EndBlock(); + }*/ + + /// + /// End content part. + /// + /*internal bool EndContent(int pos) + { + bool commit = __EndContent(); + if (!commit) + Position = pos; + return commit; + }*/ + + /// + /// Starts a new nesting block. + /// + /*internal int BeginBlock() + { + int pos = Position; + if (_stackIdx + 1 >= _commitTextStack.Length) + throw new ArgumentException("Block nesting level exhausted."); + _stackIdx += 1; + _commitTextStack[_stackIdx] = false; + return pos; + }*/ + + /// + /// Ends a nesting block. + /// + /*internal bool EndBlock() + { + if (_stackIdx <= 0) + throw new ArgumentException("Block nesting level underflow."); + _stackIdx -= 1; + if (_commitTextStack[_stackIdx + 1]) + _commitTextStack[_stackIdx] = _commitTextStack[_stackIdx + 1]; + return _commitTextStack[_stackIdx + 1]; + }*/ + + /// + /// Ends a nesting block. + /// + /*internal bool EndBlock(int pos) + { + bool commit = __EndBlock(); + if (!commit) + Position = pos; + return commit; + }*/ + + /// + /// Gets or sets the position within the underlying stream. + /// + /*int Position + { + get + { + _textWriter.Flush(); + StreamWriter streamWriter = _textWriter as StreamWriter; + if (streamWriter != null) + return (int)streamWriter.BaseStream.Position; + + StringWriter stringWriter = _textWriter as StringWriter; + if (stringWriter != null) + return stringWriter.GetStringBuilder().Length; + + return 0; + } + set + { + _textWriter.Flush(); + StreamWriter streamWriter = _textWriter as StreamWriter; + if (streamWriter != null) + streamWriter.BaseStream.SetLength(value); + else + { + StringWriter stringWriter = _textWriter as StringWriter; + if (stringWriter != null) + stringWriter.GetStringBuilder().Length = value; + } + } + }*/ + + /// + /// Flushes the buffers of the underlying text writer. + /// + internal void Flush() + { + //_textWriter.Flush(); + _xmlWriter.Flush(); + } + + /// + /// Returns an indent string of blanks. + /// + static string Ind(int indent) + { + return new String(' ', indent); + } + + /// + /// Gets an indent string of current indent. + /// + /*string Indentation + { + get { return Ind(_writeIndent); } + }*/ + + /// + /// Marks the current block as 'committed'. That means the block contains + /// serialized data. + /// + /*private void CommitText() + { + _commitTextStack[_stackIdx] = true; + } + int _stackIdx; + readonly bool[] _commitTextStack = new bool[32]; + + //int _linePos; + const int LineBreakBeyond = 200; + //char _lastChar; + */ + + bool _fWriteStamp = false; + + /* XML */ + + readonly XmlWriter _xmlWriter; + + /* TextWriter tw=null; + XmlWriter xw = XmlWriter.Create(tw, new XmlWriterSettings()); + + xw.WriteAttributeString("",""); + xw.WriteStartElement(""); + xw.WriteEndElement(); + xw.Close(); +*/ + + + internal void WriteStartDocument() + { + _xmlWriter.WriteStartDocument(); + } + + internal void WriteEndDocument() + { + _xmlWriter.WriteEndDocument(); + + // todo force close + _xmlWriter.Close(); + } + + internal void WriteStartElement(string name) + { + _xmlWriter.WriteStartElement(name); + } + + internal void WriteEndElement() + { + _xmlWriter.WriteEndElement(); + } + + internal void WriteElement(string name, string value) + { + _xmlWriter.WriteStartElement(name); + _xmlWriter.WriteValue(value); + _xmlWriter.WriteEndElement(); + } + + internal void WriteElement(string name) + { + _xmlWriter.WriteStartElement(name); + _xmlWriter.WriteEndElement(); + } + + internal void WriteValue(string value) + { + _xmlWriter.WriteValue(value); + } + + internal void WriteContent(string value) + { + // TODO + //_xmlWriter.WriteCData(value); + _xmlWriter.WriteString(value); + + } + + internal void BeginAttributes() + { + _xmlWriter.WriteStartElement("Attributes"); + } + internal void EndAttributes() + { + _xmlWriter.WriteEndElement(); + } + + } +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/SerializationFormat.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/SerializationFormat.cs new file mode 100644 index 0000000..2c2abd3 --- /dev/null +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/SerializationFormat.cs @@ -0,0 +1,45 @@ +#region MigraDoc - Creating Documents on the Fly +// +// Authors: +// Stefan Lange +// Klaus Potzesny +// David Stephensen +// +// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany) +// +// http://www.pdfsharp.com +// http://www.migradoc.com +// http://sourceforge.net/projects/pdfsharp +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#pragma warning disable 1591 + +namespace MigraDoc.DocumentObjectModel +{ + /// + /// Specifies the serialization format of the document + /// + public enum SerializationFormat + { + DDL, + XML + } +} diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj b/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj index 5e73ffd..760893b 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj @@ -64,6 +64,12 @@ + + + + + + @@ -175,6 +181,7 @@ + @@ -192,6 +199,7 @@ + From 6a7ce05675a2062eb1fa583aa2c144e02e12b88f Mon Sep 17 00:00:00 2001 From: emazv72 Date: Tue, 20 Nov 2018 10:09:14 +0100 Subject: [PATCH 02/25] Update README.md --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 46f5079..bcacd7d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,31 @@ + +# XML based alternative serialization support + +This version add support to an alternative format for serialization based on XML. + +It can be used like this: + + MigraDoc.DocumentObjectModel.IO.Xml.DdlWriter.WriteToFile(document, "MigraDoc.xml"); + + using (StreamReader sr = File.OpenText("MigraDoc.xml")) + { + var errors = new MigraDoc.DocumentObjectModel.IO.DdlReaderErrors(); + var reader = new MigraDoc.DocumentObjectModel.IO.Xml.DdlReader(sr, errors); + + document = reader.ReadDocument(); + + using (StreamWriter sw = new StreamWriter("MigraDoc.xml.errors")) + { + foreach (MigraDoc.DocumentObjectModel.IO.DdlReaderError error in errors) + { + sw.WriteLine("{0}:{1} {2} {3}", error.SourceLine, error.SourceColumn, error.ErrorLevel, error.ErrorMessage); + + } + + } + + } + # MigraDoc MigraDoc Foundation - Creating documents on the fly From 48d727789e3e0813654351b7c3aee005954a4eba Mon Sep 17 00:00:00 2001 From: emazv72 Date: Thu, 22 Nov 2018 09:27:09 +0100 Subject: [PATCH 03/25] Comment fix for release build --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 52 +-- .../DocumentObjectModel/XmlSerializer.cs | 424 +----------------- 2 files changed, 7 insertions(+), 469 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index 25740ca..6968279 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -79,7 +79,7 @@ internal DdlParser(string fileName, string ddl, DdlReaderErrors errors) } /// - /// Parses the keyword «». + /// Parses the keyword «document». /// internal Document ParseDocument(Document document) { @@ -383,47 +383,7 @@ private void ParseHeaderFooter(Section section) } } - // TODO - - /// - /// Determines whether the next text is paragraph content or document element. - /// - /*private bool IsParagraphContent() - { - - if (MoveToParagraphContent()) - { - if (_scanner.Char == Chars.BackSlash) - { - XmlSymbol symbol = _scanner.PeekKeyword(); - switch (symbol) - { - case XmlSymbol.Bold: - case XmlSymbol.Italic: - case XmlSymbol.Underline: - case XmlSymbol.Field: - case XmlSymbol.Font: - case XmlSymbol.FontColor: - case XmlSymbol.FontSize: - case XmlSymbol.Footnote: - case XmlSymbol.Hyperlink: - case XmlSymbol.Symbol: - case XmlSymbol.Chr: - case XmlSymbol.Tab: - case XmlSymbol.LineBreak: - case XmlSymbol.Space: - case XmlSymbol.SoftHyphen: - return true; - } - return false; - } - return true; - } - return false; - - - - }*/ + /// /// Parses the document elements of a «\paragraph», «\cell» or comparable. @@ -701,7 +661,7 @@ private void ParseBoldItalicEtc(FormattedText formattedText, XmlSymbol symbol) AssertSymbol(symbol); if (IsStartElement()) - { + { ParseFormattedText(formattedText.Elements); AssertSymbol(symbol, true); @@ -722,7 +682,7 @@ private void ParseFont(FormattedText formattedText) ParseAttributes(formattedText, null, false); if (hasContent) - { + { ParseFormattedText(formattedText.Elements); AssertSymbol(XmlSymbol.Font, true); @@ -730,7 +690,7 @@ private void ParseFont(FormattedText formattedText) MoveNext(false); } - + /// /// Parses the keyword «\fontsize». /// @@ -935,7 +895,7 @@ private void ParseSpace(ParagraphElements elements) if (count != null) space.Count = Int32.Parse(count); - MoveNext(); + MoveNext(false); } diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs index c19b281..0f168d7 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/XmlSerializer.cs @@ -128,132 +128,6 @@ internal void WriteStamp() } } - /// - /// Appends a string indented without line feed. - /// - /*internal void Write(string str) - { - string wrappedStr = DoWordWrap(str); - if (wrappedStr.Length < str.Length && wrappedStr != "") - { - WriteLineToStream(wrappedStr); - Write(str.Substring(wrappedStr.Length)); - } - else - WriteToStream(str); - CommitText(); - }*/ - - /// - /// Writes a string indented with line feed. - /// - /*internal void WriteLine(string str) - { - string wrappedStr = DoWordWrap(str); - if (wrappedStr.Length < str.Length) - { - WriteLineToStream(wrappedStr); - WriteLine(str.Substring(wrappedStr.Length)); - } - else - WriteLineToStream(wrappedStr); - CommitText(); - }*/ - - /// - /// Returns the part of the string str that fits into the line (up to 80 chars). - /// If Wordwrap is impossible it returns the input-string str itself. - /// - /*string DoWordWrap(string str) - { - if (str.Length + _writeIndent < LineBreakBeyond) - return str; - - int idxCRLF = str.IndexOf("\x0D\x0A", StringComparison.Ordinal); - if (idxCRLF > 0 && idxCRLF + _writeIndent <= LineBreakBeyond) - return str.Substring(0, idxCRLF + 1); - - int splitIndexBlank = str.Substring(0, LineBreakBeyond - _writeIndent).LastIndexOf(" ", StringComparison.Ordinal); - int splitIndexCRLF = str.Substring(0, LineBreakBeyond - _writeIndent).LastIndexOf("\x0D\x0A", StringComparison.Ordinal); - int splitIndex = Math.Max(splitIndexBlank, splitIndexCRLF); - if (splitIndex == -1) - splitIndex = Math.Min(str.IndexOf(" ", LineBreakBeyond - _writeIndent + 1, StringComparison.Ordinal), - str.IndexOf("\x0D\x0A", LineBreakBeyond - _writeIndent + 1, StringComparison.Ordinal)); - return splitIndex > 0 ? str.Substring(0, splitIndex) : str; - - }*/ - - /// - /// Writes an empty line. - /// - /*internal void WriteLine() - { - WriteLine(String.Empty); - }*/ - - /// - /// Write a line without committing (without marking the text as serialized). - /// - /*internal void WriteLineNoCommit(string str) - { - WriteLineToStream(str); - }*/ - - /// - /// Write a line without committing (without marking the text as serialized). - /// - /*internal void WriteLineNoCommit() - { - WriteLineNoCommit(String.Empty); - }*/ - - /// - /// Writes a text as comment and automatically word-wraps it. - /// - /*internal void WriteComment(string comment) - { - if (String.IsNullOrEmpty(comment)) - return; - - // if string contains CR/LF, split up recursively - int crlf = comment.IndexOf("\x0D\x0A", StringComparison.Ordinal); - if (crlf != -1) - { - WriteComment(comment.Substring(0, crlf)); - WriteComment(comment.Substring(crlf + 2)); - return; - } - CloseUpLine(); - int len; - int chopBeyond = LineBreakBeyond - _indent - "// ".Length; - while ((len = comment.Length) > 0) - { - string wrt; - if (len <= chopBeyond) - { - wrt = "// " + comment; - comment = String.Empty; - } - else - { - int idxChop; - if ((idxChop = comment.LastIndexOf(' ', chopBeyond)) == -1 && - (idxChop = comment.IndexOf(' ', chopBeyond)) == -1) - { - wrt = "// " + comment; - comment = String.Empty; - } - else - { - wrt = "// " + comment.Substring(0, idxChop); - comment = comment.Substring(idxChop + 1); - } - } - WriteLineToStream(wrt); - CommitText(); - } - }*/ - internal void WriteComment(string comment) { @@ -264,153 +138,6 @@ internal void WriteComment(string comment) } - /// - /// Writes a line break if the current position is not at the beginning - /// of a new line. - /// - /*internal void CloseUpLine() - { - if (_linePos > 0) - WriteLine(); - }*/ - - /// - /// Effectively writes text to the stream. The text is automatically indented and - /// word-wrapped. A given text gets never word-wrapped to keep comments or string - /// literals unbroken. - /// - /*void WriteToStream(string text, bool fLineBreak, bool fAutoIndent) - { - // if string contains CR/LF, split up recursively - int crlf = text.IndexOf("\x0D\x0A", StringComparison.Ordinal); - if (crlf != -1) - { - WriteToStream(text.Substring(0, crlf), true, fAutoIndent); - WriteToStream(text.Substring(crlf + 2), fLineBreak, fAutoIndent); - return; - } - - int len = text.Length; - if (len > 0) - { - if (_linePos > 0) - { - // does not work - // if (IsBlankRequired(this .lastChar, _text[0])) - // _text = "·" + _text; - } - else - { - if (fAutoIndent) - { - text = Indentation + text; - len += _writeIndent; - } - } - _textWriter.Write(text); - _linePos += len; - // wordwrap required? - if (_linePos > LineBreakBeyond) - { - fLineBreak = true; - //this .textWriter.Write("//¶"); // for debugging only - } - else - _lastChar = text[len - 1]; - } - - if (fLineBreak) - { - _textWriter.WriteLine(String.Empty); // what a line break is may depend on encoding - _linePos = 0; - _lastChar = '\x0A'; - } - }*/ - - /// - /// Write the text into the stream without breaking it and adds an indentation to it. - /// - /*void WriteToStream(string text) - { - WriteToStream(text, false, true); - }*/ - - /// - /// Write a line to the stream. - /// - /*void WriteLineToStream(string text) - { - WriteToStream(text, true, true); - }*/ - - ///// - ///// Mighty function to figure out if a blank is required as separator. - ///// // Does not work without context... - ///// - //bool IsBlankRequired(char left, char right) - //{ - // if (left == ' ' || right == ' ') - // return false; - - // // 1st try - // bool leftLetterOrDigit = Char.IsLetterOrDigit(left); - // bool rightLetterOrDigit = Char.IsLetterOrDigit(right); - - // if (leftLetterOrDigit && rightLetterOrDigit) - // return true; - - // return false; - //} - - /// - /// Start attribute part. - /// - /*internal int BeginAttributes() - { - int pos = Position; - WriteLineNoCommit("["); - IncreaseIndent(); - BeginBlock(); - return pos; - - }*/ - - /// - /// Start attribute part. - /// - /*internal int BeginAttributes(string str) - { - int pos = Position; - WriteLineNoCommit(str); - WriteLineNoCommit("["); - IncreaseIndent(); - BeginBlock(); - return pos; - }*/ - - - - /// - /// End attribute part. - /// - /*internal bool EndAttributes() - { - DecreaseIndent(); - WriteLineNoCommit("]"); - return EndBlock(); - - }*/ - - /// - /// End attribute part. - /// - /*internal bool EndAttributes(int pos) - { - bool commit = EndAttributes(); - if (!commit) - Position = pos; - return commit; - }*/ /// /// Write attribute of type Unit, Color, int, float, double, bool, string or enum. @@ -473,122 +200,6 @@ internal void WriteSimpleAttribute(string valueName, object value) } } - /// - /// Start content part. - /// - /*internal int BeginContent() - { - int pos = Position; - WriteLineNoCommit("{"); - IncreaseIndent(); - BeginBlock(); - return pos; - - }*/ - - /// - /// Start content part. - /// - /*internal int BeginContent(string str) - { - int pos = Position; - WriteLineNoCommit(str); - WriteLineNoCommit("{"); - IncreaseIndent(); - BeginBlock(); - return pos; - }*/ - - /// - /// End content part. - /// - /*internal bool EndContent() - { - DecreaseIndent(); - WriteLineNoCommit("}"); - return EndBlock(); - }*/ - - /// - /// End content part. - /// - /*internal bool EndContent(int pos) - { - bool commit = __EndContent(); - if (!commit) - Position = pos; - return commit; - }*/ - - /// - /// Starts a new nesting block. - /// - /*internal int BeginBlock() - { - int pos = Position; - if (_stackIdx + 1 >= _commitTextStack.Length) - throw new ArgumentException("Block nesting level exhausted."); - _stackIdx += 1; - _commitTextStack[_stackIdx] = false; - return pos; - }*/ - - /// - /// Ends a nesting block. - /// - /*internal bool EndBlock() - { - if (_stackIdx <= 0) - throw new ArgumentException("Block nesting level underflow."); - _stackIdx -= 1; - if (_commitTextStack[_stackIdx + 1]) - _commitTextStack[_stackIdx] = _commitTextStack[_stackIdx + 1]; - return _commitTextStack[_stackIdx + 1]; - }*/ - - /// - /// Ends a nesting block. - /// - /*internal bool EndBlock(int pos) - { - bool commit = __EndBlock(); - if (!commit) - Position = pos; - return commit; - }*/ - - /// - /// Gets or sets the position within the underlying stream. - /// - /*int Position - { - get - { - _textWriter.Flush(); - StreamWriter streamWriter = _textWriter as StreamWriter; - if (streamWriter != null) - return (int)streamWriter.BaseStream.Position; - - StringWriter stringWriter = _textWriter as StringWriter; - if (stringWriter != null) - return stringWriter.GetStringBuilder().Length; - - return 0; - } - set - { - _textWriter.Flush(); - StreamWriter streamWriter = _textWriter as StreamWriter; - if (streamWriter != null) - streamWriter.BaseStream.SetLength(value); - else - { - StringWriter stringWriter = _textWriter as StringWriter; - if (stringWriter != null) - stringWriter.GetStringBuilder().Length = value; - } - } - }*/ /// /// Flushes the buffers of the underlying text writer. @@ -607,29 +218,6 @@ static string Ind(int indent) return new String(' ', indent); } - /// - /// Gets an indent string of current indent. - /// - /*string Indentation - { - get { return Ind(_writeIndent); } - }*/ - - /// - /// Marks the current block as 'committed'. That means the block contains - /// serialized data. - /// - /*private void CommitText() - { - _commitTextStack[_stackIdx] = true; - } - int _stackIdx; - readonly bool[] _commitTextStack = new bool[32]; - - //int _linePos; - const int LineBreakBeyond = 200; - //char _lastChar; - */ bool _fWriteStamp = false; @@ -637,17 +225,7 @@ static string Ind(int indent) readonly XmlWriter _xmlWriter; - /* TextWriter tw=null; - XmlWriter xw = XmlWriter.Create(tw, new XmlWriterSettings()); - - xw.WriteAttributeString("",""); - xw.WriteStartElement(""); - xw.WriteEndElement(); - xw.Close(); -*/ - - - internal void WriteStartDocument() + internal void WriteStartDocument() { _xmlWriter.WriteStartDocument(); } From 5dcbe8d4e03fab67b83b02d337a726a346fd9bec Mon Sep 17 00:00:00 2001 From: emazv72 Date: Wed, 13 Feb 2019 19:12:20 +0100 Subject: [PATCH 04/25] xml parser fix --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index 6968279..41317f3 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -662,6 +662,7 @@ private void ParseBoldItalicEtc(FormattedText formattedText, XmlSymbol symbol) if (IsStartElement()) { + MoveNext(false); ParseFormattedText(formattedText.Elements); AssertSymbol(symbol, true); From cf2284ac5ce80fbb6f7ab0814313aa38df72c94b Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Sun, 7 Apr 2019 10:47:54 +0200 Subject: [PATCH 05/25] last page header and footer --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 9 +- .../DocumentObjectModel.IO.Xml/Elements.cs | 12 +- .../enums/XmlSymbol.cs | 6 +- .../DocumentObjectModel.IO/DdlParser.cs | 10 +- .../DocumentObjectModel.IO/Symbols.cs | 6 +- .../DocumentObjectModel.IO/enums/Symbol.cs | 6 +- .../VisitorBase.cs | 8 +- .../DocumentObjectModel/HeaderFooter.cs | 24 +- .../DocumentObjectModel/HeadersFooters.cs | 48 +- .../DocumentObjectModel/PageSetup.cs | 35 +- .../enums/HeaderFooterIndex.cs | 13 +- .../Rendering/FormattedDocument.cs | 1362 +++++++++-------- .../RtfRendering/HeaderFooterRenderer.cs | 5 +- .../RtfRendering/PageSetupRenderer.cs | 3 +- 14 files changed, 829 insertions(+), 718 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index 41317f3..3ce5912 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -277,7 +277,8 @@ private bool IsHeaderFooter() return (sym == XmlSymbol.Header || sym == XmlSymbol.Footer || sym == XmlSymbol.PrimaryHeader || sym == XmlSymbol.PrimaryFooter || sym == XmlSymbol.EvenPageHeader || sym == XmlSymbol.EvenPageFooter || - sym == XmlSymbol.FirstPageHeader || sym == XmlSymbol.FirstPageFooter); + sym == XmlSymbol.FirstPageHeader || sym == XmlSymbol.FirstPageFooter || + sym == XmlSymbol.LastPageHeader || sym == XmlSymbol.LastPageFooter); } /// @@ -333,6 +334,7 @@ private void ParseHeaderFooter(Section section) bool isHeader = hdrFtrSym == XmlSymbol.Header || hdrFtrSym == XmlSymbol.PrimaryHeader || hdrFtrSym == XmlSymbol.FirstPageHeader || + hdrFtrSym == XmlSymbol.LastPageHeader || hdrFtrSym == XmlSymbol.EvenPageHeader; // Recall that the styles "Header" resp. "Footer" are used as default if @@ -350,6 +352,7 @@ private void ParseHeaderFooter(Section section) headersFooters.Primary = headerFooter.Clone(); headersFooters.EvenPage = headerFooter.Clone(); headersFooters.FirstPage = headerFooter.Clone(); + headersFooters.LastPage = headerFooter.Clone(); } else { @@ -369,6 +372,10 @@ private void ParseHeaderFooter(Section section) case XmlSymbol.FirstPageFooter: headersFooters.FirstPage = headerFooter; break; + case XmlSymbol.LastPageHeader: + case XmlSymbol.LastPageFooter: + headersFooters.LastPage = headerFooter; + break; } } diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs index aa34669..9a64e8a 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs @@ -24,8 +24,10 @@ static XmlKeyWords() EnumToName.Add(XmlSymbol.PrimaryHeader, "primaryheader"); EnumToName.Add(XmlSymbol.PrimaryFooter, "primaryfooter"); EnumToName.Add(XmlSymbol.FirstPageHeader, "firstpageheader"); - EnumToName.Add(XmlSymbol.FirstPageFooter, "firstpagefooter"); - EnumToName.Add(XmlSymbol.EvenPageHeader, "evenpageheader"); + EnumToName.Add(XmlSymbol.LastPageHeader, "lastpageheader"); + EnumToName.Add(XmlSymbol.FirstPageFooter, "firstpagefooter"); + EnumToName.Add(XmlSymbol.LastPageFooter, "lastpagefooter"); + EnumToName.Add(XmlSymbol.EvenPageHeader, "evenpageheader"); EnumToName.Add(XmlSymbol.EvenPageFooter, "evenpagefooter"); EnumToName.Add(XmlSymbol.Table, "table"); EnumToName.Add(XmlSymbol.Columns, "columns"); @@ -127,8 +129,10 @@ static XmlKeyWords() NameToEnum.Add("primaryheader", XmlSymbol.PrimaryHeader); NameToEnum.Add("primaryfooter", XmlSymbol.PrimaryFooter); NameToEnum.Add("firstpageheader", XmlSymbol.FirstPageHeader); - NameToEnum.Add("firstpagefooter", XmlSymbol.FirstPageFooter); - NameToEnum.Add("evenpageheader", XmlSymbol.EvenPageHeader); + NameToEnum.Add("lastpageheader", XmlSymbol.LastPageHeader); + NameToEnum.Add("firstpagefooter", XmlSymbol.FirstPageFooter); + NameToEnum.Add("lastpagefooter", XmlSymbol.LastPageFooter); + NameToEnum.Add("evenpageheader", XmlSymbol.EvenPageHeader); NameToEnum.Add("evenpagefooter", XmlSymbol.EvenPageFooter); NameToEnum.Add("table", XmlSymbol.Table); NameToEnum.Add("columns", XmlSymbol.Columns); diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs index 753fe60..689ac20 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs @@ -75,11 +75,13 @@ enum XmlSymbol Header, PrimaryHeader, FirstPageHeader, - EvenPageHeader, + LastPageHeader, + EvenPageHeader, Footer, PrimaryFooter, FirstPageFooter, - EvenPageFooter, + LastPageFooter, + EvenPageFooter, Table, Columns, Column, diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs index 9926d86..3d801d3 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs @@ -345,7 +345,8 @@ private void ParseHeaderFooter(Section section) headersFooters.Primary = headerFooter.Clone(); headersFooters.EvenPage = headerFooter.Clone(); headersFooters.FirstPage = headerFooter.Clone(); - } + headersFooters.LastPage = headerFooter.Clone(); + } else { switch (hdrFtrSym) @@ -364,7 +365,12 @@ private void ParseHeaderFooter(Section section) case Symbol.FirstPageFooter: headersFooters.FirstPage = headerFooter; break; - } + + case Symbol.LastPageHeader: + case Symbol.LastPageFooter: + headersFooters.LastPage = headerFooter; + break; + } } } catch (DdlParserException ex) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs index 1a24673..d85b39e 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs @@ -52,8 +52,10 @@ static KeyWords() EnumToName.Add(Symbol.PrimaryHeader, @"\primaryheader"); EnumToName.Add(Symbol.PrimaryFooter, @"\primaryfooter"); EnumToName.Add(Symbol.FirstPageHeader, @"\firstpageheader"); - EnumToName.Add(Symbol.FirstPageFooter, @"\firstpagefooter"); - EnumToName.Add(Symbol.EvenPageHeader, @"\evenpageheader"); + EnumToName.Add(Symbol.LastPageHeader, @"\lastpageheader"); + EnumToName.Add(Symbol.FirstPageFooter, @"\firstpagefooter"); + EnumToName.Add(Symbol.LastPageFooter, @"\lastpagefooter"); + EnumToName.Add(Symbol.EvenPageHeader, @"\evenpageheader"); EnumToName.Add(Symbol.EvenPageFooter, @"\evenpagefooter"); EnumToName.Add(Symbol.Table, @"\table"); EnumToName.Add(Symbol.Columns, @"\columns"); diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/enums/Symbol.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/enums/Symbol.cs index d76acf3..6f343c1 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/enums/Symbol.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/enums/Symbol.cs @@ -102,11 +102,13 @@ enum Symbol Header, PrimaryHeader, FirstPageHeader, - EvenPageHeader, + LastPageHeader, + EvenPageHeader, Footer, PrimaryFooter, FirstPageFooter, - EvenPageFooter, + LastPageFooter, + EvenPageFooter, Table, Columns, Column, diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs index 38ee8a7..93efe81 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs @@ -568,14 +568,18 @@ internal override void VisitSection(Section section) section.Headers._evenPage = prevSec.Headers._evenPage; if (!section.Headers.HasHeaderFooter(HeaderFooterIndex.FirstPage)) section.Headers._firstPage = prevSec.Headers._firstPage; + if (!section.Headers.HasHeaderFooter(HeaderFooterIndex.LastPage)) + section.Headers._lastPage = prevSec.Headers._lastPage; - if (!section.Footers.HasHeaderFooter(HeaderFooterIndex.Primary)) + if (!section.Footers.HasHeaderFooter(HeaderFooterIndex.Primary)) section.Footers._primary = prevSec.Footers._primary; if (!section.Footers.HasHeaderFooter(HeaderFooterIndex.EvenPage)) section.Footers._evenPage = prevSec.Footers._evenPage; if (!section.Footers.HasHeaderFooter(HeaderFooterIndex.FirstPage)) section.Footers._firstPage = prevSec.Footers._firstPage; - } + if (!section.Footers.HasHeaderFooter(HeaderFooterIndex.LastPage)) + section.Footers._lastPage = prevSec.Footers._lastPage; + } if (section._pageSetup == null) section._pageSetup = prevPageSetup; diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs index 71a803d..c97feab 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeaderFooter.cs @@ -205,10 +205,18 @@ public bool IsFirstPage get { return ((HeadersFooters)_parent)._firstPage == this; } } - /// - /// Returns true if this is an even page header or footer, false otherwise. - /// - public bool IsEvenPage + /// + /// Returns true if this is a last page header or footer, false otherwise. + /// + public bool IsLastPage + { + get { return ((HeadersFooters)_parent)._lastPage == this; } + } + + /// + /// Returns true if this is an even page header or footer, false otherwise. + /// + public bool IsEvenPage { get { return ((HeadersFooters)_parent)._evenPage == this; } } @@ -295,7 +303,9 @@ internal override void Serialize(Serializer serializer) Serialize(serializer, "evenpage"); else if (headersfooters.FirstPage == this) Serialize(serializer, "firstpage"); - } + else if (headersfooters.LastPage == this) + Serialize(serializer, "lastpage"); + } /// /// Converts HeaderFooter into DDL. @@ -325,7 +335,9 @@ internal override void Serialize(XmlSerializer serializer) Serialize(serializer, "Evenpage"); else if (headersfooters.FirstPage == this) Serialize(serializer, "Firstpage"); - } + else if (headersfooters.LastPage == this) + Serialize(serializer, "Lastpage"); + } internal void Serialize(XmlSerializer serializer, string prefix) { diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs index b91e3d1..53c4ace 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs @@ -144,10 +144,25 @@ public HeaderFooter FirstPage [DV] internal HeaderFooter _firstPage; - /// - /// Gets or sets the primary HeaderFooter of the HeadersFooters object. - /// - public HeaderFooter Primary + /// + /// Gets or sets the last page HeaderFooter of the HeadersFooters object. + /// + public HeaderFooter LastPage + { + get { return _lastPage ?? (_lastPage = new HeaderFooter(this)); } + set + { + SetParent(value); + _lastPage = value; + } + } + [DV] + internal HeaderFooter _lastPage; + + /// + /// Gets or sets the primary HeaderFooter of the HeadersFooters object. + /// + public HeaderFooter Primary { get { return _primary ?? (_primary = new HeaderFooter(this)); } set @@ -169,9 +184,10 @@ internal override void Serialize(Serializer serializer) bool hasPrimary = HasHeaderFooter(HeaderFooterIndex.Primary); bool hasEvenPage = HasHeaderFooter(HeaderFooterIndex.EvenPage); bool hasFirstPage = HasHeaderFooter(HeaderFooterIndex.FirstPage); + bool hasLastPage = HasHeaderFooter(HeaderFooterIndex.LastPage); - // \primary... - if (hasPrimary) + // \primary... + if (hasPrimary) Primary.Serialize(serializer, "primary"); // \even... @@ -181,16 +197,21 @@ internal override void Serialize(Serializer serializer) // \firstpage... if (hasFirstPage) FirstPage.Serialize(serializer, "firstpage"); - } + + // \lastpage... + if (hasLastPage) + LastPage.Serialize(serializer, "lastpage"); + } internal override void Serialize(XmlSerializer serializer) { bool hasPrimary = HasHeaderFooter(HeaderFooterIndex.Primary); bool hasEvenPage = HasHeaderFooter(HeaderFooterIndex.EvenPage); bool hasFirstPage = HasHeaderFooter(HeaderFooterIndex.FirstPage); + bool hasLastPage = HasHeaderFooter(HeaderFooterIndex.LastPage); - // \primary... - if (hasPrimary) + // \primary... + if (hasPrimary) Primary.Serialize(serializer, "Primary"); // \even... @@ -200,7 +221,10 @@ internal override void Serialize(XmlSerializer serializer) // \firstpage... if (hasFirstPage) FirstPage.Serialize(serializer, "Firstpage"); - } + + if (hasLastPage) + LastPage.Serialize(serializer, "Lastpage"); + } /// /// Allows the visitor object to visit the document object and its child objects. @@ -217,7 +241,9 @@ void IVisitable.AcceptVisitor(DocumentObjectVisitor visitor, bool visitChildren) ((IVisitable)_evenPage).AcceptVisitor(visitor, true); if (HasHeaderFooter(HeaderFooterIndex.FirstPage)) ((IVisitable)_firstPage).AcceptVisitor(visitor, true); - } + if (HasHeaderFooter(HeaderFooterIndex.LastPage)) + ((IVisitable)_lastPage).AcceptVisitor(visitor, true); + } } /// diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs index ad0441b..76a99be 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/PageSetup.cs @@ -276,11 +276,23 @@ public bool DifferentFirstPageHeaderFooter [DV] internal NBool _differentFirstPageHeaderFooter = NBool.NullValue; - /// - /// Gets or sets the distance between the header and the page top - /// of the pages in the section. - /// - public Unit HeaderDistance + /// + /// Gets or sets a value which define whether the section has a different + /// last page header and footer. + /// + public bool DifferentLastPageHeaderFooter + { + get { return _differentLastPageHeaderFooter.Value; } + set { _differentLastPageHeaderFooter.Value = value; } + } + [DV] + internal NBool _differentLastPageHeaderFooter = NBool.NullValue; + + /// + /// Gets or sets the distance between the header and the page top + /// of the pages in the section. + /// + public Unit HeaderDistance { get { return _headerDistance; } set { _headerDistance = value; } @@ -386,7 +398,8 @@ internal static PageSetup DefaultPageSetup _defaultPageSetup.FooterDistance = "1.25cm"; _defaultPageSetup.OddAndEvenPagesHeaderFooter = false; _defaultPageSetup.DifferentFirstPageHeaderFooter = false; - _defaultPageSetup.MirrorMargins = false; + _defaultPageSetup.DifferentLastPageHeaderFooter = false; + _defaultPageSetup.MirrorMargins = false; _defaultPageSetup.HorizontalPageBreak = false; } return _defaultPageSetup; @@ -436,7 +449,10 @@ internal override void Serialize(Serializer serializer) if (!_differentFirstPageHeaderFooter.IsNull) serializer.WriteSimpleAttribute("DifferentFirstPageHeaderFooter", DifferentFirstPageHeaderFooter); - if (!_sectionStart.IsNull) + if (!_differentLastPageHeaderFooter.IsNull) + serializer.WriteSimpleAttribute("DifferentLastPageHeaderFooter", DifferentLastPageHeaderFooter); + + if (!_sectionStart.IsNull) serializer.WriteSimpleAttribute("SectionStart", SectionStart); if (!_pageFormat.IsNull) @@ -495,7 +511,10 @@ internal override void Serialize(XmlSerializer serializer) if (!_differentFirstPageHeaderFooter.IsNull) serializer.WriteSimpleAttribute("DifferentFirstPageHeaderFooter", DifferentFirstPageHeaderFooter); - if (!_sectionStart.IsNull) + if (!_differentLastPageHeaderFooter.IsNull) + serializer.WriteSimpleAttribute("DifferentLastPageHeaderFooter", DifferentLastPageHeaderFooter); + + if (!_sectionStart.IsNull) serializer.WriteSimpleAttribute("SectionStart", SectionStart); if (!_pageFormat.IsNull) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/HeaderFooterIndex.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/HeaderFooterIndex.cs index 142be19..e617e55 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/HeaderFooterIndex.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/HeaderFooterIndex.cs @@ -47,9 +47,14 @@ public enum HeaderFooterIndex /// FirstPage = 1, - /// - /// Header or footer for the even pages of the section. - /// - EvenPage = 2 + /// + /// Header or footer for the last page of the section. + /// + LastPage = 2, + + /// + /// Header or footer for the even pages of the section. + /// + EvenPage = 3 } } diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs index 59817f1..67bb30c 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs @@ -38,523 +38,543 @@ namespace MigraDoc.Rendering { - /// - /// Represents a formatted document. - /// - public class FormattedDocument : IAreaProvider - { - enum PagePosition - { - First, - Odd, - Even - } - - private struct HeaderFooterPosition - { - internal HeaderFooterPosition(int sectionNr, PagePosition pagePosition) - { - _sectionNr = sectionNr; - _pagePosition = pagePosition; - } - - public override bool Equals(object obj) - { - if (obj is HeaderFooterPosition) - { - HeaderFooterPosition hfp = (HeaderFooterPosition)obj; - return _sectionNr == hfp._sectionNr && _pagePosition == hfp._pagePosition; - } - return false; - } - - public override int GetHashCode() - { - return _sectionNr.GetHashCode() ^ _pagePosition.GetHashCode(); - } - - readonly int _sectionNr; - readonly PagePosition _pagePosition; - } - - internal FormattedDocument(Document document, DocumentRenderer documentRenderer) - { - _document = document; - _documentRenderer = documentRenderer; - } - - /// - /// Formats the document by performing line breaks and page breaks. - /// - internal void Format(XGraphics gfx) - { - _bookmarks = new Dictionary(); - _pageRenderInfos = new Dictionary>(); - _pageInfos = new Dictionary(); - _pageFieldInfos = new Dictionary(); - _formattedHeaders = new Dictionary(); - _formattedFooters = new Dictionary(); - _gfx = gfx; - _currentPage = 0; - _sectionNumber = 0; - _pageCount = 0; - _shownPageNumber = 0; - _documentRenderer.ProgressCompleted = 0; - _documentRenderer.ProgressMaximum = 0; - if (_documentRenderer.HasPrepareDocumentProgress) - { - foreach (Section section in _document.Sections) - _documentRenderer.ProgressMaximum += section.Elements.Count; - } - foreach (Section section in _document.Sections) - { - _isNewSection = true; - _currentSection = section; - ++_sectionNumber; - if (NeedsEmptyPage()) - InsertEmptyPage(); - - TopDownFormatter formatter = new TopDownFormatter(this, _documentRenderer, section.Elements); - formatter.FormatOnAreas(gfx, true); - FillSectionPagesInfo(); - _documentRenderer.ProgressCompleted += section.Elements.Count; - } - _pageCount = _currentPage; - FillNumPagesInfo(); - } - - PagePosition CurrentPagePosition - { - get - { - if (_isNewSection) - return PagePosition.First; - // Choose header and footer based on the shown page number, not the physical page number. - if (_shownPageNumber % 2 == 0) - return PagePosition.Even; - return PagePosition.Odd; - } - } - - void FormatHeadersFooters() - { - HeadersFooters headers = (HeadersFooters)_currentSection.GetValue("Headers", GV.ReadOnly); - if (headers != null) - { - PagePosition pagePos = CurrentPagePosition; - HeaderFooterPosition hfp = new HeaderFooterPosition(_sectionNumber, pagePos); - if (!_formattedHeaders.ContainsKey(hfp)) - FormatHeader(hfp, ChooseHeaderFooter(headers, pagePos)); - } - - HeadersFooters footers = (HeadersFooters)_currentSection.GetValue("Footers", GV.ReadOnly); - if (footers != null) - { - PagePosition pagePos = CurrentPagePosition; - HeaderFooterPosition hfp = new HeaderFooterPosition(_sectionNumber, pagePos); - if (!_formattedFooters.ContainsKey(hfp)) - FormatFooter(hfp, ChooseHeaderFooter(footers, pagePos)); - } - } - - - void FormatHeader(HeaderFooterPosition hfp, HeaderFooter header) - { - if (header != null && !_formattedHeaders.ContainsKey(hfp)) - { - FormattedHeaderFooter formattedHeaderFooter = new FormattedHeaderFooter(header, _documentRenderer, _currentFieldInfos); - formattedHeaderFooter.ContentRect = GetHeaderArea(_currentSection, _currentPage); - formattedHeaderFooter.Format(_gfx); - _formattedHeaders.Add(hfp, formattedHeaderFooter); - } - } - - - void FormatFooter(HeaderFooterPosition hfp, HeaderFooter footer) - { - if (footer != null && !_formattedFooters.ContainsKey(hfp)) - { - FormattedHeaderFooter formattedHeaderFooter = new FormattedHeaderFooter(footer, _documentRenderer, _currentFieldInfos); - formattedHeaderFooter.ContentRect = GetFooterArea(_currentSection, _currentPage); - formattedHeaderFooter.Format(_gfx); - _formattedFooters.Add(hfp, formattedHeaderFooter); - } - } - - /// - /// Fills the number pages information after formatting the document. - /// - void FillNumPagesInfo() - { - for (int page = 1; page <= _pageCount; ++page) - { - if (IsEmptyPage(page)) - continue; - - FieldInfos fieldInfos = _pageFieldInfos[page]; - fieldInfos.NumPages = _pageCount; - } - } - - /// - /// Fills the section pages information after formatting a section. - /// - void FillSectionPagesInfo() - { - for (int page = _currentPage; page > 0; --page) - { - if (IsEmptyPage(page)) - continue; - - FieldInfos fieldInfos = _pageFieldInfos[page]; - if (fieldInfos.Section != _sectionNumber) - break; - - fieldInfos.SectionPages = _sectionPages; - } - } - - Rectangle CalcContentRect(int page) - { - PageSetup pageSetup = _currentSection.PageSetup; - XUnit width = pageSetup.EffectivePageWidth.Point; - - width -= pageSetup.RightMargin.Point; - width -= pageSetup.LeftMargin.Point; - - XUnit height = pageSetup.EffectivePageHeight.Point; - - height -= pageSetup.TopMargin.Point; - height -= pageSetup.BottomMargin.Point; - XUnit x; - XUnit y = pageSetup.TopMargin.Point; - if (pageSetup.MirrorMargins) - x = page % 2 == 0 ? pageSetup.RightMargin.Point : pageSetup.LeftMargin.Point; - else - x = pageSetup.LeftMargin.Point; - return new Rectangle(x, y, width, height); - } - - /// - /// Gets the rendering informations for the page content. - /// - /// The page to render. - /// Rendering information for the page content. - public RenderInfo[] GetRenderInfos(int page) - { - if (_pageRenderInfos.ContainsKey(page)) - return (_pageRenderInfos[page]).ToArray(); - return null; - } - private Dictionary> _pageRenderInfos; - - /// - /// Gets a formatted headerfooter object for header of the given page. - /// - /// The physical page the header shall appear on. - /// The required header, null if none exists to render. - internal FormattedHeaderFooter GetFormattedHeader(int page) - { - FieldInfos fieldInfos = _pageFieldInfos[page]; - int logicalPage = fieldInfos.DisplayPageNr; - - PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; - - if (page == 1) - pagePos = PagePosition.First; - else //page > 1 - { - if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. - pagePos = PagePosition.First; - else - { - FieldInfos prevFieldInfos = _pageFieldInfos[page - 1]; - if (fieldInfos.Section != prevFieldInfos.Section) - pagePos = PagePosition.First; - } - } - - HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos); - if (_formattedHeaders.ContainsKey(hfp)) - return _formattedHeaders[hfp]; - return null; - } - - /// - /// Gets a formatted headerfooter object for footer of the given page. - /// - /// The physical page the footer shall appear on. - /// The required footer, null if none exists to render. - internal FormattedHeaderFooter GetFormattedFooter(int page) - { - FieldInfos fieldInfos = _pageFieldInfos[page]; - int logicalPage = fieldInfos.DisplayPageNr; - - PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; - - if (page == 1) - pagePos = PagePosition.First; - else //page > 1 - { - if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. - pagePos = PagePosition.First; - else - { - FieldInfos prevFieldInfos = _pageFieldInfos[page - 1]; - if (fieldInfos.Section != prevFieldInfos.Section) - pagePos = PagePosition.First; - } - } - - HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos); - if (_formattedFooters.ContainsKey(hfp)) - return _formattedFooters[hfp]; - return null; - } - - private Rectangle GetHeaderArea(Section section, int page) - { - PageSetup pageSetup = section.PageSetup; - XUnit xPos; - if (pageSetup.MirrorMargins && page % 2 == 0) - xPos = pageSetup.RightMargin.Point; - else - xPos = pageSetup.LeftMargin.Point; - - XUnit width = pageSetup.EffectivePageWidth.Point; - width -= pageSetup.LeftMargin + pageSetup.RightMargin; - - XUnit yPos = pageSetup.HeaderDistance.Point; - XUnit height = pageSetup.TopMargin - pageSetup.HeaderDistance; - return new Rectangle(xPos, yPos, width, height); - } - - internal Rectangle GetHeaderArea(int page) - { - FieldInfos fieldInfos = _pageFieldInfos[page]; - Section section = _document.Sections[fieldInfos.Section - 1]; - return GetHeaderArea(section, page); - } - - internal Rectangle GetFooterArea(int page) - { - FieldInfos fieldInfos = _pageFieldInfos[page]; - Section section = _document.Sections[fieldInfos.Section - 1]; - return GetFooterArea(section, page); - } - - private Rectangle GetFooterArea(Section section, int page) - { - PageSetup pageSetup = section.PageSetup; - XUnit xPos; - if (pageSetup.MirrorMargins && page % 2 == 0) - xPos = pageSetup.RightMargin.Point; - else - xPos = pageSetup.LeftMargin.Point; - - XUnit width = pageSetup.EffectivePageWidth.Point; - width -= pageSetup.LeftMargin + pageSetup.RightMargin; - XUnit yPos = pageSetup.EffectivePageHeight.Point; - - yPos -= pageSetup.BottomMargin.Point; - XUnit height = pageSetup.BottomMargin - pageSetup.FooterDistance; - return new Rectangle(xPos, yPos, width, height); - } - - private HeaderFooter ChooseHeaderFooter(HeadersFooters hfs, PagePosition pagePos) - { - if (hfs == null) - return null; - - PageSetup pageSetup = _currentSection.PageSetup; - - if (pagePos == PagePosition.First) - { - if (pageSetup.DifferentFirstPageHeaderFooter) - return (HeaderFooter)hfs.GetValue("FirstPage", GV.ReadOnly); - } - if (pagePos == PagePosition.Even || _shownPageNumber/*_currentPage*/ % 2 == 0) - { - if (pageSetup.OddAndEvenPagesHeaderFooter) - return (HeaderFooter)hfs.GetValue("EvenPage", GV.ReadOnly); - } - return (HeaderFooter)hfs.GetValue("Primary", GV.ReadOnly); - } - - /// - /// Gets the number of pages of the document. - /// - public int PageCount - { - get { return _pageCount; } - } - int _pageCount; - - - /// - /// Gets information about the specified page. - /// - /// The page the information is asked for. - /// The page information. - public PageInfo GetPageInfo(int page) - { - if (page < 1 || page > _pageCount) + /// + /// Represents a formatted document. + /// + public class FormattedDocument : IAreaProvider + { + enum PagePosition + { + First, + Last, + Odd, + Even + } + + private struct HeaderFooterPosition + { + internal HeaderFooterPosition(int sectionNr, PagePosition pagePosition) + { + _sectionNr = sectionNr; + _pagePosition = pagePosition; + } + + public override bool Equals(object obj) + { + if (obj is HeaderFooterPosition) + { + HeaderFooterPosition hfp = (HeaderFooterPosition)obj; + return _sectionNr == hfp._sectionNr && _pagePosition == hfp._pagePosition; + } + return false; + } + + public override int GetHashCode() + { + return _sectionNr.GetHashCode() ^ _pagePosition.GetHashCode(); + } + + readonly int _sectionNr; + readonly PagePosition _pagePosition; + } + + internal FormattedDocument(Document document, DocumentRenderer documentRenderer) + { + _document = document; + _documentRenderer = documentRenderer; + } + + /// + /// Formats the document by performing line breaks and page breaks. + /// + internal void Format(XGraphics gfx) + { + _bookmarks = new Dictionary(); + _pageRenderInfos = new Dictionary>(); + _pageInfos = new Dictionary(); + _pageFieldInfos = new Dictionary(); + _formattedHeaders = new Dictionary(); + _formattedFooters = new Dictionary(); + _gfx = gfx; + _currentPage = 0; + _sectionNumber = 0; + _pageCount = 0; + _shownPageNumber = 0; + _documentRenderer.ProgressCompleted = 0; + _documentRenderer.ProgressMaximum = 0; + if (_documentRenderer.HasPrepareDocumentProgress) + { + foreach (Section section in _document.Sections) + _documentRenderer.ProgressMaximum += section.Elements.Count; + } + foreach (Section section in _document.Sections) + { + _isNewSection = true; + _currentSection = section; + ++_sectionNumber; + if (NeedsEmptyPage()) + InsertEmptyPage(); + + TopDownFormatter formatter = new TopDownFormatter(this, _documentRenderer, section.Elements); + formatter.FormatOnAreas(gfx, true); + FillSectionPagesInfo(); + _documentRenderer.ProgressCompleted += section.Elements.Count; + } + _pageCount = _currentPage; + FillNumPagesInfo(); + } + + PagePosition CurrentPagePosition + { + get + { + if (_isNewSection) + return PagePosition.First; + // Choose header and footer based on the shown page number, not the physical page number. + if (_shownPageNumber % 2 == 0) + return PagePosition.Even; + return PagePosition.Odd; + } + } + + void FormatHeadersFooters() + { + HeadersFooters headers = (HeadersFooters)_currentSection.GetValue("Headers", GV.ReadOnly); + if (headers != null) + { + PagePosition pagePos = CurrentPagePosition; + HeaderFooterPosition hfp = new HeaderFooterPosition(_sectionNumber, pagePos); + if (!_formattedHeaders.ContainsKey(hfp)) + FormatHeader(hfp, ChooseHeaderFooter(headers, pagePos)); + + hfp = new HeaderFooterPosition(_sectionNumber, PagePosition.Last); + if (!_formattedHeaders.ContainsKey(hfp)) + FormatHeader(hfp, ChooseHeaderFooter(headers, PagePosition.Last)); + } + + HeadersFooters footers = (HeadersFooters)_currentSection.GetValue("Footers", GV.ReadOnly); + if (footers != null) + { + PagePosition pagePos = CurrentPagePosition; + HeaderFooterPosition hfp = new HeaderFooterPosition(_sectionNumber, pagePos); + if (!_formattedFooters.ContainsKey(hfp)) + FormatFooter(hfp, ChooseHeaderFooter(footers, pagePos)); + + hfp = new HeaderFooterPosition(_sectionNumber, PagePosition.Last); + if (!_formattedHeaders.ContainsKey(hfp)) + FormatFooter(hfp, ChooseHeaderFooter(footers, PagePosition.Last)); + } + } + + + void FormatHeader(HeaderFooterPosition hfp, HeaderFooter header) + { + if (header != null && !_formattedHeaders.ContainsKey(hfp)) + { + FormattedHeaderFooter formattedHeaderFooter = new FormattedHeaderFooter(header, _documentRenderer, _currentFieldInfos); + formattedHeaderFooter.ContentRect = GetHeaderArea(_currentSection, _currentPage); + formattedHeaderFooter.Format(_gfx); + _formattedHeaders.Add(hfp, formattedHeaderFooter); + } + } + + + void FormatFooter(HeaderFooterPosition hfp, HeaderFooter footer) + { + if (footer != null && !_formattedFooters.ContainsKey(hfp)) + { + FormattedHeaderFooter formattedHeaderFooter = new FormattedHeaderFooter(footer, _documentRenderer, _currentFieldInfos); + formattedHeaderFooter.ContentRect = GetFooterArea(_currentSection, _currentPage); + formattedHeaderFooter.Format(_gfx); + _formattedFooters.Add(hfp, formattedHeaderFooter); + } + } + + /// + /// Fills the number pages information after formatting the document. + /// + void FillNumPagesInfo() + { + for (int page = 1; page <= _pageCount; ++page) + { + if (IsEmptyPage(page)) + continue; + + FieldInfos fieldInfos = _pageFieldInfos[page]; + fieldInfos.NumPages = _pageCount; + } + } + + /// + /// Fills the section pages information after formatting a section. + /// + void FillSectionPagesInfo() + { + for (int page = _currentPage; page > 0; --page) + { + if (IsEmptyPage(page)) + continue; + + FieldInfos fieldInfos = _pageFieldInfos[page]; + if (fieldInfos.Section != _sectionNumber) + break; + + fieldInfos.SectionPages = _sectionPages; + } + } + + Rectangle CalcContentRect(int page) + { + PageSetup pageSetup = _currentSection.PageSetup; + XUnit width = pageSetup.EffectivePageWidth.Point; + + width -= pageSetup.RightMargin.Point; + width -= pageSetup.LeftMargin.Point; + + XUnit height = pageSetup.EffectivePageHeight.Point; + + height -= pageSetup.TopMargin.Point; + height -= pageSetup.BottomMargin.Point; + XUnit x; + XUnit y = pageSetup.TopMargin.Point; + if (pageSetup.MirrorMargins) + x = page % 2 == 0 ? pageSetup.RightMargin.Point : pageSetup.LeftMargin.Point; + else + x = pageSetup.LeftMargin.Point; + return new Rectangle(x, y, width, height); + } + + /// + /// Gets the rendering informations for the page content. + /// + /// The page to render. + /// Rendering information for the page content. + public RenderInfo[] GetRenderInfos(int page) + { + if (_pageRenderInfos.ContainsKey(page)) + return (_pageRenderInfos[page]).ToArray(); + return null; + } + private Dictionary> _pageRenderInfos; + + /// + /// Gets a formatted headerfooter object for header of the given page. + /// + /// The physical page the header shall appear on. + /// The required header, null if none exists to render. + internal FormattedHeaderFooter GetFormattedHeader(int page) + { + FieldInfos fieldInfos = _pageFieldInfos[page]; + int logicalPage = fieldInfos.DisplayPageNr; + + PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; + + if (page == 1) + pagePos = PagePosition.First; + else + if (page == _pageCount) + pagePos = PagePosition.Last; + else //page > 1 + { + if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. + pagePos = PagePosition.First; + else + { + FieldInfos prevFieldInfos = _pageFieldInfos[page - 1]; + if (fieldInfos.Section != prevFieldInfos.Section) + pagePos = PagePosition.First; + } + } + + HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos); + if (_formattedHeaders.ContainsKey(hfp)) + return _formattedHeaders[hfp]; + return null; + } + + /// + /// Gets a formatted headerfooter object for footer of the given page. + /// + /// The physical page the footer shall appear on. + /// The required footer, null if none exists to render. + internal FormattedHeaderFooter GetFormattedFooter(int page) + { + FieldInfos fieldInfos = _pageFieldInfos[page]; + int logicalPage = fieldInfos.DisplayPageNr; + + PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; + + if (page == 1) + pagePos = PagePosition.First; + else //page > 1 + if (page == _pageCount) + pagePos = PagePosition.Last; + else + { + if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. + pagePos = PagePosition.First; + else + { + FieldInfos prevFieldInfos = _pageFieldInfos[page - 1]; + if (fieldInfos.Section != prevFieldInfos.Section) + pagePos = PagePosition.First; + } + } + + HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos); + if (_formattedFooters.ContainsKey(hfp)) + return _formattedFooters[hfp]; + return null; + } + + private Rectangle GetHeaderArea(Section section, int page) + { + PageSetup pageSetup = section.PageSetup; + XUnit xPos; + if (pageSetup.MirrorMargins && page % 2 == 0) + xPos = pageSetup.RightMargin.Point; + else + xPos = pageSetup.LeftMargin.Point; + + XUnit width = pageSetup.EffectivePageWidth.Point; + width -= pageSetup.LeftMargin + pageSetup.RightMargin; + + XUnit yPos = pageSetup.HeaderDistance.Point; + XUnit height = pageSetup.TopMargin - pageSetup.HeaderDistance; + return new Rectangle(xPos, yPos, width, height); + } + + internal Rectangle GetHeaderArea(int page) + { + FieldInfos fieldInfos = _pageFieldInfos[page]; + Section section = _document.Sections[fieldInfos.Section - 1]; + return GetHeaderArea(section, page); + } + + internal Rectangle GetFooterArea(int page) + { + FieldInfos fieldInfos = _pageFieldInfos[page]; + Section section = _document.Sections[fieldInfos.Section - 1]; + return GetFooterArea(section, page); + } + + private Rectangle GetFooterArea(Section section, int page) + { + PageSetup pageSetup = section.PageSetup; + XUnit xPos; + if (pageSetup.MirrorMargins && page % 2 == 0) + xPos = pageSetup.RightMargin.Point; + else + xPos = pageSetup.LeftMargin.Point; + + XUnit width = pageSetup.EffectivePageWidth.Point; + width -= pageSetup.LeftMargin + pageSetup.RightMargin; + XUnit yPos = pageSetup.EffectivePageHeight.Point; + + yPos -= pageSetup.BottomMargin.Point; + XUnit height = pageSetup.BottomMargin - pageSetup.FooterDistance; + return new Rectangle(xPos, yPos, width, height); + } + + private HeaderFooter ChooseHeaderFooter(HeadersFooters hfs, PagePosition pagePos) + { + if (hfs == null) + return null; + + PageSetup pageSetup = _currentSection.PageSetup; + + if (pagePos == PagePosition.First) + { + if (pageSetup.DifferentFirstPageHeaderFooter) + return (HeaderFooter)hfs.GetValue("FirstPage", GV.ReadOnly); + } + if (pagePos == PagePosition.Last) + { + if (pageSetup.DifferentLastPageHeaderFooter) + return (HeaderFooter)hfs.GetValue("LastPage", GV.ReadOnly); + } + if (pagePos == PagePosition.Even || _shownPageNumber/*_currentPage*/ % 2 == 0) + { + if (pageSetup.OddAndEvenPagesHeaderFooter) + return (HeaderFooter)hfs.GetValue("EvenPage", GV.ReadOnly); + } + return (HeaderFooter)hfs.GetValue("Primary", GV.ReadOnly); + } + + /// + /// Gets the number of pages of the document. + /// + public int PageCount + { + get { return _pageCount; } + } + int _pageCount; + + + /// + /// Gets information about the specified page. + /// + /// The page the information is asked for. + /// The page information. + public PageInfo GetPageInfo(int page) + { + if (page < 1 || page > _pageCount) #if !SILVERLIGHT - throw new ArgumentOutOfRangeException("page", page, page.ToString(CultureInfo.InvariantCulture)); + throw new ArgumentOutOfRangeException("page", page, page.ToString(CultureInfo.InvariantCulture)); #else throw new PdfSharp.ArgumentOutOfRangeException("page", page, page.ToString(CultureInfo.InvariantCulture)); #endif - return _pageInfos[page]; - } - - #region IAreaProvider Members - - Area IAreaProvider.GetNextArea() - { - if (_isNewSection) - _sectionPages = 0; - - ++_currentPage; - ++_shownPageNumber; - ++_sectionPages; - InitFieldInfos(); - FormatHeadersFooters(); - _isNewSection = false; - return CalcContentRect(_currentPage); - } - int _currentPage; - - Area IAreaProvider.ProbeNextArea() - { - return CalcContentRect(_currentPage + 1); - } - - void InitFieldInfos() - { - _currentFieldInfos = new FieldInfos(_bookmarks); - _currentFieldInfos.PhysicalPageNr = _currentPage; - _currentFieldInfos.Section = _sectionNumber; - - if (_isNewSection && !_currentSection.PageSetup._startingNumber.IsNull) - _shownPageNumber = _currentSection.PageSetup.StartingNumber; - - _currentFieldInfos.DisplayPageNr = _shownPageNumber; - } - - void IAreaProvider.StoreRenderInfos(List renderInfos) - { - _pageRenderInfos.Add(_currentPage, renderInfos); - XSize pageSize = CalcPageSize(_currentSection.PageSetup); - PageOrientation pageOrientation = CalcPageOrientation(_currentSection.PageSetup); - PageInfo pageInfo = new PageInfo(pageSize.Width, pageSize.Height, pageOrientation); - _pageInfos.Add(_currentPage, pageInfo); - _pageFieldInfos.Add(_currentPage, _currentFieldInfos); - } - - PageOrientation CalcPageOrientation(PageSetup pageSetup) - { - PageOrientation pageOrientation = PageOrientation.Portrait; - if (_currentSection.PageSetup.Orientation == Orientation.Landscape) - pageOrientation = PageOrientation.Landscape; - - return pageOrientation; - } - - XSize CalcPageSize(PageSetup pageSetup) - { - return new XSize(pageSetup.PageWidth.Point, pageSetup.PageHeight.Point); - } - - bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo) - { - switch (layoutInfo.HorizontalReference) - { - case HorizontalReference.PageMargin: - case HorizontalReference.AreaBoundary: - return PositionHorizontallyToMargin(layoutInfo); - - case HorizontalReference.Page: - return PositionHorizontallyToPage(layoutInfo); - } - return false; - } - - /// - /// Gets the alignment depending on the currentPage for the alignments "Outside" and "Inside". - /// - /// The original alignment - /// the alignment depending on the currentPage for the alignments "Outside" and "Inside" - private ElementAlignment GetCurrentAlignment(ElementAlignment alignment) - { - ElementAlignment align = alignment; - - if (align == ElementAlignment.Inside) - { - align = _currentPage % 2 == 0 ? ElementAlignment.Far : ElementAlignment.Near; - } - else if (align == ElementAlignment.Outside) - { - align = _currentPage % 2 == 0 ? ElementAlignment.Near : ElementAlignment.Far; - } - return align; - } - - bool PositionHorizontallyToMargin(LayoutInfo layoutInfo) - { - Rectangle rect = CalcContentRect(_currentPage); - ElementAlignment align = GetCurrentAlignment(layoutInfo.HorizontalAlignment); - - - switch (align) - { - case ElementAlignment.Near: - if (layoutInfo.Left != 0) - { - layoutInfo.ContentArea.X += layoutInfo.Left; - return true; - } - if (layoutInfo.MarginLeft != 0) - { - layoutInfo.ContentArea.X += layoutInfo.MarginLeft; - return true; - } - return false; - - case ElementAlignment.Far: - XUnit xPos = rect.X + rect.Width; - xPos -= layoutInfo.ContentArea.Width; - xPos -= layoutInfo.MarginRight; - layoutInfo.ContentArea.X = xPos; - return true; - - case ElementAlignment.Center: - xPos = rect.Width; - xPos -= layoutInfo.ContentArea.Width; - xPos = rect.X + xPos / 2; - layoutInfo.ContentArea.X = xPos; - return true; - } - return false; - } - - bool PositionHorizontallyToPage(LayoutInfo layoutInfo) - { - XUnit xPos; - ElementAlignment align = GetCurrentAlignment(layoutInfo.HorizontalAlignment); - switch (align) - { - case ElementAlignment.Near: + return _pageInfos[page]; + } + + #region IAreaProvider Members + + Area IAreaProvider.GetNextArea() + { + if (_isNewSection) + _sectionPages = 0; + + ++_currentPage; + ++_shownPageNumber; + ++_sectionPages; + InitFieldInfos(); + FormatHeadersFooters(); + _isNewSection = false; + return CalcContentRect(_currentPage); + } + int _currentPage; + + Area IAreaProvider.ProbeNextArea() + { + return CalcContentRect(_currentPage + 1); + } + + void InitFieldInfos() + { + _currentFieldInfos = new FieldInfos(_bookmarks); + _currentFieldInfos.PhysicalPageNr = _currentPage; + _currentFieldInfos.Section = _sectionNumber; + + if (_isNewSection && !_currentSection.PageSetup._startingNumber.IsNull) + _shownPageNumber = _currentSection.PageSetup.StartingNumber; + + _currentFieldInfos.DisplayPageNr = _shownPageNumber; + } + + void IAreaProvider.StoreRenderInfos(List renderInfos) + { + _pageRenderInfos.Add(_currentPage, renderInfos); + XSize pageSize = CalcPageSize(_currentSection.PageSetup); + PageOrientation pageOrientation = CalcPageOrientation(_currentSection.PageSetup); + PageInfo pageInfo = new PageInfo(pageSize.Width, pageSize.Height, pageOrientation); + _pageInfos.Add(_currentPage, pageInfo); + _pageFieldInfos.Add(_currentPage, _currentFieldInfos); + } + + PageOrientation CalcPageOrientation(PageSetup pageSetup) + { + PageOrientation pageOrientation = PageOrientation.Portrait; + if (_currentSection.PageSetup.Orientation == Orientation.Landscape) + pageOrientation = PageOrientation.Landscape; + + return pageOrientation; + } + + XSize CalcPageSize(PageSetup pageSetup) + { + return new XSize(pageSetup.PageWidth.Point, pageSetup.PageHeight.Point); + } + + bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo) + { + switch (layoutInfo.HorizontalReference) + { + case HorizontalReference.PageMargin: + case HorizontalReference.AreaBoundary: + return PositionHorizontallyToMargin(layoutInfo); + + case HorizontalReference.Page: + return PositionHorizontallyToPage(layoutInfo); + } + return false; + } + + /// + /// Gets the alignment depending on the currentPage for the alignments "Outside" and "Inside". + /// + /// The original alignment + /// the alignment depending on the currentPage for the alignments "Outside" and "Inside" + private ElementAlignment GetCurrentAlignment(ElementAlignment alignment) + { + ElementAlignment align = alignment; + + if (align == ElementAlignment.Inside) + { + align = _currentPage % 2 == 0 ? ElementAlignment.Far : ElementAlignment.Near; + } + else if (align == ElementAlignment.Outside) + { + align = _currentPage % 2 == 0 ? ElementAlignment.Near : ElementAlignment.Far; + } + return align; + } + + bool PositionHorizontallyToMargin(LayoutInfo layoutInfo) + { + Rectangle rect = CalcContentRect(_currentPage); + ElementAlignment align = GetCurrentAlignment(layoutInfo.HorizontalAlignment); + + + switch (align) + { + case ElementAlignment.Near: + if (layoutInfo.Left != 0) + { + layoutInfo.ContentArea.X += layoutInfo.Left; + return true; + } + if (layoutInfo.MarginLeft != 0) + { + layoutInfo.ContentArea.X += layoutInfo.MarginLeft; + return true; + } + return false; + + case ElementAlignment.Far: + XUnit xPos = rect.X + rect.Width; + xPos -= layoutInfo.ContentArea.Width; + xPos -= layoutInfo.MarginRight; + layoutInfo.ContentArea.X = xPos; + return true; + + case ElementAlignment.Center: + xPos = rect.Width; + xPos -= layoutInfo.ContentArea.Width; + xPos = rect.X + xPos / 2; + layoutInfo.ContentArea.X = xPos; + return true; + } + return false; + } + + bool PositionHorizontallyToPage(LayoutInfo layoutInfo) + { + XUnit xPos; + ElementAlignment align = GetCurrentAlignment(layoutInfo.HorizontalAlignment); + switch (align) + { + case ElementAlignment.Near: #if true - // Attempt to make it compatible with MigraDoc CPP. - // Ignore layoutInfo.Left if absolute position is specified in layoutInfo.MarginLeft. - // Use layoutInfo.Left if layoutInfo.MarginLeft is 0. - // TODO We would need HasValue for XUnit to determine whether a value was assigned. - if (layoutInfo.HorizontalReference == HorizontalReference.Page || - layoutInfo.HorizontalReference == HorizontalReference.PageMargin) - xPos = layoutInfo.MarginLeft != 0 ? layoutInfo.MarginLeft : layoutInfo.Left; - else - xPos = Math.Max(layoutInfo.MarginLeft, layoutInfo.Left); + // Attempt to make it compatible with MigraDoc CPP. + // Ignore layoutInfo.Left if absolute position is specified in layoutInfo.MarginLeft. + // Use layoutInfo.Left if layoutInfo.MarginLeft is 0. + // TODO We would need HasValue for XUnit to determine whether a value was assigned. + if (layoutInfo.HorizontalReference == HorizontalReference.Page || + layoutInfo.HorizontalReference == HorizontalReference.PageMargin) + xPos = layoutInfo.MarginLeft != 0 ? layoutInfo.MarginLeft : layoutInfo.Left; + else + xPos = Math.Max(layoutInfo.MarginLeft, layoutInfo.Left); #else if (layoutInfo.HorizontalReference == HorizontalReference.Page || layoutInfo.HorizontalReference == HorizontalReference.PageMargin) @@ -562,164 +582,164 @@ bool PositionHorizontallyToPage(LayoutInfo layoutInfo) else xPos = Math.Max(layoutInfo.MarginLeft, layoutInfo.Left); #endif - layoutInfo.ContentArea.X = xPos; - break; - - case ElementAlignment.Far: - xPos = _currentSection.PageSetup.EffectivePageWidth.Point; - xPos -= layoutInfo.ContentArea.Width; - xPos -= layoutInfo.MarginRight; - layoutInfo.ContentArea.X = xPos; - break; - - case ElementAlignment.Center: - xPos = _currentSection.PageSetup.EffectivePageWidth.Point; - xPos -= layoutInfo.ContentArea.Width; - xPos /= 2; - layoutInfo.ContentArea.X = xPos; - break; - } - return true; - } - - bool PositionVerticallyToMargin(LayoutInfo layoutInfo) - { - Rectangle rect = CalcContentRect(_currentPage); - XUnit yPos; - switch (layoutInfo.VerticalAlignment) - { - case ElementAlignment.Near: - yPos = rect.Y; - if (layoutInfo.Top == 0) - yPos += layoutInfo.MarginTop; - else - yPos += layoutInfo.Top; - layoutInfo.ContentArea.Y = yPos; - break; - - case ElementAlignment.Far: - yPos = rect.Y + rect.Height; - yPos -= layoutInfo.ContentArea.Height; - yPos -= layoutInfo.MarginBottom; - layoutInfo.ContentArea.Y = yPos; - break; - - case ElementAlignment.Center: - yPos = rect.Height; - yPos -= layoutInfo.ContentArea.Height; - yPos = rect.Y + yPos / 2; - layoutInfo.ContentArea.Y = yPos; - break; - } - return true; - } - - bool NeedsEmptyPage() - { - int nextPage = _currentPage + 1; - PageSetup pageSetup = _currentSection.PageSetup; - bool startOnEvenPage = pageSetup.SectionStart == BreakType.BreakEvenPage; - bool startOnOddPage = pageSetup.SectionStart == BreakType.BreakOddPage; - - if (startOnOddPage) - return nextPage % 2 == 0; - if (startOnEvenPage) - return nextPage % 2 == 1; - - return false; - } - - void InsertEmptyPage() - { - ++_currentPage; - ++_shownPageNumber; - _emptyPages.Add(_currentPage, null); - - XSize pageSize = CalcPageSize(_currentSection.PageSetup); - PageOrientation pageOrientation = CalcPageOrientation(_currentSection.PageSetup); - PageInfo pageInfo = new PageInfo(pageSize.Width, pageSize.Height, pageOrientation); - _pageInfos.Add(_currentPage, pageInfo); - } - - bool PositionVerticallyToPage(LayoutInfo layoutInfo) - { - XUnit yPos; - switch (layoutInfo.VerticalAlignment) - { - case ElementAlignment.Near: - yPos = Math.Max(layoutInfo.MarginTop, layoutInfo.Top); - layoutInfo.ContentArea.Y = yPos; - break; - - case ElementAlignment.Far: - yPos = _currentSection.PageSetup.EffectivePageHeight.Point; - yPos -= layoutInfo.ContentArea.Height; - yPos -= layoutInfo.MarginBottom; - layoutInfo.ContentArea.Y = yPos; - break; - - case ElementAlignment.Center: - yPos = _currentSection.PageSetup.EffectivePageHeight.Point; - yPos -= layoutInfo.ContentArea.Height; - yPos /= 2; - layoutInfo.ContentArea.Y = yPos; - break; - } - return true; - } - - bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo) - { - switch (layoutInfo.VerticalReference) - { - case VerticalReference.PreviousElement: - return false; - - case VerticalReference.AreaBoundary: - case VerticalReference.PageMargin: - return PositionVerticallyToMargin(layoutInfo); - - case VerticalReference.Page: - return PositionVerticallyToPage(layoutInfo); - } - return false; - } - - internal FieldInfos GetFieldInfos(int page) - { - return _pageFieldInfos[page]; - } - - FieldInfos IAreaProvider.AreaFieldInfos - { - get { return _currentFieldInfos; } - } - - bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo) - { - return layoutInfo.PageBreakBefore; - } - - internal bool IsEmptyPage(int page) - { - return _emptyPages.ContainsKey(page); - } - #endregion - - Dictionary _bookmarks; - int _sectionPages; - int _shownPageNumber; - int _sectionNumber; - Section _currentSection; - bool _isNewSection; - FieldInfos _currentFieldInfos; - Dictionary _pageFieldInfos; - Dictionary _formattedHeaders; - Dictionary _formattedFooters; - readonly DocumentRenderer _documentRenderer; - XGraphics _gfx; - Dictionary _pageInfos; - readonly Dictionary _emptyPages = new Dictionary(); - readonly Document _document; - } + layoutInfo.ContentArea.X = xPos; + break; + + case ElementAlignment.Far: + xPos = _currentSection.PageSetup.EffectivePageWidth.Point; + xPos -= layoutInfo.ContentArea.Width; + xPos -= layoutInfo.MarginRight; + layoutInfo.ContentArea.X = xPos; + break; + + case ElementAlignment.Center: + xPos = _currentSection.PageSetup.EffectivePageWidth.Point; + xPos -= layoutInfo.ContentArea.Width; + xPos /= 2; + layoutInfo.ContentArea.X = xPos; + break; + } + return true; + } + + bool PositionVerticallyToMargin(LayoutInfo layoutInfo) + { + Rectangle rect = CalcContentRect(_currentPage); + XUnit yPos; + switch (layoutInfo.VerticalAlignment) + { + case ElementAlignment.Near: + yPos = rect.Y; + if (layoutInfo.Top == 0) + yPos += layoutInfo.MarginTop; + else + yPos += layoutInfo.Top; + layoutInfo.ContentArea.Y = yPos; + break; + + case ElementAlignment.Far: + yPos = rect.Y + rect.Height; + yPos -= layoutInfo.ContentArea.Height; + yPos -= layoutInfo.MarginBottom; + layoutInfo.ContentArea.Y = yPos; + break; + + case ElementAlignment.Center: + yPos = rect.Height; + yPos -= layoutInfo.ContentArea.Height; + yPos = rect.Y + yPos / 2; + layoutInfo.ContentArea.Y = yPos; + break; + } + return true; + } + + bool NeedsEmptyPage() + { + int nextPage = _currentPage + 1; + PageSetup pageSetup = _currentSection.PageSetup; + bool startOnEvenPage = pageSetup.SectionStart == BreakType.BreakEvenPage; + bool startOnOddPage = pageSetup.SectionStart == BreakType.BreakOddPage; + + if (startOnOddPage) + return nextPage % 2 == 0; + if (startOnEvenPage) + return nextPage % 2 == 1; + + return false; + } + + void InsertEmptyPage() + { + ++_currentPage; + ++_shownPageNumber; + _emptyPages.Add(_currentPage, null); + + XSize pageSize = CalcPageSize(_currentSection.PageSetup); + PageOrientation pageOrientation = CalcPageOrientation(_currentSection.PageSetup); + PageInfo pageInfo = new PageInfo(pageSize.Width, pageSize.Height, pageOrientation); + _pageInfos.Add(_currentPage, pageInfo); + } + + bool PositionVerticallyToPage(LayoutInfo layoutInfo) + { + XUnit yPos; + switch (layoutInfo.VerticalAlignment) + { + case ElementAlignment.Near: + yPos = Math.Max(layoutInfo.MarginTop, layoutInfo.Top); + layoutInfo.ContentArea.Y = yPos; + break; + + case ElementAlignment.Far: + yPos = _currentSection.PageSetup.EffectivePageHeight.Point; + yPos -= layoutInfo.ContentArea.Height; + yPos -= layoutInfo.MarginBottom; + layoutInfo.ContentArea.Y = yPos; + break; + + case ElementAlignment.Center: + yPos = _currentSection.PageSetup.EffectivePageHeight.Point; + yPos -= layoutInfo.ContentArea.Height; + yPos /= 2; + layoutInfo.ContentArea.Y = yPos; + break; + } + return true; + } + + bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo) + { + switch (layoutInfo.VerticalReference) + { + case VerticalReference.PreviousElement: + return false; + + case VerticalReference.AreaBoundary: + case VerticalReference.PageMargin: + return PositionVerticallyToMargin(layoutInfo); + + case VerticalReference.Page: + return PositionVerticallyToPage(layoutInfo); + } + return false; + } + + internal FieldInfos GetFieldInfos(int page) + { + return _pageFieldInfos[page]; + } + + FieldInfos IAreaProvider.AreaFieldInfos + { + get { return _currentFieldInfos; } + } + + bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo) + { + return layoutInfo.PageBreakBefore; + } + + internal bool IsEmptyPage(int page) + { + return _emptyPages.ContainsKey(page); + } + #endregion + + Dictionary _bookmarks; + int _sectionPages; + int _shownPageNumber; + int _sectionNumber; + Section _currentSection; + bool _isNewSection; + FieldInfos _currentFieldInfos; + Dictionary _pageFieldInfos; + Dictionary _formattedHeaders; + Dictionary _formattedFooters; + readonly DocumentRenderer _documentRenderer; + XGraphics _gfx; + Dictionary _pageInfos; + readonly Dictionary _emptyPages = new Dictionary(); + readonly Document _document; + } } \ No newline at end of file diff --git a/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/HeaderFooterRenderer.cs b/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/HeaderFooterRenderer.cs index 77ee0bc..c65379c 100644 --- a/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/HeaderFooterRenderer.cs +++ b/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/HeaderFooterRenderer.cs @@ -74,8 +74,9 @@ internal override void Render() private List GetHeaderFooterControls() { List retColl = new List(); - bool differentFirst = (bool)_pageSetup.GetValue("DifferentFirstPageHeaderFooter", GV.GetNull); - bool oddEven = (bool)_pageSetup.GetValue("OddAndEvenPagesHeaderFooter", GV.GetNull); + bool differentFirst = (bool)_pageSetup.GetValue("DifferentFirstPageHeaderFooter", GV.GetNull); + // TODO support DifferentLastPageHeaderFooter + bool oddEven = (bool)_pageSetup.GetValue("OddAndEvenPagesHeaderFooter", GV.GetNull); string ctrlBase = _headerFooter.IsHeader ? "header" : "footer"; if (_renderAs == HeaderFooterIndex.FirstPage) { diff --git a/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/PageSetupRenderer.cs b/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/PageSetupRenderer.cs index 0cbaaa9..c169169 100644 --- a/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/PageSetupRenderer.cs +++ b/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/PageSetupRenderer.cs @@ -50,7 +50,8 @@ internal override void Render() { _useEffectiveValue = true; object obj = GetValueAsIntended("DifferentFirstPageHeaderFooter"); - if (obj != null && (bool)obj) + // TODO DifferentLastPageHeaderFooter + if (obj != null && (bool)obj) _rtfWriter.WriteControl("titlepg"); obj = GetValueAsIntended("Orientation"); From db92ade018299f6cbb7a30376a149cf8572cd6b2 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Sun, 7 Apr 2019 13:38:35 +0200 Subject: [PATCH 06/25] footer fix --- MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs index 67bb30c..7183e30 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs @@ -161,7 +161,7 @@ void FormatHeadersFooters() FormatFooter(hfp, ChooseHeaderFooter(footers, pagePos)); hfp = new HeaderFooterPosition(_sectionNumber, PagePosition.Last); - if (!_formattedHeaders.ContainsKey(hfp)) + if (!_formattedFooters.ContainsKey(hfp)) FormatFooter(hfp, ChooseHeaderFooter(footers, PagePosition.Last)); } } From eea1e74bd60c873fddaeefca21bd60b80144347f Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Sun, 7 Apr 2019 13:58:47 +0200 Subject: [PATCH 07/25] upgrade README.md --- README.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bcacd7d..df1f62b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -# XML based alternative serialization support +This is ( almost ) the master branch with a couple features. -This version add support to an alternative format for serialization based on XML. +# XML based alternative serialization and deserialization support + +This version add support to an alternative format for serialization based on XML. A sample MigraDoc/XML file can be found [here](https://raw.githubusercontent.com/emazv72/MigraDoc-samples/master/samples/xml/MigraDoc.xml) It can be used like this: @@ -25,7 +27,23 @@ It can be used like this: } } - + +# Last page header and footer + +- Add the DifferentLastPageHeaderFooter flag to enable the feature and add the corresponding headers and footers + +
+ + + + + .... + + + .... + +
+ # MigraDoc MigraDoc Foundation - Creating documents on the fly From aee6c15f53813661cd5164167fb191bbc26246d3 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Sun, 7 Apr 2019 15:26:53 +0200 Subject: [PATCH 08/25] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index df1f62b..bc2bed2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ - -This is ( almost ) the master branch with a couple features. +- This is ( almost ) the master branch with a couple added features. # XML based alternative serialization and deserialization support @@ -30,7 +29,7 @@ It can be used like this: # Last page header and footer -- Add the DifferentLastPageHeaderFooter flag to enable the feature and add the corresponding headers and footers +- Add the DifferentLastPageHeaderFooter flag and the corresponding headers and footers
From 296000cee8f8093628438deeae812a23775c2265 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Wed, 17 Apr 2019 15:10:00 +0200 Subject: [PATCH 09/25] last page header footer rendering fix --- .../src/MigraDoc.Rendering/Rendering/FormattedDocument.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs index 7183e30..a584750 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs @@ -304,12 +304,12 @@ internal FormattedHeaderFooter GetFormattedFooter(int page) PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; - if (page == 1) - pagePos = PagePosition.First; - else //page > 1 if (page == _pageCount) pagePos = PagePosition.Last; else + if (page == 1) + pagePos = PagePosition.First; + else //page > 1 { if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. pagePos = PagePosition.First; From a49affe57668669d3e6398f95aaac87327082bcd Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Tue, 18 Jun 2019 17:16:47 +0200 Subject: [PATCH 10/25] ListInfo fix serialization --- .../DocumentObjectModel/ListInfo.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs index 84e6771..1e00ca6 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ListInfo.cs @@ -113,13 +113,17 @@ internal override void Serialize(Serializer serializer) internal override void Serialize(XmlSerializer serializer) { - if (!_listType.IsNull) - serializer.WriteSimpleAttribute("ListInfo.ListType", ListType); + serializer.WriteStartElement("ListInfo"); + + if (!_listType.IsNull) + serializer.WriteSimpleAttribute("ListType", ListType); if (!_numberPosition.IsNull) - serializer.WriteSimpleAttribute("ListInfo.NumberPosition", NumberPosition); + serializer.WriteSimpleAttribute("NumberPosition", NumberPosition); if (!_continuePreviousList.IsNull) - serializer.WriteSimpleAttribute("ListInfo.ContinuePreviousList", ContinuePreviousList); - } + serializer.WriteSimpleAttribute("ContinuePreviousList", ContinuePreviousList); + + serializer.WriteEndElement(); // listinfo + } /// /// Returns the meta object of this instance. From 8ff7bff9abdc672a74739a43619eee3b9bcb9473 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Mon, 22 Jul 2019 15:23:10 +0200 Subject: [PATCH 11/25] paragraph parsing fix --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 47 +++++++++++++++++-- .../Properties/AssemblyInfo.cs | 2 +- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index 3ce5912..c8cfc8c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -41,6 +41,7 @@ using System.Collections.Generic; using AttrDictionary = System.Collections.Generic.Dictionary; using AttributePair = System.Collections.Generic.KeyValuePair; +using System.Text; namespace MigraDoc.DocumentObjectModel.IO.Xml { @@ -390,7 +391,7 @@ private void ParseHeaderFooter(Section section) } } - + /// /// Parses the document elements of a «\paragraph», «\cell» or comparable. @@ -637,12 +638,12 @@ private void ParseFormattedText(ParagraphElements elements) break; case XmlNodeType.Text: - text = RemoveTrailingWhiteSpace(RemoveLeadingWhiteSpace(_reader.Value)); + text = GetText(_reader.Value); if (text != String.Empty) elements.AddText(text); - MoveNext(); + MoveNext(false); break; case XmlNodeType.CDATA: @@ -651,7 +652,7 @@ private void ParseFormattedText(ParagraphElements elements) if (text != String.Empty) elements.AddText(text); - MoveNext(); + MoveNext(false); break; default: break; @@ -2573,5 +2574,43 @@ private string RemoveTrailingWhiteSpace(string text) return text; } + + /// + /// Extracts paragraph text removing and compressing white spaces + /// + /// + /// + private string GetText(string text) + { + + StringBuilder token = new StringBuilder(); + bool whiteSpace = false; + + if (text != null) + { + int idx = 0; + while (idx < text.Length) + { + if (Char.IsWhiteSpace(text[idx])) + { + if (!whiteSpace) + token.Append(' '); + + whiteSpace = true; + } + else + { + token.Append(text[idx]); + whiteSpace = false; + } + + idx++; + } + + } + + return token.ToString().TrimEnd(); + } + } } \ No newline at end of file diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs index a39114d..d6ee01f 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ [assembly: AssemblyTitle(VersionInfo.Title)] [assembly: AssemblyDescription(VersionInfo.Description)] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany(VersionInfo.Company)] +[assembly: AssemblyCompany(VersionInfo.Company + "(xmlddl build)")] #if DEBUG [assembly: AssemblyProduct(VersionInfo.Product + " (Debug Build)")] #else From f5ee6f35a96fff99b46d81127f8d795d27f28a87 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Mon, 22 Jul 2019 15:56:39 +0200 Subject: [PATCH 12/25] text parser fix --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index c8cfc8c..428d507 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -2609,7 +2609,7 @@ private string GetText(string text) } - return token.ToString().TrimEnd(); + return token.ToString().Trim(); } } From 5ce54bd1da6e50b8f22a80a36df8641808f14df6 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Mon, 22 Jul 2019 17:25:13 +0200 Subject: [PATCH 13/25] support para break --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 10 +- .../DocumentObjectModel.IO.Xml/Elements.cs | 323 +++++++++--------- .../enums/XmlSymbol.cs | 1 + .../DocumentObjectModel/Character.cs | 3 +- 4 files changed, 169 insertions(+), 168 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index 428d507..abb147a 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -538,12 +538,10 @@ private void ParseFormattedText(ParagraphElements elements) switch (XmlSymbol) { - // TODO - /* - case XmlSymbol.EmptyLine: - elements.AddCharacter(SymbolName.ParaBreak); - ReadText(rootLevel); - break;*/ + case XmlSymbol.ParaBreak: + elements.AddCharacter(SymbolName.ParaBreak); + MoveNext(false); + break; /* case XmlSymbol.Comment: diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs index 9a64e8a..f21c13c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/Elements.cs @@ -4,56 +4,57 @@ namespace MigraDoc.DocumentObjectModel.IO.Xml { - internal class XmlKeyWords - { - static XmlKeyWords() - { - EnumToName.Add(XmlSymbol.True, "true"); - EnumToName.Add(XmlSymbol.False, "false"); - //EnumToName.Add(XmlSymbol.Null, "null"); + internal class XmlKeyWords + { + static XmlKeyWords() + { + EnumToName.Add(XmlSymbol.True, "true"); + EnumToName.Add(XmlSymbol.False, "false"); + //EnumToName.Add(XmlSymbol.Null, "null"); - EnumToName.Add(XmlSymbol.Attributes, "attributes"); - EnumToName.Add(XmlSymbol.Styles, "styles"); - EnumToName.Add(XmlSymbol.Style, "style"); - EnumToName.Add(XmlSymbol.Document, "document"); - EnumToName.Add(XmlSymbol.Sections, "sections"); - EnumToName.Add(XmlSymbol.Section, "section"); - EnumToName.Add(XmlSymbol.Paragraph, "p"); // paragraph - EnumToName.Add(XmlSymbol.Header, "header"); - EnumToName.Add(XmlSymbol.Footer, "footer"); - EnumToName.Add(XmlSymbol.PrimaryHeader, "primaryheader"); - EnumToName.Add(XmlSymbol.PrimaryFooter, "primaryfooter"); - EnumToName.Add(XmlSymbol.FirstPageHeader, "firstpageheader"); + + EnumToName.Add(XmlSymbol.Attributes, "attributes"); + EnumToName.Add(XmlSymbol.Styles, "styles"); + EnumToName.Add(XmlSymbol.Style, "style"); + EnumToName.Add(XmlSymbol.Document, "document"); + EnumToName.Add(XmlSymbol.Sections, "sections"); + EnumToName.Add(XmlSymbol.Section, "section"); + EnumToName.Add(XmlSymbol.Paragraph, "p"); // paragraph + EnumToName.Add(XmlSymbol.Header, "header"); + EnumToName.Add(XmlSymbol.Footer, "footer"); + EnumToName.Add(XmlSymbol.PrimaryHeader, "primaryheader"); + EnumToName.Add(XmlSymbol.PrimaryFooter, "primaryfooter"); + EnumToName.Add(XmlSymbol.FirstPageHeader, "firstpageheader"); EnumToName.Add(XmlSymbol.LastPageHeader, "lastpageheader"); EnumToName.Add(XmlSymbol.FirstPageFooter, "firstpagefooter"); EnumToName.Add(XmlSymbol.LastPageFooter, "lastpagefooter"); EnumToName.Add(XmlSymbol.EvenPageHeader, "evenpageheader"); - EnumToName.Add(XmlSymbol.EvenPageFooter, "evenpagefooter"); - EnumToName.Add(XmlSymbol.Table, "table"); - EnumToName.Add(XmlSymbol.Columns, "columns"); - EnumToName.Add(XmlSymbol.Column, "column"); - EnumToName.Add(XmlSymbol.Rows, "rows"); - EnumToName.Add(XmlSymbol.Row, "row"); - EnumToName.Add(XmlSymbol.Cell, "cell"); - EnumToName.Add(XmlSymbol.Image, "image"); - // EnumToName.Add(XmlSymbol.Text, "text"); - EnumToName.Add(XmlSymbol.TextFrame, "textframe"); - EnumToName.Add(XmlSymbol.PageBreak, "pagebreak"); - EnumToName.Add(XmlSymbol.Barcode, "barcode"); - EnumToName.Add(XmlSymbol.Chart, "chart"); - EnumToName.Add(XmlSymbol.HeaderArea, "headerarea"); - EnumToName.Add(XmlSymbol.FooterArea, "footerarea"); - EnumToName.Add(XmlSymbol.TopArea, "toparea"); - EnumToName.Add(XmlSymbol.BottomArea, "bottomarea"); - EnumToName.Add(XmlSymbol.LeftArea, "leftarea"); - EnumToName.Add(XmlSymbol.RightArea, "rightarea"); - EnumToName.Add(XmlSymbol.PlotArea, "plotarea"); - EnumToName.Add(XmlSymbol.Legend, "legend"); - EnumToName.Add(XmlSymbol.XAxis, "xaxis"); - EnumToName.Add(XmlSymbol.YAxis, "yaxis"); - EnumToName.Add(XmlSymbol.ZAxis, "zaxis"); - EnumToName.Add(XmlSymbol.Series, "series"); - EnumToName.Add(XmlSymbol.XSeries, "xseries"); + EnumToName.Add(XmlSymbol.EvenPageFooter, "evenpagefooter"); + EnumToName.Add(XmlSymbol.Table, "table"); + EnumToName.Add(XmlSymbol.Columns, "columns"); + EnumToName.Add(XmlSymbol.Column, "column"); + EnumToName.Add(XmlSymbol.Rows, "rows"); + EnumToName.Add(XmlSymbol.Row, "row"); + EnumToName.Add(XmlSymbol.Cell, "cell"); + EnumToName.Add(XmlSymbol.Image, "image"); + // EnumToName.Add(XmlSymbol.Text, "text"); + EnumToName.Add(XmlSymbol.TextFrame, "textframe"); + EnumToName.Add(XmlSymbol.PageBreak, "pagebreak"); + EnumToName.Add(XmlSymbol.Barcode, "barcode"); + EnumToName.Add(XmlSymbol.Chart, "chart"); + EnumToName.Add(XmlSymbol.HeaderArea, "headerarea"); + EnumToName.Add(XmlSymbol.FooterArea, "footerarea"); + EnumToName.Add(XmlSymbol.TopArea, "toparea"); + EnumToName.Add(XmlSymbol.BottomArea, "bottomarea"); + EnumToName.Add(XmlSymbol.LeftArea, "leftarea"); + EnumToName.Add(XmlSymbol.RightArea, "rightarea"); + EnumToName.Add(XmlSymbol.PlotArea, "plotarea"); + EnumToName.Add(XmlSymbol.Legend, "legend"); + EnumToName.Add(XmlSymbol.XAxis, "xaxis"); + EnumToName.Add(XmlSymbol.YAxis, "yaxis"); + EnumToName.Add(XmlSymbol.ZAxis, "zaxis"); + EnumToName.Add(XmlSymbol.Series, "series"); + EnumToName.Add(XmlSymbol.XSeries, "xseries"); EnumToName.Add(XmlSymbol.XValue, "xvalue"); EnumToName.Add(XmlSymbol.Point, "point"); @@ -61,29 +62,30 @@ static XmlKeyWords() EnumToName.Add(XmlSymbol.TabStop, "tabstop"); EnumToName.Add(XmlSymbol.Bold, "b"); - EnumToName.Add(XmlSymbol.Italic, "i"); - EnumToName.Add(XmlSymbol.Underline, "u"); - EnumToName.Add(XmlSymbol.FontSize, "fontsize"); - EnumToName.Add(XmlSymbol.FontColor, "fontcolor"); - EnumToName.Add(XmlSymbol.Font, "font"); - // - EnumToName.Add(XmlSymbol.Field, "field"); - EnumToName.Add(XmlSymbol.Symbol, "symbol"); - EnumToName.Add(XmlSymbol.Chr, "chr"); - // - EnumToName.Add(XmlSymbol.Footnote, "footnote"); - EnumToName.Add(XmlSymbol.Hyperlink, "hyperlink"); - // - EnumToName.Add(XmlSymbol.SoftHyphen, "-"); - EnumToName.Add(XmlSymbol.Tab, "tab"); - EnumToName.Add(XmlSymbol.LineBreak, "br"); - EnumToName.Add(XmlSymbol.Space, "space"); - EnumToName.Add(XmlSymbol.NoSpace, "nospace"); + EnumToName.Add(XmlSymbol.Italic, "i"); + EnumToName.Add(XmlSymbol.Underline, "u"); + EnumToName.Add(XmlSymbol.FontSize, "fontsize"); + EnumToName.Add(XmlSymbol.FontColor, "fontcolor"); + EnumToName.Add(XmlSymbol.Font, "font"); + // + EnumToName.Add(XmlSymbol.Field, "field"); + EnumToName.Add(XmlSymbol.Symbol, "symbol"); + EnumToName.Add(XmlSymbol.Chr, "chr"); + // + EnumToName.Add(XmlSymbol.Footnote, "footnote"); + EnumToName.Add(XmlSymbol.Hyperlink, "hyperlink"); + // + EnumToName.Add(XmlSymbol.SoftHyphen, "-"); + EnumToName.Add(XmlSymbol.Tab, "tab"); + EnumToName.Add(XmlSymbol.LineBreak, "br"); + EnumToName.Add(XmlSymbol.ParaBreak, "pbr"); + EnumToName.Add(XmlSymbol.Space, "space"); + EnumToName.Add(XmlSymbol.NoSpace, "nospace"); - // - // + // + // - /*EnumToName.Add(XmlSymbol.BraceLeft, "{"); + /*EnumToName.Add(XmlSymbol.BraceLeft, "{"); EnumToName.Add(XmlSymbol.BraceRight, "}"); EnumToName.Add(XmlSymbol.BracketLeft, "["); EnumToName.Add(XmlSymbol.BracketRight, "]"); @@ -108,57 +110,57 @@ static XmlKeyWords() EnumToName.Add(XmlSymbol.MinusAssign, "-="); EnumToName.Add(XmlSymbol.Blank, " "); */ - //--------------------------------------------------------------- - //--------------------------------------------------------------- - //--------------------------------------------------------------- + //--------------------------------------------------------------- + //--------------------------------------------------------------- + //--------------------------------------------------------------- - NameToEnum.Add("true", XmlSymbol.True); - NameToEnum.Add("false", XmlSymbol.False); - //NameToEnum.Add("null", XmlSymbol.Null); - // - NameToEnum.Add("attributes", XmlSymbol.Attributes); - NameToEnum.Add("styles", XmlSymbol.Styles); - NameToEnum.Add("style", XmlSymbol.Style); - NameToEnum.Add("document", XmlSymbol.Document); - NameToEnum.Add("info", XmlSymbol.Info); - NameToEnum.Add("sections", XmlSymbol.Sections); - NameToEnum.Add("section", XmlSymbol.Section); - NameToEnum.Add("p", XmlSymbol.Paragraph); - NameToEnum.Add("header", XmlSymbol.Header); - NameToEnum.Add("footer", XmlSymbol.Footer); - NameToEnum.Add("primaryheader", XmlSymbol.PrimaryHeader); - NameToEnum.Add("primaryfooter", XmlSymbol.PrimaryFooter); - NameToEnum.Add("firstpageheader", XmlSymbol.FirstPageHeader); + NameToEnum.Add("true", XmlSymbol.True); + NameToEnum.Add("false", XmlSymbol.False); + //NameToEnum.Add("null", XmlSymbol.Null); + // + NameToEnum.Add("attributes", XmlSymbol.Attributes); + NameToEnum.Add("styles", XmlSymbol.Styles); + NameToEnum.Add("style", XmlSymbol.Style); + NameToEnum.Add("document", XmlSymbol.Document); + NameToEnum.Add("info", XmlSymbol.Info); + NameToEnum.Add("sections", XmlSymbol.Sections); + NameToEnum.Add("section", XmlSymbol.Section); + NameToEnum.Add("p", XmlSymbol.Paragraph); + NameToEnum.Add("header", XmlSymbol.Header); + NameToEnum.Add("footer", XmlSymbol.Footer); + NameToEnum.Add("primaryheader", XmlSymbol.PrimaryHeader); + NameToEnum.Add("primaryfooter", XmlSymbol.PrimaryFooter); + NameToEnum.Add("firstpageheader", XmlSymbol.FirstPageHeader); NameToEnum.Add("lastpageheader", XmlSymbol.LastPageHeader); NameToEnum.Add("firstpagefooter", XmlSymbol.FirstPageFooter); NameToEnum.Add("lastpagefooter", XmlSymbol.LastPageFooter); NameToEnum.Add("evenpageheader", XmlSymbol.EvenPageHeader); - NameToEnum.Add("evenpagefooter", XmlSymbol.EvenPageFooter); - NameToEnum.Add("table", XmlSymbol.Table); - NameToEnum.Add("columns", XmlSymbol.Columns); - NameToEnum.Add("column", XmlSymbol.Column); - NameToEnum.Add("rows", XmlSymbol.Rows); - NameToEnum.Add("row", XmlSymbol.Row); - NameToEnum.Add("cell", XmlSymbol.Cell); - NameToEnum.Add("image", XmlSymbol.Image); - //NameToEnum.Add("text", XmlSymbol.Text); - NameToEnum.Add("textframe", XmlSymbol.TextFrame); - NameToEnum.Add("pagebreak", XmlSymbol.PageBreak); - NameToEnum.Add("barcode", XmlSymbol.Barcode); - NameToEnum.Add("chart", XmlSymbol.Chart); - NameToEnum.Add("headerarea", XmlSymbol.HeaderArea); - NameToEnum.Add("footerarea", XmlSymbol.FooterArea); - NameToEnum.Add("toparea", XmlSymbol.TopArea); - NameToEnum.Add("bottomarea", XmlSymbol.BottomArea); - NameToEnum.Add("leftarea", XmlSymbol.LeftArea); - NameToEnum.Add("rightarea", XmlSymbol.RightArea); - NameToEnum.Add("plotarea", XmlSymbol.PlotArea); - NameToEnum.Add("legend", XmlSymbol.Legend); - NameToEnum.Add("xaxis", XmlSymbol.XAxis); - NameToEnum.Add("yaxis", XmlSymbol.YAxis); - NameToEnum.Add("zaxis", XmlSymbol.ZAxis); - NameToEnum.Add("series", XmlSymbol.Series); - NameToEnum.Add("xseries", XmlSymbol.XSeries); + NameToEnum.Add("evenpagefooter", XmlSymbol.EvenPageFooter); + NameToEnum.Add("table", XmlSymbol.Table); + NameToEnum.Add("columns", XmlSymbol.Columns); + NameToEnum.Add("column", XmlSymbol.Column); + NameToEnum.Add("rows", XmlSymbol.Rows); + NameToEnum.Add("row", XmlSymbol.Row); + NameToEnum.Add("cell", XmlSymbol.Cell); + NameToEnum.Add("image", XmlSymbol.Image); + //NameToEnum.Add("text", XmlSymbol.Text); + NameToEnum.Add("textframe", XmlSymbol.TextFrame); + NameToEnum.Add("pagebreak", XmlSymbol.PageBreak); + NameToEnum.Add("barcode", XmlSymbol.Barcode); + NameToEnum.Add("chart", XmlSymbol.Chart); + NameToEnum.Add("headerarea", XmlSymbol.HeaderArea); + NameToEnum.Add("footerarea", XmlSymbol.FooterArea); + NameToEnum.Add("toparea", XmlSymbol.TopArea); + NameToEnum.Add("bottomarea", XmlSymbol.BottomArea); + NameToEnum.Add("leftarea", XmlSymbol.LeftArea); + NameToEnum.Add("rightarea", XmlSymbol.RightArea); + NameToEnum.Add("plotarea", XmlSymbol.PlotArea); + NameToEnum.Add("legend", XmlSymbol.Legend); + NameToEnum.Add("xaxis", XmlSymbol.XAxis); + NameToEnum.Add("yaxis", XmlSymbol.YAxis); + NameToEnum.Add("zaxis", XmlSymbol.ZAxis); + NameToEnum.Add("series", XmlSymbol.Series); + NameToEnum.Add("xseries", XmlSymbol.XSeries); NameToEnum.Add("xvalue", XmlSymbol.XValue); NameToEnum.Add("point", XmlSymbol.Point); @@ -166,57 +168,58 @@ static XmlKeyWords() NameToEnum.Add("tabstop", XmlSymbol.TabStop); NameToEnum.Add("b", XmlSymbol.Bold); - NameToEnum.Add("i", XmlSymbol.Italic); - NameToEnum.Add("u", XmlSymbol.Underline); - NameToEnum.Add("fontsize", XmlSymbol.FontSize); - NameToEnum.Add("fontcolor", XmlSymbol.FontColor); - NameToEnum.Add("font", XmlSymbol.Font); - // - NameToEnum.Add("field", XmlSymbol.Field); - NameToEnum.Add("symbol", XmlSymbol.Symbol); - NameToEnum.Add("chr", XmlSymbol.Chr); - // - NameToEnum.Add("footnote", XmlSymbol.Footnote); - NameToEnum.Add("hyperlink", XmlSymbol.Hyperlink); - // - NameToEnum.Add("-", XmlSymbol.SoftHyphen); //??? \( is another special case. - NameToEnum.Add("tab", XmlSymbol.Tab); - NameToEnum.Add("br", XmlSymbol.LineBreak); - NameToEnum.Add("space", XmlSymbol.Space); - NameToEnum.Add("nospace", XmlSymbol.NoSpace); - } + NameToEnum.Add("i", XmlSymbol.Italic); + NameToEnum.Add("u", XmlSymbol.Underline); + NameToEnum.Add("fontsize", XmlSymbol.FontSize); + NameToEnum.Add("fontcolor", XmlSymbol.FontColor); + NameToEnum.Add("font", XmlSymbol.Font); + // + NameToEnum.Add("field", XmlSymbol.Field); + NameToEnum.Add("symbol", XmlSymbol.Symbol); + NameToEnum.Add("chr", XmlSymbol.Chr); + // + NameToEnum.Add("footnote", XmlSymbol.Footnote); + NameToEnum.Add("hyperlink", XmlSymbol.Hyperlink); + // + NameToEnum.Add("-", XmlSymbol.SoftHyphen); //??? \( is another special case. + NameToEnum.Add("tab", XmlSymbol.Tab); + NameToEnum.Add("br", XmlSymbol.LineBreak); + NameToEnum.Add("pbr", XmlSymbol.ParaBreak); + NameToEnum.Add("space", XmlSymbol.Space); + NameToEnum.Add("nospace", XmlSymbol.NoSpace); + } - /// - /// Returns XmlSymbol value from name, or XmlSymbol.None if no such XmlSymbol exists. - /// - internal static XmlSymbol SymbolFromName(string name) - { - XmlSymbol XmlSymbol; - if (!NameToEnum.TryGetValue(name.ToLower(), out XmlSymbol)) - { - // Check for case sensitive keywords. Allow first character upper case only. - if (string.Compare(name, "True", StringComparison.OrdinalIgnoreCase) == 0) - XmlSymbol = XmlSymbol.True; - else if (string.Compare(name, "False", StringComparison.OrdinalIgnoreCase) == 0) - XmlSymbol = XmlSymbol.False; - /*else if (string.Compare(name, "Null", StringComparison.OrdinalIgnoreCase) == 0) + /// + /// Returns XmlSymbol value from name, or XmlSymbol.None if no such XmlSymbol exists. + /// + internal static XmlSymbol SymbolFromName(string name) + { + XmlSymbol XmlSymbol; + if (!NameToEnum.TryGetValue(name.ToLower(), out XmlSymbol)) + { + // Check for case sensitive keywords. Allow first character upper case only. + if (string.Compare(name, "True", StringComparison.OrdinalIgnoreCase) == 0) + XmlSymbol = XmlSymbol.True; + else if (string.Compare(name, "False", StringComparison.OrdinalIgnoreCase) == 0) + XmlSymbol = XmlSymbol.False; + /*else if (string.Compare(name, "Null", StringComparison.OrdinalIgnoreCase) == 0) XmlSymbol = XmlSymbol.Null;*/ - else - XmlSymbol = XmlSymbol.None; - } - return XmlSymbol; - } + else + XmlSymbol = XmlSymbol.None; + } + return XmlSymbol; + } - /// - /// Returns string from XmlSymbol value. - /// - internal static string NameFromSymbol(XmlSymbol XmlSymbol) - { - return EnumToName[XmlSymbol]; - } + /// + /// Returns string from XmlSymbol value. + /// + internal static string NameFromSymbol(XmlSymbol XmlSymbol) + { + return EnumToName[XmlSymbol]; + } - static readonly Dictionary EnumToName = new Dictionary(); - static readonly Dictionary NameToEnum = new Dictionary(); - } + static readonly Dictionary EnumToName = new Dictionary(); + static readonly Dictionary NameToEnum = new Dictionary(); + } } diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs index 689ac20..a00635e 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/enums/XmlSymbol.cs @@ -133,6 +133,7 @@ enum XmlSymbol NonBreakeableBlank, SoftHyphen, LineBreak, + ParaBreak, Space, NoSpace, diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs index ffa9339..a521c49 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Character.cs @@ -197,8 +197,7 @@ internal override void Serialize(XmlSerializer serializer) else if ((SymbolName)_symbolName.Value == SymbolName.LineBreak) text = "br"; else if ((SymbolName)_symbolName.Value == SymbolName.ParaBreak) - //text = "ParagraphBreak"; - throw new NotImplementedException("ParagraphBreak"); + text = "pbr"; //else if (symbolType == SymbolName.MarginBreak) // text = "\\marginbreak "; From 9aff895e854b49eeb4cf4f240e38a057495c6064 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Mon, 5 Aug 2019 19:13:26 +0200 Subject: [PATCH 14/25] CDATA parser fix --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 80 ++++++++++++++----- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index abb147a..301f868 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -527,8 +527,6 @@ private void RemoveTrailingBlank(ParagraphElements elements) private void ParseFormattedText(ParagraphElements elements) { - string text; - bool loop = true; while (loop) { @@ -636,20 +634,12 @@ private void ParseFormattedText(ParagraphElements elements) break; case XmlNodeType.Text: - text = GetText(_reader.Value); - - if (text != String.Empty) - elements.AddText(text); - + ReadText(elements); MoveNext(false); break; case XmlNodeType.CDATA: - text = _reader.Value; - - if (text != String.Empty) - elements.AddText(text); - + ReadLiteralText(elements); MoveNext(false); break; default: @@ -658,6 +648,7 @@ private void ParseFormattedText(ParagraphElements elements) } } + /// /// Parses the keywords «\bold», «\italic», and «\underline». /// @@ -2530,7 +2521,7 @@ private static bool GetAttributeValueAsBool(AttrDictionary attributes, string ke return value.ToLower() == "true"; } - + /* private string RemoveLeadingWhiteSpace(string text) { if (text != null) @@ -2572,15 +2563,16 @@ private string RemoveTrailingWhiteSpace(string text) return text; } + */ /// /// Extracts paragraph text removing and compressing white spaces - /// - /// - /// - private string GetText(string text) + /// + private void ReadText(ParagraphElements elements) { + String text = _reader.Value; + StringBuilder token = new StringBuilder(); bool whiteSpace = false; @@ -2607,8 +2599,60 @@ private string GetText(string text) } - return token.ToString().Trim(); + text = token.ToString().Trim(); + + if (text != String.Empty) + elements.AddText(text); + } + /// + /// Extracts paragraph text without compressing white spaces + /// + private void ReadLiteralText(ParagraphElements elements) + { + + String text = _reader.Value; + + StringBuilder token = new StringBuilder(); + int spaceCount = 0; + + if (text != null) + { + int idx = 0; + while (idx < text.Length) + { + if (text[idx].Equals(' ')) + { + if (token.Length > 0) + { + elements.AddText(token.ToString()); + token.Length = 0; + } + + spaceCount++; + } + else + { + if (spaceCount > 0) + { + elements.AddSpace(spaceCount); + spaceCount = 0; + } + + token.Append(text[idx]); + } + + idx++; + } + + } + + if (spaceCount > 0) + elements.AddSpace(spaceCount); + + if (token.Length > 0) + elements.AddText(token.ToString()); + } } } \ No newline at end of file From 9d424cbbc2a2aeea9481576d1eb658ca947216d5 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Thu, 8 Aug 2019 18:49:36 +0200 Subject: [PATCH 15/25] rounded corner radius for table cells --- .../DocumentObjectModel.Tables/Cell.cs | 29 +- .../Rendering/TableRenderer.cs | 1493 +++++++++-------- 2 files changed, 801 insertions(+), 721 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs index 21c3887..a083652 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs @@ -334,10 +334,21 @@ public RoundedCorner RoundedCorner [DV] internal RoundedCorner _roundedCorner; - /// - /// Gets or sets the number of cells to be merged right. - /// - public int MergeRight + /// + /// Gets or sets the rounder corner radius + /// + public Unit RoundedCornerRadius + { + get { return _roundedCornerRadius; } + set { _roundedCornerRadius = value; } + } + [DV] + internal Unit _roundedCornerRadius = Unit.NullValue; + + /// + /// Gets or sets the number of cells to be merged right. + /// + public int MergeRight { get { return _mergeRight.Value; } set { _mergeRight.Value = value; } @@ -418,7 +429,10 @@ internal override void Serialize(Serializer serializer) if (_roundedCorner != RoundedCorner.None) serializer.WriteSimpleAttribute("RoundedCorner", RoundedCorner); - serializer.EndAttributes(pos); + if (!_roundedCornerRadius.IsNull) + serializer.WriteSimpleAttribute("RoundedCornerRadius", RoundedCornerRadius); + + serializer.EndAttributes(pos); pos = serializer.BeginContent(); if (!IsNull("Elements")) @@ -452,9 +466,10 @@ internal override void Serialize(XmlSerializer serializer) if (_roundedCorner != RoundedCorner.None) serializer.WriteSimpleAttribute("RoundedCorner", RoundedCorner); - serializer.BeginAttributes(); + if (!_roundedCornerRadius.IsNull) + serializer.WriteSimpleAttribute("RoundedCornerRadius", RoundedCornerRadius); - if (!IsNull("Borders")) + if (!IsNull("Borders")) _borders.Serialize(serializer, null); if (!IsNull("Shading")) diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs index cebbcd4..95057ff 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs @@ -40,702 +40,767 @@ namespace MigraDoc.Rendering { - /// - /// Renders a table to an XGraphics object. - /// - internal class TableRenderer : Renderer - { - internal TableRenderer(XGraphics gfx, Table documentObject, FieldInfos fieldInfos) - : base(gfx, documentObject, fieldInfos) - { - _table = documentObject; - } - - internal TableRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos) - : base(gfx, renderInfo, fieldInfos) - { - _table = (Table)_renderInfo.DocumentObject; - } - - internal override LayoutInfo InitialLayoutInfo - { - get - { - LayoutInfo layoutInfo = new LayoutInfo(); - layoutInfo.KeepTogether = _table.KeepTogether; - layoutInfo.KeepWithNext = false; - layoutInfo.MarginBottom = 0; - layoutInfo.MarginLeft = 0; - layoutInfo.MarginTop = 0; - layoutInfo.MarginRight = 0; - return layoutInfo; - } - } - - private void InitRendering() - { - TableFormatInfo formatInfo = (TableFormatInfo)_renderInfo.FormatInfo; - _bottomBorderMap = formatInfo.BottomBorderMap; - _connectedRowsMap = formatInfo.ConnectedRowsMap; - _formattedCells = formatInfo.FormattedCells; - - _currRow = formatInfo.StartRow; - _startRow = formatInfo.StartRow; - _endRow = formatInfo.EndRow; - - _mergedCells = formatInfo.MergedCells; - _lastHeaderRow = formatInfo.LastHeaderRow; - _startX = _renderInfo.LayoutInfo.ContentArea.X; - _startY = _renderInfo.LayoutInfo.ContentArea.Y; - } - - private void RenderHeaderRows() - { - if (_lastHeaderRow < 0) - return; + /// + /// Renders a table to an XGraphics object. + /// + internal class TableRenderer : Renderer + { + internal TableRenderer(XGraphics gfx, Table documentObject, FieldInfos fieldInfos) + : base(gfx, documentObject, fieldInfos) + { + _table = documentObject; + } + + internal TableRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos) + : base(gfx, renderInfo, fieldInfos) + { + _table = (Table)_renderInfo.DocumentObject; + } + + internal override LayoutInfo InitialLayoutInfo + { + get + { + LayoutInfo layoutInfo = new LayoutInfo(); + layoutInfo.KeepTogether = _table.KeepTogether; + layoutInfo.KeepWithNext = false; + layoutInfo.MarginBottom = 0; + layoutInfo.MarginLeft = 0; + layoutInfo.MarginTop = 0; + layoutInfo.MarginRight = 0; + return layoutInfo; + } + } + + private void InitRendering() + { + TableFormatInfo formatInfo = (TableFormatInfo)_renderInfo.FormatInfo; + _bottomBorderMap = formatInfo.BottomBorderMap; + _connectedRowsMap = formatInfo.ConnectedRowsMap; + _formattedCells = formatInfo.FormattedCells; + + _currRow = formatInfo.StartRow; + _startRow = formatInfo.StartRow; + _endRow = formatInfo.EndRow; + + _mergedCells = formatInfo.MergedCells; + _lastHeaderRow = formatInfo.LastHeaderRow; + _startX = _renderInfo.LayoutInfo.ContentArea.X; + _startY = _renderInfo.LayoutInfo.ContentArea.Y; + } + + private void RenderHeaderRows() + { + if (_lastHeaderRow < 0) + return; + + foreach (Cell cell in _mergedCells) + { + if (cell.Row.Index <= _lastHeaderRow) + RenderCell(cell); + } + } + + private void RenderCell(Cell cell) + { + Rectangle innerRect = GetInnerRect(CalcStartingHeight(), cell); + RenderShading(cell, innerRect); + RenderContent(cell, innerRect); + RenderBorders(cell, innerRect); + } + + private void EqualizeRoundedCornerBorders(Cell cell) + { + // If any of a corner relevant border is set, we want to copy its values to the second corner relevant border, + // to ensure the innerWidth of the cell is the same, regardless of which border is used. + // If set, we use the vertical borders as source for the values, otherwise we use the horizontal borders. + RoundedCorner roundedCorner = cell.RoundedCorner; + + if (roundedCorner == RoundedCorner.None) + return; + + BorderType primaryBorderType = BorderType.Top, secondaryBorderType = BorderType.Top; + + if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.BottomLeft) + primaryBorderType = BorderType.Left; + if (roundedCorner == RoundedCorner.TopRight || roundedCorner == RoundedCorner.BottomRight) + primaryBorderType = BorderType.Right; + + if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.TopRight) + secondaryBorderType = BorderType.Top; + if (roundedCorner == RoundedCorner.BottomLeft || roundedCorner == RoundedCorner.BottomRight) + secondaryBorderType = BorderType.Bottom; + + // If both borders don't exist, there's nothing to do and we should not create one by accessing it. + if (!cell.Borders.HasBorder(primaryBorderType) && !cell.Borders.HasBorder(secondaryBorderType)) + return; - foreach (Cell cell in _mergedCells) - { - if (cell.Row.Index <= _lastHeaderRow) - RenderCell(cell); - } - } - - private void RenderCell(Cell cell) - { - Rectangle innerRect = GetInnerRect(CalcStartingHeight(), cell); - RenderShading(cell, innerRect); - RenderContent(cell, innerRect); - RenderBorders(cell, innerRect); - } - - private void EqualizeRoundedCornerBorders(Cell cell) - { - // If any of a corner relevant border is set, we want to copy its values to the second corner relevant border, - // to ensure the innerWidth of the cell is the same, regardless of which border is used. - // If set, we use the vertical borders as source for the values, otherwise we use the horizontal borders. - RoundedCorner roundedCorner = cell.RoundedCorner; - - if (roundedCorner == RoundedCorner.None) - return; - - BorderType primaryBorderType = BorderType.Top, secondaryBorderType = BorderType.Top; - - if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.BottomLeft) - primaryBorderType = BorderType.Left; - if (roundedCorner == RoundedCorner.TopRight || roundedCorner == RoundedCorner.BottomRight) - primaryBorderType = BorderType.Right; - - if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.TopRight) - secondaryBorderType = BorderType.Top; - if (roundedCorner == RoundedCorner.BottomLeft || roundedCorner == RoundedCorner.BottomRight) - secondaryBorderType = BorderType.Bottom; - - // If both borders don't exist, there's nothing to do and we should not create one by accessing it. - if (!cell.Borders.HasBorder(primaryBorderType) && !cell.Borders.HasBorder(secondaryBorderType)) - return; - - // Get the borders. By using GV.ReadWrite we create the border, if not existing. - Border primaryBorder = (Border)cell.Borders.GetValue(primaryBorderType.ToString(), GV.ReadWrite); - Border secondaryBorder = (Border)cell.Borders.GetValue(secondaryBorderType.ToString(), GV.ReadWrite); - - Border source = primaryBorder.Visible ? primaryBorder - : secondaryBorder.Visible ? secondaryBorder : null; - Border target = primaryBorder.Visible ? secondaryBorder - : secondaryBorder.Visible ? primaryBorder : null; - - if (source == null || target == null) - return; - - target.Visible = source.Visible; - target.Width = source.Width; - target.Style = source.Style; - target.Color = source.Color; - } - - private void RenderShading(Cell cell, Rectangle innerRect) - { - ShadingRenderer shadeRenderer = new ShadingRenderer(_gfx, cell.Shading); - shadeRenderer.Render(innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height, cell.RoundedCorner); - } - - private void RenderBorders(Cell cell, Rectangle innerRect) - { - XUnit leftPos = innerRect.X; - XUnit rightPos = leftPos + innerRect.Width; - XUnit topPos = innerRect.Y; - XUnit bottomPos = innerRect.Y + innerRect.Height; - Borders mergedBorders = _mergedCells.GetEffectiveBorders(cell); - - BordersRenderer bordersRenderer = new BordersRenderer(mergedBorders, _gfx); - XUnit bottomWidth = bordersRenderer.GetWidth(BorderType.Bottom); - XUnit leftWidth = bordersRenderer.GetWidth(BorderType.Left); - XUnit topWidth = bordersRenderer.GetWidth(BorderType.Top); - XUnit rightWidth = bordersRenderer.GetWidth(BorderType.Right); - - if (cell.RoundedCorner == RoundedCorner.TopLeft) - bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y, innerRect.Width + rightWidth, innerRect.Height + bottomWidth); - else if (cell.RoundedCorner == RoundedCorner.TopRight) - bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X - leftWidth, innerRect.Y, innerRect.Width + leftWidth, innerRect.Height + bottomWidth); - else if (cell.RoundedCorner == RoundedCorner.BottomLeft) - bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y - topWidth, innerRect.Width + rightWidth, innerRect.Height + topWidth); - else if (cell.RoundedCorner == RoundedCorner.BottomRight) - bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X - leftWidth, innerRect.Y - topWidth, innerRect.Width + leftWidth, innerRect.Height + topWidth); - - // Render horizontal and vertical borders only if touching no rounded corner. - if (cell.RoundedCorner != RoundedCorner.TopRight && cell.RoundedCorner != RoundedCorner.BottomRight) - bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos, bottomPos + bottomWidth - topPos); - - if (cell.RoundedCorner != RoundedCorner.TopLeft && cell.RoundedCorner != RoundedCorner.BottomLeft) - bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos, bottomPos + bottomWidth - topPos); - - if (cell.RoundedCorner != RoundedCorner.BottomLeft && cell.RoundedCorner != RoundedCorner.BottomRight) - bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth, bottomPos, rightPos + rightWidth + leftWidth - leftPos); - - if (cell.RoundedCorner != RoundedCorner.TopLeft && cell.RoundedCorner != RoundedCorner.TopRight) - bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos); - - RenderDiagonalBorders(mergedBorders, innerRect); - } - - private void RenderDiagonalBorders(Borders mergedBorders, Rectangle innerRect) - { - BordersRenderer bordersRenderer = new BordersRenderer(mergedBorders, _gfx); - bordersRenderer.RenderDiagonally(BorderType.DiagonalDown, innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height); - bordersRenderer.RenderDiagonally(BorderType.DiagonalUp, innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height); - } - - private void RenderContent(Cell cell, Rectangle innerRect) - { - FormattedCell formattedCell = _formattedCells[cell]; - RenderInfo[] renderInfos = formattedCell.GetRenderInfos(); - - if (renderInfos == null) - return; - - VerticalAlignment verticalAlignment = cell.VerticalAlignment; - XUnit contentHeight = formattedCell.ContentHeight; - XUnit innerHeight = innerRect.Height; - XUnit targetX = innerRect.X + cell.Column.LeftPadding; - - XUnit targetY; - if (verticalAlignment == VerticalAlignment.Bottom) - { - targetY = innerRect.Y + innerRect.Height; - targetY -= cell.Row.BottomPadding; - targetY -= contentHeight; - } - else if (verticalAlignment == VerticalAlignment.Center) - { - targetY = innerRect.Y + cell.Row.TopPadding; - targetY += innerRect.Y + innerRect.Height - cell.Row.BottomPadding; - targetY -= contentHeight; - targetY /= 2; - } - else - targetY = innerRect.Y + cell.Row.TopPadding; + // Get the borders. By using GV.ReadWrite we create the border, if not existing. + Border primaryBorder = (Border)cell.Borders.GetValue(primaryBorderType.ToString(), GV.ReadWrite); + Border secondaryBorder = (Border)cell.Borders.GetValue(secondaryBorderType.ToString(), GV.ReadWrite); + + Border source = primaryBorder.Visible ? primaryBorder + : secondaryBorder.Visible ? secondaryBorder : null; + Border target = primaryBorder.Visible ? secondaryBorder + : secondaryBorder.Visible ? primaryBorder : null; + + if (source == null || target == null) + return; + + target.Visible = source.Visible; + target.Width = source.Width; + target.Style = source.Style; + target.Color = source.Color; + } - RenderByInfos(targetX, targetY, renderInfos); - } + private void RenderShading(Cell cell, Rectangle innerRect) + { + ShadingRenderer shadeRenderer = new ShadingRenderer(_gfx, cell.Shading); + shadeRenderer.Render(innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height, cell.RoundedCorner); + } - private Rectangle GetInnerRect(XUnit startingHeight, Cell cell) - { - BordersRenderer bordersRenderer = new BordersRenderer(_mergedCells.GetEffectiveBorders(cell), _gfx); - FormattedCell formattedCell = _formattedCells[cell]; - XUnit width = formattedCell.InnerWidth; + private void RenderBorders(Cell cell, Rectangle innerRect) + { + XUnit leftPos = innerRect.X; + XUnit rightPos = leftPos + innerRect.Width; + XUnit topPos = innerRect.Y; + XUnit bottomPos = innerRect.Y + innerRect.Height; + Borders mergedBorders = _mergedCells.GetEffectiveBorders(cell); - XUnit y = _startY; - if (cell.Row.Index > _lastHeaderRow) - y += startingHeight; - else - y += CalcMaxTopBorderWidth(0); + BordersRenderer bordersRenderer = new BordersRenderer(mergedBorders, _gfx); + XUnit bottomWidth = bordersRenderer.GetWidth(BorderType.Bottom); + XUnit leftWidth = bordersRenderer.GetWidth(BorderType.Left); + XUnit topWidth = bordersRenderer.GetWidth(BorderType.Top); + XUnit rightWidth = bordersRenderer.GetWidth(BorderType.Right); -#if true - // !!!new 18-03-09 Attempt to fix an exception. begin - XUnit upperBorderPos; - if (!_bottomBorderMap.TryGetValue(cell.Row.Index, out upperBorderPos)) - { - //GetType(); - } - // !!!new 18-03-09 Attempt to fix an exception. end -#else - XUnit upperBorderPos = _bottomBorderMap[cell.Row.Index]; -#endif + if (!cell.RoundedCornerRadius.IsNull && cell.RoundedCorner != RoundedCorner.None) + { - y += upperBorderPos; - if (cell.Row.Index > _lastHeaderRow) - y -= _bottomBorderMap[_startRow]; + XUnit radius = cell.RoundedCornerRadius.Point; -#if true - // !!!new 18-03-09 Attempt to fix an exception. begin - XUnit lowerBorderPos; - if (!_bottomBorderMap.TryGetValue(cell.Row.Index + cell.MergeDown + 1, out lowerBorderPos)) - { - //GetType(); - } - // !!!new 18-03-09 Attempt to fix an exception. end -#else - XUnit lowerBorderPos = _bottomBorderMap[cell.Row.Index + cell.MergeDown + 1]; -#endif + if (cell.RoundedCorner == RoundedCorner.TopLeft) + { + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y, radius - leftWidth, radius); - XUnit height = lowerBorderPos - upperBorderPos; - height -= bordersRenderer.GetWidth(BorderType.Bottom); + bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth + radius, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos - radius); - XUnit x = _startX; - for (int clmIdx = 0; clmIdx < cell.Column.Index; ++clmIdx) - { - x += _table.Columns[clmIdx].Width; - } - x += LeftBorderOffset; + bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos + radius, bottomPos + bottomWidth - topPos - radius); - return new Rectangle(x, y, width, height); - } + bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth, bottomPos, rightPos + rightWidth + leftWidth - leftPos); - internal override void Render() - { - InitRendering(); - RenderHeaderRows(); - if (_startRow < _table.Rows.Count) - { - Cell cell = _table[_startRow, 0]; + bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos, bottomPos + bottomWidth - topPos); - int cellIdx = _mergedCells.BinarySearch(_table[_startRow, 0], new CellComparer()); - while (cellIdx < _mergedCells.Count) - { - cell = _mergedCells[cellIdx]; - if (cell.Row.Index > _endRow) - break; + } + else if (cell.RoundedCorner == RoundedCorner.TopRight) + { - RenderCell(cell); - ++cellIdx; - } - } - } + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X + rightWidth + innerRect.Width - radius, innerRect.Y, radius - rightWidth, radius); - private void InitFormat(Area area, FormatInfo previousFormatInfo) - { - TableFormatInfo prevTableFormatInfo = (TableFormatInfo)previousFormatInfo; - TableRenderInfo tblRenderInfo = new TableRenderInfo(); - tblRenderInfo.DocumentObject = _table; + bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos - radius); - // Equalize the two borders, that are used to determine a rounded corner's border. - // This way the innerWidth of the cell, which is got by the saved _formattedCells, is the same regardless of which corner relevant border is set. - foreach (Row row in _table.Rows) - foreach (Cell cell in row.Cells) - EqualizeRoundedCornerBorders(cell); + bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos, bottomPos + bottomWidth - topPos); - _renderInfo = tblRenderInfo; + bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth, bottomPos, rightPos + rightWidth + leftWidth - leftPos); - if (prevTableFormatInfo != null) - { - _mergedCells = prevTableFormatInfo.MergedCells; - _formattedCells = prevTableFormatInfo.FormattedCells; - _bottomBorderMap = prevTableFormatInfo.BottomBorderMap; - _lastHeaderRow = prevTableFormatInfo.LastHeaderRow; - _connectedRowsMap = prevTableFormatInfo.ConnectedRowsMap; - _startRow = prevTableFormatInfo.EndRow + 1; - } - else - { - _mergedCells = new MergedCellList(_table); - FormatCells(); - CalcLastHeaderRow(); - CreateConnectedRows(); - CreateBottomBorderMap(); - if (_doHorizontalBreak) - { - CalcLastHeaderColumn(); - CreateConnectedColumns(); - } - _startRow = _lastHeaderRow + 1; - } - ((TableFormatInfo)tblRenderInfo.FormatInfo).MergedCells = _mergedCells; - ((TableFormatInfo)tblRenderInfo.FormatInfo).FormattedCells = _formattedCells; - ((TableFormatInfo)tblRenderInfo.FormatInfo).BottomBorderMap = _bottomBorderMap; - ((TableFormatInfo)tblRenderInfo.FormatInfo).ConnectedRowsMap = _connectedRowsMap; - ((TableFormatInfo)tblRenderInfo.FormatInfo).LastHeaderRow = _lastHeaderRow; - } - - private void FormatCells() - { - _formattedCells = new Dictionary(); //new Sorted_List(new CellComparer()); - foreach (Cell cell in _mergedCells) - { - FormattedCell formattedCell = new FormattedCell(cell, _documentRenderer, _mergedCells.GetEffectiveBorders(cell), - _fieldInfos, 0, 0); - formattedCell.Format(_gfx); - _formattedCells.Add(cell, formattedCell); - } - } - - /// - /// Formats (measures) the table. - /// - /// The area on which to fit the table. - /// - internal override void Format(Area area, FormatInfo previousFormatInfo) - { - DocumentElements elements = DocumentRelations.GetParent(_table) as DocumentElements; - if (elements != null) - { - Section section = DocumentRelations.GetParent(elements) as Section; - if (section != null) - _doHorizontalBreak = section.PageSetup.HorizontalPageBreak; - } + bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos + radius, bottomPos + bottomWidth - topPos - radius); - _renderInfo = new TableRenderInfo(); - InitFormat(area, previousFormatInfo); - - // Don't take any Rows higher then MaxElementHeight - XUnit topHeight = CalcStartingHeight(); - XUnit probeHeight = topHeight; - XUnit offset; - if (_startRow > _lastHeaderRow + 1 && - _startRow < _table.Rows.Count) - offset = _bottomBorderMap[_startRow] - topHeight; - else - offset = -CalcMaxTopBorderWidth(0); - - int probeRow = _startRow; - XUnit currentHeight = 0; - XUnit startingHeight = 0; - bool isEmpty = false; - - while (probeRow < _table.Rows.Count) - { - bool firstProbe = probeRow == _startRow; - probeRow = _connectedRowsMap[probeRow]; - // Don't take any Rows higher then MaxElementHeight - probeHeight = _bottomBorderMap[probeRow + 1] - offset; - // First test whether MaxElementHeight has been set. - if (MaxElementHeight > 0 && firstProbe && probeHeight > MaxElementHeight - Tolerance) - probeHeight = MaxElementHeight - Tolerance; - //if (firstProbe && probeHeight > MaxElementHeight - Tolerance) - // probeHeight = MaxElementHeight - Tolerance; - - //The height for the first new row(s) + headerrows: - if (startingHeight == 0) - { - if (probeHeight > area.Height) - { - isEmpty = true; - break; - } - startingHeight = probeHeight; - } + } + else if (cell.RoundedCorner == RoundedCorner.BottomLeft) + { - if (probeHeight > area.Height) - break; + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y + innerRect.Height + bottomWidth - radius, radius - leftWidth, radius - bottomWidth); - else - { - _currRow = probeRow; - currentHeight = probeHeight; - ++probeRow; - } - } - if (!isEmpty) - { - TableFormatInfo formatInfo = (TableFormatInfo)_renderInfo.FormatInfo; - formatInfo.StartRow = _startRow; - formatInfo._isEnding = _currRow >= _table.Rows.Count - 1; - formatInfo.EndRow = _currRow; - } - FinishLayoutInfo(area, currentHeight, startingHeight); - } - - private void FinishLayoutInfo(Area area, XUnit currentHeight, XUnit startingHeight) - { - LayoutInfo layoutInfo = _renderInfo.LayoutInfo; - layoutInfo.StartingHeight = startingHeight; - //REM: Trailing height would have to be calculated in case tables had a keep with next property. - layoutInfo.TrailingHeight = 0; - if (_currRow >= 0) - { - layoutInfo.ContentArea = new Rectangle(area.X, area.Y, 0, currentHeight); - XUnit width = LeftBorderOffset; - foreach (Column clm in _table.Columns) - { - width += clm.Width; - } - layoutInfo.ContentArea.Width = width; - } - layoutInfo.MinWidth = layoutInfo.ContentArea.Width; + bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos); - if (!_table.Rows._leftIndent.IsNull) - layoutInfo.Left = _table.Rows.LeftIndent.Point; + bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos, bottomPos + bottomWidth - topPos - radius); - else if (_table.Rows.Alignment == RowAlignment.Left) - { - XUnit leftOffset = LeftBorderOffset; - leftOffset += _table.Columns[0].LeftPadding; - layoutInfo.Left = -leftOffset; - } + bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth + radius, bottomPos, rightPos + rightWidth + leftWidth - leftPos - radius); - switch (_table.Rows.Alignment) - { - case RowAlignment.Left: - layoutInfo.HorizontalAlignment = ElementAlignment.Near; - break; + bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos, bottomPos + bottomWidth - topPos); - case RowAlignment.Right: - layoutInfo.HorizontalAlignment = ElementAlignment.Far; - break; + } + else if (cell.RoundedCorner == RoundedCorner.BottomRight) + { - case RowAlignment.Center: - layoutInfo.HorizontalAlignment = ElementAlignment.Center; - break; - } - } + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X + rightWidth /*- leftWidth*/ + innerRect.Width - radius, innerRect.Y + bottomWidth/*- topWidth*/ + innerRect.Height - radius, radius - rightWidth /*+ leftWidth*/, radius - bottomWidth /*+topWidth*/); - private XUnit LeftBorderOffset - { - get - { - if (_leftBorderOffset < 0) - { - if (_table.Rows.Count > 0 && _table.Columns.Count > 0) - { - Borders borders = _mergedCells.GetEffectiveBorders(_table[0, 0]); - BordersRenderer bordersRenderer = new BordersRenderer(borders, _gfx); - _leftBorderOffset = bordersRenderer.GetWidth(BorderType.Left); - } - else - _leftBorderOffset = 0; - } - return _leftBorderOffset; - } - } - - private XUnit _leftBorderOffset = -1; - - /// - /// Calcs either the height of the header rows or the height of the uppermost top border. - /// - /// - private XUnit CalcStartingHeight() - { - XUnit height = 0; - if (_lastHeaderRow >= 0) - { - height = _bottomBorderMap[_lastHeaderRow + 1]; - height += CalcMaxTopBorderWidth(0); - } - else - { - if (_table.Rows.Count > _startRow) - height = CalcMaxTopBorderWidth(_startRow); - } + bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos); - return height; - } + bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos, bottomPos + bottomWidth - topPos); + bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth, bottomPos, rightPos + rightWidth + leftWidth - leftPos - radius); - private void CalcLastHeaderColumn() - { - _lastHeaderColumn = -1; - foreach (Column clm in _table.Columns) - { - if (clm.HeadingFormat) - _lastHeaderColumn = clm.Index; - else break; - } - if (_lastHeaderColumn >= 0) - _lastHeaderRow = CalcLastConnectedColumn(_lastHeaderColumn); - - // Ignore heading format if all the table is heading: - if (_lastHeaderRow == _table.Rows.Count - 1) - _lastHeaderRow = -1; - } - - private void CalcLastHeaderRow() - { - _lastHeaderRow = -1; - foreach (Row row in _table.Rows) - { - if (row.HeadingFormat) - _lastHeaderRow = row.Index; - else break; - } - if (_lastHeaderRow >= 0) - _lastHeaderRow = CalcLastConnectedRow(_lastHeaderRow); + bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos, bottomPos + bottomWidth - topPos - radius); - // Ignore heading format if all the table is heading: - if (_lastHeaderRow == _table.Rows.Count - 1) - _lastHeaderRow = -1; - } - private void CreateConnectedRows() - { - _connectedRowsMap = new Dictionary(); //new Sorted_List(); - foreach (Cell cell in _mergedCells) - { - if (!_connectedRowsMap.ContainsKey(cell.Row.Index)) - { - int lastConnectedRow = CalcLastConnectedRow(cell.Row.Index); - _connectedRowsMap[cell.Row.Index] = lastConnectedRow; - } - } - } + } + } + else + { + if (cell.RoundedCorner == RoundedCorner.TopLeft) + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y, innerRect.Width + rightWidth, innerRect.Height + bottomWidth); + else if (cell.RoundedCorner == RoundedCorner.TopRight) + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X - leftWidth, innerRect.Y, innerRect.Width + leftWidth, innerRect.Height + bottomWidth); + else if (cell.RoundedCorner == RoundedCorner.BottomLeft) + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y - topWidth, innerRect.Width + rightWidth, innerRect.Height + topWidth); + else if (cell.RoundedCorner == RoundedCorner.BottomRight) + bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X - leftWidth, innerRect.Y - topWidth, innerRect.Width + leftWidth, innerRect.Height + topWidth); - private void CreateConnectedColumns() - { - _connectedColumnsMap = new Dictionary(); //new SortedList(); - foreach (Cell cell in _mergedCells) - { - if (!_connectedColumnsMap.ContainsKey(cell.Column.Index)) - { - int lastConnectedColumn = CalcLastConnectedColumn(cell.Column.Index); - _connectedColumnsMap[cell.Column.Index] = lastConnectedColumn; - } - } - } + // Render horizontal and vertical borders only if touching no rounded corner. + if (cell.RoundedCorner != RoundedCorner.TopRight && cell.RoundedCorner != RoundedCorner.BottomRight) + bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos, bottomPos + bottomWidth - topPos); - private void CreateBottomBorderMap() - { - _bottomBorderMap = new Dictionary(); //new SortedList(); - _bottomBorderMap.Add(0, XUnit.FromPoint(0)); - while (!_bottomBorderMap.ContainsKey(_table.Rows.Count)) - { - CreateNextBottomBorderPosition(); - } - } - - /// - /// Calculates the top border width for the first row that is rendered or formatted. - /// - /// The row index. - private XUnit CalcMaxTopBorderWidth(int row) - { - XUnit maxWidth = 0; - if (_table.Rows.Count > row) - { - int cellIdx = _mergedCells.BinarySearch(_table[row, 0], new CellComparer()); - Cell rowCell = _mergedCells[cellIdx]; - while (cellIdx < _mergedCells.Count) - { - rowCell = _mergedCells[cellIdx]; - if (rowCell.Row.Index > row) - break; + if (cell.RoundedCorner != RoundedCorner.TopLeft && cell.RoundedCorner != RoundedCorner.BottomLeft) + bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos, bottomPos + bottomWidth - topPos); - if (rowCell._borders != null && !rowCell._borders.IsNull()) - { - BordersRenderer bordersRenderer = new BordersRenderer(rowCell.Borders, _gfx); - XUnit width = bordersRenderer.GetWidth(BorderType.Top); - if (width > maxWidth) - maxWidth = width; - } - ++cellIdx; - } - } - return maxWidth; - } - - /// - /// Creates the next bottom border position. - /// - private void CreateNextBottomBorderPosition() - { - //int lastIdx = _bottomBorderMap.Count - 1; - // SortedList version: - //int lastBorderRow = (int)bottomBorderMap.GetKey(lastIdx); - //XUnit lastPos = (XUnit)bottomBorderMap.GetByIndex(lastIdx); - int lastBorderRow = 0; - foreach (int key in _bottomBorderMap.Keys) - { - if (key > lastBorderRow) - lastBorderRow = key; - } - XUnit lastPos = _bottomBorderMap[lastBorderRow]; + if (cell.RoundedCorner != RoundedCorner.BottomLeft && cell.RoundedCorner != RoundedCorner.BottomRight) + bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth, bottomPos, rightPos + rightWidth + leftWidth - leftPos); - Cell minMergedCell = GetMinMergedCell(lastBorderRow); - FormattedCell minMergedFormattedCell = _formattedCells[minMergedCell]; - XUnit maxBottomBorderPosition = lastPos + minMergedFormattedCell.InnerHeight; - maxBottomBorderPosition += CalcBottomBorderWidth(minMergedCell); + if (cell.RoundedCorner != RoundedCorner.TopLeft && cell.RoundedCorner != RoundedCorner.TopRight) + bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos); - foreach (Cell cell in _mergedCells) - { - if (cell.Row.Index > minMergedCell.Row.Index + minMergedCell.MergeDown) - break; + RenderDiagonalBorders(mergedBorders, innerRect); + } + } - if (cell.Row.Index + cell.MergeDown == minMergedCell.Row.Index + minMergedCell.MergeDown) - { - FormattedCell formattedCell = _formattedCells[cell]; - // !!!new 18-03-09 Attempt to fix an exception. begin - // if (cell.Row.Index < _bottomBorderMap.Count) - { - // !!!new 18-03-09 Attempt to fix an exception. end + private void RenderDiagonalBorders(Borders mergedBorders, Rectangle innerRect) + { + BordersRenderer bordersRenderer = new BordersRenderer(mergedBorders, _gfx); + bordersRenderer.RenderDiagonally(BorderType.DiagonalDown, innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height); + bordersRenderer.RenderDiagonally(BorderType.DiagonalUp, innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height); + } + + private void RenderContent(Cell cell, Rectangle innerRect) + { + FormattedCell formattedCell = _formattedCells[cell]; + RenderInfo[] renderInfos = formattedCell.GetRenderInfos(); + + if (renderInfos == null) + return; + + VerticalAlignment verticalAlignment = cell.VerticalAlignment; + XUnit contentHeight = formattedCell.ContentHeight; + XUnit innerHeight = innerRect.Height; + XUnit targetX = innerRect.X + cell.Column.LeftPadding; + + XUnit targetY; + if (verticalAlignment == VerticalAlignment.Bottom) + { + targetY = innerRect.Y + innerRect.Height; + targetY -= cell.Row.BottomPadding; + targetY -= contentHeight; + } + else if (verticalAlignment == VerticalAlignment.Center) + { + targetY = innerRect.Y + cell.Row.TopPadding; + targetY += innerRect.Y + innerRect.Height - cell.Row.BottomPadding; + targetY -= contentHeight; + targetY /= 2; + } + else + targetY = innerRect.Y + cell.Row.TopPadding; + + RenderByInfos(targetX, targetY, renderInfos); + } + + private Rectangle GetInnerRect(XUnit startingHeight, Cell cell) + { + BordersRenderer bordersRenderer = new BordersRenderer(_mergedCells.GetEffectiveBorders(cell), _gfx); + FormattedCell formattedCell = _formattedCells[cell]; + XUnit width = formattedCell.InnerWidth; + + XUnit y = _startY; + if (cell.Row.Index > _lastHeaderRow) + y += startingHeight; + else + y += CalcMaxTopBorderWidth(0); + +#if true + // !!!new 18-03-09 Attempt to fix an exception. begin + XUnit upperBorderPos; + if (!_bottomBorderMap.TryGetValue(cell.Row.Index, out upperBorderPos)) + { + //GetType(); + } + // !!!new 18-03-09 Attempt to fix an exception. end +#else + XUnit upperBorderPos = _bottomBorderMap[cell.Row.Index]; +#endif + + y += upperBorderPos; + if (cell.Row.Index > _lastHeaderRow) + y -= _bottomBorderMap[_startRow]; + +#if true + // !!!new 18-03-09 Attempt to fix an exception. begin + XUnit lowerBorderPos; + if (!_bottomBorderMap.TryGetValue(cell.Row.Index + cell.MergeDown + 1, out lowerBorderPos)) + { + //GetType(); + } + // !!!new 18-03-09 Attempt to fix an exception. end +#else + XUnit lowerBorderPos = _bottomBorderMap[cell.Row.Index + cell.MergeDown + 1]; +#endif + + XUnit height = lowerBorderPos - upperBorderPos; + height -= bordersRenderer.GetWidth(BorderType.Bottom); + + XUnit x = _startX; + for (int clmIdx = 0; clmIdx < cell.Column.Index; ++clmIdx) + { + x += _table.Columns[clmIdx].Width; + } + x += LeftBorderOffset; + + return new Rectangle(x, y, width, height); + } + + internal override void Render() + { + InitRendering(); + RenderHeaderRows(); + if (_startRow < _table.Rows.Count) + { + Cell cell = _table[_startRow, 0]; + + int cellIdx = _mergedCells.BinarySearch(_table[_startRow, 0], new CellComparer()); + while (cellIdx < _mergedCells.Count) + { + cell = _mergedCells[cellIdx]; + if (cell.Row.Index > _endRow) + break; + + RenderCell(cell); + ++cellIdx; + } + } + } + + private void InitFormat(Area area, FormatInfo previousFormatInfo) + { + TableFormatInfo prevTableFormatInfo = (TableFormatInfo)previousFormatInfo; + TableRenderInfo tblRenderInfo = new TableRenderInfo(); + tblRenderInfo.DocumentObject = _table; + + // Equalize the two borders, that are used to determine a rounded corner's border. + // This way the innerWidth of the cell, which is got by the saved _formattedCells, is the same regardless of which corner relevant border is set. + foreach (Row row in _table.Rows) + foreach (Cell cell in row.Cells) + EqualizeRoundedCornerBorders(cell); + + _renderInfo = tblRenderInfo; + + if (prevTableFormatInfo != null) + { + _mergedCells = prevTableFormatInfo.MergedCells; + _formattedCells = prevTableFormatInfo.FormattedCells; + _bottomBorderMap = prevTableFormatInfo.BottomBorderMap; + _lastHeaderRow = prevTableFormatInfo.LastHeaderRow; + _connectedRowsMap = prevTableFormatInfo.ConnectedRowsMap; + _startRow = prevTableFormatInfo.EndRow + 1; + } + else + { + _mergedCells = new MergedCellList(_table); + FormatCells(); + CalcLastHeaderRow(); + CreateConnectedRows(); + CreateBottomBorderMap(); + if (_doHorizontalBreak) + { + CalcLastHeaderColumn(); + CreateConnectedColumns(); + } + _startRow = _lastHeaderRow + 1; + } + ((TableFormatInfo)tblRenderInfo.FormatInfo).MergedCells = _mergedCells; + ((TableFormatInfo)tblRenderInfo.FormatInfo).FormattedCells = _formattedCells; + ((TableFormatInfo)tblRenderInfo.FormatInfo).BottomBorderMap = _bottomBorderMap; + ((TableFormatInfo)tblRenderInfo.FormatInfo).ConnectedRowsMap = _connectedRowsMap; + ((TableFormatInfo)tblRenderInfo.FormatInfo).LastHeaderRow = _lastHeaderRow; + } + + private void FormatCells() + { + _formattedCells = new Dictionary(); //new Sorted_List(new CellComparer()); + foreach (Cell cell in _mergedCells) + { + FormattedCell formattedCell = new FormattedCell(cell, _documentRenderer, _mergedCells.GetEffectiveBorders(cell), + _fieldInfos, 0, 0); + formattedCell.Format(_gfx); + _formattedCells.Add(cell, formattedCell); + } + } + + /// + /// Formats (measures) the table. + /// + /// The area on which to fit the table. + /// + internal override void Format(Area area, FormatInfo previousFormatInfo) + { + DocumentElements elements = DocumentRelations.GetParent(_table) as DocumentElements; + if (elements != null) + { + Section section = DocumentRelations.GetParent(elements) as Section; + if (section != null) + _doHorizontalBreak = section.PageSetup.HorizontalPageBreak; + } + + _renderInfo = new TableRenderInfo(); + InitFormat(area, previousFormatInfo); + + // Don't take any Rows higher then MaxElementHeight + XUnit topHeight = CalcStartingHeight(); + XUnit probeHeight = topHeight; + XUnit offset; + if (_startRow > _lastHeaderRow + 1 && + _startRow < _table.Rows.Count) + offset = _bottomBorderMap[_startRow] - topHeight; + else + offset = -CalcMaxTopBorderWidth(0); + + int probeRow = _startRow; + XUnit currentHeight = 0; + XUnit startingHeight = 0; + bool isEmpty = false; + + while (probeRow < _table.Rows.Count) + { + bool firstProbe = probeRow == _startRow; + probeRow = _connectedRowsMap[probeRow]; + // Don't take any Rows higher then MaxElementHeight + probeHeight = _bottomBorderMap[probeRow + 1] - offset; + // First test whether MaxElementHeight has been set. + if (MaxElementHeight > 0 && firstProbe && probeHeight > MaxElementHeight - Tolerance) + probeHeight = MaxElementHeight - Tolerance; + //if (firstProbe && probeHeight > MaxElementHeight - Tolerance) + // probeHeight = MaxElementHeight - Tolerance; + + //The height for the first new row(s) + headerrows: + if (startingHeight == 0) + { + if (probeHeight > area.Height) + { + isEmpty = true; + break; + } + startingHeight = probeHeight; + } + + if (probeHeight > area.Height) + break; + + else + { + _currRow = probeRow; + currentHeight = probeHeight; + ++probeRow; + } + } + if (!isEmpty) + { + TableFormatInfo formatInfo = (TableFormatInfo)_renderInfo.FormatInfo; + formatInfo.StartRow = _startRow; + formatInfo._isEnding = _currRow >= _table.Rows.Count - 1; + formatInfo.EndRow = _currRow; + } + FinishLayoutInfo(area, currentHeight, startingHeight); + } + + private void FinishLayoutInfo(Area area, XUnit currentHeight, XUnit startingHeight) + { + LayoutInfo layoutInfo = _renderInfo.LayoutInfo; + layoutInfo.StartingHeight = startingHeight; + //REM: Trailing height would have to be calculated in case tables had a keep with next property. + layoutInfo.TrailingHeight = 0; + if (_currRow >= 0) + { + layoutInfo.ContentArea = new Rectangle(area.X, area.Y, 0, currentHeight); + XUnit width = LeftBorderOffset; + foreach (Column clm in _table.Columns) + { + width += clm.Width; + } + layoutInfo.ContentArea.Width = width; + } + layoutInfo.MinWidth = layoutInfo.ContentArea.Width; + + if (!_table.Rows._leftIndent.IsNull) + layoutInfo.Left = _table.Rows.LeftIndent.Point; + + else if (_table.Rows.Alignment == RowAlignment.Left) + { + XUnit leftOffset = LeftBorderOffset; + leftOffset += _table.Columns[0].LeftPadding; + layoutInfo.Left = -leftOffset; + } + + switch (_table.Rows.Alignment) + { + case RowAlignment.Left: + layoutInfo.HorizontalAlignment = ElementAlignment.Near; + break; + + case RowAlignment.Right: + layoutInfo.HorizontalAlignment = ElementAlignment.Far; + break; + + case RowAlignment.Center: + layoutInfo.HorizontalAlignment = ElementAlignment.Center; + break; + } + } + + private XUnit LeftBorderOffset + { + get + { + if (_leftBorderOffset < 0) + { + if (_table.Rows.Count > 0 && _table.Columns.Count > 0) + { + Borders borders = _mergedCells.GetEffectiveBorders(_table[0, 0]); + BordersRenderer bordersRenderer = new BordersRenderer(borders, _gfx); + _leftBorderOffset = bordersRenderer.GetWidth(BorderType.Left); + } + else + _leftBorderOffset = 0; + } + return _leftBorderOffset; + } + } + + private XUnit _leftBorderOffset = -1; + + /// + /// Calcs either the height of the header rows or the height of the uppermost top border. + /// + /// + private XUnit CalcStartingHeight() + { + XUnit height = 0; + if (_lastHeaderRow >= 0) + { + height = _bottomBorderMap[_lastHeaderRow + 1]; + height += CalcMaxTopBorderWidth(0); + } + else + { + if (_table.Rows.Count > _startRow) + height = CalcMaxTopBorderWidth(_startRow); + } + + return height; + } + + + private void CalcLastHeaderColumn() + { + _lastHeaderColumn = -1; + foreach (Column clm in _table.Columns) + { + if (clm.HeadingFormat) + _lastHeaderColumn = clm.Index; + else break; + } + if (_lastHeaderColumn >= 0) + _lastHeaderRow = CalcLastConnectedColumn(_lastHeaderColumn); + + // Ignore heading format if all the table is heading: + if (_lastHeaderRow == _table.Rows.Count - 1) + _lastHeaderRow = -1; + } + + private void CalcLastHeaderRow() + { + _lastHeaderRow = -1; + foreach (Row row in _table.Rows) + { + if (row.HeadingFormat) + _lastHeaderRow = row.Index; + else break; + } + if (_lastHeaderRow >= 0) + _lastHeaderRow = CalcLastConnectedRow(_lastHeaderRow); + + // Ignore heading format if all the table is heading: + if (_lastHeaderRow == _table.Rows.Count - 1) + _lastHeaderRow = -1; + } + + private void CreateConnectedRows() + { + _connectedRowsMap = new Dictionary(); //new Sorted_List(); + foreach (Cell cell in _mergedCells) + { + if (!_connectedRowsMap.ContainsKey(cell.Row.Index)) + { + int lastConnectedRow = CalcLastConnectedRow(cell.Row.Index); + _connectedRowsMap[cell.Row.Index] = lastConnectedRow; + } + } + } + + private void CreateConnectedColumns() + { + _connectedColumnsMap = new Dictionary(); //new SortedList(); + foreach (Cell cell in _mergedCells) + { + if (!_connectedColumnsMap.ContainsKey(cell.Column.Index)) + { + int lastConnectedColumn = CalcLastConnectedColumn(cell.Column.Index); + _connectedColumnsMap[cell.Column.Index] = lastConnectedColumn; + } + } + } + + private void CreateBottomBorderMap() + { + _bottomBorderMap = new Dictionary(); //new SortedList(); + _bottomBorderMap.Add(0, XUnit.FromPoint(0)); + while (!_bottomBorderMap.ContainsKey(_table.Rows.Count)) + { + CreateNextBottomBorderPosition(); + } + } + + /// + /// Calculates the top border width for the first row that is rendered or formatted. + /// + /// The row index. + private XUnit CalcMaxTopBorderWidth(int row) + { + XUnit maxWidth = 0; + if (_table.Rows.Count > row) + { + int cellIdx = _mergedCells.BinarySearch(_table[row, 0], new CellComparer()); + Cell rowCell = _mergedCells[cellIdx]; + while (cellIdx < _mergedCells.Count) + { + rowCell = _mergedCells[cellIdx]; + if (rowCell.Row.Index > row) + break; + + if (rowCell._borders != null && !rowCell._borders.IsNull()) + { + BordersRenderer bordersRenderer = new BordersRenderer(rowCell.Borders, _gfx); + XUnit width = bordersRenderer.GetWidth(BorderType.Top); + if (width > maxWidth) + maxWidth = width; + } + ++cellIdx; + } + } + return maxWidth; + } + + /// + /// Creates the next bottom border position. + /// + private void CreateNextBottomBorderPosition() + { + //int lastIdx = _bottomBorderMap.Count - 1; + // SortedList version: + //int lastBorderRow = (int)bottomBorderMap.GetKey(lastIdx); + //XUnit lastPos = (XUnit)bottomBorderMap.GetByIndex(lastIdx); + int lastBorderRow = 0; + foreach (int key in _bottomBorderMap.Keys) + { + if (key > lastBorderRow) + lastBorderRow = key; + } + XUnit lastPos = _bottomBorderMap[lastBorderRow]; + + Cell minMergedCell = GetMinMergedCell(lastBorderRow); + FormattedCell minMergedFormattedCell = _formattedCells[minMergedCell]; + XUnit maxBottomBorderPosition = lastPos + minMergedFormattedCell.InnerHeight; + maxBottomBorderPosition += CalcBottomBorderWidth(minMergedCell); + + foreach (Cell cell in _mergedCells) + { + if (cell.Row.Index > minMergedCell.Row.Index + minMergedCell.MergeDown) + break; + + if (cell.Row.Index + cell.MergeDown == minMergedCell.Row.Index + minMergedCell.MergeDown) + { + FormattedCell formattedCell = _formattedCells[cell]; + // !!!new 18-03-09 Attempt to fix an exception. begin + // if (cell.Row.Index < _bottomBorderMap.Count) + { + // !!!new 18-03-09 Attempt to fix an exception. end #if true - // !!!new 18-03-09 Attempt to fix an exception. begin - XUnit topBorderPos = maxBottomBorderPosition; - if (!_bottomBorderMap.TryGetValue(cell.Row.Index, out topBorderPos)) - { - //GetType(); - } - // !!!new 18-03-09 Attempt to fix an exception. end + // !!!new 18-03-09 Attempt to fix an exception. begin + XUnit topBorderPos = maxBottomBorderPosition; + if (!_bottomBorderMap.TryGetValue(cell.Row.Index, out topBorderPos)) + { + //GetType(); + } + // !!!new 18-03-09 Attempt to fix an exception. end #else XUnit topBorderPos = _bottomBorderMap[cell.Row.Index]; #endif - XUnit bottomBorderPos = topBorderPos + formattedCell.InnerHeight; - bottomBorderPos += CalcBottomBorderWidth(cell); - if (bottomBorderPos > maxBottomBorderPosition) - maxBottomBorderPosition = bottomBorderPos; - // !!!new 18-03-09 Attempt to fix an exception. begin - } - // !!!new 18-03-09 Attempt to fix an exception. end - } - } - _bottomBorderMap.Add(minMergedCell.Row.Index + minMergedCell.MergeDown + 1, maxBottomBorderPosition); - } - - /// - /// Calculates bottom border width of a cell. - /// - /// The cell the bottom border of the row that is probed. - /// The calculated border width. - private XUnit CalcBottomBorderWidth(Cell cell) - { - Borders borders = _mergedCells.GetEffectiveBorders(cell); - if (borders != null) - { - BordersRenderer bordersRenderer = new BordersRenderer(borders, _gfx); - return bordersRenderer.GetWidth(BorderType.Bottom); - } - return 0; - } - - /// - /// Gets the first cell that ends in the given row or as close as possible. - /// - /// The row to probe. - /// The first cell with minimal vertical merge. - private Cell GetMinMergedCell(int row) - { + XUnit bottomBorderPos = topBorderPos + formattedCell.InnerHeight; + bottomBorderPos += CalcBottomBorderWidth(cell); + if (bottomBorderPos > maxBottomBorderPosition) + maxBottomBorderPosition = bottomBorderPos; + // !!!new 18-03-09 Attempt to fix an exception. begin + } + // !!!new 18-03-09 Attempt to fix an exception. end + } + } + _bottomBorderMap.Add(minMergedCell.Row.Index + minMergedCell.MergeDown + 1, maxBottomBorderPosition); + } + + /// + /// Calculates bottom border width of a cell. + /// + /// The cell the bottom border of the row that is probed. + /// The calculated border width. + private XUnit CalcBottomBorderWidth(Cell cell) + { + Borders borders = _mergedCells.GetEffectiveBorders(cell); + if (borders != null) + { + BordersRenderer bordersRenderer = new BordersRenderer(borders, _gfx); + return bordersRenderer.GetWidth(BorderType.Bottom); + } + return 0; + } + + /// + /// Gets the first cell that ends in the given row or as close as possible. + /// + /// The row to probe. + /// The first cell with minimal vertical merge. + private Cell GetMinMergedCell(int row) + { #if true - //!!!new 18-03-10 begin - // Also look at rows above "row", but only consider cells that end at "row" or as close as possible. - int minMerge = _table.Rows.Count; - Cell minCell = null; - foreach (Cell cell in _mergedCells) - { - if (cell.Row.Index <= row && cell.Row.Index + cell.MergeDown >= row) - { - if (cell.Row.Index == row && cell.MergeDown == 0) - { - // Perfect match: non-merged cell in the desired row. - minCell = cell; - break; - } - else if (cell.Row.Index + cell.MergeDown - row < minMerge) - { - minMerge = cell.Row.Index + cell.MergeDown - row; - minCell = cell; - } - } - else if (cell.Row.Index > row) - break; - } - //!!!new 18-03-10 end + //!!!new 18-03-10 begin + // Also look at rows above "row", but only consider cells that end at "row" or as close as possible. + int minMerge = _table.Rows.Count; + Cell minCell = null; + foreach (Cell cell in _mergedCells) + { + if (cell.Row.Index <= row && cell.Row.Index + cell.MergeDown >= row) + { + if (cell.Row.Index == row && cell.MergeDown == 0) + { + // Perfect match: non-merged cell in the desired row. + minCell = cell; + break; + } + else if (cell.Row.Index + cell.MergeDown - row < minMerge) + { + minMerge = cell.Row.Index + cell.MergeDown - row; + minCell = cell; + } + } + else if (cell.Row.Index > row) + break; + } + //!!!new 18-03-10 end #else int minMerge = _table.Rows.Count; Cell minCell = null; @@ -758,64 +823,64 @@ private Cell GetMinMergedCell(int row) break; } #endif - return minCell; - } - - /// - /// Calculates the last row that is connected with the given row. - /// - /// The row that is probed for downward connection. - /// The last row that is connected with the given row. - private int CalcLastConnectedRow(int row) - { - int lastConnectedRow = row; - foreach (Cell cell in _mergedCells) - { - if (cell.Row.Index <= lastConnectedRow) - { - int downConnection = Math.Max(cell.Row.KeepWith, cell.MergeDown); - if (lastConnectedRow < cell.Row.Index + downConnection) - lastConnectedRow = cell.Row.Index + downConnection; - } - } - return lastConnectedRow; - } - - /// - /// Calculates the last column that is connected with the specified column. - /// - /// The column that is probed for downward connection. - /// The last column that is connected with the given column. - private int CalcLastConnectedColumn(int column) - { - int lastConnectedColumn = column; - foreach (Cell cell in _mergedCells) - { - if (cell.Column.Index <= lastConnectedColumn) - { - int rightConnection = Math.Max(cell.Column.KeepWith, cell.MergeRight); - if (lastConnectedColumn < cell.Column.Index + rightConnection) - lastConnectedColumn = cell.Column.Index + rightConnection; - } - } - return lastConnectedColumn; - } - - private readonly Table _table; - private MergedCellList _mergedCells; - private Dictionary _formattedCells; //SortedList formattedCells; - private Dictionary _bottomBorderMap; //SortedList bottomBorderMap; - private Dictionary _connectedRowsMap; //SortedList connectedRowsMap; - private Dictionary _connectedColumnsMap; //SortedList connectedColumnsMap; - - private int _lastHeaderRow; - private int _lastHeaderColumn; - private int _startRow; - private int _currRow; - private int _endRow = -1; - - private bool _doHorizontalBreak; - private XUnit _startX; - private XUnit _startY; - } + return minCell; + } + + /// + /// Calculates the last row that is connected with the given row. + /// + /// The row that is probed for downward connection. + /// The last row that is connected with the given row. + private int CalcLastConnectedRow(int row) + { + int lastConnectedRow = row; + foreach (Cell cell in _mergedCells) + { + if (cell.Row.Index <= lastConnectedRow) + { + int downConnection = Math.Max(cell.Row.KeepWith, cell.MergeDown); + if (lastConnectedRow < cell.Row.Index + downConnection) + lastConnectedRow = cell.Row.Index + downConnection; + } + } + return lastConnectedRow; + } + + /// + /// Calculates the last column that is connected with the specified column. + /// + /// The column that is probed for downward connection. + /// The last column that is connected with the given column. + private int CalcLastConnectedColumn(int column) + { + int lastConnectedColumn = column; + foreach (Cell cell in _mergedCells) + { + if (cell.Column.Index <= lastConnectedColumn) + { + int rightConnection = Math.Max(cell.Column.KeepWith, cell.MergeRight); + if (lastConnectedColumn < cell.Column.Index + rightConnection) + lastConnectedColumn = cell.Column.Index + rightConnection; + } + } + return lastConnectedColumn; + } + + private readonly Table _table; + private MergedCellList _mergedCells; + private Dictionary _formattedCells; //SortedList formattedCells; + private Dictionary _bottomBorderMap; //SortedList bottomBorderMap; + private Dictionary _connectedRowsMap; //SortedList connectedRowsMap; + private Dictionary _connectedColumnsMap; //SortedList connectedColumnsMap; + + private int _lastHeaderRow; + private int _lastHeaderColumn; + private int _startRow; + private int _currRow; + private int _endRow = -1; + + private bool _doHorizontalBreak; + private XUnit _startX; + private XUnit _startY; + } } \ No newline at end of file From d165db904a7ef03424d66c408a13dd91a6081fe3 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Fri, 6 Dec 2019 18:19:00 +0100 Subject: [PATCH 16/25] makes DifferentLastPageHeaderFooter section aware --- MigraDoc/src/MigraDoc.Rendering/Rendering/FieldInfos.cs | 3 ++- .../src/MigraDoc.Rendering/Rendering/FormattedDocument.cs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/FieldInfos.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/FieldInfos.cs index aaf70f4..41a19d0 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/FieldInfos.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/FieldInfos.cs @@ -93,6 +93,7 @@ internal BookmarkInfo(int physicalPageNumber, int displayPageNumber) internal int Section; internal int SectionPages; internal int NumPages; - internal DateTime Date; + internal int LastPage; + internal DateTime Date; } } diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs index a584750..9dae321 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/FormattedDocument.cs @@ -220,6 +220,8 @@ void FillSectionPagesInfo() break; fieldInfos.SectionPages = _sectionPages; + + fieldInfos.LastPage = _currentPage; } } @@ -272,7 +274,7 @@ internal FormattedHeaderFooter GetFormattedHeader(int page) if (page == 1) pagePos = PagePosition.First; else - if (page == _pageCount) + if (page == fieldInfos.LastPage) pagePos = PagePosition.Last; else //page > 1 { @@ -304,7 +306,7 @@ internal FormattedHeaderFooter GetFormattedFooter(int page) PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; - if (page == _pageCount) + if (page == fieldInfos.LastPage) pagePos = PagePosition.Last; else if (page == 1) From f76ace9981cb2c49160b5540c5effdd5bcd982f8 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Tue, 17 Dec 2019 11:32:23 +0100 Subject: [PATCH 17/25] fix cell serialization --- .../DocumentObjectModel.Tables/Cell.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs index a083652..b6c33cb 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs @@ -469,6 +469,8 @@ internal override void Serialize(XmlSerializer serializer) if (!_roundedCornerRadius.IsNull) serializer.WriteSimpleAttribute("RoundedCornerRadius", RoundedCornerRadius); + serializer.BeginAttributes(); + if (!IsNull("Borders")) _borders.Serialize(serializer, null); From 1bef504b7b5913df0cc7d2c7f3f8e0c866ac791b Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Tue, 17 Dec 2019 15:07:59 +0100 Subject: [PATCH 18/25] Avoid rendering failure images --- .../DocumentObjectModel.Shapes/Image.cs | 23 +- .../Rendering/ImageRenderer.cs | 642 +++++++++--------- 2 files changed, 340 insertions(+), 325 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs index 9da5c84..3739b7c 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs @@ -158,13 +158,24 @@ public double Resolution } [DV] internal NDouble _resolution = NDouble.NullValue; - //#endregion - #region Internal - /// - /// Converts Image into DDL. - /// - internal override void Serialize(Serializer serializer) + /// + /// Gets or sets whether to render a failure image. + /// + public bool RenderOnFailure + { + get { return _renderOnFailure.Value; } + set { _renderOnFailure.Value = value; } + } + [DV] + internal NBool _renderOnFailure = NBool.NullValue; + //#endregion + + #region Internal + /// + /// Converts Image into DDL. + /// + internal override void Serialize(Serializer serializer) { serializer.WriteLine("\\image(\"" + _name.Value.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\")"); diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs index b4ad613..3e6cdf9 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs @@ -37,318 +37,322 @@ namespace MigraDoc.Rendering { - /// - /// Renders images. - /// - internal class ImageRenderer : ShapeRenderer - { - internal ImageRenderer(XGraphics gfx, Image image, FieldInfos fieldInfos) - : base(gfx, image, fieldInfos) - { - _image = image; - ImageRenderInfo renderInfo = new ImageRenderInfo(); - renderInfo.DocumentObject = _shape; - _renderInfo = renderInfo; - } - - internal ImageRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos) - : base(gfx, renderInfo, fieldInfos) - { - _image = (Image)renderInfo.DocumentObject; - } - - internal override void Format(Area area, FormatInfo previousFormatInfo) - { - _imageFilePath = _image.GetFilePath(_documentRenderer.WorkingDirectory); - // The Image is stored in the string if path starts with "base64:", otherwise we check whether the file exists. - if (!_imageFilePath.StartsWith("base64:") && - !XImage.ExistsFile(_imageFilePath)) - { - _failure = ImageFailure.FileNotFound; - Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning"); - } - ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - formatInfo.Failure = _failure; - formatInfo.ImagePath = _imageFilePath; - CalculateImageDimensions(); - base.Format(area, previousFormatInfo); - } - - protected override XUnit ShapeHeight - { - get - { - ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - return formatInfo.Height + _lineFormatRenderer.GetWidth(); - } - } - - protected override XUnit ShapeWidth - { - get - { - ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - return formatInfo.Width + _lineFormatRenderer.GetWidth(); - } - } - - internal override void Render() - { - RenderFilling(); - - ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - Area contentArea = _renderInfo.LayoutInfo.ContentArea; - XRect destRect = new XRect(contentArea.X, contentArea.Y, formatInfo.Width, formatInfo.Height); - - if (formatInfo.Failure == ImageFailure.None) - { - XImage xImage = null; - try - { - XRect srcRect = new XRect(formatInfo.CropX, formatInfo.CropY, formatInfo.CropWidth, formatInfo.CropHeight); - //xImage = XImage.FromFile(formatInfo.ImagePath); - xImage = CreateXImage(formatInfo.ImagePath); - _gfx.DrawImage(xImage, destRect, srcRect, XGraphicsUnit.Point); //Pixel. - } - catch (Exception) - { - RenderFailureImage(destRect); - } - finally - { - if (xImage != null) - xImage.Dispose(); - } - } - else - RenderFailureImage(destRect); - - RenderLine(); - } - - void RenderFailureImage(XRect destRect) - { - _gfx.DrawRectangle(XBrushes.LightGray, destRect); - string failureString; - ImageFormatInfo formatInfo = (ImageFormatInfo)RenderInfo.FormatInfo; - - switch (formatInfo.Failure) - { - case ImageFailure.EmptySize: - failureString = Messages2.DisplayEmptyImageSize; - break; - - case ImageFailure.FileNotFound: - failureString = Messages2.DisplayImageFileNotFound; - break; - - case ImageFailure.InvalidType: - failureString = Messages2.DisplayInvalidImageType; - break; - - case ImageFailure.NotRead: - default: - failureString = Messages2.DisplayImageNotRead; - break; - } - - // Create stub font - XFont font = new XFont("Courier New", 8); - _gfx.DrawString(failureString, font, XBrushes.Red, destRect, XStringFormats.Center); - } - - private void CalculateImageDimensions() - { - ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - - if (formatInfo.Failure == ImageFailure.None) - { - XImage xImage = null; - try - { - //xImage = XImage.FromFile(_imageFilePath); - xImage = CreateXImage(_imageFilePath); - } - catch (InvalidOperationException ex) - { - Debug.WriteLine(Messages2.InvalidImageType(ex.Message)); - formatInfo.Failure = ImageFailure.InvalidType; - } - - if (formatInfo.Failure == ImageFailure.None) - { - try - { - XUnit usrWidth = _image.Width.Point; - XUnit usrHeight = _image.Height.Point; - bool usrWidthSet = !_image._width.IsNull; - bool usrHeightSet = !_image._height.IsNull; - - XUnit resultWidth = usrWidth; - XUnit resultHeight = usrHeight; - - Debug.Assert(xImage != null); - double xPixels = xImage.PixelWidth; - bool usrResolutionSet = !_image._resolution.IsNull; - - double horzRes = usrResolutionSet ? _image.Resolution : xImage.HorizontalResolution; - double vertRes = usrResolutionSet ? _image.Resolution : xImage.VerticalResolution; - -// ReSharper disable CompareOfFloatsByEqualityOperator - if (horzRes == 0 && vertRes == 0) - { - horzRes = 72; - vertRes = 72; - } - else if (horzRes == 0) - { - Debug.Assert(false, "How can this be?"); - horzRes = 72; - } - else if (vertRes == 0) - { - Debug.Assert(false, "How can this be?"); - vertRes = 72; - } - // ReSharper restore CompareOfFloatsByEqualityOperator - - XUnit inherentWidth = XUnit.FromInch(xPixels / horzRes); - double yPixels = xImage.PixelHeight; - XUnit inherentHeight = XUnit.FromInch(yPixels / vertRes); - - //bool lockRatio = _image.IsNull("LockAspectRatio") ? true : _image.LockAspectRatio; - bool lockRatio = _image._lockAspectRatio.IsNull || _image.LockAspectRatio; - - double scaleHeight = _image.ScaleHeight; - double scaleWidth = _image.ScaleWidth; - //bool scaleHeightSet = !_image.IsNull("ScaleHeight"); - //bool scaleWidthSet = !_image.IsNull("ScaleWidth"); - bool scaleHeightSet = !_image._scaleHeight.IsNull; - bool scaleWidthSet = !_image._scaleWidth.IsNull; - - if (lockRatio && !(scaleHeightSet && scaleWidthSet)) - { - if (usrWidthSet && !usrHeightSet) - { - resultHeight = inherentHeight / inherentWidth * usrWidth; - } - else if (usrHeightSet && !usrWidthSet) - { - resultWidth = inherentWidth / inherentHeight * usrHeight; - } -// ReSharper disable once ConditionIsAlwaysTrueOrFalse - else if (!usrHeightSet && !usrWidthSet) - { - resultHeight = inherentHeight; - resultWidth = inherentWidth; - } - - if (scaleHeightSet) - { - resultHeight = resultHeight * scaleHeight; - resultWidth = resultWidth * scaleHeight; - } - if (scaleWidthSet) - { - resultHeight = resultHeight * scaleWidth; - resultWidth = resultWidth * scaleWidth; - } - } - else - { - if (!usrHeightSet) - resultHeight = inherentHeight; - - if (!usrWidthSet) - resultWidth = inherentWidth; - - if (scaleHeightSet) - resultHeight = resultHeight * scaleHeight; - if (scaleWidthSet) - resultWidth = resultWidth * scaleWidth; - } - - formatInfo.CropWidth = (int)xPixels; - formatInfo.CropHeight = (int)yPixels; - if (_image._pictureFormat != null && !_image._pictureFormat.IsNull()) - { - PictureFormat picFormat = _image.PictureFormat; - //Cropping in pixels. - XUnit cropLeft = picFormat.CropLeft.Point; - XUnit cropRight = picFormat.CropRight.Point; - XUnit cropTop = picFormat.CropTop.Point; - XUnit cropBottom = picFormat.CropBottom.Point; - formatInfo.CropX = (int)(horzRes * cropLeft.Inch); - formatInfo.CropY = (int)(vertRes * cropTop.Inch); - formatInfo.CropWidth -= (int)(horzRes * ((XUnit)(cropLeft + cropRight)).Inch); - formatInfo.CropHeight -= (int)(vertRes * ((XUnit)(cropTop + cropBottom)).Inch); - - //Scaled cropping of the height and width. - double xScale = resultWidth / inherentWidth; - double yScale = resultHeight / inherentHeight; - - cropLeft = xScale * cropLeft; - cropRight = xScale * cropRight; - cropTop = yScale * cropTop; - cropBottom = yScale * cropBottom; - - resultHeight = resultHeight - cropTop - cropBottom; - resultWidth = resultWidth - cropLeft - cropRight; - } - if (resultHeight <= 0 || resultWidth <= 0) - { - formatInfo.Width = XUnit.FromCentimeter(2.5); - formatInfo.Height = XUnit.FromCentimeter(2.5); - Debug.WriteLine(Messages2.EmptyImageSize); - _failure = ImageFailure.EmptySize; - } - else - { - formatInfo.Width = resultWidth; - formatInfo.Height = resultHeight; - } - } - catch (Exception ex) - { - Debug.WriteLine(Messages2.ImageNotReadable(_image.Name, ex.Message)); - formatInfo.Failure = ImageFailure.NotRead; - } - finally - { - if (xImage != null) - xImage.Dispose(); - } - } - } - if (formatInfo.Failure != ImageFailure.None) - { - if (!_image._width.IsNull) - formatInfo.Width = _image.Width.Point; - else - formatInfo.Width = XUnit.FromCentimeter(2.5); - - if (!_image._height.IsNull) - formatInfo.Height = _image.Height.Point; - else - formatInfo.Height = XUnit.FromCentimeter(2.5); - } - } - - XImage CreateXImage(string uri) - { - if (uri.StartsWith("base64:")) - { - string base64 = uri.Substring("base64:".Length); - byte[] bytes = Convert.FromBase64String(base64); + /// + /// Renders images. + /// + internal class ImageRenderer : ShapeRenderer + { + internal ImageRenderer(XGraphics gfx, Image image, FieldInfos fieldInfos) + : base(gfx, image, fieldInfos) + { + _image = image; + ImageRenderInfo renderInfo = new ImageRenderInfo(); + renderInfo.DocumentObject = _shape; + _renderInfo = renderInfo; + } + + internal ImageRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos) + : base(gfx, renderInfo, fieldInfos) + { + _image = (Image)renderInfo.DocumentObject; + } + + internal override void Format(Area area, FormatInfo previousFormatInfo) + { + _imageFilePath = _image.GetFilePath(_documentRenderer.WorkingDirectory); + // The Image is stored in the string if path starts with "base64:", otherwise we check whether the file exists. + if (!_imageFilePath.StartsWith("base64:") && + !XImage.ExistsFile(_imageFilePath)) + { + _failure = ImageFailure.FileNotFound; + Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning"); + } + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + formatInfo.Failure = _failure; + formatInfo.ImagePath = _imageFilePath; + CalculateImageDimensions(); + base.Format(area, previousFormatInfo); + } + + protected override XUnit ShapeHeight + { + get + { + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + return formatInfo.Height + _lineFormatRenderer.GetWidth(); + } + } + + protected override XUnit ShapeWidth + { + get + { + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + return formatInfo.Width + _lineFormatRenderer.GetWidth(); + } + } + + internal override void Render() + { + RenderFilling(); + + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + Area contentArea = _renderInfo.LayoutInfo.ContentArea; + XRect destRect = new XRect(contentArea.X, contentArea.Y, formatInfo.Width, formatInfo.Height); + + if (formatInfo.Failure == ImageFailure.None) + { + XImage xImage = null; + try + { + XRect srcRect = new XRect(formatInfo.CropX, formatInfo.CropY, formatInfo.CropWidth, formatInfo.CropHeight); + //xImage = XImage.FromFile(formatInfo.ImagePath); + xImage = CreateXImage(formatInfo.ImagePath); + _gfx.DrawImage(xImage, destRect, srcRect, XGraphicsUnit.Point); //Pixel. + } + catch (Exception) + { + if (_image._renderOnFailure.IsNull || _image._renderOnFailure.Value) + RenderFailureImage(destRect); + } + finally + { + if (xImage != null) + xImage.Dispose(); + } + } + else + { + if (_image._renderOnFailure.IsNull || _image._renderOnFailure.Value) + RenderFailureImage(destRect); + } + + RenderLine(); + } + + void RenderFailureImage(XRect destRect) + { + _gfx.DrawRectangle(XBrushes.LightGray, destRect); + string failureString; + ImageFormatInfo formatInfo = (ImageFormatInfo)RenderInfo.FormatInfo; + + switch (formatInfo.Failure) + { + case ImageFailure.EmptySize: + failureString = Messages2.DisplayEmptyImageSize; + break; + + case ImageFailure.FileNotFound: + failureString = Messages2.DisplayImageFileNotFound; + break; + + case ImageFailure.InvalidType: + failureString = Messages2.DisplayInvalidImageType; + break; + + case ImageFailure.NotRead: + default: + failureString = Messages2.DisplayImageNotRead; + break; + } + + // Create stub font + XFont font = new XFont("Courier New", 8); + _gfx.DrawString(failureString, font, XBrushes.Red, destRect, XStringFormats.Center); + } + + private void CalculateImageDimensions() + { + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + + if (formatInfo.Failure == ImageFailure.None) + { + XImage xImage = null; + try + { + //xImage = XImage.FromFile(_imageFilePath); + xImage = CreateXImage(_imageFilePath); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine(Messages2.InvalidImageType(ex.Message)); + formatInfo.Failure = ImageFailure.InvalidType; + } + + if (formatInfo.Failure == ImageFailure.None) + { + try + { + XUnit usrWidth = _image.Width.Point; + XUnit usrHeight = _image.Height.Point; + bool usrWidthSet = !_image._width.IsNull; + bool usrHeightSet = !_image._height.IsNull; + + XUnit resultWidth = usrWidth; + XUnit resultHeight = usrHeight; + + Debug.Assert(xImage != null); + double xPixels = xImage.PixelWidth; + bool usrResolutionSet = !_image._resolution.IsNull; + + double horzRes = usrResolutionSet ? _image.Resolution : xImage.HorizontalResolution; + double vertRes = usrResolutionSet ? _image.Resolution : xImage.VerticalResolution; + + // ReSharper disable CompareOfFloatsByEqualityOperator + if (horzRes == 0 && vertRes == 0) + { + horzRes = 72; + vertRes = 72; + } + else if (horzRes == 0) + { + Debug.Assert(false, "How can this be?"); + horzRes = 72; + } + else if (vertRes == 0) + { + Debug.Assert(false, "How can this be?"); + vertRes = 72; + } + // ReSharper restore CompareOfFloatsByEqualityOperator + + XUnit inherentWidth = XUnit.FromInch(xPixels / horzRes); + double yPixels = xImage.PixelHeight; + XUnit inherentHeight = XUnit.FromInch(yPixels / vertRes); + + //bool lockRatio = _image.IsNull("LockAspectRatio") ? true : _image.LockAspectRatio; + bool lockRatio = _image._lockAspectRatio.IsNull || _image.LockAspectRatio; + + double scaleHeight = _image.ScaleHeight; + double scaleWidth = _image.ScaleWidth; + //bool scaleHeightSet = !_image.IsNull("ScaleHeight"); + //bool scaleWidthSet = !_image.IsNull("ScaleWidth"); + bool scaleHeightSet = !_image._scaleHeight.IsNull; + bool scaleWidthSet = !_image._scaleWidth.IsNull; + + if (lockRatio && !(scaleHeightSet && scaleWidthSet)) + { + if (usrWidthSet && !usrHeightSet) + { + resultHeight = inherentHeight / inherentWidth * usrWidth; + } + else if (usrHeightSet && !usrWidthSet) + { + resultWidth = inherentWidth / inherentHeight * usrHeight; + } + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + else if (!usrHeightSet && !usrWidthSet) + { + resultHeight = inherentHeight; + resultWidth = inherentWidth; + } + + if (scaleHeightSet) + { + resultHeight = resultHeight * scaleHeight; + resultWidth = resultWidth * scaleHeight; + } + if (scaleWidthSet) + { + resultHeight = resultHeight * scaleWidth; + resultWidth = resultWidth * scaleWidth; + } + } + else + { + if (!usrHeightSet) + resultHeight = inherentHeight; + + if (!usrWidthSet) + resultWidth = inherentWidth; + + if (scaleHeightSet) + resultHeight = resultHeight * scaleHeight; + if (scaleWidthSet) + resultWidth = resultWidth * scaleWidth; + } + + formatInfo.CropWidth = (int)xPixels; + formatInfo.CropHeight = (int)yPixels; + if (_image._pictureFormat != null && !_image._pictureFormat.IsNull()) + { + PictureFormat picFormat = _image.PictureFormat; + //Cropping in pixels. + XUnit cropLeft = picFormat.CropLeft.Point; + XUnit cropRight = picFormat.CropRight.Point; + XUnit cropTop = picFormat.CropTop.Point; + XUnit cropBottom = picFormat.CropBottom.Point; + formatInfo.CropX = (int)(horzRes * cropLeft.Inch); + formatInfo.CropY = (int)(vertRes * cropTop.Inch); + formatInfo.CropWidth -= (int)(horzRes * ((XUnit)(cropLeft + cropRight)).Inch); + formatInfo.CropHeight -= (int)(vertRes * ((XUnit)(cropTop + cropBottom)).Inch); + + //Scaled cropping of the height and width. + double xScale = resultWidth / inherentWidth; + double yScale = resultHeight / inherentHeight; + + cropLeft = xScale * cropLeft; + cropRight = xScale * cropRight; + cropTop = yScale * cropTop; + cropBottom = yScale * cropBottom; + + resultHeight = resultHeight - cropTop - cropBottom; + resultWidth = resultWidth - cropLeft - cropRight; + } + if (resultHeight <= 0 || resultWidth <= 0) + { + formatInfo.Width = XUnit.FromCentimeter(2.5); + formatInfo.Height = XUnit.FromCentimeter(2.5); + Debug.WriteLine(Messages2.EmptyImageSize); + _failure = ImageFailure.EmptySize; + } + else + { + formatInfo.Width = resultWidth; + formatInfo.Height = resultHeight; + } + } + catch (Exception ex) + { + Debug.WriteLine(Messages2.ImageNotReadable(_image.Name, ex.Message)); + formatInfo.Failure = ImageFailure.NotRead; + } + finally + { + if (xImage != null) + xImage.Dispose(); + } + } + } + if (formatInfo.Failure != ImageFailure.None) + { + if (!_image._width.IsNull) + formatInfo.Width = _image.Width.Point; + else + formatInfo.Width = XUnit.FromCentimeter(2.5); + + if (!_image._height.IsNull) + formatInfo.Height = _image.Height.Point; + else + formatInfo.Height = XUnit.FromCentimeter(2.5); + } + } + + XImage CreateXImage(string uri) + { + if (uri.StartsWith("base64:")) + { + string base64 = uri.Substring("base64:".Length); + byte[] bytes = Convert.FromBase64String(base64); #if WPF || CORE_WITH_GDI || GDI - // WPF stores a reference to the stream internally. We must not destroy the stream here, otherwise rendering the PDF will fail. - // Same for GDI. CORE currently uses the GDI implementation. - // We have to rely on the garbage collector to properly dispose the MemoryStream. - { - Stream stream = new MemoryStream(bytes); - XImage image = XImage.FromStream(stream); - return image; - } + // WPF stores a reference to the stream internally. We must not destroy the stream here, otherwise rendering the PDF will fail. + // Same for GDI. CORE currently uses the GDI implementation. + // We have to rely on the garbage collector to properly dispose the MemoryStream. + { + Stream stream = new MemoryStream(bytes); + XImage image = XImage.FromStream(stream); + return image; + } #else using (Stream stream = new MemoryStream(bytes)) { @@ -356,12 +360,12 @@ XImage CreateXImage(string uri) return image; } #endif - } - return XImage.FromFile(uri); - } - - readonly Image _image; - string _imageFilePath; - ImageFailure _failure; - } + } + return XImage.FromFile(uri); + } + + readonly Image _image; + string _imageFilePath; + ImageFailure _failure; + } } From 7fee56a6a600aade8ffa907ce1bb965a125c46d1 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Tue, 4 Aug 2020 18:36:20 +0200 Subject: [PATCH 19/25] barcode rendering --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 1 - .../DocumentObjectModel.Shapes/Barcode.cs | 100 ++++- .../enums/BarcodeType.cs | 8 +- .../Properties/AssemblyInfo.cs | 2 +- .../MigraDoc.Rendering-gdi.csproj | 7 + .../MigraDoc.Rendering-gdi/packages.config | 4 + .../MigraDoc.Rendering-wpf.csproj | 3 + .../MigraDoc.Rendering.csproj | 5 + .../Rendering/BarcodeRenderer.cs | 392 ++++++++++++++++++ .../Rendering/ParagraphRenderer.cs | 5 +- .../MigraDoc.Rendering/Rendering/Renderer.cs | 4 + .../src/MigraDoc.Rendering/packages.config | 4 + 12 files changed, 528 insertions(+), 7 deletions(-) create mode 100644 MigraDoc/src/MigraDoc.Rendering-gdi/packages.config create mode 100644 MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs create mode 100644 MigraDoc/src/MigraDoc.Rendering/packages.config diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index 301f868..c493b45 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -1133,7 +1133,6 @@ private void ParseTextFrame(DocumentElements elements) } } - // TODO private void ParseBarcode(DocumentElements elements) { // Syntax: diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs index 42cd756..49d0ccb 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs @@ -120,28 +120,31 @@ public string Code /// /// ??? /// - public double LineRatio + /*public double LineRatio { get { return _lineRatio.Value; } set { _lineRatio.Value = value; } } [DV] internal NDouble _lineRatio = NDouble.NullValue; + */ /// /// ??? /// - public double LineHeight + /*public double LineHeight { get { return _lineHeight.Value; } set { _lineHeight.Value = value; } } [DV] internal NDouble _lineHeight = NDouble.NullValue; + */ /// /// ??? /// + /* public double NarrowLineWidth { get { return _narrowLineWidth.Value; } @@ -149,6 +152,93 @@ public double NarrowLineWidth } [DV] internal NDouble _narrowLineWidth = NDouble.NullValue; + */ + + /// + /// Gets or sets the ScaleWidth of the image. + /// If the Width is set to, the resulting image width is ScaleWidth * Width. + /// + public double ScaleWidth + { + get { return _scaleWidth.Value; } + set { _scaleWidth.Value = value; } + } + [DV] + internal NDouble _scaleWidth = NDouble.NullValue; + + /// + /// Gets or sets the ScaleHeight of the image. + /// If the Height is set too, the resulting image height is ScaleHeight * Height. + /// + public double ScaleHeight + { + get { return _scaleHeight.Value; } + set { _scaleHeight.Value = value; } + } + [DV] + internal NDouble _scaleHeight = NDouble.NullValue; + + /// + /// Gets or sets whether the AspectRatio of the image is kept unchanged. + /// If both Width and Height are set, this property is ignored. + /// + public bool LockAspectRatio + { + get { return _lockAspectRatio.Value; } + set { _lockAspectRatio.Value = value; } + } + [DV] + internal NBool _lockAspectRatio = NBool.NullValue; + + /// + /// Gets or sets the PictureFormat for the image + /// + public PictureFormat PictureFormat + { + get { return _pictureFormat ?? (_pictureFormat = new PictureFormat(this)); } + set + { + SetParent(value); + _pictureFormat = value; + } + } + [DV] + internal PictureFormat _pictureFormat; + + /// + /// Gets or sets a user defined resolution for the image in dots per inch. + /// + public double Resolution + { + get { return _resolution.Value; } + set { _resolution.Value = value; } + } + [DV] + internal NDouble _resolution = NDouble.NullValue; + + /* + /// + /// Gets or sets a the width of the barcode, in pixels. + /// + public int BarcodeWidth + { + get { return _barcodeWidth.Value; } + set { _barcodeWidth.Value = value; } + } + [DV] + internal NInt _barcodeWidth = NInt.NullValue; + + /// + /// Gets or sets a the height of the barcode, in pixels. + /// + public int BarcodeHeight + { + get { return _barcodeHeight.Value; } + set { _barcodeHeight.Value = value; } + } + [DV] + internal NInt _barcodeHeight = NInt.NullValue; + */ #endregion #region Internal @@ -174,12 +264,15 @@ internal override void Serialize(Serializer serializer) serializer.WriteSimpleAttribute("Text", Text); if (!_type.IsNull) serializer.WriteSimpleAttribute("Type", Type); + + /* if (!_lineRatio.IsNull) serializer.WriteSimpleAttribute("LineRatio", LineRatio); if (!_lineHeight.IsNull) serializer.WriteSimpleAttribute("LineHeight", LineHeight); if (!_narrowLineWidth.IsNull) serializer.WriteSimpleAttribute("NarrowLineWidth", NarrowLineWidth); + */ serializer.EndAttributes(pos); } @@ -206,12 +299,15 @@ internal override void Serialize(XmlSerializer serializer) serializer.WriteSimpleAttribute("Text", Text); if (!_type.IsNull) serializer.WriteSimpleAttribute("Type", Type); + + /* if (!_lineRatio.IsNull) serializer.WriteSimpleAttribute("LineRatio", LineRatio); if (!_lineHeight.IsNull) serializer.WriteSimpleAttribute("LineHeight", LineHeight); if (!_narrowLineWidth.IsNull) serializer.WriteSimpleAttribute("NarrowLineWidth", NarrowLineWidth); + */ serializer.WriteEndElement(); // barcode diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/enums/BarcodeType.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/enums/BarcodeType.cs index 41487ca..0397241 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/enums/BarcodeType.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/enums/BarcodeType.cs @@ -52,6 +52,12 @@ public enum BarcodeType /// /// Barcode "Code 128" /// - Barcode128 + Barcode128, + + /// + /// QR Code + /// + QRCode + } } diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs index d6ee01f..c120ffa 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ [assembly: AssemblyTitle(VersionInfo.Title)] [assembly: AssemblyDescription(VersionInfo.Description)] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany(VersionInfo.Company + "(xmlddl build)")] +[assembly: AssemblyCompany(VersionInfo.Company + "(xmlddl/qrcode build)")] #if DEBUG [assembly: AssemblyProduct(VersionInfo.Product + " (Debug Build)")] #else diff --git a/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj b/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj index 74a2220..9afa4b1 100644 --- a/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj +++ b/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj @@ -118,6 +118,9 @@ {cfdb7d46-ea8d-47de-b10a-9e755a1b48ba} PdfSharp.Charting-gdi + + ..\packages\ZXing.Net.0.16.5\lib\net20\zxing.dll + @@ -162,6 +165,9 @@ Rendering\Area.cs + + Rendering\BarcodeRenderer.cs + Rendering\BordersRenderer.cs @@ -345,6 +351,7 @@ StrongnameKey.snk + diff --git a/MigraDoc/src/MigraDoc.Rendering-gdi/packages.config b/MigraDoc/src/MigraDoc.Rendering-gdi/packages.config new file mode 100644 index 0000000..d397372 --- /dev/null +++ b/MigraDoc/src/MigraDoc.Rendering-gdi/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj b/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj index 4e8017c..d7be8ec 100644 --- a/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj +++ b/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj @@ -158,6 +158,9 @@ Rendering\Area.cs + + Rendering\BarcodeRenderer.cs + Rendering\BordersRenderer.cs diff --git a/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj b/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj index f6c2489..1a33e1d 100644 --- a/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj +++ b/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj @@ -41,6 +41,9 @@ + + ..\packages\ZXing.Net.0.16.5\lib\net20\zxing.dll + @@ -85,6 +88,7 @@ + @@ -131,6 +135,7 @@ + diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs new file mode 100644 index 0000000..504d564 --- /dev/null +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs @@ -0,0 +1,392 @@ +#region MigraDoc - Creating Documents on the Fly +// +// Authors: +// Klaus Potzesny +// +// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany) +// +// http://www.pdfsharp.com +// http://www.migradoc.com +// http://sourceforge.net/projects/pdfsharp +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.IO; +using System.Diagnostics; +using PdfSharp.Drawing; +using MigraDoc.DocumentObjectModel.Shapes; +using MigraDoc.Rendering.Resources; + +#if CORE_WITH_GDI || GDI +using System.Drawing.Imaging; +using ZXing; +using ZXing.Common; +#endif + +namespace MigraDoc.Rendering +{ + /// + /// Renders images. + /// + internal class BarcodeRenderer : ShapeRenderer + { + internal BarcodeRenderer(XGraphics gfx, Barcode barcode, FieldInfos fieldInfos) + : base(gfx, barcode, fieldInfos) + { + _barcode = barcode; + ImageRenderInfo renderInfo = new ImageRenderInfo(); + renderInfo.DocumentObject = _shape; + _renderInfo = renderInfo; + } + + internal BarcodeRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos) + : base(gfx, renderInfo, fieldInfos) + { + _barcode = (Barcode)renderInfo.DocumentObject; + } + + internal override void Format(Area area, FormatInfo previousFormatInfo) + { + + //_imageFilePath = _image.GetFilePath(_documentRenderer.WorkingDirectory); + + // The Image is stored in the string if path starts with "base64:", otherwise we check whether the file exists. + /*if (!_imageFilePath.StartsWith("base64:") && + !XImage.ExistsFile(_imageFilePath)) + { + _failure = ImageFailure.FileNotFound; + Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning"); + }*/ + + //ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + + // formatInfo.Failure = _failure; + // formatInfo.ImagePath = _imageFilePath; + + CalculateImageDimensions(); + base.Format(area, previousFormatInfo); + + } + + protected override XUnit ShapeHeight + { + get + { + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + return formatInfo.Height + _lineFormatRenderer.GetWidth(); + } + } + + protected override XUnit ShapeWidth + { + get + { + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + return formatInfo.Width + _lineFormatRenderer.GetWidth(); + } + } + + internal override void Render() + { + RenderFilling(); + + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + Area contentArea = _renderInfo.LayoutInfo.ContentArea; + XRect destRect = new XRect(contentArea.X, contentArea.Y, formatInfo.Width, formatInfo.Height); + + if (formatInfo.Failure == ImageFailure.None) + { + XImage xImage = null; + try + { + XRect srcRect = new XRect(formatInfo.CropX, formatInfo.CropY, formatInfo.CropWidth, formatInfo.CropHeight); + //xImage = XImage.FromFile(formatInfo.ImagePath); + xImage = CreateXImage(/*formatInfo.ImagePath*/); + _gfx.DrawImage(xImage, destRect, srcRect, XGraphicsUnit.Point); //Pixel. + } + catch (Exception) + { + //if (_image._renderOnFailure.IsNull || _image._renderOnFailure.Value) + // RenderFailureImage(destRect); + } + finally + { + if (xImage != null) + xImage.Dispose(); + } + } + else + { + //if (_image._renderOnFailure.IsNull || _image._renderOnFailure.Value) + // RenderFailureImage(destRect); + } + + RenderLine(); + } + + private void CalculateImageDimensions() + { + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + + if (formatInfo.Failure == ImageFailure.None) + { + XImage xImage = null; + + try + { + xImage = CreateXImage(); + + } + catch (InvalidOperationException ex) + { + Debug.WriteLine(Messages2.InvalidImageType(ex.Message)); + formatInfo.Failure = ImageFailure.InvalidType; + } + + if (formatInfo.Failure == ImageFailure.None) + { + try + { + XUnit usrWidth = _barcode.Width.Point; + XUnit usrHeight = _barcode.Height.Point; + bool usrWidthSet = !_barcode._width.IsNull; + bool usrHeightSet = !_barcode._height.IsNull; + + XUnit resultWidth = usrWidth; + XUnit resultHeight = usrHeight; + + Debug.Assert(xImage != null); + double xPixels = xImage.PixelWidth; + bool usrResolutionSet = !_barcode._resolution.IsNull; + + double horzRes = usrResolutionSet ? _barcode.Resolution : xImage.HorizontalResolution; + double vertRes = usrResolutionSet ? _barcode.Resolution : xImage.VerticalResolution; + + // ReSharper disable CompareOfFloatsByEqualityOperator + if (horzRes == 0 && vertRes == 0) + { + horzRes = 72; + vertRes = 72; + } + else if (horzRes == 0) + { + Debug.Assert(false, "How can this be?"); + horzRes = 72; + } + else if (vertRes == 0) + { + Debug.Assert(false, "How can this be?"); + vertRes = 72; + } + // ReSharper restore CompareOfFloatsByEqualityOperator + + XUnit inherentWidth = XUnit.FromInch(xPixels / horzRes); + double yPixels = xImage.PixelHeight; + XUnit inherentHeight = XUnit.FromInch(yPixels / vertRes); + + //bool lockRatio = _image.IsNull("LockAspectRatio") ? true : _image.LockAspectRatio; + bool lockRatio = _barcode._lockAspectRatio.IsNull || _barcode.LockAspectRatio; + + double scaleHeight = _barcode.ScaleHeight; + double scaleWidth = _barcode.ScaleWidth; + //bool scaleHeightSet = !_image.IsNull("ScaleHeight"); + //bool scaleWidthSet = !_image.IsNull("ScaleWidth"); + bool scaleHeightSet = !_barcode._scaleHeight.IsNull; + bool scaleWidthSet = !_barcode._scaleWidth.IsNull; + + if (lockRatio && !(scaleHeightSet && scaleWidthSet)) + { + if (usrWidthSet && !usrHeightSet) + { + resultHeight = inherentHeight / inherentWidth * usrWidth; + } + else if (usrHeightSet && !usrWidthSet) + { + resultWidth = inherentWidth / inherentHeight * usrHeight; + } + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + else if (!usrHeightSet && !usrWidthSet) + { + resultHeight = inherentHeight; + resultWidth = inherentWidth; + } + + if (scaleHeightSet) + { + resultHeight = resultHeight * scaleHeight; + resultWidth = resultWidth * scaleHeight; + } + if (scaleWidthSet) + { + resultHeight = resultHeight * scaleWidth; + resultWidth = resultWidth * scaleWidth; + } + } + else + { + if (!usrHeightSet) + resultHeight = inherentHeight; + + if (!usrWidthSet) + resultWidth = inherentWidth; + + if (scaleHeightSet) + resultHeight = resultHeight * scaleHeight; + if (scaleWidthSet) + resultWidth = resultWidth * scaleWidth; + } + + formatInfo.CropWidth = (int)xPixels; + formatInfo.CropHeight = (int)yPixels; + if (_barcode._pictureFormat != null && !_barcode._pictureFormat.IsNull()) + { + PictureFormat picFormat = _barcode.PictureFormat; + //Cropping in pixels. + XUnit cropLeft = picFormat.CropLeft.Point; + XUnit cropRight = picFormat.CropRight.Point; + XUnit cropTop = picFormat.CropTop.Point; + XUnit cropBottom = picFormat.CropBottom.Point; + formatInfo.CropX = (int)(horzRes * cropLeft.Inch); + formatInfo.CropY = (int)(vertRes * cropTop.Inch); + formatInfo.CropWidth -= (int)(horzRes * ((XUnit)(cropLeft + cropRight)).Inch); + formatInfo.CropHeight -= (int)(vertRes * ((XUnit)(cropTop + cropBottom)).Inch); + + //Scaled cropping of the height and width. + double xScale = resultWidth / inherentWidth; + double yScale = resultHeight / inherentHeight; + + cropLeft = xScale * cropLeft; + cropRight = xScale * cropRight; + cropTop = yScale * cropTop; + cropBottom = yScale * cropBottom; + + resultHeight = resultHeight - cropTop - cropBottom; + resultWidth = resultWidth - cropLeft - cropRight; + } + if (resultHeight <= 0 || resultWidth <= 0) + { + formatInfo.Width = XUnit.FromCentimeter(2.5); + formatInfo.Height = XUnit.FromCentimeter(2.5); + Debug.WriteLine(Messages2.EmptyImageSize); + //_failure = ImageFailure.EmptySize; + } + else + { + formatInfo.Width = resultWidth; + formatInfo.Height = resultHeight; + } + } + catch (Exception ex) + { + Debug.WriteLine(Messages2.ImageNotReadable(_barcode.Code, ex.Message)); + formatInfo.Failure = ImageFailure.NotRead; + } + finally + { + if (xImage != null) + xImage.Dispose(); + } + } + } + if (formatInfo.Failure != ImageFailure.None) + { + if (!_barcode._width.IsNull) + formatInfo.Width = _barcode.Width.Point; + else + formatInfo.Width = XUnit.FromCentimeter(2.5); + + if (!_barcode._height.IsNull) + formatInfo.Height = _barcode.Height.Point; + else + formatInfo.Height = XUnit.FromCentimeter(2.5); + } + } + + XImage CreateXImage() + { + + XImage image = null; + +#if CORE_WITH_GDI || GDI + + if (String.IsNullOrEmpty(_barcode.Code)) + throw new ArgumentNullException("Code"); + + BarcodeFormat format = BarcodeFormat.All_1D; + + switch (_barcode.Type) + { + case BarcodeType.Barcode25i: + format = BarcodeFormat.ITF; + break; + case BarcodeType.Barcode39: + format = BarcodeFormat.CODE_39; + break; + case BarcodeType.Barcode128: + format = BarcodeFormat.CODE_128; + break; + case BarcodeType.QRCode: + format = BarcodeFormat.QR_CODE; + break; + default: + break; + } + + var options = new EncodingOptions(); + + // hack + const float resolution = 200; + int horzPixels = (int)(_barcode.Width.Inch * resolution); + int vertPixels = (int)(_barcode.Height.Inch * resolution); + + options.Width = horzPixels; + options.Height = vertPixels; + + var writer = new BarcodeWriter + { + Format = format, + Options = options + }; + + var bmp = writer.Write(_barcode.Code); + + string fileName = Path.GetTempFileName(); + + bmp.SetResolution(resolution, resolution); + bmp.Save(fileName, ImageFormat.Png); + + image = XImage.FromFile(fileName); + + /* + if (File.Exists(fileName)) + File.Delete(fileName); + */ + +#endif + return image; + + } + + readonly Barcode _barcode; + //string _imageFilePath; + //ImageFailure _failure; + } +} diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs index 5f441de..1d11b00 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs @@ -1543,14 +1543,15 @@ FormatResult FormatElement(DocumentObject docObj) return FormatPageRefField((PageRefField)docObj); case "Image": - return FormatImage((Image)docObj); + case "Barcode": + return FormatImage(/*(Image)docObj*/); default: return FormatResult.Continue; } } - FormatResult FormatImage(Image image) + FormatResult FormatImage(/*Image image*/) { XUnit width = CurrentImageRenderInfo.LayoutInfo.ContentArea.Width; return FormatAsWord(width); diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/Renderer.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/Renderer.cs index 0a00e0d..12b9521 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/Renderer.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/Renderer.cs @@ -161,6 +161,8 @@ internal static Renderer Create(XGraphics gfx, DocumentRenderer documentRenderer renderer = new ChartRenderer(gfx, (Chart)documentObject, fieldInfos); else if (documentObject is Image) renderer = new ImageRenderer(gfx, (Image)documentObject, fieldInfos); + else if (documentObject is Barcode) + renderer = new BarcodeRenderer(gfx, (Barcode)documentObject, fieldInfos); if (renderer != null) renderer._documentRenderer = documentRenderer; @@ -194,6 +196,8 @@ internal static Renderer Create(XGraphics gfx, DocumentRenderer documentRenderer // renderer = new ChartRenderer(gfx, renderInfo, fieldInfos); else if (renderInfo.DocumentObject is Image) renderer = new ImageRenderer(gfx, renderInfo, fieldInfos); + else if (renderInfo.DocumentObject is Barcode) + renderer = new BarcodeRenderer(gfx, renderInfo, fieldInfos); if (renderer != null) renderer._documentRenderer = documentRenderer; diff --git a/MigraDoc/src/MigraDoc.Rendering/packages.config b/MigraDoc/src/MigraDoc.Rendering/packages.config new file mode 100644 index 0000000..d397372 --- /dev/null +++ b/MigraDoc/src/MigraDoc.Rendering/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 0bff673d6ecf0f2da37cfe613ee798e71a0e3ff0 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Tue, 4 Aug 2020 18:40:22 +0200 Subject: [PATCH 20/25] doc fix --- .../DocumentObjectModel.Shapes/Barcode.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs index 49d0ccb..8b7ca21 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs @@ -117,10 +117,11 @@ public string Code [DV] internal NString _code = NString.NullValue; + /* /// /// ??? /// - /*public double LineRatio + public double LineRatio { get { return _lineRatio.Value; } set { _lineRatio.Value = value; } @@ -129,10 +130,11 @@ public string Code internal NDouble _lineRatio = NDouble.NullValue; */ + /* /// /// ??? /// - /*public double LineHeight + public double LineHeight { get { return _lineHeight.Value; } set { _lineHeight.Value = value; } @@ -141,10 +143,10 @@ public string Code internal NDouble _lineHeight = NDouble.NullValue; */ + /* /// /// ??? /// - /* public double NarrowLineWidth { get { return _narrowLineWidth.Value; } From 34a9759ef51c49c773a9e3024b3a1b4b7a69f950 Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Wed, 5 Aug 2020 15:04:18 +0200 Subject: [PATCH 21/25] support barcode elements inside a paragraph --- .../DocumentObjectModel.IO.Xml/DdlParser.cs | 21 +++++++++++-------- .../DocumentObjectModel.Shapes/Barcode.cs | 6 ++++++ .../DocumentObjectModel/ParagraphElements.cs | 12 +++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs index c493b45..d6866fe 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO.Xml/DdlParser.cs @@ -434,7 +434,7 @@ private DocumentElements ParseDocumentElements(DocumentElements elements, XmlSym break; case XmlSymbol.Image: - ParseImage(elements.AddImage(""), false); + ParseImage(elements.AddImage("") /*, false */); break; case XmlSymbol.Chart: @@ -442,7 +442,7 @@ private DocumentElements ParseDocumentElements(DocumentElements elements, XmlSym break; case XmlSymbol.Barcode: - ParseBarcode(elements); + ParseBarcode(elements.AddBarcode()); break; default: @@ -560,7 +560,11 @@ private void ParseFormattedText(ParagraphElements elements) MoveNext(false); break; - case XmlSymbol.Bold: + case XmlSymbol.Barcode: + ParseBarcode(elements.AddBarcode()); + break; + + case XmlSymbol.Bold: ParseBoldItalicEtc(elements.AddFormattedText(TextFormat.Bold), XmlSymbol.Bold); break; @@ -589,8 +593,7 @@ private void ParseFormattedText(ParagraphElements elements) break; case XmlSymbol.Image: - ParseImage(elements.AddImage(""), true); - + ParseImage(elements.AddImage("")/*, true*/); break; case XmlSymbol.Field: @@ -1074,7 +1077,7 @@ private void ParseCell(Cell cell) /// /// Parses the keyword «\image». /// - private void ParseImage(Image image, bool paragraphContent) + private void ParseImage(Image image /*, bool paragraphContent*/) { // Future syntax by example // \image("Name") @@ -1133,7 +1136,7 @@ private void ParseTextFrame(DocumentElements elements) } } - private void ParseBarcode(DocumentElements elements) + private void ParseBarcode(/*DocumentElements elements*/ Barcode barcode) { // Syntax: // 1. \barcode(Code) @@ -1145,7 +1148,7 @@ private void ParseBarcode(DocumentElements elements) { AssertSymbol(XmlSymbol.Barcode); - Barcode barcode = elements.AddBarcode(); + //Barcode barcode = elements.AddBarcode(); ParseAttributes(barcode); @@ -1324,7 +1327,7 @@ private void ParseArea(TextArea area) case XmlSymbol.Image: Image image = new Image(); - ParseImage(image, false); + ParseImage(image/*, false */); area.Elements.Add(image); break; diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs index 8b7ca21..7d82a31 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs @@ -84,6 +84,7 @@ public BarcodeType Type [DV(Type = typeof(BarcodeType))] internal NEnum _type = NEnum.NullValue(typeof(BarcodeType)); + /* /// /// Gets or sets a value indicating whether bars shall appear beside the barcode /// @@ -94,6 +95,7 @@ public bool BearerBars } [DV] internal NBool _bearerBars = NBool.NullValue; + */ /// /// Gets or sets the a value indicating whether the barcode's code is rendered. @@ -260,8 +262,10 @@ internal override void Serialize(Serializer serializer) if (!_orientation.IsNull) serializer.WriteSimpleAttribute("Orientation", Orientation); + /* if (!_bearerBars.IsNull) serializer.WriteSimpleAttribute("BearerBars", BearerBars); + */ if (!_text.IsNull) serializer.WriteSimpleAttribute("Text", Text); if (!_type.IsNull) @@ -295,8 +299,10 @@ internal override void Serialize(XmlSerializer serializer) if (!_orientation.IsNull) serializer.WriteSimpleAttribute("Orientation", Orientation); + /* if (!_bearerBars.IsNull) serializer.WriteSimpleAttribute("BearerBars", BearerBars); + */ if (!_text.IsNull) serializer.WriteSimpleAttribute("Text", Text); if (!_type.IsNull) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs index 247d64d..604677f 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs @@ -421,6 +421,16 @@ public Image AddImage(string name) return image; } + /// + /// Adds a new Barcode. + /// + public Barcode AddBarcode() + { + Barcode barcode = new Barcode(); + Add(barcode); + return barcode; + } + /// /// /// @@ -462,6 +472,8 @@ internal override Meta Meta { get { return _meta ?? (_meta = new Meta(typeof(ParagraphElements))); } } + + static Meta _meta; #endregion } From 1bba5e0fb8efe3b3370f122ab795db48874dd98a Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Wed, 5 Aug 2020 16:38:26 +0200 Subject: [PATCH 22/25] barcode rendering fix --- .../DocumentObjectModel.Shapes/Barcode.cs | 45 ++-- .../Properties/AssemblyInfo.cs | 4 +- .../Rendering/BarcodeRenderer.cs | 233 +++--------------- .../Rendering/ImageFormatInfo.cs | 1 + 4 files changed, 60 insertions(+), 223 deletions(-) diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs index 7d82a31..2bf9a6e 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs @@ -62,6 +62,8 @@ internal Barcode(DocumentObject parent) : base(parent) { } #endregion #region Properties + + /* /// /// Gets or sets the text orientation for the barcode content. /// @@ -72,6 +74,7 @@ public TextOrientation Orientation } [DV(Type = typeof(TextOrientation))] internal NEnum _orientation = NEnum.NullValue(typeof(TextOrientation)); + */ /// /// Gets or sets the type of the barcode. @@ -97,6 +100,7 @@ public bool BearerBars internal NBool _bearerBars = NBool.NullValue; */ + /* /// /// Gets or sets the a value indicating whether the barcode's code is rendered. /// @@ -107,6 +111,7 @@ public bool Text } [DV] internal NBool _text = NBool.NullValue; + */ /// /// Gets or sets code the barcode represents. @@ -158,6 +163,7 @@ public double NarrowLineWidth internal NDouble _narrowLineWidth = NDouble.NullValue; */ + /* /// /// Gets or sets the ScaleWidth of the image. /// If the Width is set to, the resulting image width is ScaleWidth * Width. @@ -169,7 +175,9 @@ public double ScaleWidth } [DV] internal NDouble _scaleWidth = NDouble.NullValue; + */ + /* /// /// Gets or sets the ScaleHeight of the image. /// If the Height is set too, the resulting image height is ScaleHeight * Height. @@ -181,7 +189,9 @@ public double ScaleHeight } [DV] internal NDouble _scaleHeight = NDouble.NullValue; + */ + /* /// /// Gets or sets whether the AspectRatio of the image is kept unchanged. /// If both Width and Height are set, this property is ignored. @@ -193,7 +203,9 @@ public bool LockAspectRatio } [DV] internal NBool _lockAspectRatio = NBool.NullValue; + */ + /* /// /// Gets or sets the PictureFormat for the image /// @@ -208,6 +220,7 @@ public PictureFormat PictureFormat } [DV] internal PictureFormat _pictureFormat; + */ /// /// Gets or sets a user defined resolution for the image in dots per inch. @@ -220,29 +233,16 @@ public double Resolution [DV] internal NDouble _resolution = NDouble.NullValue; - /* - /// - /// Gets or sets a the width of the barcode, in pixels. - /// - public int BarcodeWidth - { - get { return _barcodeWidth.Value; } - set { _barcodeWidth.Value = value; } - } - [DV] - internal NInt _barcodeWidth = NInt.NullValue; - /// - /// Gets or sets a the height of the barcode, in pixels. + /// Gets or sets whether to render a failure image. /// - public int BarcodeHeight + public bool RenderOnFailure { - get { return _barcodeHeight.Value; } - set { _barcodeHeight.Value = value; } + get { return _renderOnFailure.Value; } + set { _renderOnFailure.Value = value; } } [DV] - internal NInt _barcodeHeight = NInt.NullValue; - */ + internal NBool _renderOnFailure = NBool.NullValue; #endregion #region Internal @@ -260,14 +260,14 @@ internal override void Serialize(Serializer serializer) base.Serialize(serializer); + /* if (!_orientation.IsNull) serializer.WriteSimpleAttribute("Orientation", Orientation); - /* if (!_bearerBars.IsNull) serializer.WriteSimpleAttribute("BearerBars", BearerBars); - */ if (!_text.IsNull) serializer.WriteSimpleAttribute("Text", Text); + */ if (!_type.IsNull) serializer.WriteSimpleAttribute("Type", Type); @@ -297,14 +297,15 @@ internal override void Serialize(XmlSerializer serializer) base.Serialize(serializer); + /* if (!_orientation.IsNull) serializer.WriteSimpleAttribute("Orientation", Orientation); - /* if (!_bearerBars.IsNull) serializer.WriteSimpleAttribute("BearerBars", BearerBars); - */ if (!_text.IsNull) serializer.WriteSimpleAttribute("Text", Text); + */ + if (!_type.IsNull) serializer.WriteSimpleAttribute("Type", Type); diff --git a/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs b/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs index c120ffa..583e1f8 100644 --- a/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs +++ b/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/AssemblyInfo.cs @@ -33,11 +33,11 @@ [assembly: AssemblyTitle(VersionInfo.Title)] [assembly: AssemblyDescription(VersionInfo.Description)] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany(VersionInfo.Company + "(xmlddl/qrcode build)")] +[assembly: AssemblyCompany(VersionInfo.Company )] #if DEBUG [assembly: AssemblyProduct(VersionInfo.Product + " (Debug Build)")] #else - [assembly: AssemblyProduct(VersionInfo.Product)] + [assembly: AssemblyProduct(VersionInfo.Product +"(xmlddl/barcode build 05/08/2020)")] #endif [assembly: AssemblyCopyright(VersionInfo.Copyright)] [assembly: AssemblyTrademark(VersionInfo.Trademark)] diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs index 504d564..2343067 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/BarcodeRenderer.cs @@ -66,22 +66,23 @@ internal BarcodeRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldI internal override void Format(Area area, FormatInfo previousFormatInfo) { - //_imageFilePath = _image.GetFilePath(_documentRenderer.WorkingDirectory); + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - // The Image is stored in the string if path starts with "base64:", otherwise we check whether the file exists. - /*if (!_imageFilePath.StartsWith("base64:") && - !XImage.ExistsFile(_imageFilePath)) - { - _failure = ImageFailure.FileNotFound; - Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning"); - }*/ + if (!_barcode._height.IsNull) + formatInfo.Height = _barcode.Height.Point; + else + formatInfo.Height = XUnit.FromCentimeter(2.5); - //ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + if (!_barcode._width.IsNull) + formatInfo.Width = _barcode.Width.Point; + else + formatInfo.Width = XUnit.FromCentimeter(2.5); - // formatInfo.Failure = _failure; - // formatInfo.ImagePath = _imageFilePath; + if (!_barcode._resolution.IsNull) + formatInfo.Resolution = _barcode.Resolution; + else + formatInfo.Resolution = 72; - CalculateImageDimensions(); base.Format(area, previousFormatInfo); } @@ -118,14 +119,13 @@ internal override void Render() try { XRect srcRect = new XRect(formatInfo.CropX, formatInfo.CropY, formatInfo.CropWidth, formatInfo.CropHeight); - //xImage = XImage.FromFile(formatInfo.ImagePath); - xImage = CreateXImage(/*formatInfo.ImagePath*/); + xImage = CreateBarcode(); _gfx.DrawImage(xImage, destRect, srcRect, XGraphicsUnit.Point); //Pixel. } catch (Exception) { - //if (_image._renderOnFailure.IsNull || _image._renderOnFailure.Value) - // RenderFailureImage(destRect); + if (_barcode._renderOnFailure.IsNull || _barcode._renderOnFailure.Value) + RenderFailureImage(destRect); } finally { @@ -142,193 +142,28 @@ internal override void Render() RenderLine(); } - private void CalculateImageDimensions() + void RenderFailureImage(XRect destRect) { - ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; + _gfx.DrawRectangle(XBrushes.LightGray, destRect); + string failureString; + ImageFormatInfo formatInfo = (ImageFormatInfo)RenderInfo.FormatInfo; - if (formatInfo.Failure == ImageFailure.None) - { - XImage xImage = null; - - try - { - xImage = CreateXImage(); - - } - catch (InvalidOperationException ex) - { - Debug.WriteLine(Messages2.InvalidImageType(ex.Message)); - formatInfo.Failure = ImageFailure.InvalidType; - } + failureString = Messages2.DisplayInvalidImageType; - if (formatInfo.Failure == ImageFailure.None) - { - try - { - XUnit usrWidth = _barcode.Width.Point; - XUnit usrHeight = _barcode.Height.Point; - bool usrWidthSet = !_barcode._width.IsNull; - bool usrHeightSet = !_barcode._height.IsNull; - - XUnit resultWidth = usrWidth; - XUnit resultHeight = usrHeight; - - Debug.Assert(xImage != null); - double xPixels = xImage.PixelWidth; - bool usrResolutionSet = !_barcode._resolution.IsNull; - - double horzRes = usrResolutionSet ? _barcode.Resolution : xImage.HorizontalResolution; - double vertRes = usrResolutionSet ? _barcode.Resolution : xImage.VerticalResolution; - - // ReSharper disable CompareOfFloatsByEqualityOperator - if (horzRes == 0 && vertRes == 0) - { - horzRes = 72; - vertRes = 72; - } - else if (horzRes == 0) - { - Debug.Assert(false, "How can this be?"); - horzRes = 72; - } - else if (vertRes == 0) - { - Debug.Assert(false, "How can this be?"); - vertRes = 72; - } - // ReSharper restore CompareOfFloatsByEqualityOperator - - XUnit inherentWidth = XUnit.FromInch(xPixels / horzRes); - double yPixels = xImage.PixelHeight; - XUnit inherentHeight = XUnit.FromInch(yPixels / vertRes); - - //bool lockRatio = _image.IsNull("LockAspectRatio") ? true : _image.LockAspectRatio; - bool lockRatio = _barcode._lockAspectRatio.IsNull || _barcode.LockAspectRatio; - - double scaleHeight = _barcode.ScaleHeight; - double scaleWidth = _barcode.ScaleWidth; - //bool scaleHeightSet = !_image.IsNull("ScaleHeight"); - //bool scaleWidthSet = !_image.IsNull("ScaleWidth"); - bool scaleHeightSet = !_barcode._scaleHeight.IsNull; - bool scaleWidthSet = !_barcode._scaleWidth.IsNull; - - if (lockRatio && !(scaleHeightSet && scaleWidthSet)) - { - if (usrWidthSet && !usrHeightSet) - { - resultHeight = inherentHeight / inherentWidth * usrWidth; - } - else if (usrHeightSet && !usrWidthSet) - { - resultWidth = inherentWidth / inherentHeight * usrHeight; - } - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - else if (!usrHeightSet && !usrWidthSet) - { - resultHeight = inherentHeight; - resultWidth = inherentWidth; - } - - if (scaleHeightSet) - { - resultHeight = resultHeight * scaleHeight; - resultWidth = resultWidth * scaleHeight; - } - if (scaleWidthSet) - { - resultHeight = resultHeight * scaleWidth; - resultWidth = resultWidth * scaleWidth; - } - } - else - { - if (!usrHeightSet) - resultHeight = inherentHeight; - - if (!usrWidthSet) - resultWidth = inherentWidth; - - if (scaleHeightSet) - resultHeight = resultHeight * scaleHeight; - if (scaleWidthSet) - resultWidth = resultWidth * scaleWidth; - } - - formatInfo.CropWidth = (int)xPixels; - formatInfo.CropHeight = (int)yPixels; - if (_barcode._pictureFormat != null && !_barcode._pictureFormat.IsNull()) - { - PictureFormat picFormat = _barcode.PictureFormat; - //Cropping in pixels. - XUnit cropLeft = picFormat.CropLeft.Point; - XUnit cropRight = picFormat.CropRight.Point; - XUnit cropTop = picFormat.CropTop.Point; - XUnit cropBottom = picFormat.CropBottom.Point; - formatInfo.CropX = (int)(horzRes * cropLeft.Inch); - formatInfo.CropY = (int)(vertRes * cropTop.Inch); - formatInfo.CropWidth -= (int)(horzRes * ((XUnit)(cropLeft + cropRight)).Inch); - formatInfo.CropHeight -= (int)(vertRes * ((XUnit)(cropTop + cropBottom)).Inch); - - //Scaled cropping of the height and width. - double xScale = resultWidth / inherentWidth; - double yScale = resultHeight / inherentHeight; - - cropLeft = xScale * cropLeft; - cropRight = xScale * cropRight; - cropTop = yScale * cropTop; - cropBottom = yScale * cropBottom; - - resultHeight = resultHeight - cropTop - cropBottom; - resultWidth = resultWidth - cropLeft - cropRight; - } - if (resultHeight <= 0 || resultWidth <= 0) - { - formatInfo.Width = XUnit.FromCentimeter(2.5); - formatInfo.Height = XUnit.FromCentimeter(2.5); - Debug.WriteLine(Messages2.EmptyImageSize); - //_failure = ImageFailure.EmptySize; - } - else - { - formatInfo.Width = resultWidth; - formatInfo.Height = resultHeight; - } - } - catch (Exception ex) - { - Debug.WriteLine(Messages2.ImageNotReadable(_barcode.Code, ex.Message)); - formatInfo.Failure = ImageFailure.NotRead; - } - finally - { - if (xImage != null) - xImage.Dispose(); - } - } - } - if (formatInfo.Failure != ImageFailure.None) - { - if (!_barcode._width.IsNull) - formatInfo.Width = _barcode.Width.Point; - else - formatInfo.Width = XUnit.FromCentimeter(2.5); - - if (!_barcode._height.IsNull) - formatInfo.Height = _barcode.Height.Point; - else - formatInfo.Height = XUnit.FromCentimeter(2.5); - } + // Create stub font + XFont font = new XFont("Courier New", 8); + _gfx.DrawString(failureString, font, XBrushes.Red, destRect, XStringFormats.Center); } - XImage CreateXImage() + + XImage CreateBarcode() { XImage image = null; -#if CORE_WITH_GDI || GDI + ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; - if (String.IsNullOrEmpty(_barcode.Code)) - throw new ArgumentNullException("Code"); +#if CORE_WITH_GDI || GDI BarcodeFormat format = BarcodeFormat.All_1D; @@ -350,12 +185,13 @@ XImage CreateXImage() break; } + if (String.IsNullOrEmpty(_barcode.Code)) + throw new ArgumentNullException("Code"); + var options = new EncodingOptions(); - // hack - const float resolution = 200; - int horzPixels = (int)(_barcode.Width.Inch * resolution); - int vertPixels = (int)(_barcode.Height.Inch * resolution); + int horzPixels = (int)(formatInfo.Width.Inch * formatInfo.Resolution); + int vertPixels = (int)(formatInfo.Height.Inch * formatInfo.Resolution); options.Width = horzPixels; options.Height = vertPixels; @@ -370,7 +206,7 @@ XImage CreateXImage() string fileName = Path.GetTempFileName(); - bmp.SetResolution(resolution, resolution); + bmp.SetResolution((float)formatInfo.Resolution, (float)formatInfo.Resolution); bmp.Save(fileName, ImageFormat.Png); image = XImage.FromFile(fileName); @@ -379,7 +215,6 @@ XImage CreateXImage() if (File.Exists(fileName)) File.Delete(fileName); */ - #endif return image; diff --git a/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageFormatInfo.cs b/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageFormatInfo.cs index 37008b3..49c956c 100644 --- a/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageFormatInfo.cs +++ b/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageFormatInfo.cs @@ -43,6 +43,7 @@ internal sealed class ImageFormatInfo : ShapeFormatInfo internal int CropHeight; internal XUnit Width; internal XUnit Height; + internal double Resolution; internal ImageFailure Failure; internal string ImagePath; From 439d87882505a884329925dbf4b47e49e72bc5be Mon Sep 17 00:00:00 2001 From: Emanuele Zavallone Date: Wed, 5 Aug 2020 16:44:40 +0200 Subject: [PATCH 23/25] amend README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bc2bed2..68d84ea 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -- This is ( almost ) the master branch with a couple added features. +- This is ( almost ) the master branch with a some added features. # XML based alternative serialization and deserialization support @@ -42,6 +42,12 @@ It can be used like this: ....
+ +# 1D & 2D barcode3 support via zxing + +- Add a Barcode tag like this: + + # MigraDoc MigraDoc Foundation - Creating documents on the fly From 23fd9f6a1eaeafd34efd28590e5622b05f1bd965 Mon Sep 17 00:00:00 2001 From: "EMA-DELL\\emaw8" Date: Wed, 26 Aug 2020 11:49:36 +0200 Subject: [PATCH 24/25] fix readme --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 68d84ea..b2e4fbe 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -- This is ( almost ) the master branch with a some added features. +# Fork with a some features added. -# XML based alternative serialization and deserialization support +## XML based serialization and deserialization -This version add support to an alternative format for serialization based on XML. A sample MigraDoc/XML file can be found [here](https://raw.githubusercontent.com/emazv72/MigraDoc-samples/master/samples/xml/MigraDoc.xml) +This version adds support to an alternative format for serialization based on XML. A sample MigraDoc/XML file can be found [here](https://raw.githubusercontent.com/emazv72/MigraDoc-samples/master/samples/xml/MigraDoc.xml) -It can be used like this: +Example usage: MigraDoc.DocumentObjectModel.IO.Xml.DdlWriter.WriteToFile(document, "MigraDoc.xml"); @@ -27,9 +27,9 @@ It can be used like this: } -# Last page header and footer +## Last page header and footer -- Add the DifferentLastPageHeaderFooter flag and the corresponding headers and footers +- DifferentLastPageHeaderFooter flag and the corresponding headers and footers:
@@ -43,12 +43,14 @@ It can be used like this:
-# 1D & 2D barcode3 support via zxing +## 1D & 2D barcode support via zxing + +- Added support for the Barcode tag: + + + -- Add a Barcode tag like this: - - # MigraDoc MigraDoc Foundation - Creating documents on the fly From 51696425f2219b9f4943fe35f2dc945b69512e42 Mon Sep 17 00:00:00 2001 From: emazv72 Date: Wed, 26 Aug 2020 11:49:36 +0200 Subject: [PATCH 25/25] fix readme --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 68d84ea..b2e4fbe 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -- This is ( almost ) the master branch with a some added features. +# Fork with a some features added. -# XML based alternative serialization and deserialization support +## XML based serialization and deserialization -This version add support to an alternative format for serialization based on XML. A sample MigraDoc/XML file can be found [here](https://raw.githubusercontent.com/emazv72/MigraDoc-samples/master/samples/xml/MigraDoc.xml) +This version adds support to an alternative format for serialization based on XML. A sample MigraDoc/XML file can be found [here](https://raw.githubusercontent.com/emazv72/MigraDoc-samples/master/samples/xml/MigraDoc.xml) -It can be used like this: +Example usage: MigraDoc.DocumentObjectModel.IO.Xml.DdlWriter.WriteToFile(document, "MigraDoc.xml"); @@ -27,9 +27,9 @@ It can be used like this: } -# Last page header and footer +## Last page header and footer -- Add the DifferentLastPageHeaderFooter flag and the corresponding headers and footers +- DifferentLastPageHeaderFooter flag and the corresponding headers and footers:
@@ -43,12 +43,14 @@ It can be used like this:
-# 1D & 2D barcode3 support via zxing +## 1D & 2D barcode support via zxing + +- Added support for the Barcode tag: + + + -- Add a Barcode tag like this: - - # MigraDoc MigraDoc Foundation - Creating documents on the fly