Пример #1
0
 /// <summary>
 /// Clip the region the graphics will draw on by the overflow style of the containing block.<br/>
 /// Recursively travel up the tree to find containing block that has overflow style set to hidden. if not
 /// block found there will be no clipping and null will be returned.
 /// </summary>
 /// <param name="g">the graphics to clip</param>
 /// <param name="box">the box that is rendered to get containing blocks</param>
 /// <returns>the prev region if clipped, otherwise null</returns>
 public static RectangleF ClipGraphicsByOverflow(IGraphics g, CssBox box)
 {
     var containingBlock = box.ContainingBlock;
     while (true)
     {
         if (containingBlock.Overflow == CssConstants.Hidden)
         {
             var prevClip = g.GetClip();
             var rect = box.ContainingBlock.ClientRectangle;
             rect.X -= 2; // atodo: find better way to fix it
             rect.Width += 2;
             rect.Offset(box.HtmlContainer.ScrollOffset);
             rect.Intersect(prevClip);
             g.SetClip(rect);
             return prevClip;
         }
         else
         {
             var cBlock = containingBlock.ContainingBlock;
             if (cBlock == containingBlock)
                 return RectangleF.Empty;
             containingBlock = cBlock;
         }
     }
 }
Пример #2
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="owner">the CSS box owner of the word</param>
 /// <param name="word">the word chars </param>
 /// <param name="hasSpaceBefore">was there a whitespace before the word chars (before trim)</param>
 /// <param name="hasSpaceAfter">was there a whitespace after the word chars (before trim)</param>
 public CssBoxWord(CssBox owner, string word, bool hasSpaceBefore, bool hasSpaceAfter)
 {
     _ownerBox = owner;
     _word = word;
     _hasSpaceBefore = hasSpaceBefore;
     _hasSpaceAfter = hasSpaceAfter;
 }
Пример #3
0
        /// <summary>
        /// Init.
        /// </summary>
        /// <param name="parent">the parent box of this box</param>
        /// <param name="tag">the html tag data of this box</param>
        public CssBoxFrame(CssBox parent, HtmlTag tag)
            : base(parent, tag)
        {
            _imageWord = new CssRectImage(this);
            Words.Add(_imageWord);

            Uri uri;
            if (Uri.TryCreate(GetAttribute("src"),UriKind.Absolute, out uri))
            {
                if(uri.Host.IndexOf("youtube.com",StringComparison.InvariantCultureIgnoreCase) > -1)
                {
                    _isVideo = true;
                    LoadYoutubeDataAsync(uri);
                }
                else if (uri.Host.IndexOf("vimeo.com",StringComparison.InvariantCultureIgnoreCase) > -1)
                {
                    _isVideo = true;
                    LoadVimeoDataAsync(uri);
                }
            }

            if (!_isVideo)
            {
                SetErrorBorder();
            }
        }
Пример #4
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="owner">the CSS box owner of the word</param>
 /// <param name="text">the word chars </param>
 /// <param name="hasSpaceBefore">was there a whitespace before the word chars (before trim)</param>
 /// <param name="hasSpaceAfter">was there a whitespace after the word chars (before trim)</param>
 public CssRectWord(CssBox owner, string text, bool hasSpaceBefore, bool hasSpaceAfter)
     : base(owner)
 {
     _text = text;
     _hasSpaceBefore = hasSpaceBefore;
     _hasSpaceAfter = hasSpaceAfter;
 }
Пример #5
0
 /// <summary>
 /// Cascades to the TD's the border spacified in the TABLE tag.
 /// </summary>
 /// <param name="table"></param>
 /// <param name="border"></param>
 private static void ApplyTableBorder(CssBox table, string border)
 {
     SetForAllCells(table, cell =>
     {
         cell.BorderLeftStyle = cell.BorderTopStyle = cell.BorderRightStyle = cell.BorderBottomStyle = CssConstants.Solid;
         cell.BorderLeftWidth = cell.BorderTopWidth = cell.BorderRightWidth = cell.BorderBottomWidth = border;
     });
 }
Пример #6
0
 /// <summary>
 /// Creates a new LineBox
 /// </summary>
 public CssLineBox(CssBox ownerBox)
 {
     _rects = new Dictionary<CssBox, RectangleF>();
     _relatedBoxes = new List<CssBox>();
     _words = new List<CssBoxWord>();
     _ownerBox = ownerBox;
     _ownerBox.LineBoxes.Add(this);
 }
Пример #7
0
 /// <summary>
 /// Generate html from the given dom tree.<br/>
 /// Generate all the tyle inside the html.
 /// </summary>
 /// <param name="root">the box of the html generate html from</param>
 /// <param name="styleGen">Optional: controls the way styles are generated when html is generated</param>
 /// <param name="onlySelected">Optional: true - generate only selected html subset, false - generate all (default - false)</param>
 /// <returns>generated html</returns>
 public static string GenerateHtml(CssBox root, HtmlGenerationStyle styleGen = HtmlGenerationStyle.Inline, bool onlySelected = false)
 {
     var sb = new StringBuilder();
     if (root != null)
     {
         WriteHtml(sb, root, 0, styleGen, onlySelected ? CollectSelectedHtmlTags(root) : null);
     }
     return sb.ToString();
 }
Пример #8
0
        public CssSpacingBox(CssBox tableBox, ref CssBox extendedBox, int startRow)
            : base(tableBox, new HtmlTag("none",new Dictionary<string, string>{{"colspan","1"}} ))
        {
            _extendedBox = extendedBox;
            Display = CssConstants.None;

            _startRow = startRow;
            _endRow = startRow + Int32.Parse(extendedBox.GetAttribute("rowspan", "1")) - 1;
        }
Пример #9
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="parentBox">optional: the parent of this css box in html</param>
 /// <param name="tag">optional: the html tag associated with this css box</param>
 internal CssBox(CssBox parentBox = null, HtmlTag tag = null)
 {
     if(parentBox != null)
     {
         _parentBox = parentBox;
         _parentBox.Boxes.Add(this);
     }
     _htmltag = tag;
 }
