Implemented experiment
This commit is contained in:
@@ -17,7 +17,7 @@ namespace QuestPDF.Examples
|
||||
.PageSize(PageSizes.A4)
|
||||
.ShowResults()
|
||||
.MaxPages(10_000)
|
||||
.EnableCaching(true)
|
||||
//.EnableCaching(true)
|
||||
.EnableDebugging(false)
|
||||
.Render(container =>
|
||||
{
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace QuestPDF.ReportSample
|
||||
HeaderFields = HeaderFields(),
|
||||
|
||||
LogoData = Helpers.GetImage("Logo.png"),
|
||||
Sections = Enumerable.Range(0, 40).Select(x => GenerateSection()).ToList(),
|
||||
Photos = Enumerable.Range(0, 25).Select(x => GetReportPhotos()).ToList()
|
||||
Sections = Enumerable.Range(0, 2000).Select(x => GenerateSection()).ToList(),
|
||||
Photos = Enumerable.Range(0, 200).Select(x => GetReportPhotos()).ToList()
|
||||
};
|
||||
|
||||
List<ReportHeaderField> HeaderFields()
|
||||
|
||||
@@ -24,7 +24,10 @@ namespace QuestPDF.ReportSample
|
||||
[Test]
|
||||
public void GenerateAndShowPdf()
|
||||
{
|
||||
//ImagePlaceholder.Solid = true;
|
||||
Settings.DocumentLayoutExceptionThreshold = 10_000;
|
||||
Settings.EnableCaching = true;
|
||||
Settings.EnableDebugging = false;
|
||||
ImagePlaceholder.Solid = true;
|
||||
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"test_result.pdf");
|
||||
Report.GeneratePdf(path);
|
||||
|
||||
@@ -20,6 +20,7 @@ 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,7 +18,8 @@ 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();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using QuestPDF.Drawing.Exceptions;
|
||||
@@ -67,13 +68,24 @@ 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)
|
||||
|
||||
@@ -51,6 +51,11 @@ namespace QuestPDF.Drawing
|
||||
|
||||
}
|
||||
|
||||
public void DrawPicture(SKPicture picture)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DrawHyperlink(string url, Size size)
|
||||
{
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ 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);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
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() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ namespace QuestPDF.Elements
|
||||
public void Compose(IContainer container)
|
||||
{
|
||||
container
|
||||
//.Element(new DrawingCache())
|
||||
.Background(BackgroundColor)
|
||||
.Layers(layers =>
|
||||
{
|
||||
|
||||
@@ -15,17 +15,6 @@ 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));
|
||||
|
||||
@@ -10,6 +10,7 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user