161 lines
5.8 KiB
C#
161 lines
5.8 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using NUnit.Framework;
|
|
using QuestPDF.Drawing;
|
|
using QuestPDF.Examples.Engine;
|
|
using QuestPDF.Fluent;
|
|
using QuestPDF.Helpers;
|
|
using QuestPDF.Infrastructure;
|
|
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 = "ينا الألم. في بعض الأحيان ونظراً للالتزامات التي يفرضها علينا";
|
|
|
|
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);
|
|
});
|
|
});
|
|
}
|
|
|
|
float MeasureText(string text, SKPaint paint)
|
|
{
|
|
var font = paint.ToFont();
|
|
using var shaper = new SKShaper(paint.Typeface);
|
|
var result = shaper.Shape(text + " ", paint);
|
|
return Math.Max(result.Points.First().X, result.Points.Last().X);
|
|
|
|
var glyphCount = result.Codepoints.Length;
|
|
var glyphIds = new ushort[glyphCount];
|
|
var glyphWidths = new float[glyphCount];
|
|
var glyphBounds = new SKRect[glyphCount];
|
|
|
|
font.GetGlyphs(result.Codepoints.Select(x => (int)x).ToArray(), glyphIds);
|
|
font.GetGlyphWidths(glyphIds, glyphWidths, glyphBounds);
|
|
|
|
return glyphWidths.Sum();
|
|
|
|
return result.Points.Max(p => p.X);
|
|
|
|
using var skTextBlobBuilder = new SKTextBlobBuilder();
|
|
|
|
var positionedRunBuffer = skTextBlobBuilder.AllocatePositionedRun(font, result.Codepoints.Length);
|
|
var glyphSpan = positionedRunBuffer.GetGlyphSpan();
|
|
var positionSpan = positionedRunBuffer.GetPositionSpan();
|
|
|
|
for (int index = 0; index < result.Codepoints.Length; ++index)
|
|
{
|
|
glyphSpan[index] = (ushort) result.Codepoints[index];
|
|
positionSpan[index] = result.Points[index];
|
|
}
|
|
|
|
using var text1 = skTextBlobBuilder.Build();
|
|
return text1.Bounds.Width;
|
|
}
|
|
|
|
[Test]
|
|
public void ShapeSingle()
|
|
{
|
|
using var textPaint = new SKPaint
|
|
{
|
|
Color = SKColors.Black,
|
|
Typeface = SKTypeface.CreateDefault(),
|
|
IsAntialias = true,
|
|
TextSize = 20
|
|
};
|
|
|
|
var text = string.Join(" ", Enumerable.Range(0, 10_000).Select(x => Placeholders.Sentence()));
|
|
|
|
using var shaper = new SKShaper(textPaint.Typeface);
|
|
var result = shaper.Shape(text + " ", textPaint);
|
|
}
|
|
|
|
[Test]
|
|
public void ShapeMany()
|
|
{
|
|
using var textPaint = new SKPaint
|
|
{
|
|
Color = SKColors.Black,
|
|
Typeface = SKTypeface.CreateDefault(),
|
|
IsAntialias = true,
|
|
TextSize = 20
|
|
};
|
|
|
|
var text = string.Join(" ", Enumerable.Range(0, 1_000).Select(x => Placeholders.Sentence()));
|
|
|
|
foreach (var part in Regex.Split(text, "( )|(\\w+)"))
|
|
{
|
|
using var shaper = new SKShaper(textPaint.Typeface);
|
|
var result = shaper.Shape(part + " ", textPaint);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ShapeMany2()
|
|
{
|
|
using var textPaint = new SKPaint
|
|
{
|
|
Color = SKColors.Black,
|
|
Typeface = SKTypeface.CreateDefault(),
|
|
IsAntialias = true,
|
|
TextSize = 20
|
|
};
|
|
|
|
using var shaper = new SKShaper(textPaint.Typeface);
|
|
|
|
foreach (var i in Enumerable.Range(0, 10_000))
|
|
{
|
|
var text = Placeholders.Paragraph();
|
|
|
|
textPaint.MeasureText(text);
|
|
var result = shaper.Shape(text + " ", textPaint);
|
|
}
|
|
}
|
|
}
|
|
} |