Compare commits

...

1 Commits

Author SHA1 Message Date
MarcinZiabek 69b54eed5d General concept of RTL support 2022-06-12 15:13:26 +02:00
13 changed files with 135 additions and 63 deletions
+26 -58
View File
@@ -8,58 +8,8 @@ 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 = "ينا الألم. في بعض الأحيان ونظراً للالتزامات التي يفرضها علينا";
//
// var text = arabic;
// var metrics = textPaint.FontMetrics;
//
// container
// .Padding(25)
// .Canvas((canvas, space) =>
// {
// canvas.Translate(0, 20);
//
// var width = MeasureText(text, textPaint);
// var widthReal = textPaint.MeasureText(text);
// canvas.DrawRect(0, metrics.Descent, width, metrics.Ascent - metrics.Descent, backgroundPaint);
//
// canvas.DrawShapedText(text, 0, 0, textPaint);
//
// canvas.Translate(0, 40);
// canvas.DrawText(text, 0, 0, textPaint);
// });
// });
// }
[Test]
public void MeasureTest()
public void ShapeText()
{
using var textPaint = new SKPaint
{
@@ -68,12 +18,30 @@ namespace QuestPDF.Examples
IsAntialias = true,
TextSize = 20
};
var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec odio ipsum, aliquam a neque a, lacinia vehicula lectus.";
var arabic = "ينا الألم. في بعض الأحيان ونظراً للالتزامات التي يفرضها علينا";
// 012345678901234567890123456789012345678901234567890123456
var shaper = new SKShaper(textPaint.Typeface);
var result = shaper.Shape(lorem, textPaint);
}
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);
});
}
}
}
@@ -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() ?? "-----");
+18
View File
@@ -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);
}
}
}
+9
View File
@@ -0,0 +1,9 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.Proxy
{
internal class DirectionProxy : ContainerElement
{
}
}
+1
View File
@@ -25,6 +25,7 @@ namespace QuestPDF.Drawing
PopulateBufferWithText(buffer, text);
buffer.GuessSegmentProperties();
//buffer.Direction = Direction.RightToLeft;
Font.Shape(buffer);
+9
View File
@@ -0,0 +1,9 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class ContentDirection : ContainerElement
{
public ContentDirectionType Direction { get; set; }
}
}
+3
View File
@@ -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 =>
{
+9 -3
View File
@@ -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);
}
}
}
+10
View File
@@ -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; }
}
}