/// <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 FlowRunsIntoHost(LayoutVisitor lay, CssBox hostBox, CssBox splitableBox, CssBox b, int childNumber, //child number of b float limitRight, float firstRunStartX, float leftMostSpace, float rightMostSpace, List<CssRun> runs, ref CssLineBox hostLine, ref float cx) { //flow runs into hostLine, create new line if need bool wrapNoWrapBox = false; CssWhiteSpace bWhiteSpace = b.WhiteSpace; bool hostBoxIsB = hostBox == b; if (bWhiteSpace == CssWhiteSpace.NoWrap && cx > firstRunStartX) { var tmpRight = cx; for (int i = runs.Count - 1; i >= 0; --i) { tmpRight += runs[i].Width; } //----------------------------------------- if (tmpRight > limitRight) { wrapNoWrapBox = true; } } //----------------------------------------------------- int lim = runs.Count - 1; for (int i = 0; i <= lim; ++i) { var run = runs[i]; //--------------------------------------------------- //check if need to start new line ? if ((cx + run.Width + rightMostSpace > limitRight && bWhiteSpace != CssWhiteSpace.NoWrap && bWhiteSpace != CssWhiteSpace.Pre && (bWhiteSpace != CssWhiteSpace.PreWrap || !run.IsSpaces)) || run.IsLineBreak || wrapNoWrapBox) { wrapNoWrapBox = false; //once! //------------------------------- //create new line *** hostLine = new CssLineBox(hostBox); hostBox.AddLineBox(hostLine); //reset x pos for new line cx = firstRunStartX; // handle if line is wrapped for the first text element where parent has left margin/padding if (childNumber == 0 && //b is first child of splitable box ('b' == splitableBox.GetFirstChild()) !run.IsLineBreak && (i == 0 || splitableBox.ParentBox.IsBlock))//this run is first run of 'b' (run == b.FirstRun) { //TODO: review here again!!!! //cx += splitableBox.ActualMarginLeft + // splitableBox.ActualBorderLeftWidth + // splitableBox.ActualPaddingLeft; } if (run.IsSolidContent || i == 0) { cx += leftMostSpace; } } //--------------------------------------------------- if (run.IsSpaces && hostLine.RunCount == 0) { //not add continue; } //--------------------------------------------------- hostLine.AddRun(run); //*** if (lim == 0) { //single one if (!hostBoxIsB) { cx += b.ActualPaddingLeft; } run.SetLocation(cx, 0); cx += run.Width + b.ActualPaddingRight; } else { if (i == 0) { //first if (!hostBoxIsB) { cx += b.ActualPaddingLeft; } run.SetLocation(cx, 0); cx = run.Right; } else if (i == lim) { run.SetLocation(cx, 0); cx += run.Width + b.ActualPaddingRight; } else { run.SetLocation(cx, 0); cx = run.Right; } } //--------------------------------------------------- //move current_line_x to right of run //cx = run.Right; } }