From 501eeb74ead4a97e068e1ed2b19fe9f7da4df569 Mon Sep 17 00:00:00 2001 From: win Date: Fri, 24 Jul 2015 16:59:25 +0600 Subject: [PATCH 01/11] 9002: test files --- .../Samples/0_acid1_dev/003.2.html | 3 +- .../Samples/0_acid1_dev/003.3 | 137 ++++++++++++++++++ .../Samples/0_acid1_dev/003.3.html | 17 +++ .../2_Boxes/1_CoreBox/CssBox.cs | 2 +- .../1_CoreBox/CssBox_OtherActualValues.cs | 3 + .../0_General/CssLayoutEngine.cs | 12 +- 6 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 create mode 100644 Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.2.html b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.2.html index 808ec4e0d..80ad44299 100644 --- a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.2.html +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.2.html @@ -119,7 +119,7 @@ - + abcd

bang @@ -132,5 +132,6 @@

+ 1234 diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 new file mode 100644 index 000000000..80ad44299 --- /dev/null +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 @@ -0,0 +1,137 @@ + + + display/box/float/clear test + + + + + abcd +
+

+ bang + + +

+

+ whimper + + +

+
+ 1234 + + diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html new file mode 100644 index 000000000..fb4e13373 --- /dev/null +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html @@ -0,0 +1,17 @@ + + + test + + + +
+ 12345 +
sub1
+
sub2
+ 67890 +
+
+ abcde +
+ + diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 6ec101eb6..5a43d490b 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -59,7 +59,7 @@ public CssBox(BoxSpec spec, IRootGraphics rootgfx) if (!spec.IsFreezed) { //must be freezed - //throw new NotSupportedException(); + throw new NotSupportedException(); } #endif diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs index 209291522..ebe52c19f 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs @@ -105,7 +105,10 @@ internal void DirectSetBorderWidth(CssSide side, float w) public static void ChangeDisplayType(CssBox box, CssDisplay newdisplay) { + if (box._cssDisplay == CssDisplay.Block && newdisplay == CssDisplay.Inline) + { + } if ((box._boxCompactFlags & BoxFlags.DONT_CHANGE_DISPLAY_TYPE) == 0) { box._cssDisplay = newdisplay; diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index b379fa2b7..f52191fe9 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -176,7 +176,7 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) } else { - localTop = prevSibling.LocalVisualBottom; + localTop = prevSibling.LocalVisualBottom; } localTop += box.UpdateMarginTopCollapse(prevSibling); box.SetLocation(localLeft, localTop); @@ -766,6 +766,15 @@ static void FlowBoxContentIntoHostLineFmtContext( var ifonts = lay.SampleIFonts; foreach (CssBox b in srcBox.GetChildBoxIter()) { + +#if DEBUG + if (b.__aa_dbugId == 4) + { + + } +#endif + + float leftMostSpace = 0, rightMostSpace = 0; //if b has absolute pos then it is removed from the flow if (b.NeedComputedValueEvaluation) @@ -987,7 +996,6 @@ static void FlowBoxContentIntoHostLineFmtContext( } break; } - } else { From 9304448960ebc203eb03bc2d3b696c1d4a1a931b Mon Sep 17 00:00:00 2001 From: win Date: Sat, 25 Jul 2015 18:23:22 +0700 Subject: [PATCH 02/11] 9003: new Css3 display enum, and clean up --- .../Samples/0_acid1_dev/003.3 | 137 ------------------ .../7_Events/HtmlInputEventAdapter.cs | 4 + Source/LayoutFarm.CssBase/CssProps.cs | 48 +++++- .../2_Boxes/1_CoreBox/CssBox.cs | 4 +- .../1_CoreBox/CssBox_OtherActualValues.cs | 5 +- .../2_Boxes/2_Runs/CssRun.cs | 4 +- .../4_HitAndSelections/SelectionRange.cs | 19 ++- .../3_Boxes_Layout/0_General/BoxHitUtils.cs | 4 +- .../0_General/CssLayoutEngine.cs | 1 + 9 files changed, 70 insertions(+), 156 deletions(-) delete mode 100644 Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 deleted file mode 100644 index 80ad44299..000000000 --- a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3 +++ /dev/null @@ -1,137 +0,0 @@ - - - display/box/float/clear test - - - - - abcd -
-

- bang - - -

-

- whimper - - -

-
- 1234 - - diff --git a/Source/LayoutFarm.Composers/7_Events/HtmlInputEventAdapter.cs b/Source/LayoutFarm.Composers/7_Events/HtmlInputEventAdapter.cs index 6cb62e39c..86f5fa781 100755 --- a/Source/LayoutFarm.Composers/7_Events/HtmlInputEventAdapter.cs +++ b/Source/LayoutFarm.Composers/7_Events/HtmlInputEventAdapter.cs @@ -136,6 +136,7 @@ public void MouseMove(UIMouseEventArgs e, CssBox startAt) //dragging *** , if changed if (this._mousedownX != x || this._mousedownY != y) { + //handle mouse drag CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(x, y); @@ -169,6 +170,7 @@ public void MouseMove(UIMouseEventArgs e, CssBox startAt) BoxHitUtils.HitTest(_mouseDownStartAt, lastRootGlobalX, lastRootGlobalY, _latestMouseDownChain); } + //create selection range var newSelectionRange = new SelectionRange( _latestMouseDownChain, @@ -176,10 +178,12 @@ public void MouseMove(UIMouseEventArgs e, CssBox startAt) this.ifonts); if (newSelectionRange.IsValid) { + this._htmlContainer.SetSelection(newSelectionRange); } else { + this._htmlContainer.SetSelection(null); } } diff --git a/Source/LayoutFarm.CssBase/CssProps.cs b/Source/LayoutFarm.CssBase/CssProps.cs index 7c57101ca..a01948f67 100755 --- a/Source/LayoutFarm.CssBase/CssProps.cs +++ b/Source/LayoutFarm.CssBase/CssProps.cs @@ -4,8 +4,54 @@ namespace LayoutFarm.Css { + // + // = block | inline | run-in ; + // + // = flow | flow-root | table | flex | grid | ruby ; + // + // = list-item && ? && [ flow | flow-root ]? + // + // = table-row-group | table-header-group | + // table-footer-group | table-row | table-cell | + // table-column-group | table-column | table-caption | + // ruby-base | ruby-text | ruby-base-container | + // ruby-text-container ; + // + // = contents | none ; + // + // = inline-block | inline-list-item | + // inline-table | inline-flex | inline-grid ; + // //-------------------------------------------------- + + public enum CssDisplayOutside : byte + { + Block, + Inline, + RunIn + } + public enum CssDisplayInside : byte + { + Flow, + FlowRoot, + Table, + Flex, + Grid, + Ruby + } + public enum CssDisplayBox : byte + { + Contents, + None + } + public enum CssDisplayLegacy : byte + { + InlineBlock, + InlineListItem, + InlineTable, + InlineFlex, + InlineGrid + } - //-------------------------------------------------- public enum CssDisplay : byte { [Map(CssConstants.Inline)] diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 5a43d490b..6237fef40 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -148,13 +148,13 @@ public bool IsCustomCssBox /// /// is the box "Display" is "Inline", is this is an inline box and not block. /// - public bool IsInline + internal bool IsInline { get { return (this._boxCompactFlags & BoxFlags.IS_INLINE_BOX) != 0; } - internal set + set { if (value) { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs index ebe52c19f..613e3a31f 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs @@ -105,10 +105,7 @@ internal void DirectSetBorderWidth(CssSide side, float w) public static void ChangeDisplayType(CssBox box, CssDisplay newdisplay) { - if (box._cssDisplay == CssDisplay.Block && newdisplay == CssDisplay.Inline) - { - - } + if ((box._boxCompactFlags & BoxFlags.DONT_CHANGE_DISPLAY_TYPE) == 0) { box._cssDisplay = newdisplay; diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/2_Runs/CssRun.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/2_Runs/CssRun.cs index 5fd9d517a..164280e29 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/2_Runs/CssRun.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/2_Runs/CssRun.cs @@ -144,9 +144,7 @@ public float Left set { this._x = value; - if (_x == 55) - { - } + } } diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/4_HitAndSelections/SelectionRange.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/4_HitAndSelections/SelectionRange.cs index 6b84be289..af98e8c43 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/4_HitAndSelections/SelectionRange.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/4_HitAndSelections/SelectionRange.cs @@ -26,9 +26,9 @@ public class SelectionRange public SelectionRange(CssBoxHitChain startChain, CssBoxHitChain endChain, IFonts ifonts) - { + { if (IsOnTheSameLine(startChain, endChain)) - { + { //on the same line if (endChain.RootGlobalX < startChain.RootGlobalX) { @@ -40,6 +40,7 @@ public SelectionRange(CssBoxHitChain startChain, } else { + //across line if (endChain.RootGlobalY < startChain.RootGlobalY) { //swap @@ -48,8 +49,7 @@ public SelectionRange(CssBoxHitChain startChain, startChain = tmp; } } - - + //1. this.SetupStartHitPoint(startChain, ifonts); //2. @@ -59,6 +59,7 @@ public SelectionRange(CssBoxHitChain startChain, return; } + this.SetupEndHitPoint(startChain, endChain, ifonts); this.snapSelectionArea = this.GetSelectionRectArea(); } @@ -328,10 +329,14 @@ void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, IFonts } break; } + +#if DEBUG if (xposOnEndLine == 0) { } +#endif + //---------------------------------- this.selectedLines = new List(); if (startHitHostLine == endline) @@ -778,19 +783,19 @@ public static void SelectPartialFromStart(this CssLineBox lineBox, int endAtPx, EndHitRun = endRun, EndHitCharIndex = endRunIndex }; - } + } public static void Select(this CssLineBox lineBox, int startAtPx, int endAt, CssRun startRun, int startRunIndex, CssRun endRun, int endRunIndex) - { + { lineBox.SelectionSegment = new SelectionSegment(startAtPx, endAt - startAtPx) { StartHitRun = startRun, StartHitCharIndex = startRunIndex, EndHitRun = endRun, EndHitCharIndex = endRunIndex - }; + }; } } diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs index d06f4d574..7f30785ae 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs @@ -26,7 +26,7 @@ public static class BoxHitUtils public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain) { - + //-------------------------------------- float boxHitLocalX = x - box.LocalX; float boxHitLocalY = y - box.LocalY; @@ -112,7 +112,7 @@ public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain var blockRun = (CssBlockRun)foundRun; CssLineBox hostLine = blockRun.HostLine; //adjust with hostline - + HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain); } } diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index f52191fe9..5af888734 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -118,6 +118,7 @@ public static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay) } //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom; } + /// /// Check if the given box contains only inline child boxes. /// From e6586ed711c2d9952baa67935cfc61f2080a369a Mon Sep 17 00:00:00 2001 From: win Date: Sat, 25 Jul 2015 19:24:27 +0700 Subject: [PATCH 03/11] 9004: CssBox,OutsideDisplayIsInline --- Source/LayoutFarm.CssBase/CssProps.cs | 8 +- .../2_Boxes/1_CoreBox/CssBox.cs | 4 +- .../1_CoreBox/CssBox_OtherActualValues.cs | 110 +++++++++++++++++- .../2_Boxes/1_CoreBox/CssLineBox.cs | 2 +- .../0_General/CssLayoutEngine.cs | 12 +- 5 files changed, 123 insertions(+), 13 deletions(-) diff --git a/Source/LayoutFarm.CssBase/CssProps.cs b/Source/LayoutFarm.CssBase/CssProps.cs index a01948f67..fd974839f 100755 --- a/Source/LayoutFarm.CssBase/CssProps.cs +++ b/Source/LayoutFarm.CssBase/CssProps.cs @@ -25,12 +25,18 @@ namespace LayoutFarm.Css public enum CssDisplayOutside : byte { + None, Block, Inline, - RunIn + RunIn, + + TableCell, + TableCaption } public enum CssDisplayInside : byte { + None, + Flow, FlowRoot, Table, diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 6237fef40..37e02a360 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -40,7 +40,7 @@ public partial class CssBox readonly Css.BoxSpec _myspec; object _controller; IRootGraphics rootgfx; - + #if DEBUG public int dbugMark1; public readonly int __aa_dbugId = dbugTotalId++; @@ -148,7 +148,7 @@ public bool IsCustomCssBox /// /// is the box "Display" is "Inline", is this is an inline box and not block. /// - internal bool IsInline + internal bool OutsideDisplayIsInline { get { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs index 613e3a31f..269146fa0 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs @@ -22,6 +22,9 @@ partial class CssBox float _actualBorderSpacingHorizontal; float _actualBorderSpacingVertical; + CssDisplayOutside _displayOutside; + CssDisplayInside _displayInside; + /// /// Gets the line height /// @@ -36,9 +39,18 @@ public CssDisplay CssDisplay { get { + //TODO review here return this._cssDisplay; } } + public CssDisplayOutside CssDisplayOutside + { + get { return this._displayOutside; } + } + public CssDisplayInside CssDisplayInside + { + get { return this._displayInside; } + } /// /// Gets the text indentation (on first line only) /// @@ -103,16 +115,104 @@ internal void DirectSetBorderWidth(CssSide side, float w) } } + static void TranslateDisplayInsideOutside(CssDisplay cssDisplay, out CssDisplayInside inside, out CssDisplayOutside outside) + { + //Short display Full display Generated box + //none 〃 subtree omitted from box tree + //contents 〃 element replaced by contents in box tree + + //block 'block flow' block-level block container aka block box + //flow-root 'block flow-root' block-level block container that establishes a new block formatting context (BFC) + //inline 'inline flow' inline box + //inline-block 'inline flow-root' inline-level block container + //run-in 'run-in flow' run-in box (inline box with special box-tree-munging rules) + //list-item 'list-item block flow' block box with additional marker box + //inline list-item 'list-item inline flow' inline box with additional marker box + //flex 'block flex' block-level flex container + //inline-flex 'inline flex' inline-level flex container + //grid 'block grid' block-level grid container + //inline-grid 'inline grid' inline-level grid container + //ruby 'inline ruby' inline-level ruby container + //block ruby 'block ruby' block box containing ruby container + //table 'block table' block-level table wrapper box containing table box + //inline-table 'inline table' inline-level table wrapper box containing table box + //table-cell 'table-cell flow' table cell block container + //table-caption 'table-caption flow' table cell block container + //ruby-base 'ruby-base flow' layout-specific internal box + //ruby-text 'ruby-text flow' layout-specific internal box + //other 〃 layout-specific internal box + switch (cssDisplay) + { + default: + throw new NotSupportedException(); + + case CssDisplay.None: + outside = CssDisplayOutside.None; + inside = CssDisplayInside.None; + break; + //outside -> inline + case CssDisplay.Inline: + outside = CssDisplayOutside.Inline; //* + inside = CssDisplayInside.Flow; + break; + case CssDisplay.InlineBlock: + outside = CssDisplayOutside.Inline; //* + inside = CssDisplayInside.FlowRoot; + break; + case CssDisplay.InlineTable: + outside = CssDisplayOutside.Inline; //* + inside = CssDisplayInside.Table; + break; + case CssDisplay.InlineFlex: + outside = CssDisplayOutside.Inline; //* + inside = CssDisplayInside.Flex; + break; + //------- + //outside -> block + case CssDisplay.Flex: + outside = CssDisplayOutside.Block; + inside = CssDisplayInside.Flex; + break; + + case CssDisplay.Block: + outside = CssDisplayOutside.Block; + inside = CssDisplayInside.Flow; + break; + + case CssDisplay.Table: + outside = CssDisplayOutside.Block; + inside = CssDisplayInside.Table; + break; + //----------------- + //special + case CssDisplay.TableCaption: + outside = CssDisplayOutside.TableCaption; + inside = CssDisplayInside.Flow; + break; + case CssDisplay.TableCell: + outside = CssDisplayOutside.TableCell; + inside = CssDisplayInside.Flow; + break; + + } + + } public static void ChangeDisplayType(CssBox box, CssDisplay newdisplay) { - + + + CssDisplayInside displayInside; + CssDisplayOutside displayOutside; + TranslateDisplayInsideOutside(newdisplay, out displayInside, out displayOutside); + + if ((box._boxCompactFlags & BoxFlags.DONT_CHANGE_DISPLAY_TYPE) == 0) { box._cssDisplay = newdisplay; } - box.IsInline = ((newdisplay == CssDisplay.Inline || + box.OutsideDisplayIsInline = ((newdisplay == CssDisplay.Inline || newdisplay == CssDisplay.InlineBlock || newdisplay == CssDisplay.InlineFlex) && !box.IsBrElement); @@ -130,11 +230,13 @@ public static void ChangeDisplayType(CssBox box, CssDisplay newdisplay) switch (newdisplay) { case CssDisplay.Block: + case CssDisplay.InlineBlock: + case CssDisplay.ListItem: case CssDisplay.Table: - case CssDisplay.TableCell: - case CssDisplay.InlineBlock: case CssDisplay.InlineTable: + case CssDisplay.TableCell: + case CssDisplay.Flex: case CssDisplay.InlineFlex: box._boxCompactFlags |= BoxFlags.HAS_CONTAINER_PROP; diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs index 149f608c9..bc6b244e1 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs @@ -690,7 +690,7 @@ static int StepUpRegisterStrips(Dictionary dicStrips, //step up var strip = inputList[i]; var upperBox = strip.owner.ParentBox; - if (upperBox != null && upperBox != lineOwnerBox && upperBox.IsInline) + if (upperBox != null && upperBox != lineOwnerBox && upperBox.OutsideDisplayIsInline) { RegisterStripPart(upperBox, strip.Left, strip.Top, strip.Right, strip.Bottom, inputList, dicStrips); } diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index 5af888734..cb94610fa 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -118,7 +118,7 @@ public static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay) } //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom; } - + /// /// Check if the given box contains only inline child boxes. /// @@ -131,7 +131,7 @@ static bool ContainsInlinesOnly(CssBox box) while (linkedNode != null) { - if (!linkedNode.Value.IsInline) + if (!linkedNode.Value.OutsideDisplayIsInline) { return false; } @@ -532,7 +532,7 @@ static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay) childBox.SetVisualHeight(FontDefaultConfig.DEFAULT_FONT_SIZE * 0.95f); } //----------------------------- - if (childBox.IsInline) + if (childBox.OutsideDisplayIsInline) { //inline correction on-the-fly ! //1. collect consecutive inlinebox @@ -550,7 +550,7 @@ static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay) if (tmp != null) { childBox = tmp.Value; - if (childBox.IsInline) + if (childBox.OutsideDisplayIsInline) { tmp = tmp.Next; if (tmp == null) @@ -775,7 +775,6 @@ static void FlowBoxContentIntoHostLineFmtContext( } #endif - float leftMostSpace = 0, rightMostSpace = 0; //if b has absolute pos then it is removed from the flow if (b.NeedComputedValueEvaluation) @@ -795,6 +794,9 @@ static void FlowBoxContentIntoHostLineFmtContext( //------------------------------------------------ if (b.CssDisplay == CssDisplay.InlineBlock) { + //outside -> inline + //inside -> block + //can't split //create 'block-run' PerformContentLayout(b, lay); From bfa0b3a71da0b89170852ddda6c1274e59eb0662 Mon Sep 17 00:00:00 2001 From: win Date: Sat, 25 Jul 2015 19:27:00 +0700 Subject: [PATCH 04/11] 9005: CssBox.HasOnlyRuns --- .../LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs | 2 +- .../2_Boxes/1_CoreBox/CssBox_Unsafe.cs | 4 ++-- .../3_Boxes_Layout/0_General/CssLayoutEngine.cs | 8 +++++--- .../3_Boxes_Layout/0_General/CssTableLayoutEngine.cs | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 37e02a360..238d577fc 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -374,7 +374,7 @@ List Runs } } - internal bool HasRuns + internal bool HasOnlyRuns { get { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs index 0172438fd..5fea806cf 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs @@ -77,7 +77,7 @@ public override string ToString() { if (this._controller != null) { - if (this.HasRuns) + if (this.HasOnlyRuns) { return this._controller.ToString() + " " + this.CssDisplay + " r=" + this.RunCount; } @@ -88,7 +88,7 @@ public override string ToString() } else { - if (this.HasRuns) + if (this.HasOnlyRuns) { return "!a " + " " + this.CssDisplay + " r=" + this.RunCount; } diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index cb94610fa..bcf71e324 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -745,11 +745,13 @@ static void FlowBoxContentIntoHostLineFmtContext( ref float cx, ref FloatFormattingContext floatCtx) { - + //recursive *** //-------------------------------------------------------------------- var oX = cx; - if (srcBox.HasRuns) + + + if (srcBox.HasOnlyRuns) { //condition 3 @@ -827,7 +829,7 @@ static void FlowBoxContentIntoHostLineFmtContext( new List() { b.JustBlockRun }, ref hostLine, ref cx); } - else if (b.HasRuns) + else if (b.HasOnlyRuns) { switch (b.Float) { diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssTableLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssTableLayoutEngine.cs index c687cf8f9..67f7ccc12 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssTableLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssTableLayoutEngine.cs @@ -1292,7 +1292,7 @@ static void CalculateMinMaxSumWords( paddingSum += CssTableLayoutEngine.CalculateTableSpacing(box); } - if (box.HasRuns) + if (box.HasOnlyRuns) { // calculate the min and max sum for all the words in the box foreach (CssRun run in box.GetRunIter()) From 4eae129b2b80f43601d7c6d2b10ee26be3a7f8d0 Mon Sep 17 00:00:00 2001 From: win Date: Sat, 25 Jul 2015 20:44:51 +0700 Subject: [PATCH 05/11] 9006: check if display inside is Block --- .../HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html | 2 +- .../2_Boxes/1_CoreBox/CssBox.cs | 4 +++- .../2_Boxes/1_CoreBox/CssBox_Fields.cs | 7 ++----- .../3_Boxes_Layout/0_General/CssLayoutEngine.cs | 12 +++++++++--- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html index fb4e13373..77d1203bb 100644 --- a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html @@ -4,7 +4,7 @@ -
+
12345
sub1
sub2
diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 238d577fc..158cf850b 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -373,7 +373,9 @@ List Runs return this._aa_contentRuns; } } - + /// + /// box has only runs + /// internal bool HasOnlyRuns { get diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs index 470da3678..9b2bbb581 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs @@ -58,15 +58,12 @@ partial class CssBox //condition 1: invalid * //condition 2: valid //condition 3: valid - LinkedList _clientLineBoxes; - + LinkedList _clientLineBoxes; /// /// absolute position layer /// - CssBoxCollection _absPosLayer; - //List _absLayer2; - + CssBoxCollection _absPosLayer; CssBlockRun justBlockRun; diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index bcf71e324..9c8bf8c99 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -745,7 +745,7 @@ static void FlowBoxContentIntoHostLineFmtContext( ref float cx, ref FloatFormattingContext floatCtx) { - + //recursive *** //-------------------------------------------------------------------- var oX = cx; @@ -769,7 +769,6 @@ static void FlowBoxContentIntoHostLineFmtContext( var ifonts = lay.SampleIFonts; foreach (CssBox b in srcBox.GetChildBoxIter()) { - #if DEBUG if (b.__aa_dbugId == 4) { @@ -794,8 +793,15 @@ static void FlowBoxContentIntoHostLineFmtContext( cx += leftMostSpace; //------------------------------------------------ - if (b.CssDisplay == CssDisplay.InlineBlock) + + if (b.CssDisplay == CssDisplay.InlineBlock || !ContainsInlinesOnly(b)) { + //-------- + // if inside display is block context *** + //--------- + + + //outside -> inline //inside -> block From a2182d2791d511452ca20bbefeb0c3a60b1238f2 Mon Sep 17 00:00:00 2001 From: win Date: Sun, 26 Jul 2015 09:29:14 +0700 Subject: [PATCH 06/11] 9007: TransplateDisplayOutsideInside --- .../Samples/0_acid1_dev/003.3.html | 1 + .../Samples/0_acid1_dev/003.4.html | 22 ++ Source/LayoutFarm.CssBase/CssProps.cs | 37 +- .../2_Boxes/1_CoreBox/CssBox.cs | 19 +- .../2_Boxes/1_CoreBox/CssBoxCollection.cs | 1 + .../1_CoreBox/CssBox_OtherActualValues.cs | 42 ++- .../3_Boxes_Layout/0_General/BoxHitUtils.cs | 8 +- .../0_General/CssLayoutEngine.cs | 320 +++++++++--------- 8 files changed, 236 insertions(+), 214 deletions(-) create mode 100644 Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.4.html diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html index 77d1203bb..b866681e7 100644 --- a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html @@ -4,6 +4,7 @@ + xyz
12345
sub1
diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.4.html b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.4.html new file mode 100644 index 000000000..30377e503 --- /dev/null +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.4.html @@ -0,0 +1,22 @@ + + + test + + + + abcd +
+

