public static void PerformContentLayout(CssBox box, LayoutVisitor lay) { //recursive //this box has its own container property //this box may use... // 1) line formatting context , or // 2) block formatting context CssBox myContainingBlock = lay.LatestContainingBlock; CssBox prevSibling = lay.LatestSiblingBox; if (box.CssDisplay != Css.CssDisplay.TableCell) { //------------------------------------------- if (box.CssDisplay != Css.CssDisplay.Table) { float availableWidth = myContainingBlock.GetClientWidth(); // Console.WriteLine(availableWidth.ToString()); if (!box.Width.IsEmptyOrAuto) { float w = CssValueParser.ConvertToPx(box.Width, availableWidth, box); //specific width box.SetCssBoxWidth(w); } else { box.SetCssBoxFromContainerAvailableWidth(availableWidth); } } //------------------------------------------- float localLeft = myContainingBlock.GetClientLeft() + box.ActualMarginLeft; float localTop = 0; if (prevSibling == null) { //this is first child of parent if (box.ParentBox != null) { localTop = myContainingBlock.GetClientTop(); } } else { localTop = prevSibling.LocalVisualBottom; } //if (box.Float != CssFloat.None) //{ // //float box // //find context floating c // if (lay.HasFloatBoxInContext) // { // } //} localTop += box.UpdateMarginTopCollapse(prevSibling); box.SetLocation(localLeft, localTop); box.SetHeightToZero(); } //-------------------------------------------------------------------------- switch (box.CssDisplay) { case Css.CssDisplay.Table: case Css.CssDisplay.InlineTable: { //If we're talking about a table here.. lay.PushContaingBlock(box); var currentLevelLatestSibling = lay.LatestSiblingBox; lay.LatestSiblingBox = null;//reset CssTableLayoutEngine.PerformLayout(box, myContainingBlock.GetClientWidth(), lay); lay.LatestSiblingBox = currentLevelLatestSibling; lay.PopContainingBlock(); //TODO: check if this can have absolute layer? } break; default: { //formatting context for... //1. line formatting context //2. block formatting context if (box.IsCustomCssBox) { //has custom layout method box.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock); box.CustomRecomputedValue(lay.LatestContainingBlock); } else { if (ContainsInlinesOnly(box)) { //This will automatically set the bottom of this block LinesFormattingEngine.DoLayoutLinesContext(box, lay); } else if (box.ChildCount > 0) { DoLayoutBlocksContext(box, lay); } if (box.HasAbsoluteLayer) { LayoutContentInAbsoluteLayer(lay, box); } } //--------------------- //again! switch (box.CssDisplay) { case CssDisplay.Flex: case CssDisplay.InlineFlex: { //------------------------------------------------ RearrangeWithFlexContext(box, lay); //------------------------------------------------ } break; default: { //TODO: review here again //if (box.Float != CssFloat.None) //{ // var iw = box.InnerContentWidth; // var ew = box.VisualWidth; // box.SetVisualSize(box.InnerContentWidth, box.InnerContentHeight); // //float to specific position // //box.SetVisualSize(iw, box.VisualHeight); //} } break; } //--------------------- } break; } switch (box.Float) { case CssFloat.Left: { #if DEBUG CssBox a = box; #endif //place it to floating context CssBox currentFloatOwner = lay.GetFloatingContextStack().CurrentTopOwner; CssBox recentLeftFloatBox = lay.LatestLeftFloatBox; CssBox recentRightFloatBox = lay.LatestRightFloatBox; float availableWidth2 = myContainingBlock.GetClientWidth(); if (recentRightFloatBox != null) { availableWidth2 -= recentRightFloatBox.LocalX; } float sx = myContainingBlock.GetClientLeft(); //-------------------------------------------------------------------- float sy = 0; if (myContainingBlock.LineBoxCount > 0) { //line context sy = myContainingBlock.GetClientTop(); } else { var prevNode = box.GetPrevNode(); if (prevNode != null) { if (prevNode.Float != CssFloat.None) { //float left/right //TODO: review inherit here if (box.VisualWidth < availableWidth2) { sy = prevNode.LocalY; } else { sy = prevNode.LocalVisualBottom; } } else { sy = prevNode.LocalVisualBottom; } } else { sy = myContainingBlock.GetClientTop(); } } if (recentLeftFloatBox != null) { availableWidth2 -= recentLeftFloatBox.LocalVisualRight; //TODO: review here again sx = recentLeftFloatBox.LocalVisualRight + recentLeftFloatBox.ActualMarginRight; sy = recentLeftFloatBox.LocalY; } if (box.VisualWidth > availableWidth2) { //start newline sx = myContainingBlock.GetClientLeft(); float sy1 = 0; float sy2 = 0; sy1 = sy2 = myContainingBlock.GetClientTop(); if (recentLeftFloatBox != null) { sy1 = recentLeftFloatBox.LocalVisualBottom + recentLeftFloatBox.ActualMarginBottom; } if (recentRightFloatBox != null) { sy2 = recentRightFloatBox.LocalVisualBottom + recentRightFloatBox.ActualMarginBottom; } sy = (sy1 > sy2) ? sy1 : sy2; } sx += box.ActualMarginLeft; sy += box.ActualMarginTop; box.SetLocation(sx, sy); lay.AddFloatBox(box); } break; case CssFloat.Right: { CssBox recentLeftFloatBox = lay.LatestLeftFloatBox; CssBox recentRightFloatBox = lay.LatestRightFloatBox; float availableWidth2 = myContainingBlock.GetClientWidth(); if (recentLeftFloatBox != null) { availableWidth2 -= recentLeftFloatBox.LocalVisualRight; } float sx = myContainingBlock.GetClientRight() - (box.VisualWidth + box.ActualMarginLeft + box.ActualMarginRight); //-------------------------------------------------------------------- float sy = 0; if (myContainingBlock.LineBoxCount > 0) { //line context sy = myContainingBlock.GetClientTop(); } else { var prevNode = box.GetPrevNode(); if (prevNode != null) { if (prevNode.Float != CssFloat.None) { //float left/right //TODO: review inherit here if (box.VisualWidth < availableWidth2) { sy = prevNode.LocalY; } else { sy = prevNode.LocalVisualBottom; } } else { sy = prevNode.LocalVisualBottom; } } else { sy = myContainingBlock.GetClientTop(); } } //-------------------------------------------------------------------- if (recentRightFloatBox != null) { availableWidth2 -= recentRightFloatBox.LocalX; sx = recentRightFloatBox.LocalX - box.VisualWidth; sy = recentRightFloatBox.LocalY; } if (box.VisualWidth > availableWidth2) { //start newline sx = myContainingBlock.GetClientRight() - (box.VisualWidth + box.ActualMarginLeft + box.ActualMarginRight); float sy1 = 0; float sy2 = 0; sy1 = sy2 = myContainingBlock.GetClientTop(); //if (recentLeftFloatBox != null) //{ // sy1 = recentLeftFloatBox.LocalY + recentLeftFloatBox.InnerContentHeight + // recentLeftFloatBox.ActualPaddingBottom + // recentLeftFloatBox.ActualMarginBottom; //} //if (recentRightFloatBox != null) //{ // sy2 = recentRightFloatBox.LocalY + recentRightFloatBox.InnerContentHeight + // recentRightFloatBox.ActualPaddingBottom + // recentRightFloatBox.ActualMarginBottom; //} if (recentLeftFloatBox != null) { sy1 = recentLeftFloatBox.LocalVisualBottom + recentLeftFloatBox.ActualMarginBottom; } if (recentRightFloatBox != null) { sy2 = recentRightFloatBox.LocalVisualBottom + recentRightFloatBox.ActualMarginBottom; } sy = (sy1 > sy2) ? sy1 : sy2; } sx += box.ActualMarginLeft; sy += box.ActualMarginTop; box.SetLocation(sx, sy); lay.AddFloatBox(box); } break; case CssFloat.None: default: { //review here for inherit property } break; } }