Code structure improvements
This commit is contained in:
Родитель
a08a7b85c9
Коммит
bb8e590fc6
|
@ -0,0 +1,16 @@
|
|||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Calculation
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuestPDF.Elements.Text.Items;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Calculation
|
||||
{
|
||||
internal class TextLine
|
||||
{
|
||||
public ICollection<TextLineElement> Elements { get; set; }
|
||||
|
||||
public float TextHeight => Elements.Max(x => x.Measurement.Height);
|
||||
public float LineHeight => Elements.Max(x => x.Measurement.LineHeight * x.Measurement.Height);
|
||||
|
||||
public float Ascent => Elements.Min(x => x.Measurement.Ascent) - (LineHeight - TextHeight) / 2;
|
||||
public float Descent => Elements.Max(x => x.Measurement.Descent) + (LineHeight - TextHeight) / 2;
|
||||
|
||||
public float Width => Elements.Sum(x => x.Measurement.Width);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using QuestPDF.Elements.Text.Calculation;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal class TextLineElement
|
||||
{
|
||||
public ITextBlockElement Element { get; set; }
|
||||
public TextMeasurementResult Measurement { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Calculation
|
||||
{
|
||||
internal class TextMeasurementRequest
|
||||
{
|
||||
public ICanvas Canvas { get; set; }
|
||||
public IPageContext PageContext { get; set; }
|
||||
|
||||
public int StartIndex { get; set; }
|
||||
public float AvailableWidth { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Calculation
|
||||
{
|
||||
internal class TextMeasurementResult
|
||||
{
|
||||
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; }
|
||||
public int TotalIndex { get; set; }
|
||||
|
||||
public bool IsLast => EndIndex == TotalIndex;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using QuestPDF.Elements.Text.Calculation;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal interface ITextBlockElement
|
||||
{
|
||||
TextMeasurementResult? Measure(TextMeasurementRequest request);
|
||||
void Draw(TextDrawingRequest request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using QuestPDF.Drawing.SpacePlan;
|
||||
using QuestPDF.Elements.Text.Calculation;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal class TextBlockElement : ITextBlockElement
|
||||
{
|
||||
public Element Element { get; set; } = Empty.Instance;
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
Element.HandleVisitor(x => (x as IStateResettable)?.ResetState());
|
||||
Element.HandleVisitor(x => x.Initialize(request.PageContext, request.Canvas));
|
||||
|
||||
var measurement = Element.Measure(new Size(request.AvailableWidth, Size.Max.Height));
|
||||
|
||||
if (measurement is Wrap || measurement is PartialRender)
|
||||
return null;
|
||||
|
||||
var elementSize = measurement as Size;
|
||||
|
||||
return new TextMeasurementResult
|
||||
{
|
||||
Width = elementSize.Width,
|
||||
|
||||
Ascent = -elementSize.Height,
|
||||
Descent = 0,
|
||||
|
||||
LineHeight = 1,
|
||||
|
||||
StartIndex = 0,
|
||||
EndIndex = 0,
|
||||
TotalIndex = 0
|
||||
};
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
Element.HandleVisitor(x => (x as IStateResettable)?.ResetState());
|
||||
Element.HandleVisitor(x => x.Initialize(request.PageContext, request.Canvas));
|
||||
|
||||
request.Canvas.Translate(new Position(0, request.TotalAscent));
|
||||
Element.Draw(new Size(request.TextSize.Width, -request.TotalAscent));
|
||||
request.Canvas.Translate(new Position(0, -request.TotalAscent));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using QuestPDF.Elements.Text.Calculation;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal class TextBlockExternalLink : ITextBlockElement
|
||||
{
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
public string Text { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
return GetItem().MeasureWithoutCache(request);
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
request.Canvas.Translate(new Position(0, request.TotalAscent));
|
||||
request.Canvas.DrawExternalLink(Url, new Size(request.TextSize.Width, request.TextSize.Height));
|
||||
request.Canvas.Translate(new Position(0, -request.TotalAscent));
|
||||
|
||||
GetItem().Draw(request);
|
||||
}
|
||||
|
||||
private TextItem GetItem()
|
||||
{
|
||||
return new TextItem
|
||||
{
|
||||
Style = Style,
|
||||
Text = Text
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using QuestPDF.Elements.Text.Calculation;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal class TextBlockInternalLink : ITextBlockElement
|
||||
{
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
public string Text { get; set; }
|
||||
public string LocationName { get; set; }
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
return GetItem().MeasureWithoutCache(request);
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
request.Canvas.Translate(new Position(0, request.TotalAscent));
|
||||
request.Canvas.DrawLocationLink(LocationName, new Size(request.TextSize.Width, request.TextSize.Height));
|
||||
request.Canvas.Translate(new Position(0, -request.TotalAscent));
|
||||
|
||||
GetItem().Draw(request);
|
||||
}
|
||||
|
||||
private TextItem GetItem()
|
||||
{
|
||||
return new TextItem
|
||||
{
|
||||
Style = Style,
|
||||
Text = Text
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using QuestPDF.Elements.Text.Calculation;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal class TextBlockPageNumber : ITextBlockElement
|
||||
{
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
public string SlotName { get; set; }
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
return GetItem(request.PageContext).MeasureWithoutCache(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()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
using System.Collections.Generic;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements.Text.Calculation;
|
||||
using QuestPDF.Infrastructure;
|
||||
using Size = QuestPDF.Infrastructure.Size;
|
||||
|
||||
namespace QuestPDF.Elements.Text.Items
|
||||
{
|
||||
internal class TextItem : ITextBlockElement
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
|
||||
private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache =
|
||||
new Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?>();
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
var cacheKey = (request.StartIndex, request.AvailableWidth);
|
||||
|
||||
if (!MeasureCache.ContainsKey(cacheKey))
|
||||
MeasureCache[cacheKey] = MeasureWithoutCache(request);
|
||||
|
||||
return MeasureCache[cacheKey];
|
||||
}
|
||||
|
||||
internal TextMeasurementResult? MeasureWithoutCache(TextMeasurementRequest request)
|
||||
{
|
||||
var paint = Style.ToPaint();
|
||||
var fontMetrics = Style.ToFontMetrics();
|
||||
|
||||
// start breaking text from requested position
|
||||
var text = Text.Substring(request.StartIndex);
|
||||
var breakingIndex = (int)paint.BreakText(text, request.AvailableWidth);
|
||||
|
||||
if (breakingIndex <= 0)
|
||||
return null;
|
||||
|
||||
// break text only on spaces
|
||||
if (breakingIndex < text.Length)
|
||||
{
|
||||
breakingIndex = text.Substring(0, breakingIndex).LastIndexOf(" ");
|
||||
|
||||
if (breakingIndex <= 0)
|
||||
return null;
|
||||
|
||||
breakingIndex += 1;
|
||||
}
|
||||
|
||||
text = text.Substring(0, breakingIndex);
|
||||
|
||||
// measure final text
|
||||
var width = paint.MeasureText(text);
|
||||
|
||||
return new TextMeasurementResult
|
||||
{
|
||||
Width = width,
|
||||
|
||||
Ascent = fontMetrics.Ascent,
|
||||
Descent = fontMetrics.Descent,
|
||||
|
||||
LineHeight = Style.LineHeight,
|
||||
|
||||
StartIndex = request.StartIndex,
|
||||
EndIndex = request.StartIndex + breakingIndex,
|
||||
TotalIndex = Text.Length
|
||||
};
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
var fontMetrics = Style.ToFontMetrics();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuestPDF.Drawing.SpacePlan;
|
||||
using QuestPDF.Elements.Text.Calculation;
|
||||
using QuestPDF.Elements.Text.Items;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Elements.Text
|
||||
{
|
||||
internal class TextLineElement
|
||||
{
|
||||
public ITextElement Element { get; set; }
|
||||
public TextMeasurementResult Measurement { get; set; }
|
||||
}
|
||||
|
||||
internal class TextLine
|
||||
{
|
||||
public ICollection<TextLineElement> Elements { get; set; }
|
||||
|
||||
public float TextHeight => Elements.Max(x => x.Measurement.Height);
|
||||
public float LineHeight => Elements.Max(x => x.Measurement.LineHeight * x.Measurement.Height);
|
||||
|
||||
public float Ascent => Elements.Min(x => x.Measurement.Ascent) - (LineHeight - TextHeight) / 2;
|
||||
public float Descent => Elements.Max(x => x.Measurement.Descent) + (LineHeight - TextHeight) / 2;
|
||||
|
||||
public float Width => Elements.Sum(x => x.Measurement.Width);
|
||||
}
|
||||
|
||||
internal class TextBlock : Element, IStateResettable
|
||||
{
|
||||
public HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
|
||||
public List<ITextElement> Children { get; set; } = new List<ITextElement>();
|
||||
public List<ITextBlockElement> Children { get; set; } = new List<ITextBlockElement>();
|
||||
|
||||
public Queue<ITextElement> RenderingQueue { get; set; }
|
||||
public Queue<ITextBlockElement> RenderingQueue { get; set; }
|
||||
public int CurrentElementIndex { get; set; }
|
||||
|
||||
public void ResetState()
|
||||
{
|
||||
RenderingQueue = new Queue<ITextElement>(Children);
|
||||
RenderingQueue = new Queue<ITextBlockElement>(Children);
|
||||
CurrentElementIndex = 0;
|
||||
}
|
||||
|
||||
|
@ -137,7 +120,7 @@ namespace QuestPDF.Elements.Text
|
|||
|
||||
public IEnumerable<TextLine> DivideTextItemsIntoLines(float availableWidth, float availableHeight)
|
||||
{
|
||||
var queue = new Queue<ITextElement>(RenderingQueue);
|
||||
var queue = new Queue<ITextBlockElement>(RenderingQueue);
|
||||
var currentItemIndex = CurrentElementIndex;
|
||||
var currentHeight = 0f;
|
||||
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Drawing.SpacePlan;
|
||||
using QuestPDF.Infrastructure;
|
||||
using Size = QuestPDF.Infrastructure.Size;
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
internal class TextMeasurementResult
|
||||
{
|
||||
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; }
|
||||
public int TotalIndex { get; set; }
|
||||
|
||||
public bool IsLast => EndIndex == TotalIndex;
|
||||
}
|
||||
|
||||
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 : ITextElement
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
|
||||
private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache =
|
||||
new Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?>();
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
var cacheKey = (request.StartIndex, request.AvailableWidth);
|
||||
|
||||
if (!MeasureCache.ContainsKey(cacheKey))
|
||||
MeasureCache[cacheKey] = MeasureWithoutCache(request);
|
||||
|
||||
return MeasureCache[cacheKey];
|
||||
}
|
||||
|
||||
internal TextMeasurementResult? MeasureWithoutCache(TextMeasurementRequest request)
|
||||
{
|
||||
var paint = Style.ToPaint();
|
||||
var fontMetrics = Style.ToFontMetrics();
|
||||
|
||||
// start breaking text from requested position
|
||||
var text = Text.Substring(request.StartIndex);
|
||||
var breakingIndex = (int)paint.BreakText(text, request.AvailableWidth);
|
||||
|
||||
if (breakingIndex <= 0)
|
||||
return null;
|
||||
|
||||
// break text only on spaces
|
||||
if (breakingIndex < text.Length)
|
||||
{
|
||||
breakingIndex = text.Substring(0, breakingIndex).LastIndexOf(" ");
|
||||
|
||||
if (breakingIndex <= 0)
|
||||
return null;
|
||||
|
||||
breakingIndex += 1;
|
||||
}
|
||||
|
||||
text = text.Substring(0, breakingIndex);
|
||||
|
||||
// measure final text
|
||||
var width = paint.MeasureText(text);
|
||||
|
||||
return new TextMeasurementResult
|
||||
{
|
||||
Width = width,
|
||||
|
||||
Ascent = fontMetrics.Ascent,
|
||||
Descent = fontMetrics.Descent,
|
||||
|
||||
LineHeight = Style.LineHeight,
|
||||
|
||||
StartIndex = request.StartIndex,
|
||||
EndIndex = request.StartIndex + breakingIndex,
|
||||
TotalIndex = Text.Length
|
||||
};
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
var fontMetrics = Style.ToFontMetrics();
|
||||
|
||||
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).MeasureWithoutCache(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()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal class InternalLinkTextItem : ITextElement
|
||||
{
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
public string Text { get; set; }
|
||||
public string LocationName { get; set; }
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
return GetItem().MeasureWithoutCache(request);
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
request.Canvas.Translate(new Position(0, request.TotalAscent));
|
||||
request.Canvas.DrawLocationLink(LocationName, new Size(request.TextSize.Width, request.TextSize.Height));
|
||||
request.Canvas.Translate(new Position(0, -request.TotalAscent));
|
||||
|
||||
GetItem().Draw(request);
|
||||
}
|
||||
|
||||
private TextItem GetItem()
|
||||
{
|
||||
return new TextItem
|
||||
{
|
||||
Style = Style,
|
||||
Text = Text
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExternalLinkTextItem : ITextElement
|
||||
{
|
||||
public TextStyle Style { get; set; } = new TextStyle();
|
||||
public string Text { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
return GetItem().MeasureWithoutCache(request);
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
request.Canvas.Translate(new Position(0, request.TotalAscent));
|
||||
request.Canvas.DrawExternalLink(Url, new Size(request.TextSize.Width, request.TextSize.Height));
|
||||
request.Canvas.Translate(new Position(0, -request.TotalAscent));
|
||||
|
||||
GetItem().Draw(request);
|
||||
}
|
||||
|
||||
private TextItem GetItem()
|
||||
{
|
||||
return new TextItem
|
||||
{
|
||||
Style = Style,
|
||||
Text = Text
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal class ElementTextItem : ITextElement
|
||||
{
|
||||
public Element Element { get; set; } = Empty.Instance;
|
||||
|
||||
public TextMeasurementResult? Measure(TextMeasurementRequest request)
|
||||
{
|
||||
Element.HandleVisitor(x => (x as IStateResettable)?.ResetState());
|
||||
Element.HandleVisitor(x => x.Initialize(request.PageContext, request.Canvas));
|
||||
|
||||
var measurement = Element.Measure(new Size(request.AvailableWidth, Size.Max.Height));
|
||||
|
||||
if (measurement is Wrap || measurement is PartialRender)
|
||||
return null;
|
||||
|
||||
var elementSize = measurement as Size;
|
||||
|
||||
return new TextMeasurementResult
|
||||
{
|
||||
Width = elementSize.Width,
|
||||
|
||||
Ascent = -elementSize.Height,
|
||||
Descent = 0,
|
||||
|
||||
LineHeight = 1,
|
||||
|
||||
StartIndex = 0,
|
||||
EndIndex = 0,
|
||||
TotalIndex = 0
|
||||
};
|
||||
}
|
||||
|
||||
public void Draw(TextDrawingRequest request)
|
||||
{
|
||||
Element.HandleVisitor(x => (x as IStateResettable)?.ResetState());
|
||||
Element.HandleVisitor(x => x.Initialize(request.PageContext, request.Canvas));
|
||||
|
||||
request.Canvas.Translate(new Position(0, request.TotalAscent));
|
||||
Element.Draw(new Size(request.TextSize.Width, -request.TotalAscent));
|
||||
request.Canvas.Translate(new Position(0, -request.TotalAscent));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Elements.Text;
|
||||
using QuestPDF.Elements.Text.Items;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Fluent
|
||||
|
@ -39,7 +40,7 @@ namespace QuestPDF.Fluent
|
|||
Spacing = value;
|
||||
}
|
||||
|
||||
private void AddItemToLastTextBlock(ITextElement element)
|
||||
private void AddItemToLastTextBlock(ITextBlockElement element)
|
||||
{
|
||||
if (!TextBlocks.Any())
|
||||
TextBlocks.Add(new TextBlock());
|
||||
|
@ -69,7 +70,7 @@ namespace QuestPDF.Fluent
|
|||
.Skip(1)
|
||||
.Select(x => new TextBlock
|
||||
{
|
||||
Children = new List<ITextElement> { x }
|
||||
Children = new List<ITextBlockElement> { x }
|
||||
})
|
||||
.ToList()
|
||||
.ForEach(TextBlocks.Add);
|
||||
|
@ -84,7 +85,7 @@ namespace QuestPDF.Fluent
|
|||
{
|
||||
style ??= DefaultStyle;
|
||||
|
||||
AddItemToLastTextBlock(new PageNumberTextItem()
|
||||
AddItemToLastTextBlock(new TextBlockPageNumber()
|
||||
{
|
||||
Style = style,
|
||||
SlotName = slotName
|
||||
|
@ -110,7 +111,7 @@ namespace QuestPDF.Fluent
|
|||
{
|
||||
style ??= DefaultStyle;
|
||||
|
||||
AddItemToLastTextBlock(new InternalLinkTextItem
|
||||
AddItemToLastTextBlock(new TextBlockInternalLink
|
||||
{
|
||||
Style = style,
|
||||
Text = text,
|
||||
|
@ -122,7 +123,7 @@ namespace QuestPDF.Fluent
|
|||
{
|
||||
style ??= DefaultStyle;
|
||||
|
||||
AddItemToLastTextBlock(new ExternalLinkTextItem
|
||||
AddItemToLastTextBlock(new TextBlockExternalLink
|
||||
{
|
||||
Style = style,
|
||||
Text = text,
|
||||
|
@ -134,7 +135,7 @@ namespace QuestPDF.Fluent
|
|||
{
|
||||
var container = new Container();
|
||||
|
||||
AddItemToLastTextBlock(new ElementTextItem
|
||||
AddItemToLastTextBlock(new TextBlockElement
|
||||
{
|
||||
Element = container
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче