static void SetFinalInnerContentSize(CssBox box, float innerContentW, float innerContentH, LayoutVisitor lay) { box.InnerContentWidth = innerContentW; box.InnerContentHeight = innerContentH; if (!box.Height.IsEmptyOrAuto) { var h = CssValueParser.ConvertToPx(box.Height, lay.LatestContainingBlock.VisualWidth, lay.LatestContainingBlock); box.SetExpectedSize(box.ExpectedWidth, h); box.SetVisualHeight(h); box.SetCssBoxHeight(h); } else { switch (box.Position) { case CssPosition.Fixed: case CssPosition.Absolute: box.SetVisualHeight(box.InnerContentHeight); break; } } if (!box.Width.IsEmptyOrAuto) { //find max line width var w = CssValueParser.ConvertToPx(box.Width, lay.LatestContainingBlock.VisualWidth, lay.LatestContainingBlock); box.SetExpectedSize(w, box.ExpectedHeight); box.SetVisualWidth(w); box.SetCssBoxWidth(w); } else { switch (box.Position) { case CssPosition.Fixed: case CssPosition.Absolute: box.SetVisualWidth(box.InnerContentWidth); break; } } switch (box.Overflow) { case CssOverflow.Scroll: case CssOverflow.Auto: { if ((box.InnerContentHeight > box.VisualHeight) || (box.InnerContentWidth > box.VisualWidth)) { lay.RequestScrollView(box); } } break; } }
/// <summary> /// do layout line formatting context /// </summary> /// <param name="hostBlock"></param> /// <param name="lay"></param> public static void DoLayoutLinesContext(CssBox hostBlock, LayoutVisitor lay) { //this in line formatting context //*** hostBlock must confirm that it has all inline children hostBlock.SetHeightToZero(); hostBlock.ResetLineBoxes(); //---------------------------------------------------------------------------------------- float limitLocalRight = hostBlock.VisualWidth - (hostBlock.ActualPaddingRight + hostBlock.ActualBorderRightWidth); float localX = hostBlock.ActualTextIndent + hostBlock.ActualPaddingLeft + hostBlock.ActualBorderLeftWidth; float localY = hostBlock.ActualPaddingTop + hostBlock.ActualBorderTopWidth; //---------------------------------------------------------------------------------------- if (lay.HasFloatBoxInContext) { var recentLeftFloatBox = lay.LatestLeftFloatBox; var recentRightFloatBox = lay.LatestRightFloatBox; var latestSibling = lay.LatestSiblingBox; if (latestSibling != null) { //check latest sibling first if (hostBlock.Float == CssFloat.None) { if (recentLeftFloatBox != null) { if (hostBlock.LocalY < recentLeftFloatBox.LocalVisualBottom) { localX = recentLeftFloatBox.LocalVisualRight; } } else { } } } else { if (hostBlock.Float == CssFloat.None) { if (recentLeftFloatBox != null) { localX = recentLeftFloatBox.LocalVisualRight; } if (recentRightFloatBox != null) { limitLocalRight = recentRightFloatBox.LocalX; } } //check if need newline or not } } int interlineSpace = 0; //First line box var line = new CssLineBox(hostBlock); hostBlock.AddLineBox(line); //**** var floatCtx = new FloatFormattingContext(); FlowBoxContentIntoHostLineFmtContext(lay, hostBlock, hostBlock, limitLocalRight, localX, ref line, ref localX, ref floatCtx); //**** // if width is not restricted we need to lower it to the actual width if (hostBlock.VisualWidth + lay.ContainerBlockGlobalX >= CssBoxConstConfig.BOX_MAX_RIGHT) { float newWidth = localX + hostBlock.ActualPaddingRight + hostBlock.ActualBorderRightWidth;// CssBox.MAX_RIGHT - (args.ContainerBlockGlobalX + blockBox.LocalX); if (newWidth <= CSS_OFFSET_THRESHOLD) { newWidth = CSS_OFFSET_THRESHOLD; } hostBlock.SetVisualWidth(newWidth); } //--------------------- float maxLineWidth = 0; if (hostBlock.CssDirection == CssDirection.Rtl) { CssTextAlign textAlign = hostBlock.CssTextAlign; foreach (CssLineBox linebox in hostBlock.GetLineBoxIter()) { ApplyAlignment(linebox, textAlign, lay); ApplyRightToLeft(linebox); //*** linebox.CloseLine(lay); //*** linebox.CachedLineTop = localY; localY += linebox.CacheLineHeight + interlineSpace; // + interline space? if (maxLineWidth < linebox.CachedExactContentWidth) { maxLineWidth = linebox.CachedExactContentWidth; } } } else { CssTextAlign textAlign = hostBlock.CssTextAlign; foreach (CssLineBox linebox in hostBlock.GetLineBoxIter()) { ApplyAlignment(linebox, textAlign, lay); linebox.CloseLine(lay); //*** linebox.CachedLineTop = localY; localY += linebox.CacheLineHeight + interlineSpace; if (maxLineWidth < linebox.CachedExactContentWidth) { maxLineWidth = linebox.CachedExactContentWidth; } } } hostBlock.SetVisualHeight(localY + hostBlock.ActualPaddingBottom + hostBlock.ActualBorderBottomWidth); //final SetFinalInnerContentSize(hostBlock, maxLineWidth, hostBlock.VisualHeight, lay); }
static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay) { //block formatting context.... lay.PushContaingBlock(box); var currentLevelLatestSibling = lay.LatestSiblingBox; lay.LatestSiblingBox = null;//reset //------------------------------------------ var children = CssBox.UnsafeGetChildren(box); var cnode = children.GetFirstLinkedNode(); while (cnode != null) { var childBox = cnode.Value; //---------------------------- if (childBox.IsBrElement) { //br always block CssBox.ChangeDisplayType(childBox, Css.CssDisplay.Block); childBox.SetVisualHeight(FontDefaultConfig.DEFAULT_FONT_SIZE * 0.95f); } //----------------------------- if (childBox.OutsideDisplayIsInline) { //inline correction on-the-fly ! //1. collect consecutive inlinebox // and move to new anon block box CssBox anoForInline = CreateAnonBlock(box, childBox); anoForInline.ReEvaluateComputedValues(lay.SampleIFonts, box); var tmp = cnode.Next; do { children.Remove(childBox); anoForInline.AppendChild(childBox); if (tmp != null) { childBox = tmp.Value; if (childBox.OutsideDisplayIsInline) { tmp = tmp.Next; if (tmp == null) { children.Remove(childBox); anoForInline.AppendChild(childBox); break;//break from do while } } else { break;//break from do while } } else { break;//break from do while } } while (true); childBox = anoForInline; //------------------------ //2. move this inline box //to new anonbox cnode = tmp; //------------------------ childBox.PerformLayout(lay); if (childBox.CanBeReferenceSibling) { lay.LatestSiblingBox = childBox; } } else { //if(childBox.__aa_dbugId == 5) //{ //} childBox.PerformLayout(lay); switch (childBox.Float) { case CssFloat.Left: { childBox.IsOutOfFlowBox = true; // lay.LatestLeftFloatBox = childBox; } break; case CssFloat.Right: { childBox.IsOutOfFlowBox = true; //float box is out-of-flow box //so move it to abs layer //lay.LatestRightFloatBox = childBox; } break; } if (childBox.Float == CssFloat.None && childBox.CanBeReferenceSibling) { lay.LatestSiblingBox = childBox; } cnode = cnode.Next; } } //------------------------------------------ lay.LatestSiblingBox = currentLevelLatestSibling; lay.PopContainingBlock(); //------------------------------------------------ float boxWidth = CalculateActualWidth(box); if (lay.ContainerBlockGlobalX + boxWidth > CssBoxConstConfig.BOX_MAX_RIGHT) { } else { if (box.CssDisplay != Css.CssDisplay.TableCell) { if (box.Width.IsEmptyOrAuto) { box.SetVisualWidth(boxWidth); } } } float boxHeight = box.GetHeightAfterMarginBottomCollapse(lay.LatestContainingBlock); //TODO: review here again, box.SetVisualHeight(boxHeight); //-------------------------------------------------------------------------------- //final SetFinalInnerContentSize(box, boxWidth, boxHeight, lay); }
static void RearrangeWithFlexContext(CssBox box, LayoutVisitor lay) { //this is an experiment!, var children = CssBox.UnsafeGetChildren(box); var cnode = children.GetFirstLinkedNode(); List<FlexItem> simpleFlexLine = new List<FlexItem>(); FlexLine flexLine = new FlexLine(box); while (cnode != null) { flexLine.AddChild(new FlexItem(cnode.Value)); cnode = cnode.Next; } flexLine.Arrange(); if (box.Height.IsEmptyOrAuto) { //set new height box.SetVisualHeight(flexLine.LineHeightAfterArrange); //check if it need scrollbar or not } if (box.Width.IsEmptyOrAuto) { box.SetVisualWidth(flexLine.LineWidthAfterArrange); } SetFinalInnerContentSize(box, flexLine.LineWidthAfterArrange, flexLine.LineHeightAfterArrange, lay); }
public void PerformLayout(LayoutVisitor lay) { if (this._rootBox == null) { return; } //----------------------- //reset _actualWidth = _actualHeight = 0; // if width is not restricted we set it to large value to get the actual later _rootBox.SetLocation(0, 0); _rootBox.SetVisualSize(this._maxWidth > 0 ? this._maxWidth : MAX_WIDTH, 0); CssBox.ValidateComputeValues(_rootBox); //----------------------- //LayoutVisitor layoutArgs = new LayoutVisitor(this.GraphicsPlatform, this); lay.PushContaingBlock(_rootBox); //----------------------- _rootBox.PerformLayout(lay); if (this._maxWidth <= 0.1) { // in case the width is not restricted we need to double layout, first will find the width so second can layout by it (center alignment) _rootBox.SetVisualWidth((int)Math.Ceiling(this._actualWidth)); _actualWidth = _actualHeight = 0; _rootBox.PerformLayout(lay); } lay.PopContainingBlock(); //----------------------- //TODO: review here again FloatingContextStack floatStack = lay.GetFloatingContextStack(); List <FloatingContext> totalContexts = floatStack.GetTotalContexts(); int j = totalContexts.Count; for (int i = 0; i < j; ++i) { FloatingContext floatingContext = totalContexts[i]; int floatBoxCount = floatingContext.FloatBoxCount; if (floatBoxCount == 0) { continue; } CssBox floatingOwner = floatingContext.Owner; float rfx, rfy; floatingOwner.GetGlobalLocation(out rfx, out rfy); CssBox prevParent = null; //TODO: review here again float extraAdjustX = 0; //temp fixed for (int n = 0; n < floatBoxCount; ++n) { float bfx, bfy; CssBox box = floatingContext.GetBox(n); box.GetGlobalLocation(out bfx, out bfy); //diff float nx = bfx - rfx; float ny = bfy - rfy; if (prevParent != null && prevParent != box.ParentBox) { if (n > 0) { CssBox prevFloatChild = floatingContext.GetBox(n - 1); //TODO: review here again //temp fix extraAdjustX = prevFloatChild.ActualMarginRight + box.ActualMarginLeft; ny += box.ActualMarginTop; } } box.SetLocation(nx + extraAdjustX, ny); prevParent = box.ParentBox; floatingOwner.AppendToAbsoluteLayer(box); } } OnLayoutFinished(); //----------------------- unchecked { layoutVersion++; } //----------------------- }