Пример #10
0
 /// <summary>
 /// Asigns the given css style blocks to the given css box checking if matching.
 /// </summary>
 /// <param name="box">the css box to assign css to</param>
 /// <param name="cssData">the css data to use to get the matching css blocks</param>
 /// <param name="className">the class selector to search for css blocks</param>
 private static void AssignCssBlocks(CssBox box, CssData cssData, string className)
 {
     var blocks = cssData.GetCssBlock(className);
     foreach (var block in blocks)
     {
         if (IsBlockAssignableToBox(box, block))
         {
             AssignCssBlock(box, block);
         }
     }
 }
Пример #11
0
        /// <summary>
        /// Check if the given box contains only inline child boxes.
        /// </summary>
        /// <param name="box">the box to check</param>
        /// <returns>true - only inline child boxes, false - otherwise</returns>
        public static bool ContainsInlinesOnly(CssBox box)
        {
            foreach (CssBox b in box.Boxes)
            {
                if (!b.IsInline)
                {
                    return false;
                }
            }

            return true;
        }
Пример #12
0
 /// <summary>
 /// Asigns the given css style block properties to the given css box.
 /// </summary>
 /// <param name="box">the css box to assign css to</param>
 /// <param name="block">the css block to assign</param>
 private static void AssignCssBlock(CssBox box, CssBlock block)
 {
     foreach (var prop in block.Properties)
     {
         var value = prop.Value;
         if (prop.Value == CssConstants.Inherit && box.ParentBox != null)
         {
             value = CssUtils.GetPropertyValue(box.ParentBox, prop.Key);
         }
         CssUtils.SetPropertyValue(box, prop.Key, value);
     }
 }
Пример #13
0
        /// <summary>
        /// Check if the given box contains only inline child boxes.
        /// </summary>
        /// <param name="box">the box to check</param>
        /// <returns>true - only inline child boxes, false - otherwise</returns>
        public static bool ContainsInlinesOnly(CssBox box)
        {
            foreach (CssBox b in box.Boxes)
            {
                if (b.Display != CssConstants.Inline)
                {
                    return false;
                }
            }

            return true;
        }
Пример #14
0
        public CssTable(CssBox tableBox, Graphics g)
            : this()
        {
            if (!(tableBox.Display == CssConstants.Table || tableBox.Display == CssConstants.InlineTable))
                throw new ArgumentException("Box is not a table", "tableBox");

            _tableBox = tableBox;

            MeasureWords(tableBox, g);

            Analyze(g);
        }
Пример #15
0
 /// <summary>
 /// Recursively searches for the parent with the specified HTML Tag name
 /// </summary>
 /// <param name="root"></param>
 /// <param name="tagName"></param>
 /// <param name="box"></param>
 public static CssBox FindParent(CssBox root, string tagName, CssBox box)
 {
     if (box == null)
     {
         return root;
     }
     else if (box.HtmlTag != null && box.HtmlTag.Name.Equals(tagName, StringComparison.CurrentCultureIgnoreCase))
     {
         return box.ParentBox ?? root;
     }
     else
     {
         return FindParent(root, tagName, box.ParentBox);
     }
 }
Пример #16
0
        /// <summary>
        /// Applies special vertical alignment for table-cells
        /// </summary>
        /// <param name="g"></param>
        /// <param name="cell"></param>
        public static void ApplyCellVerticalAlignment(IGraphics g, CssBox cell)
        {
            ArgChecker.AssertArgNotNull(g, "g");
            ArgChecker.AssertArgNotNull(cell, "cell");

            if (cell.VerticalAlign == CssConstants.Top || cell.VerticalAlign == CssConstants.Baseline) return;

            float cellbot = cell.ClientBottom;
            float bottom = cell.GetMaximumBottom(cell, 0f);
            float dist = 0f;

            if (cell.VerticalAlign == CssConstants.Bottom)
            {
                dist = cellbot - bottom;
            }
            else if (cell.VerticalAlign == CssConstants.Middle)
            {
                dist = (cellbot - bottom) / 2;
            }

            foreach (CssBox b in cell.Boxes)
            {
                b.OffsetTop(dist);
            }

            //float top = cell.ClientTop;
            //float bottom = cell.ClientBottom;
            //bool middle = cell.VerticalAlign == CssConstants.Middle;

            //foreach (LineBox line in cell.LineBoxes)
            //{
            //    for (int i = 0; i < line.RelatedBoxes.Count; i++)
            //    {

            //        float diff = bottom - line.RelatedBoxes[i].Rectangles[line].Bottom;
            //        if (middle) diff /= 2f;
            //        RectangleF r = line.RelatedBoxes[i].Rectangles[line];
            //        line.RelatedBoxes[i].Rectangles[line] = new RectangleF(r.X, r.Y + diff, r.Width, r.Height);

            //    }

            //    foreach (BoxWord word in line.Words)
            //    {
            //        float gap = word.Top - top;
            //        word.Top = bottom - gap - word.Height;
            //    }
            //}
        }
        /// <summary>
        /// Draw the background image of the given box in the given rectangle.<br/>
        /// Handle background-repeat and background-position values.
        /// </summary>
        /// <param name="g">the device to draw into</param>
        /// <param name="box">the box to draw its background image</param>
        /// <param name="imageLoadHandler">the handler that loads image to draw</param>
        /// <param name="rectangle">the rectangle to draw image in</param>
        public static void DrawBackgroundImage(IGraphics g, CssBox box, ImageLoadHandler imageLoadHandler, RectangleF rectangle)
        {
            // image size depends if specific rectangle given in image loader
            var imgSize = new Size(imageLoadHandler.Rectangle == Rectangle.Empty ? imageLoadHandler.Image.Width : imageLoadHandler.Rectangle.Width,
                                   imageLoadHandler.Rectangle == Rectangle.Empty ? imageLoadHandler.Image.Height : imageLoadHandler.Rectangle.Height);

            // get the location by BackgroundPosition value
            var location = GetLocation(box.BackgroundPosition, rectangle, imgSize);

            var srcRect = imageLoadHandler.Rectangle == Rectangle.Empty
                              ? new Rectangle(0, 0, imgSize.Width, imgSize.Height)
                              : new Rectangle(imageLoadHandler.Rectangle.Left, imageLoadHandler.Rectangle.Top, imgSize.Width, imgSize.Height);

            // initial image destination rectangle
            var destRect = new Rectangle(location, imgSize);

            // need to clip so repeated image will be cut on rectangle
            var prevClip = g.GetClip();
            var lRectangle = rectangle;
            lRectangle.Intersect(prevClip);
            g.SetClip(lRectangle);

            switch( box.BackgroundRepeat )
            {
                case "no-repeat":
                    g.DrawImage(imageLoadHandler.Image, destRect, srcRect);
                    break;
                case "repeat-x":
                    DrawRepeatX(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize);
                    break;
                case "repeat-y":
                    DrawRepeatY(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize);
                    break;
                default:
                    DrawRepeat(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize);
                    break;
            }

            g.SetClip(prevClip);
        }