+ bang + + +

+

+ whimper + + +

+
+ 1234 + + diff --git a/Source/LayoutFarm.CssBase/CssProps.cs b/Source/LayoutFarm.CssBase/CssProps.cs index fd974839f..e5482aef5 100755 --- a/Source/LayoutFarm.CssBase/CssProps.cs +++ b/Source/LayoutFarm.CssBase/CssProps.cs @@ -25,39 +25,31 @@ namespace LayoutFarm.Css public enum CssDisplayOutside : byte { - None, + Internal, + Block, Inline, RunIn, TableCell, - TableCaption + TableCaption, + } + public enum CssDisplayInside : byte { - None, + Internal, Flow, FlowRoot, Table, Flex, Grid, - Ruby - } - public enum CssDisplayBox : byte - { - Contents, - None - } - public enum CssDisplayLegacy : byte - { - InlineBlock, - InlineListItem, - InlineTable, - InlineFlex, - InlineGrid + Ruby, } + + public enum CssDisplay : byte { [Map(CssConstants.Inline)] @@ -93,13 +85,7 @@ public enum CssDisplay : byte [Map(CssConstants.None)] None, - - //=========================================== - /// - ///following group act as Containing box : Block,Table,TableCell, ListItem - /// - __CONTAINER_BEGIN_HERE, - + [Map(CssConstants.Block)] Block, [Map(CssConstants.Table)] @@ -110,8 +96,7 @@ public enum CssDisplay : byte ListItem, [Map(CssConstants.Flex)] - Flex - //=========================================== + Flex } public enum CssWhiteSpace : byte { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 158cf850b..919b39470 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -40,7 +40,7 @@ public partial class CssBox readonly Css.BoxSpec _myspec; object _controller; IRootGraphics rootgfx; - + #if DEBUG public int dbugMark1; public readonly int __aa_dbugId = dbugTotalId++; @@ -107,7 +107,22 @@ public CssBox ParentBox { get { return _parentBox; } } - + internal bool HasContainerProperty + { + get + { + switch (this._cssDisplay) + { + case Css.CssDisplay.Block: + case Css.CssDisplay.Table: + case Css.CssDisplay.TableCell: + case Css.CssDisplay.ListItem: + case Css.CssDisplay.Flex: + return true; + } + return false; + } + } public CssBox GetTopRootCssBox() { var topmost = this; diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs index 2a02b3ff8..c98ec3fe5 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs @@ -13,6 +13,7 @@ class CssBoxCollection public CssBoxCollection() { } + public IEnumerable GetChildBoxIter() { var cNode = _boxes.First; diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs index 269146fa0..333ee1a16 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_OtherActualValues.cs @@ -115,7 +115,7 @@ internal void DirectSetBorderWidth(CssSide side, float w) } } - static void TranslateDisplayInsideOutside(CssDisplay cssDisplay, out CssDisplayInside inside, out CssDisplayOutside outside) + static void TransplateDisplayOutsideInside(CssDisplay cssDisplay, out CssDisplayOutside outside, out CssDisplayInside inside) { //Short display Full display Generated box //none 〃 subtree omitted from box tree @@ -146,10 +146,18 @@ static void TranslateDisplayInsideOutside(CssDisplay cssDisplay, out CssDisplayI default: throw new NotSupportedException(); + case CssDisplay.TableColumn: + case CssDisplay.TableColumnGroup: + case CssDisplay.TableRow: + case CssDisplay.TableRowGroup: + case CssDisplay.TableHeaderGroup: + case CssDisplay.TableFooterGroup: case CssDisplay.None: - outside = CssDisplayOutside.None; - inside = CssDisplayInside.None; + outside = CssDisplayOutside.Internal; + inside = CssDisplayInside.Internal; break; + + //outside -> inline case CssDisplay.Inline: outside = CssDisplayOutside.Inline; //* @@ -169,10 +177,14 @@ static void TranslateDisplayInsideOutside(CssDisplay cssDisplay, out CssDisplayI break; //------- //outside -> block + case CssDisplay.ListItem: + outside = CssDisplayOutside.Block; + inside = CssDisplayInside.Flow; + break; case CssDisplay.Flex: outside = CssDisplayOutside.Block; inside = CssDisplayInside.Flex; - break; + break; case CssDisplay.Block: outside = CssDisplayOutside.Block; @@ -200,22 +212,20 @@ static void TranslateDisplayInsideOutside(CssDisplay cssDisplay, out CssDisplayI public static void ChangeDisplayType(CssBox box, CssDisplay newdisplay) { - - CssDisplayInside displayInside; - CssDisplayOutside displayOutside; - TranslateDisplayInsideOutside(newdisplay, out displayInside, out displayOutside); - + TransplateDisplayOutsideInside(newdisplay, out box._displayOutside, out box._displayInside); if ((box._boxCompactFlags & BoxFlags.DONT_CHANGE_DISPLAY_TYPE) == 0) - { + { box._cssDisplay = newdisplay; } - box.OutsideDisplayIsInline = ((newdisplay == CssDisplay.Inline || - newdisplay == CssDisplay.InlineBlock || - newdisplay == CssDisplay.InlineFlex) - && !box.IsBrElement); + //box.OutsideDisplayIsInline = ((newdisplay == CssDisplay.Inline || + // newdisplay == CssDisplay.InlineBlock || + // newdisplay == CssDisplay.InlineFlex) + // && !box.IsBrElement); + box.OutsideDisplayIsInline = box._displayOutside == CssDisplayOutside.Inline && !box.IsBrElement; + //--------------------------- box._isVisible = box._cssDisplay != CssDisplay.None && box._myspec.Visibility == CssVisibility.Visible; @@ -235,8 +245,8 @@ public static void ChangeDisplayType(CssBox box, CssDisplay newdisplay) case CssDisplay.ListItem: case CssDisplay.Table: case CssDisplay.InlineTable: - case CssDisplay.TableCell: - + case CssDisplay.TableCell: + case CssDisplay.Flex: case CssDisplay.InlineFlex: box._boxCompactFlags |= BoxFlags.HAS_CONTAINER_PROP; diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs index 7f30785ae..d4186e59e 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/BoxHitUtils.cs @@ -26,10 +26,10 @@ public static class BoxHitUtils public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain) { - + //-------------------------------------- float boxHitLocalX = x - box.LocalX; - float boxHitLocalY = y - box.LocalY; + float boxHitLocalY = y - box.LocalY; bool isPointInArea = box.IsPointInArea(x, y); //---------------------------------------------------------------------- if (isPointInArea) @@ -112,7 +112,7 @@ public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain var blockRun = (CssBlockRun)foundRun; CssLineBox hostLine = blockRun.HostLine; //adjust with hostline - + HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain); } } @@ -257,7 +257,7 @@ internal static CssBox SearchUpForContainingBlockBox(CssBox startBox) } var box = startBox.ParentBox; - while (box.CssDisplay < Css.CssDisplay.__CONTAINER_BEGIN_HERE && + while (box.HasContainerProperty && box.ParentBox != null) { box = box.ParentBox; diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index 9c8bf8c99..475fc2cea 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -17,130 +17,19 @@ using System.Collections.Generic; using PixelFarm.Drawing; using LayoutFarm.Css; -using PixelFarm.Drawing; namespace LayoutFarm.HtmlBoxes { /// /// Helps on CSS Layout. /// - static partial class CssLayoutEngine + static class CssLayoutEngine { const float CSS_OFFSET_THRESHOLD = 0.1f; - - /// - /// Measure image box size by the width\height set on the box and the actual rendered image size.
- /// If no image exists for the box error icon will be set. - ///
- /// the image word to measure - public static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay) - { - var width = imgRun.OwnerBox.Width; - var height = imgRun.OwnerBox.Height; - - bool hasImageTagWidth = width.Number > 0 && width.UnitOrNames == CssUnitOrNames.Pixels; - bool hasImageTagHeight = height.Number > 0 && height.UnitOrNames == CssUnitOrNames.Pixels; - bool scaleImageHeight = false; - - if (hasImageTagWidth) - { - imgRun.Width = width.Number; - } - else if (width.Number > 0 && width.IsPercentage) - { - - imgRun.Width = width.Number * lay.LatestContainingBlock.VisualWidth; - scaleImageHeight = true; - } - else if (imgRun.HasUserImageContent) - { - imgRun.Width = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageWidth : imgRun.ImageRectangle.Width; - } - else - { - imgRun.Width = hasImageTagHeight ? height.Number / 1.14f : 20; - } - - var maxWidth = imgRun.OwnerBox.MaxWidth;// new CssLength(imageWord.OwnerBox.MaxWidth); - if (maxWidth.Number > 0) - { - float maxWidthVal = -1; - switch (maxWidth.UnitOrNames) - { - case CssUnitOrNames.Percent: - { - maxWidthVal = maxWidth.Number * lay.LatestContainingBlock.VisualWidth; - } break; - case CssUnitOrNames.Pixels: - { - maxWidthVal = maxWidth.Number; - } break; - } - - - if (maxWidthVal > -1 && imgRun.Width > maxWidthVal) - { - imgRun.Width = maxWidthVal; - scaleImageHeight = !hasImageTagHeight; - } - } - - if (hasImageTagHeight) - { - imgRun.Height = height.Number; - } - else if (imgRun.HasUserImageContent) - { - imgRun.Height = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageHeight : imgRun.ImageRectangle.Height; - } - else - { - imgRun.Height = imgRun.Width > 0 ? imgRun.Width * 1.14f : 22.8f; - } - - if (imgRun.HasUserImageContent) - { - // If only the width was set in the html tag, ratio the height. - if ((hasImageTagWidth && !hasImageTagHeight) || scaleImageHeight) - { - // Divide the given tag width with the actual image width, to get the ratio. - float ratio = imgRun.Width / imgRun.OriginalImageWidth; - imgRun.Height = imgRun.OriginalImageHeight * ratio; - } - // If only the height was set in the html tag, ratio the width. - else if (hasImageTagHeight && !hasImageTagWidth) - { - // Divide the given tag height with the actual image height, to get the ratio. - float ratio = imgRun.Height / imgRun.OriginalImageHeight; - imgRun.Width = imgRun.OriginalImageWidth * ratio; - } - } - //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom; - } - - /// - /// Check if the given box contains only inline child boxes. - /// - /// the box to check - /// true - only inline child boxes, false - otherwise - static bool ContainsInlinesOnly(CssBox box) - { - var children = CssBox.UnsafeGetChildren(box); - var linkedNode = children.GetFirstLinkedNode(); - while (linkedNode != null) - { - - if (!linkedNode.Value.OutsideDisplayIsInline) - { - return false; - } - linkedNode = linkedNode.Next; - } - return true; - } public static void PerformContentLayout(CssBox box, LayoutVisitor lay) { + //recursive //this box has its own container property //this box may use... @@ -201,39 +90,7 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) lay.LatestSiblingBox = currentLevelLatestSibling; lay.PopContainingBlock(); //TODO: check if this can have absolute layer? - } break; - case CssDisplay.InlineFlex: - case CssDisplay.Flex: - { - //------------------------------------------------ - //arrange as normal first - if (box.IsCustomCssBox) - { - //has custom layout method - box.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock); - box.CustomRecomputedValue(lay.LatestContainingBlock, lay.GraphicsPlatform); - } - else - { - if (ContainsInlinesOnly(box)) - { - //This will automatically set the bottom of this block - DoLayoutLinesContext(box, lay); - } - else if (box.ChildCount > 0) - { - DoLayoutBlocksContext(box, lay); - } - - if (box.HasAbsoluteLayer) - { - LayoutContentInAbsoluteLayer(lay, box); - } - } - //------------------------------------------------ - RearrangeWithFlexContext(box, lay); - //------------------------------------------------ - } break; + } break; default: { //formatting context for... @@ -256,19 +113,35 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) { DoLayoutBlocksContext(box, lay); } + if (box.HasAbsoluteLayer) { LayoutContentInAbsoluteLayer(lay, box); } } - //TODO: review here again - if (box.Float != CssFloat.None) + //--------------------- + //again! + switch (box.CssDisplay) { - var iw = box.InnerContentWidth; - var ew = box.VisualWidth; - //float to specific position - box.SetVisualSize(iw, box.VisualHeight); + 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; + //float to specific position + box.SetVisualSize(iw, box.VisualHeight); + } + } break; } + //--------------------- } break; } @@ -384,6 +257,120 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) } } + + + + /// + /// Measure image box size by the width\height set on the box and the actual rendered image size.
+ /// If no image exists for the box error icon will be set. + ///
+ /// the image word to measure + public static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay) + { + var width = imgRun.OwnerBox.Width; + var height = imgRun.OwnerBox.Height; + + bool hasImageTagWidth = width.Number > 0 && width.UnitOrNames == CssUnitOrNames.Pixels; + bool hasImageTagHeight = height.Number > 0 && height.UnitOrNames == CssUnitOrNames.Pixels; + bool scaleImageHeight = false; + + if (hasImageTagWidth) + { + imgRun.Width = width.Number; + } + else if (width.Number > 0 && width.IsPercentage) + { + + imgRun.Width = width.Number * lay.LatestContainingBlock.VisualWidth; + scaleImageHeight = true; + } + else if (imgRun.HasUserImageContent) + { + imgRun.Width = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageWidth : imgRun.ImageRectangle.Width; + } + else + { + imgRun.Width = hasImageTagHeight ? height.Number / 1.14f : 20; + } + + var maxWidth = imgRun.OwnerBox.MaxWidth;// new CssLength(imageWord.OwnerBox.MaxWidth); + if (maxWidth.Number > 0) + { + float maxWidthVal = -1; + switch (maxWidth.UnitOrNames) + { + case CssUnitOrNames.Percent: + { + maxWidthVal = maxWidth.Number * lay.LatestContainingBlock.VisualWidth; + } break; + case CssUnitOrNames.Pixels: + { + maxWidthVal = maxWidth.Number; + } break; + } + + + if (maxWidthVal > -1 && imgRun.Width > maxWidthVal) + { + imgRun.Width = maxWidthVal; + scaleImageHeight = !hasImageTagHeight; + } + } + + if (hasImageTagHeight) + { + imgRun.Height = height.Number; + } + else if (imgRun.HasUserImageContent) + { + imgRun.Height = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageHeight : imgRun.ImageRectangle.Height; + } + else + { + imgRun.Height = imgRun.Width > 0 ? imgRun.Width * 1.14f : 22.8f; + } + + if (imgRun.HasUserImageContent) + { + // If only the width was set in the html tag, ratio the height. + if ((hasImageTagWidth && !hasImageTagHeight) || scaleImageHeight) + { + // Divide the given tag width with the actual image width, to get the ratio. + float ratio = imgRun.Width / imgRun.OriginalImageWidth; + imgRun.Height = imgRun.OriginalImageHeight * ratio; + } + // If only the height was set in the html tag, ratio the width. + else if (hasImageTagHeight && !hasImageTagWidth) + { + // Divide the given tag height with the actual image height, to get the ratio. + float ratio = imgRun.Height / imgRun.OriginalImageHeight; + imgRun.Width = imgRun.OriginalImageWidth * ratio; + } + } + //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom; + } + + /// + /// Check if the given box contains only inline child boxes. + /// + /// the box to check + /// true - only inline child boxes, false - otherwise + static bool ContainsInlinesOnly(CssBox box) + { + var children = CssBox.UnsafeGetChildren(box); + var linkedNode = children.GetFirstLinkedNode(); + while (linkedNode != null) + { + if (!linkedNode.Value.OutsideDisplayIsInline) + { + return false; + } + + linkedNode = linkedNode.Next; + } + return true; + } + /// /// do layout line formatting context /// @@ -446,12 +433,13 @@ static void DoLayoutLinesContext(CssBox hostBlock, LayoutVisitor lay) int interlineSpace = 0; - //First line box + //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); @@ -749,8 +737,6 @@ static void FlowBoxContentIntoHostLineFmtContext( //recursive *** //-------------------------------------------------------------------- var oX = cx; - - if (srcBox.HasOnlyRuns) { //condition 3 @@ -769,6 +755,13 @@ static void FlowBoxContentIntoHostLineFmtContext( var ifonts = lay.SampleIFonts; foreach (CssBox b in srcBox.GetChildBoxIter()) { + if (b.CssDisplay == CssDisplay.Block) + { + //if display outside is block + //just break + + } + //----------------------------------------- #if DEBUG if (b.__aa_dbugId == 4) { @@ -792,15 +785,11 @@ static void FlowBoxContentIntoHostLineFmtContext( #endif cx += leftMostSpace; - //------------------------------------------------ - - if (b.CssDisplay == CssDisplay.InlineBlock || !ContainsInlinesOnly(b)) + if (b.CssDisplay == CssDisplay.InlineBlock) { //-------- // if inside display is block context *** - //--------- - - + //--------- //outside -> inline //inside -> block @@ -808,7 +797,6 @@ static void FlowBoxContentIntoHostLineFmtContext( //can't split //create 'block-run' PerformContentLayout(b, lay); - CssBlockRun blockRun = b.JustBlockRun; if (blockRun == null) { @@ -835,6 +823,7 @@ static void FlowBoxContentIntoHostLineFmtContext( new List() { b.JustBlockRun }, ref hostLine, ref cx); } + else if (b.HasOnlyRuns) { switch (b.Float) @@ -847,6 +836,7 @@ static void FlowBoxContentIntoHostLineFmtContext( leftMostSpace, rightMostSpace, CssBox.UnsafeGetRunList(b), ref hostLine, ref cx); + } break; case CssFloat.Left: { @@ -854,8 +844,6 @@ static void FlowBoxContentIntoHostLineFmtContext( //1. current line is shortening //2. add 'b' to special container *** - - var newAnonBlock = new CssFloatContainerBox( CssBox.UnsafeGetBoxSpec(b), b.RootGfx, CssDisplay.Block); @@ -1303,7 +1291,7 @@ static void ApplyJustifyAlignment(CssLineBox lineBox) /// /// /// - private static void ApplyCenterAlignment(CssLineBox line) + static void ApplyCenterAlignment(CssLineBox line) { if (line.RunCount == 0) return; @@ -1324,7 +1312,7 @@ private static void ApplyCenterAlignment(CssLineBox line) /// /// /// - private static void ApplyRightAlignment(CssLineBox line) + static void ApplyRightAlignment(CssLineBox line) { if (line.RunCount == 0) { From 4a2a13d819195478ade9d3990c8edabe64f20781 Mon Sep 17 00:00:00 2001 From: win Date: Sun, 26 Jul 2015 10:27:10 +0700 Subject: [PATCH 07/11] 9008: begin simplify layout tech --- .../2_Boxes/1_CoreBox/CssBox.cs | 3 - .../2_Boxes/1_CoreBox/CssLineBox.cs | 3 - .../0_General/CssLayoutEngine.cs | 81 ++++++++++++++++--- 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs index 919b39470..22e047abb 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox.cs @@ -281,10 +281,7 @@ internal string dbugCopyTextContent() #endif internal void AddLineBox(CssLineBox linebox) { - - linebox.linkedNode = this._clientLineBoxes.AddLast(linebox); - } internal int LineBoxCount { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs index bc6b244e1..4f28b8d4e 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs @@ -135,9 +135,6 @@ sealed class CssLineBox static int dbugTotalId; public readonly int dbugId = dbugTotalId++; #endif - - - /// /// Creates a new LineBox /// diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index 475fc2cea..04f8cbae1 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -20,6 +20,51 @@ namespace LayoutFarm.HtmlBoxes { + + enum LayoutContextMode + { + Inline, + Block + } + + class LayoutContext + { + CssBox hostBox; + LayoutVisitor lay; + LayoutContextMode mode; + public LayoutContext() + { + } + public CssBox HostBox + { + get { return this.hostBox; } + + } + public void BeginHostBox(CssBox hostBox, LayoutVisitor lay) + { + this.hostBox = hostBox; + this.lay = lay; + this.mode = LayoutContextMode.Inline; + } + public void AddCssBox(CssBox box) + { + switch (mode) + { + case LayoutContextMode.Block: + { + } break; + default: + { + + } break; + + } + } + } + + + + /// /// Helps on CSS Layout. /// @@ -90,7 +135,7 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) lay.LatestSiblingBox = currentLevelLatestSibling; lay.PopContainingBlock(); //TODO: check if this can have absolute layer? - } break; + } break; default: { //formatting context for... @@ -104,6 +149,21 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) } else { + + //new candidate technique + var layoutContext = new LayoutContext(); + layoutContext.BeginHostBox(box, lay); + + var children = CssBox.UnsafeGetChildren(box); + var cnode = children.GetFirstLinkedNode(); + + while (cnode != null) + { + layoutContext.AddCssBox(cnode.Value); + cnode = cnode.Next; + } + //---------------------------------------------- + if (ContainsInlinesOnly(box)) { //This will automatically set the bottom of this block @@ -114,6 +174,8 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) DoLayoutBlocksContext(box, lay); } + + if (box.HasAbsoluteLayer) { LayoutContentInAbsoluteLayer(lay, box); @@ -493,6 +555,7 @@ static void DoLayoutLinesContext(CssBox hostBlock, LayoutVisitor lay) } } } + hostBlock.SetVisualHeight(localY + hostBlock.ActualPaddingBottom + hostBlock.ActualBorderBottomWidth); //final @@ -545,7 +608,7 @@ static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay) { children.Remove(childBox); anoForInline.AppendChild(childBox); - break; + break;//break from do while } } else @@ -555,7 +618,7 @@ static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay) } else { - break; + break;//break from do while } } while (true); @@ -755,7 +818,7 @@ static void FlowBoxContentIntoHostLineFmtContext( var ifonts = lay.SampleIFonts; foreach (CssBox b in srcBox.GetChildBoxIter()) { - if (b.CssDisplay == CssDisplay.Block) + if (b.CssDisplayOutside == CssDisplayOutside.Block) { //if display outside is block //just break @@ -998,19 +1061,15 @@ static void FlowBoxContentIntoHostLineFmtContext( } else { -#if DEBUG - if (srcBox.CssDisplay == CssDisplay.InlineBlock) - { - //should not found here! - throw new NotSupportedException(); - } -#endif + + //go deeper //recursive *** //not new lineFormatting context FlowBoxContentIntoHostLineFmtContext(lay, hostBox, b, limitLocalRight, firstRunStartX, ref hostLine, ref cx, ref floatCtx); + } cx += rightMostSpace; From fece95a0b56d1acba40ff1280d2092d740db2d6c Mon Sep 17 00:00:00 2001 From: win Date: Sun, 26 Jul 2015 13:22:08 +0700 Subject: [PATCH 08/11] 9009: LinesFormattingContext --- .../0_General/CssLayoutEngine.cs | 2077 ++++++++--------- .../5_Boxes_SpecialBoxes/CssBoxImage.cs | 99 +- 2 files changed, 1103 insertions(+), 1073 deletions(-) diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index 04f8cbae1..3f3ec5a3e 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -23,675 +23,586 @@ namespace LayoutFarm.HtmlBoxes enum LayoutContextMode { + Init, Inline, Block } - class LayoutContext + class LinesFormattingContext { - CssBox hostBox; + const float CSS_OFFSET_THRESHOLD = 0.1f; + CssBox hostBlock; LayoutVisitor lay; - LayoutContextMode mode; - public LayoutContext() - { - } - public CssBox HostBox - { - get { return this.hostBox; } - - } - public void BeginHostBox(CssBox hostBox, LayoutVisitor lay) + public void BeginContext(CssBox hostBlock, LayoutVisitor lay) { - this.hostBox = hostBox; + this.hostBlock = hostBlock; this.lay = lay; - this.mode = LayoutContextMode.Inline; } - public void AddCssBox(CssBox box) + public void EndContext() { - switch (mode) - { - case LayoutContextMode.Block: - { - } break; - default: - { + } - } break; + 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 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) + { - /// - /// Helps on CSS Layout. - /// - static class CssLayoutEngine - { + wrapNoWrapBox = false; //once! - const float CSS_OFFSET_THRESHOLD = 0.1f; - public static void PerformContentLayout(CssBox box, LayoutVisitor lay) - { - //recursive + //------------------------------- + //create new line *** + hostLine = new CssLineBox(hostBox); + hostBox.AddLineBox(hostLine); + //reset x pos for new line + cx = firstRunStartX; - //this box has its own container property - //this box may use... - // 1) line formatting context , or - // 2) block formatting context - var myContainingBlock = lay.LatestContainingBlock; - CssBox prevSibling = lay.LatestSiblingBox; - if (box.CssDisplay != Css.CssDisplay.TableCell) - { - //------------------------------------------- - if (box.CssDisplay != Css.CssDisplay.Table) - { - float availableWidth = myContainingBlock.GetClientWidth(); - if (!box.Width.IsEmptyOrAuto) + // 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) { - availableWidth = CssValueParser.ConvertToPx(box.Width, availableWidth, box); + cx += splitableBox.ActualMarginLeft + + splitableBox.ActualBorderLeftWidth + + splitableBox.ActualPaddingLeft; } - box.SetCssBoxWidth(availableWidth); + if (run.IsSolidContent || i == 0) + { + cx += leftMostSpace; + } } - //------------------------------------------- + //--------------------------------------------------- - float localLeft = myContainingBlock.GetClientLeft() + box.ActualMarginLeft; - float localTop = 0; + if (run.IsSpaces && hostLine.RunCount == 0) + { + //not add + continue; + } + //--------------------------------------------------- - if (prevSibling == null) + hostLine.AddRun(run); //*** + if (lim == 0) { - //this is first child of parent - if (box.ParentBox != null) + //single one + if (!hostBoxIsB) { - localTop = myContainingBlock.GetClientTop(); + cx += b.ActualPaddingLeft; } + run.SetLocation(cx, 0); + cx += run.Width + b.ActualPaddingRight; } else { - localTop = prevSibling.LocalVisualBottom; - } - localTop += box.UpdateMarginTopCollapse(prevSibling); - box.SetLocation(localLeft, localTop); - box.SetHeightToZero(); - } - //-------------------------------------------------------------------------- + if (i == 0) + { + //first + if (!hostBoxIsB) + { + cx += b.ActualPaddingLeft; + } - switch (box.CssDisplay) - { - case Css.CssDisplay.Table: - case Css.CssDisplay.InlineTable: + run.SetLocation(cx, 0); + cx = run.Right; + } + else if (i == lim) { - //If we're talking about a table here.. + 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; + } + } + /// + /// do layout line formatting context + /// + /// + /// + 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(); - lay.PushContaingBlock(box); - var currentLevelLatestSibling = lay.LatestSiblingBox; - lay.LatestSiblingBox = null;//reset + //---------------------------------------------------------------------------------------- + float limitLocalRight = hostBlock.VisualWidth - (hostBlock.ActualPaddingRight + hostBlock.ActualBorderRightWidth); + float localX = hostBlock.ActualTextIndent + hostBlock.ActualPaddingLeft + hostBlock.ActualBorderLeftWidth; + float localY = hostBlock.ActualPaddingTop + hostBlock.ActualBorderTopWidth; + //---------------------------------------------------------------------------------------- - CssTableLayoutEngine.PerformLayout(box, myContainingBlock.GetClientWidth(), lay); + if (lay.HasFloatBoxInContext) + { + var recentLeftFloatBox = lay.LatestLeftFloatBox; + var recentRightFloatBox = lay.LatestRightFloatBox; + var latestSibling = lay.LatestSiblingBox; - lay.LatestSiblingBox = currentLevelLatestSibling; - lay.PopContainingBlock(); - //TODO: check if this can have absolute layer? - } break; - default: + if (latestSibling != null) + { + //check latest sibling first + if (hostBlock.Float == CssFloat.None) { - //formatting context for... - //1. line formatting context - //2. block formatting context - if (box.IsCustomCssBox) + if (recentLeftFloatBox != null) { - //has custom layout method - box.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock); - box.CustomRecomputedValue(lay.LatestContainingBlock, lay.GraphicsPlatform); + if (hostBlock.LocalY < recentLeftFloatBox.LocalVisualBottom) + { + localX = recentLeftFloatBox.LocalVisualRight; + } } else { - //new candidate technique - var layoutContext = new LayoutContext(); - layoutContext.BeginHostBox(box, lay); + } + } + } + else + { + if (hostBlock.Float == CssFloat.None) + { + if (recentLeftFloatBox != null) + { + localX = recentLeftFloatBox.LocalVisualRight; + } + if (recentRightFloatBox != null) + { + limitLocalRight = recentRightFloatBox.LocalX; + } + } + //check if need newline or not + } - var children = CssBox.UnsafeGetChildren(box); - var cnode = children.GetFirstLinkedNode(); + } - while (cnode != null) - { - layoutContext.AddCssBox(cnode.Value); - cnode = cnode.Next; - } - //---------------------------------------------- + int interlineSpace = 0; - if (ContainsInlinesOnly(box)) - { - //This will automatically set the bottom of this block - DoLayoutLinesContext(box, lay); - } - else if (box.ChildCount > 0) - { - DoLayoutBlocksContext(box, lay); - } + //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 (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; - //float to specific position - box.SetVisualSize(iw, box.VisualHeight); - } - } break; - } - //--------------------- - } break; + //**** + // 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); } - - - switch (box.Float) + //--------------------- + float maxLineWidth = 0; + if (hostBlock.CssDirection == CssDirection.Rtl) { - case CssFloat.Left: - { - var recentLeftFloatBox = lay.LatestLeftFloatBox; - var recentRightFloatBox = lay.LatestRightFloatBox; - float availableWidth2 = myContainingBlock.GetClientWidth(); - - if (recentRightFloatBox != null) - { - availableWidth2 -= recentRightFloatBox.LocalX; - } - - float sx = myContainingBlock.GetClientLeft(); - float sy = myContainingBlock.GetClientTop(); - - if (recentLeftFloatBox != null) - { - availableWidth2 -= recentLeftFloatBox.LocalVisualRight; - sx = recentLeftFloatBox.LocalVisualRight; - 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.LocalX + recentLeftFloatBox.InnerContentHeight + - recentLeftFloatBox.ActualPaddingBottom + - recentLeftFloatBox.ActualMarginBottom; - } - if (recentRightFloatBox != null) - { - sy2 = recentRightFloatBox.LocalX + recentRightFloatBox.InnerContentHeight + - recentRightFloatBox.ActualPaddingBottom + - recentRightFloatBox.ActualMarginBottom; - } - - sy = (sy1 > sy2) ? sy1 : sy2; - } + 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? - box.SetLocation(sx, sy); - lay.LatestLeftFloatBox = box; - lay.AddFloatBox(box); - } break; - case CssFloat.Right: + if (maxLineWidth < linebox.CachedExactContentWidth) { + maxLineWidth = linebox.CachedExactContentWidth; + } + } + } + else + { - var recentLeftFloatBox = lay.LatestLeftFloatBox; - var recentRightFloatBox = lay.LatestRightFloatBox; - float availableWidth2 = myContainingBlock.GetClientWidth(); - - if (recentLeftFloatBox != null) - { - availableWidth2 -= recentLeftFloatBox.LocalX; - } - - float sx = myContainingBlock.GetClientRight() - box.VisualWidth; - float 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; + CssTextAlign textAlign = hostBlock.CssTextAlign; + foreach (CssLineBox linebox in hostBlock.GetLineBoxIter()) + { + ApplyAlignment(linebox, textAlign, lay); - float sy1 = 0; - float sy2 = 0; - sy1 = sy2 = myContainingBlock.GetClientTop(); + linebox.CloseLine(lay); //*** - if (recentLeftFloatBox != null) - { - sy1 = recentLeftFloatBox.LocalY + recentLeftFloatBox.InnerContentHeight + - recentLeftFloatBox.ActualPaddingBottom + - recentLeftFloatBox.ActualMarginBottom; - } - if (recentRightFloatBox != null) - { - sy2 = recentRightFloatBox.LocalY + recentRightFloatBox.InnerContentHeight + - recentRightFloatBox.ActualPaddingBottom + - recentRightFloatBox.ActualMarginBottom; - } + linebox.CachedLineTop = localY; + localY += linebox.CacheLineHeight + interlineSpace; - sy = (sy1 > sy2) ? sy1 : sy2; - } - box.SetLocation(sx, sy); - lay.LatestRightFloatBox = box; - lay.AddFloatBox(box); - } break; - case CssFloat.None: - default: + if (maxLineWidth < linebox.CachedExactContentWidth) { - //review here for inherit property - - } break; + maxLineWidth = linebox.CachedExactContentWidth; + } + } } - } - + hostBlock.SetVisualHeight(localY + hostBlock.ActualPaddingBottom + hostBlock.ActualBorderBottomWidth); + //final + SetFinalInnerContentSize(hostBlock, maxLineWidth, hostBlock.VisualHeight, lay); + } /// - /// Measure image box size by the width\height set on the box and the actual rendered image size.
- /// If no image exists for the box error icon will be set. + /// Recursively flows the content of the box using the inline model ///
- /// the image word to measure - public static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay) + /// + /// + /// + /// + /// + /// + /// + static void FlowBoxContentIntoHostLineFmtContext( + LayoutVisitor lay, + CssBox hostBox, //target host box that contains line formatting context + CssBox srcBox, //src that has runs /splitable content) to flow into hostBox line model + float limitLocalRight, + float firstRunStartX, + ref CssLineBox hostLine, + ref float cx, + ref FloatFormattingContext floatCtx) { - var width = imgRun.OwnerBox.Width; - var height = imgRun.OwnerBox.Height; - - bool hasImageTagWidth = width.Number > 0 && width.UnitOrNames == CssUnitOrNames.Pixels; - bool hasImageTagHeight = height.Number > 0 && height.UnitOrNames == CssUnitOrNames.Pixels; - bool scaleImageHeight = false; - if (hasImageTagWidth) - { - imgRun.Width = width.Number; - } - else if (width.Number > 0 && width.IsPercentage) + //recursive *** + //-------------------------------------------------------------------- + var oX = cx; + if (srcBox.HasOnlyRuns) { + //condition 3 - imgRun.Width = width.Number * lay.LatestContainingBlock.VisualWidth; - scaleImageHeight = true; - } - else if (imgRun.HasUserImageContent) - { - imgRun.Width = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageWidth : imgRun.ImageRectangle.Width; + FlowRunsIntoHost(lay, hostBox, srcBox, srcBox, 0, + limitLocalRight, firstRunStartX, + 0, 0, + CssBox.UnsafeGetRunList(srcBox), + ref hostLine, ref cx + ); } else { - imgRun.Width = hasImageTagHeight ? height.Number / 1.14f : 20; - } - var maxWidth = imgRun.OwnerBox.MaxWidth;// new CssLength(imageWord.OwnerBox.MaxWidth); - if (maxWidth.Number > 0) - { - float maxWidthVal = -1; - switch (maxWidth.UnitOrNames) + int childNumber = 0; + var ifonts = lay.SampleIFonts; + foreach (CssBox b in srcBox.GetChildBoxIter()) { - case CssUnitOrNames.Percent: - { - maxWidthVal = maxWidth.Number * lay.LatestContainingBlock.VisualWidth; - } break; - case CssUnitOrNames.Pixels: - { - maxWidthVal = maxWidth.Number; - } break; - } + if (b.CssDisplayOutside == CssDisplayOutside.Block) + { + //if display outside is block + //just break + } + //----------------------------------------- +#if DEBUG + if (b.__aa_dbugId == 4) + { - if (maxWidthVal > -1 && imgRun.Width > maxWidthVal) - { - imgRun.Width = maxWidthVal; - scaleImageHeight = !hasImageTagHeight; - } - } + } +#endif - if (hasImageTagHeight) - { - imgRun.Height = height.Number; - } - else if (imgRun.HasUserImageContent) - { - imgRun.Height = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageHeight : imgRun.ImageRectangle.Height; - } - else - { - imgRun.Height = imgRun.Width > 0 ? imgRun.Width * 1.14f : 22.8f; - } + float leftMostSpace = 0, rightMostSpace = 0; + //if b has absolute pos then it is removed from the flow + if (b.NeedComputedValueEvaluation) + { + b.ReEvaluateComputedValues(ifonts, hostBox); + } + b.MeasureRunsSize(lay); +#if DEBUG + if (b.Position == CssPosition.Absolute) + { + //should not found here! + throw new NotSupportedException(); + } +#endif - if (imgRun.HasUserImageContent) - { - // If only the width was set in the html tag, ratio the height. - if ((hasImageTagWidth && !hasImageTagHeight) || scaleImageHeight) - { - // Divide the given tag width with the actual image width, to get the ratio. - float ratio = imgRun.Width / imgRun.OriginalImageWidth; - imgRun.Height = imgRun.OriginalImageHeight * ratio; - } - // If only the height was set in the html tag, ratio the width. - else if (hasImageTagHeight && !hasImageTagWidth) - { - // Divide the given tag height with the actual image height, to get the ratio. - float ratio = imgRun.Height / imgRun.OriginalImageHeight; - imgRun.Width = imgRun.OriginalImageWidth * ratio; - } - } - //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom; - } + cx += leftMostSpace; + if (b.CssDisplay == CssDisplay.InlineBlock) + { + //-------- + // if inside display is block context *** + //--------- - /// - /// Check if the given box contains only inline child boxes. - /// - /// the box to check - /// true - only inline child boxes, false - otherwise - static bool ContainsInlinesOnly(CssBox box) - { - var children = CssBox.UnsafeGetChildren(box); - var linkedNode = children.GetFirstLinkedNode(); - while (linkedNode != null) - { - if (!linkedNode.Value.OutsideDisplayIsInline) - { - return false; - } - - linkedNode = linkedNode.Next; - } - return true; - } - - /// - /// do layout line formatting context - /// - /// - /// - 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(); + //outside -> inline + //inside -> block - //---------------------------------------------------------------------------------------- - float limitLocalRight = hostBlock.VisualWidth - (hostBlock.ActualPaddingRight + hostBlock.ActualBorderRightWidth); - float localX = hostBlock.ActualTextIndent + hostBlock.ActualPaddingLeft + hostBlock.ActualBorderLeftWidth; - float localY = hostBlock.ActualPaddingTop + hostBlock.ActualBorderTopWidth; - //---------------------------------------------------------------------------------------- + //can't split + //create 'block-run' + CssLayoutEngine.PerformContentLayout(b, lay); + CssBlockRun blockRun = b.JustBlockRun; + if (blockRun == null) + { + blockRun = new CssBlockRun(b); + blockRun.SetOwner(srcBox); + b.JustBlockRun = blockRun; + } - 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 (b.Width.IsEmptyOrAuto) { - if (hostBlock.LocalY < recentLeftFloatBox.LocalVisualBottom) - { - localX = recentLeftFloatBox.LocalVisualRight; - } + blockRun.SetSize(CssBox.GetLatestCachedMinWidth(b), b.VisualHeight); } else { - + blockRun.SetSize(b.VisualWidth, b.VisualHeight); } + + b.SetLocation(b.LocalX, 0); //because of inline*** + + FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber, + limitLocalRight, firstRunStartX, + leftMostSpace, rightMostSpace, + new List() { b.JustBlockRun }, + ref hostLine, ref cx); } - } - else - { - if (hostBlock.Float == CssFloat.None) + + else if (b.HasOnlyRuns) { - if (recentLeftFloatBox != null) - { - localX = recentLeftFloatBox.LocalVisualRight; - } - if (recentRightFloatBox != null) + switch (b.Float) { - limitLocalRight = recentRightFloatBox.LocalX; - } - } - //check if need newline or not - } - - } - - int interlineSpace = 0; + default: + case CssFloat.None: + { + FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber, + limitLocalRight, firstRunStartX, + leftMostSpace, rightMostSpace, + CssBox.UnsafeGetRunList(b), + ref hostLine, ref cx); - //First line box + } break; + case CssFloat.Left: + { + //float is out of flow item + //1. current line is shortening + //2. add 'b' to special container *** - var line = new CssLineBox(hostBlock); - hostBlock.AddLineBox(line); - //**** - var floatCtx = new FloatFormattingContext(); + var newAnonBlock = new CssFloatContainerBox( + CssBox.UnsafeGetBoxSpec(b), + b.RootGfx, CssDisplay.Block); + newAnonBlock.ReEvaluateComputedValues(ifonts, hostBox); - FlowBoxContentIntoHostLineFmtContext(lay, hostBlock, hostBlock, - limitLocalRight, localX, - ref line, ref localX, ref floatCtx); + //add to abs layer + hostBox.AppendToAbsoluteLayer(newAnonBlock); + newAnonBlock.ResetLineBoxes(); - //**** - // 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? + float localX1 = 0; + var line = new CssLineBox(newAnonBlock); + newAnonBlock.AddLineBox(line); - if (maxLineWidth < linebox.CachedExactContentWidth) - { - maxLineWidth = linebox.CachedExactContentWidth; - } - } - } - else - { + var newFloatCtx = new FloatFormattingContext(); + FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b, + limitLocalRight, 0, + ref line, ref localX1, ref newFloatCtx); - CssTextAlign textAlign = hostBlock.CssTextAlign; - foreach (CssLineBox linebox in hostBlock.GetLineBoxIter()) - { - ApplyAlignment(linebox, textAlign, lay); - linebox.CloseLine(lay); //*** + float localY = 0; + int interlineSpace = 0; + float maxLineWidth = 0; + CssTextAlign textAlign = newAnonBlock.CssTextAlign; + foreach (CssLineBox linebox in newAnonBlock.GetLineBoxIter()) + { + ApplyAlignment(linebox, textAlign, lay); + linebox.CloseLine(lay); //*** + linebox.CachedLineTop = localY; + localY += linebox.CacheLineHeight + interlineSpace; + if (maxLineWidth < linebox.CachedExactContentWidth) + { + maxLineWidth = linebox.CachedExactContentWidth; + } + } - linebox.CachedLineTop = localY; - localY += linebox.CacheLineHeight + interlineSpace; + float hostSizeW = hostBox.VisualWidth; + SetFinalInnerContentSize(newAnonBlock, maxLineWidth, localY, lay); + //need to adjust line box - if (maxLineWidth < linebox.CachedExactContentWidth) - { - maxLineWidth = linebox.CachedExactContentWidth; - } - } - } + //TODO: review here!, + if (hostLine.CanDoMoreLeftOffset(newAnonBlock.InnerContentWidth, limitLocalRight)) + { + hostLine.DoLeftOffset(newAnonBlock.InnerContentWidth); + cx = hostLine.GetRightOfLastRun(); + newAnonBlock.SetLocation(floatCtx.lineLeftOffset, floatCtx.offsetFloatTop); //TODO: review top location again + floatCtx.lineLeftOffset = newAnonBlock.LocalX + newAnonBlock.InnerContentWidth; + } + else + { + //newline + newAnonBlock.SetLocation(hostBox.GetClientLeft(), hostLine.CalculateLineHeight()); + floatCtx.offsetFloatTop = newAnonBlock.LocalY; + } - hostBlock.SetVisualHeight(localY + hostBlock.ActualPaddingBottom + hostBlock.ActualBorderBottomWidth); + } break; + case CssFloat.Right: + { + //float is out of flow item + //1. create new block box and then + //flow content in to this new box + var newAnonBlock = new CssFloatContainerBox( + CssBox.UnsafeGetBoxSpec(b), + b.RootGfx, CssDisplay.Block); - //final - SetFinalInnerContentSize(hostBlock, maxLineWidth, hostBlock.VisualHeight, lay); - } - static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay) - { + newAnonBlock.ReEvaluateComputedValues(ifonts, hostBox); - //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; + //add to abs layer + hostBox.AppendToAbsoluteLayer(newAnonBlock); + newAnonBlock.ResetLineBoxes(); + float localX1 = 0; - //---------------------------- - 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 + var line = new CssLineBox(newAnonBlock); + newAnonBlock.AddLineBox(line); - CssBox anoForInline = CreateAnonBlock(box, childBox); - anoForInline.ReEvaluateComputedValues(lay.SampleIFonts, box); + var newFloatCtx = new FloatFormattingContext(); + FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b, + limitLocalRight, 0, + ref line, ref localX1, ref newFloatCtx); - var tmp = cnode.Next; - do - { - children.Remove(childBox); - anoForInline.AppendChild(childBox); + float localY = 0; + int interlineSpace = 0; + float maxLineWidth = 0; + CssTextAlign textAlign = newAnonBlock.CssTextAlign; + foreach (CssLineBox linebox in newAnonBlock.GetLineBoxIter()) + { + ApplyAlignment(linebox, textAlign, lay); + linebox.CloseLine(lay); //*** + linebox.CachedLineTop = localY; + localY += linebox.CacheLineHeight + interlineSpace; + if (maxLineWidth < linebox.CachedExactContentWidth) + { + maxLineWidth = linebox.CachedExactContentWidth; + } + } + SetFinalInnerContentSize(newAnonBlock, maxLineWidth, localY, lay); - 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); + //todo: review here + float hostSizeW = hostBox.VisualWidth; + var rightOfLastRun = hostLine.GetRightOfLastRun(); - childBox = anoForInline; - //------------------------ - //2. move this inline box - //to new anonbox - cnode = tmp; - //------------------------ - childBox.PerformLayout(lay); + if (!floatCtx.floatingOutOfLine) + { + if (rightOfLastRun + maxLineWidth < hostSizeW - floatCtx.lineRightOffset) + { + float newX = hostSizeW - (maxLineWidth + floatCtx.lineRightOffset); + newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop); + floatCtx.lineRightOffset = newX; + floatCtx.rightFloatBox = newAnonBlock; + floatCtx.floatingOutOfLine = true; + } + else + { + //start newline + float newX = hostSizeW - maxLineWidth; + newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop + hostLine.CalculateLineHeight()); + floatCtx.lineRightOffset = newX; + floatCtx.rightFloatBox = newAnonBlock; + floatCtx.floatingOutOfLine = true; + floatCtx.offsetFloatTop = newAnonBlock.LocalY; + } + } + else + { + //out-of-line mode + if (floatCtx.rightFloatBox != null) + { + float newX = floatCtx.rightFloatBox.LocalX - maxLineWidth; + if (newX > 0) + { + newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop); + floatCtx.lineRightOffset = newX; + floatCtx.rightFloatBox = newAnonBlock; + floatCtx.offsetFloatTop = newAnonBlock.LocalY; + } + else + { //start new line + newX = hostSizeW - maxLineWidth; + newAnonBlock.SetLocation(newX, floatCtx.rightFloatBox.LocalY + floatCtx.rightFloatBox.InnerContentHeight); + floatCtx.lineRightOffset = newX; + floatCtx.rightFloatBox = newAnonBlock; + floatCtx.offsetFloatTop = newAnonBlock.LocalY + newAnonBlock.InnerContentHeight; + } + } + else + { + throw new NotSupportedException(); + } + } - if (childBox.CanBeReferenceSibling) - { - lay.LatestSiblingBox = childBox; + } break; + } } - } - else - { - - childBox.PerformLayout(lay); - - switch (childBox.Float) + else { - 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; - } + //go deeper + //recursive *** + //not new lineFormatting context + FlowBoxContentIntoHostLineFmtContext(lay, hostBox, b, + limitLocalRight, firstRunStartX, + ref hostLine, ref cx, ref floatCtx); - if (childBox.Float == CssFloat.None && childBox.CanBeReferenceSibling) - { - lay.LatestSiblingBox = childBox; } - cnode = cnode.Next; - + cx += rightMostSpace; + childNumber++; } } - - //------------------------------------------ - lay.LatestSiblingBox = currentLevelLatestSibling; - lay.PopContainingBlock(); - //------------------------------------------------ - float boxWidth = CalculateActualWidth(box); - - if (lay.ContainerBlockGlobalX + boxWidth > CssBoxConstConfig.BOX_MAX_RIGHT) - { - } - else + if (srcBox.Position == CssPosition.Relative) { - if (box.CssDisplay != Css.CssDisplay.TableCell) - { - box.SetVisualWidth(boxWidth); - } + //offset content relative to it 'flow' position' + var left = CssValueParser.ConvertToPx(srcBox.Left, hostBox.VisualWidth, srcBox); + var top = CssValueParser.ConvertToPx(srcBox.Top, hostBox.VisualWidth, srcBox); + srcBox.SetLocation(srcBox.LocalX + left, srcBox.LocalY + top); } - float boxHeight = box.GetHeightAfterMarginBottomCollapse(lay.LatestContainingBlock); - box.SetVisualHeight(boxHeight); - //-------------------------------------------------------------------------------- - //final - SetFinalInnerContentSize(box, boxWidth, boxHeight, lay); - } + + static void SetFinalInnerContentSize(CssBox box, float innerContentW, float innerContentH, LayoutVisitor lay) { box.InnerContentWidth = innerContentW; @@ -747,344 +658,619 @@ static void SetFinalInnerContentSize(CssBox box, float innerContentW, float inne } break; } } - static float CalculateActualWidth(CssBox box) + + /// + /// Applies vertical and horizontal alignment to words in lineboxes + /// + /// + /// + static void ApplyAlignment(CssLineBox lineBox, CssTextAlign textAlign, LayoutVisitor lay) { - float maxRight = 0; - var boxes = CssBox.UnsafeGetChildren(box); - var cnode = boxes.GetFirstLinkedNode(); - while (cnode != null) + switch (textAlign) { - var cssbox = cnode.Value; - float nodeRight = cssbox.LocalX + cssbox.InnerContentWidth + - cssbox.ActualPaddingLeft + cssbox.ActualPaddingRight + - cssbox.ActualMarginLeft + - cssbox.ActualMarginRight; - - maxRight = nodeRight > maxRight ? nodeRight : maxRight; - cnode = cnode.Next; + case CssTextAlign.Right: + ApplyRightAlignment(lineBox); + break; + case CssTextAlign.Center: + ApplyCenterAlignment(lineBox); + break; + case CssTextAlign.Justify: + ApplyJustifyAlignment(lineBox); + break; + default: + break; } - return maxRight + (box.ActualBorderLeftWidth + box.ActualPaddingLeft + - box.ActualPaddingRight + box.ActualBorderRightWidth); - } - - static CssBox CreateAnonBlock(CssBox parent, CssBox insertBefore) - { - //auto gen by layout engine *** - var newBox = new CssBox(CssBox.UnsafeGetBoxSpec(parent).GetAnonVersion(), parent.RootGfx); - CssBox.ChangeDisplayType(newBox, Css.CssDisplay.Block); - parent.InsertChild(insertBefore, newBox); - return newBox; + //--------------------------------------------- + // Applies vertical alignment to the linebox + return; + //TODO: review here + lineBox.ApplyBaseline(lineBox.CalculateTotalBoxBaseLine(lay)); + //--------------------------------------------- } /// - /// Recursively flows the content of the box using the inline model + /// Applies right to left direction to words /// - /// - /// - /// - /// - /// - /// - /// - static void FlowBoxContentIntoHostLineFmtContext( - LayoutVisitor lay, - CssBox hostBox, //target host box that contains line formatting context - CssBox srcBox, //src that has runs /splitable content) to flow into hostBox line model - float limitLocalRight, - float firstRunStartX, - ref CssLineBox hostLine, - ref float cx, - ref FloatFormattingContext floatCtx) + /// + /// + static void ApplyRightToLeft(CssLineBox lineBox) { - - //recursive *** - //-------------------------------------------------------------------- - var oX = cx; - if (srcBox.HasOnlyRuns) + if (lineBox.RunCount > 0) { - //condition 3 - FlowRunsIntoHost(lay, hostBox, srcBox, srcBox, 0, - limitLocalRight, firstRunStartX, - 0, 0, - CssBox.UnsafeGetRunList(srcBox), - ref hostLine, ref cx - ); + float left = lineBox.GetFirstRun().Left; + float right = lineBox.GetLastRun().Right; + foreach (CssRun run in lineBox.GetRunIter()) + { + float diff = run.Left - left; + float w_right = right - diff; + run.Left = w_right - run.Width; + } } - else + } + static void ApplyJustifyAlignment(CssLineBox lineBox) + { + + + if (lineBox.IsLastLine) return; + + float indent = lineBox.IsFirstLine ? lineBox.OwnerBox.ActualTextIndent : 0f; + + float runWidthSum = 0f; + int runCount = 0; + + float availableWidth = lineBox.OwnerBox.GetClientWidth() - indent; + + // Gather text sum + foreach (CssRun w in lineBox.GetRunIter()) { + runWidthSum += w.Width; + runCount++; + } - int childNumber = 0; - var ifonts = lay.SampleIFonts; - foreach (CssBox b in srcBox.GetChildBoxIter()) + if (runCount == 0) return; //Avoid Zero division + + float spaceOfEachRun = (availableWidth - runWidthSum) / runCount; //Spacing that will be used + + float cX = lineBox.OwnerBox.GetClientLeft() + indent; + CssRun lastRun = lineBox.GetLastRun(); + foreach (CssRun run in lineBox.GetRunIter()) + { + run.Left = cX; + cX = run.Right + spaceOfEachRun; + if (run == lastRun) { - if (b.CssDisplayOutside == CssDisplayOutside.Block) - { - //if display outside is block - //just break + run.Left = lineBox.OwnerBox.GetClientRight() - run.Width; + } + } + } - } - //----------------------------------------- -#if DEBUG - if (b.__aa_dbugId == 4) - { + /// + /// Applies centered alignment to the text on the linebox + /// + /// + /// + static void ApplyCenterAlignment(CssLineBox line) + { - } -#endif + if (line.RunCount == 0) return; + CssRun lastRun = line.GetLastRun(); + float diff = (line.OwnerBox.GetClientWidth() - lastRun.Right) / 2; + if (diff > CSS_OFFSET_THRESHOLD) + { + foreach (CssRun word in line.GetRunIter()) + { + word.Left += diff; + } + line.CachedLineContentWidth += diff; + } + } - float leftMostSpace = 0, rightMostSpace = 0; - //if b has absolute pos then it is removed from the flow - if (b.NeedComputedValueEvaluation) + /// + /// Applies right alignment to the text on the linebox + /// + /// + /// + static void ApplyRightAlignment(CssLineBox line) + { + if (line.RunCount == 0) + { + return; + } + CssRun lastRun = line.GetLastRun(); + float diff = line.OwnerBox.GetClientWidth() - line.GetLastRun().Right; + if (diff > CSS_OFFSET_THRESHOLD) + { + foreach (CssRun word in line.GetRunIter()) + { + word.Left += diff; + } + } + } + + } + + + + /// + /// Helps on CSS Layout. + /// + static class CssLayoutEngine + { + + + 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 + + var myContainingBlock = lay.LatestContainingBlock; + CssBox prevSibling = lay.LatestSiblingBox; + if (box.CssDisplay != Css.CssDisplay.TableCell) + { + //------------------------------------------- + if (box.CssDisplay != Css.CssDisplay.Table) + { + float availableWidth = myContainingBlock.GetClientWidth(); + if (!box.Width.IsEmptyOrAuto) { - b.ReEvaluateComputedValues(ifonts, hostBox); + availableWidth = CssValueParser.ConvertToPx(box.Width, availableWidth, box); } - b.MeasureRunsSize(lay); -#if DEBUG - if (b.Position == CssPosition.Absolute) + + box.SetCssBoxWidth(availableWidth); + } + //------------------------------------------- + + float localLeft = myContainingBlock.GetClientLeft() + box.ActualMarginLeft; + float localTop = 0; + + if (prevSibling == null) + { + //this is first child of parent + if (box.ParentBox != null) { - //should not found here! - throw new NotSupportedException(); + localTop = myContainingBlock.GetClientTop(); } -#endif + } + else + { + localTop = prevSibling.LocalVisualBottom; + } + localTop += box.UpdateMarginTopCollapse(prevSibling); + box.SetLocation(localLeft, localTop); + box.SetHeightToZero(); + } + //-------------------------------------------------------------------------- - cx += leftMostSpace; - if (b.CssDisplay == CssDisplay.InlineBlock) + switch (box.CssDisplay) + { + case Css.CssDisplay.Table: + case Css.CssDisplay.InlineTable: { - //-------- - // if inside display is block context *** - //--------- - - //outside -> inline - //inside -> block + //If we're talking about a table here.. - //can't split - //create 'block-run' - PerformContentLayout(b, lay); - CssBlockRun blockRun = b.JustBlockRun; - if (blockRun == null) - { - blockRun = new CssBlockRun(b); - blockRun.SetOwner(srcBox); - b.JustBlockRun = blockRun; - } + lay.PushContaingBlock(box); + var currentLevelLatestSibling = lay.LatestSiblingBox; + lay.LatestSiblingBox = null;//reset + CssTableLayoutEngine.PerformLayout(box, myContainingBlock.GetClientWidth(), lay); - if (b.Width.IsEmptyOrAuto) + 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) { - blockRun.SetSize(CssBox.GetLatestCachedMinWidth(b), b.VisualHeight); + //has custom layout method + box.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock); + box.CustomRecomputedValue(lay.LatestContainingBlock, lay.GraphicsPlatform); } else { - blockRun.SetSize(b.VisualWidth, b.VisualHeight); - } - - b.SetLocation(b.LocalX, 0); //because of inline*** - FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber, - limitLocalRight, firstRunStartX, - leftMostSpace, rightMostSpace, - new List() { b.JustBlockRun }, - ref hostLine, ref cx); - } + if (ContainsInlinesOnly(box)) + { + ////This will automatically set the bottom of this block + LinesFormattingContext.DoLayoutLinesContext(box, lay); + } + else if (box.ChildCount > 0) + { + DoLayoutBlocksContext(box, lay); + } - else if (b.HasOnlyRuns) - { - switch (b.Float) + if (box.HasAbsoluteLayer) + { + LayoutContentInAbsoluteLayer(lay, box); + } + } + //--------------------- + //again! + switch (box.CssDisplay) { - default: - case CssFloat.None: + case CssDisplay.Flex: + case CssDisplay.InlineFlex: { - FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber, - limitLocalRight, firstRunStartX, - leftMostSpace, rightMostSpace, - CssBox.UnsafeGetRunList(b), - ref hostLine, ref cx); - + //------------------------------------------------ + RearrangeWithFlexContext(box, lay); + //------------------------------------------------ } break; - case CssFloat.Left: - { - //float is out of flow item - //1. current line is shortening - //2. add 'b' to special container *** + default: + { //TODO: review here again + if (box.Float != CssFloat.None) + { + var iw = box.InnerContentWidth; + var ew = box.VisualWidth; + //float to specific position + box.SetVisualSize(iw, box.VisualHeight); + } + } break; + } + //--------------------- + } break; + } - var newAnonBlock = new CssFloatContainerBox( - CssBox.UnsafeGetBoxSpec(b), - b.RootGfx, CssDisplay.Block); - newAnonBlock.ReEvaluateComputedValues(ifonts, hostBox); - //add to abs layer - hostBox.AppendToAbsoluteLayer(newAnonBlock); - newAnonBlock.ResetLineBoxes(); + switch (box.Float) + { + case CssFloat.Left: + { + var recentLeftFloatBox = lay.LatestLeftFloatBox; + var recentRightFloatBox = lay.LatestRightFloatBox; + float availableWidth2 = myContainingBlock.GetClientWidth(); - float localX1 = 0; - var line = new CssLineBox(newAnonBlock); - newAnonBlock.AddLineBox(line); + if (recentRightFloatBox != null) + { + availableWidth2 -= recentRightFloatBox.LocalX; + } - var newFloatCtx = new FloatFormattingContext(); - FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b, - limitLocalRight, 0, - ref line, ref localX1, ref newFloatCtx); + float sx = myContainingBlock.GetClientLeft(); + float sy = myContainingBlock.GetClientTop(); + if (recentLeftFloatBox != null) + { + availableWidth2 -= recentLeftFloatBox.LocalVisualRight; + sx = recentLeftFloatBox.LocalVisualRight; + sy = recentLeftFloatBox.LocalY; + } - float localY = 0; - int interlineSpace = 0; - float maxLineWidth = 0; - CssTextAlign textAlign = newAnonBlock.CssTextAlign; - foreach (CssLineBox linebox in newAnonBlock.GetLineBoxIter()) - { - ApplyAlignment(linebox, textAlign, lay); - linebox.CloseLine(lay); //*** - linebox.CachedLineTop = localY; - localY += linebox.CacheLineHeight + interlineSpace; - if (maxLineWidth < linebox.CachedExactContentWidth) - { - maxLineWidth = linebox.CachedExactContentWidth; - } - } + if (box.VisualWidth > availableWidth2) + { + //start newline + sx = myContainingBlock.GetClientLeft(); - float hostSizeW = hostBox.VisualWidth; - SetFinalInnerContentSize(newAnonBlock, maxLineWidth, localY, lay); - //need to adjust line box + float sy1 = 0; + float sy2 = 0; + sy1 = sy2 = myContainingBlock.GetClientTop(); - //TODO: review here!, - if (hostLine.CanDoMoreLeftOffset(newAnonBlock.InnerContentWidth, limitLocalRight)) - { - hostLine.DoLeftOffset(newAnonBlock.InnerContentWidth); - cx = hostLine.GetRightOfLastRun(); - newAnonBlock.SetLocation(floatCtx.lineLeftOffset, floatCtx.offsetFloatTop); //TODO: review top location again - floatCtx.lineLeftOffset = newAnonBlock.LocalX + newAnonBlock.InnerContentWidth; - } - else - { - //newline - newAnonBlock.SetLocation(hostBox.GetClientLeft(), hostLine.CalculateLineHeight()); - floatCtx.offsetFloatTop = newAnonBlock.LocalY; - } + if (recentLeftFloatBox != null) + { + sy1 = recentLeftFloatBox.LocalX + recentLeftFloatBox.InnerContentHeight + + recentLeftFloatBox.ActualPaddingBottom + + recentLeftFloatBox.ActualMarginBottom; + } + if (recentRightFloatBox != null) + { + sy2 = recentRightFloatBox.LocalX + recentRightFloatBox.InnerContentHeight + + recentRightFloatBox.ActualPaddingBottom + + recentRightFloatBox.ActualMarginBottom; + } - } break; - case CssFloat.Right: - { - //float is out of flow item - //1. create new block box and then - //flow content in to this new box - var newAnonBlock = new CssFloatContainerBox( - CssBox.UnsafeGetBoxSpec(b), - b.RootGfx, CssDisplay.Block); + sy = (sy1 > sy2) ? sy1 : sy2; + } - newAnonBlock.ReEvaluateComputedValues(ifonts, hostBox); + box.SetLocation(sx, sy); + lay.LatestLeftFloatBox = box; + lay.AddFloatBox(box); + } break; + case CssFloat.Right: + { - //add to abs layer - hostBox.AppendToAbsoluteLayer(newAnonBlock); - newAnonBlock.ResetLineBoxes(); - float localX1 = 0; + var recentLeftFloatBox = lay.LatestLeftFloatBox; + var recentRightFloatBox = lay.LatestRightFloatBox; + float availableWidth2 = myContainingBlock.GetClientWidth(); - var line = new CssLineBox(newAnonBlock); - newAnonBlock.AddLineBox(line); + if (recentLeftFloatBox != null) + { + availableWidth2 -= recentLeftFloatBox.LocalX; + } - var newFloatCtx = new FloatFormattingContext(); - FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b, - limitLocalRight, 0, - ref line, ref localX1, ref newFloatCtx); + float sx = myContainingBlock.GetClientRight() - box.VisualWidth; + float sy = myContainingBlock.GetClientTop(); - float localY = 0; - int interlineSpace = 0; - float maxLineWidth = 0; - CssTextAlign textAlign = newAnonBlock.CssTextAlign; - foreach (CssLineBox linebox in newAnonBlock.GetLineBoxIter()) - { - ApplyAlignment(linebox, textAlign, lay); - linebox.CloseLine(lay); //*** - linebox.CachedLineTop = localY; - localY += linebox.CacheLineHeight + interlineSpace; - if (maxLineWidth < linebox.CachedExactContentWidth) - { - maxLineWidth = linebox.CachedExactContentWidth; - } - } - SetFinalInnerContentSize(newAnonBlock, maxLineWidth, localY, lay); + if (recentRightFloatBox != null) + { + availableWidth2 -= recentRightFloatBox.LocalX; + sx = recentRightFloatBox.LocalX - box.VisualWidth; + sy = recentRightFloatBox.LocalY; + } - //todo: review here - float hostSizeW = hostBox.VisualWidth; - var rightOfLastRun = hostLine.GetRightOfLastRun(); + if (box.VisualWidth > availableWidth2) + { + //start newline + sx = myContainingBlock.GetClientRight() - box.VisualWidth; - if (!floatCtx.floatingOutOfLine) - { - if (rightOfLastRun + maxLineWidth < hostSizeW - floatCtx.lineRightOffset) - { - float newX = hostSizeW - (maxLineWidth + floatCtx.lineRightOffset); - newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop); - floatCtx.lineRightOffset = newX; - floatCtx.rightFloatBox = newAnonBlock; - floatCtx.floatingOutOfLine = true; - } - else - { - //start newline - float newX = hostSizeW - maxLineWidth; - newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop + hostLine.CalculateLineHeight()); - floatCtx.lineRightOffset = newX; - floatCtx.rightFloatBox = newAnonBlock; - floatCtx.floatingOutOfLine = true; - floatCtx.offsetFloatTop = newAnonBlock.LocalY; - } - } - else - { - //out-of-line mode - if (floatCtx.rightFloatBox != null) - { - float newX = floatCtx.rightFloatBox.LocalX - maxLineWidth; - if (newX > 0) - { - newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop); - floatCtx.lineRightOffset = newX; - floatCtx.rightFloatBox = newAnonBlock; - floatCtx.offsetFloatTop = newAnonBlock.LocalY; - } - else - { //start new line - newX = hostSizeW - maxLineWidth; - newAnonBlock.SetLocation(newX, floatCtx.rightFloatBox.LocalY + floatCtx.rightFloatBox.InnerContentHeight); - floatCtx.lineRightOffset = newX; - floatCtx.rightFloatBox = newAnonBlock; - floatCtx.offsetFloatTop = newAnonBlock.LocalY + newAnonBlock.InnerContentHeight; - } - } - else - { - throw new NotSupportedException(); - } - } + float sy1 = 0; + float sy2 = 0; + sy1 = sy2 = myContainingBlock.GetClientTop(); - } break; + if (recentLeftFloatBox != null) + { + sy1 = recentLeftFloatBox.LocalY + recentLeftFloatBox.InnerContentHeight + + recentLeftFloatBox.ActualPaddingBottom + + recentLeftFloatBox.ActualMarginBottom; + } + if (recentRightFloatBox != null) + { + sy2 = recentRightFloatBox.LocalY + recentRightFloatBox.InnerContentHeight + + recentRightFloatBox.ActualPaddingBottom + + recentRightFloatBox.ActualMarginBottom; + } + + sy = (sy1 > sy2) ? sy1 : sy2; } + box.SetLocation(sx, sy); + lay.LatestRightFloatBox = box; + lay.AddFloatBox(box); + } break; + case CssFloat.None: + default: + { + //review here for inherit property + + } break; + } + + } + + + + /// + /// Check if the given box contains only inline child boxes. + /// + /// the box to check + /// true - only inline child boxes, false - otherwise + static bool ContainsInlinesOnly(CssBox box) + { + var children = CssBox.UnsafeGetChildren(box); + var linkedNode = children.GetFirstLinkedNode(); + while (linkedNode != null) + { + if (!linkedNode.Value.OutsideDisplayIsInline) + { + return false; + } + + linkedNode = linkedNode.Next; + } + return true; + } + + 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 + } + else + { + + 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; - //go deeper - //recursive *** - //not new lineFormatting context - FlowBoxContentIntoHostLineFmtContext(lay, hostBox, b, - limitLocalRight, firstRunStartX, - ref hostLine, ref cx, ref floatCtx); + } break; + } + if (childBox.Float == CssFloat.None && childBox.CanBeReferenceSibling) + { + lay.LatestSiblingBox = childBox; } - cx += rightMostSpace; - childNumber++; + cnode = cnode.Next; + } } - if (srcBox.Position == CssPosition.Relative) + + //------------------------------------------ + lay.LatestSiblingBox = currentLevelLatestSibling; + lay.PopContainingBlock(); + //------------------------------------------------ + float boxWidth = CalculateActualWidth(box); + + if (lay.ContainerBlockGlobalX + boxWidth > CssBoxConstConfig.BOX_MAX_RIGHT) { - //offset content relative to it 'flow' position' - var left = CssValueParser.ConvertToPx(srcBox.Left, hostBox.VisualWidth, srcBox); - var top = CssValueParser.ConvertToPx(srcBox.Top, hostBox.VisualWidth, srcBox); - srcBox.SetLocation(srcBox.LocalX + left, srcBox.LocalY + top); } + else + { + if (box.CssDisplay != Css.CssDisplay.TableCell) + { + box.SetVisualWidth(boxWidth); + } + } + + float boxHeight = box.GetHeightAfterMarginBottomCollapse(lay.LatestContainingBlock); + box.SetVisualHeight(boxHeight); + //-------------------------------------------------------------------------------- + //final + SetFinalInnerContentSize(box, boxWidth, boxHeight, lay); + + } + + 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; + } + } + static float CalculateActualWidth(CssBox box) + { + float maxRight = 0; + var boxes = CssBox.UnsafeGetChildren(box); + var cnode = boxes.GetFirstLinkedNode(); + while (cnode != null) + { + var cssbox = cnode.Value; + float nodeRight = cssbox.LocalX + cssbox.InnerContentWidth + + cssbox.ActualPaddingLeft + cssbox.ActualPaddingRight + + cssbox.ActualMarginLeft + + cssbox.ActualMarginRight; + + maxRight = nodeRight > maxRight ? nodeRight : maxRight; + cnode = cnode.Next; + } + return maxRight + (box.ActualBorderLeftWidth + box.ActualPaddingLeft + + box.ActualPaddingRight + box.ActualBorderRightWidth); + } + static CssBox CreateAnonBlock(CssBox parent, CssBox insertBefore) + { + //auto gen by layout engine *** + var newBox = new CssBox(CssBox.UnsafeGetBoxSpec(parent).GetAnonVersion(), parent.RootGfx); + CssBox.ChangeDisplayType(newBox, Css.CssDisplay.Block); + parent.InsertChild(insertBefore, newBox); + return newBox; } + + static void LayoutContentInAbsoluteLayer(LayoutVisitor lay, CssBox srcBox) { @@ -1138,255 +1324,8 @@ static void LayoutContentInAbsoluteLayer(LayoutVisitor lay, CssBox srcBox) srcBox.InnerContentHeight = i_maxBottom; } - 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 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) - { - 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; - } - } - /// - /// Applies vertical and horizontal alignment to words in lineboxes - /// - /// - /// - static void ApplyAlignment(CssLineBox lineBox, CssTextAlign textAlign, LayoutVisitor lay) - { - switch (textAlign) - { - case CssTextAlign.Right: - ApplyRightAlignment(lineBox); - break; - case CssTextAlign.Center: - ApplyCenterAlignment(lineBox); - break; - case CssTextAlign.Justify: - ApplyJustifyAlignment(lineBox); - break; - default: - break; - } - //--------------------------------------------- - // Applies vertical alignment to the linebox - return; - //TODO: review here - lineBox.ApplyBaseline(lineBox.CalculateTotalBoxBaseLine(lay)); - //--------------------------------------------- - } - - /// - /// Applies right to left direction to words - /// - /// - /// - static void ApplyRightToLeft(CssLineBox lineBox) - { - if (lineBox.RunCount > 0) - { - - float left = lineBox.GetFirstRun().Left; - float right = lineBox.GetLastRun().Right; - foreach (CssRun run in lineBox.GetRunIter()) - { - float diff = run.Left - left; - float w_right = right - diff; - run.Left = w_right - run.Width; - } - } - } - static void ApplyJustifyAlignment(CssLineBox lineBox) - { - - - if (lineBox.IsLastLine) return; - - float indent = lineBox.IsFirstLine ? lineBox.OwnerBox.ActualTextIndent : 0f; - - float runWidthSum = 0f; - int runCount = 0; - - float availableWidth = lineBox.OwnerBox.GetClientWidth() - indent; - - // Gather text sum - foreach (CssRun w in lineBox.GetRunIter()) - { - runWidthSum += w.Width; - runCount++; - } - - if (runCount == 0) return; //Avoid Zero division - - float spaceOfEachRun = (availableWidth - runWidthSum) / runCount; //Spacing that will be used - - float cX = lineBox.OwnerBox.GetClientLeft() + indent; - CssRun lastRun = lineBox.GetLastRun(); - foreach (CssRun run in lineBox.GetRunIter()) - { - run.Left = cX; - cX = run.Right + spaceOfEachRun; - if (run == lastRun) - { - run.Left = lineBox.OwnerBox.GetClientRight() - run.Width; - } - } - } - - /// - /// Applies centered alignment to the text on the linebox - /// - /// - /// - static void ApplyCenterAlignment(CssLineBox line) - { - if (line.RunCount == 0) return; - CssRun lastRun = line.GetLastRun(); - float diff = (line.OwnerBox.GetClientWidth() - lastRun.Right) / 2; - if (diff > CSS_OFFSET_THRESHOLD) - { - foreach (CssRun word in line.GetRunIter()) - { - word.Left += diff; - } - line.CachedLineContentWidth += diff; - } - } - /// - /// Applies right alignment to the text on the linebox - /// - /// - /// - static void ApplyRightAlignment(CssLineBox line) - { - if (line.RunCount == 0) - { - return; - } - CssRun lastRun = line.GetLastRun(); - float diff = line.OwnerBox.GetClientWidth() - line.GetLastRun().Right; - if (diff > CSS_OFFSET_THRESHOLD) - { - foreach (CssRun word in line.GetRunIter()) - { - word.Left += diff; - } - } - } static void RearrangeWithFlexContext(CssBox box, LayoutVisitor lay) { diff --git a/Source/LayoutFarm.HtmlRenderer/5_Boxes_SpecialBoxes/CssBoxImage.cs b/Source/LayoutFarm.HtmlRenderer/5_Boxes_SpecialBoxes/CssBoxImage.cs index 426f4afc2..e6632ac47 100755 --- a/Source/LayoutFarm.HtmlRenderer/5_Boxes_SpecialBoxes/CssBoxImage.cs +++ b/Source/LayoutFarm.HtmlRenderer/5_Boxes_SpecialBoxes/CssBoxImage.cs @@ -146,9 +146,9 @@ public override void Paint(PaintVisitor p, RectangleF rect) } break; } -//#if DEBUG -// p.FillRectangle(Color.Red, rect.X, rect.Y, rect.Width, rect.Height); -//#endif + //#if DEBUG + // p.FillRectangle(Color.Red, rect.X, rect.Y, rect.Width, rect.Height); + //#endif } @@ -183,8 +183,99 @@ public override void MeasureRunsSize(LayoutVisitor lay) this.RunSizeMeasurePass = true; - CssLayoutEngine.MeasureImageSize(_imgRun, lay); + MeasureImageSize(_imgRun, lay); } + + /// + /// Measure image box size by the width\height set on the box and the actual rendered image size.
+ /// If no image exists for the box error icon will be set. + ///
+ /// the image word to measure + static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay) + { + var width = imgRun.OwnerBox.Width; + var height = imgRun.OwnerBox.Height; + + bool hasImageTagWidth = width.Number > 0 && width.UnitOrNames == Css.CssUnitOrNames.Pixels; + bool hasImageTagHeight = height.Number > 0 && height.UnitOrNames == Css.CssUnitOrNames.Pixels; + bool scaleImageHeight = false; + + if (hasImageTagWidth) + { + imgRun.Width = width.Number; + } + else if (width.Number > 0 && width.IsPercentage) + { + + imgRun.Width = width.Number * lay.LatestContainingBlock.VisualWidth; + scaleImageHeight = true; + } + else if (imgRun.HasUserImageContent) + { + imgRun.Width = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageWidth : imgRun.ImageRectangle.Width; + } + else + { + imgRun.Width = hasImageTagHeight ? height.Number / 1.14f : 20; + } + + var maxWidth = imgRun.OwnerBox.MaxWidth;// new CssLength(imageWord.OwnerBox.MaxWidth); + if (maxWidth.Number > 0) + { + float maxWidthVal = -1; + switch (maxWidth.UnitOrNames) + { + case Css.CssUnitOrNames.Percent: + { + maxWidthVal = maxWidth.Number * lay.LatestContainingBlock.VisualWidth; + } break; + case Css.CssUnitOrNames.Pixels: + { + maxWidthVal = maxWidth.Number; + } break; + } + + + if (maxWidthVal > -1 && imgRun.Width > maxWidthVal) + { + imgRun.Width = maxWidthVal; + scaleImageHeight = !hasImageTagHeight; + } + } + + if (hasImageTagHeight) + { + imgRun.Height = height.Number; + } + else if (imgRun.HasUserImageContent) + { + imgRun.Height = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageHeight : imgRun.ImageRectangle.Height; + } + else + { + imgRun.Height = imgRun.Width > 0 ? imgRun.Width * 1.14f : 22.8f; + } + + if (imgRun.HasUserImageContent) + { + // If only the width was set in the html tag, ratio the height. + if ((hasImageTagWidth && !hasImageTagHeight) || scaleImageHeight) + { + // Divide the given tag width with the actual image width, to get the ratio. + float ratio = imgRun.Width / imgRun.OriginalImageWidth; + imgRun.Height = imgRun.OriginalImageHeight * ratio; + } + // If only the height was set in the html tag, ratio the width. + else if (hasImageTagHeight && !hasImageTagWidth) + { + // Divide the given tag height with the actual image height, to get the ratio. + float ratio = imgRun.Height / imgRun.OriginalImageHeight; + imgRun.Width = imgRun.OriginalImageWidth * ratio; + } + } + //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom; + } + } From 658939a9c53380b2df905bd493fe2bce27ac3a6f Mon Sep 17 00:00:00 2001 From: win Date: Sun, 26 Jul 2015 18:15:19 +0700 Subject: [PATCH 09/11] 9010: fixed block in inline warning : fixed code is not follow w3c breaking algo , but the result is compatible with w3c because we simply used special block-run :) --- .../Samples/0_acid1_dev/003.3.html | 2 +- .../2_Boxes/1_CoreBox/CssBoxCollection.cs | 20 +- .../2_Boxes/1_CoreBox/CssBox_Fields.cs | 10 +- .../2_Boxes/1_CoreBox/CssBox_Unsafe.cs | 7 +- .../2_Boxes/1_CoreBox/CssLineBox.cs | 16 +- .../CssLayoutEngine.FloatFormattingContext.cs | 7 +- .../0_General/CssLayoutEngine.cs | 332 +++++++++--------- 7 files changed, 204 insertions(+), 190 deletions(-) diff --git a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html index b866681e7..d7a3b221c 100644 --- a/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html +++ b/Source/HtmlRenderer.Demo/Samples/0_acid1_dev/003.3.html @@ -5,7 +5,7 @@ xyz -
+
12345
sub1
sub2
diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs index c98ec3fe5..07554844b 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs @@ -1,6 +1,4 @@ -//2014,2015 BSD,WinterDev - - +//2014,2015 BSD, WinterDev using System; using System.Collections.Generic; @@ -12,8 +10,8 @@ class CssBoxCollection LinkedList _boxes = new LinkedList(); public CssBoxCollection() { - } - + } + public IEnumerable GetChildBoxIter() { var cNode = _boxes.First; @@ -32,6 +30,16 @@ public IEnumerable GetChildBoxBackwardIter() cNode = cNode.Previous; } } + public void AddFirst(CssBox owner, CssBox box) + { +#if DEBUG + if (owner == box) + { + throw new NotSupportedException(); + } +#endif + CssBox.UnsafeSetNodes(box, owner, _boxes.AddFirst(box)); + } public void AddChild(CssBox owner, CssBox box) { @@ -93,7 +101,7 @@ public CssBox GetLastChild() public IEnumerator GetEnumerator() { return this._boxes.GetEnumerator(); - } + } #if DEBUG public bool dbugContains(CssBox box) diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs index 9b2bbb581..b471b27a1 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs @@ -58,12 +58,12 @@ partial class CssBox //condition 1: invalid * //condition 2: valid //condition 3: valid - LinkedList _clientLineBoxes; + LinkedList _clientLineBoxes; /// /// absolute position layer /// - CssBoxCollection _absPosLayer; + CssBoxCollection _absPosLayer; CssBlockRun justBlockRun; @@ -174,6 +174,10 @@ public void RemoveChild(CssBox box) } break; } } + internal void InsertFirst(CssBox box) + { + this._aa_boxes.AddFirst(this, box); + } public void AppendChild(CssBox box) { switch (box.Position) @@ -346,7 +350,7 @@ public void AppendToAbsoluteLayer(CssBox box) //} } - + //------------------------------------- internal void ResetLineBoxes() { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs index 5fea806cf..56a11994c 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Unsafe.cs @@ -33,6 +33,7 @@ internal static CssBoxCollection UnsafeGetChildren(CssBox box) { return box._aa_boxes; } + public static BoxSpec UnsafeGetBoxSpec(CssBox box) { //this method is for BoxCreator and debug only! @@ -67,10 +68,8 @@ public static void UnsafeSetContentRuns(CssBox box, List runs, bool isAl //** box._boxCompactFlags &= ~BoxFlags.LAY_RUNSIZE_MEASURE; } - //---------- - - - + + //----------- #if DEBUG public override string ToString() diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs index 4f28b8d4e..38689d4ad 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs @@ -114,7 +114,7 @@ public override string ToString() /// sealed class CssLineBox { - readonly CssBox _ownerBox; + CssBox _ownerBox; //a run may come from another CssBox (not from _ownerBox) readonly List _runs = new List(); @@ -142,6 +142,10 @@ public CssLineBox(CssBox ownerBox) { _ownerBox = ownerBox; } + internal void ChangeOwnerLine(CssBox newOwnerBox) + { + this._ownerBox = newOwnerBox; + } internal CssLineBox NextLine { get @@ -185,15 +189,15 @@ internal float CachedExactContentWidth } internal float CalculateLineHeight() { - + float maxBottom = 0; List myruns = this._runs; - int j = myruns.Count; + int j = myruns.Count; for (int i = 0; i < j; ++i) { - CssRun run = myruns[i]; + CssRun run = myruns[i]; //maxRight = run.Right > maxRight ? run.Right : maxRight; - maxBottom = run.Bottom > maxBottom ? run.Bottom : maxBottom; + maxBottom = run.Bottom > maxBottom ? run.Bottom : maxBottom; } return maxBottom; } @@ -274,7 +278,7 @@ internal bool CanDoMoreLeftOffset(float newOffset, float rightLimit) { int j = this._runs.Count; if (j > 0) - { + { //last run right position //1. find current left start if (_runs[j - 1].Right + newOffset > rightLimit) diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.FloatFormattingContext.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.FloatFormattingContext.cs index b2b820d78..9eafbfad2 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.FloatFormattingContext.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.FloatFormattingContext.cs @@ -6,18 +6,13 @@ namespace LayoutFarm.HtmlBoxes { struct FloatFormattingContext { - - //Stack lineFormattingContextStack = new Stack(); - - //Stack lineOffsetLeftStack = new Stack(); - //Stack lineOffsetRightStack = new Stack(); - //Stack floatingOutOfLineStack = new Stack(); public CssBox rightFloatBox; public CssBox leftFloatBox; public float lineLeftOffset; public float lineRightOffset; public float offsetFloatTop; public bool floatingOutOfLine; + } } \ No newline at end of file diff --git a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs index 3f3ec5a3e..93b34b33f 100755 --- a/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs +++ b/Source/LayoutFarm.HtmlRenderer/3_Boxes_Layout/0_General/CssLayoutEngine.cs @@ -21,148 +21,12 @@ namespace LayoutFarm.HtmlBoxes { - enum LayoutContextMode - { - Init, - Inline, - Block - } - class LinesFormattingContext + + static class LinesFormattingEngine { const float CSS_OFFSET_THRESHOLD = 0.1f; - CssBox hostBlock; - LayoutVisitor lay; - public void BeginContext(CssBox hostBlock, LayoutVisitor lay) - { - this.hostBlock = hostBlock; - this.lay = lay; - } - public void EndContext() - { - } - 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 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) - { - 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; - } - } /// /// do layout line formatting context /// @@ -231,7 +95,6 @@ public static void DoLayoutLinesContext(CssBox hostBlock, LayoutVisitor lay) hostBlock.AddLineBox(line); //**** var floatCtx = new FloatFormattingContext(); - FlowBoxContentIntoHostLineFmtContext(lay, hostBlock, hostBlock, limitLocalRight, localX, ref line, ref localX, ref floatCtx); @@ -292,6 +155,129 @@ public static void DoLayoutLinesContext(CssBox hostBlock, LayoutVisitor lay) 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 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) + { + 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; + } + } + /// /// Recursively flows the content of the box using the inline model /// @@ -332,23 +318,14 @@ static void FlowBoxContentIntoHostLineFmtContext( int childNumber = 0; var ifonts = lay.SampleIFonts; - foreach (CssBox b in srcBox.GetChildBoxIter()) - { - if (b.CssDisplayOutside == CssDisplayOutside.Block) - { - //if display outside is block - //just break - - } - //----------------------------------------- -#if DEBUG - if (b.__aa_dbugId == 4) - { - - } -#endif + CssBoxCollection children = CssBox.UnsafeGetChildren(srcBox); + var cNode = children.GetFirstLinkedNode(); + while (cNode != null) + { float leftMostSpace = 0, rightMostSpace = 0; + CssBox b = cNode.Value; + //if b has absolute pos then it is removed from the flow if (b.NeedComputedValueEvaluation) { @@ -363,15 +340,16 @@ static void FlowBoxContentIntoHostLineFmtContext( } #endif + cx += leftMostSpace; - if (b.CssDisplay == CssDisplay.InlineBlock) + if (b.CssDisplayInside == CssDisplayInside.FlowRoot)//eg. inline block { //-------- - // if inside display is block context *** + // if inside display is FlowRoot *** //--------- //outside -> inline - //inside -> block + //inside -> flow-root //can't split //create 'block-run' @@ -402,7 +380,32 @@ static void FlowBoxContentIntoHostLineFmtContext( new List() { b.JustBlockRun }, ref hostLine, ref cx); } + else if (b.CssDisplayOutside == CssDisplayOutside.Block) + { + //warning : this code block not follow w3c spec *** + + + CssLayoutEngine.PerformContentLayout(b, lay); + CssBlockRun blockRun = b.JustBlockRun; + if (blockRun == null) + { + blockRun = new CssBlockRun(b); + blockRun.SetOwner(srcBox); + b.JustBlockRun = blockRun; + } + + //set width to full *** + blockRun.SetSize(hostBox.GetClientWidth(), b.VisualHeight); + + b.SetLocation(b.LocalX, 0); //because of inline*** + + FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber, + limitLocalRight, firstRunStartX, + leftMostSpace, rightMostSpace, + new List() { b.JustBlockRun }, + ref hostLine, ref cx); + } else if (b.HasOnlyRuns) { switch (b.Float) @@ -499,7 +502,7 @@ static void FlowBoxContentIntoHostLineFmtContext( var newFloatCtx = new FloatFormattingContext(); FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b, - limitLocalRight, 0, + limitLocalRight, 0, ref line, ref localX1, ref newFloatCtx); float localY = 0; @@ -577,8 +580,6 @@ static void FlowBoxContentIntoHostLineFmtContext( } else { - - //go deeper //recursive *** //not new lineFormatting context @@ -590,6 +591,8 @@ static void FlowBoxContentIntoHostLineFmtContext( cx += rightMostSpace; childNumber++; + //--------------------- + cNode = cNode.Next; } } if (srcBox.Position == CssPosition.Relative) @@ -789,7 +792,7 @@ static void ApplyRightAlignment(CssLineBox line) } } - + /// @@ -798,7 +801,7 @@ static void ApplyRightAlignment(CssLineBox line) static class CssLayoutEngine { - + public static void PerformContentLayout(CssBox box, LayoutVisitor lay) { //recursive @@ -879,11 +882,12 @@ public static void PerformContentLayout(CssBox box, LayoutVisitor lay) if (ContainsInlinesOnly(box)) { - ////This will automatically set the bottom of this block - LinesFormattingContext.DoLayoutLinesContext(box, lay); + //This will automatically set the bottom of this block + LinesFormattingEngine.DoLayoutLinesContext(box, lay); } else if (box.ChildCount > 0) { + DoLayoutBlocksContext(box, lay); } From 0bbaa184683d505a8ce149d2aea16561347f9f61 Mon Sep 17 00:00:00 2001 From: win Date: Sun, 26 Jul 2015 18:17:08 +0700 Subject: [PATCH 10/11] 9011: removed CssLineBox.ChangeOwnerLine --- .../2_Boxes/1_CoreBox/CssLineBox.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs index 38689d4ad..2bf0be349 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssLineBox.cs @@ -114,7 +114,7 @@ public override string ToString() /// sealed class CssLineBox { - CssBox _ownerBox; + readonly CssBox _ownerBox; //a run may come from another CssBox (not from _ownerBox) readonly List _runs = new List(); @@ -142,10 +142,7 @@ public CssLineBox(CssBox ownerBox) { _ownerBox = ownerBox; } - internal void ChangeOwnerLine(CssBox newOwnerBox) - { - this._ownerBox = newOwnerBox; - } + internal CssLineBox NextLine { get From e3f0a5e5e4e6570ce5a4d419c21e7f1067fdf035 Mon Sep 17 00:00:00 2001 From: win Date: Sun, 26 Jul 2015 18:24:01 +0700 Subject: [PATCH 11/11] 9012: remove CssBoxCollection.AddFirst() unused --- .../2_Boxes/1_CoreBox/CssBoxCollection.cs | 11 +---------- .../2_Boxes/1_CoreBox/CssBox_Fields.cs | 5 +---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs index 07554844b..1e82d4e76 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBoxCollection.cs @@ -30,16 +30,7 @@ public IEnumerable GetChildBoxBackwardIter() cNode = cNode.Previous; } } - public void AddFirst(CssBox owner, CssBox box) - { -#if DEBUG - if (owner == box) - { - throw new NotSupportedException(); - } -#endif - CssBox.UnsafeSetNodes(box, owner, _boxes.AddFirst(box)); - } + public void AddChild(CssBox owner, CssBox box) { diff --git a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs index b471b27a1..11920bafb 100755 --- a/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs +++ b/Source/LayoutFarm.HtmlRenderer/2_Boxes/1_CoreBox/CssBox_Fields.cs @@ -174,10 +174,7 @@ public void RemoveChild(CssBox box) } break; } } - internal void InsertFirst(CssBox box) - { - this._aa_boxes.AddFirst(this, box); - } + public void AppendChild(CssBox box) { switch (box.Position)