예제 #1
0
        /// <summary>
        /// This is the main process of rendering a project to a pdf
        /// </summary>
        private RenderResultInfo RenderToDocument(object data, TemplateProject project, out PdfDocument document)
        {
            _loadingTimer.Reset();
            _totalTimer.Restart();

            _loadingTimer.Start();
            _baseFontFamily = project.FontName;
            var result = new RenderResultInfo {
                Success = false
            };

            _loadingTimer.Stop();

            var mapper = new DataMapper(project, data);

            document                   = new PdfDocument();
            document.Info.Author       = "Generated from data by Form8sn";
            document.Info.Title        = project.Name;
            document.Info.CreationDate = DateTime.UtcNow;

            // Go through the project file and data, generate all the pages, and the
            // template boxes with appropriately formatted data
            var pageList = PrepareAllPages(project, mapper, result);

            if (pageList is null)
            {
                result.Success = false;
                return(result);
            }

            // Next, go through the prepared page and render them to PDF
            var ok = RenderPagesToPdfDocument(project, document, pageList, result);

            if (!ok)
            {
                result.Success = false;
                return(result);
            }

            _totalTimer.Stop();

            result.Success = true;

            result.OverallTime = _totalTimer.Elapsed;
            result.LoadingTime = _loadingTimer.Elapsed;

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Follow all data paths and page repeaters in the project. Results in either a set of pages that
        /// can be rendered to PDF, or null if the document can't be rendered
        /// </summary>
        /// <param name="project">Project file to generate a document for</param>
        /// <param name="mapper">Data mapper holding the final data for a single document</param>
        /// <param name="result">Rendering result, including any error messages</param>
        /// <returns>List of pages to render, or null</returns>
        public static List <DocumentPage>?PrepareAllPages(TemplateProject project, DataMapper mapper, RenderResultInfo result)
        {
            var runningTotals = new Dictionary <string, decimal>(); // path -> total

            // First, we run through the definitions, gathering data
            // This lets us count pages, and defers fitting content into boxes until
            // we've decided to show it (e.g. if it's dependent on an empty box)
            var pageList = new List <DocumentPage>();

            for (var pageIndex = 0; pageIndex < project.Pages.Count; pageIndex++)
            {
                var pageDef = project.Pages[pageIndex] !;
                if (pageDef.RepeatMode.Repeats)
                {
                    var dataSets = mapper.GetRepeatData(pageDef.RepeatMode.DataPath);

                    for (var repeatIndex = 0; repeatIndex < dataSets.Count; repeatIndex++)
                    {
                        var repeatData = dataSets[repeatIndex];
                        mapper.SetRepeater(repeatData, pageDef.RepeatMode.DataPath);
                        var pageResult = PreparePage(pageDef, mapper, runningTotals, pageIndex);
                        mapper.ClearRepeater();
                        ClearPageTotals(runningTotals);

                        if (pageResult.IsFailure)
                        {
                            result.ErrorMessage = pageResult.FailureMessage;
                            return(null);
                        }

                        pageResult.ResultData.RepeatIndex = repeatIndex;
                        pageResult.ResultData.RepeatCount = dataSets.Count;
                        pageList.Add(pageResult.ResultData);
                    }
                }
                else
                {
                    var pageResult = PreparePage(pageDef, mapper, runningTotals, pageIndex);
                    ClearPageTotals(runningTotals);

                    if (pageResult.IsFailure)
                    {
                        result.ErrorMessage = pageResult.FailureMessage;
                        return(null);
                    }

                    pageList.Add(pageResult.ResultData);
                }
            }

            // remove boxes that have null/empty dependencies
            PruneBoxes(pageList);
            return(pageList);
        }
예제 #3
0
        /// <summary>
        /// Render prepared pages into a PDF document
        /// </summary>
        /// <param name="project">Project file to generate a document for</param>
        /// <param name="document">Open and writable PDF file to add pages to</param>
        /// <param name="pageList">A set of pages from PrepareAllPages()</param>
        /// <param name="result">Rendering result, including any error messages</param>
        /// <returns>True for success, false for failure</returns>
        public bool RenderPagesToPdfDocument(TemplateProject project, PdfDocument document, List <DocumentPage> pageList, RenderResultInfo result)
        {
            for (var pageIndex = 0; pageIndex < pageList.Count; pageIndex++)
            {
                _loadingTimer.Start();
                var page    = pageList[pageIndex] !;
                var pageDef = page.Definition;

                using var background = LoadBackground(project, page.SourcePageIndex, pageDef);
                var font = GetFont(pageDef.PageFontSize ?? project.BaseFontSize ?? 16);
                _loadingTimer.Stop();

                var pageResult = OutputPage(document, page, font, background, pageIndex, pageList.Count);
                if (pageResult.IsFailure)
                {
                    result.ErrorMessage = pageResult.FailureMessage;
                    return(false);
                }
            }
            return(true);
        }