Пример #18
0
 /// <summary>
 /// Draws all the border of the box with respect to style, width, etc.
 /// </summary>
 /// <param name="g">the device to draw into</param>
 /// <param name="box">the box to draw borders for</param>
 /// <param name="rect">the bounding rectangle to draw in</param>
 /// <param name="isFirst">is it the first rectangle of the element</param>
 /// <param name="isLast">is it the last rectangle of the element</param>
 public static void DrawBoxBorders(IGraphics g, CssBox box, RectangleF rect, bool isFirst, bool isLast)
 {
     if( rect.Width > 0 && rect.Height > 0 )
     {
         if (!(string.IsNullOrEmpty(box.BorderTopStyle) || box.BorderTopStyle == CssConstants.None || box.BorderTopStyle == CssConstants.Hidden) && box.ActualBorderTopWidth > 0)
         {
             DrawBorder(Border.Top, box, g, rect, isFirst, isLast);
         }
         if (isFirst && !(string.IsNullOrEmpty(box.BorderLeftStyle) || box.BorderLeftStyle == CssConstants.None || box.BorderLeftStyle == CssConstants.Hidden) && box.ActualBorderLeftWidth > 0)
         {
             DrawBorder(Border.Left, box, g, rect, true, isLast);
         }
         if (!(string.IsNullOrEmpty(box.BorderBottomStyle) || box.BorderBottomStyle == CssConstants.None || box.BorderBottomStyle == CssConstants.Hidden) && box.ActualBorderBottomWidth > 0)
         {
             DrawBorder(Border.Bottom, box, g, rect, isFirst, isLast);
         }
         if (isLast && !(string.IsNullOrEmpty(box.BorderRightStyle) || box.BorderRightStyle == CssConstants.None || box.BorderRightStyle == CssConstants.Hidden) && box.ActualBorderRightWidth > 0)
         {
             DrawBorder(Border.Right, box, g, rect, isFirst, true);
         }
     }
 }
Пример #19
0
        /// <summary>
        /// Check if the given box contains only inline child boxes in all subtree.
        /// </summary>
        /// <param name="box">the box to check</param>
        /// <returns>true - only inline child boxes, false - otherwise</returns>
        private static bool ContainsInlinesOnlyDeep(CssBox box)
        {
            foreach (var childBox in box.Boxes)
            {
                if (!childBox.IsInline || !ContainsInlinesOnlyDeep(childBox))
                {
                    return false;
                }
            }

            return true;
        }
Пример #20
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="tableBox"></param>
 private CssLayoutEngineTable(CssBox tableBox)
 {
     _tableBox = tableBox;
 }
Пример #21
0
        /// <summary>
        /// Applies style to all boxes in the tree.<br/>
        /// If the html tag has style defined for each apply that style to the css box of the tag.<br/>
        /// If the html tag has "class" attribute and the class name has style defined apply that style on the tag css box.<br/>
        /// If the html tag has "style" attribute parse it and apply the parsed style on the tag css box.<br/>
        /// If the html tag is "style" tag parse it content and add to the css data for all future tags parsing.<br/>
        /// If the html tag is "link" that point to style data parse it content and add to the css data for all future tags parsing.<br/>
        /// </summary>
        /// <param name="box"></param>
        /// <param name="bridge"> </param>
        /// <param name="cssData"> </param>
        /// <param name="cssDataChanged">check if the css data has been modified by the handled html not to change the base css data</param>
        private static void CascadeStyles(CssBox box, object bridge, ref CssData cssData, ref bool cssDataChanged)
        {
            box.InheritStyle();

            if (box.HtmlTag != null)
            {
                // try assign style using the html element tag
                AssignCssBlocks(box, cssData, box.HtmlTag.Name);

                // try assign style using the "class" attribute of the html element
                if (box.HtmlTag.HasAttribute("class"))
                {
                    AssignCssBlocks(box, cssData, "." + box.HtmlTag.Attributes["class"]);
                    AssignCssBlocks(box, cssData, box.HtmlTag.Name + "." + box.HtmlTag.Attributes["class"]);
                }

                // try assign style using the "id" attribute of the html element
                if (box.HtmlTag.HasAttribute("id"))
                {
                    AssignCssBlocks(box, cssData, "#" + box.HtmlTag.Attributes["id"]);
                }

                HtmlParser.TranslateAttributes(box.HtmlTag, box);

                // Check for the style="" attribute
                if (box.HtmlTag.HasAttribute("style"))
                {
                    var block = CssParser.ParseCssBlockImp(box.HtmlTag.Name, box.HtmlTag.Attributes["style"]);
                    AssignCssBlock(box, block);
                }

                // Check for the <style> tag
                if (box.HtmlTag.Name.Equals("style", StringComparison.CurrentCultureIgnoreCase) && box.Boxes.Count == 1)
                {
                    CloneCssData(ref cssData, ref cssDataChanged);
                    CssParser.ParseStyleSheet(cssData, box.Boxes[0].Text);
                }

                // Check for the <link rel=stylesheet> tag
                if (box.HtmlTag.Name.Equals("link", StringComparison.CurrentCultureIgnoreCase) &&
                    box.GetAttribute("rel", string.Empty).Equals("stylesheet", StringComparison.CurrentCultureIgnoreCase))
                {
                    CloneCssData(ref cssData, ref cssDataChanged);
                    var styleSheet = CssValueParser.GetStyleSheet(box.GetAttribute("href", string.Empty), bridge);
                    CssParser.ParseStyleSheet(cssData, styleSheet);
                }
            }

            foreach (var childBox in box.Boxes)
            {
                CascadeStyles(childBox, bridge, ref cssData, ref cssDataChanged);
            }
        }
