Implemented ScaleToFit element
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class ScaleToFitExamples
|
||||
{
|
||||
[Test]
|
||||
public void ScaleToFit()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A4)
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container.Padding(25).Stack(stack =>
|
||||
{
|
||||
var text = Placeholders.Paragraph();
|
||||
|
||||
foreach (var i in Enumerable.Range(0, 16))
|
||||
{
|
||||
stack
|
||||
.Item()
|
||||
.MinimalBox()
|
||||
.Border(1)
|
||||
.Padding(5)
|
||||
.Width(50 + i * 25)
|
||||
.Height(25 + i * 5)
|
||||
.ScaleToFit()
|
||||
.Text(text);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements
|
||||
{
|
||||
internal class ScaleToFit : ContainerElement
|
||||
{
|
||||
internal override SpacePlan Measure(Size availableSpace)
|
||||
{
|
||||
if (Child == null)
|
||||
return SpacePlan.FullRender(Size.Zero);
|
||||
|
||||
var perfectScale = FindPerfectScale(Child, availableSpace);
|
||||
|
||||
if (perfectScale == null)
|
||||
return SpacePlan.Wrap();
|
||||
|
||||
var targetSpace = ScaleSize(availableSpace, perfectScale.Value);
|
||||
return SpacePlan.FullRender(targetSpace);
|
||||
}
|
||||
|
||||
internal override void Draw(Size availableSpace)
|
||||
{
|
||||
var perfectScale = FindPerfectScale(Child, availableSpace);
|
||||
|
||||
if (!perfectScale.HasValue)
|
||||
return;
|
||||
|
||||
var targetScale = perfectScale.Value;
|
||||
var targetSpace = ScaleSize(availableSpace, 1 / targetScale);
|
||||
|
||||
Canvas.Scale(targetScale, targetScale);
|
||||
Child?.Draw(targetSpace);
|
||||
Canvas.Scale(1 / targetScale, 1 / targetScale);
|
||||
}
|
||||
|
||||
private static Size ScaleSize(Size size, float factor)
|
||||
{
|
||||
return new Size(size.Width * factor, size.Height * factor);
|
||||
}
|
||||
|
||||
private static float? FindPerfectScale(Element child, Size availableSpace)
|
||||
{
|
||||
if (ChildFits(1))
|
||||
return 1;
|
||||
|
||||
var maxScale = 1f;
|
||||
var minScale = Size.Epsilon;
|
||||
|
||||
var lastWorkingScale = (float?)null;
|
||||
|
||||
foreach (var _ in Enumerable.Range(0, 8))
|
||||
{
|
||||
var halfScale = (maxScale + minScale) / 2;
|
||||
|
||||
if (ChildFits(halfScale))
|
||||
{
|
||||
minScale = halfScale;
|
||||
lastWorkingScale = halfScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxScale = halfScale;
|
||||
}
|
||||
}
|
||||
|
||||
return lastWorkingScale;
|
||||
|
||||
bool ChildFits(float scale)
|
||||
{
|
||||
var scaledSpace = ScaleSize(availableSpace, 1 / scale);
|
||||
return child.Measure(scaledSpace).Type == SpacePlanType.FullRender;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,5 +165,10 @@ namespace QuestPDF.Fluent
|
||||
{
|
||||
return element.Element(new PreventPaging());
|
||||
}
|
||||
|
||||
public static IContainer ScaleToFit(this IContainer element)
|
||||
{
|
||||
return element.Element(new ScaleToFit());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user