Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69b54eed5d |
@@ -11,7 +11,7 @@
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.4" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
<PackageReference Include="Svg.Skia" Version="0.5.10" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -567,55 +567,5 @@ namespace QuestPDF.Examples
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextShaping_Unicode()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(600, 100)
|
||||
|
||||
.ProduceImages()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(35)
|
||||
.MinimalBox()
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default.FontSize(20));
|
||||
|
||||
text.Span("Complex Unicode structure: ");
|
||||
|
||||
|
||||
text.Span("T̶̖̔͆͆̽̔ḩ̷̼̫̐̈́̀͜͝͝ì̶͇̤͓̱̣͇͓͉̎s̵̡̟̹͍̜͉̗̾͛̈̐́͋͂͝͠ͅ ̴̨͙͍͇̭̒͗̀́͝ì̷̡̺͉̼̏̏̉̌͝s̷͍͙̗̰̖͙̈̑̂̔͑͊̌̓̊̇͜ ̶̛̼͚͊̅͘ṭ̷̨̘̣̙̖͉͌̏̂̅͑̄̽̕͝ȅ̶̲̲̙̭͈̬̣͔̝͔̈́͝s̸̢̯̪̫͓̭̮̓̀͆͜ț̸̢͉̞̥̤̏̌̓͝").FontColor(Colors.Red.Medium);
|
||||
|
||||
|
||||
text.Span(".");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextShaping_Arabic()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 100)
|
||||
|
||||
.ProduceImages()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.MinimalBox()
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Text("ينا الألم. في بعض الأحيان ونظراً للالتزامات التي يفرضها علينا")
|
||||
.FontSize(20);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class TextShapingTests
|
||||
{
|
||||
[Test]
|
||||
public void ShapeText()
|
||||
{
|
||||
using var textPaint = new SKPaint
|
||||
{
|
||||
Color = SKColors.Black,
|
||||
Typeface = SKTypeface.CreateDefault(),
|
||||
IsAntialias = true,
|
||||
TextSize = 20
|
||||
};
|
||||
|
||||
using var backgroundPaint = new SKPaint
|
||||
{
|
||||
Color = SKColors.LightGray
|
||||
};
|
||||
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(550, 250)
|
||||
.ProduceImages()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
//var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec odio ipsum, aliquam a neque a, lacinia vehicula lectus.";
|
||||
//var arabic = "ينا الألم. في بعض الأحيان ونظراً للالتزامات التي يفرضها علينا الواجب والعمل سنتنازل غالباً ونرفض الشعور";
|
||||
|
||||
var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
var arabic = "ينا الألم. في بعض (5000) الأحيان ونظراً للالتزامات التي يفرضها علينا";
|
||||
|
||||
container
|
||||
.Padding(25)
|
||||
.Text(arabic)
|
||||
.FontSize(25);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,8 +48,7 @@
|
||||
<PackageReference Include="Avalonia.Markup.Xaml.Loader" Version="0.10.10" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.10" />
|
||||
<PackageReference Include="ReactiveUI" Version="17.1.50" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.80.4" />
|
||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.4" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -33,10 +33,11 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
page.MarginHorizontal(50);
|
||||
|
||||
page.Size(PageSizes.A4);
|
||||
page.ContentDirectionRightToLeft();
|
||||
|
||||
page.Header().Element(ComposeHeader);
|
||||
page.Content().Element(ComposeContent);
|
||||
|
||||
|
||||
page.Footer().AlignCenter().Text(text =>
|
||||
{
|
||||
text.CurrentPageNumber().Format(x => x?.FormatAsRomanNumeral() ?? "-----");
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.4" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.4" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace QuestPDF.Drawing
|
||||
document.Compose(container);
|
||||
var content = container.Compose();
|
||||
ApplyDefaultTextStyle(content, TextStyle.LibraryDefault);
|
||||
ApplyContentDirection(content);
|
||||
|
||||
var metadata = document.GetMetadata();
|
||||
var pageContext = new PageContext();
|
||||
@@ -199,5 +200,22 @@ namespace QuestPDF.Drawing
|
||||
foreach (var child in content.GetChildren())
|
||||
ApplyDefaultTextStyle(child, targetTextStyle);
|
||||
}
|
||||
|
||||
internal static void ApplyContentDirection(this Element? content, ContentDirectionType contentDirectionType = ContentDirectionType.LeftToRight)
|
||||
{
|
||||
if (content == null)
|
||||
return;
|
||||
|
||||
var targetDirection = contentDirectionType;
|
||||
|
||||
if (content is ContentDirection contentDirection)
|
||||
targetDirection = contentDirection.Direction;
|
||||
|
||||
if (content is IContentDirectionAware contentDirectionAware)
|
||||
contentDirectionAware.ContentDirection = targetDirection;
|
||||
|
||||
foreach (var child in content.GetChildren())
|
||||
ApplyContentDirection(child, targetDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Drawing.Proxy
|
||||
{
|
||||
internal class DirectionProxy : ContainerElement
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ namespace QuestPDF.Drawing
|
||||
|
||||
PopulateBufferWithText(buffer, text);
|
||||
buffer.GuessSegmentProperties();
|
||||
//buffer.Direction = Direction.RightToLeft;
|
||||
|
||||
Font.Shape(buffer);
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements
|
||||
{
|
||||
internal class ContentDirection : ContainerElement
|
||||
{
|
||||
public ContentDirectionType Direction { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ namespace QuestPDF.Elements
|
||||
public float MarginBottom { get; set; }
|
||||
|
||||
public string BackgroundColor { get; set; } = Colors.Transparent;
|
||||
|
||||
public ContentDirectionType ContentDirection { get; set; } = ContentDirectionType.LeftToRight;
|
||||
|
||||
public Element Background { get; set; } = Empty.Instance;
|
||||
public Element Foreground { get; set; } = Empty.Instance;
|
||||
@@ -30,6 +32,7 @@ namespace QuestPDF.Elements
|
||||
public void Compose(IContainer container)
|
||||
{
|
||||
container
|
||||
.ContentDirection(ContentDirection)
|
||||
.Background(BackgroundColor)
|
||||
.Layers(layers =>
|
||||
{
|
||||
|
||||
@@ -8,11 +8,13 @@ using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text
|
||||
{
|
||||
internal class TextBlock : Element, IStateResettable
|
||||
internal class TextBlock : Element, IContentDirectionAware, IStateResettable
|
||||
{
|
||||
public HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
||||
public List<ITextBlockItem> Items { get; set; } = new List<ITextBlockItem>();
|
||||
|
||||
public ContentDirectionType ContentDirection { get; set; }
|
||||
|
||||
public string Text => string.Join(" ", Items.Where(x => x is TextBlockSpan).Cast<TextBlockSpan>().Select(x => x.Text));
|
||||
|
||||
private Queue<ITextBlockItem> RenderingQueue { get; set; }
|
||||
@@ -69,8 +71,12 @@ namespace QuestPDF.Elements.Text
|
||||
|
||||
Canvas.Translate(new Position(alignmentOffset, 0));
|
||||
Canvas.Translate(new Position(0, -line.Ascent));
|
||||
|
||||
foreach (var item in line.Elements)
|
||||
|
||||
var elements = ContentDirection == ContentDirectionType.LeftToRight
|
||||
? line.Elements
|
||||
: line.Elements.Reverse();
|
||||
|
||||
foreach (var item in elements)
|
||||
{
|
||||
var textDrawingRequest = new TextDrawingRequest
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Linq.Expressions;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Fluent
|
||||
{
|
||||
public static class ContentDirectionExtensions
|
||||
{
|
||||
internal static IContainer ContentDirection(this IContainer element, ContentDirectionType contentDirectionType)
|
||||
{
|
||||
var contentDirection = new ContentDirection
|
||||
{
|
||||
Direction = contentDirectionType
|
||||
};
|
||||
|
||||
return element.Element(contentDirection);
|
||||
}
|
||||
|
||||
public static IContainer ContentDirectionLeftToRight(this IContainer element)
|
||||
{
|
||||
return element.ContentDirection(ContentDirectionType.LeftToRight);
|
||||
}
|
||||
|
||||
public static IContainer ContentDirectionRightToLeft(this IContainer element)
|
||||
{
|
||||
return element.ContentDirection(ContentDirectionType.RightToLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,16 @@ namespace QuestPDF.Fluent
|
||||
DefaultTextStyle(handler(TextStyle.Default));
|
||||
}
|
||||
|
||||
public void ContentDirectionLeftToRight()
|
||||
{
|
||||
Page.ContentDirection = ContentDirectionType.LeftToRight;
|
||||
}
|
||||
|
||||
public void ContentDirectionRightToLeft()
|
||||
{
|
||||
Page.ContentDirection = ContentDirectionType.RightToLeft;
|
||||
}
|
||||
|
||||
public void PageColor(string color)
|
||||
{
|
||||
Page.BackgroundColor = color;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace QuestPDF.Infrastructure
|
||||
{
|
||||
public enum ContentDirectionType
|
||||
{
|
||||
LeftToRight,
|
||||
RightToLeft
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ namespace QuestPDF.Infrastructure
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
Right,
|
||||
|
||||
Start,
|
||||
End
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace QuestPDF.Infrastructure
|
||||
{
|
||||
internal interface IContentDirectionAware
|
||||
{
|
||||
public ContentDirectionType ContentDirection { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<Authors>MarcinZiabek</Authors>
|
||||
<Company>CodeFlint</Company>
|
||||
<PackageId>QuestPDF</PackageId>
|
||||
<Version>2022.6.0</Version>
|
||||
<Version>2022.6.0-prerelease</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>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt"))</PackageReleaseNotes>
|
||||
<LangVersion>9</LangVersion>
|
||||
@@ -23,8 +23,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.4" />
|
||||
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.80.4" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
Integrated the text-shaping algorithm. This change significantly improves the Unicode compatibility. Also, it extends support for more advanced languages (e.g. Arabic) that:
|
||||
1) Combine multiple text characters and display them as a single visual glyph.
|
||||
2) Are displayed in the right-to-left order.
|
||||
|
||||
Improved the exception message when SkiaSharp throws the TypeInitializationException. On some operating systems, SkiaSharp requires additional dependencies installed as nuget packages. This change should help developers determine how to choose and install them correctly.
|
||||
|
||||
Fixed: a rare case when the Row.AutoItem() does not correctly calculate the width of its content.
|
||||
|
||||
Implemented support for the text shaping algorithm that fixes rendering more advanced languages such as Arabic.
|
||||
Improved exception message when SkiaSharp throws the TypeInitializationException (when additional dependencies are needed).
|
||||
Fixed: a rare case when the Row.AutoItem does not calculate properly the width of its content.
|
||||
Fixed: the QuestPDF Previewer does not work with content-rich documents.
|
||||
|
||||
@@ -59,7 +59,7 @@ Install-Package QuestPDF
|
||||
dotnet add package QuestPDF
|
||||
|
||||
// Package reference in .csproj file
|
||||
<PackageReference Include="QuestPDF" Version="2022.6.0" />
|
||||
<PackageReference Include="QuestPDF" Version="2022.5.0" />
|
||||
```
|
||||
|
||||
[](https://www.nuget.org/packages/QuestPDF/)
|
||||
|
||||
Reference in New Issue
Block a user