Fixed: AspectRatio behaviour does not take into account child measurement. Added tests for AspectRatio, Image and DynamicImage elements. Small TestPlan framework improvements.

This commit is contained in:
MarcinZiabek 2021-03-23 18:05:39 +01:00
Родитель 08126b2fa4
Коммит c5cb588857
19 изменённых файлов: 464 добавлений и 152 удалений

Просмотреть файл

@ -13,7 +13,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuestPDF.InvoiceSample\QuestPDF.InvoiceSample.csproj" />
<ProjectReference Include="..\QuestPDF\QuestPDF.csproj" />
</ItemGroup>

Просмотреть файл

@ -21,10 +21,10 @@ namespace QuestPDF.UnitTests
TestPlan
.For(x => new Alignment
{
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.MeasureElement(new Size(1000, 500))
.ExpectChildMeasure("child", expectedInput: new Size(1000, 500), returns: new Wrap())
.ExpectChildMeasure(expectedInput: new Size(1000, 500), returns: new Wrap())
.CheckMeasureResult(new Wrap());
}
@ -37,12 +37,12 @@ namespace QuestPDF.UnitTests
Horizontal = HorizontalAlignment.Center,
Vertical = VerticalAlignment.Middle,
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.DrawElement(new Size(1000, 500))
.ExpectChildMeasure("child", expectedInput: new Size(1000, 500), returns: new PartialRender(new Size(400, 200)))
.ExpectChildMeasure(expectedInput: new Size(1000, 500), returns: new PartialRender(new Size(400, 200)))
.ExpectCanvasTranslate(new Position(300, 150))
.ExpectChildDraw("child", new Size(400, 200))
.ExpectChildDraw(new Size(400, 200))
.ExpectCanvasTranslate(new Position(-300, -150))
.CheckDrawResult();
}
@ -56,12 +56,12 @@ namespace QuestPDF.UnitTests
Horizontal = HorizontalAlignment.Left,
Vertical = VerticalAlignment.Middle,
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("child", expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectCanvasTranslate(new Position(0, 125))
.ExpectChildDraw("child", new Size(100, 50))
.ExpectChildDraw(new Size(100, 50))
.ExpectCanvasTranslate(new Position(0, -125))
.CheckDrawResult();
}
@ -75,12 +75,12 @@ namespace QuestPDF.UnitTests
Horizontal = HorizontalAlignment.Center,
Vertical = VerticalAlignment.Bottom,
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("child", expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectCanvasTranslate(new Position(150, 250))
.ExpectChildDraw("child", new Size(100, 50))
.ExpectChildDraw(new Size(100, 50))
.ExpectCanvasTranslate(new Position(-150, -250))
.CheckDrawResult();
}
@ -94,12 +94,12 @@ namespace QuestPDF.UnitTests
Horizontal = HorizontalAlignment.Right,
Vertical = VerticalAlignment.Top,
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("child", expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectCanvasTranslate(new Position(300, 0))
.ExpectChildDraw("child", new Size(100, 50))
.ExpectChildDraw(new Size(100, 50))
.ExpectCanvasTranslate(new Position(-300, 0))
.CheckDrawResult();
}

Просмотреть файл

@ -15,5 +15,168 @@ namespace QuestPDF.UnitTests
[Test]
public void Draw_ShouldHandleNullChild() => new AspectRatio().DrawWithoutChild();
[Test]
public void Measure_FitWidth_EnoughSpace_FullRender()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
public void Measure_FitWidth_EnoughSpace_PartialRender()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), new PartialRender(100, 50))
.CheckMeasureResult(new PartialRender(400, 200));
}
[Test]
public void Measure_FitWidth_EnoughSpace_Wrap()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_FitWidth_EnoughSpace()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitWidth,
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
public void Measure_FitWidth_NotEnoughSpace()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitWidth,
Ratio = 2f
})
.MeasureElement(new Size(400, 199))
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_FitHeight_EnoughSpace()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitHeight,
Ratio = 2f
})
.MeasureElement(new Size(401, 200))
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
public void Measure_FitHeight_NotEnoughSpace()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitHeight,
Ratio = 2f
})
.MeasureElement(new Size(399, 200))
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_FitArea_ToWidth()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
public void Measure_FitArea_ToHeight()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.MeasureElement(new Size(500, 200))
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
public void DrawChild_PerWidth()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.DrawElement(new Size(500, 200))
.ExpectChildDraw(new Size(400, 200))
.CheckDrawResult();
}
[Test]
public void DrawChild_PerHeight()
{
TestPlan
.For(x => new AspectRatio
{
Child = x.CreateChild(),
Option = AspectRatioOption.FitArea,
Ratio = 2f
})
.DrawElement(new Size(400, 300))
.ExpectChildDraw(new Size(400, 200))
.CheckDrawResult();
}
}
}

