Пример #1
0
        /// <summary>
        /// Gets an attribute representing a single border side.
        /// If a border style/color/width has been specified individually, it will override the grouped definition.
        /// </summary>
        /// <returns>If the attribute is misformed, the <see cref="HtmlBorder.IsValid"/> property is set to false.</returns>
        public SideBorder GetAsSideBorder(String name)
        {
            string     attrValue = this[name];
            SideBorder border    = SideBorder.Parse(attrValue);

            // handle attributes specified individually.
            Unit width = SideBorder.ParseWidth(this[name + "-width"]);

            if (width.IsValid)
            {
                border.Width = width;
            }

            var color = GetAsColor(name + "-color");

            if (!color.IsEmpty)
            {
                border.Color = color;
            }

            var style = ConverterUtility.ConvertToBorderStyle(this[name + "-style"]);

            if (style != w.BorderValues.Nil)
            {
                border.Style = style;
            }

            return(border);
        }
Пример #2
0
        /// <summary>
        /// Gets an attribute representing a color (named color, hexadecimal or hexadecimal
        /// without the preceding # character).
        /// </summary>
        public System.Drawing.Color GetAsColor(String name)
        {
            string attrValue = this[name];

            if (attrValue != null)
            {
                return(ConverterUtility.ConvertToForeColor(attrValue));
            }

            return(System.Drawing.Color.Empty);
        }
Пример #3
0
        /// <summary>
        /// Gets the font attribute and combine with the style, size and family.
        /// </summary>
        public HtmlFont GetAsFont(String name)
        {
            HtmlFont font      = HtmlFont.Parse(this[name]);
            string   attrValue = this[name + "-style"];

            if (attrValue != null)
            {
                var style = ConverterUtility.ConvertToFontStyle(attrValue);
                if (style.HasValue)
                {
                    font.Style = style.Value;
                }
            }
            attrValue = this[name + "-variant"];
            if (attrValue != null)
            {
                var variant = ConverterUtility.ConvertToFontVariant(attrValue);
                if (variant.HasValue)
                {
                    font.Variant = variant.Value;
                }
            }
            attrValue = this[name + "-weight"];
            if (attrValue != null)
            {
                var weight = ConverterUtility.ConvertToFontWeight(attrValue);
                if (weight.HasValue)
                {
                    font.Weight = weight.Value;
                }
            }
            attrValue = this[name + "-family"];
            if (attrValue != null)
            {
                font.Family = ConverterUtility.ConvertToFontFamily(attrValue);
            }
            Unit unit = this.GetAsUnit(name + "-size");

            if (unit.IsValid)
            {
                font.Size = unit;
            }
            return(font);
        }
