Skip to content

Commit d936de6

Browse files
authored
Merge pull request #13 from alfattack/absolute-positioning
Support absolute positioning
2 parents e2fd2d2 + 71e21af commit d936de6

File tree

4 files changed

+60
-9
lines changed

4 files changed

+60
-9
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<html>
2+
<body>
3+
<div style="position: absolute; top: 700px; left: 90px; width: 75px; height: 75px; background-color: black;"></div>
4+
5+
<div style="position: relative;">
6+
<div style="width: 200px; height: 200px; background-color: green;"></div>
7+
<div style="width: 50px; height: 50px; background-color: red; position: absolute; top: 30px; left: 400px;"></div>
8+
</div>
9+
10+
<div style="width: 400px; height: 200px; margin-left: 80px; background-color: purple"></div>
11+
12+
<div style="width: 600px; height: 300px; background-color: white; position: relative;">
13+
<div style="width: 50px; height: 50px; background-color: brown; top: 50px; left: 25px; position: absolute; "></div>
14+
</div>
15+
16+
</body>
17+
</html>

Source/Demos/HtmlRenderer.Demo.Console/Program.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
foreach (var htmlSample in samples)
2525
{
2626
////Just doing one test here. Comment this for all of them.
27-
if (!htmlSample.FullName.Contains("16", StringComparison.OrdinalIgnoreCase)) continue;
27+
if (!htmlSample.FullName.Contains("37", StringComparison.OrdinalIgnoreCase)) continue;
2828

29-
await skia.GenerateSampleAsync(htmlSample);
30-
await svgSkia.GenerateSampleAsync(htmlSample);
31-
//await pdfSharp.GenerateSampleAsync(htmlSample);
29+
//await skia.GenerateSampleAsync(htmlSample);
30+
//await svgSkia.GenerateSampleAsync(htmlSample);
31+
await pdfSharp.GenerateSampleAsync(htmlSample);
3232
}
3333

3434

Source/HtmlRenderer/Core/Dom/CssBox.cs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,17 @@ public virtual bool IsFixed
201201
}
202202
}
203203

204+
/// <summary>
205+
/// Gets a value indicating whether this instance has Position = absolute.
206+
/// </summary>
207+
/// <value>
208+
/// <c>true</c> if this instance is fixed; otherwise, <c>false</c>.
209+
/// </value>
210+
public virtual bool IsAbsolute
211+
{
212+
get => Position == CssConstants.Absolute;
213+
}
214+
204215
/// <summary>
205216
/// Get the href link of the box (by default get "href" attribute)
206217
/// </summary>
@@ -650,6 +661,26 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g)
650661
left = 0;
651662
top = 0;
652663
}
664+
else if (Position == CssConstants.Absolute)
665+
{
666+
// find the first positioned parent.
667+
CssBox currentParent = ParentBox;
668+
CssBox positionedAncestor = null;
669+
while(currentParent != null && string.IsNullOrEmpty(currentParent.Position))
670+
{
671+
currentParent = currentParent.ParentBox;
672+
}
673+
positionedAncestor = currentParent;
674+
675+
if (positionedAncestor != null)
676+
{
677+
var location = GetActualLocation(this.Left, this.Top);
678+
left = positionedAncestor.Location.X + location.X;
679+
top = positionedAncestor.Location.Y + location.Y;
680+
681+
Location = new RPoint(left, top);
682+
}
683+
}
653684
else
654685
{
655686
left = ContainingBlock.Location.X + ContainingBlock.ActualPaddingLeft + ActualMarginLeft + ContainingBlock.ActualBorderLeftWidth;
@@ -709,11 +740,11 @@ protected virtual async Task PerformLayoutImpAsync(RGraphics g)
709740
ActualBottom = prevSibling.ActualBottom;
710741
}
711742
}
712-
ActualBottom = Math.Max(ActualBottom, Location.Y + ActualHeight);
713743

744+
ActualBottom = Math.Max(ActualBottom, Location.Y + ActualHeight);
714745
await CreateListItemBoxAsync(g);
715746

716-
if (!IsFixed)
747+
if (!IsFixed && !IsAbsolute)
717748
{
718749
var actualWidth = Math.Max(GetMinimumWidth() + GetWidthMarginDeep(this), Size.Width < 90999 ? ActualRight - HtmlContainer.Root.Location.X : 0);
719750
HtmlContainer.ActualSize = CommonUtils.Max(HtmlContainer.ActualSize, new RSize(actualWidth, ActualBottom - HtmlContainer.Root.Location.Y));
@@ -1192,12 +1223,15 @@ private double CalculateActualRight()
11921223
private double MarginBottomCollapse()
11931224
{
11941225
double margin = 0;
1226+
1227+
// Get the last child box that doesn't have absolute or fixed positioning.
1228+
var lastChildBox = _boxes.Where(b => b.Position != CssConstants.Fixed && b.Position != CssConstants.Absolute).LastOrDefault();
11951229
if (ParentBox != null && ParentBox.Boxes.IndexOf(this) == ParentBox.Boxes.Count - 1 && _parentBox.ActualMarginBottom < 0.1)
11961230
{
1197-
var lastChildBottomMargin = _boxes[_boxes.Count - 1].ActualMarginBottom;
1231+
var lastChildBottomMargin = lastChildBox?.ActualMarginBottom ?? 0;
11981232
margin = Height == "auto" ? Math.Max(ActualMarginBottom, lastChildBottomMargin) : lastChildBottomMargin;
11991233
}
1200-
return Math.Max(ActualBottom, _boxes[_boxes.Count - 1].ActualBottom + margin + ActualPaddingBottom + ActualBorderBottomWidth);
1234+
return Math.Max(ActualBottom, (lastChildBox?.ActualBottom ?? 0) + margin + ActualPaddingBottom + ActualBorderBottomWidth);
12011235
}
12021236

12031237
/// <summary>

Source/HtmlRenderer/Core/Utils/DomUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public static CssBox GetPreviousSibling(CssBox b)
106106
sib = b.ParentBox.Boxes[index - ++diff];
107107
}
108108

109-
return (sib.Display == CssConstants.None || sib.Position == CssConstants.Fixed) ? null : sib;
109+
return (sib.Display == CssConstants.None || sib.Position == CssConstants.Absolute || sib.Position == CssConstants.Fixed) ? null : sib;
110110
}
111111
}
112112
return null;

0 commit comments

Comments
 (0)