Просмотреть файл

@ -31,11 +31,11 @@ namespace QuestPDF.UnitTests
.For(x => new Background
{
Color = "#F00",
Child = x.CreateChild("a")
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), "#F00")
.ExpectChildDraw("a", new Size(400, 300))
.ExpectChildDraw(new Size(400, 300))
.CheckDrawResult();
}
}

Просмотреть файл

@ -23,10 +23,10 @@ namespace QuestPDF.UnitTests
Bottom = 30,
Left = 40,
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("child", expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.CheckMeasureResult( new FullRender(new Size(100, 50)));
}
@ -43,15 +43,15 @@ namespace QuestPDF.UnitTests
Color = "#FF0000",
Child = x.CreateChild("child")
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildDraw("child", new Size(400, 300))
.ExpectChildDraw(new Size(400, 300))
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(430, 10), "#FF0000") // top
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(40, 320), "#FF0000") // left
.ExpectCanvasDrawRectangle(new Position(-20, 285), new Size(430, 30), "#FF0000") // bottom
.ExpectCanvasDrawRectangle(new Position(390, -5), new Size(20, 320), "#FF0000") // right
.ExpectChildDraw("child", new Size(400, 300))
.ExpectChildDraw(new Size(400, 300))
.CheckDrawResult();
}
}

Просмотреть файл

