This commit is contained in:
MarcinZiabek 2022-03-12 12:17:00 +01:00
Родитель fdf8e3eb1a
Коммит 5402e5fedc
6 изменённых файлов: 117 добавлений и 57 удалений

Просмотреть файл

@ -23,7 +23,7 @@ namespace QuestPDF.Examples
.PageSize(PageSizes.A4)
.ProducePdf()
.ShowResults()
.Render(x => ComposeBook(x, chapters));
.RenderDocument(x => ComposeBook(x, chapters));
}
[Test]
@ -42,8 +42,8 @@ namespace QuestPDF.Examples
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.ProducePdf()
.Render(x => ComposeBook(x, chapters));
.ProducePdf()
.RenderDocument(x => ComposeBook(x, chapters));
}
IEnumerable<float> PerformTest(int attempts)
@ -102,37 +102,30 @@ namespace QuestPDF.Examples
}
}
private void ComposeBook(IContainer container, ICollection<BookChapter> chapters)
private void ComposeBook(IDocumentContainer container, ICollection<BookChapter> chapters)
{
var subtitleStyle = TextStyle.Default.Size(24).SemiBold().Color(Colors.Blue.Medium);
var normalStyle = TextStyle.Default.Size(14);
ComposePage(container);
void ComposePage(IContainer container)
container.Page(page =>
{
container
.Padding(50)
.Decoration(decoration =>
{
decoration
.Content()
.Column(column =>
{
column.Item().Element(Title);
column.Item().PageBreak();
column.Item().Element(TableOfContents);
column.Item().PageBreak();
page.Margin(50);
page.Content().Column(column =>
{
column.Item().Element(Title);
column.Item().PageBreak();
column.Item().Element(TableOfContents);
column.Item().PageBreak();
Chapters(column);
Chapters(column);
column.Item().Element(Acknowledgements);
});
column.Item().Element(Acknowledgements);
});
page.Footer().Element(Footer);
});
decoration.After().Element(Footer);
});
}
void Title(IContainer container)
{
container

Просмотреть файл

@ -31,7 +31,8 @@ namespace QuestPDF.Examples
{
text.DefaultTextStyle(TextStyle.Default.Size(20));
text.Span("This is a normal text, followed by an ");
text.Span("underlined red text.", TextStyle.Default.Size(20).Color(Colors.Red.Medium).Underline());
text.Span("underlined red text", TextStyle.Default.Color(Colors.Red.Medium).Underline());
text.Span(".");
});
});
}
@ -189,7 +190,7 @@ namespace QuestPDF.Examples
text.EmptyLine();
text.Span("The new text element also supports injecting custom content between words: ");
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
text.Element().PaddingBottom(-4).Height(16).Width(32).Image(Placeholders.Image);
text.Span(".");
text.EmptyLine();
@ -246,7 +247,7 @@ namespace QuestPDF.Examples
text.Span("and this is slightly bigger text.", TextStyle.Default.Size(16));
text.Span("The new text element also supports injecting custom content between words: ");
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
text.Element().PaddingBottom(-4).Height(16).Width(32).Image(Placeholders.Image);
text.Span(".");
text.EmptyLine();
@ -288,7 +289,57 @@ namespace QuestPDF.Examples
page.Content().Text(
"This is a specially crafted sentence with a specially chosen length for demonstration of the bug that occurs ;;;;;. ",
TextStyle.Default.Size(11));
TextStyle.Default.Size(11).BackgroundColor(Colors.Red.Lighten3));
});
});
}
[Test]
public void EmptyText()
{
// issue 135
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Margin(50);
page.Background(Colors.White);
page.Size(PageSizes.A4);
page.Content().Text(
" ",
TextStyle.Default.Size(11).BackgroundColor(Colors.Red.Lighten3));
});
});
}
[Test]
public void Whitespaces()
{
// issue 135
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Margin(50);
page.Background(Colors.White);
page.Size(PageSizes.A4);
page.Content().Text(
" x ",
TextStyle.Default.Size(11).BackgroundColor(Colors.Red.Lighten3));
});
});
}

