Compare commits

..

5 Commits

Author SHA1 Message Date
MarcinZiabek 5cc0397acb Added more examples for the Shrink element 2022-10-19 23:20:19 +02:00
MarcinZiabek 73448f483c Extended and renamed the MinimalBox element 2022-10-19 21:37:10 +02:00
MarcinZiabek 7b7fac07b3 Relative padding implementation 2022-10-05 00:58:00 +02:00
MarcinZiabek 759655059d Renaming 2022-10-04 22:47:18 +02:00
MarcinZiabek fa3d912e41 RelativeSize, RelativePosition 2022-10-04 22:26:25 +02:00
28 changed files with 539 additions and 171 deletions
@@ -0,0 +1,36 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class RelativePaddingExamples
{
[Test]
public void ItemTypes()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(250, 250)
.ShowResults()
.Render(container =>
{
container
.Width(250)
.Height(250)
.Padding(50)
.Background(Colors.Grey.Lighten2)
.RelativePaddingLeft(0.1f)
.RelativePaddingTop(0.2f)
.RelativePaddingRight(0.3f)
.RelativePaddingBottom(0.4f)
.Background(Colors.Grey.Darken2);
});
}
}
}
@@ -0,0 +1,32 @@
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class RelativePositionExamples
{
[Test]
public void ItemTypes()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(500, 500)
.ShowResults()
.Render(container =>
{
container
.Padding(100)
.Background(Colors.Grey.Lighten2)
.RelativePositionVertical(0.5f, -0.5f)
.RelativePositionHorizontal(1f, -0.5f)
.RelativeWidth(0.4f)
.RelativeHeight(0.6f)
.Background(Colors.Grey.Darken2);
});
}
}
}
+38
View File
@@ -0,0 +1,38 @@
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class RelativeSizeExamples
{
[Test]
public void ItemTypes()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(600, 600)
.ShowResults()
.Render(container =>
{
container
.AlignMiddle()
.AlignCenter()
.Width(400)
.Height(400)
.Background(Colors.Grey.Lighten2)
.AlignMiddle()
.AlignCenter()
.Container()
.AlignMiddle()
.AlignCenter()
.RelativeWidth(0.25f)
.RelativeHeight(0.5f)
.Background(Colors.Grey.Darken2);
});
}
}
}
+93
View File
@@ -0,0 +1,93 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class ShrinkExamples
{
[Test]
public void Shrink_Without()
{
RenderingTest
.Create()
.PageSize(300, 200)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Border(2)
.Background(Colors.Grey.Lighten2)
.Padding(20)
.Text("This is test.")
.FontSize(20);
});
}
[Test]
public void Shrink_Horizontal()
{
RenderingTest
.Create()
.PageSize(300, 200)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Border(2)
.ShrinkHorizontal()
.Background(Colors.Grey.Lighten2)
.Padding(20)
.Text("This is test.")
.FontSize(20);
});
}
[Test]
public void Shrink_Vertical()
{
RenderingTest
.Create()
.PageSize(300, 200)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Border(2)
.ShrinkVertical()
.Background(Colors.Grey.Lighten2)
.Padding(20)
.Text("This is test.")
.FontSize(20);
});
}
[Test]
public void Shrink_Both()
{
RenderingTest
.Create()
.PageSize(300, 200)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Border(2)
.Shrink()
.Background(Colors.Grey.Lighten2)
.Padding(20)
.Text("This is test.")
.FontSize(20);
});
}
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ namespace QuestPDF.Examples
.PageSize(PageSizes.A4)
.ShowResults()
.MaxPages(10_000)
//.EnableCaching(true)
.EnableCaching(true)
.EnableDebugging(false)
.Render(container =>
{
+2 -2
View File
@@ -15,8 +15,8 @@ namespace QuestPDF.ReportSample
HeaderFields = HeaderFields(),
LogoData = Helpers.GetImage("Logo.png"),
Sections = Enumerable.Range(0, 2000).Select(x => GenerateSection()).ToList(),
Photos = Enumerable.Range(0, 200).Select(x => GetReportPhotos()).ToList()
Sections = Enumerable.Range(0, 40).Select(x => GenerateSection()).ToList(),
Photos = Enumerable.Range(0, 25).Select(x => GetReportPhotos()).ToList()
};
List<ReportHeaderField> HeaderFields()
+1 -4
View File
@@ -24,10 +24,7 @@ namespace QuestPDF.ReportSample
[Test]
public void GenerateAndShowPdf()
{
Settings.DocumentLayoutExceptionThreshold = 10_000;
Settings.EnableCaching = true;
Settings.EnableDebugging = false;
ImagePlaceholder.Solid = true;
//ImagePlaceholder.Solid = true;
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"test_result.pdf");
Report.GeneratePdf(path);
@@ -7,18 +7,20 @@ using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class BoxTests
public class ShrinkTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<MinimalBox>();
public void Measure() => SimpleContainerTests.Measure<Shrink>();
[Test]
public void Draw_Wrap()
{
TestPlan
.For(x => new MinimalBox
.For(x => new Shrink
{
Child = x.CreateChild()
Child = x.CreateChild(),
ShrinkVertical = true,
ShrinkHorizontal = true
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.Wrap())
@@ -29,9 +31,11 @@ namespace QuestPDF.UnitTests
public void Measure_PartialRender()
{
TestPlan
.For(x => new MinimalBox
.For(x => new Shrink
{
Child = x.CreateChild()
Child = x.CreateChild(),
ShrinkVertical = true,
ShrinkHorizontal = true
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.PartialRender(200, 100))
@@ -43,9 +47,11 @@ namespace QuestPDF.UnitTests
public void Measure_FullRender()
{
TestPlan
.For(x => new MinimalBox
.For(x => new Shrink
{
Child = x.CreateChild()
Child = x.CreateChild(),
ShrinkVertical = true,
ShrinkHorizontal = true
})
.MeasureElement(new Size(500, 400))
.ExpectChildMeasure(expectedInput: new Size(500, 400), returns: SpacePlan.FullRender(300, 200))
@@ -20,7 +20,6 @@ namespace QuestPDF.UnitTests.TestEngine
public void DrawRectangle(Position vector, Size size, string color) => DrawRectFunc(vector, size, color);
public void DrawText(SKTextBlob skTextBlob, Position position, TextStyle style) => throw new NotImplementedException();
public void DrawImage(SKImage image, Position position, Size size) => DrawImageFunc(image, position, size);
public void DrawPicture(SKPicture picture) => throw new NotImplementedException();
public void DrawHyperlink(string url, Size size) => throw new NotImplementedException();
public void DrawSectionLink(string sectionName, Size size) => throw new NotImplementedException();
@@ -18,8 +18,7 @@ namespace QuestPDF.UnitTests.TestEngine
public void DrawRectangle(Position vector, Size size, string color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
public void DrawText(SKTextBlob skTextBlob, Position position, TextStyle style) => throw new NotImplementedException();
public void DrawImage(SKImage image, Position position, Size size) => Operations.Add(new CanvasDrawImageOperation(position, size));
public void DrawPicture(SKPicture picture) => throw new NotImplementedException();
public void DrawHyperlink(string url, Size size) => throw new NotImplementedException();
public void DrawSectionLink(string sectionName, Size size) => throw new NotImplementedException();
public void DrawSection(string sectionName) => throw new NotImplementedException();
+2 -14
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using QuestPDF.Drawing.Exceptions;
@@ -68,24 +67,13 @@ namespace QuestPDF.Drawing
ApplyDefaultTextStyle(content, TextStyle.LibraryDefault);
var debuggingState = Settings.EnableDebugging ? ApplyDebugging(content) : null;
debuggingState = null;
//if (Settings.EnableCaching)
//ApplyCaching(content);
if (Settings.EnableCaching)
ApplyCaching(content);
var pageContext = new PageContext();
var stopwatch = new Stopwatch();
stopwatch.Restart();
RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
stopwatch.Stop();
Console.WriteLine($"Cold free: {stopwatch.Elapsed}");
stopwatch.Restart();
RenderPass(pageContext, canvas, content, debuggingState);
stopwatch.Stop();
Console.WriteLine($"Canvas: {stopwatch.Elapsed}");
}
internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DebuggingState? debuggingState)
-5
View File
@@ -51,11 +51,6 @@ namespace QuestPDF.Drawing
}
public void DrawPicture(SKPicture picture)
{
}
public void DrawHyperlink(string url, Size size)
{
-5
View File
@@ -38,11 +38,6 @@ namespace QuestPDF.Drawing
Canvas.DrawImage(image, new SKRect(vector.X, vector.Y, size.Width, size.Height));
}
public void DrawPicture(SKPicture picture)
{
Canvas.DrawPicture(picture);
}
public void DrawHyperlink(string url, Size size)
{
Canvas.DrawUrlAnnotation(new SKRect(0, 0, size.Width, size.Height), url);
-39
View File
@@ -1,39 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Drawing
{
internal class SkiaCaptureCanvas : SkiaCanvasBase
{
private SKPictureRecorder? PictureRecorder { get; set; }
private Size? CurrentPageSize { get; set; }
public SKPicture? CurrentPicture { get; set; }
public override void BeginDocument()
{
}
public override void BeginPage(Size size)
{
CurrentPageSize = size;
PictureRecorder = new SKPictureRecorder();
Canvas = PictureRecorder.BeginRecording(new SKRect(0, 0, size.Width, size.Height));
}
public override void EndPage()
{
CurrentPicture = PictureRecorder?.EndRecording();
PictureRecorder?.Dispose();
PictureRecorder = null;
}
public override void EndDocument() { }
}
}
-59
View File
@@ -1,59 +0,0 @@
using System.Collections.Generic;
using QuestPDF.Drawing;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Elements
{
internal class DrawingCache : ContainerElement
{
private SkiaCaptureCanvas CaptureCanvas { get; } = new();
private Dictionary<int, SpacePlan> MeasureCache { get; } = new();
private Dictionary<int, SKPicture> DrawCache { get; } = new();
~DrawingCache()
{
foreach (var picture in DrawCache.Values)
picture.Dispose();
DrawCache.Clear();
}
internal override void Initialize(IPageContext pageContext, ICanvas canvas)
{
Child.VisitChildren(x => x.Canvas = CaptureCanvas);
base.Initialize(pageContext, canvas);
}
internal override SpacePlan Measure(Size availableSpace)
{
var cacheKey = PageContext.CurrentPage;
if (MeasureCache.TryGetValue(cacheKey, out var result))
return result;
var childSize = Child?.Measure(availableSpace) ?? SpacePlan.FullRender(Size.Zero);
MeasureCache.Add(cacheKey, childSize);
return childSize;
}
internal override void Draw(Size availableSpace)
{
var cacheKey = PageContext.CurrentPage;
if (DrawCache.TryGetValue(cacheKey, out var result))
{
Canvas.DrawPicture(result);
return;
}
CaptureCanvas.BeginPage(availableSpace);
Child?.Draw(availableSpace);
CaptureCanvas.EndPage();
var picture = CaptureCanvas.CurrentPicture;
DrawCache.Add(cacheKey, picture);
}
}
}
-18
View File
@@ -1,18 +0,0 @@
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class MinimalBox : ContainerElement
{
internal override void Draw(Size availableSpace)
{
var targetSize = base.Measure(availableSpace);
if (targetSize.Type == SpacePlanType.Wrap)
return;
base.Draw(targetSize);
}
}
}
-1
View File
@@ -30,7 +30,6 @@ namespace QuestPDF.Elements
public void Compose(IContainer container)
{
container
//.Element(new DrawingCache())
.Background(BackgroundColor)
.Layers(layers =>
{
+65
View File
@@ -0,0 +1,65 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class RelativePadding : ContainerElement
{
public float Top { get; set; }
public float Right { get; set; }
public float Bottom { get; set; }
public float Left { get; set; }
internal override SpacePlan Measure(Size availableSpace)
{
if (Child == null)
return SpacePlan.FullRender(0, 0);
var internalSpace = InternalSpace(availableSpace);
if (internalSpace.Width < 0 || internalSpace.Height < 0)
return SpacePlan.Wrap();
var measure = base.Measure(internalSpace);
if (measure.Type == SpacePlanType.Wrap)
return SpacePlan.Wrap();
if (measure.Type == SpacePlanType.PartialRender)
return SpacePlan.PartialRender(availableSpace);
if (measure.Type == SpacePlanType.FullRender)
return SpacePlan.FullRender(availableSpace);
throw new NotSupportedException();
}
internal override void Draw(Size availableSpace)
{
if (Child == null)
return;
var internalOffset = InternalOffset(availableSpace);
var internalSpace = InternalSpace(availableSpace);
Canvas.Translate(internalOffset);
base.Draw(internalSpace);
Canvas.Translate(internalOffset.Reverse());
}
private Position InternalOffset(Size availableSpace)
{
return new Position(
availableSpace.Width * Left,
availableSpace.Height * Top);
}
private Size InternalSpace(Size availableSpace)
{
return new Size(
availableSpace.Width * (1f - Left - Right),
availableSpace.Height * (1f - Top - Bottom));
}
}
}
+33
View File
@@ -0,0 +1,33 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class RelativePosition : ContainerElement
{
public float VerticalParent { get; set; }
public float VerticalChild { get; set; }
public float HorizontalParent { get; set; }
public float HorizontalChild { get; set; }
internal override void Draw(Size availableSpace)
{
if (Child == null)
return;
var childSize = base.Measure(availableSpace);
if (childSize.Type == SpacePlanType.Wrap)
return;
var left = availableSpace.Width * HorizontalParent + childSize.Width * HorizontalChild;
var top = availableSpace.Height * VerticalParent + childSize.Height * VerticalChild;
Canvas.Translate(new Position(left, top));
base.Draw(childSize);
Canvas.Translate(new Position(-left, -top));
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class RelativeSize : ContainerElement
{
public float? WidthFactor { get; set; } = 1f;
public float? HeightFactor { get; set; } = 1f;
internal override SpacePlan Measure(Size availableSpace)
{
var internalSpace = new Size(
availableSpace.Width * (WidthFactor ?? 1),
availableSpace.Height * (HeightFactor ?? 1));
var childSpace = Child?.Measure(internalSpace) ?? SpacePlan.FullRender(0, 0);
if (childSpace.Type == SpacePlanType.Wrap)
return SpacePlan.Wrap();
var targetSpace = new Size(
WidthFactor.HasValue ? internalSpace.Width : childSpace.Width,
HeightFactor.HasValue ? internalSpace.Height : childSpace.Height);
if (childSpace.Type == SpacePlanType.PartialRender)
return SpacePlan.PartialRender(targetSpace);
if (childSpace.Type == SpacePlanType.FullRender)
return SpacePlan.FullRender(targetSpace);
throw new ArgumentException();
}
}
}
+27
View File
@@ -0,0 +1,27 @@
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class Shrink : ContainerElement
{
public bool ShrinkVertical { get; set; }
public bool ShrinkHorizontal { get; set; }
internal override void Draw(Size availableSpace)
{
var childSize = base.Measure(availableSpace);
if (childSize.Type == SpacePlanType.Wrap)
return;
var targetSize = new Size(
ShrinkVertical ? childSize.Width : availableSpace.Width,
ShrinkHorizontal ? childSize.Height : availableSpace.Height);
// TODO: adjust offset for RTL mode
base.Draw(targetSize);
}
}
}
-11
View File
@@ -154,17 +154,6 @@ namespace QuestPDF.Fluent
});
}
[Obsolete("This element has been renamed since version 2022.1. Please use the MinimalBox method.")]
public static IContainer Box(this IContainer element)
{
return element.Element(new MinimalBox());
}
public static IContainer MinimalBox(this IContainer element)
{
return element.Element(new MinimalBox());
}
public static IContainer Unconstrained(this IContainer element)
{
return element.Element(new Unconstrained());
@@ -0,0 +1,37 @@
using System;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
namespace QuestPDF.Fluent
{
public static class RelativePaddingExtensions
{
private static IContainer RelativePadding(this IContainer element, Action<RelativePadding> handler)
{
var relativePadding = element as RelativePadding ?? new RelativePadding();
handler(relativePadding);
return element.Element(relativePadding);
}
public static IContainer RelativePaddingTop(this IContainer element, float value)
{
return element.RelativePadding(x => x.Top += value);
}
public static IContainer RelativePaddingBottom(this IContainer element, float value)
{
return element.RelativePadding(x => x.Bottom += value);
}
public static IContainer RelativePaddingLeft(this IContainer element, float value)
{
return element.RelativePadding(x => x.Left += value);
}
public static IContainer RelativePaddingRight(this IContainer element, float value)
{
return element.RelativePadding(x => x.Right += value);
}
}
}
@@ -0,0 +1,35 @@
using System;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
namespace QuestPDF.Fluent
{
public static class RelativePositionExtensions
{
private static IContainer RelativePosition(this IContainer element, Action<RelativePosition> handler)
{
var relativePosition = element as RelativePosition ?? new RelativePosition();
handler(relativePosition);
return element.Element(relativePosition);
}
public static IContainer RelativePositionVertical(this IContainer element, float parentOffset, float childOffset)
{
return element.RelativePosition(x =>
{
x.VerticalParent = parentOffset;
x.VerticalChild = childOffset;
});
}
public static IContainer RelativePositionHorizontal(this IContainer element, float parentOffset, float childOffset)
{
return element.RelativePosition(x =>
{
x.HorizontalParent = parentOffset;
x.HorizontalChild = childOffset;
});
}
}
}
+27
View File
@@ -0,0 +1,27 @@
using System;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
namespace QuestPDF.Fluent
{
public static class RelativeSizeExtensions
{
private static IContainer RelativeSize(this IContainer element, Action<RelativeSize> handler)
{
var relativeSize = element as RelativeSize ?? new RelativeSize();
handler(relativeSize);
return element.Element(relativeSize);
}
public static IContainer RelativeWidth(this IContainer element, float value)
{
return element.RelativeSize(x => x.WidthFactor = value);
}
public static IContainer RelativeHeight(this IContainer element, float value)
{
return element.RelativeSize(x => x.HeightFactor = value);
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using System;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
namespace QuestPDF.Fluent
{
public static class ShrinkExtensions
{
private static IContainer Shrink(this IContainer element, Action<Shrink> handler)
{
var shrink = element as Shrink ?? new Shrink();
handler(shrink);
return element.Element(shrink);
}
public static IContainer Shrink(this IContainer element)
{
return element.ShrinkVertical().ShrinkHorizontal();
}
public static IContainer ShrinkVertical(this IContainer element)
{
return element.Shrink(x => x.ShrinkVertical = true);
}
public static IContainer ShrinkHorizontal(this IContainer element)
{
return element.Shrink(x => x.ShrinkHorizontal = true);
}
#region Obsolete
[Obsolete("This element has been renamed since version 2022.1. Please use the Shrink method.")]
public static IContainer Box(this IContainer element)
{
return element.Element(new Shrink());
}
[Obsolete("This element has been renamed since version 2022.11. Please use the Shrink method.")]
public static IContainer MinimalBox(this IContainer element)
{
return element.Element(new Shrink());
}
#endregion
}
}
@@ -15,6 +15,17 @@ namespace QuestPDF.Fluent
return descriptor;
}
public static T Fallback<T>(this T descriptor, TextStyle? value = null) where T : TextSpanDescriptor
{
descriptor.TextStyle.Fallback = value;
return descriptor;
}
public static T Fallback<T>(this T descriptor, Func<TextStyle, TextStyle> handler) where T : TextSpanDescriptor
{
return descriptor.Fallback(handler(TextStyle.Default));
}
public static T FontColor<T>(this T descriptor, string value) where T : TextSpanDescriptor
{
descriptor.MutateTextStyle(x => x.FontColor(value));
-1
View File
@@ -10,7 +10,6 @@ namespace QuestPDF.Infrastructure
void DrawRectangle(Position vector, Size size, string color);
void DrawText(SKTextBlob skTextBlob, Position position, TextStyle style);
void DrawImage(SKImage image, Position position, Size size);
void DrawPicture(SKPicture picture);
void DrawHyperlink(string url, Size size);
void DrawSectionLink(string sectionName, Size size);