Пример #22
0
        /// <summary>
        /// Check if the given css block is assignable to the given css box.<br/>
        /// the block is assignable if it has no hierarchial selectors or if the hierarchy matches.<br/>
        /// </summary>
        /// <param name="box">the box to check assign to</param>
        /// <param name="block">the block to check assign of</param>
        /// <returns>true - the block is assignable to the box, false - otherwise</returns>
        private static bool IsBlockAssignableToBox(CssBox box, CssBlock block)
        {
            if (block.Selectors != null)
            {
                foreach (var selector in block.Selectors)
                {
                    bool matched = false;
                    while (!matched)
                    {
                        box = box.ParentBox;
                        while (box != null && box.HtmlTag == null)
                            box = box.ParentBox;

                        if (box == null)
                            return false;

                        if (box.HtmlTag.Name == selector.Class)
                            matched = true;

                        if (!matched && box.HtmlTag.HasAttribute("class"))
                        {
                            var className = box.HtmlTag.Attributes["class"];
                            if (selector.Class == "." + className || selector.Class == box.HtmlTag.Name + "." + className)
                                matched = true;
                        }

                        if (!matched && box.HtmlTag.HasAttribute("id"))
                        {
                            var id = box.HtmlTag.Attributes["id"];
                            if (selector.Class == "#" + id)
                                matched = true;
                        }

                        if (!matched && selector.DirectParent)
                            return false;
                    }
                }
            }

            return true;
        }
Пример #23
0
        /// <summary>
        /// Inherits inheritable values from specified box.
        /// </summary>
        /// <param name="everything">Set to true to inherit all CSS properties instead of only the ineritables</param>
        /// <param name="p">Box to inherit the properties</param>
        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;
                }
            }
        }
Пример #24
0
        /// <summary>
        /// Rearrange the DOM of the box to have block box with boxes before the inner block box and after.
        /// </summary>
        /// <param name="box">the box that has the problem</param>
        private static void CorrectBlockInsideInlineImp(CssBox box)
        {
            if (box.Boxes.Count > 1)
            {
                var leftBlock = CssBox.CreateBlock(box);

                while (ContainsInlinesOnlyDeep(box.Boxes[0]))
                    box.Boxes[0].ParentBox = leftBlock;
                leftBlock.SetBeforeBox(box.Boxes[0]);

                var splitBox = box.Boxes[1];
                splitBox.ParentBox = null;

                CorrectBlockSplitBadBox(box, splitBox, leftBlock);

                if (box.Boxes.Count > 2)
                {
                    var rightBox = CssBox.CreateBox(box, null, box.Boxes[2]);
                    while (box.Boxes.Count > 3)
                        box.Boxes[3].ParentBox = rightBox;
                }
                box.Display = CssConstants.Block;

            }
            else
            {
                box.Boxes[0].Display = CssConstants.Block;
            }
        }
Пример #25
0
        /// <summary>
        /// Makes block boxes be among only block boxes and all inline boxes have block parent box.<br/>
        /// Inline boxes should live in a pool of Inline boxes only so they will define a single block.<br/>
        /// At the end of this process a block box will have only block siblings and inline box will have
        /// only inline siblings.
        /// </summary>
        /// <param name="box">the current box to correct its sub-tree</param>
        private static void CorrectInlineBoxesParent(CssBox box)
        {
            if (ContainsVariantBoxes(box))
            {
                for (int i = 0; i < box.Boxes.Count; i++)
                {
                    if (box.Boxes[i].IsInline)
                    {
                        var newbox = CssBox.CreateBlock(box, null, box.Boxes[i++]);
                        while (i < box.Boxes.Count && box.Boxes[i].IsInline)
                        {
                            box.Boxes[i].ParentBox = newbox;
                        }
                    }
                }
            }

            if (!DomUtils.ContainsInlinesOnly(box))
            {
                foreach (var childBox in box.Boxes)
                {
                    CorrectInlineBoxesParent(childBox);
                }
            }
        }
Пример #26
0
 /// <summary>
 /// Creates a new BoxWord which represents an image
 /// </summary>
 /// <param name="owner">the CSS box owner of the word</param>
 public CssRectImage(CssBox owner)
     : base(owner)
 {
 }
Пример #27
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="parent">the parent box of this box</param>
 /// <param name="tag">the html tag data of this box</param>
 public CssBoxImage(CssBox parent, HtmlTag tag)
     : base(parent, tag)
 {
     _imageWord = new CssRectImage(this);
     Words.Add(_imageWord);
 }
