/// <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; }
/// <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; }