123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- using System;
- using System.Drawing.Printing;
- using System.Collections;
- using System.Collections.Generic;
- using FastReport.Utils;
- using System.Drawing;
- namespace FastReport.Print
- {
- internal class SplitPrintController : PrintControllerBase
- {
- #region Fields
- private List<SplittedPage> splittedPages;
- private float addX = 5;
- private float addY = 5;
- private float offsetX;
- private float offsetY;
- private bool landscape;
- #endregion
- #region Private methods
- private ReportPage GetNextSplittedPage()
- {
- if (splittedPages.Count == 0)
- return null;
- PageNo = splittedPages[0].pageNo;
- offsetX = splittedPages[0].offsetX;
- offsetY = splittedPages[0].offsetY;
- landscape = splittedPages[0].landscape;
- splittedPages.RemoveAt(0);
- return Report.PreparedPages.GetPage(PageNo);
- }
- private bool HasMoreSplittedPages()
- {
- return splittedPages.Count > 0;
- }
- private void TrySplit(float a, float b, float c, float d, out int x, out int y)
- {
- x = Math.Abs(Math.Truncate(a / c) * c - a) < 11 ?
- (int)Math.Round(a / c) : (int)Math.Truncate(a / c) + 1;
- y = Math.Abs(Math.Truncate(b / d) * d - b) < 11 ?
- (int)Math.Round(b / d) : (int)Math.Truncate(b / d) + 1;
- }
- private void SplitPage(float a, float b, float c, float d, out int x, out int y, out bool needRotate)
- {
- needRotate = false;
- TrySplit(a, b, c, d, out x, out y);
- int tempX = x;
- int tempY = y;
- float tempC = c;
- c = d;
- d = tempC;
- TrySplit(a, b, c, d, out x, out y);
- if (x * y >= tempX * tempY)
- {
- x = tempX;
- y = tempY;
- }
- else
- needRotate = true;
- }
- #endregion
- #region Public methods
- public override void QueryPageSettings(object sender, QueryPageSettingsEventArgs e)
- {
- Page = GetNextSplittedPage();
- if (Page != null)
- {
- SetPaperSize(Report.PrintSettings.PrintOnSheetWidth, Report.PrintSettings.PrintOnSheetHeight,
- Report.PrintSettings.PrintOnSheetRawPaperSize, e);
- e.PageSettings.Landscape = landscape;
- SetPaperSource(Page, e);
- Duplex duplex = Page.Duplex;
- if (duplex != Duplex.Default)
- e.PageSettings.PrinterSettings.Duplex = duplex;
- }
- }
- public override void PrintPage(object sender, PrintPageEventArgs e)
- {
- StartPage(e);
- Graphics g = e.Graphics;
- FRPaintEventArgs paintArgs;
- IGraphics gr = GdiGraphics.FromGraphics(g);
-
- if (Config.IsRunningOnMono)
- {
- // Point is the only right thing to use in mono. Pixel unit produces weird layout
- g.PageUnit = GraphicsUnit.Point;
- g.ResetTransform();
- g.TranslateTransform(offsetX * Units.Millimeters * 72f / 96f, offsetY * Units.Millimeters * 72f / 96f);
- // workaround different pango/cairo rendering behavior
- if (DrawUtils.GetMonoRendering(g) == MonoRendering.Pango)
- {
- g.ScaleTransform(72f / 96f, 72f / 96f);
- paintArgs = new FRPaintEventArgs(gr, 1, 1, Report.GraphicCache);
- }
- else
- {
- paintArgs = new FRPaintEventArgs(gr, 72f / 96f, 72f / 96f, Report.GraphicCache);
- }
- }
- else
- {
- g.PageUnit = GraphicsUnit.Pixel;
- g.TranslateTransform(offsetX * Units.Millimeters * g.DpiX / 96, offsetY * Units.Millimeters * g.DpiY / 96);
- paintArgs = new FRPaintEventArgs(gr, g.DpiX / 96, g.DpiY / 96, Report.GraphicCache);
- }
- Page.Print(paintArgs);
- Page.Dispose();
- FinishPage(e);
- e.HasMorePages = HasMoreSplittedPages();
- }
- #endregion
- public SplitPrintController(Report report, PrintDocument doc, int curPage) : base(report, doc, curPage)
- {
- splittedPages = new List<SplittedPage>();
- // get hard margins
- float leftMargin = doc.PrinterSettings.DefaultPageSettings.HardMarginX / 100f * 25.4f;
- float topMargin = doc.PrinterSettings.DefaultPageSettings.HardMarginY / 100f * 25.4f;
- float rightMargin = leftMargin;
- float bottomMargin = topMargin;
- int countX;
- int countY;
- bool needChangeOrientation;
- while (true)
- {
- Page = GetNextPage();
- if (Page == null)
- break;
- if (!Page.UnlimitedHeight && !Page.UnlimitedWidth)
- {
- SplitPage(Page.PaperWidth, Page.PaperHeight,
- Report.PrintSettings.PrintOnSheetWidth, Report.PrintSettings.PrintOnSheetHeight,
- out countX, out countY, out needChangeOrientation);
- }
- else
- {
- SplitPage(Page.WidthInPixels / Units.Millimeters, Page.HeightInPixels / Units.Millimeters,
- Report.PrintSettings.PrintOnSheetWidth, Report.PrintSettings.PrintOnSheetHeight,
- out countX, out countY, out needChangeOrientation);
- }
- bool landscape = false;
- if (needChangeOrientation)
- landscape = true;
- float pieceX = landscape ? Report.PrintSettings.PrintOnSheetHeight : Report.PrintSettings.PrintOnSheetWidth;
- float pieceY = landscape ? Report.PrintSettings.PrintOnSheetWidth : Report.PrintSettings.PrintOnSheetHeight;
- float marginY = 0;
- float printedY = 0;
- float offsY = -topMargin;
- for (int y = 1; y <= countY; y++)
- {
- float marginX = 0;
- float printedX = 0;
- float offsX = -leftMargin;
- for (int x = 1; x <= countX; x++)
- {
- splittedPages.Add(new SplittedPage(PageNo, offsX, offsY, landscape));
- printedX += (pieceX - marginX - rightMargin) - addX;
- offsX = -printedX;
- marginX = leftMargin;
- }
- printedY += (pieceY - marginY - bottomMargin) - addY;
- offsY = -printedY;
- marginY = topMargin;
- }
- Page.Dispose();
- }
- }
- private class SplittedPage
- {
- // physical pageno
- public int pageNo;
- // offsetx, in mm
- public float offsetX;
- // offsety, in mm
- public float offsetY;
- // determines if we should rotate the output page
- public bool landscape;
- public SplittedPage(int pageNo, float ofsX, float ofsY, bool landscape)
- {
- this.pageNo = pageNo;
- offsetX = ofsX;
- offsetY = ofsY;
- this.landscape = landscape;
- }
- }
- }
- }
|