Пример #28
0
        /// <summary>
        /// Get the table boxes into the proper fields.
        /// </summary>
        private void AssignBoxKinds()
        {
            foreach (var box in _tableBox.Boxes)
            {
                switch (box.Display)
                {
                case CssConstants.TableCaption:
                    _caption = box;
                    break;

                case CssConstants.TableRow:
                    _bodyrows.Add(box);
                    break;

                case CssConstants.TableRowGroup:
                    foreach (CssBox childBox in box.Boxes)
                    {
                        if (childBox.Display == CssConstants.TableRow)
                        {
                            _bodyrows.Add(childBox);
                        }
                    }
                    break;

                case CssConstants.TableHeaderGroup:
                    if (_headerBox != null)
                    {
                        _bodyrows.Add(box);
                    }
                    else
                    {
                        _headerBox = box;
                    }
                    break;

                case CssConstants.TableFooterGroup:
                    if (_footerBox != null)
                    {
                        _bodyrows.Add(box);
                    }
                    else
                    {
                        _footerBox = box;
                    }
                    break;

                case CssConstants.TableColumn:
                    for (int i = 0; i < GetSpan(box); i++)
                    {
                        _columns.Add(box);
                    }
                    break;

                case CssConstants.TableColumnGroup:
                    if (box.Boxes.Count == 0)
                    {
                        int gspan = GetSpan(box);
                        for (int i = 0; i < gspan; i++)
                        {
                            _columns.Add(box);
                        }
                    }
                    else
                    {
                        foreach (CssBox bb in box.Boxes)
                        {
                            int bbspan = GetSpan(bb);
                            for (int i = 0; i < bbspan; i++)
                            {
                                _columns.Add(bb);
                            }
                        }
                    }
                    break;
                }
            }

            if (_headerBox != null)
            {
                _allRows.AddRange(_headerBox.Boxes);
            }

            _allRows.AddRange(_bodyrows);

            if (_footerBox != null)
            {
                _allRows.AddRange(_footerBox.Boxes);
            }
        }
Пример #29
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="g">Device Info</param>
        /// <param name="blockbox">Blockbox that contains the text flow</param>
        /// <param name="box">Current box to flow its content</param>
        /// <param name="limitRight">Maximum reached right</param>
        /// <param name="linespacing">Space to use between rows of text</param>
        /// <param name="startx">x starting coordinate for when breaking lines of text</param>
        /// <param name="line">Current linebox being used</param>
        /// <param name="curx">Current x coordinate that will be the left of the next word</param>
        /// <param name="cury">Current y coordinate that will be the top of the next word</param>
        /// <param name="maxRight">Maximum right reached so far</param>
        /// <param name="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float limitRight, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxRight, ref float maxbottom)
        {
            var startY = cury;

            box.FirstHostingLineBox = line;
            var localCurx      = curx;
            var localMaxRight  = maxRight;
            var localmaxbottom = maxbottom;

            foreach (CssBox b in box.Boxes)
            {
                float leftspacing  = b.Position != CssConstants.Absolute ? b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft : 0;
                float rightspacing = b.Position != CssConstants.Absolute ? b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight : 0;

                b.RectanglesReset();
                b.MeasureWordsSize(g);

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    // fix word space for first word in inline tag
                    if (!b.Words[0].IsImage && b.Words[0].HasSpaceBefore && b.IsInline)
                    {
                        var sib = DomUtils.GetPreviousContainingBlockSibling(b);
                        if (sib != null && sib.IsInline)
                        {
                            curx += b.ActualWordSpacing;
                        }
                    }

                    foreach (var word in b.Words)
                    {
                        if (maxbottom - cury < box.ActualLineHeight)
                        {
                            maxbottom += box.ActualLineHeight - (maxbottom - cury);
                        }

                        if ((b.WhiteSpace != CssConstants.Nowrap && b.WhiteSpace != CssConstants.Pre && curx + word.Width + rightspacing > limitRight) || word.IsLineBreak)
                        {
                            curx = startx;

                            // handle if line is wrapped for the first text element where parent has left margin\padding
                            if (b == box.Boxes[0] && word == b.Words[0] && !word.IsLineBreak)
                            {
                                curx += box.ActualMarginLeft + box.ActualBorderLeftWidth + box.ActualPaddingLeft;
                            }

                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

                            if (word.IsImage || word.Equals(b.FirstWord))
                            {
                                curx += leftspacing;
                            }
                        }

                        line.ReportExistanceOf(word);

                        word.Left = curx;
                        word.Top  = cury;

                        curx = word.Left + word.FullWidth - word.LastMeasureOffset.X / 2;

                        maxRight  = Math.Max(maxRight, word.Right);
                        maxbottom = Math.Max(maxbottom, word.Bottom);

                        if (b.Position != CssConstants.Absolute)
                        {
                        }
                        else
                        {
                            word.Left += box.ActualMarginLeft;
                            word.Top  += box.ActualMarginTop;
                        }
                    }
                }
                else
                {
                    FlowBox(g, blockbox, b, limitRight, linespacing, startx, ref line, ref curx, ref cury, ref maxRight, ref maxbottom);
                }

                curx += rightspacing;
            }

            // handle height setting
            if (maxbottom - startY < box.ActualHeight)
            {
                maxbottom += box.ActualHeight - (maxbottom - startY);
            }

            // handle box that is only a whitespace
            if (box.Text != null && box.Text.IsWhitespace() && !box.IsImage && box.IsInline && box.Boxes.Count == 0 && box.Words.Count == 0)
            {
                curx += box.ActualWordSpacing;
            }

            // hack to support specific absolute possition elements
            if (box.Position == CssConstants.Absolute)
            {
                curx      = localCurx;
                maxRight  = localMaxRight;
                maxbottom = localmaxbottom;
                AdjustAbsolutePosition(box, 0, 0);
            }

            box.LastHostingLineBox = line;
        }