@ -34,10 +34,10 @@ namespace QuestPDF.UnitTests
.For(x => new Constrained
{
MinHeight = 100,
Child = x.CreateChild("a")
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure("a", new Size(400, 200), new FullRender(400, 50))
.ExpectChildMeasure(new Size(400, 200), new FullRender(400, 50))
.CheckMeasureResult(new FullRender(400, 100));
}
@ -48,10 +48,10 @@ namespace QuestPDF.UnitTests
.For(x => new Constrained
{
MinHeight = 100,
Child = x.CreateChild("a")
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure("a", new Size(400, 200), new FullRender(400, 150))
.ExpectChildMeasure(new Size(400, 200), new FullRender(400, 150))
.CheckMeasureResult(new FullRender(400, 150));
}
@ -74,10 +74,10 @@ namespace QuestPDF.UnitTests
.For(x => new Constrained
{
MaxHeight = 100,
Child = x.CreateChild("a")
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure("a", new Size(400, 100), new PartialRender(400, 75))
.ExpectChildMeasure(new Size(400, 100), new PartialRender(400, 75))
.CheckMeasureResult(new PartialRender(400, 75));
}
@ -88,10 +88,10 @@ namespace QuestPDF.UnitTests
.For(x => new Constrained
{
MaxHeight = 100,
Child = x.CreateChild("a")
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure("a", new Size(400, 100), new Wrap())
.ExpectChildMeasure(new Size(400, 100), new Wrap())
.CheckMeasureResult(new Wrap());
}
}

Просмотреть файл

@ -1,10 +1,86 @@
using NUnit.Framework;
using System;
using FluentAssertions;
using NUnit.Framework;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
using SkiaSharp;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class DynamicImageTests
{
[Test]
public void Measure_TakesAvailableSpaceRegardlessOfSize()
{
TestPlan
.For(x => new DynamicImage
{
Source = GenerateImage
})
.MeasureElement(new Size(300, 200))
.CheckMeasureResult(new FullRender(300, 200));
}
[Test]
public void Draw_HandlesNull()
{
TestPlan
.For(x => new DynamicImage
{
Source = size => null
})
.DrawElement(new Size(300, 200))
.CheckDrawResult();
}
[Test]
public void Draw_PreservesSize()
{
TestPlan
.For(x => new DynamicImage
{
Source = GenerateImage
})
.DrawElement(new Size(300, 200))
.ExpectCanvasDrawImage(Position.Zero, new Size(300, 200))
.CheckDrawResult();
}
[Test]
public void Draw_PassesCorrectSizeToSource()
{
Size passedSize = null;
TestPlan
.For(x => new DynamicImage
{
Source = size =>
{
passedSize = size;
return GenerateImage(size);
}
})
.DrawElement(new Size(400, 300))
.ExpectCanvasDrawImage(Position.Zero, new Size(400, 300))
.CheckDrawResult();
passedSize.Should().Be(new Size(400, 300));
}
byte[] GenerateImage(Size size)
{
var image = GenerateImage((int) size.Width, (int) size.Height);
return image.Encode(SKEncodedImageFormat.Png, 100).ToArray();
}
SKImage GenerateImage(int width, int height)
{
var imageInfo = new SKImageInfo(width, height);
using var surface = SKSurface.Create(imageInfo);
return surface.Snapshot();
}
}
}

Просмотреть файл

@ -1,10 +0,0 @@
using NUnit.Framework;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class EmptyTests
{
}
}

Просмотреть файл

@ -1,7 +1,12 @@
using Moq;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
using SkiaSharp;
namespace QuestPDF.UnitTests
{
@ -9,17 +14,57 @@ namespace QuestPDF.UnitTests
public class ImageTests
{
[Test]
public void Draw_ShouldHandleNullChild()
{
Assert.DoesNotThrow(() =>
{
var image = new Image()
{
InternalImage = null
};
public void Measure_ShouldHandleNullChild() => new AspectRatio().MeasureWithoutChild();
image.Draw(It.IsAny<ICanvas>(), Size.Zero);
});
[Test]
public void Draw_ShouldHandleNullChild() => new AspectRatio().DrawWithoutChild();
[Test]
public void Measure_TakesAvailableSpaceRegardlessOfSize()
{
TestPlan
.For(x => new Image
{
InternalImage = GenerateImage(400, 300)
})
.MeasureElement(new Size(300, 200))
.CheckMeasureResult(new FullRender(300, 200));
}
[Test]
public void Draw_TakesAvailableSpaceRegardlessOfSize()
{
TestPlan
.For(x => new Image
{
InternalImage = GenerateImage(400, 300)
})
.DrawElement(new Size(300, 200))
.ExpectCanvasDrawImage(new Position(0, 0), new Size(300, 200))
.CheckDrawResult();
}
[Test]
public void Fluent_RecognizesImageProportions()
{
var image = GenerateImage(600, 200).Encode(SKEncodedImageFormat.Png, 100).ToArray();
TestPlan
.For(x =>
{
var container = new Container();
container.Image(image);
return container;
})
.MeasureElement(new Size(300, 200))
.CheckMeasureResult(new FullRender(300, 100));;
}
SKImage GenerateImage(int width, int height)
{
var imageInfo = new SKImageInfo(width, height);
using var surface = SKSurface.Create(imageInfo);
return surface.Snapshot();
}
}
}

Просмотреть файл

@ -17,62 +17,77 @@ namespace QuestPDF.UnitTests
[Test]
public void Draw_ShouldHandleNullChild() => new Padding().DrawWithoutChild();
private Padding GetPadding(Element child)
private Padding GetPadding(TestPlan plan)
{
return new Padding()
{
Top = 5,
Right = 10,
Bottom = 15,
Left = 20,
Top = 10,
Right = 20,
Bottom = 30,
Left = 40,
Child = child
Child = plan.CreateChild()
};
}
[Test]
public void Measure_WhenChildReturnsWrap_ReturnsWrap()
public void Measure_General_EnoughSpace()
{
var child = new Mock<Element>();
child
.Setup(x => x.Measure(It.IsAny<Size>()))
.Returns(() => new Wrap());
GetPadding(child.Object)
.Measure(Size.Zero)
.Should()
.BeOfType<Wrap>();
TestPlan
.For(GetPadding)
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(340, 260), new FullRender(140, 60))
.CheckMeasureResult(new FullRender(200, 100));
}
[Test]
public void Measure_WhenChildReturnsFullRender_ReturnsFullRender()
public void Measure_NotEnoughWidth()
{
var child = new Mock<Element>();
child
.Setup(x => x.Measure(It.IsAny<Size>()))
.Returns(() => new FullRender(Size.Zero));
GetPadding(child.Object)
.Measure(Size.Zero)
.Should()
.BeOfType<FullRender>();
TestPlan
.For(GetPadding)
.MeasureElement(new Size(50, 300))
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_WhenChildReturnsPartialRender_ReturnsPartialRender()
public void Measure_NotEnoughHeight()
{
var child = new Mock<Element>();
TestPlan
.For(GetPadding)
.MeasureElement(new Size(20, 300))
.CheckMeasureResult(new Wrap());
}
child
.Setup(x => x.Measure(It.IsAny<Size>()))
.Returns(() => new PartialRender(Size.Zero));
[Test]
public void Measure_AcceptsPartialRender()
{
TestPlan
.For(GetPadding)
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(340, 260), new PartialRender(40, 160))
.CheckMeasureResult(new PartialRender(100, 200));
}
GetPadding(child.Object)
.Measure(Size.Zero)
.Should()
.BeOfType<PartialRender>();
[Test]
public void Measure_AcceptsWrap()
{
TestPlan
.For(GetPadding)
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(340, 260), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Draw_General()
{
TestPlan
.For(GetPadding)
.DrawElement(new Size(400, 300))
.ExpectCanvasTranslate(new Position(40, 10))
.ExpectChildDraw(new Size(340, 260))
.ExpectCanvasTranslate(new Position(-40, -10))
.CheckDrawResult();
}
}
}

