// "Therefore those skilled at the unorthodox // are infinite as heaven and earth, // inexhaustible as the great rivers. // When they come to an end, // they begin again, // like the days and months; // they die and are reborn, // like the four seasons." // // - Sun Tsu, // "The Art of War" using System; using System.Globalization; using System.Text.RegularExpressions; using TheArtOfDev.HtmlRenderer.Adapters; using TheArtOfDev.HtmlRenderer.Adapters.Entities; using TheArtOfDev.HtmlRenderer.Core.Parse; using TheArtOfDev.HtmlRenderer.Core.Utils; namespace TheArtOfDev.HtmlRenderer.Core.Dom { /// /// Base class for css box to handle the css properties.
/// Has field and property for every css property that can be set, the properties add additional parsing like /// setting the correct border depending what border value was set (single, two , all four).
/// Has additional fields to control the location and size of the box and 'actual' css values for some properties /// that require additional calculations and parsing.
///
internal abstract class CssBoxProperties { #region CSS Fields private string _backgroundColor = "transparent"; private string _backgroundGradient = "none"; private string _backgroundGradientAngle = "90"; private string _backgroundImage = "none"; private string _backgroundPosition = "0% 0%"; private string _backgroundRepeat = "repeat"; private string _borderTopWidth = "medium"; private string _borderRightWidth = "medium"; private string _borderBottomWidth = "medium"; private string _borderLeftWidth = "medium"; private string _borderTopColor = "black"; private string _borderRightColor = "black"; private string _borderBottomColor = "black"; private string _borderLeftColor = "black"; private string _borderTopStyle = "none"; private string _borderRightStyle = "none"; private string _borderBottomStyle = "none"; private string _borderLeftStyle = "none"; private string _borderSpacing = "0"; private string _borderCollapse = "separate"; private string _bottom; private string _color = "black"; private string _cornerNwRadius = "0"; private string _cornerNeRadius = "0"; private string _cornerSeRadius = "0"; private string _cornerSwRadius = "0"; private string _cornerRadius = "0"; private string _emptyCells = "show"; private string _direction = "ltr"; private string _display = "inline"; private string _fontFamily; private string _fontSize = "medium"; private string _fontStyle = "normal"; private string _fontVariant = "normal"; private string _fontWeight = "normal"; private string _float = "none"; private string _height = "auto"; private string _marginBottom = "0"; private string _marginLeft = "0"; private string _marginRight = "0"; private string _marginTop = "0"; private string _left = "auto"; private string _lineHeight = "normal"; private string _listStyleType = "disc"; private string _listStyleImage = string.Empty; private string _listStylePosition = "outside"; private string _listStyle = string.Empty; private string _overflow = "visible"; private string _paddingLeft = "0"; private string _paddingBottom = "0"; private string _paddingRight = "0"; private string _paddingTop = "0"; private string _right; private string _textAlign = string.Empty; private string _textDecoration = string.Empty; private string _textIndent = "0"; private string _top = "auto"; private string _position = "static"; private string _verticalAlign = "baseline"; private string _width = "auto"; private string _maxWidth = "none"; private string _wordSpacing = "normal"; private string _wordBreak = "normal"; private string _whiteSpace = "normal"; private string _visibility = "visible"; #endregion #region Fields /// /// Gets or sets the location of the box /// private RPoint _location; /// /// Gets or sets the size of the box /// private RSize _size; private double _actualCornerNw = double.NaN; private double _actualCornerNe = double.NaN; private double _actualCornerSw = double.NaN; private double _actualCornerSe = double.NaN; private RColor _actualColor = RColor.Empty; private double _actualBackgroundGradientAngle = double.NaN; private double _actualHeight = double.NaN; private double _actualWidth = double.NaN; private double _actualPaddingTop = double.NaN; private double _actualPaddingBottom = double.NaN; private double _actualPaddingRight = double.NaN; private double _actualPaddingLeft = double.NaN; private double _actualMarginTop = double.NaN; private double _collapsedMarginTop = double.NaN; private double _actualMarginBottom = double.NaN; private double _actualMarginRight = double.NaN; private double _actualMarginLeft = double.NaN; private double _actualBorderTopWidth = double.NaN; private double _actualBorderLeftWidth = double.NaN; private double _actualBorderBottomWidth = double.NaN; private double _actualBorderRightWidth = double.NaN; /// /// the width of whitespace between words /// private double _actualLineHeight = double.NaN; private double _actualWordSpacing = double.NaN; private double _actualTextIndent = double.NaN; private double _actualBorderSpacingHorizontal = double.NaN; private double _actualBorderSpacingVertical = double.NaN; private RColor _actualBackgroundGradient = RColor.Empty; private RColor _actualBorderTopColor = RColor.Empty; private RColor _actualBorderLeftColor = RColor.Empty; private RColor _actualBorderBottomColor = RColor.Empty; private RColor _actualBorderRightColor = RColor.Empty; private RColor _actualBackgroundColor = RColor.Empty; private RFont _actualFont; #endregion #region CSS Properties public string BorderBottomWidth { get { return _borderBottomWidth; } set { _borderBottomWidth = value; _actualBorderBottomWidth = Single.NaN; } } public string BorderLeftWidth { get { return _borderLeftWidth; } set { _borderLeftWidth = value; _actualBorderLeftWidth = Single.NaN; } } public string BorderRightWidth { get { return _borderRightWidth; } set { _borderRightWidth = value; _actualBorderRightWidth = Single.NaN; } } public string BorderTopWidth { get { return _borderTopWidth; } set { _borderTopWidth = value; _actualBorderTopWidth = Single.NaN; } } public string BorderBottomStyle { get { return _borderBottomStyle; } set { _borderBottomStyle = value; } } public string BorderLeftStyle { get { return _borderLeftStyle; } set { _borderLeftStyle = value; } } public string BorderRightStyle { get { return _borderRightStyle; } set { _borderRightStyle = value; } } public string BorderTopStyle { get { return _borderTopStyle; } set { _borderTopStyle = value; } } public string BorderBottomColor { get { return _borderBottomColor; } set { _borderBottomColor = value; _actualBorderBottomColor = RColor.Empty; } } public string BorderLeftColor { get { return _borderLeftColor; } set { _borderLeftColor = value; _actualBorderLeftColor = RColor.Empty; } } public string BorderRightColor { get { return _borderRightColor; } set { _borderRightColor = value; _actualBorderRightColor = RColor.Empty; } } public string BorderTopColor { get { return _borderTopColor; } set { _borderTopColor = value; _actualBorderTopColor = RColor.Empty; } } public string BorderSpacing { get { return _borderSpacing; } set { _borderSpacing = value; } } public string BorderCollapse { get { return _borderCollapse; } set { _borderCollapse = value; } } public string CornerRadius { get { return _cornerRadius; } set { MatchCollection r = RegexParserUtils.Match(RegexParserUtils.CssLength, value); switch (r.Count) { case 1: CornerNeRadius = r[0].Value; CornerNwRadius = r[0].Value; CornerSeRadius = r[0].Value; CornerSwRadius = r[0].Value; break; case 2: CornerNeRadius = r[0].Value; CornerNwRadius = r[0].Value; CornerSeRadius = r[1].Value; CornerSwRadius = r[1].Value; break; case 3: CornerNeRadius = r[0].Value; CornerNwRadius = r[1].Value; CornerSeRadius = r[2].Value; break; case 4: CornerNeRadius = r[0].Value; CornerNwRadius = r[1].Value; CornerSeRadius = r[2].Value; CornerSwRadius = r[3].Value; break; } _cornerRadius = value; } } public string CornerNwRadius { get { return _cornerNwRadius; } set { _cornerNwRadius = value; } } public string CornerNeRadius { get { return _cornerNeRadius; } set { _cornerNeRadius = value; } } public string CornerSeRadius { get { return _cornerSeRadius; } set { _cornerSeRadius = value; } } public string CornerSwRadius { get { return _cornerSwRadius; } set { _cornerSwRadius = value; } } public string MarginBottom { get { return _marginBottom; } set { _marginBottom = value; } } public string MarginLeft { get { return _marginLeft; } set { _marginLeft = value; } } public string MarginRight { get { return _marginRight; } set { _marginRight = value; } } public string MarginTop { get { return _marginTop; } set { _marginTop = value; } } public string PaddingBottom { get { return _paddingBottom; } set { _paddingBottom = value; _actualPaddingBottom = double.NaN; } } public string PaddingLeft { get { return _paddingLeft; } set { _paddingLeft = value; _actualPaddingLeft = double.NaN; } } public string PaddingRight { get { return _paddingRight; } set { _paddingRight = value; _actualPaddingRight = double.NaN; } } public string PaddingTop { get { return _paddingTop; } set { _paddingTop = value; _actualPaddingTop = double.NaN; } } public string Left { get { return _left; } set { _left = value; } } public string Top { get { return _top; } set { _top = value; } } public string Width { get { return _width; } set { _width = value; } } public string MaxWidth { get { return _maxWidth; } set { _maxWidth = value; } } public string Height { get { return _height; } set { _height = value; } } public string BackgroundColor { get { return _backgroundColor; } set { _backgroundColor = value; } } public string BackgroundImage { get { return _backgroundImage; } set { _backgroundImage = value; } } public string BackgroundPosition { get { return _backgroundPosition; } set { _backgroundPosition = value; } } public string BackgroundRepeat { get { return _backgroundRepeat; } set { _backgroundRepeat = value; } } public string BackgroundGradient { get { return _backgroundGradient; } set { _backgroundGradient = value; } } public string BackgroundGradientAngle { get { return _backgroundGradientAngle; } set { _backgroundGradientAngle = value; } } public string Color { get { return _color; } set { _color = value; _actualColor = RColor.Empty; } } public string Display { get { return _display; } set { _display = value; } } public string Direction { get { return _direction; } set { _direction = value; } } public string EmptyCells { get { return _emptyCells; } set { _emptyCells = value; } } public string Float { get { return _float; } set { _float = value; } } public string Position { get { return _position; } set { _position = value; } } public string LineHeight { get { return _lineHeight; } set { _lineHeight = string.Format(NumberFormatInfo.InvariantInfo, "{0}px", CssValueParser.ParseLength(value, Size.Height, this, CssConstants.Em)); } } public string VerticalAlign { get { return _verticalAlign; } set { _verticalAlign = value; } } public string TextIndent { get { return _textIndent; } set { _textIndent = NoEms(value); } } public string TextAlign { get { return _textAlign; } set { _textAlign = value; } } public string TextDecoration { get { return _textDecoration; } set { _textDecoration = value; } } public string WhiteSpace { get { return _whiteSpace; } set { _whiteSpace = value; } } public string Visibility { get { return _visibility; } set { _visibility = value; } } public string WordSpacing { get { return _wordSpacing; } set { _wordSpacing = NoEms(value); } } public string WordBreak { get { return _wordBreak; } set { _wordBreak = value; } } public string FontFamily { get { return _fontFamily; } set { _fontFamily = value; } } public string FontSize { get { return _fontSize; } set { string length = RegexParserUtils.Search(RegexParserUtils.CssLength, value); if (length != null) { string computedValue; CssLength len = new CssLength(length); if (len.HasError) { computedValue = "medium"; } else if (len.Unit == CssUnit.Ems && GetParent() != null) { computedValue = len.ConvertEmToPoints(GetParent().ActualFont.Size).ToString(); } else { computedValue = len.ToString(); } _fontSize = computedValue; } else { _fontSize = value; } } } public string FontStyle { get { return _fontStyle; } set { _fontStyle = value; } } public string FontVariant { get { return _fontVariant; } set { _fontVariant = value; } } public string FontWeight { get { return _fontWeight; } set { _fontWeight = value; } } public string ListStyle { get { return _listStyle; } set { _listStyle = value; } } public string Overflow { get { return _overflow; } set { _overflow = value; } } public string ListStylePosition { get { return _listStylePosition; } set { _listStylePosition = value; } } public string ListStyleImage { get { return _listStyleImage; } set { _listStyleImage = value; } } public string ListStyleType { get { return _listStyleType; } set { _listStyleType = value; } } #endregion /// /// Gets or sets the location of the box /// public RPoint Location { get { return _location; } set { _location = value; } } /// /// Gets or sets the size of the box /// public RSize Size { get { return _size; } set { _size = value; } } /// /// Gets the bounds of the box /// public RRect Bounds { get { return new RRect(Location, Size); } } /// /// Gets the width available on the box, counting padding and margin. /// public double AvailableWidth { get { return Size.Width - ActualBorderLeftWidth - ActualPaddingLeft - ActualPaddingRight - ActualBorderRightWidth; } } /// /// Gets the right of the box. When setting, it will affect only the width of the box. /// public double ActualRight { get { return Location.X + Size.Width; } set { Size = new RSize(value - Location.X, Size.Height); } } /// /// Gets or sets the bottom of the box. /// (When setting, alters only the Size.Height of the box) /// public double ActualBottom { get { return Location.Y + Size.Height; } set { Size = new RSize(Size.Width, value - Location.Y); } } /// /// Gets the left of the client rectangle (Where content starts rendering) /// public double ClientLeft { get { return Location.X + ActualBorderLeftWidth + ActualPaddingLeft; } } /// /// Gets the top of the client rectangle (Where content starts rendering) /// public double ClientTop { get { return Location.Y + ActualBorderTopWidth + ActualPaddingTop; } } /// /// Gets the right of the client rectangle /// public double ClientRight { get { return ActualRight - ActualPaddingRight - ActualBorderRightWidth; } } /// /// Gets the bottom of the client rectangle /// public double ClientBottom { get { return ActualBottom - ActualPaddingBottom - ActualBorderBottomWidth; } } /// /// Gets the client rectangle /// public RRect ClientRectangle { get { return RRect.FromLTRB(ClientLeft, ClientTop, ClientRight, ClientBottom); } } /// /// Gets the actual height /// public double ActualHeight { get { if (double.IsNaN(_actualHeight)) { _actualHeight = CssValueParser.ParseLength(Height, Size.Height, this); } return _actualHeight; } } /// /// Gets the actual height /// public double ActualWidth { get { if (double.IsNaN(_actualWidth)) { _actualWidth = CssValueParser.ParseLength(Width, Size.Width, this); } return _actualWidth; } } /// /// Gets the actual top's padding /// public double ActualPaddingTop { get { if (double.IsNaN(_actualPaddingTop)) { _actualPaddingTop = CssValueParser.ParseLength(PaddingTop, Size.Width, this); } return _actualPaddingTop; } } /// /// Gets the actual padding on the left /// public double ActualPaddingLeft { get { if (double.IsNaN(_actualPaddingLeft)) { _actualPaddingLeft = CssValueParser.ParseLength(PaddingLeft, Size.Width, this); } return _actualPaddingLeft; } } /// /// Gets the actual Padding of the bottom /// public double ActualPaddingBottom { get { if (double.IsNaN(_actualPaddingBottom)) { _actualPaddingBottom = CssValueParser.ParseLength(PaddingBottom, Size.Width, this); } return _actualPaddingBottom; } } /// /// Gets the actual padding on the right /// public double ActualPaddingRight { get { if (double.IsNaN(_actualPaddingRight)) { _actualPaddingRight = CssValueParser.ParseLength(PaddingRight, Size.Width, this); } return _actualPaddingRight; } } /// /// Gets the actual top's Margin /// public double ActualMarginTop { get { if (double.IsNaN(_actualMarginTop)) { if (MarginTop == CssConstants.Auto) MarginTop = "0"; var actualMarginTop = CssValueParser.ParseLength(MarginTop, Size.Width, this); if (MarginLeft.EndsWith("%")) return actualMarginTop; _actualMarginTop = actualMarginTop; } return _actualMarginTop; } } /// /// The margin top value if was effected by margin collapse. /// public double CollapsedMarginTop { get { return double.IsNaN(_collapsedMarginTop) ? 0 : _collapsedMarginTop; } set { _collapsedMarginTop = value; } } /// /// Gets the actual Margin on the left /// public double ActualMarginLeft { get { if (double.IsNaN(_actualMarginLeft)) { if (MarginLeft == CssConstants.Auto) MarginLeft = "0"; var actualMarginLeft = CssValueParser.ParseLength(MarginLeft, Size.Width, this); if (MarginLeft.EndsWith("%")) return actualMarginLeft; _actualMarginLeft = actualMarginLeft; } return _actualMarginLeft; } } /// /// Gets the actual Margin of the bottom /// public double ActualMarginBottom { get { if (double.IsNaN(_actualMarginBottom)) { if (MarginBottom == CssConstants.Auto) MarginBottom = "0"; var actualMarginBottom = CssValueParser.ParseLength(MarginBottom, Size.Width, this); if (MarginLeft.EndsWith("%")) return actualMarginBottom; _actualMarginBottom = actualMarginBottom; } return _actualMarginBottom; } } /// /// Gets the actual Margin on the right /// public double ActualMarginRight { get { if (double.IsNaN(_actualMarginRight)) { if (MarginRight == CssConstants.Auto) MarginRight = "0"; var actualMarginRight = CssValueParser.ParseLength(MarginRight, Size.Width, this); if (MarginLeft.EndsWith("%")) return actualMarginRight; _actualMarginRight = actualMarginRight; } return _actualMarginRight; } } /// /// Gets the actual top border width /// public double ActualBorderTopWidth { get { if (double.IsNaN(_actualBorderTopWidth)) { _actualBorderTopWidth = CssValueParser.GetActualBorderWidth(BorderTopWidth, this); if (string.IsNullOrEmpty(BorderTopStyle) || BorderTopStyle == CssConstants.None) { _actualBorderTopWidth = 0f; } } return _actualBorderTopWidth; } } /// /// Gets the actual Left border width /// public double ActualBorderLeftWidth { get { if (double.IsNaN(_actualBorderLeftWidth)) { _actualBorderLeftWidth = CssValueParser.GetActualBorderWidth(BorderLeftWidth, this); if (string.IsNullOrEmpty(BorderLeftStyle) || BorderLeftStyle == CssConstants.None) { _actualBorderLeftWidth = 0f; } } return _actualBorderLeftWidth; } } /// /// Gets the actual Bottom border width /// public double ActualBorderBottomWidth { get { if (double.IsNaN(_actualBorderBottomWidth)) { _actualBorderBottomWidth = CssValueParser.GetActualBorderWidth(BorderBottomWidth, this); if (string.IsNullOrEmpty(BorderBottomStyle) || BorderBottomStyle == CssConstants.None) { _actualBorderBottomWidth = 0f; } } return _actualBorderBottomWidth; } } /// /// Gets the actual Right border width /// public double ActualBorderRightWidth { get { if (double.IsNaN(_actualBorderRightWidth)) { _actualBorderRightWidth = CssValueParser.GetActualBorderWidth(BorderRightWidth, this); if (string.IsNullOrEmpty(BorderRightStyle) || BorderRightStyle == CssConstants.None) { _actualBorderRightWidth = 0f; } } return _actualBorderRightWidth; } } /// /// Gets the actual top border Color /// public RColor ActualBorderTopColor { get { if (_actualBorderTopColor.IsEmpty) { _actualBorderTopColor = GetActualColor(BorderTopColor); } return _actualBorderTopColor; } } protected abstract RColor GetActualColor(string colorStr); /// /// Gets the actual Left border Color /// public RColor ActualBorderLeftColor { get { if ((_actualBorderLeftColor.IsEmpty)) { _actualBorderLeftColor = GetActualColor(BorderLeftColor); } return _actualBorderLeftColor; } } /// /// Gets the actual Bottom border Color /// public RColor ActualBorderBottomColor { get { if ((_actualBorderBottomColor.IsEmpty)) { _actualBorderBottomColor = GetActualColor(BorderBottomColor); } return _actualBorderBottomColor; } } /// /// Gets the actual Right border Color /// public RColor ActualBorderRightColor { get { if ((_actualBorderRightColor.IsEmpty)) { _actualBorderRightColor = GetActualColor(BorderRightColor); } return _actualBorderRightColor; } } /// /// Gets the actual length of the north west corner /// public double ActualCornerNw { get { if (double.IsNaN(_actualCornerNw)) { _actualCornerNw = CssValueParser.ParseLength(CornerNwRadius, 0, this); } return _actualCornerNw; } } /// /// Gets the actual length of the north east corner /// public double ActualCornerNe { get { if (double.IsNaN(_actualCornerNe)) { _actualCornerNe = CssValueParser.ParseLength(CornerNeRadius, 0, this); } return _actualCornerNe; } } /// /// Gets the actual length of the south east corner /// public double ActualCornerSe { get { if (double.IsNaN(_actualCornerSe)) { _actualCornerSe = CssValueParser.ParseLength(CornerSeRadius, 0, this); } return _actualCornerSe; } } /// /// Gets the actual length of the south west corner /// public double ActualCornerSw { get { if (double.IsNaN(_actualCornerSw)) { _actualCornerSw = CssValueParser.ParseLength(CornerSwRadius, 0, this); } return _actualCornerSw; } } /// /// Gets a value indicating if at least one of the corners of the box is rounded /// public bool IsRounded { get { return ActualCornerNe > 0f || ActualCornerNw > 0f || ActualCornerSe > 0f || ActualCornerSw > 0f; } } /// /// Gets the actual width of whitespace between words. /// public double ActualWordSpacing { get { return _actualWordSpacing; } } /// /// /// Gets the actual color for the text. /// public RColor ActualColor { get { if (_actualColor.IsEmpty) { _actualColor = GetActualColor(Color); } return _actualColor; } } /// /// Gets the actual background color of the box /// public RColor ActualBackgroundColor { get { if (_actualBackgroundColor.IsEmpty) { _actualBackgroundColor = GetActualColor(BackgroundColor); } return _actualBackgroundColor; } } /// /// Gets the second color that creates a gradient for the background /// public RColor ActualBackgroundGradient { get { if (_actualBackgroundGradient.IsEmpty) { _actualBackgroundGradient = GetActualColor(BackgroundGradient); } return _actualBackgroundGradient; } } /// /// Gets the actual angle specified for the background gradient /// public double ActualBackgroundGradientAngle { get { if (double.IsNaN(_actualBackgroundGradientAngle)) { _actualBackgroundGradientAngle = CssValueParser.ParseNumber(BackgroundGradientAngle, 360f); } return _actualBackgroundGradientAngle; } } /// /// Gets the actual font of the parent /// public RFont ActualParentFont { get { return GetParent() == null ? ActualFont : GetParent().ActualFont; } } /// /// Gets the font that should be actually used to paint the text of the box /// public RFont ActualFont { get { if (_actualFont == null) { if (string.IsNullOrEmpty(FontFamily)) { FontFamily = CssConstants.DefaultFont; } if (string.IsNullOrEmpty(FontSize)) { FontSize = CssConstants.FontSize.ToString(CultureInfo.InvariantCulture) + "pt"; } RFontStyle st = RFontStyle.Regular; if (FontStyle == CssConstants.Italic || FontStyle == CssConstants.Oblique) { st |= RFontStyle.Italic; } if (FontWeight != CssConstants.Normal && FontWeight != CssConstants.Lighter && !string.IsNullOrEmpty(FontWeight) && FontWeight != CssConstants.Inherit) { st |= RFontStyle.Bold; } double fsize; double parentSize = CssConstants.FontSize; if (GetParent() != null) parentSize = GetParent().ActualFont.Size; switch (FontSize) { case CssConstants.Medium: fsize = CssConstants.FontSize; break; case CssConstants.XXSmall: fsize = CssConstants.FontSize - 4; break; case CssConstants.XSmall: fsize = CssConstants.FontSize - 3; break; case CssConstants.Small: fsize = CssConstants.FontSize - 2; break; case CssConstants.Large: fsize = CssConstants.FontSize + 2; break; case CssConstants.XLarge: fsize = CssConstants.FontSize + 3; break; case CssConstants.XXLarge: fsize = CssConstants.FontSize + 4; break; case CssConstants.Smaller: fsize = parentSize - 2; break; case CssConstants.Larger: fsize = parentSize + 2; break; default: fsize = CssValueParser.ParseLength(FontSize, parentSize, parentSize, null, true, true); break; } if (fsize <= 1f) { fsize = CssConstants.FontSize; } _actualFont = GetCachedFont(FontFamily, fsize, st); } return _actualFont; } } protected abstract RFont GetCachedFont(string fontFamily, double fsize, RFontStyle st); /// /// Gets the line height /// public double ActualLineHeight { get { if (double.IsNaN(_actualLineHeight)) { _actualLineHeight = .9f * CssValueParser.ParseLength(LineHeight, Size.Height, this); } return _actualLineHeight; } } /// /// Gets the text indentation (on first line only) /// public double ActualTextIndent { get { if (double.IsNaN(_actualTextIndent)) { _actualTextIndent = CssValueParser.ParseLength(TextIndent, Size.Width, this); } return _actualTextIndent; } } /// /// Gets the actual horizontal border spacing for tables /// public double ActualBorderSpacingHorizontal { get { if (double.IsNaN(_actualBorderSpacingHorizontal)) { MatchCollection matches = RegexParserUtils.Match(RegexParserUtils.CssLength, BorderSpacing); if (matches.Count == 0) { _actualBorderSpacingHorizontal = 0; } else if (matches.Count > 0) { _actualBorderSpacingHorizontal = CssValueParser.ParseLength(matches[0].Value, 1, this); } } return _actualBorderSpacingHorizontal; } } /// /// Gets the actual vertical border spacing for tables /// public double ActualBorderSpacingVertical { get { if (double.IsNaN(_actualBorderSpacingVertical)) { MatchCollection matches = RegexParserUtils.Match(RegexParserUtils.CssLength, BorderSpacing); if (matches.Count == 0) { _actualBorderSpacingVertical = 0; } else if (matches.Count == 1) { _actualBorderSpacingVertical = CssValueParser.ParseLength(matches[0].Value, 1, this); } else { _actualBorderSpacingVertical = CssValueParser.ParseLength(matches[1].Value, 1, this); } } return _actualBorderSpacingVertical; } } /// /// Get the parent of this css properties instance. /// /// protected abstract CssBoxProperties GetParent(); /// /// Gets the height of the font in the specified units /// /// public double GetEmHeight() { return ActualFont.Height; } /// /// Ensures that the specified length is converted to pixels if necessary /// /// protected string NoEms(string length) { var len = new CssLength(length); if (len.Unit == CssUnit.Ems) { length = len.ConvertEmToPixels(GetEmHeight()).ToString(); } return length; } /// /// Set the style/width/color for all 4 borders on the box.
/// if null is given for a value it will not be set. ///
/// optional: the style to set /// optional: the width to set /// optional: the color to set protected void SetAllBorders(string style = null, string width = null, string color = null) { if (style != null) BorderLeftStyle = BorderTopStyle = BorderRightStyle = BorderBottomStyle = style; if (width != null) BorderLeftWidth = BorderTopWidth = BorderRightWidth = BorderBottomWidth = width; if (color != null) BorderLeftColor = BorderTopColor = BorderRightColor = BorderBottomColor = color; } /// /// Measures the width of whitespace between words (set ). /// protected void MeasureWordSpacing(RGraphics g) { if (double.IsNaN(ActualWordSpacing)) { _actualWordSpacing = CssUtils.WhiteSpace(g, this); if (WordSpacing != CssConstants.Normal) { string len = RegexParserUtils.Search(RegexParserUtils.CssLength, WordSpacing); _actualWordSpacing += CssValueParser.ParseLength(len, 1, this); } } } /// /// Inherits inheritable values from specified box. /// /// Set to true to inherit all CSS properties instead of only the ineritables /// Box to inherit the properties protected void InheritStyle(CssBox p, bool everything) { if (p != null) { _borderSpacing = p._borderSpacing; _borderCollapse = p._borderCollapse; _color = p._color; _emptyCells = p._emptyCells; _whiteSpace = p._whiteSpace; _visibility = p._visibility; _textIndent = p._textIndent; _textAlign = p._textAlign; _verticalAlign = p._verticalAlign; _fontFamily = p._fontFamily; _fontSize = p._fontSize; _fontStyle = p._fontStyle; _fontVariant = p._fontVariant; _fontWeight = p._fontWeight; _listStyleImage = p._listStyleImage; _listStylePosition = p._listStylePosition; _listStyleType = p._listStyleType; _listStyle = p._listStyle; _lineHeight = p._lineHeight; _wordBreak = p.WordBreak; _direction = p._direction; if (everything) { _backgroundColor = p._backgroundColor; _backgroundGradient = p._backgroundGradient; _backgroundGradientAngle = p._backgroundGradientAngle; _backgroundImage = p._backgroundImage; _backgroundPosition = p._backgroundPosition; _backgroundRepeat = p._backgroundRepeat; _borderTopWidth = p._borderTopWidth; _borderRightWidth = p._borderRightWidth; _borderBottomWidth = p._borderBottomWidth; _borderLeftWidth = p._borderLeftWidth; _borderTopColor = p._borderTopColor; _borderRightColor = p._borderRightColor; _borderBottomColor = p._borderBottomColor; _borderLeftColor = p._borderLeftColor; _borderTopStyle = p._borderTopStyle; _borderRightStyle = p._borderRightStyle; _borderBottomStyle = p._borderBottomStyle; _borderLeftStyle = p._borderLeftStyle; _bottom = p._bottom; _cornerNwRadius = p._cornerNwRadius; _cornerNeRadius = p._cornerNeRadius; _cornerSeRadius = p._cornerSeRadius; _cornerSwRadius = p._cornerSwRadius; _cornerRadius = p._cornerRadius; _display = p._display; _float = p._float; _height = p._height; _marginBottom = p._marginBottom; _marginLeft = p._marginLeft; _marginRight = p._marginRight; _marginTop = p._marginTop; _left = p._left; _lineHeight = p._lineHeight; _overflow = p._overflow; _paddingLeft = p._paddingLeft; _paddingBottom = p._paddingBottom; _paddingRight = p._paddingRight; _paddingTop = p._paddingTop; _right = p._right; _textDecoration = p._textDecoration; _top = p._top; _position = p._position; _width = p._width; _maxWidth = p._maxWidth; _wordSpacing = p._wordSpacing; } } } } }