@@ -534,19 +534,55 @@ internal static class DrawingElementRenderer
|
||||
for (var page = 0; page < pages.Count; page++)
|
||||
{
|
||||
if (page > 0) column.Item().PageBreak();
|
||||
var offset = value is DrawingValue ? page * pageHeight : 0;
|
||||
// Koordinaten sind nach Slice()/RecordPages() bereits seitenlokal (bei 0 beginnend) -
|
||||
// kein zusätzlicher viewBox-Y-Offset nötig oder sinnvoll (siehe Slice()).
|
||||
column.Item().Height(UnitConverter.Points(pageHeight, unit)).Svg(
|
||||
BuildSvg(pages[page], width, pageHeight, offset, unit));
|
||||
BuildSvg(pages[page], width, pageHeight, 0, unit));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Schneidet die Zeichenbefehle anhand ihrer Y-Koordinate in Seiten auf und verschiebt sie auf
|
||||
// seitenlokale Koordinaten (Y=0 am Seitenanfang). Ein SVG-Element mit "viewBox" und
|
||||
// "overflow=hidden" wird von QuestPDFs Svg()-Renderer NICHT zuverlässig geclippt - ein
|
||||
// (Y-)Offset im viewBox allein reicht nicht, um pro Seite nur den jeweiligen Ausschnitt zu
|
||||
// zeigen; ohne dieses echte Zerschneiden landet auf jeder Seite (nahezu) der komplette
|
||||
// Zeicheninhalt erneut (Bug: doppelte/überlappende Fehlzeitenliste über mehrere Seiten).
|
||||
private static List<DrawingValue> Slice(DrawingValue value, float pageHeight)
|
||||
{
|
||||
var pageCount = Math.Max(1, (int)Math.Ceiling(Math.Max(0, value.ContentHeight) / pageHeight));
|
||||
return Enumerable.Repeat(value, pageCount).ToList();
|
||||
var pages = new List<List<DrawingCommand>>();
|
||||
for (var i = 0; i < pageCount; i++) pages.Add([]);
|
||||
var pendingLinePage = 0;
|
||||
foreach (var command in value.Commands)
|
||||
{
|
||||
var y = CommandY(command);
|
||||
if (y is null) { pages[0].Add(command); continue; }
|
||||
var page = Math.Clamp((int)(y.Value / pageHeight), 0, pageCount - 1);
|
||||
// LineTo gehört inhaltlich zum vorherigen MoveTo (eine Linie) - beide müssen auf
|
||||
// derselben Seite landen, sonst fehlt beim Rendern der Linie der Startpunkt.
|
||||
if (command is MoveTo) pendingLinePage = page;
|
||||
else if (command is LineTo) page = pendingLinePage;
|
||||
pages[page].Add(ShiftY(command, page * pageHeight));
|
||||
}
|
||||
return pages.Select(commands => new DrawingValue(commands, pageHeight)).ToList();
|
||||
}
|
||||
|
||||
private static float? CommandY(DrawingCommand command) => command switch
|
||||
{
|
||||
DrawString s => s.Y, DrawStringEx s => s.Y, MoveTo m => m.Y, LineTo l => l.Y,
|
||||
DrawRectangle r => r.Y, DrawImage i => i.Y, DrawLine ln => Math.Min(ln.Y1, ln.Y2), _ => null,
|
||||
};
|
||||
|
||||
private static DrawingCommand ShiftY(DrawingCommand command, float dy) => command switch
|
||||
{
|
||||
DrawString s => s with { Y = s.Y - dy }, DrawStringEx s => s with { Y = s.Y - dy },
|
||||
MoveTo m => m with { Y = m.Y - dy }, LineTo l => l with { Y = l.Y - dy },
|
||||
DrawRectangle r => r with { Y = r.Y - dy }, DrawImage i => i with { Y = i.Y - dy },
|
||||
DrawLine ln => ln with { Y1 = ln.Y1 - dy, Y2 = ln.Y2 - dy },
|
||||
_ => command,
|
||||
};
|
||||
|
||||
internal static List<IReadOnlyList<DrawingCommand>> RecordPages(PagedDrawingValue value,
|
||||
float width, float height, int maxPages)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user