/************************************************************************************* DocX – DocX is the community edition of Xceed Words for .NET Copyright (C) 2009-2016 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license For more features and fast professional support, pick up Xceed Words for .NET at https://xceed.com/xceed-words-for-net/ ***********************************************************************************/ using System; using System.Linq; using System.Xml.Linq; using System.Drawing; using System.Globalization; namespace Xceed.Words.NET { /// /// A text formatting. /// public class Formatting : IComparable { #region Private Members private XElement _rPr; private bool? _hidden; private bool? _bold; private bool? _italic; private StrikeThrough? _strikethrough; private Script? _script; private Highlight? _highlight; private Color? _shading; private Border _border; private double? _size; private Color? _fontColor; private Color? _underlineColor; private UnderlineStyle? _underlineStyle; private Misc? _misc; private CapsStyle? _capsStyle; private Font _fontFamily; private int? _percentageScale; private int? _kerning; private int? _position; private double? _spacing; private string _styleName; private CultureInfo _language; #endregion #region Constructors /// /// A text formatting. /// public Formatting() { _capsStyle = Xceed.Words.NET.CapsStyle.none; _strikethrough = Xceed.Words.NET.StrikeThrough.none; _script = Xceed.Words.NET.Script.none; _highlight = Xceed.Words.NET.Highlight.none; _underlineStyle = Xceed.Words.NET.UnderlineStyle.none; _misc = Xceed.Words.NET.Misc.none; // Use current culture by default _language = CultureInfo.CurrentCulture; _rPr = new XElement( XName.Get( "rPr", DocX.w.NamespaceName ) ); } #endregion #region Public Properties /// /// Text language /// public CultureInfo Language { get { return _language; } set { _language = value; } } /// /// This formatting will apply Bold. /// public bool? Bold { get { return _bold; } set { _bold = value; } } /// /// This formatting will apply Italic. /// public bool? Italic { get { return _italic; } set { _italic = value; } } /// /// This formatting will apply StrickThrough. /// public StrikeThrough? StrikeThrough { get { return _strikethrough; } set { _strikethrough = value; } } /// /// The script that this formatting should be, normal, superscript or subscript. /// public Script? Script { get { return _script; } set { _script = value; } } /// /// The Size of this text, must be between 0 and 1638. /// public double? Size { get { return _size; } set { double? temp = value * 2; if( temp - ( int )temp == 0 ) { if( value > 0 && value < 1639 ) { _size = value; } else throw new ArgumentException( "Size", "Value must be in the range 0 - 1638" ); } else throw new ArgumentException( "Size", "Value must be either a whole or half number, examples: 32, 32.5" ); } } /// /// Percentage scale must be one of the following values 200, 150, 100, 90, 80, 66, 50 or 33. /// public int? PercentageScale { get { return _percentageScale; } set { if( ( new int?[] { 200, 150, 100, 90, 80, 66, 50, 33 } ).Contains( value ) ) { _percentageScale = value; } else throw new ArgumentOutOfRangeException( "PercentageScale", "Value must be one of the following: 200, 150, 100, 90, 80, 66, 50 or 33" ); } } /// /// The Kerning to apply to this text must be one of the following values 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72. /// public int? Kerning { get { return _kerning; } set { if( new int?[] { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 }.Contains( value ) ) _kerning = value; else throw new ArgumentOutOfRangeException( "Kerning", "Value must be one of the following: 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48 or 72" ); } } /// /// Text position must be in the range (-1585 - 1585). /// public int? Position { get { return _position; } set { if( value > -1585 && value < 1585 ) _position = value; else throw new ArgumentOutOfRangeException( "Position", "Value must be in the range -1585 - 1585" ); } } /// /// Text spacing must be in the range (-1585 - 1585). /// public double? Spacing { get { return _spacing; } set { double? temp = value * 20; if( temp - ( int )temp == 0 ) { if( value > -1585 && value < 1585 ) _spacing = value; else throw new ArgumentException( "Spacing", "Value must be in the range: -1584 - 1584" ); } else throw new ArgumentException( "Spacing", "Value must be either a whole or acurate to one decimal, examples: 32, 32.1, 32.2, 32.9" ); } } /// /// The colour of the text. /// public Color? FontColor { get { return _fontColor; } set { _fontColor = value; } } /// /// Highlight colour. /// public Highlight? Highlight { get { return _highlight; } set { _highlight = value; } } /// /// Shading color. /// public Color? Shading { get { return _shading; } set { _shading = value; } } public Border Border { get { return _border; } set { _border = value; } } public string StyleName { get { return _styleName; } set { _styleName = value; } } /// /// The Underline style that this formatting applies. /// public UnderlineStyle? UnderlineStyle { get { return _underlineStyle; } set { _underlineStyle = value; } } /// /// The underline colour. /// public Color? UnderlineColor { get { return _underlineColor; } set { _underlineColor = value; } } /// /// Misc settings. /// public Misc? Misc { get { return _misc; } set { _misc = value; } } /// /// Is this text hidden or visible. /// public bool? Hidden { get { return _hidden; } set { _hidden = value; } } /// /// Capitalization style. /// public CapsStyle? CapsStyle { get { return _capsStyle; } set { _capsStyle = value; } } /// /// The font Family of this formatting. /// /// public Font FontFamily { get { return _fontFamily; } set { _fontFamily = value; } } #endregion #region Internal Properties internal XElement Xml { get { _rPr = new XElement( XName.Get( "rPr", DocX.w.NamespaceName ) ); if( _language != null ) { _rPr.Add( new XElement( XName.Get( "lang", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _language.Name ) ) ); } if( _spacing.HasValue ) { _rPr.Add( new XElement( XName.Get( "spacing", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _spacing.Value * 20 ) ) ); } if( !string.IsNullOrEmpty( _styleName ) ) { _rPr.Add( new XElement( XName.Get( "rStyle", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _styleName ) ) ); } if( _position.HasValue ) { _rPr.Add( new XElement( XName.Get( "position", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _position.Value * 2 ) ) ); } if( _kerning.HasValue ) { _rPr.Add( new XElement( XName.Get( "kern", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _kerning.Value * 2 ) ) ); } if( _percentageScale.HasValue ) { _rPr.Add( new XElement( XName.Get( "w", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _percentageScale ) ) ); } if( _fontFamily != null ) { _rPr.Add ( new XElement( XName.Get( "rFonts", DocX.w.NamespaceName ), new XAttribute( XName.Get( "ascii", DocX.w.NamespaceName ), _fontFamily.Name ), new XAttribute( XName.Get( "hAnsi", DocX.w.NamespaceName ), _fontFamily.Name ), new XAttribute( XName.Get( "cs", DocX.w.NamespaceName ), _fontFamily.Name ), new XAttribute( XName.Get( "eastAsia", DocX.w.NamespaceName ), _fontFamily.Name ) ) ); } if( _hidden.HasValue && _hidden.Value ) { _rPr.Add( new XElement( XName.Get( "vanish", DocX.w.NamespaceName ) ) ); } if( _bold.HasValue && _bold.Value ) { _rPr.Add( new XElement( XName.Get( "b", DocX.w.NamespaceName ) ) ); } if( _italic.HasValue && _italic.Value ) { _rPr.Add( new XElement( XName.Get( "i", DocX.w.NamespaceName ) ) ); } if( _underlineStyle.HasValue ) { switch( _underlineStyle ) { case Xceed.Words.NET.UnderlineStyle.none: break; case Xceed.Words.NET.UnderlineStyle.singleLine: _rPr.Add( new XElement( XName.Get( "u", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), "single" ) ) ); break; case Xceed.Words.NET.UnderlineStyle.doubleLine: _rPr.Add( new XElement( XName.Get( "u", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), "double" ) ) ); break; default: _rPr.Add( new XElement( XName.Get( "u", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _underlineStyle.ToString() ) ) ); break; } } if( _underlineColor.HasValue ) { // If an underlineColor has been set but no underlineStyle has been set if( _underlineStyle == Xceed.Words.NET.UnderlineStyle.none ) { // Set the underlineStyle to the default _underlineStyle = Xceed.Words.NET.UnderlineStyle.singleLine; _rPr.Add( new XElement( XName.Get( "u", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), "single" ) ) ); } _rPr.Element( XName.Get( "u", DocX.w.NamespaceName ) ).Add( new XAttribute( XName.Get( "color", DocX.w.NamespaceName ), _underlineColor.Value.ToHex() ) ); } if( _strikethrough.HasValue ) { switch( _strikethrough ) { case Xceed.Words.NET.StrikeThrough.none: break; case Xceed.Words.NET.StrikeThrough.strike: _rPr.Add( new XElement( XName.Get( "strike", DocX.w.NamespaceName ) ) ); break; case Xceed.Words.NET.StrikeThrough.doubleStrike: _rPr.Add( new XElement( XName.Get( "dstrike", DocX.w.NamespaceName ) ) ); break; default: break; } } if( _script.HasValue ) { switch( _script ) { case Xceed.Words.NET.Script.none: break; default: _rPr.Add( new XElement( XName.Get( "vertAlign", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _script.ToString() ) ) ); break; } } if( _size.HasValue ) { _rPr.Add( new XElement( XName.Get( "sz", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), ( _size * 2 ).ToString() ) ) ); _rPr.Add( new XElement( XName.Get( "szCs", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), ( _size * 2 ).ToString() ) ) ); } if( _fontColor.HasValue ) { _rPr.Add( new XElement( XName.Get( "color", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _fontColor.Value.ToHex() ) ) ); } if( _highlight.HasValue ) { switch( _highlight ) { case Xceed.Words.NET.Highlight.none: break; default: _rPr.Add( new XElement( XName.Get( "highlight", DocX.w.NamespaceName ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _highlight.ToString() ) ) ); break; } } if( _shading.HasValue ) { _rPr.Add( new XElement( XName.Get( "shd", DocX.w.NamespaceName ), new XAttribute( XName.Get( "fill", DocX.w.NamespaceName ), _shading.Value.ToHex() ) ) ); } if( _border != null ) { _rPr.Add( new XElement( XName.Get( "bdr", DocX.w.NamespaceName ), new object[] { new XAttribute( XName.Get( "color", DocX.w.NamespaceName ), _border.Color ), new XAttribute( XName.Get( "space", DocX.w.NamespaceName ), _border.Space ), new XAttribute( XName.Get( "sz", DocX.w.NamespaceName ), _border.Size ), new XAttribute( XName.Get( "val", DocX.w.NamespaceName ), _border.Tcbs ) } ) ); } if( _capsStyle.HasValue ) { switch( _capsStyle ) { case Xceed.Words.NET.CapsStyle.none: break; default: _rPr.Add( new XElement( XName.Get( _capsStyle.ToString(), DocX.w.NamespaceName ) ) ); break; } } if( _misc.HasValue ) { switch( _misc ) { case Xceed.Words.NET.Misc.none: break; case Xceed.Words.NET.Misc.outlineShadow: _rPr.Add( new XElement( XName.Get( "outline", DocX.w.NamespaceName ) ) ); _rPr.Add( new XElement( XName.Get( "shadow", DocX.w.NamespaceName ) ) ); break; case Xceed.Words.NET.Misc.engrave: _rPr.Add( new XElement( XName.Get( "imprint", DocX.w.NamespaceName ) ) ); break; default: _rPr.Add( new XElement( XName.Get( _misc.ToString(), DocX.w.NamespaceName ) ) ); break; } } return _rPr; } } #endregion #region Public Methods /// /// Returns a cloned instance of Formatting. /// /// public Formatting Clone() { var clone = new Formatting(); clone.Bold = _bold; clone.CapsStyle = _capsStyle; clone.FontColor = _fontColor; clone.FontFamily = _fontFamily; clone.Hidden = _hidden; clone.Highlight = _highlight; clone.Shading = _shading; clone.Border = _border; clone.Italic = _italic; if( _kerning.HasValue ) { clone.Kerning = _kerning; } clone.Language = _language; clone.Misc = _misc; if( _percentageScale.HasValue ) { clone.PercentageScale = _percentageScale; } if( _position.HasValue ) { clone.Position = _position; } clone.Script = _script; if( _size.HasValue ) { clone.Size = _size; } if( _spacing.HasValue ) { clone.Spacing = _spacing; } if( !string.IsNullOrEmpty( _styleName ) ) { clone.StyleName = _styleName; } clone.StrikeThrough = _strikethrough; clone.UnderlineColor = _underlineColor; clone.UnderlineStyle = _underlineStyle; return clone; } public static Formatting Parse( XElement rPr, Formatting formatting = null ) { if( formatting == null ) { formatting = new Formatting(); } if( rPr == null ) return formatting; // Build up the Formatting object. foreach( XElement option in rPr.Elements() ) { switch( option.Name.LocalName ) { case "lang": formatting.Language = new CultureInfo(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName), null) ?? option.GetAttribute(XName.Get("eastAsia", DocX.w.NamespaceName), null) ?? option.GetAttribute(XName.Get("bidi", DocX.w.NamespaceName))); break; case "spacing": formatting.Spacing = Double.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 20.0; break; case "position": formatting.Position = Int32.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2; break; case "kern": formatting.Kerning = Int32.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2; break; case "w": formatting.PercentageScale = Int32.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))); break; case "sz": formatting.Size = Double.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2; break; case "rFonts": var fontName = option.GetAttribute( XName.Get( "ascii", DocX.w.NamespaceName ), null ) ?? option.GetAttribute( XName.Get( "hAnsi", DocX.w.NamespaceName ), null ) ?? option.GetAttribute( XName.Get( "cs", DocX.w.NamespaceName ), null ) ?? option.GetAttribute( XName.Get( "hint", DocX.w.NamespaceName ), null ) ?? option.GetAttribute( XName.Get( "eastAsia", DocX.w.NamespaceName ), null ); formatting.FontFamily = ( fontName != null ) ? new Font( fontName ) : ( formatting.FontFamily == null ) ? new Font( "Calibri" ) : formatting.FontFamily; break; case "color": try { var color = option.GetAttribute(XName.Get("val", DocX.w.NamespaceName)); formatting.FontColor = ( color == "auto") ? Color.Black : ColorTranslator.FromHtml(string.Format("#{0}", color)); } catch (Exception) { // ignore } break; case "vanish": formatting._hidden = true; break; case "b": formatting.Bold = option.GetAttribute( XName.Get( "val", DocX.w.NamespaceName ) ) != "0"; break; case "i": formatting.Italic = true; break; case "highlight": switch( option.GetAttribute( XName.Get( "val", DocX.w.NamespaceName ) ) ) { case "yellow": formatting.Highlight = NET.Highlight.yellow; break; case "green": formatting.Highlight = NET.Highlight.green; break; case "cyan": formatting.Highlight = NET.Highlight.cyan; break; case "magenta": formatting.Highlight = NET.Highlight.magenta; break; case "blue": formatting.Highlight = NET.Highlight.blue; break; case "red": formatting.Highlight = NET.Highlight.red; break; case "darkBlue": formatting.Highlight = NET.Highlight.darkBlue; break; case "darkCyan": formatting.Highlight = NET.Highlight.darkCyan; break; case "darkGreen": formatting.Highlight = NET.Highlight.darkGreen; break; case "darkMagenta": formatting.Highlight = NET.Highlight.darkMagenta; break; case "darkRed": formatting.Highlight = NET.Highlight.darkRed; break; case "darkYellow": formatting.Highlight = NET.Highlight.darkYellow; break; case "darkGray": formatting.Highlight = NET.Highlight.darkGray; break; case "lightGray": formatting.Highlight = NET.Highlight.lightGray; break; case "black": formatting.Highlight = NET.Highlight.black; break; } break; case "strike": formatting.StrikeThrough = NET.StrikeThrough.strike; break; case "dstrike": formatting.StrikeThrough = NET.StrikeThrough.doubleStrike; break; case "u": formatting.UnderlineStyle = HelperFunctions.GetUnderlineStyle(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))); try { var color = option.GetAttribute( XName.Get( "color", DocX.w.NamespaceName ) ); if( !string.IsNullOrEmpty( color ) ) { formatting.UnderlineColor = System.Drawing.ColorTranslator.FromHtml( string.Format( "#{0}", color ) ); } } catch( Exception ) { // ignore } break; case "vertAlign": //script var script = option.GetAttribute(XName.Get("val", DocX.w.NamespaceName), null); formatting.Script = (Script)Enum.Parse(typeof(Script), script); break; case "caps": formatting.CapsStyle = NET.CapsStyle.caps; break; case "smallCaps": formatting.CapsStyle = NET.CapsStyle.smallCaps; break; case "shd": var fill = option.GetAttribute( XName.Get( "fill", DocX.w.NamespaceName ) ); if( !string.IsNullOrEmpty( fill ) ) { formatting.Shading = System.Drawing.ColorTranslator.FromHtml( string.Format( "#{0}", fill ) ); } break; case "bdr": var borderSize = BorderSize.one; var borderColor = Color.Black; var borderSpace = 0; var borderStyle = BorderStyle.Tcbs_single; var bdrColor = option.Attribute( XName.Get( "color", DocX.w.NamespaceName ) ); if( ( bdrColor != null ) && ( bdrColor.Value != "auto" ) ) { borderColor = System.Drawing.ColorTranslator.FromHtml( string.Format( "#{0}", bdrColor.Value ) ); } var size = option.Attribute( XName.Get( "sz", DocX.w.NamespaceName ) ); if( size != null ) { var sizeValue = System.Convert.ToSingle( size.Value ); if( sizeValue == 2 ) borderSize = BorderSize.one; else if( sizeValue == 4 ) borderSize = BorderSize.two; else if( sizeValue == 6 ) borderSize = BorderSize.three; else if( sizeValue == 8 ) borderSize = BorderSize.four; else if( sizeValue == 12 ) borderSize = BorderSize.five; else if( sizeValue == 18 ) borderSize = BorderSize.six; else if( sizeValue == 24 ) borderSize = BorderSize.seven; else if( sizeValue == 36 ) borderSize = BorderSize.eight; else if( sizeValue == 48 ) borderSize = BorderSize.nine; else borderSize = BorderSize.one; } var space = option.Attribute( XName.Get( "space", DocX.w.NamespaceName ) ); if( space != null ) { borderSpace = System.Convert.ToInt32( space.Value ); } var bdrStyle = option.Attribute( XName.Get( "val", DocX.w.NamespaceName ) ); if( bdrStyle != null ) { borderStyle = (BorderStyle)Enum.Parse( typeof( BorderStyle ), "Tcbs_" + bdrStyle.Value ); } formatting.Border = new Border( borderStyle, borderSize, borderSpace, borderColor ); break; case "rStyle": var style = option.GetAttribute( XName.Get( "val", DocX.w.NamespaceName ), null ); formatting.StyleName = style; break; default: break; } } return formatting; } public int CompareTo( object obj ) { Formatting other = ( Formatting )obj; if( other._hidden != _hidden ) return -1; if( other._bold != _bold ) return -1; if( other._italic != _italic ) return -1; if( other._strikethrough != _strikethrough ) return -1; if( other._script != _script ) return -1; if( other._highlight != _highlight ) return -1; if( other._shading != _shading ) return -1; if( other._border != _border ) return -1; if( other._size != _size ) return -1; if( other._fontColor != _fontColor ) return -1; if( other._underlineColor != _underlineColor ) return -1; if( other._underlineStyle != _underlineStyle ) return -1; if( other._misc != _misc ) return -1; if( other._capsStyle != _capsStyle ) return -1; if( other._fontFamily != _fontFamily ) return -1; if( other._percentageScale != _percentageScale ) return -1; if( other._kerning != _kerning ) return -1; if( other._position != _position ) return -1; if( other._spacing != _spacing ) return -1; if( other._styleName != _styleName ) return -1; if( !other._language.Equals(_language) ) return -1; return 0; } #endregion } }