/// <summary> /// Correct DOM tree if there is block boxes that are inside inline blocks.<br/> /// Need to rearrange 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) { try { if (DomUtils.ContainsInlinesOnly(box) && !ContainsInlinesOnlyDeep(box)) { var tempRightBox = CorrectBlockInsideInlineImp(box); while (tempRightBox != null) { // loop on the created temp right box for the fixed box until no more need (optimization remove recursion) CssBox newTempRightBox = null; if (DomUtils.ContainsInlinesOnly(tempRightBox) && !ContainsInlinesOnlyDeep(tempRightBox)) { newTempRightBox = CorrectBlockInsideInlineImp(tempRightBox); } tempRightBox.ParentBox.SetAllBoxes(tempRightBox); tempRightBox.ParentBox = null; tempRightBox = newTempRightBox; } } if (!DomUtils.ContainsInlinesOnly(box)) { foreach (var childBox in box.Boxes) { CorrectBlockInsideInline(childBox); } } } catch (Exception ex) { box.HtmlContainer.ReportError(HtmlRenderErrorType.HtmlParsing, "Failed in block inside inline box correction", ex); } }
/// <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); } } }
/// <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)) //if this box contains inline and block elements { for (int i = 0; i < box.Boxes.Count; i++) { //if the child isInline box take the child and add it to newbox // then set newbox as the parentbox if (box.Boxes[i].IsInline) { //creates new box in parent(box) at position it was in currently in 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); } } }
/// <summary> /// Gets if this box has only inline siblings (including itself) /// </summary> /// <returns></returns> internal bool HasJustInlineSiblings() { if (ParentBox == null) { return(false); } return(DomUtils.ContainsInlinesOnly(ParentBox)); }
/// <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); } } }
/// <summary> /// Correct DOM tree if there is block boxes that are inside inline blocks.<br/> /// Need to rearrange 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) { try { if (DomUtils.ContainsInlinesOnly(box) && !ContainsInlinesOnlyDeep(box)) { CorrectBlockInsideInlineImp(box); } if (!DomUtils.ContainsInlinesOnly(box)) { foreach (var childBox in box.Boxes) { CorrectBlockInsideInline(childBox); } } } catch (Exception ex) { box.HtmlContainer.ReportError(HtmlRenderErrorType.HtmlParsing, "Failed in block inside inline box correction", ex); } }
/// <summary> /// Measures the bounds of box and children, recursively.<br/> /// Performs layout of the DOM structure creating lines by set bounds restrictions. /// </summary> /// <param name="g">Device context to use</param> private void MeasureBoundsImp(Graphics g) { if (Display == CssConstants.None) { return; } RectanglesReset(); MeasureWordsSize(g); if (Display == CssConstants.Block || Display == CssConstants.ListItem || Display == CssConstants.Table || Display == CssConstants.InlineTable || Display == CssConstants.TableCell || Display == CssConstants.None) { if (Display != CssConstants.TableCell) { var prevSibling = DomUtils.GetPreviousSibling(this); float left = ContainingBlock.Location.X + ContainingBlock.ActualPaddingLeft + ActualMarginLeft + ContainingBlock.ActualBorderLeftWidth; float top = (prevSibling == null && ParentBox != null ? ParentBox.ClientTop : ParentBox == null ? Location.Y : 0) + MarginTopCollapse(prevSibling) + (prevSibling != null ? prevSibling.ActualBottom + prevSibling.ActualBorderBottomWidth : 0); Location = new PointF(left, top); ActualBottom = top; } // Because their width and height are set by CssTable if (Display != CssConstants.TableCell && Display != CssConstants.Table) { //width at 100% (or auto) float minwidth = GetMinimumWidth(); float width = ContainingBlock.Size.Width - ContainingBlock.ActualPaddingLeft - ContainingBlock.ActualPaddingRight - ContainingBlock.ActualBorderLeftWidth - ContainingBlock.ActualBorderRightWidth - ActualMarginLeft - ActualMarginRight - ActualBorderLeftWidth - ActualBorderRightWidth; //Check width if not auto if (Width != CssConstants.Auto && !string.IsNullOrEmpty(Width)) { width = CssValueParser.ParseLength(Width, width, this); } if (width < minwidth || width >= 9999) { width = minwidth; } Size = new SizeF(width, Size.Height); } //If we're talking about a table here.. if (Display == CssConstants.Table || Display == CssConstants.InlineTable) { new CssTable(this, g); } else { //If there's just inlines, create LineBoxes if (DomUtils.ContainsInlinesOnly(this)) { ActualBottom = Location.Y; CssLayoutEngine.CreateLineBoxes(g, this); //This will automatically set the bottom of this block } else if (_boxes.Count > 0) { foreach (var childBox in Boxes) { childBox.MeasureBoundsImp(g); } ActualBottom = MarginBottomCollapse(); } } } if (HtmlContainer != null) { HtmlContainer.ActualSize = new SizeF(Math.Max(HtmlContainer.ActualSize.Width, Size.Width < 9999 ? Size.Width : 0), Math.Max(HtmlContainer.ActualSize.Height, Size.Height)); } }