Пример #30
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="g">Device Info</param>
        /// <param name="blockbox">Blockbox that contains the text flow</param>
        /// <param name="box">Current box to flow its content</param>
        /// <param name="limitRight">Maximum reached right</param>
        /// <param name="linespacing">Space to use between rows of text</param>
        /// <param name="startx">x starting coordinate for when breaking lines of text</param>
        /// <param name="line">Current linebox being used</param>
        /// <param name="curx">Current x coordinate that will be the left of the next word</param>
        /// <param name="cury">Current y coordinate that will be the top of the next word</param>
        /// <param name="maxRight">Maximum right reached so far</param>
        /// <param name="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(IGraphics g, CssBox blockbox, CssBox box, float limitRight, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxRight, ref float maxbottom)
        {
            var startX = curx;
            var startY = cury;

            box.FirstHostingLineBox = line;
            var localCurx      = curx;
            var localMaxRight  = maxRight;
            var localmaxbottom = maxbottom;

            foreach (CssBox b in box.Boxes)
            {
                float leftspacing  = b.Position != CssConstants.Absolute ? b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft : 0;
                float rightspacing = b.Position != CssConstants.Absolute ? b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight : 0;

                b.RectanglesReset();
                b.MeasureWordsSize(g);

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    bool wrapNoWrapBox = false;
                    if (b.WhiteSpace == CssConstants.NoWrap && curx > startx)
                    {
                        var boxRight = curx;
                        foreach (var word in b.Words)
                        {
                            boxRight += word.FullWidth;
                        }
                        if (boxRight > limitRight)
                        {
                            wrapNoWrapBox = true;
                        }
                    }

                    if (DomUtils.IsBoxHasWhitespace(b))
                    {
                        curx += box.ActualWordSpacing;
                    }

                    foreach (var word in b.Words)
                    {
                        if (maxbottom - cury < box.ActualLineHeight)
                        {
                            maxbottom += box.ActualLineHeight - (maxbottom - cury);
                        }

                        if ((b.WhiteSpace != CssConstants.NoWrap && b.WhiteSpace != CssConstants.Pre && curx + word.Width + rightspacing > limitRight) || word.IsLineBreak || wrapNoWrapBox)
                        {
                            wrapNoWrapBox = false;
                            curx          = startx;

                            // handle if line is wrapped for the first text element where parent has left margin\padding
                            if (b == box.Boxes[0] && !word.IsLineBreak && (word == b.Words[0] || (box.ParentBox != null && box.ParentBox.IsBlock)))
                            {
                                curx += box.ActualMarginLeft + box.ActualBorderLeftWidth + box.ActualPaddingLeft;
                            }

                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

                            if (word.IsImage || word.Equals(b.FirstWord))
                            {
                                curx += leftspacing;
                            }
                        }

                        line.ReportExistanceOf(word);

                        word.Left = curx;
                        word.Top  = cury;

                        curx = word.Left + word.FullWidth;

                        maxRight  = Math.Max(maxRight, word.Right);
                        maxbottom = Math.Max(maxbottom, word.Bottom);

                        if (b.Position == CssConstants.Absolute)
                        {
                            word.Left += box.ActualMarginLeft;
                            word.Top  += box.ActualMarginTop;
                        }
                    }
                }
                else
                {
                    FlowBox(g, blockbox, b, limitRight, linespacing, startx, ref line, ref curx, ref cury, ref maxRight, ref maxbottom);
                }

                curx += rightspacing;
            }

            // handle height setting
            if (maxbottom - startY < box.ActualHeight)
            {
                maxbottom += box.ActualHeight - (maxbottom - startY);
            }

            // handle width setting
            if (box.IsInline && 0 <= curx - startX && curx - startX < box.ActualWidth)
            {
                // hack for actual width handling
                curx += box.ActualWidth - (curx - startX);
                line.Rectangles.Add(box, new RectangleF(startX, startY, box.ActualWidth, box.ActualHeight));
            }

            // handle box that is only a whitespace
            if (box.Text != null && box.Text.IsWhitespace() && !box.IsImage && box.IsInline && box.Boxes.Count == 0 && box.Words.Count == 0)
            {
                curx += box.ActualWordSpacing;
            }

            // hack to support specific absolute position elements
            if (box.Position == CssConstants.Absolute)
            {
                curx      = localCurx;
                maxRight  = localMaxRight;
                maxbottom = localmaxbottom;
                AdjustAbsolutePosition(box, 0, 0);
            }

            box.LastHostingLineBox = line;
        }
Пример #31
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="g">Device Info</param>
        /// <param name="blockbox">Blockbox that contains the text flow</param>
        /// <param name="box">Current box to flow its content</param>
        /// <param name="maxright">Maximum reached right</param>
        /// <param name="linespacing">Space to use between rows of text</param>
        /// <param name="startx">x starting coordinate for when breaking lines of text</param>
        /// <param name="line">Current linebox being used</param>
        /// <param name="curx">Current x coordinate that will be the left of the next word</param>
        /// <param name="cury">Current y coordinate that will be the top of the next word</param>
        /// <param name="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float maxright, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxbottom)
        {
            var startY = cury;

            box.FirstHostingLineBox = line;

            foreach (CssBox b in box.Boxes)
            {
                float leftspacing  = b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft;
                float rightspacing = b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight;

                b.RectanglesReset();
                b.MeasureWordsSize(g);

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    // fix word space for first word in inline tag
                    if (!b.Words[0].IsImage && b.Words[0].HasSpaceBefore && b.Display == CssConstants.Inline)
                    {
                        var sib = DomUtils.GetPreviousContainingBlockSibling(b);
                        if (sib != null && sib.Display == CssConstants.Inline)
                        {
                            curx += b.ActualWordSpacing;
                        }
                    }

                    foreach (var word in b.Words)
                    {
                        if (maxbottom - cury < box.ActualLineHeight)
                        {
                            maxbottom += box.ActualLineHeight - (maxbottom - cury);
                        }

                        if ((b.WhiteSpace != CssConstants.Nowrap && curx + word.Width + rightspacing > maxright) || word.IsLineBreak)
                        {
                            curx = startx;
                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

                            if (word.IsImage || word.Equals(b.FirstWord))
                            {
                                curx += leftspacing;
                            }
                        }

                        // atodo: why?
                        line.ReportExistanceOf(word);

                        word.Left = curx;                                             // -word.LastMeasureOffset.X + 1;
                        word.Top  = cury;                                             // - word.LastMeasureOffset.Y;

                        curx = word.Right + (word.IsImage ? b.ActualWordSpacing : 0); // +word.SpacesAfterWidth;

                        maxbottom = Math.Max(maxbottom, word.Bottom);                 //+ (word.IsImage ? topspacing + bottomspacing : 0));
                    }

                    // fix word space for last word that is right before inline tag
                    var lastWord = b.Words[b.Words.Count - 1];
                    if (!lastWord.IsImage && !lastWord.HasSpaceAfter)
                    {
                        var next = DomUtils.GetNextSibling(b);
                        if (next == null || next.Display == CssConstants.Inline)
                        {
                            curx -= b.ActualWordSpacing + CssUtils.GetWordEndWhitespace(b.ActualFont);
                        }
                    }
                }
                else
                {
                    FlowBox(g, blockbox, b, maxright, linespacing, startx, ref line, ref curx, ref cury, ref maxbottom);
                }

                curx += rightspacing;
            }

            // handle height setting
            if (maxbottom - startY < box.ActualHeight)
            {
                maxbottom += box.ActualHeight - (maxbottom - startY);
            }

            // handle box that is only a whitespace
            if (box.Text == " " && !box.IsImage && box.IsInline && box.Boxes.Count == 0 && box.Words.Count == 0)
            {
                curx += box.ActualWordSpacing;
            }

            box.LastHostingLineBox = line;
        }
Пример #32
0
        /// <summary>
        /// Gets the span attribute of the tag of the specified box
        /// </summary>
        /// <param name="b"></param>
        private static int GetSpan(CssBox b)
        {
            float f = CssValueParser.ParseNumber(b.GetAttribute("span"), 1);

            return(Math.Max(1, Convert.ToInt32(f)));
        }
Пример #33
0
        /// <summary>
        /// Check if the given box contains inline and block child boxes.
        /// </summary>
        /// <param name="box">the box to check</param>
        /// <returns>true - has variant child boxes, false - otherwise</returns>
        private static bool ContainsVariantBoxes(CssBox box)
        {
            bool hasBlock = false;
            bool hasInline = false;
            for (int i = 0; i < box.Boxes.Count && (!hasBlock || !hasInline); i++)
            {
                var isBlock = box.Boxes[i].Display != CssConstants.Inline;
                hasBlock = hasBlock || isBlock;
                hasInline = hasInline || !isBlock;
            }

            return hasBlock && hasInline;
        }
Пример #34
0
        /// <summary>
        /// Gets the rectangles where inline box will be drawn. See Remarks for more info.
        /// </summary>
        /// <returns>Rectangles where content should be placed</returns>
        /// <remarks>
        /// Inline boxes can be splitted across different LineBoxes, that's why this method
        /// Delivers a rectangle for each LineBox related to this box, if inline.
        /// </remarks>

        /// <summary>
        /// Inherits inheritable values from parent.
        /// </summary>
        internal new void InheritStyle(CssBox box = null, bool everything = false)
        {
            base.InheritStyle(box ?? ParentBox, everything);
        }
Пример #35
0
        /// <summary>
        /// Correct DOM tree if there is block boxes that are inside inline blocks.<br/>
        /// Need to rearange the tree so block box will be only the child of other block box.
        /// </summary>
        /// <param name="box">the current box to correct its sub-tree</param>
        private static void CorrectBlockInsideInline(CssBox box)
        {
            if (DomUtils.ContainsInlinesOnly(box) && !ContainsInlinesOnlyDeep(box))
            {
                CorrectBlockInsideInlineImp(box);
            }

            if (!DomUtils.ContainsInlinesOnly(box))
            {
                foreach (var childBox in box.Boxes)
                {
                    CorrectBlockInsideInline(childBox);
                }
            }
        }
Пример #36
0
 /// <summary>
 /// Select all the words that are between <paramref name="selectionStart"/> word and <paramref name="selectionEnd"/> word in the DOM hierarchy.<br/>
 /// </summary>
 /// <param name="root">the root of the DOM sub-tree the selection is in</param>
 /// <param name="selectionStart">selection start word limit</param>
 /// <param name="selectionEnd">selection end word limit</param>
 private void SelectWordsInRange(CssBox root, CssRect selectionStart, CssRect selectionEnd)
 {
     bool inSelection = false;
     SelectWordsInRange(root, selectionStart, selectionEnd, ref inSelection);
 }
Пример #37
0
        /// <summary>
        /// Split bad box that has inline and block boxes into two parts, the left - before the block box
        /// and right - after the block box.
        /// </summary>
        /// <param name="parentBox">the parent box that has the problem</param>
        /// <param name="badBox">the box to split into different boxes</param>
        /// <param name="leftBlock">the left block box that is created for the split</param>
        private static void CorrectBlockSplitBadBox(CssBox parentBox, CssBox badBox, CssBox leftBlock)
        {
            var leftbox = CssBox.CreateBox(leftBlock, badBox.HtmlTag);
            leftbox.InheritStyle(badBox, true);

            while (badBox.Boxes[0].IsInline && ContainsInlinesOnlyDeep(badBox.Boxes[0]))
                badBox.Boxes[0].ParentBox = leftbox;

            var splitBox = badBox.Boxes[0];
            if (!ContainsInlinesOnlyDeep(splitBox))
            {
                CorrectBlockSplitBadBox(parentBox, splitBox, leftBlock);
                splitBox.ParentBox = null;
            }
            else
            {
                splitBox.ParentBox = parentBox;
            }

            if (badBox.Boxes.Count > 0)
            {
                CssBox rightBox = null;
                if (splitBox.ParentBox != null || parentBox.Boxes.Count < 2)
                {
                    rightBox = CssBox.CreateBox(parentBox, badBox.HtmlTag);
                    rightBox.InheritStyle(badBox, true);

                    if (parentBox.Boxes.Count > 2)
                        rightBox.SetBeforeBox(parentBox.Boxes[1]);

                    splitBox.SetBeforeBox(rightBox);
                }
                else if (parentBox.Boxes.Count > 2)
                {
                    rightBox = parentBox.Boxes[2];
                }

                while (badBox.Boxes.Count > 0)
                    badBox.Boxes[0].ParentBox = rightBox;
            }
            else if(splitBox.ParentBox != null && parentBox.Boxes.Count > 1)
            {
                splitBox.SetBeforeBox(parentBox.Boxes[1]);
            }
        }
