Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e18b5170e6 | |||
| 5010b61565 | |||
| 44d7538578 | |||
| f8d270bd2a | |||
| b894262f7e | |||
| 4423774648 | |||
| 5d4f1f530a | |||
| 3ba8185871 | |||
| b6e0bd505c | |||
| f884547d16 | |||
| 4a7f9385c4 | |||
| f4181de3d2 | |||
| 4e3ba1d878 | |||
| 6f0c6513da |
@@ -1,5 +1,7 @@
|
|||||||
|
using System.Linq;
|
||||||
using QuestPDF.Examples.Engine;
|
using QuestPDF.Examples.Engine;
|
||||||
using QuestPDF.Fluent;
|
using QuestPDF.Fluent;
|
||||||
|
using QuestPDF.Helpers;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
@@ -135,18 +137,20 @@ namespace QuestPDF.Examples
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//[ShowResult]
|
[ShowResult]
|
||||||
[ImageSize(300, 200)]
|
[ImageSize(210, 210)]
|
||||||
public void Debug(IContainer container)
|
public void Debug(IContainer container)
|
||||||
{
|
{
|
||||||
container
|
container
|
||||||
.Padding(25)
|
.Padding(25)
|
||||||
.Debug()
|
.Debug("Grid example", Colors.Blue.Medium)
|
||||||
.Padding(-5)
|
.Grid(grid =>
|
||||||
.Row(row =>
|
|
||||||
{
|
{
|
||||||
row.RelativeColumn().Padding(5).Extend().Placeholder();
|
grid.Columns(3);
|
||||||
row.RelativeColumn().Padding(5).Extend().Placeholder();
|
grid.Spacing(5);
|
||||||
|
|
||||||
|
foreach (var _ in Enumerable.Range(0, 8))
|
||||||
|
grid.Item().Height(50).Placeholder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +182,8 @@ namespace QuestPDF.Examples
|
|||||||
.AlignRight()
|
.AlignRight()
|
||||||
.Grid(grid =>
|
.Grid(grid =>
|
||||||
{
|
{
|
||||||
grid.Spacing(5);
|
grid.VerticalSpacing(20);
|
||||||
|
grid.HorizontalSpacing(10);
|
||||||
grid.Columns(12);
|
grid.Columns(12);
|
||||||
|
|
||||||
grid.Item(8).Background("#DDD").Height(50).Padding(5).Text("This is a short text", textStyle);
|
grid.Item(8).Background("#DDD").Height(50).Padding(5).Text("This is a short text", textStyle);
|
||||||
@@ -189,8 +194,95 @@ namespace QuestPDF.Examples
|
|||||||
grid.Item(8).Background("#DDD").Height(50);
|
grid.Item(8).Background("#DDD").Height(50);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//[ShowResult]
|
||||||
|
[ImageSize(300, 300)]
|
||||||
|
public void RandomColorMatrix(IContainer container)
|
||||||
|
{
|
||||||
|
container
|
||||||
|
.Padding(25)
|
||||||
|
.Grid(grid =>
|
||||||
|
{
|
||||||
|
grid.Columns(5);
|
||||||
|
|
||||||
|
Enumerable
|
||||||
|
.Range(0, 25)
|
||||||
|
.Select(x => Placeholders.BackgroundColor())
|
||||||
|
.ToList()
|
||||||
|
.ForEach(x => grid.Item().Height(50).Background(x));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[ShowResult]
|
//[ShowResult]
|
||||||
|
[ImageSize(450, 150)]
|
||||||
|
public void DefinedColors(IContainer container)
|
||||||
|
{
|
||||||
|
var colors = new[]
|
||||||
|
{
|
||||||
|
Colors.Green.Darken4,
|
||||||
|
Colors.Green.Darken3,
|
||||||
|
Colors.Green.Darken2,
|
||||||
|
Colors.Green.Darken1,
|
||||||
|
|
||||||
|
Colors.Green.Medium,
|
||||||
|
|
||||||
|
Colors.Green.Lighten1,
|
||||||
|
Colors.Green.Lighten2,
|
||||||
|
Colors.Green.Lighten3,
|
||||||
|
Colors.Green.Lighten4,
|
||||||
|
Colors.Green.Lighten5,
|
||||||
|
|
||||||
|
Colors.Green.Accent1,
|
||||||
|
Colors.Green.Accent2,
|
||||||
|
Colors.Green.Accent3,
|
||||||
|
Colors.Green.Accent4,
|
||||||
|
};
|
||||||
|
|
||||||
|
container
|
||||||
|
.Padding(25)
|
||||||
|
.Height(100)
|
||||||
|
.Row(row =>
|
||||||
|
{
|
||||||
|
foreach (var color in colors)
|
||||||
|
row.RelativeColumn().Background(color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//[ShowResult]
|
||||||
|
[ImageSize(500, 175)]
|
||||||
|
public void DefinedFonts(IContainer container)
|
||||||
|
{
|
||||||
|
var fonts = new[]
|
||||||
|
{
|
||||||
|
Fonts.Calibri,
|
||||||
|
Fonts.Candara,
|
||||||
|
Fonts.Arial,
|
||||||
|
Fonts.TimesNewRoman,
|
||||||
|
Fonts.Consolas,
|
||||||
|
Fonts.Tahoma,
|
||||||
|
Fonts.Impact,
|
||||||
|
Fonts.Trebuchet,
|
||||||
|
Fonts.ComicSans
|
||||||
|
};
|
||||||
|
|
||||||
|
container
|
||||||
|
.Padding(25)
|
||||||
|
.Grid(grid =>
|
||||||
|
{
|
||||||
|
grid.Columns(3);
|
||||||
|
|
||||||
|
foreach (var font in fonts)
|
||||||
|
{
|
||||||
|
grid.Item()
|
||||||
|
.Border(1)
|
||||||
|
.BorderColor(Colors.Grey.Medium)
|
||||||
|
.Padding(10)
|
||||||
|
.Text(font, TextStyle.Default.FontType(font).Size(16));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//[ShowResult]
|
||||||
[ImageSize(300, 300)]
|
[ImageSize(300, 300)]
|
||||||
public void Layers(IContainer container)
|
public void Layers(IContainer container)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using QuestPDF.Elements;
|
||||||
|
using QuestPDF.Examples.Engine;
|
||||||
|
using QuestPDF.Fluent;
|
||||||
|
using QuestPDF.Helpers;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace QuestPDF.Examples
|
||||||
|
{
|
||||||
|
public class TextExample : ExampleTestBase
|
||||||
|
{
|
||||||
|
[ShowResult]
|
||||||
|
[ImageSize(1400, 600)]
|
||||||
|
public void OldText(IContainer container)
|
||||||
|
{
|
||||||
|
var fonts = new[]
|
||||||
|
{
|
||||||
|
Fonts.Arial,
|
||||||
|
Fonts.Calibri,
|
||||||
|
Fonts.Cambria,
|
||||||
|
Fonts.Candara,
|
||||||
|
Fonts.ComicSans,
|
||||||
|
Fonts.Consolas,
|
||||||
|
Fonts.Corbel,
|
||||||
|
Fonts.Courier,
|
||||||
|
Fonts.CourierNew,
|
||||||
|
Fonts.Georgia,
|
||||||
|
Fonts.Impact,
|
||||||
|
Fonts.LucidaConsole,
|
||||||
|
Fonts.SegoeSD,
|
||||||
|
Fonts.SegoeUI,
|
||||||
|
Fonts.Tahoma,
|
||||||
|
Fonts.TimesNewRoman,
|
||||||
|
Fonts.TimesRoman,
|
||||||
|
Fonts.Trebuchet,
|
||||||
|
Fonts.Verdana,
|
||||||
|
};
|
||||||
|
|
||||||
|
container
|
||||||
|
.Padding(50)
|
||||||
|
.Grid(stack =>
|
||||||
|
{
|
||||||
|
stack.Spacing(10);
|
||||||
|
stack.Columns(2);
|
||||||
|
|
||||||
|
foreach (var font in fonts)
|
||||||
|
{
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
.Background(Placeholders.BackgroundColor())
|
||||||
|
.Text($"Lorem ipsum dolor sit amet {font}", TextStyle.Default.Size(24).FontType(font));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//[ShowResult]
|
||||||
|
[ImageSize(1400, 800)]
|
||||||
|
public void Test(IContainer container)
|
||||||
|
{
|
||||||
|
List<TextElement> Lorem()
|
||||||
|
{
|
||||||
|
return new List<TextElement>
|
||||||
|
{
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = "Podstawowy łaciński Tabela znaków Unicode"
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.FontType("Segoe UI Emoji").Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = "✔"
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.FontType("Segoe UI Emoji").Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = "🥛"
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.FontType("Segoe UI Emoji").Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = "🧀"
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.FontType("Segoe UI Emoji").Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = "❤🚵♀️"
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = "Lorem ipsum "
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.Size(24).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = " dolor "
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.Size(64).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = " sijt "
|
||||||
|
},
|
||||||
|
new TextElement()
|
||||||
|
{
|
||||||
|
Style = TextStyle.Default.Size(32).BackgroundColor(Placeholders.BackgroundColor()),
|
||||||
|
Text = " amet"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Func<List<TextElement>> Source = () => Split(RandomText());
|
||||||
|
|
||||||
|
container
|
||||||
|
.Padding(50)
|
||||||
|
.Box().Border(1).Stack(stack =>
|
||||||
|
{
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
//.Background(Placeholders.BackgroundColor())
|
||||||
|
.Element(new TextRun()
|
||||||
|
{
|
||||||
|
Elements = Lorem()
|
||||||
|
});
|
||||||
|
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
//.Background(Placeholders.BackgroundColor())
|
||||||
|
.Element(new TextRun()
|
||||||
|
{
|
||||||
|
Elements = Source()
|
||||||
|
});
|
||||||
|
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
//.Background(Placeholders.BackgroundColor())
|
||||||
|
.Element(new TextRun()
|
||||||
|
{
|
||||||
|
Elements = Source()
|
||||||
|
});
|
||||||
|
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
//.Background(Placeholders.BackgroundColor())
|
||||||
|
.Element(new TextRun()
|
||||||
|
{
|
||||||
|
Elements = Source()
|
||||||
|
});
|
||||||
|
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
//.Background(Placeholders.BackgroundColor())
|
||||||
|
.Element(new TextRun()
|
||||||
|
{
|
||||||
|
Elements = Source()
|
||||||
|
});
|
||||||
|
|
||||||
|
stack
|
||||||
|
.Element()
|
||||||
|
.Box()
|
||||||
|
//.Background(Placeholders.BackgroundColor())
|
||||||
|
.Element(new TextRun()
|
||||||
|
{
|
||||||
|
Elements = Source()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TextElement> RandomText()
|
||||||
|
{
|
||||||
|
var sizes = new[] { 24, 32, 48, 64};
|
||||||
|
|
||||||
|
return Placeholders
|
||||||
|
.Sentence()
|
||||||
|
.Split(" ")
|
||||||
|
.Select(x => new TextElement
|
||||||
|
{
|
||||||
|
Text = $"{x} ",
|
||||||
|
Style = TextStyle
|
||||||
|
.Default
|
||||||
|
//.Size(sizes[Placeholders.Random.Next(0, 3)])
|
||||||
|
.Size(24)
|
||||||
|
.BackgroundColor(Placeholders.BackgroundColor())
|
||||||
|
//.LineHeight((float)Placeholders.Random.NextDouble() / 2 + 1f)
|
||||||
|
.LineHeight(1.2f)
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TextElement> Split(List<TextElement> elements)
|
||||||
|
{
|
||||||
|
return elements
|
||||||
|
.SelectMany(x => x
|
||||||
|
.Text
|
||||||
|
.Select(y => new TextElement
|
||||||
|
{
|
||||||
|
Style = x.Style,
|
||||||
|
Text = y.ToString()
|
||||||
|
}))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,8 +18,8 @@ namespace QuestPDF.ReportSample
|
|||||||
HeaderFields = HeaderFields(),
|
HeaderFields = HeaderFields(),
|
||||||
|
|
||||||
LogoData = Helpers.GetImage("Logo.png"),
|
LogoData = Helpers.GetImage("Logo.png"),
|
||||||
Sections = Enumerable.Range(0, 8).Select(x => GenerateSection()).ToList(),
|
Sections = Enumerable.Range(0, 50).Select(x => GenerateSection()).ToList(),
|
||||||
Photos = Enumerable.Range(2, 6).Select(x => GetReportPhotos()).ToList()
|
Photos = Enumerable.Range(0, 30).Select(x => GetReportPhotos()).ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
List<ReportHeaderField> HeaderFields()
|
List<ReportHeaderField> HeaderFields()
|
||||||
@@ -52,8 +52,8 @@ namespace QuestPDF.ReportSample
|
|||||||
ReportSection GenerateSection()
|
ReportSection GenerateSection()
|
||||||
{
|
{
|
||||||
var sectionLength = Helpers.Random.NextDouble() > 0.75
|
var sectionLength = Helpers.Random.NextDouble() > 0.75
|
||||||
? Helpers.Random.Next(10, 20)
|
? Helpers.Random.Next(20, 40)
|
||||||
: Helpers.Random.Next(3, 11);
|
: Helpers.Random.Next(5, 10);
|
||||||
|
|
||||||
return new ReportSection
|
return new ReportSection
|
||||||
{
|
{
|
||||||
@@ -100,8 +100,7 @@ namespace QuestPDF.ReportSample
|
|||||||
{
|
{
|
||||||
Label = "Photos",
|
Label = "Photos",
|
||||||
Photos = Enumerable
|
Photos = Enumerable
|
||||||
.Range(0, Helpers.Random.Next(1, 10))
|
.Range(0, Helpers.Random.Next(1, 15))
|
||||||
.Select(x => Helpers.Random.Next(0, 128))
|
|
||||||
.Select(x => Placeholders.Image(400, 300))
|
.Select(x => Placeholders.Image(400, 300))
|
||||||
.ToList()
|
.ToList()
|
||||||
};
|
};
|
||||||
@@ -111,7 +110,7 @@ namespace QuestPDF.ReportSample
|
|||||||
{
|
{
|
||||||
return new ReportPhoto()
|
return new ReportPhoto()
|
||||||
{
|
{
|
||||||
PhotoData = Placeholders.Image(400, 300),
|
PhotoData = Placeholders.Image(800, 600),
|
||||||
|
|
||||||
Comments = Placeholders.Sentence(),
|
Comments = Placeholders.Sentence(),
|
||||||
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
|
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace QuestPDF.ReportSample.Layouts
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
container.Debug("Photo gallery").Grid(grid =>
|
container.Debug("Photos").Grid(grid =>
|
||||||
{
|
{
|
||||||
grid.Spacing(5);
|
grid.Spacing(5);
|
||||||
grid.Columns(3);
|
grid.Columns(3);
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ namespace QuestPDF.ReportSample
|
|||||||
[Test]
|
[Test]
|
||||||
public void PerformanceBenchmark()
|
public void PerformanceBenchmark()
|
||||||
{
|
{
|
||||||
|
// target document length should be around 100 pages
|
||||||
|
|
||||||
// test size
|
// test size
|
||||||
const int testSize = 100;
|
const int testSize = 100;
|
||||||
const decimal performanceTarget = 5; // documents per second
|
const decimal performanceTarget = 1; // documents per second
|
||||||
|
|
||||||
// create report models
|
// create report models
|
||||||
var reports = Enumerable
|
var reports = Enumerable
|
||||||
|
|||||||
+105
-34
@@ -1,4 +1,5 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using FluentAssertions.Equivalency;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Fluent;
|
using QuestPDF.Fluent;
|
||||||
@@ -6,7 +7,7 @@ using QuestPDF.UnitTests.TestEngine;
|
|||||||
|
|
||||||
namespace QuestPDF.UnitTests
|
namespace QuestPDF.UnitTests
|
||||||
{
|
{
|
||||||
/*[TestFixture]
|
[TestFixture]
|
||||||
public class GridTests
|
public class GridTests
|
||||||
{
|
{
|
||||||
#region Alignment
|
#region Alignment
|
||||||
@@ -39,30 +40,30 @@ namespace QuestPDF.UnitTests
|
|||||||
// assert
|
// assert
|
||||||
var expected = new Container();
|
var expected = new Container();
|
||||||
|
|
||||||
expected.Stack(stack =>
|
expected.Container().Stack(stack =>
|
||||||
{
|
{
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(6).Element(childA);
|
row.RelativeColumn(6).Container().Element(childA);
|
||||||
row.RelativeColumn(4).Element(childB);
|
row.RelativeColumn(4).Container().Element(childB);
|
||||||
row.RelativeColumn(2).Element(Empty.Instance);
|
row.RelativeColumn(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(4).Element(childC);
|
row.RelativeColumn(4).Container().Element(childC);
|
||||||
row.RelativeColumn(2).Element(childD);
|
row.RelativeColumn(2).Container().Element(childD);
|
||||||
row.RelativeColumn(6).Element(Empty.Instance);
|
row.RelativeColumn(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(8).Element(childE);
|
row.RelativeColumn(8).Container().Element(childE);
|
||||||
row.RelativeColumn(4).Element(Empty.Instance);
|
row.RelativeColumn(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
structure.Child.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering().IncludingAllRuntimeProperties());
|
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -93,33 +94,33 @@ namespace QuestPDF.UnitTests
|
|||||||
// assert
|
// assert
|
||||||
var expected = new Container();
|
var expected = new Container();
|
||||||
|
|
||||||
expected.Stack(stack =>
|
expected.Container().Stack(stack =>
|
||||||
{
|
{
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(1).Element(Empty.Instance);
|
row.RelativeColumn(1);
|
||||||
row.RelativeColumn(6).Element(childA);
|
row.RelativeColumn(6).Container().Element(childA);
|
||||||
row.RelativeColumn(4).Element(childB);
|
row.RelativeColumn(4).Container().Element(childB);
|
||||||
row.RelativeColumn(1).Element(Empty.Instance);
|
row.RelativeColumn(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(3).Element(Empty.Instance);
|
row.RelativeColumn(3);
|
||||||
row.RelativeColumn(4).Element(childC);
|
row.RelativeColumn(4).Container().Element(childC);
|
||||||
row.RelativeColumn(2).Element(childD);
|
row.RelativeColumn(2).Container().Element(childD);
|
||||||
row.RelativeColumn(3).Element(Empty.Instance);
|
row.RelativeColumn(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(2).Element(Empty.Instance);
|
row.RelativeColumn(2);
|
||||||
row.RelativeColumn(8).Element(childE);
|
row.RelativeColumn(8).Container().Element(childE);
|
||||||
row.RelativeColumn(2).Element(Empty.Instance);
|
row.RelativeColumn(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
structure.Child.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering().IncludingAllRuntimeProperties());
|
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -154,28 +155,98 @@ namespace QuestPDF.UnitTests
|
|||||||
{
|
{
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(2).Element(Empty.Instance);
|
row.RelativeColumn(2);
|
||||||
row.RelativeColumn(6).Element(childA);
|
row.RelativeColumn(6).Container().Element(childA);
|
||||||
row.RelativeColumn(4).Element(childB);
|
row.RelativeColumn(4).Container().Element(childB);
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(6).Element(Empty.Instance);
|
row.RelativeColumn(6);
|
||||||
row.RelativeColumn(4).Element(childC);
|
row.RelativeColumn(4).Container().Element(childC);
|
||||||
row.RelativeColumn(2).Element(childD);
|
row.RelativeColumn(2).Container().Element(childD);
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Item().Row(row =>
|
stack.Item().Row(row =>
|
||||||
{
|
{
|
||||||
row.RelativeColumn(4).Element(Empty.Instance);
|
row.RelativeColumn(4);
|
||||||
row.RelativeColumn(8).Element(childE);
|
row.RelativeColumn(8).Container().Element(childE);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
structure.Child.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering().IncludingAllRuntimeProperties());
|
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}*/
|
|
||||||
|
#region Spacing
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Spacing()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var structure = new Container();
|
||||||
|
|
||||||
|
var childA = TestPlan.CreateUniqueElement();
|
||||||
|
var childB = TestPlan.CreateUniqueElement();
|
||||||
|
var childC = TestPlan.CreateUniqueElement();
|
||||||
|
var childD = TestPlan.CreateUniqueElement();
|
||||||
|
|
||||||
|
// act
|
||||||
|
structure
|
||||||
|
.Grid(grid =>
|
||||||
|
{
|
||||||
|
grid.Columns(16);
|
||||||
|
grid.AlignCenter();
|
||||||
|
|
||||||
|
grid.VerticalSpacing(20);
|
||||||
|
grid.HorizontalSpacing(30);
|
||||||
|
|
||||||
|
grid.Item(5).Element(childA);
|
||||||
|
grid.Item(5).Element(childB);
|
||||||
|
grid.Item(10).Element(childC);
|
||||||
|
grid.Item(12).Element(childD);
|
||||||
|
});
|
||||||
|
|
||||||
|
// assert
|
||||||
|
var expected = new Container();
|
||||||
|
|
||||||
|
expected.Container().Stack(stack =>
|
||||||
|
{
|
||||||
|
stack.Spacing(20);
|
||||||
|
|
||||||
|
stack.Item().Row(row =>
|
||||||
|
{
|
||||||
|
row.Spacing(30);
|
||||||
|
|
||||||
|
row.RelativeColumn(3);
|
||||||
|
row.RelativeColumn(5).Container().Element(childA);
|
||||||
|
row.RelativeColumn(5).Container().Element(childB);
|
||||||
|
row.RelativeColumn(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.Item().Row(row =>
|
||||||
|
{
|
||||||
|
row.Spacing(30);
|
||||||
|
|
||||||
|
row.RelativeColumn(3);
|
||||||
|
row.RelativeColumn(10).Container().Element(childC);
|
||||||
|
row.RelativeColumn(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.Item().Row(row =>
|
||||||
|
{
|
||||||
|
row.Spacing(30);
|
||||||
|
|
||||||
|
row.RelativeColumn(2);
|
||||||
|
row.RelativeColumn(12).Container().Element(childD);
|
||||||
|
row.RelativeColumn(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties().AllowingInfiniteRecursion());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ namespace QuestPDF.Drawing
|
|||||||
Typeface = SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant),
|
Typeface = SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant),
|
||||||
TextSize = style.Size,
|
TextSize = style.Size,
|
||||||
TextEncoding = SKTextEncoding.Utf32,
|
TextEncoding = SKTextEncoding.Utf32,
|
||||||
|
|
||||||
TextAlign = style.Alignment switch
|
TextAlign = style.Alignment switch
|
||||||
{
|
{
|
||||||
HorizontalAlignment.Left => SKTextAlign.Left,
|
HorizontalAlignment.Left => SKTextAlign.Left,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace QuestPDF.Elements
|
|||||||
|
|
||||||
container.Stack(stack =>
|
container.Stack(stack =>
|
||||||
{
|
{
|
||||||
stack.Spacing(HorizontalSpacing);
|
stack.Spacing(VerticalSpacing);
|
||||||
|
|
||||||
while (ChildrenQueue.Any())
|
while (ChildrenQueue.Any())
|
||||||
stack.Item().Row(BuildRow);
|
stack.Item().Row(BuildRow);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using QuestPDF.Drawing;
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Drawing.SpacePlan;
|
using QuestPDF.Drawing.SpacePlan;
|
||||||
|
using QuestPDF.Fluent;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
using Size = QuestPDF.Infrastructure.Size;
|
using Size = QuestPDF.Infrastructure.Size;
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ namespace QuestPDF.Elements
|
|||||||
.DefaultIfEmpty(0)
|
.DefaultIfEmpty(0)
|
||||||
.Max();
|
.Max();
|
||||||
|
|
||||||
var realHeight = lines.Count * LineHeight;
|
var paint = Style.ToPaint().FontMetrics;
|
||||||
|
var realHeight = -paint.Ascent + paint.Descent;
|
||||||
|
|
||||||
if (realHeight > availableSpace.Height + Size.Epsilon)
|
if (realHeight > availableSpace.Height + Size.Epsilon)
|
||||||
return new Wrap();
|
return new Wrap();
|
||||||
@@ -34,12 +36,15 @@ namespace QuestPDF.Elements
|
|||||||
|
|
||||||
internal override void Draw(ICanvas canvas, Size availableSpace)
|
internal override void Draw(ICanvas canvas, Size availableSpace)
|
||||||
{
|
{
|
||||||
|
var paint = Style.ToPaint().FontMetrics;
|
||||||
|
var offeset = -paint.Ascent; // paint.Ascent - Style.Size;
|
||||||
|
|
||||||
var lines = BreakLines(availableSpace.Width);
|
var lines = BreakLines(availableSpace.Width);
|
||||||
|
|
||||||
var offsetTop = 0f;
|
var offsetTop = 0f;
|
||||||
var offsetLeft = GetLeftOffset();
|
var offsetLeft = GetLeftOffset();
|
||||||
|
|
||||||
canvas.Translate(new Position(0, Style.Size));
|
canvas.Translate(new Position(0, offeset));
|
||||||
|
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
@@ -47,7 +52,7 @@ namespace QuestPDF.Elements
|
|||||||
offsetTop += LineHeight;
|
offsetTop += LineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.Translate(new Position(0, -Style.Size));
|
canvas.Translate(new Position(0, -offeset));
|
||||||
|
|
||||||
float GetLeftOffset()
|
float GetLeftOffset()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
|
using QuestPDF.Drawing.SpacePlan;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace QuestPDF.Elements
|
||||||
|
{
|
||||||
|
public struct TextMeasurement
|
||||||
|
{
|
||||||
|
public float Width { get; set; }
|
||||||
|
public SKRect Position { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TextElement
|
||||||
|
{
|
||||||
|
public TextStyle Style { get; set; }
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<string, TextMeasurement> Measurements = new ConcurrentDictionary<string, TextMeasurement>();
|
||||||
|
|
||||||
|
public TextMeasurement Measure()
|
||||||
|
{
|
||||||
|
return Measure(Text, Style);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(ICanvas canvas)
|
||||||
|
{
|
||||||
|
(canvas as QuestPDF.Drawing.Canvas).SkiaCanvas.DrawText(Text, 0, 0, Style.ToPaint());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static TextMeasurement Measure(string text, TextStyle style)
|
||||||
|
{
|
||||||
|
var key = $"{text}_{style}";
|
||||||
|
|
||||||
|
return Measurements.GetOrAdd(key, x =>
|
||||||
|
{
|
||||||
|
var rect = new SKRect();
|
||||||
|
var width = style.ToPaint().MeasureText(text, ref rect);
|
||||||
|
|
||||||
|
return new TextMeasurement
|
||||||
|
{
|
||||||
|
Position = rect,
|
||||||
|
Width = width
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
|
using QuestPDF.Drawing.SpacePlan;
|
||||||
|
using QuestPDF.Helpers;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
using SkiaSharp;
|
||||||
|
using SkiaSharp.HarfBuzz;
|
||||||
|
|
||||||
|
namespace QuestPDF.Elements
|
||||||
|
{
|
||||||
|
internal class TextRun : Element
|
||||||
|
{
|
||||||
|
public List<TextElement> Elements = new List<TextElement>();
|
||||||
|
|
||||||
|
internal override ISpacePlan Measure(Size availableSpace)
|
||||||
|
{
|
||||||
|
var measurements = Elements.Select(x => x.Measure()).ToList();
|
||||||
|
|
||||||
|
var metrics = Elements
|
||||||
|
.Select(x => x.Style.ToPaint())
|
||||||
|
.Select(x => x.FontMetrics)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var lineHeight = metrics.Max(x => -x.Ascent) + metrics.Max(x => x.Descent);
|
||||||
|
|
||||||
|
var width = measurements.Sum(x => x.Width);
|
||||||
|
|
||||||
|
return new FullRender(width, lineHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Draw(ICanvas canvas, Size availableSpace)
|
||||||
|
{
|
||||||
|
var measurements = Elements
|
||||||
|
.Select(x => x.Measure())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var metrics = Elements
|
||||||
|
.Select(x => x.Style.ToPaint())
|
||||||
|
.Select(x => x.FontMetrics)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var offset = metrics.Max(x => -x.Ascent);
|
||||||
|
var lineHeight = metrics.Max(x => -x.Ascent) + metrics.Max(x => x.Descent);
|
||||||
|
|
||||||
|
|
||||||
|
using var typeface = SKTypeface.FromFamilyName("Helvetica");
|
||||||
|
using var shaper = new SKShaper(typeface);
|
||||||
|
var shaped = shaper.Shape("Podstawowy łaciński — ✔️ ❤️ ☆ Tabela znaków Unicode", Elements.First().Style.ToPaint());
|
||||||
|
|
||||||
|
foreach (var textElement in Elements)
|
||||||
|
{
|
||||||
|
var size = textElement.Measure();
|
||||||
|
|
||||||
|
canvas.DrawRectangle(new Position(0, 0), new Size(size.Width, lineHeight), textElement.Style.BackgroundColor);
|
||||||
|
|
||||||
|
canvas.Translate(new Position(0, offset));
|
||||||
|
textElement.Draw(canvas);
|
||||||
|
canvas.Translate(new Position(0, -offset));
|
||||||
|
|
||||||
|
canvas.Translate(new Position(size.Width, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.Translate(new Position(-measurements.Sum(x => x.Width), 0));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ namespace QuestPDF.Fluent
|
|||||||
var descriptor = new ComponentDescriptor<T>(component);
|
var descriptor = new ComponentDescriptor<T>(component);
|
||||||
handler?.Invoke(descriptor);
|
handler?.Invoke(descriptor);
|
||||||
|
|
||||||
component.Compose(element);
|
component.Compose(element.Container());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Component<T>(this IContainer element, Action<ComponentDescriptor<T>>? handler = null) where T : IComponent, new()
|
static void Component<T>(this IContainer element, Action<ComponentDescriptor<T>>? handler = null) where T : IComponent, new()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace QuestPDF.Fluent
|
|||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Element<T>(this IContainer element, T child) where T : IElement
|
internal static T Element<T>(this IContainer element, T child) where T : IElement
|
||||||
{
|
{
|
||||||
if (element?.Child != null && element.Child is Empty == false)
|
if (element?.Child != null && element.Child is Empty == false)
|
||||||
{
|
{
|
||||||
@@ -33,12 +33,12 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static void Element<TParent>(this TParent parent, Action<IContainer> handler) where TParent : IContainer
|
public static void Element<TParent>(this TParent parent, Action<IContainer> handler) where TParent : IContainer
|
||||||
{
|
{
|
||||||
handler(parent);
|
handler(parent.Container());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IContainer Element<TParent>(this TParent parent, Func<IContainer, IContainer> handler) where TParent : IContainer
|
public static IContainer Element<TParent>(this TParent parent, Func<IContainer, IContainer> handler) where TParent : IContainer
|
||||||
{
|
{
|
||||||
return handler(parent);
|
return handler(parent.Container()).Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PageNumber(this IContainer element, string textFormat = "{number}", TextStyle? style = null)
|
public static void PageNumber(this IContainer element, string textFormat = "{number}", TextStyle? style = null)
|
||||||
@@ -163,4 +163,4 @@ namespace QuestPDF.Fluent
|
|||||||
return element.Element(new Box());
|
return element.Element(new Box());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ namespace QuestPDF.Fluent
|
|||||||
return style.Mutate(x => x.Color = value);
|
return style.Mutate(x => x.Color = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TextStyle BackgroundColor(this TextStyle style, string value)
|
||||||
|
{
|
||||||
|
return style.Mutate(x => x.BackgroundColor = value);
|
||||||
|
}
|
||||||
|
|
||||||
public static TextStyle FontType(this TextStyle style, string value)
|
public static TextStyle FontType(this TextStyle style, string value)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.FontType = value);
|
return style.Mutate(x => x.FontType = value);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace QuestPDF.Helpers
|
|||||||
{
|
{
|
||||||
public static class Placeholders
|
public static class Placeholders
|
||||||
{
|
{
|
||||||
private static Random Random = new Random();
|
public static Random Random = new Random();
|
||||||
|
|
||||||
#region Word Cache
|
#region Word Cache
|
||||||
|
|
||||||
@@ -155,25 +155,25 @@ namespace QuestPDF.Helpers
|
|||||||
|
|
||||||
private static readonly string[] BackgroundColors =
|
private static readonly string[] BackgroundColors =
|
||||||
{
|
{
|
||||||
Colors.Red.Lighten2,
|
Colors.Red.Lighten3,
|
||||||
Colors.Pink.Lighten2,
|
Colors.Pink.Lighten3,
|
||||||
Colors.Purple.Lighten2,
|
Colors.Purple.Lighten3,
|
||||||
Colors.DeepPurple.Lighten2,
|
Colors.DeepPurple.Lighten3,
|
||||||
Colors.Indigo.Lighten2,
|
Colors.Indigo.Lighten3,
|
||||||
Colors.Blue.Lighten2,
|
Colors.Blue.Lighten3,
|
||||||
Colors.LightBlue.Lighten2,
|
Colors.LightBlue.Lighten3,
|
||||||
Colors.Cyan.Lighten2,
|
Colors.Cyan.Lighten3,
|
||||||
Colors.Teal.Lighten2,
|
Colors.Teal.Lighten3,
|
||||||
Colors.Green.Lighten2,
|
Colors.Green.Lighten3,
|
||||||
Colors.LightGreen.Lighten2,
|
Colors.LightGreen.Lighten3,
|
||||||
Colors.Lime.Lighten2,
|
Colors.Lime.Lighten3,
|
||||||
Colors.Yellow.Lighten2,
|
Colors.Yellow.Lighten3,
|
||||||
Colors.Amber.Lighten2,
|
Colors.Amber.Lighten3,
|
||||||
Colors.Orange.Lighten2,
|
Colors.Orange.Lighten3,
|
||||||
Colors.DeepOrange.Lighten2,
|
Colors.DeepOrange.Lighten3,
|
||||||
Colors.Brown.Lighten2,
|
Colors.Brown.Lighten3,
|
||||||
Colors.Grey.Lighten2,
|
Colors.Grey.Lighten3,
|
||||||
Colors.BlueGrey.Lighten2
|
Colors.BlueGrey.Lighten3
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string BackgroundColor()
|
public static string BackgroundColor()
|
||||||
|
|||||||
@@ -5,18 +5,19 @@ namespace QuestPDF.Infrastructure
|
|||||||
public class TextStyle
|
public class TextStyle
|
||||||
{
|
{
|
||||||
internal string Color { get; set; } = Colors.Black;
|
internal string Color { get; set; } = Colors.Black;
|
||||||
|
internal string BackgroundColor { get; set; } = Colors.Transparent;
|
||||||
internal string FontType { get; set; } = "Calibri";
|
internal string FontType { get; set; } = "Calibri";
|
||||||
internal float Size { get; set; } = 12;
|
internal float Size { get; set; } = 12;
|
||||||
internal float LineHeight { get; set; } = 1.2f;
|
internal float LineHeight { get; set; } = 1f;
|
||||||
internal HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
internal HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
||||||
internal FontWeight FontWeight { get; set; } = FontWeight.Normal;
|
internal FontWeight FontWeight { get; set; } = FontWeight.Normal;
|
||||||
internal bool IsItalic { get; set; } = false;
|
internal bool IsItalic { get; set; } = false;
|
||||||
|
|
||||||
public static TextStyle Default => new TextStyle();
|
public static TextStyle Default => new TextStyle();
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Color}|{FontType}|{Size}|{LineHeight}|{Alignment}|{FontWeight}|{IsItalic}";
|
return $"{Color}|{BackgroundColor}|{FontType}|{Size}|{LineHeight}|{Alignment}|{FontWeight}|{IsItalic}";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal TextStyle Clone() => (TextStyle)MemberwiseClone();
|
internal TextStyle Clone() => (TextStyle)MemberwiseClone();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<Authors>MarcinZiabek</Authors>
|
<Authors>MarcinZiabek</Authors>
|
||||||
<Company>CodeFlint</Company>
|
<Company>CodeFlint</Company>
|
||||||
<PackageId>QuestPDF</PackageId>
|
<PackageId>QuestPDF</PackageId>
|
||||||
<Version>2021.5-alpha2</Version>
|
<Version>2021.5.1</Version>
|
||||||
<PackageDescription>QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API.</PackageDescription>
|
<PackageDescription>QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API.</PackageDescription>
|
||||||
<PackageReleaseNotes>New elements: Grid, Canvas, EnsureSpace, Layers. Predefined colors and fonts.</PackageReleaseNotes>
|
<PackageReleaseNotes>New elements: Box, Grid, Canvas, EnsureSpance and Layers. Redesigned the Debug element. Added material design colors. Added list of basic fonts. Added spacing property to the Row element. Fluent API improvements and increased stability.</PackageReleaseNotes>
|
||||||
<LangVersion>8</LangVersion>
|
<LangVersion>8</LangVersion>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<PackageIcon>Logo.png</PackageIcon>
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SkiaSharp" Version="2.80.2" />
|
<PackageReference Include="SkiaSharp" Version="2.80.2" />
|
||||||
|
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.80.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user