Compare commits

...

14 Commits

Author SHA1 Message Date
Marcin Ziąbek e18b5170e6 Improved text run calculation 2021-05-05 11:21:53 +02:00
Marcin Ziąbek 5010b61565 Merge branch 'main' into richtext
# Conflicts:
#	QuestPDF/Elements/Stack.cs
2021-05-05 00:16:45 +02:00
Marcin Ziąbek 44d7538578 Examples to the documentation 2021-05-05 00:10:48 +02:00
Marcin Ziąbek f8d270bd2a Font measurement improvements 2021-05-04 15:33:10 +02:00
Marcin Ziąbek b894262f7e Improved developer experience via injecting Element() and Component() content in separate containers 2021-05-03 21:04:23 +02:00
Marcin Ziąbek 4423774648 Fixed Grid spacing. Adjusted performance test 2021-05-03 13:32:46 +02:00
Marcin Ziąbek 5d4f1f530a Merge pull request #11 from QuestPDF/tree_stack
Improved Stack and Row
2021-05-03 11:40:57 +02:00
Marcin Ziąbek 3ba8185871 Merge pull request #10 from QuestPDF/2021.05
2021.05 Update
2021-05-03 11:39:59 +02:00
Marcin Ziąbek b6e0bd505c Merge branch 'main' into 2021.05 2021-05-03 11:39:17 +02:00
Marcin Ziąbek f884547d16 First steps with text shaper 2021-04-29 11:18:16 +02:00
Marcin Ziąbek 4a7f9385c4 Improved text positioning 2021-04-28 23:49:22 +02:00
Marcin Ziąbek f4181de3d2 Simple drawing text 2021-04-28 00:24:26 +02:00
MarcinZiabek 4e3ba1d878 Fixed wrong import in QuestPDF.Examples.csproj 2021-04-16 10:22:41 +02:00
Marcin Ziąbek 6f0c6513da Bugfix: exception when providing null content into the Text element 2021-03-31 13:00:29 +02:00
17 changed files with 597 additions and 87 deletions
+101 -9
View File
@@ -1,5 +1,7 @@
using System.Linq;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
@@ -135,18 +137,20 @@ namespace QuestPDF.Examples
});
}
//[ShowResult]
[ImageSize(300, 200)]
[ShowResult]
[ImageSize(210, 210)]
public void Debug(IContainer container)
{
container
.Padding(25)
.Debug()
.Padding(-5)
.Row(row =>
.Debug("Grid example", Colors.Blue.Medium)
.Grid(grid =>
{
row.RelativeColumn().Padding(5).Extend().Placeholder();
row.RelativeColumn().Padding(5).Extend().Placeholder();
grid.Columns(3);
grid.Spacing(5);
foreach (var _ in Enumerable.Range(0, 8))
grid.Item().Height(50).Placeholder();
});
}
@@ -178,7 +182,8 @@ namespace QuestPDF.Examples
.AlignRight()
.Grid(grid =>
{
grid.Spacing(5);
grid.VerticalSpacing(20);
grid.HorizontalSpacing(10);
grid.Columns(12);
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);
});
}
//[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)]
public void Layers(IContainer container)
{
+212
View File
@@ -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();
}
}
}
+6 -7
View File
@@ -18,8 +18,8 @@ namespace QuestPDF.ReportSample
HeaderFields = HeaderFields(),
LogoData = Helpers.GetImage("Logo.png"),
Sections = Enumerable.Range(0, 8).Select(x => GenerateSection()).ToList(),
Photos = Enumerable.Range(2, 6).Select(x => GetReportPhotos()).ToList()
Sections = Enumerable.Range(0, 50).Select(x => GenerateSection()).ToList(),
Photos = Enumerable.Range(0, 30).Select(x => GetReportPhotos()).ToList()
};
List<ReportHeaderField> HeaderFields()
@@ -52,8 +52,8 @@ namespace QuestPDF.ReportSample
ReportSection GenerateSection()
{
var sectionLength = Helpers.Random.NextDouble() > 0.75
? Helpers.Random.Next(10, 20)
: Helpers.Random.Next(3, 11);
? Helpers.Random.Next(20, 40)
: Helpers.Random.Next(5, 10);
return new ReportSection
{
@@ -100,8 +100,7 @@ namespace QuestPDF.ReportSample
{
Label = "Photos",
Photos = Enumerable
.Range(0, Helpers.Random.Next(1, 10))
.Select(x => Helpers.Random.Next(0, 128))
.Range(0, Helpers.Random.Next(1, 15))
.Select(x => Placeholders.Image(400, 300))
.ToList()
};
@@ -111,7 +110,7 @@ namespace QuestPDF.ReportSample
{
return new ReportPhoto()
{
PhotoData = Placeholders.Image(400, 300),
PhotoData = Placeholders.Image(800, 600),
Comments = Placeholders.Sentence(),
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
@@ -72,7 +72,7 @@ namespace QuestPDF.ReportSample.Layouts
return;
}
container.Debug("Photo gallery").Grid(grid =>
container.Debug("Photos").Grid(grid =>
{
grid.Spacing(5);
grid.Columns(3);
+3 -1
View File
@@ -25,9 +25,11 @@ namespace QuestPDF.ReportSample
[Test]
public void PerformanceBenchmark()
{
// target document length should be around 100 pages
// test size
const int testSize = 100;
const decimal performanceTarget = 5; // documents per second
const decimal performanceTarget = 1; // documents per second
// create report models
var reports = Enumerable
+105 -34
View File
@@ -1,4 +1,5 @@
using FluentAssertions;
using FluentAssertions.Equivalency;
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.Fluent;
@@ -6,7 +7,7 @@ using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
/*[TestFixture]
[TestFixture]
public class GridTests
{
#region Alignment
@@ -39,30 +40,30 @@ namespace QuestPDF.UnitTests
// assert
var expected = new Container();
expected.Stack(stack =>
expected.Container().Stack(stack =>
{
stack.Item().Row(row =>
{
row.RelativeColumn(6).Element(childA);
row.RelativeColumn(4).Element(childB);
row.RelativeColumn(2).Element(Empty.Instance);
row.RelativeColumn(6).Container().Element(childA);
row.RelativeColumn(4).Container().Element(childB);
row.RelativeColumn(2);
});
stack.Item().Row(row =>
{
row.RelativeColumn(4).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(6).Element(Empty.Instance);
row.RelativeColumn(4).Container().Element(childC);
row.RelativeColumn(2).Container().Element(childD);
row.RelativeColumn(6);
});
stack.Item().Row(row =>
{
row.RelativeColumn(8).Element(childE);
row.RelativeColumn(4).Element(Empty.Instance);
row.RelativeColumn(8).Container().Element(childE);
row.RelativeColumn(4);
});
});
structure.Child.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering().IncludingAllRuntimeProperties());
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
}
[Test]
@@ -93,33 +94,33 @@ namespace QuestPDF.UnitTests
// assert
var expected = new Container();
expected.Stack(stack =>
expected.Container().Stack(stack =>
{
stack.Item().Row(row =>
{
row.RelativeColumn(1).Element(Empty.Instance);
row.RelativeColumn(6).Element(childA);
row.RelativeColumn(4).Element(childB);
row.RelativeColumn(1).Element(Empty.Instance);
row.RelativeColumn(1);
row.RelativeColumn(6).Container().Element(childA);
row.RelativeColumn(4).Container().Element(childB);
row.RelativeColumn(1);
});
stack.Item().Row(row =>
{
row.RelativeColumn(3).Element(Empty.Instance);
row.RelativeColumn(4).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(3).Element(Empty.Instance);
row.RelativeColumn(3);
row.RelativeColumn(4).Container().Element(childC);
row.RelativeColumn(2).Container().Element(childD);
row.RelativeColumn(3);
});
stack.Item().Row(row =>
{
row.RelativeColumn(2).Element(Empty.Instance);
row.RelativeColumn(8).Element(childE);
row.RelativeColumn(2).Element(Empty.Instance);
row.RelativeColumn(2);
row.RelativeColumn(8).Container().Element(childE);
row.RelativeColumn(2);
});
});
structure.Child.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering().IncludingAllRuntimeProperties());
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
}
[Test]
@@ -154,28 +155,98 @@ namespace QuestPDF.UnitTests
{
stack.Item().Row(row =>
{
row.RelativeColumn(2).Element(Empty.Instance);
row.RelativeColumn(6).Element(childA);
row.RelativeColumn(4).Element(childB);
row.RelativeColumn(2);
row.RelativeColumn(6).Container().Element(childA);
row.RelativeColumn(4).Container().Element(childB);
});
stack.Item().Row(row =>
{
row.RelativeColumn(6).Element(Empty.Instance);
row.RelativeColumn(4).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(6);
row.RelativeColumn(4).Container().Element(childC);
row.RelativeColumn(2).Container().Element(childD);
});
stack.Item().Row(row =>
{
row.RelativeColumn(4).Element(Empty.Instance);
row.RelativeColumn(8).Element(childE);
row.RelativeColumn(4);
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
}*/
#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
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ namespace QuestPDF.Drawing
Typeface = SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant),
TextSize = style.Size,
TextEncoding = SKTextEncoding.Utf32,
TextAlign = style.Alignment switch
{
HorizontalAlignment.Left => SKTextAlign.Left,
+1 -1
View File
@@ -30,7 +30,7 @@ namespace QuestPDF.Elements
container.Stack(stack =>
{
stack.Spacing(HorizontalSpacing);
stack.Spacing(VerticalSpacing);
while (ChildrenQueue.Any())
stack.Item().Row(BuildRow);
+8 -3
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
using Size = QuestPDF.Infrastructure.Size;
@@ -24,7 +25,8 @@ namespace QuestPDF.Elements
.DefaultIfEmpty(0)
.Max();
var realHeight = lines.Count * LineHeight;
var paint = Style.ToPaint().FontMetrics;
var realHeight = -paint.Ascent + paint.Descent;
if (realHeight > availableSpace.Height + Size.Epsilon)
return new Wrap();
@@ -34,12 +36,15 @@ namespace QuestPDF.Elements
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 offsetTop = 0f;
var offsetLeft = GetLeftOffset();
canvas.Translate(new Position(0, Style.Size));
canvas.Translate(new Position(0, offeset));
foreach (var line in lines)
{
@@ -47,7 +52,7 @@ namespace QuestPDF.Elements
offsetTop += LineHeight;
}
canvas.Translate(new Position(0, -Style.Size));
canvas.Translate(new Position(0, -offeset));
float GetLeftOffset()
{
+51
View File
@@ -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
};
});
}
}
}
+71
View File
@@ -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));
//
}
}
}
+1 -1
View File
@@ -56,7 +56,7 @@ namespace QuestPDF.Fluent
var descriptor = new ComponentDescriptor<T>(component);
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()
+4 -4
View File
@@ -14,7 +14,7 @@ namespace QuestPDF.Fluent
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)
{
@@ -33,12 +33,12 @@ namespace QuestPDF.Fluent
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
{
return handler(parent);
return handler(parent.Container()).Container();
}
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());
}
}
}
}
+5
View File
@@ -18,6 +18,11 @@ namespace QuestPDF.Fluent
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)
{
return style.Mutate(x => x.FontType = value);
+20 -20
View File
@@ -7,7 +7,7 @@ namespace QuestPDF.Helpers
{
public static class Placeholders
{
private static Random Random = new Random();
public static Random Random = new Random();
#region Word Cache
@@ -155,25 +155,25 @@ namespace QuestPDF.Helpers
private static readonly string[] BackgroundColors =
{
Colors.Red.Lighten2,
Colors.Pink.Lighten2,
Colors.Purple.Lighten2,
Colors.DeepPurple.Lighten2,
Colors.Indigo.Lighten2,
Colors.Blue.Lighten2,
Colors.LightBlue.Lighten2,
Colors.Cyan.Lighten2,
Colors.Teal.Lighten2,
Colors.Green.Lighten2,
Colors.LightGreen.Lighten2,
Colors.Lime.Lighten2,
Colors.Yellow.Lighten2,
Colors.Amber.Lighten2,
Colors.Orange.Lighten2,
Colors.DeepOrange.Lighten2,
Colors.Brown.Lighten2,
Colors.Grey.Lighten2,
Colors.BlueGrey.Lighten2
Colors.Red.Lighten3,
Colors.Pink.Lighten3,
Colors.Purple.Lighten3,
Colors.DeepPurple.Lighten3,
Colors.Indigo.Lighten3,
Colors.Blue.Lighten3,
Colors.LightBlue.Lighten3,
Colors.Cyan.Lighten3,
Colors.Teal.Lighten3,
Colors.Green.Lighten3,
Colors.LightGreen.Lighten3,
Colors.Lime.Lighten3,
Colors.Yellow.Lighten3,
Colors.Amber.Lighten3,
Colors.Orange.Lighten3,
Colors.DeepOrange.Lighten3,
Colors.Brown.Lighten3,
Colors.Grey.Lighten3,
Colors.BlueGrey.Lighten3
};
public static string BackgroundColor()
+4 -3
View File
@@ -5,18 +5,19 @@ namespace QuestPDF.Infrastructure
public class TextStyle
{
internal string Color { get; set; } = Colors.Black;
internal string BackgroundColor { get; set; } = Colors.Transparent;
internal string FontType { get; set; } = "Calibri";
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 FontWeight FontWeight { get; set; } = FontWeight.Normal;
internal bool IsItalic { get; set; } = false;
public static TextStyle Default => new TextStyle();
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();
+3 -2
View File
@@ -4,9 +4,9 @@
<Authors>MarcinZiabek</Authors>
<Company>CodeFlint</Company>
<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>
<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>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageIcon>Logo.png</PackageIcon>
@@ -23,6 +23,7 @@
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="2.80.2" />
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.80.2" />
</ItemGroup>
<ItemGroup>