Просмотреть файл

@ -9,6 +9,6 @@ namespace QuestPDF.Elements.Text.Calculation
public int StartIndex { get; set; }
public float AvailableWidth { get; set; }
public bool IsFirstLineElement { get; set; }
public bool IsFirstElementInLine { get; set; }
}
}

Просмотреть файл

@ -17,6 +17,6 @@ namespace QuestPDF.Elements.Text.Calculation
public int NextIndex { get; set; }
public int TotalIndex { get; set; }
public bool IsLast => EndIndex == TotalIndex;
public bool IsLast => NextIndex == EndIndex;
}
}

Просмотреть файл

@ -33,13 +33,15 @@ namespace QuestPDF.Elements.Text.Items
var startIndex = request.StartIndex;
if (request.IsFirstLineElement)
// if the element is the first one within the line,
// ignore leading spaces
if (request.IsFirstElementInLine)
{
while (startIndex + 1 < Text.Length && Text[startIndex] == space)
while (startIndex < Text.Length && Text[startIndex] == space)
startIndex++;
}
if (Text.Length == 0)
if (Text.Length == 0 || startIndex == Text.Length)
{
return new TextMeasurementResult
{
@ -58,37 +60,26 @@ namespace QuestPDF.Elements.Text.Items
if (textLength <= 0)
return null;
if (textLength < text.Length && text[textLength] == space)
textLength++;
// break text only on spaces
if (textLength < text.Length)
{
var lastSpaceIndex = text.Slice(0, textLength).LastIndexOf(space) - 1;
var wrappedTextLength = WrapText(text, textLength, request.IsFirstElementInLine);
if (lastSpaceIndex <= 0)
{
if (!request.IsFirstLineElement)
return null;
}
else
{
textLength = lastSpaceIndex + 1;
}
}
if (wrappedTextLength == null)
return null;
textLength = wrappedTextLength.Value;
text = text.Slice(0, textLength);
var endIndex = startIndex + textLength;
var nextIndex = endIndex;
while (nextIndex + 1 < Text.Length && Text[nextIndex] == space)
// when breaking text, omit spaces at the end of the line
while (nextIndex < Text.Length && Text[nextIndex] == space)
nextIndex++;
// measure final text
var finalText = text.TrimEnd();
var width = paint.MeasureText(finalText);
var width = paint.MeasureText(text);
return new TextMeasurementResult
{
@ -104,6 +95,31 @@ namespace QuestPDF.Elements.Text.Items
NextIndex = nextIndex,
TotalIndex = Text.Length
};
static int? WrapText(ReadOnlySpan<char> text, int textLength, bool isFirstElementInLine)
{
// textLength - length of the part of the text that fits in available width (creating a line)
// entire text fits, no need to wrap
if (textLength == text.Length)
return textLength;
// current line ends at word, next character is space, perfect place to wrap
if (text[textLength - 1] != space && text[textLength] == space)
return textLength;
// find last space within the available text to wrap
var lastSpaceIndex = text.Slice(0, textLength).LastIndexOf(space);
// text contains space that can be used to wrap
if (lastSpaceIndex > 0)
return lastSpaceIndex;
// there is no available space to wrap text
// if the item is first within the line, perform safe mode and chop the word
// otherwise, move the item into the next line
return isFirstElementInLine ? textLength : null;
}
}
public virtual void Draw(TextDrawingRequest request)

Просмотреть файл

@ -170,7 +170,7 @@ namespace QuestPDF.Elements.Text
StartIndex = currentItemIndex,
AvailableWidth = availableWidth - currentWidth,
IsFirstLineElement = !currentLineElements.Any()
IsFirstElementInLine = !currentLineElements.Any()
};
var measurementResponse = currentElement.Measure(measurementRequest);