Пример #4
0
        public static SideBorder Parse(String str)
        {
            if (str == null)
            {
                return(SideBorder.Empty);
            }

            // The properties of a border that can be set, are (in order): border-width, border-style, and border-color.
            // It does not matter if one of the values above are missing, e.g. border:solid #ff0000; is allowed.
            // The main problem for parsing this attribute is that the browsers allow any permutation of the values... meaning more coding :(
            // http://www.w3schools.com/cssref/pr_border.asp

            List <String> borderParts = new List <String>(str.Split(HttpUtility.WhiteSpaces, StringSplitOptions.RemoveEmptyEntries));

            if (borderParts.Count == 0)
            {
                return(SideBorder.Empty);
            }

            // Initialize default values
            Unit  borderWidth = Unit.Empty;
            Color borderColor = Color.Empty;

            w.BorderValues borderStyle = w.BorderValues.Nil;

            // Now try to guess the values with their permutation

            // handle border style
            for (int i = 0; i < borderParts.Count; i++)
            {
                borderStyle = ConverterUtility.ConvertToBorderStyle(borderParts[i]);
                if (borderStyle != w.BorderValues.Nil)
                {
                    borderParts.RemoveAt(i);                     // no need to process this part anymore
                    break;
                }
            }

            for (int i = 0; i < borderParts.Count; i++)
            {
                borderWidth = ParseWidth(borderParts[i]);
                if (borderWidth.IsValid)
                {
                    borderParts.RemoveAt(i);                     // no need to process this part anymore
                    break;
                }
            }

            // find width
            if (borderParts.Count > 0)
            {
                borderColor = ConverterUtility.ConvertToForeColor(borderParts[0]);
            }

            // returns the instance with default value if needed.
            // These value are the ones used by the browser, i.e: solid 3px black
            return(new SideBorder(
                       borderStyle == w.BorderValues.Nil? w.BorderValues.Single : borderStyle,
                       borderColor.IsEmpty? Color.Black : borderColor,
                       borderWidth.IsFixed? borderWidth : new Unit(UnitMetric.Pixel, 4)));
        }
        /// <summary>
        /// Move inside the current tag related to table (td, thead, tr, ...) and converts some common
        /// attributes to their OpenXml equivalence.
        /// </summary>
        /// <param name="en">The Html enumerator positionned on a <i>table (or related)</i> tag.</param>
        /// <param name="runStyleAttributes">The collection of attributes where to store new discovered attributes.</param>
        public void ProcessCommonAttributes(HtmlEnumerator en, IList <OpenXmlElement> runStyleAttributes)
        {
            List <OpenXmlElement> containerStyleAttributes = new List <OpenXmlElement>();

            var colorValue = en.StyleAttributes.GetAsColor("background-color");

            // "background-color" is also handled by RunStyleCollection which duplicate this attribute (bug #13212). Let's ignore it
            if (!colorValue.IsEmpty && en.CurrentTag.Equals("<td>", StringComparison.InvariantCultureIgnoreCase))
            {
                colorValue = System.Drawing.Color.Empty;
            }
            if (colorValue.IsEmpty)
            {
                colorValue = en.Attributes.GetAsColor("bgcolor");
            }
            if (!colorValue.IsEmpty)
            {
                containerStyleAttributes.Add(
                    new Shading()
                {
                    Val = ShadingPatternValues.Clear, Color = "auto", Fill = colorValue.ToHexString()
                });
            }

            var htmlAlign = en.StyleAttributes["vertical-align"];

            if (htmlAlign == null)
            {
                htmlAlign = en.Attributes["valign"];
            }
            if (htmlAlign != null)
            {
                TableVerticalAlignmentValues?valign = ConverterUtility.FormatVAlign(htmlAlign);
                if (valign.HasValue)
                {
                    containerStyleAttributes.Add(new TableCellVerticalAlignment()
                    {
                        Val = valign
                    });
                }
            }

            htmlAlign = en.StyleAttributes["text-align"];
            if (htmlAlign == null)
            {
                htmlAlign = en.Attributes["align"];
            }
            if (htmlAlign != null)
            {
                JustificationValues?halign = ConverterUtility.FormatParagraphAlign(htmlAlign);
                if (halign.HasValue)
                {
                    this.BeginTagForParagraph(en.CurrentTag, new KeepNext(), new Justification {
                        Val = halign
                    });
                }
            }

            // implemented by ddforge
            String[] classes = en.Attributes.GetAsClass();
            if (classes != null)
            {
                for (int i = 0; i < classes.Length; i++)
                {
                    string className = documentStyle.GetStyle(classes[i], StyleValues.Table, ignoreCase: true);
                    if (className != null)                     // only one Style can be applied in OpenXml and dealing with inheritance is out of scope
                    {
                        containerStyleAttributes.Add(new RunStyle()
                        {
                            Val = className
                        });
                        break;
                    }
                }
            }

            this.BeginTag(en.CurrentTag, containerStyleAttributes);

            // Process general run styles
            documentStyle.Runs.ProcessCommonAttributes(en, runStyleAttributes);
        }
        /// <summary>
        /// There is a few attributes shared by a large number of tags. This method will check them for a limited
        /// number of tags (&lt;p&gt;, &lt;pre&gt;, &lt;div&gt;, &lt;span&gt; and &lt;body&gt;).
        /// </summary>
        /// <returns>Returns true if the processing of this tag should generate a new paragraph.</returns>
        public bool ProcessCommonAttributes(HtmlEnumerator en, IList <OpenXmlElement> styleAttributes)
        {
            if (en.Attributes.Count == 0)
            {
                return(false);
            }

            bool newParagraph = false;
            List <OpenXmlElement> containerStyleAttributes = new List <OpenXmlElement>();

            string attrValue = en.Attributes["lang"];

            if (attrValue != null && attrValue.Length > 0)
            {
                try
                {
                    var  ci  = System.Globalization.CultureInfo.GetCultureInfo(attrValue);
                    bool rtl = ci.TextInfo.IsRightToLeft;

                    Languages lang = new Languages()
                    {
                        Val = ci.TwoLetterISOLanguageName
                    };
                    if (rtl)
                    {
                        lang.Bidi = ci.Name;
                        styleAttributes.Add(new Languages()
                        {
                            Bidi = ci.Name
                        });

                        // notify table
                        documentStyle.Tables.BeginTag(en.CurrentTag, new TableJustification()
                        {
                            Val = TableRowAlignmentValues.Right
                        });
                    }

                    containerStyleAttributes.Add(new ParagraphMarkRunProperties(lang));
                    containerStyleAttributes.Add(new BiDi()
                    {
                        Val = OnOffValue.FromBoolean(rtl)
                    });
                }
                catch (ArgumentException)
                {
                    // lang not valid, ignore it
                }
            }


            attrValue = en.StyleAttributes["text-align"];
            if (attrValue != null && en.CurrentTag != "<font>")
            {
                JustificationValues?align = ConverterUtility.FormatParagraphAlign(attrValue);
                if (align.HasValue)
                {
                    containerStyleAttributes.Add(new Justification {
                        Val = align
                    });
                }
            }

            // according to w3c, dir should be used in conjonction with lang. But whatever happens, we'll apply the RTL layout
            attrValue = en.Attributes["dir"];
            if (attrValue != null)
            {
                if (attrValue.Equals("rtl", StringComparison.OrdinalIgnoreCase))
                {
                    styleAttributes.Add(new RightToLeftText());
                    containerStyleAttributes.Add(new Justification()
                    {
                        Val = JustificationValues.Right
                    });
                }
                else if (attrValue.Equals("ltr", StringComparison.OrdinalIgnoreCase))
                {
                    containerStyleAttributes.Add(new Justification()
                    {
                        Val = JustificationValues.Left
                    });
                }
            }

            // <span> and <font> are considered as semi-container attribute. When converted to OpenXml, there are Runs but not Paragraphs
            if (en.CurrentTag == "<p>" || en.CurrentTag == "<div>" || en.CurrentTag == "<pre>")
            {
                var border = en.StyleAttributes.GetAsBorder("border");
                if (!border.IsEmpty)
                {
                    ParagraphBorders borders = new ParagraphBorders();
                    if (border.Top.IsValid)
                    {
                        borders.Append(
                            new TopBorder()
                        {
                            Val = border.Top.Style, Color = border.Top.Color.ToHexString(), Size = (uint)border.Top.Width.ValueInPx * 4, Space = 1U
                        });
                    }
                    if (border.Left.IsValid)
                    {
                        borders.Append(
                            new LeftBorder()
                        {
                            Val = border.Left.Style, Color = border.Left.Color.ToHexString(), Size = (uint)border.Left.Width.ValueInPx * 4, Space = 1U
                        });
                    }
                    if (border.Bottom.IsValid)
                    {
                        borders.Append(
                            new BottomBorder()
                        {
                            Val = border.Bottom.Style, Color = border.Bottom.Color.ToHexString(), Size = (uint)border.Bottom.Width.ValueInPx * 4, Space = 1U
                        });
                    }
                    if (border.Right.IsValid)
                    {
                        borders.Append(
                            new RightBorder()
                        {
                            Val = border.Right.Style, Color = border.Right.Color.ToHexString(), Size = (uint)border.Right.Width.ValueInPx * 4, Space = 1U
                        });
                    }

                    containerStyleAttributes.Add(borders);
                    newParagraph = true;
                }
            }
            else if (en.CurrentTag == "<span>" || en.CurrentTag == "<font>")
            {
                // OpenXml limits the border to 4-side of the same color and style.
                SideBorder border = en.StyleAttributes.GetAsSideBorder("border");
                if (border.IsValid)
                {
                    styleAttributes.Add(new DocumentFormat.OpenXml.Wordprocessing.Border()
                    {
                        Val   = border.Style,
                        Color = border.Color.ToHexString(),
                        Size  = (uint)border.Width.ValueInPx * 4,
                        Space = 1U
                    });
                }
            }

            String[] classes = en.Attributes.GetAsClass();
            if (classes != null)
            {
                for (int i = 0; i < classes.Length; i++)
                {
                    string className = documentStyle.GetStyle(classes[i], StyleValues.Paragraph, ignoreCase: true);
                    if (className != null)
                    {
                        containerStyleAttributes.Add(new ParagraphStyleId()
                        {
                            Val = className
                        });
                        newParagraph = true;
                        break;
                    }
                }
            }

            Margin      margin      = en.StyleAttributes.GetAsMargin("margin");
            Indentation indentation = null;

            if (!margin.IsEmpty)
            {
                if (margin.Top.IsFixed || margin.Bottom.IsFixed)
                {
                    SpacingBetweenLines spacing = new SpacingBetweenLines();
                    if (margin.Top.IsFixed)
                    {
                        spacing.Before = margin.Top.ValueInDxa.ToString(CultureInfo.InvariantCulture);
                    }
                    if (margin.Bottom.IsFixed)
                    {
                        spacing.After = margin.Bottom.ValueInDxa.ToString(CultureInfo.InvariantCulture);
                    }
                    containerStyleAttributes.Add(spacing);
                }
                if (margin.Left.IsFixed || margin.Right.IsFixed)
                {
                    indentation = new Indentation();
                    if (margin.Left.IsFixed)
                    {
                        indentation.Left = margin.Left.ValueInDxa.ToString(CultureInfo.InvariantCulture);
                    }
                    if (margin.Right.IsFixed)
                    {
                        indentation.Right = margin.Right.ValueInDxa.ToString(CultureInfo.InvariantCulture);
                    }
                    containerStyleAttributes.Add(indentation);
                }
            }

            // implemented by giorand (feature #13787)
            Unit textIndent = en.StyleAttributes.GetAsUnit("text-indent");

            if (textIndent.IsValid && (en.CurrentTag == "<p>" || en.CurrentTag == "<div>"))
            {
                if (indentation == null)
                {
                    indentation = new Indentation();
                }
                indentation.FirstLine = textIndent.ValueInDxa.ToString(CultureInfo.InvariantCulture);
                containerStyleAttributes.Add(indentation);
            }

            this.BeginTag(en.CurrentTag, containerStyleAttributes);

            // Process general run styles
            documentStyle.Runs.ProcessCommonAttributes(en, styleAttributes);

            return(newParagraph);
        }
Пример #7
0
        public static HtmlFont Parse(String str)
        {
            if (str == null)
            {
                return(HtmlFont.Empty);
            }

            // The font shorthand property sets all the font properties in one declaration.
            // The properties that can be set, are (in order):
            // "font-style font-variant font-weight font-size/line-height font-family"
            // The font-size and font-family values are required.
            // If one of the other values are missing, the default values will be inserted, if any.
            // http://www.w3schools.com/cssref/pr_font_font.asp


            // in order to split by white spaces, we remove any white spaces between 2 family names (ex: Verdana, Arial -> Verdana,Arial)
            str = System.Text.RegularExpressions.Regex.Replace(str, @",\s+?", ",");

            String[] fontParts = str.Split(HttpUtility.WhiteSpaces, StringSplitOptions.RemoveEmptyEntries);
            if (fontParts.Length < 2)
            {
                return(HtmlFont.Empty);
            }
            HtmlFont font = HtmlFont.Empty;

            if (fontParts.Length == 2)             // 2=the minimal set of required parameters
            {
                // should be the size and the family (in that order). Others are set to their default values
                font.size = ReadFontSize(fontParts[0]);
                if (!font.size.IsValid)
                {
                    return(HtmlFont.Empty);
                }
                font.family = ConverterUtility.ConvertToFontFamily(fontParts[1]);
                return(font);
            }

            int index = 0;

            FontStyle?style = ConverterUtility.ConvertToFontStyle(fontParts[index]);

            if (style.HasValue)
            {
                font.style = style.Value; index++;
            }

            if (index + 2 > fontParts.Length)
            {
                return(HtmlFont.Empty);
            }
            FontVariant?variant = ConverterUtility.ConvertToFontVariant(fontParts[index]);

            if (variant.HasValue)
            {
                font.variant = variant.Value; index++;
            }

            if (index + 2 > fontParts.Length)
            {
                return(HtmlFont.Empty);
            }
            FontWeight?weight = ConverterUtility.ConvertToFontWeight(fontParts[index]);

            if (weight.HasValue)
            {
                font.weight = weight.Value; index++;
            }

            if (fontParts.Length - index < 2)
            {
                return(HtmlFont.Empty);
            }
            font.size = ReadFontSize(fontParts[fontParts.Length - 2]);
            if (!font.size.IsValid)
            {
                return(HtmlFont.Empty);
            }

            font.family = ConverterUtility.ConvertToFontFamily(fontParts[fontParts.Length - 1]);

            return(font);
        }
Пример #8
0
        private static Unit ReadFontSize(string str)
        {
            Unit size = ConverterUtility.ConvertToFontSize(str);

            return(size);            // % and ratio font-size/line-height are not supported
        }
Пример #9
0
        public static Unit Parse(String str)
        {
            if (str == null)
            {
                return(Unit.Empty);
            }

            str = str.Trim().ToLower(CultureInfo.InvariantCulture);
            int length      = str.Length;
            int digitLength = -1;

            for (int i = 0; i < length; i++)
            {
                char ch = str[i];
                if ((ch < '0' || ch > '9') && (ch != '-' && ch != '.' && ch != ','))
                {
                    break;
                }

                digitLength = i;
            }
            if (digitLength == -1)
            {
                // No digits in the width, we ignore this style
                return(str == "auto"? Unit.Auto : Unit.Empty);
            }

            UnitMetric type;

            if (digitLength < length - 1)
            {
                type = ConverterUtility.ConvertToUnitMetric(str.Substring(digitLength + 1).Trim());
            }
            else
            {
                type = UnitMetric.Pixel;
            }

            string v = str.Substring(0, digitLength + 1);
            double value;

            try
            {
                TypeConverter converter = new DoubleConverter();
                value = (double)converter.ConvertFromString(null, CultureInfo.InvariantCulture, v);

                if (value < Int16.MinValue || value > Int16.MaxValue)
                {
                    return(Unit.Empty);
                }
            }
            catch (FormatException)
            {
                return(Unit.Empty);
            }
            catch (ArithmeticException)
            {
                return(Unit.Empty);
            }

            return(new Unit(type, value));
        }