Просмотреть файл

@ -1,10 +0,0 @@
using NUnit.Framework;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class PlaceholderTests
{
}
}

Просмотреть файл

@ -42,7 +42,7 @@ namespace QuestPDF.UnitTests
TestPlan
.For(x => new ShowOnce()
{
Child = x.CreateChild("child")
Child = x.CreateChild()
})
// Measure the element and return result
@ -52,21 +52,21 @@ namespace QuestPDF.UnitTests
// Draw element partially
.DrawElement(new Size(200, 200))
.ExpectChildMeasure("child", new Size(200, 200), new PartialRender(new Size(200, 200)))
.ExpectChildDraw("child", new Size(200, 200))
.ExpectChildMeasure(new Size(200, 200), new PartialRender(new Size(200, 200)))
.ExpectChildDraw(new Size(200, 200))
.CheckDrawResult()
// Element was not fully drawn
// It should be measured again for rendering on next page
.MeasureElement(new Size(800, 200))
.ExpectChildMeasure("child", new Size(800, 200), new FullRender(new Size(400, 200)))
.ExpectChildMeasure(new Size(800, 200), new FullRender(new Size(400, 200)))
.CheckMeasureResult(new FullRender(new Size(400, 200)))
// Draw element on next page
// Element was fully drawn at this point
.DrawElement(new Size(400, 200))
.ExpectChildMeasure("child", new Size(400, 200), new FullRender(new Size(400, 200)))
.ExpectChildDraw("child", new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), new FullRender(new Size(400, 200)))
.ExpectChildDraw(new Size(400, 200))
.CheckDrawResult()
// In the next attempt of measuring element, it should behave like empty parent.

Просмотреть файл

@ -10,6 +10,8 @@ namespace QuestPDF.UnitTests.TestEngine
{
internal class TestPlan
{
private const string DefaultChildName = "child";
private Element Element { get; set; }
private ICanvas Canvas { get; }
@ -101,6 +103,8 @@ namespace QuestPDF.UnitTests.TestEngine
};
}
public Element CreateChild() => CreateChild(DefaultChildName);
public Element CreateChild(string id)
{
return new ElementMock
@ -153,11 +157,21 @@ namespace QuestPDF.UnitTests.TestEngine
return this;
}
public TestPlan ExpectChildMeasure(Size expectedInput, ISpacePlan returns)
{
return ExpectChildMeasure(DefaultChildName, expectedInput, returns);
}
public TestPlan ExpectChildMeasure(string child, Size expectedInput, ISpacePlan returns)
{
return AddOperation(new ChildMeasureOperationBase(child, expectedInput, returns));
}
public TestPlan ExpectChildDraw(Size expectedInput)
{
return ExpectChildDraw(DefaultChildName, expectedInput);
}
public TestPlan ExpectChildDraw(string child, Size expectedInput)
{
return AddOperation(new ChildDrawOperationBase(child, expectedInput));

Просмотреть файл

@ -14,15 +14,26 @@ namespace QuestPDF.Elements
if(Child == null)
return new FullRender(Size.Zero);
var size = GetTargetSize(availableSpace);
var targetSize = GetTargetSize(availableSpace);
if (size.Height > availableSpace.Height + Size.Epsilon)
if (targetSize.Height > availableSpace.Height + Size.Epsilon)
return new Wrap();
if (size.Width > availableSpace.Width + Size.Epsilon)
if (targetSize.Width > availableSpace.Width + Size.Epsilon)
return new Wrap();
return new FullRender(size);
var childSize = Child.Measure(targetSize);
if (childSize is Wrap)
return new Wrap();
if (childSize is PartialRender)
return new PartialRender(targetSize);
if (childSize is FullRender)
return new FullRender(targetSize);
throw new NotSupportedException();
}
internal override void Draw(ICanvas canvas, Size availableSpace)

