|
|
@@ -1,16 +1,16 @@
|
|
|
using System;
|
|
|
-using System.Drawing;
|
|
|
-using System.Runtime.InteropServices;
|
|
|
using QuestPDF.Drawing;
|
|
|
using QuestPDF.Drawing.SpacePlan;
|
|
|
using QuestPDF.Infrastructure;
|
|
|
-using SkiaSharp;
|
|
|
using Size = QuestPDF.Infrastructure.Size;
|
|
|
|
|
|
-namespace QuestPDF.Elements
|
|
|
+namespace QuestPDF.Elements.Text
|
|
|
{
|
|
|
internal class TextMeasurementRequest
|
|
|
{
|
|
|
+ public ICanvas Canvas { get; set; }
|
|
|
+ public IPageContext PageContext { get; set; }
|
|
|
+
|
|
|
public int StartIndex { get; set; }
|
|
|
public float AvailableWidth { get; set; }
|
|
|
}
|
|
|
@@ -19,10 +19,12 @@ namespace QuestPDF.Elements
|
|
|
{
|
|
|
public float Width { get; set; }
|
|
|
public float Height => Math.Abs(Descent) + Math.Abs(Ascent);
|
|
|
-
|
|
|
+
|
|
|
public float Ascent { get; set; }
|
|
|
public float Descent { get; set; }
|
|
|
|
|
|
+ public float LineHeight { get; set; }
|
|
|
+
|
|
|
public int StartIndex { get; set; }
|
|
|
public int EndIndex { get; set; }
|
|
|
|
|
|
@@ -32,86 +34,30 @@ namespace QuestPDF.Elements
|
|
|
public bool IsLast => EndIndex == TotalIndex;
|
|
|
}
|
|
|
|
|
|
- public class TextDrawingRequest
|
|
|
+ internal class TextDrawingRequest
|
|
|
{
|
|
|
+ public ICanvas Canvas { get; set; }
|
|
|
+ public IPageContext PageContext { get; set; }
|
|
|
+
|
|
|
public int StartIndex { get; set; }
|
|
|
public int EndIndex { get; set; }
|
|
|
|
|
|
public float TotalAscent { get; set; }
|
|
|
public Size TextSize { get; set; }
|
|
|
}
|
|
|
+
|
|
|
+ internal interface ITextElement
|
|
|
+ {
|
|
|
+ TextMeasurementResult? Measure(TextMeasurementRequest request);
|
|
|
+ void Draw(TextDrawingRequest request);
|
|
|
+ }
|
|
|
|
|
|
- internal class TextItem : Element, IStateResettable
|
|
|
+ internal class TextItem : ITextElement
|
|
|
{
|
|
|
public string Text { get; set; }
|
|
|
-
|
|
|
public TextStyle Style { get; set; } = new TextStyle();
|
|
|
- internal int PointerIndex { get; set; }
|
|
|
-
|
|
|
- public void ResetState()
|
|
|
- {
|
|
|
- PointerIndex = 0;
|
|
|
- }
|
|
|
-
|
|
|
- internal override ISpacePlan Measure(Size availableSpace)
|
|
|
- {
|
|
|
- return new FullRender(Size.Zero);
|
|
|
-
|
|
|
- // if (VirtualPointer >= Text.Length)
|
|
|
- // return new FullRender(Size.Zero);
|
|
|
- //
|
|
|
- // var paint = Style.ToPaint();
|
|
|
- // var metrics = paint.FontMetrics;
|
|
|
- //
|
|
|
- // var length = (int)paint.BreakText(Text, availableSpace.Width);
|
|
|
- // length = VirtualPointer + Text.Substring(VirtualPointer, length).LastIndexOf(" ");
|
|
|
- //
|
|
|
- // var textFragment = Text.Substring(VirtualPointer, length);
|
|
|
- //
|
|
|
- // var width = paint.MeasureText(textFragment);
|
|
|
- // var height = Math.Abs(metrics.Descent) + Math.Abs(metrics.Ascent);
|
|
|
- //
|
|
|
- // if (availableSpace.Width < width || availableSpace.Height < height)
|
|
|
- // return new Wrap();
|
|
|
- //
|
|
|
- // VirtualPointer += length;
|
|
|
- //
|
|
|
- // return new TextRender(width, height)
|
|
|
- // {
|
|
|
- // Descent = metrics.Descent,
|
|
|
- // Ascent = metrics.Ascent
|
|
|
- // };
|
|
|
- }
|
|
|
-
|
|
|
- internal override void Draw(Size availableSpace)
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- internal void Draw(TextDrawingRequest request)
|
|
|
- {
|
|
|
- var fontMetrics = Style.ToPaint().FontMetrics;
|
|
|
-
|
|
|
- var text = Text.Substring(request.StartIndex, request.EndIndex - request.StartIndex);
|
|
|
-
|
|
|
- Canvas.DrawRectangle(new Position(0, request.TotalAscent), new Size(request.TextSize.Width, request.TextSize.Height), Style.BackgroundColor);
|
|
|
- Canvas.DrawText(text, Position.Zero, Style);
|
|
|
-
|
|
|
- // draw underline
|
|
|
- if (Style.IsUnderlined && fontMetrics.UnderlinePosition.HasValue)
|
|
|
- DrawLine(fontMetrics.UnderlinePosition.Value, fontMetrics.UnderlineThickness.Value);
|
|
|
-
|
|
|
- // draw stroke
|
|
|
- if (Style.IsStroked && fontMetrics.StrikeoutPosition.HasValue)
|
|
|
- DrawLine(fontMetrics.StrikeoutPosition.Value, fontMetrics.StrikeoutThickness.Value);
|
|
|
-
|
|
|
- void DrawLine(float offset, float thickness)
|
|
|
- {
|
|
|
- Canvas.DrawRectangle(new Position(0, offset - thickness / 2f), new Size(request.TextSize.Width, thickness), Style.Color);
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- internal TextMeasurementResult? MeasureText(TextMeasurementRequest request)
|
|
|
+ public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
|
|
{
|
|
|
var paint = Style.ToPaint();
|
|
|
|
|
|
@@ -129,6 +75,8 @@ namespace QuestPDF.Elements
|
|
|
|
|
|
if (breakingIndex <= 0)
|
|
|
return null;
|
|
|
+
|
|
|
+ breakingIndex += 1;
|
|
|
}
|
|
|
|
|
|
text = text.Substring(0, breakingIndex);
|
|
|
@@ -143,10 +91,66 @@ namespace QuestPDF.Elements
|
|
|
Ascent = paint.FontMetrics.Ascent,
|
|
|
Descent = paint.FontMetrics.Descent,
|
|
|
|
|
|
+ LineHeight = Style.LineHeight,
|
|
|
+
|
|
|
StartIndex = request.StartIndex,
|
|
|
EndIndex = request.StartIndex + breakingIndex,
|
|
|
TotalIndex = Text.Length
|
|
|
};
|
|
|
}
|
|
|
+
|
|
|
+ public void Draw(TextDrawingRequest request)
|
|
|
+ {
|
|
|
+ var fontMetrics = Style.ToPaint().FontMetrics;
|
|
|
+
|
|
|
+ var text = Text.Substring(request.StartIndex, request.EndIndex - request.StartIndex);
|
|
|
+
|
|
|
+ request.Canvas.DrawRectangle(new Position(0, request.TotalAscent), new Size(request.TextSize.Width, request.TextSize.Height), Style.BackgroundColor);
|
|
|
+ request.Canvas.DrawText(text, Position.Zero, Style);
|
|
|
+
|
|
|
+ // draw underline
|
|
|
+ if (Style.IsUnderlined && fontMetrics.UnderlinePosition.HasValue)
|
|
|
+ DrawLine(fontMetrics.UnderlinePosition.Value, fontMetrics.UnderlineThickness.Value);
|
|
|
+
|
|
|
+ // draw stroke
|
|
|
+ if (Style.IsStroked && fontMetrics.StrikeoutPosition.HasValue)
|
|
|
+ DrawLine(fontMetrics.StrikeoutPosition.Value, fontMetrics.StrikeoutThickness.Value);
|
|
|
+
|
|
|
+ void DrawLine(float offset, float thickness)
|
|
|
+ {
|
|
|
+ request.Canvas.DrawRectangle(new Position(0, offset - thickness / 2f), new Size(request.TextSize.Width, thickness), Style.Color);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ internal class PageNumberTextItem : ITextElement
|
|
|
+ {
|
|
|
+ public TextStyle Style { get; set; } = new TextStyle();
|
|
|
+ public string SlotName { get; set; }
|
|
|
+
|
|
|
+ public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
|
|
+ {
|
|
|
+ return GetItem(request.PageContext).Measure(request);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Draw(TextDrawingRequest request)
|
|
|
+ {
|
|
|
+ GetItem(request.PageContext).Draw(request);
|
|
|
+ }
|
|
|
+
|
|
|
+ private TextItem GetItem(IPageContext context)
|
|
|
+ {
|
|
|
+ var pageNumberPlaceholder = 123;
|
|
|
+
|
|
|
+ var pageNumber = context.GetRegisteredLocations().Contains(SlotName)
|
|
|
+ ? context.GetLocationPage(SlotName)
|
|
|
+ : pageNumberPlaceholder;
|
|
|
+
|
|
|
+ return new TextItem
|
|
|
+ {
|
|
|
+ Style = Style,
|
|
|
+ Text = pageNumber.ToString()
|
|
|
+ };
|
|
|
+ }
|
|
|
}
|
|
|
}
|