Пример #38
0
        /// <summary>
        /// Select all the words that are between <paramref name="selectionStart"/> word and <paramref name="selectionEnd"/> word in the DOM hierarchy.
        /// </summary>
        /// <param name="box">the current traversal node</param>
        /// <param name="selectionStart">selection start word limit</param>
        /// <param name="selectionEnd">selection end word limit</param>
        /// <param name="inSelection">used to know the traversal is currently in selected range</param>
        /// <returns></returns>
        private bool SelectWordsInRange(CssBox box, CssRect selectionStart, CssRect selectionEnd, ref bool inSelection)
        {
            foreach (var boxWord in box.Words)
            {
                if (!inSelection && boxWord == selectionStart)
                {
                    inSelection = true;
                }
                if (inSelection)
                {
                    boxWord.Selection = this;

                    if (selectionStart == selectionEnd || boxWord == selectionEnd)
                    {
                        return true;
                    }
                }
            }

            foreach (var childBox in box.Boxes)
            {
                if (SelectWordsInRange(childBox, selectionStart, selectionEnd, ref inSelection))
                {
                    return true;
                }
            }

            return false;
        }
Пример #39
0
        /// <summary>
        /// Correct the DOM tree recursively by replacing  "br" html boxes with anonymous blocks that respect br spec.<br/>
        /// If the "br" tag is after inline box then the anon block will have zero height only acting as newline,
        /// but if it is after block box then it will have min-height of the font size so it will create empty line.
        /// </summary>
        /// <param name="box">the current box to correct its sub-tree</param>
        private static void CorrectLineBreaksBlocks(CssBox box)
        {
            int lastBr = -1;
            CssBox brBox;
            do
            {
                brBox = null;
                CssBox prevBox = null;
                for (int i = 0; i < box.Boxes.Count && brBox == null; i++)
                {
                    if (i > lastBr && box.Boxes[i].HtmlTag != null && box.Boxes[i].HtmlTag.Name == "br")
                    {
                        brBox = box.Boxes[i];
                        lastBr = i;
                    }
                    else
                    {
                        prevBox = box.Boxes[i];
                    }
                }

                if (brBox != null)
                {
                    var anonBlock = CssBox.CreateBlock(box, new HtmlTag("br"), brBox);
                    if (prevBox == null || prevBox.Display != CssConstants.Inline)
                        anonBlock.Height = ".9em"; // atodo: check the height to min-height when it is supported
                    brBox.ParentBox = null;
                }

            } while (brBox != null);

            foreach (var childBox in box.Boxes)
            {
                CorrectLineBreaksBlocks(childBox);
            }
        }
Пример #40
0
 /// <summary>
 /// Gets the actual horizontal spacing of the table
 /// </summary>
 private static float GetHorizontalSpacing(CssBox box)
 {
     return(box.BorderCollapse == CssConstants.Collapse ? -1f : box.ActualBorderSpacingHorizontal);
 }
Пример #41
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="owner">the CSS box owner of the word</param>
 protected CssRect(CssBox owner)
 {
     _ownerBox = owner;
 }
Пример #42
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="owner">the CSS box owner of the word</param>
 protected CssRect(CssBox owner)
 {
     _ownerBox = owner;
 }
Пример #43
0
 /// <summary>
 /// Init.
 /// </summary>
 /// <param name="parent">the parent box of this box</param>
 /// <param name="tag">the html tag data of this box</param>
 public CssBoxHr(CssBox parent, HtmlTag tag)
     : base(parent, tag)
 {
     Display = CssConstants.Block;
 }
Пример #44
0
        /// <summary>
        /// Layout the cells by the calculated table layout
        /// </summary>
        /// <param name="g"></param>
        private void LayoutCells(Graphics g)
        {
            float startx     = Math.Max(_tableBox.ClientLeft + GetHorizontalSpacing(), 0);
            float starty     = Math.Max(_tableBox.ClientTop + GetVerticalSpacing(), 0);
            float cury       = starty;
            float maxRight   = startx;
            float maxBottom  = 0f;
            int   currentrow = 0;

            for (int i = 0; i < _allRows.Count; i++)
            {
                var   row    = _allRows[i];
                float curx   = startx;
                int   curCol = 0;

                for (int j = 0; j < row.Boxes.Count; j++)
                {
                    CssBox cell = row.Boxes[j];
                    if (curCol >= _columnWidths.Length)
                    {
                        break;
                    }

                    int   rowspan     = GetRowSpan(cell);
                    var   columnIndex = GetCellRealColumnIndex(row, cell);
                    float width       = GetCellWidth(columnIndex, cell);
                    cell.Location = new PointF(curx, cury);
                    cell.Size     = new SizeF(width, 0f);
                    cell.PerformLayout(g); //That will automatically set the bottom of the cell

                    //Alter max bottom only if row is cell's row + cell's rowspan - 1
                    CssSpacingBox sb = cell as CssSpacingBox;
                    if (sb != null)
                    {
                        if (sb.EndRow == currentrow)
                        {
                            maxBottom = Math.Max(maxBottom, sb.ExtendedBox.ActualBottom);
                        }
                    }
                    else if (rowspan == 1)
                    {
                        maxBottom = Math.Max(maxBottom, cell.ActualBottom);
                    }
                    maxRight = Math.Max(maxRight, cell.ActualRight);
                    curCol++;
                    curx = cell.ActualRight + GetHorizontalSpacing();
                }

                foreach (CssBox cell in row.Boxes)
                {
                    CssSpacingBox spacer = cell as CssSpacingBox;

                    if (spacer == null && GetRowSpan(cell) == 1)
                    {
                        cell.ActualBottom = maxBottom;
                        CssLayoutEngine.ApplyCellVerticalAlignment(g, cell);
                    }
                    else if (spacer != null && spacer.EndRow == currentrow)
                    {
                        spacer.ExtendedBox.ActualBottom = maxBottom;
                        CssLayoutEngine.ApplyCellVerticalAlignment(g, spacer.ExtendedBox);
                    }
                }

                cury = maxBottom + GetVerticalSpacing();
                currentrow++;
            }

            _tableBox.ActualRight  = maxRight + GetHorizontalSpacing() + _tableBox.ActualBorderRightWidth;
            _tableBox.ActualBottom = Math.Max(maxBottom, starty) + GetVerticalSpacing() + _tableBox.ActualBorderBottomWidth;
        }