Implemented ScaleToFit element

This commit is contained in:
Marcin Ziąbek
2022-01-07 00:09:25 +01:00
parent 648a359d15
commit ba8b35b1c0
3 changed files with 125 additions and 0 deletions
+42
View File
@@ -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);
}
});
});
}
}
}
+78
View File
@@ -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;
}
}
}
}
+5
View File
@@ -165,5 +165,10 @@ namespace QuestPDF.Fluent
{
return element.Element(new PreventPaging());
}
public static IContainer ScaleToFit(this IContainer element)
{
return element.Element(new ScaleToFit());
}
}
}