Decoration: improved implementation, fixed unit tests
This commit is contained in:
@@ -9,35 +9,27 @@ namespace QuestPDF.UnitTests
|
||||
[TestFixture]
|
||||
public class DecorationTests
|
||||
{
|
||||
private Decoration CreateDecoration(TestPlan testPlan)
|
||||
{
|
||||
return new Decoration
|
||||
{
|
||||
Before = testPlan.CreateChild("before"),
|
||||
Content = testPlan.CreateChild("content"),
|
||||
After = testPlan.CreateChild("after"),
|
||||
};
|
||||
}
|
||||
|
||||
#region Measure
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenDecorationReturnsWrap()
|
||||
public void Measure_ReturnsWrap_WhenBeforeReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenDecorationReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.PartialRender(300, 200))
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.Wrap())
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
@@ -45,89 +37,100 @@ namespace QuestPDF.UnitTests
|
||||
public void Measure_ReturnsWrap_WhenContentReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsPartialRender_WhenContentReturnsPartialRender()
|
||||
public void Measure_ReturnsWrap_WhenAfterReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.PartialRender(200, 150))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(400, 250));
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.Wrap())
|
||||
.ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsFullRender_WhenContentReturnsFullRender()
|
||||
public void Measure_ReturnsWrap_WhenBeforeReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(200, 150))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(400, 250));
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.PartialRender(100, 50))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenAfterReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.PartialRender(100, 50))
|
||||
.ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenContentReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.PartialRender(150, 100))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(150, 200));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenContentReturnsFullRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateDecoration)
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(150, 100))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(150, 200));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Draw
|
||||
|
||||
[Test]
|
||||
public void Draw_Prepend()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Prepend,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildDraw("decoration", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, 100)
|
||||
.ExpectChildDraw("content", new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, -100)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_Append()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.For(CreateDecoration)
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildDraw("content", new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, 200)
|
||||
.ExpectChildDraw("decoration", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, -200)
|
||||
.ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(200, 40))
|
||||
.ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(200, 60))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(300, 100))
|
||||
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("before", new Size(300, 40))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
|
||||
.ExpectCanvasTranslate(0, 40)
|
||||
.ExpectChildDraw("content", new Size(300, 100))
|
||||
.ExpectCanvasTranslate(0, -40)
|
||||
|
||||
.ExpectCanvasTranslate(0, 140)
|
||||
.ExpectChildDraw("after", new Size(300, 60))
|
||||
.ExpectCanvasTranslate(0, -140)
|
||||
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace QuestPDF.Elements
|
||||
{
|
||||
public Element Element { get; set; }
|
||||
public SpacePlan Measurement { get; set; }
|
||||
public Size Size { get; set; }
|
||||
public Position Offset { get; set; }
|
||||
}
|
||||
|
||||
@@ -42,8 +41,8 @@ namespace QuestPDF.Elements
|
||||
if (renderingCommands.Any(x => x.Measurement.Type == SpacePlanType.Wrap))
|
||||
return SpacePlan.Wrap();
|
||||
|
||||
var width = renderingCommands.Max(x => x.Size.Width);
|
||||
var height = renderingCommands.Sum(x => x.Size.Height);
|
||||
var width = renderingCommands.Max(x => x.Measurement.Width);
|
||||
var height = renderingCommands.Sum(x => x.Measurement.Height);
|
||||
var size = new Size(width, height);
|
||||
|
||||
if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
|
||||
@@ -58,18 +57,32 @@ namespace QuestPDF.Elements
|
||||
|
||||
internal override void Draw(Size availableSpace)
|
||||
{
|
||||
foreach (var command in PlanLayout(availableSpace))
|
||||
var renderingCommands = PlanLayout(availableSpace).ToList();
|
||||
var width = renderingCommands.Max(x => x.Measurement.Width);
|
||||
|
||||
foreach (var command in renderingCommands)
|
||||
{
|
||||
var elementSize = new Size(width, command.Measurement.Height);
|
||||
|
||||
Canvas.Translate(command.Offset);
|
||||
command.Element.Draw(command.Size);
|
||||
command.Element.Draw(elementSize);
|
||||
Canvas.Translate(command.Offset.Reverse());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<DecorationItemRenderingCommand> PlanLayout(Size availableSpace)
|
||||
{
|
||||
var beforeMeasurement = Before.Measure(availableSpace);
|
||||
var afterMeasurement = After.Measure(availableSpace);
|
||||
SpacePlan GetDecorationMeasurement(Element element)
|
||||
{
|
||||
var measurement = element.Measure(availableSpace);
|
||||
|
||||
return measurement.Type == SpacePlanType.FullRender
|
||||
? measurement
|
||||
: SpacePlan.Wrap();
|
||||
}
|
||||
|
||||
var beforeMeasurement = GetDecorationMeasurement(Before);
|
||||
var afterMeasurement = GetDecorationMeasurement(After);
|
||||
|
||||
var contentSpace = new Size(availableSpace.Width, availableSpace.Height - beforeMeasurement.Height - afterMeasurement.Height);
|
||||
var contentMeasurement = Content.Measure(contentSpace);
|
||||
@@ -78,7 +91,6 @@ namespace QuestPDF.Elements
|
||||
{
|
||||
Element = Before,
|
||||
Measurement = beforeMeasurement,
|
||||
Size = new Size(availableSpace.Width, beforeMeasurement.Height),
|
||||
Offset = Position.Zero
|
||||
};
|
||||
|
||||
@@ -86,7 +98,6 @@ namespace QuestPDF.Elements
|
||||
{
|
||||
Element = Content,
|
||||
Measurement = contentMeasurement,
|
||||
Size = new Size(availableSpace.Width, contentMeasurement.Height),
|
||||
Offset = new Position(0, beforeMeasurement.Height)
|
||||
};
|
||||
|
||||
@@ -94,7 +105,6 @@ namespace QuestPDF.Elements
|
||||
{
|
||||
Element = After,
|
||||
Measurement = afterMeasurement,
|
||||
Size = new Size(availableSpace.Width, afterMeasurement.Height),
|
||||
Offset = new Position(0, beforeMeasurement.Height + contentMeasurement.Height)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user