Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4743768e23 | |||
| 1ba01a1cf5 | |||
| d4448437ac | |||
| bc853f48fc |
@@ -65,9 +65,9 @@ namespace QuestPDF.Examples.Engine
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderingTest ShowResults()
|
public RenderingTest ShowResults(bool value = true)
|
||||||
{
|
{
|
||||||
ShowResult = true;
|
ShowResult = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Examples.Engine;
|
using QuestPDF.Examples.Engine;
|
||||||
using QuestPDF.Fluent;
|
using QuestPDF.Fluent;
|
||||||
using QuestPDF.Helpers;
|
using QuestPDF.Helpers;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
namespace QuestPDF.Examples
|
namespace QuestPDF.Examples
|
||||||
{
|
{
|
||||||
@@ -11,36 +16,77 @@ namespace QuestPDF.Examples
|
|||||||
[Test]
|
[Test]
|
||||||
public void Benchmark()
|
public void Benchmark()
|
||||||
{
|
{
|
||||||
RenderingTest
|
GenerateAndCollect();
|
||||||
.Create()
|
|
||||||
.ProducePdf()
|
|
||||||
.PageSize(PageSizes.A4)
|
|
||||||
.ShowResults()
|
|
||||||
.MaxPages(10_000)
|
|
||||||
.EnableCaching(true)
|
|
||||||
.EnableDebugging(false)
|
|
||||||
.Render(container =>
|
|
||||||
{
|
|
||||||
container
|
|
||||||
.Padding(10)
|
|
||||||
.MinimalBox()
|
|
||||||
.Border(1)
|
|
||||||
.Table(table =>
|
|
||||||
{
|
|
||||||
const int numberOfRows = 100_000;
|
|
||||||
const int numberOfColumns = 10;
|
|
||||||
|
|
||||||
table.ColumnsDefinition(columns =>
|
|
||||||
{
|
|
||||||
foreach (var _ in Enumerable.Range(0, numberOfColumns))
|
|
||||||
columns.RelativeColumn();
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var row in Enumerable.Range(0, numberOfRows))
|
var stopwatch = new Stopwatch();
|
||||||
foreach (var column in Enumerable.Range(0, numberOfColumns))
|
stopwatch.Start();
|
||||||
table.Cell().Background(Placeholders.BackgroundColor()).Padding(5).Text($"{row}_{column}");
|
|
||||||
});
|
foreach (var _ in Enumerable.Range(0, 10000))
|
||||||
});
|
{
|
||||||
|
GenerateAndCollect();
|
||||||
|
}
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
Console.WriteLine($"Execution time: {stopwatch.Elapsed:g}");
|
||||||
|
|
||||||
|
void GenerateAndCollect()
|
||||||
|
{
|
||||||
|
var container = new Container();
|
||||||
|
|
||||||
|
container
|
||||||
|
.Padding(10)
|
||||||
|
.MinimalBox()
|
||||||
|
.Border(1)
|
||||||
|
.Column(column =>
|
||||||
|
{
|
||||||
|
const int numberOfRows = 100;
|
||||||
|
const int numberOfColumns = 10;
|
||||||
|
|
||||||
|
for (var y = 0; y < numberOfRows; y++)
|
||||||
|
{
|
||||||
|
column.Item().Row(row =>
|
||||||
|
{
|
||||||
|
for (var x = 0; x < numberOfColumns; x++)
|
||||||
|
{
|
||||||
|
row.RelativeItem()
|
||||||
|
|
||||||
|
.Background(Colors.Red.Lighten5)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Lighten4)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Lighten3)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Lighten2)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Lighten1)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Medium)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Darken1)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Darken2)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Darken3)
|
||||||
|
.Padding(3)
|
||||||
|
|
||||||
|
.Background(Colors.Red.Darken4)
|
||||||
|
.Height(3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ElementCacheManager.Collect(container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,8 @@ namespace QuestPDF.Drawing
|
|||||||
var pageContext = new PageContext();
|
var pageContext = new PageContext();
|
||||||
RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
|
RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
|
||||||
RenderPass(pageContext, canvas, content, debuggingState);
|
RenderPass(pageContext, canvas, content, debuggingState);
|
||||||
|
|
||||||
|
ElementCacheManager.Collect(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DebuggingState? debuggingState)
|
internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DebuggingState? debuggingState)
|
||||||
@@ -172,7 +174,7 @@ namespace QuestPDF.Drawing
|
|||||||
{
|
{
|
||||||
if (textBlockItem is TextBlockSpan textSpan)
|
if (textBlockItem is TextBlockSpan textSpan)
|
||||||
{
|
{
|
||||||
textSpan.Style.ApplyGlobalStyle(documentDefaultTextStyle);
|
textSpan.Style = textSpan.Style.ApplyGlobalStyle(TextStyle.LibraryDefault);
|
||||||
}
|
}
|
||||||
else if (textBlockItem is TextBlockElement textElement)
|
else if (textBlockItem is TextBlockElement textElement)
|
||||||
{
|
{
|
||||||
@@ -184,18 +186,13 @@ namespace QuestPDF.Drawing
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (content is DynamicHost dynamicHost)
|
if (content is DynamicHost dynamicHost)
|
||||||
dynamicHost.TextStyle.ApplyGlobalStyle(documentDefaultTextStyle);
|
dynamicHost.TextStyle = dynamicHost.TextStyle.ApplyGlobalStyle(documentDefaultTextStyle);
|
||||||
|
|
||||||
var targetTextStyle = documentDefaultTextStyle;
|
|
||||||
|
|
||||||
if (content is DefaultTextStyle defaultTextStyleElement)
|
if (content is DefaultTextStyle defaultTextStyleElement)
|
||||||
{
|
documentDefaultTextStyle = defaultTextStyleElement.TextStyle.ApplyGlobalStyle(documentDefaultTextStyle);
|
||||||
defaultTextStyleElement.TextStyle.ApplyParentStyle(documentDefaultTextStyle);
|
|
||||||
targetTextStyle = defaultTextStyleElement.TextStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var child in content.GetChildren())
|
foreach (var child in content.GetChildren())
|
||||||
ApplyDefaultTextStyle(child, targetTextStyle);
|
ApplyDefaultTextStyle(child, documentDefaultTextStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
|
namespace QuestPDF.Drawing
|
||||||
|
{
|
||||||
|
internal class CircularBuffer
|
||||||
|
{
|
||||||
|
private const int BufferSize = 11_000;
|
||||||
|
|
||||||
|
private object[] Buffer = new object[BufferSize];
|
||||||
|
private int WriteIndex { get; set; } = 0;
|
||||||
|
private int ReadIndex { get; set; } = 0;
|
||||||
|
|
||||||
|
public T Get<T>() where T : class, new()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (ReadIndex == WriteIndex)
|
||||||
|
return new T();
|
||||||
|
|
||||||
|
var index = ReadIndex;
|
||||||
|
ReadIndex = (ReadIndex + 1) % BufferSize;
|
||||||
|
|
||||||
|
var result = Buffer[index] as T;
|
||||||
|
Buffer[index] = null;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Store(object value)
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
Buffer[WriteIndex] = value;
|
||||||
|
WriteIndex = (WriteIndex + 1) % BufferSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// performance analysis:
|
||||||
|
// without: 115s
|
||||||
|
// ConcurrentQueue: 28s
|
||||||
|
// ConcurrentBag: 38s
|
||||||
|
// CircularBuffer: 30s
|
||||||
|
internal static class ElementCacheManager
|
||||||
|
{
|
||||||
|
private static ConcurrentDictionary<Type, ConcurrentQueue<object>> Cache { get; } = new();
|
||||||
|
|
||||||
|
public static T Get<T>() where T : class, new()
|
||||||
|
{
|
||||||
|
var buffer = Cache.GetOrAdd(typeof(T), _=> new ConcurrentQueue<object>());
|
||||||
|
return buffer.TryDequeue(out var result) ? result as T : new T();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Store<T>(T element)
|
||||||
|
{
|
||||||
|
var buffer = Cache.GetOrAdd(element.GetType(), _=> new ConcurrentQueue<object>());
|
||||||
|
buffer.Enqueue(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Collect(Element element)
|
||||||
|
{
|
||||||
|
foreach (var child in element.GetChildren())
|
||||||
|
Collect(child);
|
||||||
|
|
||||||
|
if (element is ICollectable collectable)
|
||||||
|
{
|
||||||
|
collectable.Collect();
|
||||||
|
Store(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,13 +14,13 @@ namespace QuestPDF.Drawing
|
|||||||
{
|
{
|
||||||
public static class FontManager
|
public static class FontManager
|
||||||
{
|
{
|
||||||
private static ConcurrentDictionary<string, FontStyleSet> StyleSets = new();
|
private static readonly ConcurrentDictionary<string, FontStyleSet> StyleSets = new();
|
||||||
private static ConcurrentDictionary<object, SKFontMetrics> FontMetrics = new();
|
private static readonly ConcurrentDictionary<TextStyle, SKFontMetrics> FontMetrics = new();
|
||||||
private static ConcurrentDictionary<object, SKPaint> FontPaints = new();
|
private static readonly ConcurrentDictionary<TextStyle, SKPaint> FontPaints = new();
|
||||||
private static ConcurrentDictionary<string, SKPaint> ColorPaints = new();
|
private static readonly ConcurrentDictionary<string, SKPaint> ColorPaints = new();
|
||||||
private static ConcurrentDictionary<object, Font> ShaperFonts = new();
|
private static readonly ConcurrentDictionary<TextStyle, Font> ShaperFonts = new();
|
||||||
private static ConcurrentDictionary<object, SKFont> Fonts = new();
|
private static readonly ConcurrentDictionary<TextStyle, SKFont> Fonts = new();
|
||||||
private static ConcurrentDictionary<object, TextShaper> TextShapers = new();
|
private static readonly ConcurrentDictionary<TextStyle, TextShaper> TextShapers = new();
|
||||||
|
|
||||||
static FontManager()
|
static FontManager()
|
||||||
{
|
{
|
||||||
@@ -110,7 +110,7 @@ namespace QuestPDF.Drawing
|
|||||||
|
|
||||||
internal static SKPaint ToPaint(this TextStyle style)
|
internal static SKPaint ToPaint(this TextStyle style)
|
||||||
{
|
{
|
||||||
return FontPaints.GetOrAdd(style.PaintKey, key => Convert(style));
|
return FontPaints.GetOrAdd(style, Convert);
|
||||||
|
|
||||||
static SKPaint Convert(TextStyle style)
|
static SKPaint Convert(TextStyle style)
|
||||||
{
|
{
|
||||||
@@ -172,14 +172,14 @@ namespace QuestPDF.Drawing
|
|||||||
|
|
||||||
internal static SKFontMetrics ToFontMetrics(this TextStyle style)
|
internal static SKFontMetrics ToFontMetrics(this TextStyle style)
|
||||||
{
|
{
|
||||||
return FontMetrics.GetOrAdd(style.FontMetricsKey, key => style.NormalPosition().ToPaint().FontMetrics);
|
return FontMetrics.GetOrAdd(style, key => key.NormalPosition().ToPaint().FontMetrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Font ToShaperFont(this TextStyle style)
|
internal static Font ToShaperFont(this TextStyle style)
|
||||||
{
|
{
|
||||||
return ShaperFonts.GetOrAdd(style.PaintKey, _ =>
|
return ShaperFonts.GetOrAdd(style, key =>
|
||||||
{
|
{
|
||||||
var typeface = style.ToPaint().Typeface;
|
var typeface = key.ToPaint().Typeface;
|
||||||
|
|
||||||
using var harfBuzzBlob = typeface.OpenStream(out var ttcIndex).ToHarfBuzzBlob();
|
using var harfBuzzBlob = typeface.OpenStream(out var ttcIndex).ToHarfBuzzBlob();
|
||||||
|
|
||||||
@@ -200,12 +200,12 @@ namespace QuestPDF.Drawing
|
|||||||
|
|
||||||
internal static TextShaper ToTextShaper(this TextStyle style)
|
internal static TextShaper ToTextShaper(this TextStyle style)
|
||||||
{
|
{
|
||||||
return TextShapers.GetOrAdd(style.PaintKey, _ => new TextShaper(style));
|
return TextShapers.GetOrAdd(style, key => new TextShaper(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static SKFont ToFont(this TextStyle style)
|
internal static SKFont ToFont(this TextStyle style)
|
||||||
{
|
{
|
||||||
return Fonts.GetOrAdd(style.PaintKey, _ => style.ToPaint().ToFont());
|
return Fonts.GetOrAdd(style, key => key.ToPaint().ToFont());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,5 +41,15 @@ namespace QuestPDF.Elements
|
|||||||
{
|
{
|
||||||
return $"Border: Top({Top}) Right({Right}) Bottom({Bottom}) Left({Left}) Color({Color})";
|
return $"Border: Top({Top}) Right({Right}) Bottom({Bottom}) Left({Left}) Color({Color})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Collect()
|
||||||
|
{
|
||||||
|
base.Collect();
|
||||||
|
|
||||||
|
Left = 0;
|
||||||
|
Right = 0;
|
||||||
|
Bottom = 0;
|
||||||
|
Top = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ namespace QuestPDF.Elements
|
|||||||
public Position Offset { get; set; }
|
public Position Offset { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Column : Element, ICacheable, IStateResettable
|
internal class Column : Element, ICacheable, IStateResettable, ICollectable
|
||||||
{
|
{
|
||||||
internal List<ColumnItem> Items { get; } = new();
|
internal List<ColumnItem> Items { get; } = new();
|
||||||
internal float Spacing { get; set; }
|
internal float Spacing { get; set; }
|
||||||
@@ -124,5 +124,10 @@ namespace QuestPDF.Elements
|
|||||||
|
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Collect()
|
||||||
|
{
|
||||||
|
Items.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ namespace QuestPDF.Elements
|
|||||||
{
|
{
|
||||||
internal class Container : ContainerElement
|
internal class Container : ContainerElement
|
||||||
{
|
{
|
||||||
internal Container()
|
public Container()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace QuestPDF.Elements
|
|||||||
private DynamicComponentProxy Child { get; }
|
private DynamicComponentProxy Child { get; }
|
||||||
private object InitialComponentState { get; set; }
|
private object InitialComponentState { get; set; }
|
||||||
|
|
||||||
internal TextStyle TextStyle { get; } = new();
|
internal TextStyle TextStyle { get; set; } = TextStyle.Default;
|
||||||
|
|
||||||
public DynamicHost(DynamicComponentProxy child)
|
public DynamicHost(DynamicComponentProxy child)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using QuestPDF.Infrastructure;
|
|||||||
|
|
||||||
namespace QuestPDF.Elements
|
namespace QuestPDF.Elements
|
||||||
{
|
{
|
||||||
internal class Padding : ContainerElement, ICacheable
|
internal class Padding : ContainerElement, ICacheable, ICollectable
|
||||||
{
|
{
|
||||||
public float Top { get; set; }
|
public float Top { get; set; }
|
||||||
public float Right { get; set; }
|
public float Right { get; set; }
|
||||||
@@ -62,5 +62,15 @@ namespace QuestPDF.Elements
|
|||||||
{
|
{
|
||||||
return $"Padding: Top({Top}) Right({Right}) Bottom({Bottom}) Left({Left})";
|
return $"Padding: Top({Top}) Right({Right}) Bottom({Bottom}) Left({Left})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Collect()
|
||||||
|
{
|
||||||
|
base.Collect();
|
||||||
|
|
||||||
|
Left = 0;
|
||||||
|
Right = 0;
|
||||||
|
Bottom = 0;
|
||||||
|
Top = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ namespace QuestPDF.Elements
|
|||||||
public Position Offset { get; set; }
|
public Position Offset { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Row : Element, ICacheable, IStateResettable
|
internal class Row : Element, ICacheable, IStateResettable, ICollectable
|
||||||
{
|
{
|
||||||
internal List<RowItem> Items { get; } = new();
|
internal List<RowItem> Items { get; } = new();
|
||||||
internal float Spacing { get; set; }
|
internal float Spacing { get; set; }
|
||||||
@@ -156,5 +156,10 @@ namespace QuestPDF.Elements
|
|||||||
|
|
||||||
return renderingCommands;
|
return renderingCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Collect()
|
||||||
|
{
|
||||||
|
Items.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ namespace QuestPDF.Elements.Text.Items
|
|||||||
internal class TextBlockSpan : ITextBlockItem
|
internal class TextBlockSpan : ITextBlockItem
|
||||||
{
|
{
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
public TextStyle Style { get; set; } = new();
|
public TextStyle Style { get; set; } = TextStyle.Default;
|
||||||
public TextShapingResult? TextShapingResult { get; set; }
|
public TextShapingResult? TextShapingResult { get; set; }
|
||||||
|
|
||||||
private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache = new ();
|
private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache = new ();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using QuestPDF.Infrastructure;
|
|||||||
|
|
||||||
namespace QuestPDF.Elements.Text
|
namespace QuestPDF.Elements.Text
|
||||||
{
|
{
|
||||||
internal class TextBlock : Element, IStateResettable
|
internal class TextBlock : Element, IStateResettable, ICollectable
|
||||||
{
|
{
|
||||||
public HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
public HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
||||||
public List<ITextBlockItem> Items { get; set; } = new List<ITextBlockItem>();
|
public List<ITextBlockItem> Items { get; set; } = new List<ITextBlockItem>();
|
||||||
@@ -38,6 +38,11 @@ namespace QuestPDF.Elements.Text
|
|||||||
RenderingQueue.Enqueue(item);
|
RenderingQueue.Enqueue(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Collect()
|
||||||
|
{
|
||||||
|
Items.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
internal override SpacePlan Measure(Size availableSpace)
|
internal override SpacePlan Measure(Size availableSpace)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ namespace QuestPDF.Fluent
|
|||||||
{
|
{
|
||||||
private static IContainer Border(this IContainer element, Action<Border> handler)
|
private static IContainer Border(this IContainer element, Action<Border> handler)
|
||||||
{
|
{
|
||||||
var border = element as Border ?? new Border();
|
var border = element as Border ?? ElementCacheManager.Get<Border>();
|
||||||
handler(border);
|
handler(border);
|
||||||
|
|
||||||
return element.Element(border);
|
return element.Element(border);
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
using Container = System.ComponentModel.Container;
|
||||||
|
|
||||||
namespace QuestPDF.Fluent
|
namespace QuestPDF.Fluent
|
||||||
{
|
{
|
||||||
public class ColumnDescriptor
|
public class ColumnDescriptor
|
||||||
{
|
{
|
||||||
internal Column Column { get; } = new();
|
internal Column Column { get; set; }
|
||||||
|
|
||||||
public void Spacing(float value, Unit unit = Unit.Point)
|
public void Spacing(float value, Unit unit = Unit.Point)
|
||||||
{
|
{
|
||||||
@@ -15,14 +17,9 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public IContainer Item()
|
public IContainer Item()
|
||||||
{
|
{
|
||||||
var container = new Container();
|
var columnItem = ElementCacheManager.Get<ColumnItem>();
|
||||||
|
Column.Items.Add(columnItem);
|
||||||
Column.Items.Add(new ColumnItem
|
return columnItem;
|
||||||
{
|
|
||||||
Child = container
|
|
||||||
});
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +33,8 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static void Column(this IContainer element, Action<ColumnDescriptor> handler)
|
public static void Column(this IContainer element, Action<ColumnDescriptor> handler)
|
||||||
{
|
{
|
||||||
var descriptor = new ColumnDescriptor();
|
var descriptor = ElementCacheManager.Get<ColumnDescriptor>();
|
||||||
|
descriptor.Column = ElementCacheManager.Get<Column>();
|
||||||
handler(descriptor);
|
handler(descriptor);
|
||||||
element.Element(descriptor.Column);
|
element.Element(descriptor.Column);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Drawing.Exceptions;
|
using QuestPDF.Drawing.Exceptions;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
@@ -52,10 +53,10 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static IContainer Background(this IContainer element, string color)
|
public static IContainer Background(this IContainer element, string color)
|
||||||
{
|
{
|
||||||
return element.Element(new Background
|
var background = ElementCacheManager.Get<Background>();
|
||||||
{
|
background.Color = color;
|
||||||
Color = color
|
|
||||||
});
|
return element.Element(background);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Placeholder(this IContainer element, string? text = null)
|
public static void Placeholder(this IContainer element, string? text = null)
|
||||||
@@ -162,7 +163,7 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static IContainer MinimalBox(this IContainer element)
|
public static IContainer MinimalBox(this IContainer element)
|
||||||
{
|
{
|
||||||
return element.Element(new MinimalBox());
|
return element.Element(ElementCacheManager.Get<MinimalBox>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IContainer Unconstrained(this IContainer element)
|
public static IContainer Unconstrained(this IContainer element)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ namespace QuestPDF.Fluent
|
|||||||
{
|
{
|
||||||
private static IContainer Padding(this IContainer element, Action<Padding> handler)
|
private static IContainer Padding(this IContainer element, Action<Padding> handler)
|
||||||
{
|
{
|
||||||
var padding = element as Padding ?? new Padding();
|
var padding = element as Padding ?? ElementCacheManager.Get<Padding>();
|
||||||
handler(padding);
|
handler(padding);
|
||||||
|
|
||||||
return element.Element(padding);
|
return element.Element(padding);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ namespace QuestPDF.Fluent
|
|||||||
{
|
{
|
||||||
public class RowDescriptor
|
public class RowDescriptor
|
||||||
{
|
{
|
||||||
internal Row Row { get; } = new();
|
internal Row Row { get; set; }
|
||||||
|
|
||||||
public void Spacing(float value)
|
public void Spacing(float value)
|
||||||
{
|
{
|
||||||
@@ -15,14 +16,12 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
private IContainer Item(RowItemType type, float size = 0)
|
private IContainer Item(RowItemType type, float size = 0)
|
||||||
{
|
{
|
||||||
var element = new RowItem
|
var rowItem = ElementCacheManager.Get<RowItem>();
|
||||||
{
|
rowItem.Type = type;
|
||||||
Type = type,
|
rowItem.Size = size;
|
||||||
Size = size
|
|
||||||
};
|
|
||||||
|
|
||||||
Row.Items.Add(element);
|
Row.Items.Add(rowItem);
|
||||||
return element;
|
return rowItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("This element has been renamed since version 2022.2. Please use the RelativeItem method.")]
|
[Obsolete("This element has been renamed since version 2022.2. Please use the RelativeItem method.")]
|
||||||
@@ -57,9 +56,12 @@ namespace QuestPDF.Fluent
|
|||||||
{
|
{
|
||||||
public static void Row(this IContainer element, Action<RowDescriptor> handler)
|
public static void Row(this IContainer element, Action<RowDescriptor> handler)
|
||||||
{
|
{
|
||||||
var descriptor = new RowDescriptor();
|
var descriptor = ElementCacheManager.Get<RowDescriptor>();
|
||||||
|
descriptor.Row = ElementCacheManager.Get<Row>();
|
||||||
|
|
||||||
handler(descriptor);
|
handler(descriptor);
|
||||||
element.Element(descriptor.Row);
|
element.Element(descriptor.Row);
|
||||||
|
ElementCacheManager.Store(descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,11 +12,18 @@ namespace QuestPDF.Fluent
|
|||||||
{
|
{
|
||||||
public class TextSpanDescriptor
|
public class TextSpanDescriptor
|
||||||
{
|
{
|
||||||
internal TextStyle TextStyle { get; }
|
internal TextStyle TextStyle = TextStyle.Default;
|
||||||
|
internal Action<TextStyle> AssignTextStyle { get; }
|
||||||
|
|
||||||
internal TextSpanDescriptor(TextStyle textStyle)
|
internal TextSpanDescriptor(Action<TextStyle> assignTextStyle)
|
||||||
{
|
{
|
||||||
TextStyle = textStyle;
|
AssignTextStyle = assignTextStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void MutateTextStyle(Func<TextStyle, TextStyle> handler)
|
||||||
|
{
|
||||||
|
TextStyle = handler(TextStyle);
|
||||||
|
AssignTextStyle(TextStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,16 +31,16 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public class TextPageNumberDescriptor : TextSpanDescriptor
|
public class TextPageNumberDescriptor : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
internal PageNumberFormatter FormatFunction { get; private set; } = x => x?.ToString() ?? string.Empty;
|
internal Action<PageNumberFormatter> AssignFormatFunction { get; }
|
||||||
|
|
||||||
internal TextPageNumberDescriptor(TextStyle textStyle) : base(textStyle)
|
internal TextPageNumberDescriptor(Action<TextStyle> assignTextStyle, Action<PageNumberFormatter> assignFormatFunction) : base(assignTextStyle)
|
||||||
{
|
{
|
||||||
|
AssignFormatFunction = assignFormatFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextPageNumberDescriptor Format(PageNumberFormatter formatter)
|
public TextPageNumberDescriptor Format(PageNumberFormatter formatter)
|
||||||
{
|
{
|
||||||
FormatFunction = formatter ?? FormatFunction;
|
AssignFormatFunction(formatter);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +48,7 @@ namespace QuestPDF.Fluent
|
|||||||
public class TextDescriptor
|
public class TextDescriptor
|
||||||
{
|
{
|
||||||
private ICollection<TextBlock> TextBlocks { get; } = new List<TextBlock>();
|
private ICollection<TextBlock> TextBlocks { get; } = new List<TextBlock>();
|
||||||
private TextStyle DefaultStyle { get; set; } = TextStyle.Default;
|
private TextStyle? DefaultStyle { get; set; }
|
||||||
internal HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
internal HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
||||||
private float Spacing { get; set; } = 0f;
|
private float Spacing { get; set; } = 0f;
|
||||||
|
|
||||||
@@ -91,19 +98,15 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public TextSpanDescriptor Span(string? text)
|
public TextSpanDescriptor Span(string? text)
|
||||||
{
|
{
|
||||||
var style = DefaultStyle.Clone();
|
|
||||||
var descriptor = new TextSpanDescriptor(style);
|
|
||||||
|
|
||||||
if (text == null)
|
if (text == null)
|
||||||
return descriptor;
|
return new TextSpanDescriptor(_ => { });
|
||||||
|
|
||||||
var items = text
|
var items = text
|
||||||
.Replace("\r", string.Empty)
|
.Replace("\r", string.Empty)
|
||||||
.Split(new[] { '\n' }, StringSplitOptions.None)
|
.Split(new[] { '\n' }, StringSplitOptions.None)
|
||||||
.Select(x => new TextBlockSpan
|
.Select(x => new TextBlockSpan
|
||||||
{
|
{
|
||||||
Text = x,
|
Text = x
|
||||||
Style = style
|
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@@ -118,7 +121,7 @@ namespace QuestPDF.Fluent
|
|||||||
.ToList()
|
.ToList()
|
||||||
.ForEach(TextBlocks.Add);
|
.ForEach(TextBlocks.Add);
|
||||||
|
|
||||||
return descriptor;
|
return new TextSpanDescriptor(x => items.ForEach(y => y.Style = x));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextSpanDescriptor Line(string? text)
|
public TextSpanDescriptor Line(string? text)
|
||||||
@@ -134,16 +137,10 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
private TextPageNumberDescriptor PageNumber(Func<IPageContext, int?> pageNumber)
|
private TextPageNumberDescriptor PageNumber(Func<IPageContext, int?> pageNumber)
|
||||||
{
|
{
|
||||||
var style = DefaultStyle.Clone();
|
var textBlockItem = new TextBlockPageNumber();
|
||||||
var descriptor = new TextPageNumberDescriptor(style);
|
AddItemToLastTextBlock(textBlockItem);
|
||||||
|
|
||||||
AddItemToLastTextBlock(new TextBlockPageNumber
|
return new TextPageNumberDescriptor(x => textBlockItem.Style = x, x => textBlockItem.Source = context => x(pageNumber(context)));
|
||||||
{
|
|
||||||
Source = context => descriptor.FormatFunction(pageNumber(context)),
|
|
||||||
Style = style
|
|
||||||
});
|
|
||||||
|
|
||||||
return descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextPageNumberDescriptor CurrentPageNumber()
|
public TextPageNumberDescriptor CurrentPageNumber()
|
||||||
@@ -187,20 +184,17 @@ namespace QuestPDF.Fluent
|
|||||||
if (IsNullOrEmpty(sectionName))
|
if (IsNullOrEmpty(sectionName))
|
||||||
throw new ArgumentException("Section name cannot be null or empty", nameof(sectionName));
|
throw new ArgumentException("Section name cannot be null or empty", nameof(sectionName));
|
||||||
|
|
||||||
var style = DefaultStyle.Clone();
|
|
||||||
var descriptor = new TextSpanDescriptor(style);
|
|
||||||
|
|
||||||
if (IsNullOrEmpty(text))
|
if (IsNullOrEmpty(text))
|
||||||
return descriptor;
|
return new TextSpanDescriptor(_ => { });
|
||||||
|
|
||||||
AddItemToLastTextBlock(new TextBlockSectionLink
|
var textBlockItem = new TextBlockSectionLink
|
||||||
{
|
{
|
||||||
Style = style,
|
|
||||||
Text = text,
|
Text = text,
|
||||||
SectionName = sectionName
|
SectionName = sectionName
|
||||||
});
|
};
|
||||||
|
|
||||||
return descriptor;
|
AddItemToLastTextBlock(textBlockItem);
|
||||||
|
return new TextSpanDescriptor(x => textBlockItem.Style = x);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("This element has been renamed since version 2022.3. Please use the SectionLink method.")]
|
[Obsolete("This element has been renamed since version 2022.3. Please use the SectionLink method.")]
|
||||||
@@ -214,20 +208,17 @@ namespace QuestPDF.Fluent
|
|||||||
if (IsNullOrEmpty(url))
|
if (IsNullOrEmpty(url))
|
||||||
throw new ArgumentException("Url cannot be null or empty", nameof(url));
|
throw new ArgumentException("Url cannot be null or empty", nameof(url));
|
||||||
|
|
||||||
var style = DefaultStyle.Clone();
|
|
||||||
var descriptor = new TextSpanDescriptor(style);
|
|
||||||
|
|
||||||
if (IsNullOrEmpty(text))
|
if (IsNullOrEmpty(text))
|
||||||
return descriptor;
|
return new TextSpanDescriptor(_ => { });
|
||||||
|
|
||||||
AddItemToLastTextBlock(new TextBlockHyperlink
|
var textBlockItem = new TextBlockHyperlink
|
||||||
{
|
{
|
||||||
Style = style,
|
|
||||||
Text = text,
|
Text = text,
|
||||||
Url = url
|
Url = url
|
||||||
});
|
};
|
||||||
|
|
||||||
return descriptor;
|
AddItemToLastTextBlock(textBlockItem);
|
||||||
|
return new TextSpanDescriptor(x => textBlockItem.Style = x);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("This element has been renamed since version 2022.3. Please use the Hyperlink method.")]
|
[Obsolete("This element has been renamed since version 2022.3. Please use the Hyperlink method.")]
|
||||||
@@ -251,7 +242,9 @@ namespace QuestPDF.Fluent
|
|||||||
internal void Compose(IContainer container)
|
internal void Compose(IContainer container)
|
||||||
{
|
{
|
||||||
TextBlocks.ToList().ForEach(x => x.Alignment = Alignment);
|
TextBlocks.ToList().ForEach(x => x.Alignment = Alignment);
|
||||||
container = container.DefaultTextStyle(DefaultStyle);
|
|
||||||
|
if (DefaultStyle != null)
|
||||||
|
container = container.DefaultTextStyle(DefaultStyle);
|
||||||
|
|
||||||
if (TextBlocks.Count == 1)
|
if (TextBlocks.Count == 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,120 +11,124 @@ namespace QuestPDF.Fluent
|
|||||||
if (style == null)
|
if (style == null)
|
||||||
return descriptor;
|
return descriptor;
|
||||||
|
|
||||||
descriptor.TextStyle.OverrideStyle(style);
|
descriptor.MutateTextStyle(x => x.OverrideStyle(style));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T FontColor<T>(this T descriptor, string value) where T : TextSpanDescriptor
|
public static T FontColor<T>(this T descriptor, string value) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.Color = value;
|
descriptor.MutateTextStyle(x => x.FontColor(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T BackgroundColor<T>(this T descriptor, string value) where T : TextSpanDescriptor
|
public static T BackgroundColor<T>(this T descriptor, string value) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.BackgroundColor = value;
|
descriptor.MutateTextStyle(x => x.BackgroundColor(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T FontFamily<T>(this T descriptor, string value) where T : TextSpanDescriptor
|
public static T FontFamily<T>(this T descriptor, string value) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.FontFamily = value;
|
descriptor.MutateTextStyle(x => x.FontFamily(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T FontSize<T>(this T descriptor, float value) where T : TextSpanDescriptor
|
public static T FontSize<T>(this T descriptor, float value) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.Size = value;
|
descriptor.MutateTextStyle(x => x.FontSize(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T LineHeight<T>(this T descriptor, float value) where T : TextSpanDescriptor
|
public static T LineHeight<T>(this T descriptor, float value) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.LineHeight = value;
|
descriptor.MutateTextStyle(x => x.LineHeight(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Italic<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
public static T Italic<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.IsItalic = value;
|
descriptor.MutateTextStyle(x => x.Italic(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Strikethrough<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
public static T Strikethrough<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.HasStrikethrough = value;
|
descriptor.MutateTextStyle(x => x.Strikethrough(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Underline<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
public static T Underline<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.HasUnderline = value;
|
descriptor.MutateTextStyle(x => x.Underline(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T WrapAnywhere<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
public static T WrapAnywhere<T>(this T descriptor, bool value = true) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
descriptor.TextStyle.WrapAnywhere = value;
|
descriptor.MutateTextStyle(x => x.WrapAnywhere(value));
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Weight
|
#region Weight
|
||||||
|
|
||||||
public static T Weight<T>(this T descriptor, FontWeight weight) where T : TextSpanDescriptor
|
|
||||||
{
|
|
||||||
descriptor.TextStyle.FontWeight = weight;
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T Thin<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Thin<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.Thin);
|
descriptor.MutateTextStyle(x => x.Thin());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T ExtraLight<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T ExtraLight<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.ExtraLight);
|
descriptor.MutateTextStyle(x => x.ExtraLight());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Light<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Light<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.Light);
|
descriptor.MutateTextStyle(x => x.Light());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T NormalWeight<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T NormalWeight<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.Normal);
|
descriptor.MutateTextStyle(x => x.NormalWeight());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Medium<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Medium<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.Medium);
|
descriptor.MutateTextStyle(x => x.Medium());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T SemiBold<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T SemiBold<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.SemiBold);
|
descriptor.MutateTextStyle(x => x.SemiBold());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Bold<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Bold<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.Bold);
|
descriptor.MutateTextStyle(x => x.Bold());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T ExtraBold<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T ExtraBold<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.ExtraBold);
|
descriptor.MutateTextStyle(x => x.ExtraBold());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Black<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Black<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.Black);
|
descriptor.MutateTextStyle(x => x.Black());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T ExtraBlack<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T ExtraBlack<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Weight(FontWeight.ExtraBlack);
|
descriptor.MutateTextStyle(x => x.ExtraBlack());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -132,24 +136,22 @@ namespace QuestPDF.Fluent
|
|||||||
#region Position
|
#region Position
|
||||||
public static T NormalPosition<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T NormalPosition<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Position(FontPosition.Normal);
|
descriptor.MutateTextStyle(x => x.NormalPosition());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Subscript<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Subscript<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Position(FontPosition.Subscript);
|
descriptor.MutateTextStyle(x => x.Subscript());
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Superscript<T>(this T descriptor) where T : TextSpanDescriptor
|
public static T Superscript<T>(this T descriptor) where T : TextSpanDescriptor
|
||||||
{
|
{
|
||||||
return descriptor.Position(FontPosition.Superscript);
|
descriptor.MutateTextStyle(x => x.Superscript());
|
||||||
}
|
|
||||||
|
|
||||||
private static T Position<T>(this T descriptor, FontPosition fontPosition) where T : TextSpanDescriptor
|
|
||||||
{
|
|
||||||
descriptor.TextStyle.FontPosition = fontPosition;
|
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,16 +4,10 @@ using QuestPDF.Infrastructure;
|
|||||||
|
|
||||||
namespace QuestPDF.Fluent
|
namespace QuestPDF.Fluent
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static class TextStyleExtensions
|
public static class TextStyleExtensions
|
||||||
{
|
{
|
||||||
private static TextStyle Mutate(this TextStyle style, Action<TextStyle> handler)
|
|
||||||
{
|
|
||||||
style = style.Clone();
|
|
||||||
|
|
||||||
handler(style);
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("This element has been renamed since version 2022.3. Please use the FontColor method.")]
|
[Obsolete("This element has been renamed since version 2022.3. Please use the FontColor method.")]
|
||||||
public static TextStyle Color(this TextStyle style, string value)
|
public static TextStyle Color(this TextStyle style, string value)
|
||||||
{
|
{
|
||||||
@@ -22,12 +16,12 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static TextStyle FontColor(this TextStyle style, string value)
|
public static TextStyle FontColor(this TextStyle style, string value)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.Color = value);
|
return style.Mutate(TextStyleProperty.Color, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle BackgroundColor(this TextStyle style, string value)
|
public static TextStyle BackgroundColor(this TextStyle style, string value)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.BackgroundColor = value);
|
return style.Mutate(TextStyleProperty.BackgroundColor, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("This element has been renamed since version 2022.3. Please use the FontFamily method.")]
|
[Obsolete("This element has been renamed since version 2022.3. Please use the FontFamily method.")]
|
||||||
@@ -38,7 +32,7 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static TextStyle FontFamily(this TextStyle style, string value)
|
public static TextStyle FontFamily(this TextStyle style, string value)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.FontFamily = value);
|
return style.Mutate(TextStyleProperty.FontFamily, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("This element has been renamed since version 2022.3. Please use the FontSize method.")]
|
[Obsolete("This element has been renamed since version 2022.3. Please use the FontSize method.")]
|
||||||
@@ -49,39 +43,39 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
public static TextStyle FontSize(this TextStyle style, float value)
|
public static TextStyle FontSize(this TextStyle style, float value)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.Size = value);
|
return style.Mutate(TextStyleProperty.Size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle LineHeight(this TextStyle style, float value)
|
public static TextStyle LineHeight(this TextStyle style, float value)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.LineHeight = value);
|
return style.Mutate(TextStyleProperty.LineHeight, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle Italic(this TextStyle style, bool value = true)
|
public static TextStyle Italic(this TextStyle style, bool value = true)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.IsItalic = value);
|
return style.Mutate(TextStyleProperty.IsItalic, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle Strikethrough(this TextStyle style, bool value = true)
|
public static TextStyle Strikethrough(this TextStyle style, bool value = true)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.HasStrikethrough = value);
|
return style.Mutate(TextStyleProperty.HasStrikethrough, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle Underline(this TextStyle style, bool value = true)
|
public static TextStyle Underline(this TextStyle style, bool value = true)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.HasUnderline = value);
|
return style.Mutate(TextStyleProperty.HasUnderline, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle WrapAnywhere(this TextStyle style, bool value = true)
|
public static TextStyle WrapAnywhere(this TextStyle style, bool value = true)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.WrapAnywhere = value);
|
return style.Mutate(TextStyleProperty.WrapAnywhere, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Weight
|
#region Weight
|
||||||
|
|
||||||
public static TextStyle Weight(this TextStyle style, FontWeight weight)
|
public static TextStyle Weight(this TextStyle style, FontWeight weight)
|
||||||
{
|
{
|
||||||
return style.Mutate(x => x.FontWeight = weight);
|
return style.Mutate(TextStyleProperty.FontWeight, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStyle Thin(this TextStyle style)
|
public static TextStyle Thin(this TextStyle style)
|
||||||
@@ -154,10 +148,7 @@ namespace QuestPDF.Fluent
|
|||||||
|
|
||||||
private static TextStyle Position(this TextStyle style, FontPosition fontPosition)
|
private static TextStyle Position(this TextStyle style, FontPosition fontPosition)
|
||||||
{
|
{
|
||||||
if (style.FontPosition == fontPosition)
|
return style.Mutate(TextStyleProperty.FontPosition, fontPosition);
|
||||||
return style;
|
|
||||||
|
|
||||||
return style.Mutate(t => t.FontPosition = fontPosition);
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using QuestPDF.Elements;
|
|||||||
|
|
||||||
namespace QuestPDF.Infrastructure
|
namespace QuestPDF.Infrastructure
|
||||||
{
|
{
|
||||||
internal abstract class ContainerElement : Element, IContainer
|
internal abstract class ContainerElement : Element, IContainer, ICollectable
|
||||||
{
|
{
|
||||||
internal Element? Child { get; set; } = Empty.Instance;
|
internal Element? Child { get; set; } = Empty.Instance;
|
||||||
|
|
||||||
@@ -34,5 +34,10 @@ namespace QuestPDF.Infrastructure
|
|||||||
{
|
{
|
||||||
Child?.Draw(availableSpace);
|
Child?.Draw(availableSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Collect()
|
||||||
|
{
|
||||||
|
Child = default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace QuestPDF.Infrastructure
|
||||||
|
{
|
||||||
|
public interface ICollectable
|
||||||
|
{
|
||||||
|
void Collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,10 +3,8 @@ using QuestPDF.Helpers;
|
|||||||
|
|
||||||
namespace QuestPDF.Infrastructure
|
namespace QuestPDF.Infrastructure
|
||||||
{
|
{
|
||||||
public class TextStyle
|
public record TextStyle
|
||||||
{
|
{
|
||||||
internal bool HasGlobalStyleApplied { get; private set; }
|
|
||||||
|
|
||||||
internal string? Color { get; set; }
|
internal string? Color { get; set; }
|
||||||
internal string? BackgroundColor { get; set; }
|
internal string? BackgroundColor { get; set; }
|
||||||
internal string? FontFamily { get; set; }
|
internal string? FontFamily { get; set; }
|
||||||
@@ -19,13 +17,7 @@ namespace QuestPDF.Infrastructure
|
|||||||
internal bool? HasUnderline { get; set; }
|
internal bool? HasUnderline { get; set; }
|
||||||
internal bool? WrapAnywhere { get; set; }
|
internal bool? WrapAnywhere { get; set; }
|
||||||
|
|
||||||
internal object PaintKey { get; private set; }
|
internal static TextStyle LibraryDefault { get; } = new()
|
||||||
internal object FontMetricsKey { get; private set; }
|
|
||||||
|
|
||||||
// REVIEW: Should this be a method call that news up a TextStyle,
|
|
||||||
// or can it be a static variable?
|
|
||||||
// (style mutations seem to create a clone anyway)
|
|
||||||
internal static readonly TextStyle LibraryDefault = new TextStyle
|
|
||||||
{
|
{
|
||||||
Color = Colors.Black,
|
Color = Colors.Black,
|
||||||
BackgroundColor = Colors.Transparent,
|
BackgroundColor = Colors.Transparent,
|
||||||
@@ -40,56 +32,6 @@ namespace QuestPDF.Infrastructure
|
|||||||
WrapAnywhere = false
|
WrapAnywhere = false
|
||||||
};
|
};
|
||||||
|
|
||||||
// it is important to create new instances for the DefaultTextStyle element to work correctly
|
public static TextStyle Default { get; } = new();
|
||||||
public static TextStyle Default => new TextStyle();
|
|
||||||
|
|
||||||
internal void ApplyGlobalStyle(TextStyle globalStyle)
|
|
||||||
{
|
|
||||||
if (HasGlobalStyleApplied)
|
|
||||||
return;
|
|
||||||
|
|
||||||
HasGlobalStyleApplied = true;
|
|
||||||
|
|
||||||
ApplyParentStyle(globalStyle);
|
|
||||||
PaintKey ??= (FontFamily, Size, FontWeight, FontPosition, IsItalic, Color);
|
|
||||||
FontMetricsKey ??= (FontFamily, Size, FontWeight, IsItalic);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ApplyParentStyle(TextStyle parentStyle)
|
|
||||||
{
|
|
||||||
Color ??= parentStyle.Color;
|
|
||||||
BackgroundColor ??= parentStyle.BackgroundColor;
|
|
||||||
FontFamily ??= parentStyle.FontFamily;
|
|
||||||
Size ??= parentStyle.Size;
|
|
||||||
LineHeight ??= parentStyle.LineHeight;
|
|
||||||
FontWeight ??= parentStyle.FontWeight;
|
|
||||||
FontPosition ??= parentStyle.FontPosition;
|
|
||||||
IsItalic ??= parentStyle.IsItalic;
|
|
||||||
HasStrikethrough ??= parentStyle.HasStrikethrough;
|
|
||||||
HasUnderline ??= parentStyle.HasUnderline;
|
|
||||||
WrapAnywhere ??= parentStyle.WrapAnywhere;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void OverrideStyle(TextStyle parentStyle)
|
|
||||||
{
|
|
||||||
Color = parentStyle.Color ?? Color;
|
|
||||||
BackgroundColor = parentStyle.BackgroundColor ?? BackgroundColor;
|
|
||||||
FontFamily = parentStyle.FontFamily ?? FontFamily;
|
|
||||||
Size = parentStyle.Size ?? Size;
|
|
||||||
LineHeight = parentStyle.LineHeight ?? LineHeight;
|
|
||||||
FontWeight = parentStyle.FontWeight ?? FontWeight;
|
|
||||||
FontPosition = parentStyle.FontPosition ?? FontPosition;
|
|
||||||
IsItalic = parentStyle.IsItalic ?? IsItalic;
|
|
||||||
HasStrikethrough = parentStyle.HasStrikethrough ?? HasStrikethrough;
|
|
||||||
HasUnderline = parentStyle.HasUnderline ?? HasUnderline;
|
|
||||||
WrapAnywhere = parentStyle.WrapAnywhere ?? WrapAnywhere;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal TextStyle Clone()
|
|
||||||
{
|
|
||||||
var clone = (TextStyle)MemberwiseClone();
|
|
||||||
clone.HasGlobalStyleApplied = false;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using QuestPDF.Fluent;
|
||||||
|
|
||||||
|
namespace QuestPDF.Infrastructure
|
||||||
|
{
|
||||||
|
internal enum TextStyleProperty
|
||||||
|
{
|
||||||
|
Color,
|
||||||
|
BackgroundColor,
|
||||||
|
FontFamily,
|
||||||
|
Size,
|
||||||
|
LineHeight,
|
||||||
|
FontWeight,
|
||||||
|
FontPosition,
|
||||||
|
IsItalic,
|
||||||
|
HasStrikethrough,
|
||||||
|
HasUnderline,
|
||||||
|
WrapAnywhere
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class TextStyleManager
|
||||||
|
{
|
||||||
|
public static ConcurrentDictionary<(TextStyle origin, TextStyleProperty property, object value), TextStyle> TextStyleMutateCache = new();
|
||||||
|
public static ConcurrentDictionary<(TextStyle origin, TextStyle parent, bool overrideValue), TextStyle> TextStyleApplyCache = new();
|
||||||
|
|
||||||
|
public static TextStyle Mutate(this TextStyle origin, TextStyleProperty property, object value)
|
||||||
|
{
|
||||||
|
var cacheKey = (origin, property, value);
|
||||||
|
return TextStyleMutateCache.GetOrAdd(cacheKey, x => MutateStyle(x.origin, x.property, x.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextStyle MutateStyle(TextStyle origin, TextStyleProperty property, object value, bool overrideValue = true)
|
||||||
|
{
|
||||||
|
if (overrideValue && value == null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.Color)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.Color != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (string?)value;
|
||||||
|
|
||||||
|
if (origin.Color == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { Color = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.BackgroundColor)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.BackgroundColor != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (string?)value;
|
||||||
|
|
||||||
|
if (origin.BackgroundColor == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { BackgroundColor = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.FontFamily)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.FontFamily != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (string?)value;
|
||||||
|
|
||||||
|
if (origin.FontFamily == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { FontFamily = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.Size)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.Size != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (float?)value;
|
||||||
|
|
||||||
|
if (origin.Size == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { Size = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.LineHeight)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.LineHeight != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (float?)value;
|
||||||
|
|
||||||
|
if (origin.LineHeight == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { LineHeight = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.FontWeight)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.FontWeight != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (FontWeight?)value;
|
||||||
|
|
||||||
|
if (origin.FontWeight == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { FontWeight = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.FontPosition)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.FontPosition != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (FontPosition?)value;
|
||||||
|
|
||||||
|
if (origin.FontPosition == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { FontPosition = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.IsItalic)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.IsItalic != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (bool?)value;
|
||||||
|
|
||||||
|
if (origin.IsItalic == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { IsItalic = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.HasStrikethrough)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.HasStrikethrough != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (bool?)value;
|
||||||
|
|
||||||
|
if (origin.HasStrikethrough == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { HasStrikethrough = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.HasUnderline)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.HasUnderline != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (bool?)value;
|
||||||
|
|
||||||
|
if (origin.HasUnderline == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { HasUnderline = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property == TextStyleProperty.WrapAnywhere)
|
||||||
|
{
|
||||||
|
if (!overrideValue && origin.WrapAnywhere != null)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
var castedValue = (bool?)value;
|
||||||
|
|
||||||
|
if (origin.WrapAnywhere == castedValue)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
return origin with { WrapAnywhere = castedValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(property), property, "Expected to mutate the TextStyle object. Provided property type is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static TextStyle ApplyGlobalStyle(this TextStyle style, TextStyle parent)
|
||||||
|
{
|
||||||
|
var cacheKey = (style, parent, false);
|
||||||
|
return TextStyleApplyCache.GetOrAdd(cacheKey, key => ApplyStyle(key.origin, key.parent, key.overrideValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static TextStyle OverrideStyle(this TextStyle style, TextStyle parent)
|
||||||
|
{
|
||||||
|
var cacheKey = (style, parent, true);
|
||||||
|
return TextStyleApplyCache.GetOrAdd(cacheKey, key => ApplyStyle(key.origin, key.parent, key.overrideValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextStyle ApplyStyle(TextStyle style, TextStyle parent, bool overrideValue)
|
||||||
|
{
|
||||||
|
var result = style;
|
||||||
|
|
||||||
|
result = MutateStyle(result, TextStyleProperty.Color, parent.Color, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.BackgroundColor, parent.BackgroundColor, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.FontFamily, parent.FontFamily, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.Size, parent.Size, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.LineHeight, parent.LineHeight, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.FontWeight, parent.FontWeight, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.FontPosition, parent.FontPosition, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.IsItalic, parent.IsItalic, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.HasStrikethrough, parent.HasStrikethrough, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.HasUnderline, parent.HasUnderline, overrideValue);
|
||||||
|
result = MutateStyle(result, TextStyleProperty.WrapAnywhere, parent.WrapAnywhere, overrideValue);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user