Просмотреть файл

@ -11,9 +11,6 @@ namespace QuestPDF.Elements
internal override ISpacePlan Measure(Size availableSpace)
{
if (availableSpace.Width < 0 || availableSpace.Height < 0)
return new Wrap();
return new FullRender(availableSpace.Width, availableSpace.Height);
}

Просмотреть файл

@ -17,6 +17,10 @@ namespace QuestPDF.Elements
return new FullRender(Size.Zero);
var internalSpace = InternalSpace(availableSpace);
if (internalSpace.Width <= 0 || internalSpace.Height <= 0)
return new Wrap();
var measure = Child.Measure(internalSpace) as Size;
if (measure == null)

Просмотреть файл

@ -14,8 +14,6 @@ namespace QuestPDF.Elements
public void Compose(IContainer container)
{
// TODO: consider moving this element into fluent API
container
.Background("CCC")
.AlignMiddle()

Просмотреть файл

@ -49,44 +49,6 @@ namespace QuestPDF.Fluent
return parent.Element(new Debug());
}
public static void Image(this IContainer parent, byte[] data, ImageScaling scaling = ImageScaling.FitWidth)
{
if (data == null)
return;
var image = SKImage.FromEncodedData(data);
var aspectRatio = image.Width / (float)image.Height;
var imageElement = new Image
{
InternalImage = image
};
if (scaling != ImageScaling.Resize)
parent = parent.AspectRatio(aspectRatio, Map(scaling));
parent.Element(imageElement);
static AspectRatioOption Map(ImageScaling scaling)
{
return scaling switch
{
ImageScaling.FitWidth => AspectRatioOption.FitWidth,
ImageScaling.FitHeight => AspectRatioOption.FitHeight,
ImageScaling.FitArea => AspectRatioOption.FitArea,
_ => throw new ArgumentOutOfRangeException()
};
}
}
public static void DynamicImage(this IContainer element, Func<Size, byte[]> imageSource)
{
element.Element(new DynamicImage
{
Source = imageSource
});
}
public static void PageNumber(this IContainer element, string textFormat = "{number}", TextStyle? style = null)
{
element.Element(new PageNumber

Просмотреть файл

@ -0,0 +1,48 @@
using System;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Fluent
{
public static class ImageExtensions
{
public static void Image(this IContainer parent, byte[] data, ImageScaling scaling = ImageScaling.FitWidth)
{
if (data == null)
return;
var image = SKImage.FromEncodedData(data);
var aspectRatio = image.Width / (float)image.Height;
var imageElement = new Image
{
InternalImage = image
};
if (scaling != ImageScaling.Resize)
parent = parent.AspectRatio(aspectRatio, Map(scaling));
parent.Element(imageElement);
static AspectRatioOption Map(ImageScaling scaling)
{
return scaling switch
{
ImageScaling.FitWidth => AspectRatioOption.FitWidth,
ImageScaling.FitHeight => AspectRatioOption.FitHeight,
ImageScaling.FitArea => AspectRatioOption.FitArea,
_ => throw new ArgumentOutOfRangeException()
};
}
}
public static void DynamicImage(this IContainer element, Func<Size, byte[]> imageSource)
{
element.Element(new DynamicImage
{
Source = imageSource
});
}
}
}